diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c index 14889a7a..a8003a3c 100644 --- a/src/libopensc/pkcs15-tcos.c +++ b/src/libopensc/pkcs15-tcos.c @@ -1,7 +1,7 @@ /* - * PKCS15 emulation layer for TCOS base preformatted cards + * PKCS15 emulation layer for TCOS based preformatted cards * - * Copyright (C) 2006, Peter Koch + * Copyright (C) 2006, Peter Koch * Copyright (C) 2004, Antonino Iacono * Copyright (C) 2003, Olaf Kirch * @@ -47,30 +47,34 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt {"Smartkey Card TypB", "Kobil GmbH"}, {"Chipkarte JLU Giessen", "Kobil GmbH"} }; - static const struct { - int type, id, writable; + static struct { + int flags; + const int type, id, writable; const char *path; const char *label; } certlist[]={ - { 1, 0x45, 0, "DF01C000", "Telesec Signatur Zertifikat"}, - {-1, 0x45, 1, "DF014331", "Signatur Zertifikat 1"}, - {-1, 0x45, 1, "DF014332", "Signatur Zertifikat 2"}, - {-1, 0x46, 0, "DF01C100", "Telesec Authentifizierungs Zertifikat"}, - {-1, 0x46, 1, "DF014371", "Authentifizierungs Zertifikat 1"}, - {-1, 0x46, 1, "DF014372", "Authentifizierungs Zertifikat 2"}, - {-1, 0x47, 0, "DF01C200", "Telesec Verschluesselungs Zertifikat"}, - {-1, 0x47, 1, "DF0143B1", "Verschluesselungs Zertifikat 1"}, - {-1, 0x47, 1, "DF0143B2", "Verschluesselungs Zertifikat 2"}, - {-1, 0x48, 1, "41014352", "W2K Logon Zertifikat"}, - { 2, 0x45, 1, "8000DF01C000", "SignTrust Signatur Zertifikat"}, - {-2, 0x46, 1, "800082008220", "SignTrust Verschluesselungs Zertifikat"}, - {-2, 0x47, 1, "800083008320", "SignTrust Authentifizierungs Zertifikat"}, - { 3, 0x45, 1, "41004352", "Smartkey Zertifikat 1"}, - {-3, 0x46, 1, "41004353", "Smartkey Zertifikat 2"}, - { 4, 0x45, 1, "41014352", "Smartkey Zertifikat 1"}, - {-4, 0x46, 1, "41014353", "Smartkey Zertifikat 2"}, - { 5, 0x45, 1, "41004352", "UniCard Giessen Zertifikat"}, - { 0, 0, 0, NULL, NULL} + {0, 1, 0x45, 0, "DF01C000", "Telesec Signatur Zertifikat"}, + {3, 1, 0x45, 1, "DF014331", "Signatur Zertifikat 1"}, + {3, 1, 0x45, 1, "DF014332", "Signatur Zertifikat 2"}, + {1, 1, 0x46, 0, "DF01C100", "Telesec Authentifizierungs Zertifikat"}, + {3, 1, 0x46, 1, "DF014371", "Authentifizierungs Zertifikat 1"}, + {3, 1, 0x46, 1, "DF014372", "Authentifizierungs Zertifikat 2"}, + {1, 1, 0x47, 0, "DF01C200", "Telesec Verschluesselungs Zertifikat"}, + {3, 1, 0x47, 1, "DF0143B1", "Verschluesselungs Zertifikat 1"}, + {3, 1, 0x47, 1, "DF0143B2", "Verschluesselungs Zertifikat 2"}, + {1, 1, 0x48, 1, "DF06C000", "SigG Zertifikat 1"}, + {1, 1, 0x48, 1, "DF064331", "SigG Zertifikat 2"}, + {1, 1, 0x48, 1, "DF064332", "SigG Zertifikat 3"}, + {1, 1, 0x49, 1, "41014352", "W2K Logon Zertifikat"}, + {0, 2, 0x45, 1, "8000DF01C000", "SignTrust Signatur Zertifikat"}, + {1, 2, 0x46, 1, "800082008220", "SignTrust Verschluesselungs Zertifikat"}, + {1, 2, 0x47, 1, "800083008320", "SignTrust Authentifizierungs Zertifikat"}, + {0, 3, 0x45, 1, "41004352", "Smartkey Zertifikat 1"}, + {0, 3, 0x46, 1, "41004353", "Smartkey Zertifikat 2"}, + {0, 4, 0x45, 1, "41014352", "Smartkey Zertifikat 1"}, + {0, 4, 0x46, 1, "41014353", "Smartkey Zertifikat 2"}, + {0, 5, 0x45, 1, "41004352", "UniCard Giessen Zertifikat"}, + {0, 0, 0, 0, NULL, NULL} }; static const struct { int type, id, auth_id; @@ -81,7 +85,8 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt {1, 0x45, 4, "DF015331", 0x80, "Signatur Schluessel"}, {1, 0x46, 3, "DF015371", 0x82, "Authentifizierungs Schluessel"}, {1, 0x47, 3, "DF0153B1", 0x81, "Verschluesselungs Schluessel"}, - {1, 0x48, 1, "41015103", 0x83, "W2K Logon Schluessel"}, + {1, 0x48, 5, "DF065331", 0x80, "SigG Schluessel"}, + {1, 0x49, 1, "41015103", 0x83, "W2K Logon Schluessel"}, {2, 0x45, 1, "8000DF015331", 0x80, "Signatur Schluessel"}, {2, 0x46, 2, "800082008210", 0x80, "Verschluesselungs Schluessel"}, {2, 0x47, 3, "800083008310", 0x80, "Authentifizierungs Schluessel"}, @@ -111,6 +116,9 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt {1, 4, 1, 6, 0x81, "DF015081", "Netkey PIN1", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED}, + {1, 5, 0, 6, 0x81, "DF065081", "SigG PIN", + SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | + SC_PKCS15_PIN_FLAG_INITIALIZED}, {2, 1, 0, 6, 0x81, "8000DF010000", "Signatur PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED}, @@ -142,7 +150,7 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt sc_file_t *file; sc_serial_number_t serialnr; char serial[30]; - int i, r, usage, cardtype; + int i, j, found, r, usage, cardtype; /* check if we have the correct card OS unless SC_PKCS15EMU_FLAGS_NO_CHECK */ i=(opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK); @@ -159,55 +167,23 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt serial[19] = '\0'; set_string(&p15card->serial_number, serial); + /* detect cardtype and certificates */ cardtype=0; for(i=0; certlist[i].id; ++i){ - struct sc_pkcs15_cert_info cert_info; - struct sc_pkcs15_object cert_obj; - unsigned char cert[20]; - - if(certlist[i].type>0 && cardtype!=0 && cardtype!=certlist[i].type) continue; - if(certlist[i].type<0 && cardtype!=-certlist[i].type) continue; + if(cardtype && certlist[i].type!=cardtype) continue; + if(!cardtype && (certlist[i].flags&1)) continue; + if(!cardtype && ctx->debug>=2) sc_debug(ctx, "Testing %s\n",cardlist[certlist[i].type-1].card); + if(ctx->debug>=2) sc_debug(ctx, "Testing Cert %s, %s\n", certlist[i].path, certlist[i].label); sc_format_path(certlist[i].path, &path); - sc_ctx_suppress_errors_on(card->ctx); + sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, NULL); - sc_ctx_suppress_errors_off(card->ctx); - if (r < 0) continue; - if(certlist[i].type>0) cardtype=certlist[i].type; - - /* read first 20 bytes of certificate, first two bytes - * must be 0x30 0x82, otherwise this is an empty cert-file - * Telesec-Certificates are prefixed by an OID, - * for example 06:03:55:04:24. this must be skipped - */ - r = sc_read_binary(card, 0, cert, sizeof(cert), 0); - if(r<0 || cert[0]!=0x30 || cert[1]!=0x82) continue; - if(cert[4]==0x06 && cert[5]<10 && cert[6+cert[5]]==0x30 && cert[7+cert[5]]==0x82){ - path.index=6+cert[5]; - path.count=(cert[8+cert[5]]<<8) + cert[9+cert[5]] + 4; - } else { - path.index=0; - path.count=(cert[2]<<8) + cert[3] + 4; - } - - memset(&cert_info, 0, sizeof(cert_info)); - cert_info.id.len = 1; - cert_info.id.value[0] = certlist[i].id; - cert_info.authority = 0; - cert_info.path = path; - - memset(&cert_obj, 0, sizeof(cert_obj)); - strlcpy(cert_obj.label, certlist[i].label, sizeof(cert_obj.label)); - cert_obj.flags = certlist[i].writable ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0; - - r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); - if (r < 0) { - sc_debug(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed\n", certlist[i].path); - r = SC_ERROR_INTERNAL; - goto failed; - } + sc_ctx_suppress_errors_off(ctx); + if(r<0) continue; + cardtype=certlist[i].type; + certlist[i].flags |= 4; } - if (ctx->debug >= 1) sc_debug(ctx, "Detected TCOS-Card Type-%d\n", cardtype); + if(ctx->debug >= 1) sc_debug(ctx, "Cardtype=%d, %s\n", cardtype, cardlist[cardtype-1].card); if(cardtype<1 || cardtype>(int)(sizeof(cardlist)/sizeof(cardlist[0]))){ r = SC_ERROR_WRONG_CARD; goto failed; @@ -215,6 +191,62 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt set_string(&p15card->label, cardlist[cardtype-1].card); set_string(&p15card->manufacturer_id, cardlist[cardtype-1].manufacturer); + /* insert certificates */ + for(found=1;found;){ + for(i=found=0; certlist[i].id && !found; ++i) if(certlist[i].flags&4) found=certlist[i].id; + for(j=0; j<2; ++j) for(i=0; certlist[i].id; ++i){ + struct sc_pkcs15_cert_info cert_info; + struct sc_pkcs15_object cert_obj; + unsigned char cert[20]; + + if(certlist[i].id!=found) continue; + if((certlist[i].flags&2) == 2*j) continue; + if(!(certlist[i].flags&4)) continue; + certlist[i].flags-=4; + + sc_format_path(certlist[i].path, &path); + if(sc_select_file(card, &path, NULL)<0) continue; + + /* read first 20 bytes of certificate, first two bytes + * must be 0x30 0x82, otherwise this is an empty cert-file + */ + r = sc_read_binary(card, 0, cert, sizeof(cert), 0); + if(r<0 || cert[0]!=0x30 || cert[1]!=0x82) continue; + + if(ctx->debug>=1){ + sc_debug(ctx,"Cert %02X %s, %s\n",certlist[i].id,certlist[i].path,certlist[i].label); + } + + /* Telesec-Certificates are prefixed by an OID, + * for example 06:03:55:04:24. so use appropriate offset + */ + if(cert[4]==0x06 && cert[5]<10 && cert[6+cert[5]]==0x30 && cert[7+cert[5]]==0x82){ + path.index=6+cert[5]; + path.count=(cert[8+cert[5]]<<8) + cert[9+cert[5]] + 4; + } else { + path.index=0; + path.count=(cert[2]<<8) + cert[3] + 4; + } + + memset(&cert_info, 0, sizeof(cert_info)); + cert_info.id.len = 1; + cert_info.id.value[0] = certlist[i].id; + cert_info.authority = 0; + cert_info.path = path; + + memset(&cert_obj, 0, sizeof(cert_obj)); + strlcpy(cert_obj.label, certlist[i].label, sizeof(cert_obj.label)); + cert_obj.flags = certlist[i].writable ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0; + + r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); + if (r < 0) { + sc_debug(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed\n", certlist[i].path); + r = SC_ERROR_INTERNAL; + goto failed; + } + } + } + for(i=0; keylist[i].id; ++i){ struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; @@ -222,10 +254,11 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt if(keylist[i].type!=cardtype) continue; sc_format_path(keylist[i].path, &path); - sc_ctx_suppress_errors_on(card->ctx); + sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, &file); - sc_ctx_suppress_errors_off(card->ctx); + sc_ctx_suppress_errors_off(ctx); if (r < 0) continue; + if(ctx->debug >= 1) sc_debug(ctx,"Key %02X %s, %s\n",keylist[i].id,keylist[i].path,keylist[i].label); usage = SC_PKCS15_PRKEY_USAGE_SIGN; if (file->prop_attr[1] & 0x04) usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; @@ -262,10 +295,11 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt if(pinlist[i].type && pinlist[i].type!=cardtype) continue; sc_format_path(pinlist[i].path, &path); - sc_ctx_suppress_errors_on(card->ctx); + sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, &file); - sc_ctx_suppress_errors_off(card->ctx); + sc_ctx_suppress_errors_off(ctx); if (r < 0) continue; + if(ctx->debug >= 1) sc_debug(ctx, "PIN %02X %s, %s\n", pinlist[i].id,pinlist[i].path,pinlist[i].label); memset(&pin_info, 0, sizeof(pin_info)); pin_info.auth_id.len = 1; @@ -301,6 +335,6 @@ int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opt failed: if (r < 0) - sc_debug(card->ctx, "Failed to initialize TCOS based preformatted card: %s\n", sc_strerror(r)); + sc_debug(ctx, "PKCS15-emulation for TCOS based preformatted failed: %s\n", sc_strerror(r)); return r; }