From 0e064277542377012b0d1b142f4d6d798a4a8057 Mon Sep 17 00:00:00 2001 From: resoli Date: Wed, 5 Nov 2014 22:57:25 +0100 Subject: [PATCH 001/306] Implementation of card_ctl function with SC_CARDCTL_GET_SERIALNR Implementation of card_ctl function with SC_CARDCTL_GET_SERIALNR --- src/libopensc/card-itacns.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/libopensc/card-itacns.c b/src/libopensc/card-itacns.c index 08c60415..0ab7420c 100644 --- a/src/libopensc/card-itacns.c +++ b/src/libopensc/card-itacns.c @@ -479,6 +479,38 @@ static int itacns_select_file(sc_card_t *card, SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); } +static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) +{ + sc_path_t path; + sc_file_t *file; + int r; + unsigned char ef_id_carta[16]; + sc_format_path("3F0010001003", &path); + + r = sc_select_file(card, &path, &file); + + if (r != SC_SUCCESS || file->size > 16) { + return SC_ERROR_WRONG_CARD; + } + + sc_read_binary(card, 0, ef_id_carta, file->size, 0); + /* cache serial number */ + memcpy(card->serialnr.value, ef_id_carta, 16); + card->serialnr.len = 16; + /* copy and return serial number */ + memcpy(serial, &card->serialnr, sizeof(*serial)); + return SC_SUCCESS; +} + +static int +itacns_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) +{ + switch (cmd) { + case SC_CARDCTL_GET_SERIALNR: + return itacns_get_serialnr(card, ptr); + } + return SC_ERROR_NOT_SUPPORTED; +} static struct sc_card_driver * sc_get_driver(void) { @@ -494,6 +526,7 @@ static struct sc_card_driver * sc_get_driver(void) itacns_ops.read_binary = itacns_read_binary; itacns_ops.list_files = itacns_list_files; itacns_ops.select_file = itacns_select_file; + itacns_ops.card_ctl = itacns_card_ctl; return &itacns_drv; } From 255c0335a1e0c6d79706479ded5e8a919f00646f Mon Sep 17 00:00:00 2001 From: emRoberto Resoli/em Date: Thu, 6 Nov 2014 16:17:51 +0100 Subject: [PATCH 002/306] Indenting fix and stronger limit on serial number length. --- src/libopensc/card-itacns.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-itacns.c b/src/libopensc/card-itacns.c index 0ab7420c..7f8c3fbf 100644 --- a/src/libopensc/card-itacns.c +++ b/src/libopensc/card-itacns.c @@ -482,14 +482,15 @@ static int itacns_select_file(sc_card_t *card, static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) { sc_path_t path; - sc_file_t *file; + sc_file_t *file; int r; unsigned char ef_id_carta[16]; + sc_format_path("3F0010001003", &path); r = sc_select_file(card, &path, &file); - if (r != SC_SUCCESS || file->size > 16) { + if (r != SC_SUCCESS || file->size != 16) { return SC_ERROR_WRONG_CARD; } From f83f8d28dfe93855c23c3f45fa8c21717cb5f24a Mon Sep 17 00:00:00 2001 From: resoli Date: Fri, 7 Nov 2014 11:42:16 +0100 Subject: [PATCH 003/306] itacns_get_serialnr(): relaxed checking on sc_select_file returned length, added debug log. --- src/libopensc/card-itacns.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card-itacns.c b/src/libopensc/card-itacns.c index 7f8c3fbf..d82996f0 100644 --- a/src/libopensc/card-itacns.c +++ b/src/libopensc/card-itacns.c @@ -483,23 +483,49 @@ static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) { sc_path_t path; sc_file_t *file; + size_t len; int r; - unsigned char ef_id_carta[16]; + u8 rbuf[256]; + + if (!serial) return SC_ERROR_INVALID_ARGUMENTS; + + /* see if we have cached serial number */ + if (card->serialnr.len) { + memcpy(serial, &card->serialnr, sizeof(*serial)); + return SC_SUCCESS; + } + + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Reading EF_IDCarta.\n"); sc_format_path("3F0010001003", &path); r = sc_select_file(card, &path, &file); + if (r != SC_SUCCESS) { + return SC_ERROR_WRONG_CARD; + } + len = file->size; - if (r != SC_SUCCESS || file->size != 16) { + //Returned file->size should be 16. + //We choose to not consider it as critical, because some cards + //do not return FCI/FCP templates that include the file size. + //Notify abnormal lenght anyway. + if (len != 16) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, + "Unexpected file length of EF_IDCarta (%lu)\n", + (unsigned long) len); + } + + sc_read_binary(card, 0, rbuf, 256, 0); + if (r != SC_SUCCESS) { return SC_ERROR_WRONG_CARD; } - sc_read_binary(card, 0, ef_id_carta, file->size, 0); /* cache serial number */ - memcpy(card->serialnr.value, ef_id_carta, 16); + memcpy(card->serialnr.value, rbuf, 16); card->serialnr.len = 16; /* copy and return serial number */ memcpy(serial, &card->serialnr, sizeof(*serial)); + return SC_SUCCESS; } From 56684d857c4c757c5ff86f0ab2b1a5392e845ab8 Mon Sep 17 00:00:00 2001 From: resoli Date: Fri, 7 Nov 2014 12:35:21 +0100 Subject: [PATCH 004/306] itacns_get_serialnr(): check sc_read_binary() returned data length. --- src/libopensc/card-itacns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-itacns.c b/src/libopensc/card-itacns.c index d82996f0..9ead8843 100644 --- a/src/libopensc/card-itacns.c +++ b/src/libopensc/card-itacns.c @@ -515,8 +515,8 @@ static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) (unsigned long) len); } - sc_read_binary(card, 0, rbuf, 256, 0); - if (r != SC_SUCCESS) { + r = sc_read_binary(card, 0, rbuf, 256, 0); + if (r != SC_SUCCESS || r != 16 ) { return SC_ERROR_WRONG_CARD; } From 7fea6eb8ba0caa431cf1c8ff493c4ac5a216a11f Mon Sep 17 00:00:00 2001 From: resoli Date: Fri, 7 Nov 2014 12:48:43 +0100 Subject: [PATCH 005/306] itacns_get_serialnr(): check sc_read_binary() returned data length. --- src/libopensc/card-itacns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-itacns.c b/src/libopensc/card-itacns.c index 9ead8843..1bcf3630 100644 --- a/src/libopensc/card-itacns.c +++ b/src/libopensc/card-itacns.c @@ -516,7 +516,7 @@ static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) } r = sc_read_binary(card, 0, rbuf, 256, 0); - if (r != SC_SUCCESS || r != 16 ) { + if ( r!=16 ) { return SC_ERROR_WRONG_CARD; } From 867176b0f7f50df6e31d3bea0bb07cd8b12a0aae Mon Sep 17 00:00:00 2001 From: resoli Date: Fri, 7 Nov 2014 12:49:44 +0100 Subject: [PATCH 006/306] itacns_get_serialnr(): check sc_read_binary() returned data length (only). --- src/libopensc/card-itacns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-itacns.c b/src/libopensc/card-itacns.c index 1bcf3630..d73057e6 100644 --- a/src/libopensc/card-itacns.c +++ b/src/libopensc/card-itacns.c @@ -516,7 +516,7 @@ static int itacns_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) } r = sc_read_binary(card, 0, rbuf, 256, 0); - if ( r!=16 ) { + if ( r != 16 ) { return SC_ERROR_WRONG_CARD; } From d6bb845a22953587459e56e6874d1a944588f7d1 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 19 Nov 2014 19:31:18 -0600 Subject: [PATCH 007/306] C_Digest does not check if buffer too small before update. Issue #327 C_Digest will now query for the buffer size using sc_pkcs15_md_final before calling sc_pkcs15_md_update. This avoids doing a double update when the user passes in a buffer to small, then gets the buffer and calls C_Digest again. --- src/pkcs11/pkcs11-object.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c index 1be59d9b..90b5e1d5 100644 --- a/src/pkcs11/pkcs11-object.c +++ b/src/pkcs11/pkcs11-object.c @@ -511,6 +511,7 @@ C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */ { CK_RV rv; struct sc_pkcs11_session *session; + CK_ULONG ulBuflen = 0; rv = sc_pkcs11_lock(); if (rv != CKR_OK) @@ -521,7 +522,21 @@ C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */ if (rv != CKR_OK) goto out; - rv = sc_pkcs11_md_update(session, pData, ulDataLen); + /* if pDigest == NULL, buffer size request */ + if (pDigest) { + /* As per PKCS#11 2.20 we need to check if buffer too small before update */ + rv = sc_pkcs11_md_final(session, NULL, &ulBuflen); + if (rv != CKR_OK) + goto out; + + if (ulBuflen > *pulDigestLen) { + *pulDigestLen = ulBuflen; + rv = CKR_BUFFER_TOO_SMALL; + goto out; + } + + rv = sc_pkcs11_md_update(session, pData, ulDataLen); + } if (rv == CKR_OK) rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen); From 238b9e344abfda7bde1876955213f1bad3052803 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 10 Dec 2014 11:07:56 +0100 Subject: [PATCH 008/306] Revert "Added ATR for ItalianCNS - Prov. BZ" --- src/libopensc/card-cardos.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index cbc48e83..52a90d94 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -47,8 +47,6 @@ static struct sc_atr_table cardos_atrs[] = { { "3b:e9:00:ff:c1:10:31:fe:55:00:64:05:00:c8:02:31:80:00:47", NULL, NULL, SC_CARD_TYPE_CARDOS_CIE_V1, 0, NULL }, /* Italian eID card, infocamere */ { "3b:fb:98:00:ff:c1:10:31:fe:55:00:64:05:20:47:03:31:80:00:90:00:f3", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL }, - /* Italian CNS - Prov. BZ */ - { "3b:ff:18:00:ff:c1:0a:31:fe:55:00:6b:05:08:c8:0c:01:11:01:43:4e:53:10:31:80:05", NULL, NULL, SC_CARD_TYPE_CARDOS_M4_2, 0, NULL }, /* Another Italian InfocamereCard */ { "3b:fc:98:00:ff:c1:10:31:fe:55:c8:03:49:6e:66:6f:63:61:6d:65:72:65:28", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL }, { "3b:f4:98:00:ff:c1:10:31:fe:55:4d:34:63:76:b4", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL}, From 69b27179eb65f645939aaa36faf72a38c5b07143 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sun, 7 Dec 2014 11:32:14 +0100 Subject: [PATCH 009/306] use path only if it is actually present --- src/libopensc/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/dir.c b/src/libopensc/dir.c index 8281fbc6..4a3b1485 100644 --- a/src/libopensc/dir.c +++ b/src/libopensc/dir.c @@ -91,7 +91,7 @@ parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen, int rec_nr) else app->label = NULL; - if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT) { + if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT && path_len > 0) { /* application path present: ignore AID */ if (path_len > SC_MAX_PATH_SIZE) { free(app); From e1fbdc030bab6355d9c69026da692bf50df06295 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sun, 7 Dec 2014 11:52:14 +0100 Subject: [PATCH 010/306] iso7816: make select agnosting to sc_path_t's aid --- src/libopensc/iso7816.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 4defc7f0..a35e4d01 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -452,17 +452,36 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct struct sc_apdu apdu; unsigned char buf[SC_MAX_APDU_BUFFER_SIZE]; unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf; - int r, pathlen; + int r, pathlen, pathtype; struct sc_file *file = NULL; assert(card != NULL && in_path != NULL); ctx = card->ctx; memcpy(path, in_path->value, in_path->len); pathlen = in_path->len; + pathtype = in_path->type; + + if (in_path->aid.len) { + /* First, select the application */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0); + apdu.data = in_path->aid.value; + apdu.datalen = in_path->aid.len; + apdu.lc = in_path->aid.len; + + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if (r) + LOG_FUNC_RETURN(ctx, r); + + if (pathtype == SC_PATH_TYPE_PATH + || pathtype == SC_PATH_TYPE_DF_NAME) + pathtype = SC_PATH_TYPE_FROM_CURRENT; + } sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0); - switch (in_path->type) { + switch (pathtype) { case SC_PATH_TYPE_FILE_ID: apdu.p1 = 0; if (pathlen != 2) From e137396d5655917e66bd34022026bb6462e9c541 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sun, 7 Dec 2014 17:19:45 +0100 Subject: [PATCH 011/306] workaround for compiler warnings --- src/libopensc/card-iasecc.c | 6 ++++-- src/libopensc/sc.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 905c0b23..4b0c74dc 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -2219,12 +2219,14 @@ iasecc_keyset_change(struct sc_card *card, struct sc_pin_cmd_data *data, int *tr update.fields[0].parent_tag = IASECC_SDO_KEYSET_TAG; update.fields[0].tag = IASECC_SDO_KEYSET_TAG_MAC; - update.fields[0].value = data->pin2.data; + /* FIXME is it safe to modify the const value here? */ + update.fields[0].value = (unsigned char *) data->pin2.data; update.fields[0].size = 16; update.fields[1].parent_tag = IASECC_SDO_KEYSET_TAG; update.fields[1].tag = IASECC_SDO_KEYSET_TAG_ENC; - update.fields[1].value = data->pin2.data + 16; + /* FIXME is it safe to modify the const value here? */ + update.fields[1].value = (unsigned char *) data->pin2.data + 16; update.fields[1].size = 16; rv = iasecc_sm_sdo_update(card, (scb & IASECC_SCB_METHOD_MASK_REF), &update); diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 1cc03109..a2be9b34 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -116,7 +116,7 @@ int sc_bin_to_hex(const u8 *in, size_t in_len, char *out, size_t out_len, */ size_t sc_right_trim(u8 *buf, size_t len) { - size_t i; + long i; for(i=len-1; i >=0; i--) { if(!isprint(buf[i])) { From 73715e37d92f60b4afbc6c608cbc281313781eb1 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sun, 7 Dec 2014 17:19:57 +0100 Subject: [PATCH 012/306] fixed compiler warnings fixed warnings introduced with b18c86e64621fa61555831802d9cd597e24e0ebc fixes memory leaks in pkcs15-init and pkcs15-tool --- src/tools/pkcs15-init.c | 60 ++++++++++++++++++++++++++-------------- src/tools/pkcs15-tool.c | 50 ++++++++++++++++++++++----------- src/tools/sc-hsm-tool.c | 16 ++++------- src/tools/westcos-tool.c | 10 +++---- 4 files changed, 83 insertions(+), 53 deletions(-) diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index b3d00581..52b78276 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -348,8 +348,9 @@ static char * opt_puk_label = NULL; static char * opt_pubkey_label = NULL; static char * opt_cert_label = NULL; static const char * opt_pins[4]; +static char * pins[4]; static char * opt_serial = NULL; -static char * opt_passphrase = NULL; +static const char * opt_passphrase = NULL; static char * opt_newkey = NULL; static char * opt_outkey = NULL; static char * opt_application_id = NULL; @@ -458,6 +459,10 @@ main(int argc, char **argv) return 1; } + for (n = 0; n < sizeof pins; n++) { + pins[n] = NULL; + } + for (n = 0; n < ACTION_MAX; n++) { unsigned int action = n; @@ -577,6 +582,10 @@ main(int argc, char **argv) } } + for (n = 0; n < sizeof pins; n++) { + free(pins[n]); + } + out: if (profile) { sc_pkcs15init_unbind(profile); @@ -754,9 +763,10 @@ do_init_app(struct sc_profile *profile) if (!opt_pins[2] && !opt_no_prompt && !opt_no_sopin) { - r = get_new_pin(&hints, role, "pin", &opt_pins[2]); + r = get_new_pin(&hints, role, "pin", &pins[2]); if (r < 0) goto failed; + opt_pins[2] = pins[2]; } if (!so_puk_disabled && opt_pins[2] && !opt_pins[3] && !opt_no_prompt) { @@ -766,9 +776,10 @@ do_init_app(struct sc_profile *profile) role = "user"; hints.flags |= SC_UI_PIN_OPTIONAL; - r = get_new_pin(&hints, role, "puk", &opt_pins[3]); + r = get_new_pin(&hints, role, "puk", &pins[3]); if (r < 0) goto failed; + opt_pins[3] = pins[3]; } args.so_pin = (const u8 *) opt_pins[2]; @@ -819,9 +830,11 @@ do_store_pin(struct sc_profile *profile) } sc_pkcs15init_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &info); - if (opt_pins[0] == NULL) - if ((r = get_new_pin(&hints, "user", "pin", &opt_pins[0])) < 0) + if (opt_pins[0] == NULL) { + if ((r = get_new_pin(&hints, "user", "pin", &pins[0])) < 0) goto failed; + opt_pins[0] = pins[0]; + } if (*opt_pins[0] == '\0') { util_error("You must specify a PIN\n"); @@ -839,9 +852,9 @@ do_store_pin(struct sc_profile *profile) sc_pkcs15init_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &info); hints.flags |= SC_UI_PIN_OPTIONAL; - if ((r = get_new_pin(&hints, "user", "puk", &opt_pins[1])) < 0) + if ((r = get_new_pin(&hints, "user", "puk", &pins[1])) < 0) goto failed; - + opt_pins[1] = pins[1]; } if (opt_puk_authid && opt_pins[1]) @@ -1693,19 +1706,19 @@ get_pin_callback(struct sc_profile *profile, switch (id) { case SC_PKCS15INIT_USER_PIN: name = "User PIN"; - secret = opt_pins[OPT_PIN1 & 3]; + secret = (char *) opt_pins[OPT_PIN1 & 3]; break; case SC_PKCS15INIT_USER_PUK: name = "User PIN unlock key"; - secret = opt_pins[OPT_PUK1 & 3]; + secret = (char *) opt_pins[OPT_PUK1 & 3]; break; case SC_PKCS15INIT_SO_PIN: name = "Security officer PIN"; - secret = opt_pins[OPT_PIN2 & 3]; + secret = (char *) opt_pins[OPT_PIN2 & 3]; break; case SC_PKCS15INIT_SO_PUK: name = "Security officer PIN unlock key"; - secret = opt_pins[OPT_PUK2 & 3]; + secret = (char *) opt_pins[OPT_PUK2 & 3]; break; } } @@ -1713,22 +1726,22 @@ get_pin_callback(struct sc_profile *profile, if (!(info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) && !(info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)) { name = "User PIN"; - secret = opt_pins[OPT_PIN1 & 3]; + secret = (char *) opt_pins[OPT_PIN1 & 3]; } else if (!(info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) && (info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)) { name = "User PUK"; - secret = opt_pins[OPT_PUK1 & 3]; + secret = (char *) opt_pins[OPT_PUK1 & 3]; } else if ((info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) && !(info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)) { name = "Security officer PIN"; - secret = opt_pins[OPT_PIN2 & 3]; + secret = (char *) opt_pins[OPT_PIN2 & 3]; } else if ((info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) && (info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)) { name = "Security officer PIN unlock key"; - secret = opt_pins[OPT_PUK2 & 3]; + secret = (char *) opt_pins[OPT_PUK2 & 3]; } } if (secret) @@ -1997,7 +2010,7 @@ do_read_private_key(const char *filename, const char *format, int r; if (opt_passphrase) - passphrase = opt_passphrase; + passphrase = (char *) opt_passphrase; if (!format || !strcasecmp(format, "pem")) { r = do_read_pem_private_key(filename, passphrase, pk); @@ -2026,8 +2039,12 @@ do_read_private_key(const char *filename, const char *format, return SC_ERROR_NOT_SUPPORTED; } + if (NULL == opt_passphrase) + free(passphrase); + if (r < 0) util_fatal("Unable to read private key from %s\n", filename); + return r; } @@ -2157,7 +2174,7 @@ static size_t determine_filesize(const char *filename) static int do_read_data_object(const char *name, u8 **out, size_t *outlen) { - FILE *inf; + FILE *inf; size_t filesize = determine_filesize(name); int c; @@ -2452,8 +2469,6 @@ handle_option(const struct option *opt) opt_serial = optarg; break; case OPT_PASSPHRASE: - free(opt_passphrase); - opt_passphrase = NULL; util_get_pin(optarg, &opt_passphrase); break; case OPT_PUBKEY: @@ -2773,7 +2788,7 @@ static int verify_pin(struct sc_pkcs15_card *p15card, char *auth_id_str) { struct sc_pkcs15_object *pin_obj = NULL; char pin_label[64]; - char *pin; + char *pin = NULL; int r; if (!auth_id_str) { @@ -2817,7 +2832,7 @@ static int verify_pin(struct sc_pkcs15_card *p15card, char *auth_id_str) } if (opt_pins[0] != NULL) { - pin = opt_pins[0]; + pin = (char *) opt_pins[0]; } else { sc_ui_hints_t hints; @@ -2844,5 +2859,8 @@ static int verify_pin(struct sc_pkcs15_card *p15card, char *auth_id_str) if (r < 0) fprintf(stderr, "Operation failed: %s\n", sc_strerror(r)); + if (NULL == opt_pins[0]) + free(pin); + return r; } diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index e5689fc0..603a7534 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -52,9 +52,9 @@ static char * opt_data = NULL; static char * opt_pubkey = NULL; static char * opt_outfile = NULL; static char * opt_bind_to_aid = NULL; -static const u8 * opt_newpin = NULL; -static const u8 * opt_pin = NULL; -static const u8 * opt_puk = NULL; +static const char * opt_newpin = NULL; +static const char * opt_pin = NULL; +static const char * opt_puk = NULL; static int verbose = 0; static int opt_no_prompt = 0; @@ -1116,7 +1116,7 @@ static int verify_pin(void) } if (opt_pin != NULL) - pin = opt_pin; + pin = (unsigned char *) opt_pin; else pin = get_pin("Please enter PIN", pin_obj); @@ -1127,13 +1127,16 @@ static int verify_pin(void) return -1; } + if (opt_pin == NULL) + free(pin); + return 0; } static int authenticate(sc_pkcs15_object_t *obj) { sc_pkcs15_object_t *pin_obj; - u8 *pin; + u8 *pin = NULL; int r; if (obj->auth_id.len == 0) @@ -1143,11 +1146,16 @@ static int authenticate(sc_pkcs15_object_t *obj) return r; if (opt_pin != NULL) - pin = opt_pin; + pin = (u8 *) opt_pin; else pin = get_pin("Please enter PIN", pin_obj); - return sc_pkcs15_verify_pin(p15card, pin_obj, pin, pin? strlen((char *) pin) : 0); + r = sc_pkcs15_verify_pin(p15card, pin_obj, pin, pin? strlen((char *) pin) : 0); + + if (opt_pin == NULL) + free(pin); + + return r; } static void print_pin_info(const struct sc_pkcs15_object *obj) @@ -1307,7 +1315,7 @@ static int unblock_pin(void) if (pinfo->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return 1; - puk = opt_puk; + puk = (u8 *) opt_puk; if (puk == NULL) { sc_pkcs15_object_t *puk_obj = NULL; @@ -1338,7 +1346,7 @@ static int unblock_pin(void) printf("PUK value will be prompted with pinpad.\n"); /* FIXME should OPENSSL_cleanse on pin/puk data */ - pin = opt_pin ? opt_pin : opt_newpin; + pin = opt_pin ? (u8 *) opt_pin : (u8 *) opt_newpin; while (pin == NULL) { u8 *pin2; @@ -1365,7 +1373,12 @@ static int unblock_pin(void) r = sc_pkcs15_unblock_pin(p15card, pin_obj, puk, puk ? strlen((char *) puk) : 0, pin, pin ? strlen((char *) pin) : 0); - /* FIXME must free the puk somewhere */ + + if (NULL == opt_puk) + free(puk); + if (NULL == opt_pin && NULL == opt_newpin) + free(pin); + if (r == SC_ERROR_PIN_CODE_INCORRECT) { fprintf(stderr, "PUK code incorrect; tries left: %d\n", pinfo->tries_left); return 3; @@ -1405,7 +1418,7 @@ static int change_pin(void) } } - pincode = opt_pin; + pincode = (u8 *) opt_pin; if (pincode == NULL) { pincode = get_pin("Enter old PIN", pin_obj); if (!pinpad_present && pincode == NULL) @@ -1420,7 +1433,7 @@ static int change_pin(void) if (pincode == NULL && verbose) printf("Old PIN value will be prompted with pinpad.\n"); - newpin = opt_newpin; + newpin = (u8 *) opt_newpin; while (newpin == NULL) { u8 *newpin2; @@ -1459,7 +1472,12 @@ static int change_pin(void) } if (verbose) printf("PIN code changed successfully.\n"); - /* FIXME must free the pincode somewhere */ + + if (opt_pin == NULL) + free(pincode); + if (opt_newpin == NULL) + free(newpin); + return 0; } @@ -1890,13 +1908,13 @@ int main(int argc, char * const argv[]) opt_reader = optarg; break; case OPT_PIN: - util_get_pin(optarg, (const u8 **) &opt_pin); + util_get_pin(optarg, &opt_pin); break; case OPT_NEWPIN: - util_get_pin(optarg, (const u8 **) &opt_newpin); + util_get_pin(optarg, &opt_newpin); break; case OPT_PUK: - util_get_pin(optarg, (const u8 **) &opt_puk); + util_get_pin(optarg, &opt_puk); break; case 'o': opt_outfile = optarg; diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index 2d173a0e..ac94aa90 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -664,7 +664,7 @@ static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_pas -static int import_dkek_share(sc_card_t *card, const char *inf, int iter, char *password, int num_of_password_shares) +static int import_dkek_share(sc_card_t *card, const char *inf, int iter, const char *password, int num_of_password_shares) { sc_cardctl_sc_hsm_dkek_t dkekinfo; EVP_CIPHER_CTX ctx; @@ -712,7 +712,7 @@ static int import_dkek_share(sc_card_t *card, const char *inf, int iter, char *p } } else { - pwd = password; + pwd = (char *) password; pwdlen = strlen(password); } @@ -904,7 +904,7 @@ static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int pas -static int create_dkek_share(sc_card_t *card, const char *outf, int iter, char *password, int password_shares_threshold, int password_shares_total) +static int create_dkek_share(sc_card_t *card, const char *outf, int iter, const char *password, int password_shares_threshold, int password_shares_total) { EVP_CIPHER_CTX ctx; FILE *out = NULL; @@ -927,7 +927,7 @@ static int create_dkek_share(sc_card_t *card, const char *outf, int iter, char * } } else { - pwd = password; + pwd = (char *) password; pwdlen = strlen(password); } @@ -1439,7 +1439,7 @@ int main(int argc, char * const argv[]) const char *opt_so_pin = NULL; const char *opt_pin = NULL; const char *opt_filename = NULL; - char *opt_password = NULL; + const char *opt_password = NULL; int opt_retry_counter = 3; int opt_dkek_shares = -1; int opt_key_reference = -1; @@ -1484,18 +1484,12 @@ int main(int argc, char * const argv[]) action_count++; break; case OPT_PASSWORD: - free(opt_password); - opt_password = NULL; util_get_pin(optarg, &opt_password); break; case OPT_SO_PIN: - free(opt_so_pin); - opt_so_pin = NULL; util_get_pin(optarg, &opt_so_pin); break; case OPT_PIN: - free(opt_pin); - opt_pin = NULL; util_get_pin(optarg, &opt_pin); break; case OPT_RETRY: diff --git a/src/tools/westcos-tool.c b/src/tools/westcos-tool.c index 83ece8e8..54a5d65d 100644 --- a/src/tools/westcos-tool.c +++ b/src/tools/westcos-tool.c @@ -126,7 +126,7 @@ static void print_openssl_error(void) printf("%s\n", ERR_error_string(r, NULL)); } -static int verify_pin(sc_card_t *card, int pin_reference, char *pin_value) +static int verify_pin(sc_card_t *card, int pin_reference, const char *pin_value) { int r, tries_left = -1; struct sc_pin_cmd_data data; @@ -178,8 +178,8 @@ static int verify_pin(sc_card_t *card, int pin_reference, char *pin_value) static int change_pin(sc_card_t *card, int pin_reference, - char *pin_value1, - char *pin_value2) + const char *pin_value1, + const char *pin_value2) { int r, tries_left = -1; struct sc_pin_cmd_data data; @@ -236,8 +236,8 @@ static int change_pin(sc_card_t *card, static int unlock_pin(sc_card_t *card, int pin_reference, - char *puk_value, - char *pin_value) + const char *puk_value, + const char *pin_value) { int r, tries_left = -1; struct sc_pin_cmd_data data; From 45fe96579fed3433ecd75cc1bd8d1516c4142aa2 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 10 Dec 2014 22:58:48 +0100 Subject: [PATCH 013/306] added support for sc_path_t with only aid set --- src/libopensc/iso7816.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index a35e4d01..ab901fbe 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -462,21 +462,27 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct pathtype = in_path->type; if (in_path->aid.len) { - /* First, select the application */ - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0); - apdu.data = in_path->aid.value; - apdu.datalen = in_path->aid.len; - apdu.lc = in_path->aid.len; + if (!pathlen) { + memcpy(path, in_path->aid.value, in_path->aid.len); + pathlen = in_path->aid.len; + pathtype = SC_PATH_TYPE_DF_NAME; + } else { + /* First, select the application */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0); + apdu.data = in_path->aid.value; + apdu.datalen = in_path->aid.len; + apdu.lc = in_path->aid.len; - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(ctx, r, "APDU transmit failed"); - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if (r) - LOG_FUNC_RETURN(ctx, r); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if (r) + LOG_FUNC_RETURN(ctx, r); - if (pathtype == SC_PATH_TYPE_PATH - || pathtype == SC_PATH_TYPE_DF_NAME) - pathtype = SC_PATH_TYPE_FROM_CURRENT; + if (pathtype == SC_PATH_TYPE_PATH + || pathtype == SC_PATH_TYPE_DF_NAME) + pathtype = SC_PATH_TYPE_FROM_CURRENT; + } } sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0); From 4d5997dfba5845820e301e8804c3335122403bad Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 12 Dec 2014 22:30:21 +0100 Subject: [PATCH 014/306] fixed selection of muscle applet for some JCREs Previously, partial DF name selection was used, which is not mandatory to implement for a JCRE. We now use the full DF name which must always be implemented. Note that the MUSCLE applet is deprecated and should not be used. fixes #135 --- src/libopensc/card-muscle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-muscle.c b/src/libopensc/card-muscle.c index 3b0562bf..31304b8f 100644 --- a/src/libopensc/card-muscle.c +++ b/src/libopensc/card-muscle.c @@ -81,7 +81,7 @@ static int muscle_match_card(sc_card_t *card) * however it's not always properly nulled out... */ card->ops->logout = NULL; - if (msc_select_applet(card, muscleAppletId, 5) == 1) { + if (msc_select_applet(card, muscleAppletId, sizeof muscleAppletId) == 1) { /* Muscle applet is present, check the protocol version to be sure */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x3C, 0x00, 0x00); apdu.cla = 0xB0; From aa7886f36dd99de34c7105aa66c216f4a50dd248 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 19 Dec 2014 16:52:14 +0100 Subject: [PATCH 015/306] pkcs15-init: fix memory corruption --- src/tools/pkcs15-init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 52b78276..aa3474a6 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -459,7 +459,7 @@ main(int argc, char **argv) return 1; } - for (n = 0; n < sizeof pins; n++) { + for (n = 0; n < sizeof(pins)/sizeof(pins[0]); n++) { pins[n] = NULL; } @@ -582,7 +582,7 @@ main(int argc, char **argv) } } - for (n = 0; n < sizeof pins; n++) { + for (n = 0; n < sizeof(pins)/sizeof(pins[0]); n++) { free(pins[n]); } From 291e9dab9e9032348908283675c71d563ec5fe95 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 19 Dec 2014 22:12:25 +0100 Subject: [PATCH 016/306] use OpenSC as default PKCS#11 provider closes #229 --- configure.ac | 27 +++++++++++++++++++++++++++ src/tools/pkcs11-tool.c | 7 ++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index b2853ae3..a39e7284 100644 --- a/configure.ac +++ b/configure.ac @@ -218,6 +218,13 @@ AC_ARG_WITH( , [with_pcsc_provider="detect"] ) + +AC_ARG_WITH( + [pkcs11-provider], + [AS_HELP_STRING([--with-pkcs11-provider=PATH],[Path to the default PKCS11 provider @<:@default=OpenSC@:>@])], + , + [with_pkcs11_provider="detect"] +) dnl ./configure check reader_count="" for rdriver in "${enable_pcsc}" "${enable_openct}" "${enable_ctapi}"; do @@ -568,6 +575,24 @@ if test "${enable_pcsc}" = "yes"; then AC_DEFINE([ENABLE_PCSC], [1], [Define if PC/SC is to be enabled]) fi + +if test "${with_pkcs11_provider}" = "detect"; then + case "${host}" in + *-*-darwin*) + DEFAULT_PKCS11_PROVIDER="opensc-pkcs11.dylib" + ;; + *-mingw*|*-winnt*|*-cygwin*) + DEFAULT_PKCS11_PROVIDER="opensc-pkcs11.dll" + ;; + *) + DEFAULT_PKCS11_PROVIDER="opensc-pkcs11.so" + ;; + esac +else + DEFAULT_PKCS11_PROVIDER="${with_pkcs11_provider}" +fi +AC_DEFINE_UNQUOTED([DEFAULT_PKCS11_PROVIDER], ["${DEFAULT_PKCS11_PROVIDER}"], [Default PKCS11 provider]) + if test "${enable_man}" = "detect"; then if test "${WIN32}" = "yes"; then enable_man="no" @@ -643,6 +668,7 @@ AC_SUBST([OPENSC_LT_AGE]) AC_SUBST([OPENSC_LT_OLDEST]) AC_SUBST([WIN_LIBPREFIX]) AC_SUBST([DEFAULT_PCSC_PROVIDER]) +AC_SUBST([DEFAULT_PKCS11_PROVIDER]) AC_SUBST([OPTIONAL_ZLIB_CFLAGS]) AC_SUBST([OPTIONAL_ZLIB_LIBS]) AC_SUBST([OPTIONAL_READLINE_CFLAGS]) @@ -752,6 +778,7 @@ DNIe UI support: ${enable_dnie_ui} Debug file: ${DEBUG_FILE} PC/SC default provider: ${DEFAULT_PCSC_PROVIDER} +PKCS11 default provider: ${DEFAULT_PKCS11_PROVIDER} Host: ${host} Compiler: ${CC} diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index dafd8181..846825f2 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -166,7 +166,7 @@ static const struct option options[] = { }; static const char *option_help[] = { - "Specify the module to load (mandatory)", + "Specify the module to load (default:" DEFAULT_PKCS11_PROVIDER ")", "Show global token information", "List available slots", "List slots with tokens", @@ -225,7 +225,7 @@ static const char * app_name = "pkcs11-tool"; /* for utils.c */ static int verbose = 0; static const char * opt_input = NULL; static const char * opt_output = NULL; -static const char * opt_module = NULL; +static const char * opt_module = DEFAULT_PKCS11_PROVIDER; static int opt_slot_set = 0; static CK_SLOT_ID opt_slot = 0; static const char * opt_slot_description = NULL; @@ -653,9 +653,6 @@ int main(int argc, char * argv[]) } } - if (opt_module == NULL) - util_print_usage_and_die(app_name, options, option_help, NULL); - if (action_count == 0) util_print_usage_and_die(app_name, options, option_help, NULL); From facaf5969bc80ac82395fa2789df32c48e373085 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Fri, 19 Dec 2014 17:15:41 +0100 Subject: [PATCH 017/306] Improve PKCS#11 compliance. Issue #335 * Add default behavior for cards using the PKCS#15 emulation layer. Hence, this patch provide a default value for access_flags compatible with current OpenSC's behavior while allowing compatible cards to fetch the real value from the card (IAS-ECC and AuthentIC). --- src/libopensc/pkcs15-atrust-acos.c | 5 +++++ src/libopensc/pkcs15-esteid.c | 5 +++++ src/libopensc/pkcs15-gemsafeGPK.c | 5 +++++ src/libopensc/pkcs15-openpgp.c | 5 +++++ src/libopensc/pkcs15-piv.c | 5 +++++ src/libopensc/pkcs15-pteid.c | 5 +++++ src/libopensc/pkcs15-starcert.c | 5 +++++ src/libopensc/pkcs15-tcos.c | 5 +++++ src/libopensc/pkcs15-westcos.c | 5 +++++ 9 files changed, 45 insertions(+) diff --git a/src/libopensc/pkcs15-atrust-acos.c b/src/libopensc/pkcs15-atrust-acos.c index f59539bb..67717cd2 100644 --- a/src/libopensc/pkcs15-atrust-acos.c +++ b/src/libopensc/pkcs15-atrust-acos.c @@ -235,6 +235,11 @@ static int sc_pkcs15emu_atrust_acos_init(sc_pkcs15_card_t *p15card) sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-esteid.c b/src/libopensc/pkcs15-esteid.c index 6975fe10..adf080b3 100644 --- a/src/libopensc/pkcs15-esteid.c +++ b/src/libopensc/pkcs15-esteid.c @@ -238,6 +238,11 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) prkey_info.id.value[0] = prkey_pin[i]; prkey_info.usage = prkey_usage[i]; prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = i + 1; if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) prkey_info.modulus_length = 2048; diff --git a/src/libopensc/pkcs15-gemsafeGPK.c b/src/libopensc/pkcs15-gemsafeGPK.c index 551b0a3b..64ed894b 100644 --- a/src/libopensc/pkcs15-gemsafeGPK.c +++ b/src/libopensc/pkcs15-gemsafeGPK.c @@ -472,6 +472,11 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card) sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c index 4daaa98c..81ffdb47 100644 --- a/src/libopensc/pkcs15-openpgp.c +++ b/src/libopensc/pkcs15-openpgp.c @@ -271,6 +271,11 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) prkey_info.id.value[0] = i + 1; prkey_info.usage = key_cfg[i].prkey_usage; prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = i; prkey_info.modulus_length = bebytes2ushort(cxdata + 1); diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index 7f465987..20182315 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -965,6 +965,11 @@ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE Adding pin %d label=%s",i, label); sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = prkeys[i].ref; sc_format_path(prkeys[i].path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-pteid.c b/src/libopensc/pkcs15-pteid.c index 028ef27d..f19ed529 100644 --- a/src/libopensc/pkcs15-pteid.c +++ b/src/libopensc/pkcs15-pteid.c @@ -206,6 +206,11 @@ static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card) prkey_info.id.value[0] = pteid_prkey_ids[i]; prkey_info.usage = pteid_prkey_usage[i]; prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = pteid_prkey_keyref[type][i]; prkey_info.modulus_length = 1024; if (pteid_prkey_paths[type][i] != NULL) diff --git a/src/libopensc/pkcs15-starcert.c b/src/libopensc/pkcs15-starcert.c index 19faefc8..f7c9c697 100644 --- a/src/libopensc/pkcs15-starcert.c +++ b/src/libopensc/pkcs15-starcert.c @@ -240,6 +240,11 @@ static int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card) sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c index 4c98518e..024ef843 100644 --- a/src/libopensc/pkcs15-tcos.c +++ b/src/libopensc/pkcs15-tcos.c @@ -112,6 +112,11 @@ static int insert_key( prkey_info.id.len = 1; prkey_info.id.value[0] = id; prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = key_reference; prkey_info.modulus_length = key_length; sc_format_path(path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-westcos.c b/src/libopensc/pkcs15-westcos.c index 8bd4d645..66746734 100644 --- a/src/libopensc/pkcs15-westcos.c +++ b/src/libopensc/pkcs15-westcos.c @@ -216,6 +216,11 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card) SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; prkey_info.native = 1; + /* Add default access_flags, see Issues #335 and #336 */ + prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE + | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE + | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE + | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = 1; prkey_info.modulus_length = modulus_length; prkey_info.path = path; From 3961275d8c680771b1669f44a388d6d84a614e14 Mon Sep 17 00:00:00 2001 From: Andreas Schwier Date: Mon, 3 Nov 2014 15:49:28 +0100 Subject: [PATCH 018/306] Allow user to overwrite SO-PIN when using PIN-PAD reader --- src/tools/pkcs11-tool.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index dafd8181..4a1de177 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -1138,8 +1138,10 @@ static void init_token(CK_SLOT_ID slot) opt_object_label); get_token_info(slot, &info); - if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { - if (opt_so_pin == NULL) { + if (opt_so_pin != NULL) { + new_pin = opt_so_pin; + } else { + if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { printf("Please enter the new SO PIN: "); r = util_getpass(&new_pin, &len, stdin); if (r < 0) @@ -1156,11 +1158,7 @@ static void init_token(CK_SLOT_ID slot) strcmp(new_buf, new_pin) != 0) util_fatal("Different new SO PINs, exiting\n"); pin_allocated = 1; - } else { - new_pin = (char *) opt_so_pin; } - if (!new_pin || !*new_pin) - util_fatal("Invalid SO PIN\n"); } rv = p11->C_InitToken(slot, (CK_UTF8CHAR *) new_pin, From 7e7a44acff9d3aec082076b556a9363081df862a Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Tue, 28 Oct 2014 09:05:02 +0100 Subject: [PATCH 019/306] sc_asn1_put_tag - support larger tags Enhance sc_asn1_put_tag to support larger tag names and larger tags. Prior to this, sc_asn1_put_tag did only support tags with a length of at most 127 bytes and tag names of one byte. --- src/libopensc/asn1.c | 73 ++++++++++++++++++++++++++++++++++++-------- src/libopensc/asn1.h | 6 ++-- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index cad459b0..bed2c04c 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -740,23 +740,70 @@ static int sc_asn1_decode_utf8string(const u8 *inbuf, size_t inlen, return 0; } -int sc_asn1_put_tag(int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 **ptr) +int sc_asn1_put_tag(unsigned int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 **ptr) { + size_t c = 0; + size_t tag_len; + size_t ii; u8 *p = out; + u8 tag_char[4] = {0, 0, 0, 0}; - if (outlen < 2) - return SC_ERROR_INVALID_ARGUMENTS; - if (datalen > 127) - return SC_ERROR_INVALID_ARGUMENTS; - *p++ = tag & 0xFF; /* FIXME: Support longer tags */ - outlen--; - *p++ = datalen; - outlen--; - if (outlen < datalen) - return SC_ERROR_INVALID_ARGUMENTS; + /* Check tag */ + if (tag == 0 || tag > 0xFFFFFFFF) { + /* A tag of 0x00 is not valid and at most 4-byte tag names are supported. */ + return SC_ERROR_INVALID_DATA; + } + for (tag_len = 0; tag; tag >>= 8) { + /* Note: tag char will be reversed order. */ + tag_char[tag_len++] = tag & 0xFF; + } - memcpy(p, data, datalen); - p += datalen; + if (tag_len > 1) { + if ((tag_char[tag_len - 1] & SC_ASN1_TAG_PRIMITIVE) != SC_ASN1_TAG_ESCAPE_MARKER) { + /* First byte is not escape marker. */ + return SC_ERROR_INVALID_DATA; + } + for (ii = 1; ii < tag_len - 1; ii++) { + if ((tag_char[ii] & 0x80) != 0x80) { + /* MS bit is not 'one'. */ + return SC_ERROR_INVALID_DATA; + } + } + if ((tag_char[0] & 0x80) != 0x00) { + /* MS bit of the last byte is not 'zero'. */ + return SC_ERROR_INVALID_DATA; + } + } + + /* Calculate the number of additional bytes necessary to encode the length. */ + /* c+1 is the size of the length field. */ + if (datalen > 127) { + c = 1; + while (datalen >> (c << 3)) + c++; + } + if (outlen == 0 || out == NULL) { + /* Caller only asks for the length that would be written. */ + return tag_len + (c+1) + datalen; + } + /* We will write the tag, so check the length. */ + if (outlen < tag_len + (c+1) + datalen) + return SC_ERROR_BUFFER_TOO_SMALL; + for (ii=0;ii 0) { + *p++ = 0x80 | c; + while (c--) + *p++ = (datalen >> (c << 3)) & 0xFF; + } + else { + *p++ = datalen & 0x7F; + } + if(data && datalen > 0) { + memcpy(p, data, datalen); + p += datalen; + } if (ptr != NULL) *ptr = p; return 0; diff --git a/src/libopensc/asn1.h b/src/libopensc/asn1.h index 1189275f..ef674d03 100644 --- a/src/libopensc/asn1.h +++ b/src/libopensc/asn1.h @@ -84,8 +84,10 @@ const u8 *sc_asn1_skip_tag(struct sc_context *ctx, const u8 ** buf, /* DER encoding */ /* Argument 'ptr' is set to the location of the next possible ASN.1 object. - * If NULL, no action on 'ptr' is performed. */ -int sc_asn1_put_tag(int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 ** ptr); + * If NULL, no action on 'ptr' is performed. + * If out is NULL or outlen is zero, the length that would be written is returned. + * If data is NULL, the data field will not be written. This is helpful for constructed structures. */ +int sc_asn1_put_tag(unsigned int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 ** ptr); /* ASN.1 printing functions */ void sc_asn1_print_tags(const u8 * buf, size_t buflen); From 32d8173b4c48e94fe39c97d2d2ba9b48aa47e19e Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Fri, 19 Dec 2014 17:21:37 +0100 Subject: [PATCH 020/306] IAS-ECC: Improve detection Gemalto cards(Issue #343) * Improve IAS-ECC card detection using the ATRMask. Previous commit was revert since work was not done in topic branch. --- src/libopensc/card-iasecc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 4b0c74dc..6e26c87d 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -71,7 +71,7 @@ static struct sc_card_driver iasecc_drv = { static struct sc_atr_table iasecc_known_atrs[] = { { "3B:7F:96:00:00:00:31:B8:64:40:70:14:10:73:94:01:80:82:90:00", - "FF:FF:FF:FF:FF:FF:FF:FE:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF", + "FF:FF:FF:FF:FF:FF:FF:FE:FF:FF:00:00:FF:FF:FF:FF:FF:FF:FF:FF", "IAS/ECC Gemalto", SC_CARD_TYPE_IASECC_GEMALTO, 0, NULL }, { "3B:DD:18:00:81:31:FE:45:80:F9:A0:00:00:00:77:01:08:00:07:90:00:FE", NULL, "IAS/ECC v1.0.1 Oberthur", SC_CARD_TYPE_IASECC_OBERTHUR, 0, NULL }, From bbedd4ef00bf457fdf11be7899c64579248885e1 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Wed, 3 Dec 2014 18:05:32 +0100 Subject: [PATCH 021/306] IAS-ECC: improve PKCS#11 compliance Issue #336 * Ensure CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE are only set when generating the key on board, not reason to set them when importing a private key. --- src/pkcs15init/pkcs15-iasecc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pkcs15init/pkcs15-iasecc.c b/src/pkcs15init/pkcs15-iasecc.c index 7df8103e..025f9ea0 100644 --- a/src/pkcs15init/pkcs15-iasecc.c +++ b/src/pkcs15init/pkcs15-iasecc.c @@ -889,8 +889,6 @@ iasecc_pkcs15_fix_private_key_attributes(struct sc_profile *profile, struct sc_p LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported object type"); key_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_SENSITIVE; - key_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE; - key_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE; sc_log(ctx, "SDO(class:%X,ref:%X,usage:%X)", sdo_prvkey->sdo_class, sdo_prvkey->sdo_ref, sdo_prvkey->usage); @@ -1129,6 +1127,8 @@ iasecc_pkcs15_generate_key(struct sc_profile *profile, sc_pkcs15_card_t *p15card LOG_TEST_RET(ctx, rv, "SC_AC_OP_GENERATE authentication failed"); key_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_LOCAL; + key_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE; + key_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE; rv = sc_card_ctl(card, SC_CARDCTL_IASECC_SDO_GENERATE, sdo_prvkey); LOG_TEST_RET(ctx, rv, "generate key failed"); From 4915eaa56b4e81346e1696b2cb38a0f2df14db5b Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Wed, 3 Dec 2014 17:59:04 +0100 Subject: [PATCH 022/306] Improve PKCS#11 compliance. Issue #335 * This simple patch allows for values of PKCS#11 attributes to be fetched from the underlying card. --- src/pkcs11/framework-pkcs15.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index a4ef46f0..ebe9f452 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -3368,14 +3368,26 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session, *(CK_OBJECT_CLASS*)attr->pValue = CKO_PRIVATE_KEY; break; case CKA_TOKEN: - case CKA_LOCAL: - case CKA_SENSITIVE: - case CKA_ALWAYS_SENSITIVE: - case CKA_NEVER_EXTRACTABLE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = TRUE; break; - case CKA_ALWAYS_AUTHENTICATE: + case CKA_ALWAYS_SENSITIVE: + check_attribute_buffer(attr, sizeof(CK_BBOOL)); + *(CK_BBOOL*)attr->pValue = (prkey->prv_info->access_flags & SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE) != 0; + break; + case CKA_NEVER_EXTRACTABLE: + check_attribute_buffer(attr, sizeof(CK_BBOOL)); + *(CK_BBOOL*)attr->pValue = (prkey->prv_info->access_flags & SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE) != 0; + break; + case CKA_SENSITIVE: + check_attribute_buffer(attr, sizeof(CK_BBOOL)); + *(CK_BBOOL*)attr->pValue = (prkey->prv_info->access_flags & SC_PKCS15_PRKEY_ACCESS_SENSITIVE) != 0; + break; + case CKA_LOCAL: + check_attribute_buffer(attr, sizeof(CK_BBOOL)); + *(CK_BBOOL*)attr->pValue = (prkey->prv_info->access_flags & SC_PKCS15_PRKEY_ACCESS_LOCAL) != 0; + break; + case CKA_ALWAYS_AUTHENTICATE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = prkey->prv_p15obj->user_consent; break; From d727acb47a58684dd46c7dd5c452eee07eac1a6f Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Wed, 14 Jan 2015 17:22:43 +0100 Subject: [PATCH 023/306] PKCS#11: Remove inconsistent attributes * Improve compliance related to PKCS#11 attribute fetching. --- src/pkcs11/framework-pkcs15.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index ebe9f452..c053f085 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -3429,14 +3429,10 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session, check_attribute_buffer(attr, sizeof(CK_MECHANISM_TYPE)); *(CK_MECHANISM_TYPE*)attr->pValue = CK_UNAVAILABLE_INFORMATION; break; - case CKA_ENCRYPT: case CKA_DECRYPT: case CKA_SIGN: case CKA_SIGN_RECOVER: - case CKA_WRAP: case CKA_UNWRAP: - case CKA_VERIFY: - case CKA_VERIFY_RECOVER: case CKA_DERIVE: case CKA_OPENSC_NON_REPUDIATION: /* TODO seems to be obsolete */ @@ -3862,8 +3858,6 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ case CKA_TOKEN: case CKA_LOCAL: case CKA_SENSITIVE: - case CKA_ALWAYS_SENSITIVE: - case CKA_NEVER_EXTRACTABLE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = TRUE; break; @@ -3925,11 +3919,7 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ *(CK_MECHANISM_TYPE*)attr->pValue = CK_UNAVAILABLE_INFORMATION; break; case CKA_ENCRYPT: - case CKA_DECRYPT: - case CKA_SIGN: - case CKA_SIGN_RECOVER: case CKA_WRAP: - case CKA_UNWRAP: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_DERIVE: From ed87ea38b9e8439eb7a20f6497f23b40beff25f8 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Wed, 14 Jan 2015 17:37:08 +0100 Subject: [PATCH 024/306] PKCS#11: Fetch real value of CKA_LOCAL for pubkey * Fetch value from pub_info structure for CKA_LOCAL attribute. --- src/pkcs11/framework-pkcs15.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index c053f085..15add105 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -3856,11 +3856,17 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ *(CK_OBJECT_CLASS*)attr->pValue = CKO_PUBLIC_KEY; break; case CKA_TOKEN: - case CKA_LOCAL: case CKA_SENSITIVE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = TRUE; break; + case CKA_LOCAL: + check_attribute_buffer(attr, sizeof(CK_BBOOL)); + if (pubkey->pub_info) + *(CK_BBOOL*)attr->pValue = (pubkey->pub_info->access_flags & SC_PKCS15_PRKEY_ACCESS_LOCAL) != 0; + else /* no pub_info structure, falling back to TRUE */ + *(CK_BBOOL*)attr->pValue = TRUE; + break; case CKA_PRIVATE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); if (pubkey->pub_p15obj) From 91ddcfb514991b75dacc143e427f8dd01f98c5e9 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Fri, 16 Jan 2015 10:03:13 +0100 Subject: [PATCH 025/306] PKCS15: remove redundant code for access_flags. * With commit facaf59, access_flags were set for most cards. A closer look revealed that this is already done in `sc_pkcs15emu_add_rsa_prkey`. Therefore, this removes the duplicated code for cards calling this function. --- src/libopensc/pkcs15-actalis.c | 4 ---- src/libopensc/pkcs15-atrust-acos.c | 5 ----- src/libopensc/pkcs15-esteid.c | 5 ----- src/libopensc/pkcs15-gemsafeGPK.c | 5 ----- src/libopensc/pkcs15-infocamere.c | 4 ---- src/libopensc/pkcs15-itacns.c | 5 ----- src/libopensc/pkcs15-oberthur.c | 4 ---- src/libopensc/pkcs15-openpgp.c | 5 ----- src/libopensc/pkcs15-piv.c | 5 ----- src/libopensc/pkcs15-postecert.c | 4 ---- src/libopensc/pkcs15-pteid.c | 5 ----- src/libopensc/pkcs15-starcert.c | 5 ----- src/libopensc/pkcs15-tcos.c | 5 ----- src/libopensc/pkcs15-westcos.c | 5 ----- 14 files changed, 66 deletions(-) diff --git a/src/libopensc/pkcs15-actalis.c b/src/libopensc/pkcs15-actalis.c index de335891..b8b2a0f7 100644 --- a/src/libopensc/pkcs15-actalis.c +++ b/src/libopensc/pkcs15-actalis.c @@ -122,10 +122,6 @@ static int sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, info.modulus_length = modulus_length; info.usage = usage; info.native = 1; - info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; info.key_reference = ref; if (path) diff --git a/src/libopensc/pkcs15-atrust-acos.c b/src/libopensc/pkcs15-atrust-acos.c index 67717cd2..f59539bb 100644 --- a/src/libopensc/pkcs15-atrust-acos.c +++ b/src/libopensc/pkcs15-atrust-acos.c @@ -235,11 +235,6 @@ static int sc_pkcs15emu_atrust_acos_init(sc_pkcs15_card_t *p15card) sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-esteid.c b/src/libopensc/pkcs15-esteid.c index adf080b3..6975fe10 100644 --- a/src/libopensc/pkcs15-esteid.c +++ b/src/libopensc/pkcs15-esteid.c @@ -238,11 +238,6 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) prkey_info.id.value[0] = prkey_pin[i]; prkey_info.usage = prkey_usage[i]; prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = i + 1; if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) prkey_info.modulus_length = 2048; diff --git a/src/libopensc/pkcs15-gemsafeGPK.c b/src/libopensc/pkcs15-gemsafeGPK.c index 64ed894b..551b0a3b 100644 --- a/src/libopensc/pkcs15-gemsafeGPK.c +++ b/src/libopensc/pkcs15-gemsafeGPK.c @@ -472,11 +472,6 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card) sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-infocamere.c b/src/libopensc/pkcs15-infocamere.c index 1504d40d..1ea1fefa 100644 --- a/src/libopensc/pkcs15-infocamere.c +++ b/src/libopensc/pkcs15-infocamere.c @@ -117,10 +117,6 @@ static int sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, info.modulus_length = modulus_length; info.usage = usage; info.native = 1; - info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; info.key_reference = ref; if (path) diff --git a/src/libopensc/pkcs15-itacns.c b/src/libopensc/pkcs15-itacns.c index 0977af9d..c56f05c5 100644 --- a/src/libopensc/pkcs15-itacns.c +++ b/src/libopensc/pkcs15-itacns.c @@ -319,11 +319,6 @@ static int itacns_add_prkey(sc_pkcs15_card_t *p15card, info.usage = usage; info.native = 1; info.key_reference = ref; - info.access_flags = - SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; if (path) info.path = *path; diff --git a/src/libopensc/pkcs15-oberthur.c b/src/libopensc/pkcs15-oberthur.c index bbdd14fd..db849930 100644 --- a/src/libopensc/pkcs15-oberthur.c +++ b/src/libopensc/pkcs15-oberthur.c @@ -800,10 +800,6 @@ sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card, kinfo.modulus_length = size; kinfo.native = 1; - kinfo.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; kinfo.key_reference = file_id & 0xFF; kinfo.usage = sc_oberthur_decode_usage(flags); diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c index 81ffdb47..4daaa98c 100644 --- a/src/libopensc/pkcs15-openpgp.c +++ b/src/libopensc/pkcs15-openpgp.c @@ -271,11 +271,6 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) prkey_info.id.value[0] = i + 1; prkey_info.usage = key_cfg[i].prkey_usage; prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = i; prkey_info.modulus_length = bebytes2ushort(cxdata + 1); diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index 20182315..7f465987 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -965,11 +965,6 @@ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE Adding pin %d label=%s",i, label); sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = prkeys[i].ref; sc_format_path(prkeys[i].path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-postecert.c b/src/libopensc/pkcs15-postecert.c index 8d40e031..9288b511 100644 --- a/src/libopensc/pkcs15-postecert.c +++ b/src/libopensc/pkcs15-postecert.c @@ -112,10 +112,6 @@ static int sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, info.modulus_length = modulus_length; info.usage = usage; info.native = 1; - info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; info.key_reference = ref; if (path) diff --git a/src/libopensc/pkcs15-pteid.c b/src/libopensc/pkcs15-pteid.c index f19ed529..028ef27d 100644 --- a/src/libopensc/pkcs15-pteid.c +++ b/src/libopensc/pkcs15-pteid.c @@ -206,11 +206,6 @@ static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card) prkey_info.id.value[0] = pteid_prkey_ids[i]; prkey_info.usage = pteid_prkey_usage[i]; prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = pteid_prkey_keyref[type][i]; prkey_info.modulus_length = 1024; if (pteid_prkey_paths[type][i] != NULL) diff --git a/src/libopensc/pkcs15-starcert.c b/src/libopensc/pkcs15-starcert.c index f7c9c697..19faefc8 100644 --- a/src/libopensc/pkcs15-starcert.c +++ b/src/libopensc/pkcs15-starcert.c @@ -240,11 +240,6 @@ static int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card) sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c index 024ef843..4c98518e 100644 --- a/src/libopensc/pkcs15-tcos.c +++ b/src/libopensc/pkcs15-tcos.c @@ -112,11 +112,6 @@ static int insert_key( prkey_info.id.len = 1; prkey_info.id.value[0] = id; prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = key_reference; prkey_info.modulus_length = key_length; sc_format_path(path, &prkey_info.path); diff --git a/src/libopensc/pkcs15-westcos.c b/src/libopensc/pkcs15-westcos.c index 66746734..8bd4d645 100644 --- a/src/libopensc/pkcs15-westcos.c +++ b/src/libopensc/pkcs15-westcos.c @@ -216,11 +216,6 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card) SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; prkey_info.native = 1; - /* Add default access_flags, see Issues #335 and #336 */ - prkey_info.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE - | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE - | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE - | SC_PKCS15_PRKEY_ACCESS_LOCAL; prkey_info.key_reference = 1; prkey_info.modulus_length = modulus_length; prkey_info.path = path; From 19bbfc76f5ace2ef17f2cb17f0315889e1607b39 Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Mon, 19 Jan 2015 18:04:12 +0100 Subject: [PATCH 026/306] Added initial support for STARCOS 3.4 (German D-Trust cards). Code inspired by experimental STARCOS 3 driver by Martin Vogt: http://article.gmane.org/gmane.comp.encryption.opensc.devel/9846 Supports `opensc-explorer`, `pkcs15-tool` and `pkcs15-crypt` (signing with PKCS#1 padding). Cards available from `https://www.bundesdruckerei.de/en/768-d-trust-signature-cards`. --- src/libopensc/card-starcos.c | 474 +++++++++++++++++++++++++++++++---- src/libopensc/cards.h | 1 + 2 files changed, 422 insertions(+), 53 deletions(-) diff --git a/src/libopensc/card-starcos.c b/src/libopensc/card-starcos.c index 9d43e51d..475d635d 100644 --- a/src/libopensc/card-starcos.c +++ b/src/libopensc/card-starcos.c @@ -32,6 +32,8 @@ static struct sc_atr_table starcos_atrs[] = { { "3B:B7:94:00:c0:24:31:fe:65:53:50:4b:32:33:90:00:b4", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL }, { "3B:B7:94:00:81:31:fe:65:53:50:4b:32:33:90:00:d1", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL }, { "3b:b7:18:00:c0:3e:31:fe:65:53:50:4b:32:34:90:00:25", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL }, + /* STARCOS 3.4 */ + { "3b:d8:18:ff:81:b1:fe:45:1f:03:80:64:04:1a:b4:03:81:05:61", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_4, 0, NULL }, { NULL, NULL, NULL, 0, 0, NULL } }; @@ -39,7 +41,7 @@ static struct sc_card_operations starcos_ops; static struct sc_card_operations *iso_ops = NULL; static struct sc_card_driver starcos_drv = { - "STARCOS SPK 2.3/2.4", + "STARCOS SPK 2.3/2.4/3.4", "starcos", &starcos_ops, NULL, 0, NULL @@ -70,6 +72,24 @@ typedef struct starcos_ex_data_st { unsigned int fix_digestInfo; } starcos_ex_data; +#define CHECK_NOT_SUPPORTED_V3_4(card) \ + do { \ + if ((card)->type == SC_CARD_TYPE_STARCOS_V3_4) { \ + sc_debug((card)->ctx, SC_LOG_DEBUG_NORMAL, \ + "not supported for STARCOS 3.4 cards"); \ + return SC_ERROR_NOT_SUPPORTED; \ + } \ + } while (0); + +#define CHECK_ONLY_SUPPORTED_V3_4(card) \ + do { \ + if ((card)->type != SC_CARD_TYPE_STARCOS_V3_4) { \ + sc_debug((card)->ctx, SC_LOG_DEBUG_NORMAL, \ + "only supported for STARCOS 3.4 cards"); \ + return SC_ERROR_NOT_SUPPORTED; \ + } \ + } while (0); + /* the starcos part */ static int starcos_match_card(sc_card_t *card) { @@ -103,15 +123,31 @@ static int starcos_init(sc_card_t *card) | SC_ALGORITHM_RSA_HASH_RIPEMD160 | SC_ALGORITHM_RSA_HASH_MD5_SHA1; - _sc_card_add_rsa_alg(card, 512, flags, 0x10001); - _sc_card_add_rsa_alg(card, 768, flags, 0x10001); - _sc_card_add_rsa_alg(card,1024, flags, 0x10001); - card->caps = SC_CARD_CAP_RNG; - /* we need read_binary&friends with max 128 bytes per read */ - card->max_send_size = 128; - card->max_recv_size = 128; + if (card->type == SC_CARD_TYPE_STARCOS_V3_4) { + card->name = "STARCOS SPK 3.4"; + flags |= SC_CARD_FLAG_RNG + | SC_ALGORITHM_RSA_HASH_SHA224 + | SC_ALGORITHM_RSA_HASH_SHA256 + | SC_ALGORITHM_RSA_HASH_SHA384 + | SC_ALGORITHM_RSA_HASH_SHA512; + + _sc_card_add_rsa_alg(card, 512, flags, 0x10001); + _sc_card_add_rsa_alg(card, 768, flags, 0x10001); + _sc_card_add_rsa_alg(card,1024, flags, 0x10001); + _sc_card_add_rsa_alg(card,1728, flags, 0x10001); + _sc_card_add_rsa_alg(card,1976, flags, 0x10001); + _sc_card_add_rsa_alg(card,2048, flags, 0x10001); + } else { + _sc_card_add_rsa_alg(card, 512, flags, 0x10001); + _sc_card_add_rsa_alg(card, 768, flags, 0x10001); + _sc_card_add_rsa_alg(card,1024, flags, 0x10001); + + /* we need read_binary&friends with max 128 bytes per read */ + card->max_send_size = 128; + card->max_recv_size = 128; + } return 0; } @@ -215,6 +251,182 @@ static int process_fci(sc_context_t *ctx, sc_file_t *file, return SC_SUCCESS; } +static int process_fci_v3_4(sc_context_t *ctx, sc_file_t *file, + const u8 *buf, size_t buflen) +{ + size_t taglen, len = buflen; + const u8 *tag = NULL, *p; + + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "processing %d FCI bytes\n", buflen); + + if (buflen < 2) + return SC_ERROR_INTERNAL; + if (buf[0] != 0x6f) + return SC_ERROR_INVALID_DATA; + len = (size_t)buf[1]; + if (buflen - 2 < len) + return SC_ERROR_INVALID_DATA; + + /* defaults */ + file->type = SC_FILE_TYPE_WORKING_EF; + if (len == 0) { + SC_FUNC_RETURN(ctx, 2, SC_SUCCESS); + } + + p = buf + 2; + file->ef_structure = SC_FILE_TYPE_DF; + file->shareable = 1; + tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen); + if (tag != NULL && taglen > 0 && taglen <= 16) { + memcpy(file->name, tag, taglen); + file->namelen = taglen; + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "filename %s", + sc_dump_hex(file->name, file->namelen)); + } + return SC_SUCCESS; +} + +static int process_fcp_v3_4(sc_context_t *ctx, sc_file_t *file, + const u8 *buf, size_t buflen) +{ + size_t taglen, len = buflen; + const u8 *tag = NULL, *p; + + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "processing %d FCP bytes\n", buflen); + + if (buflen < 2) + return SC_ERROR_INTERNAL; + if (buf[0] != 0x62) + return SC_ERROR_INVALID_DATA; + len = (size_t)buf[1]; + if (buflen - 2 < len) + return SC_ERROR_INVALID_DATA; + p = buf + 2; + + tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen); + if (tag != NULL && taglen >= 2) { + int bytes = (tag[0] << 8) + tag[1]; + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, + " bytes in file: %d\n", bytes); + file->size = bytes; + } + + tag = sc_asn1_find_tag(ctx, p, len, 0xc5, &taglen); + if (tag != NULL && taglen >= 2) { + int bytes = (tag[0] << 8) + tag[1]; + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, + " bytes in file 2: %d\n", bytes); + file->size = bytes; + } + + tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen); + if (tag != NULL) { + const char *type = "unknown"; + const char *structure = "unknown"; + + if (taglen >= 1) { + unsigned char byte = tag[0]; + if (byte & 0x40) { + file->shareable = 1; + } + if (byte == 0x38) { + type = "DF"; + file->type = SC_FILE_TYPE_DF; + file->shareable = 1; + } + switch (byte & 7) { + case 1: + /* transparent EF */ + type = "working EF"; + structure = "transparent"; + file->type = SC_FILE_TYPE_WORKING_EF; + file->ef_structure = SC_FILE_EF_TRANSPARENT; + break; + case 2: + /* linear fixed EF */ + type = "working EF"; + structure = "linear fixed"; + file->type = SC_FILE_TYPE_WORKING_EF; + file->ef_structure = SC_FILE_EF_LINEAR_FIXED; + break; + case 4: + /* linear variable EF */ + type = "working EF"; + structure = "linear variable"; + file->type = SC_FILE_TYPE_WORKING_EF; + file->ef_structure = SC_FILE_EF_LINEAR_VARIABLE; + break; + case 6: + /* cyclic EF */ + type = "working EF"; + structure = "cyclic"; + file->type = SC_FILE_TYPE_WORKING_EF; + file->ef_structure = SC_FILE_EF_CYCLIC; + break; + default: + /* use defaults from above */ + break; + } + } + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, + " type: %s\n", type); + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, + " EF structure: %s\n", structure); + if (taglen >= 2) { + if (tag[1] != 0x41 || taglen != 5) { + SC_FUNC_RETURN(ctx, 2,SC_ERROR_INVALID_DATA); + } + /* formatted EF */ + file->record_length = (tag[2] << 8) + tag[3]; + file->record_count = tag[4]; + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, + " rec_len: %d rec_cnt: %d\n\n", + file->record_length, file->record_count); + } + } + + tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen); + if (tag != NULL && taglen >= 2) { + file->id = (tag[0] << 8) | tag[1]; + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " file identifier: 0x%02X%02X\n", + tag[0], tag[1]); + } + + tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen); + if (tag != NULL && taglen > 0 && taglen <= 16) { + memcpy(file->name, tag, taglen); + file->namelen = taglen; + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " filename %s", + sc_dump_hex(file->name, file->namelen)); + } + + tag = sc_asn1_find_tag(ctx, p, len, 0x8a, &taglen); + if (tag != NULL && taglen == 1) { + char* status = "unknown"; + switch (tag[0]) { + case 1: + status = "creation"; + file->status = SC_FILE_STATUS_CREATION; + break; + case 5: + status = "operational active"; + file->status = SC_FILE_STATUS_ACTIVATED; + break; + case 12: + case 13: + status = "creation"; + file->status = SC_FILE_STATUS_INVALIDATED; + break; + default: + break; + } + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " file status: %s\n", status); + } + + file->magic = SC_FILE_MAGIC; + return SC_SUCCESS; +} + static int starcos_select_aid(sc_card_t *card, u8 aid[16], size_t len, sc_file_t **file_out) @@ -262,12 +474,14 @@ static int starcos_select_aid(sc_card_t *card, static int starcos_select_fid(sc_card_t *card, unsigned int id_hi, unsigned int id_lo, - sc_file_t **file_out) + sc_file_t **file_out, int is_file) { sc_apdu_t apdu; u8 data[] = {id_hi & 0xff, id_lo & 0xff}; u8 resp[SC_MAX_APDU_BUFFER_SIZE]; int bIsDF = 0, r; + int isFCP = 0; + int isMF = 0; /* request FCI to distinguish between EFs and DFs */ sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x00); @@ -279,6 +493,22 @@ static int starcos_select_fid(sc_card_t *card, apdu.data = (u8*)data; apdu.datalen = 2; + if (card->type == SC_CARD_TYPE_STARCOS_V3_4) { + if (id_hi == 0x3f && id_lo == 0x0) { + apdu.p1 = 0x0; + apdu.p2 = 0x0; + isMF = 1; + } else if (file_out || is_file) { + // last component (i.e. file or path) + apdu.p1 = 0x2; + apdu.p2 = 0x4; + } else { + // path component + apdu.p1 = 0x1; + apdu.p2 = 0x0; + } + } + r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); @@ -291,7 +521,17 @@ static int starcos_select_fid(sc_card_t *card, apdu.le = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU re-transmit failed"); - } else if (apdu.sw1 == 0x61 || (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)) { + } else if (card->type == SC_CARD_TYPE_STARCOS_V3_4 && apdu.p2 == 0x4 && apdu.sw1 == 0x6a && apdu.sw2 == 0x82) { + /* not a file, could be a path */ + bIsDF = 1; + apdu.p1 = 0x1; + apdu.p2 = 0x0; + apdu.resplen = sizeof(resp); + apdu.le = 256; + apdu.lc = 2; + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU re-transmit failed"); + } else if (apdu.sw1 == 0x61 || (apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && !isMF)) { /* SELECT returned some data (possible FCI) => * try a READ BINARY to see if a EF is selected */ sc_apdu_t apdu2; @@ -303,16 +543,19 @@ static int starcos_select_fid(sc_card_t *card, apdu2.lc = 0; r = sc_transmit_apdu(card, &apdu2); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); - if (apdu2.sw1 == 0x69 && apdu2.sw2 == 0x86) + if (apdu2.sw1 == 0x69 && apdu2.sw2 == 0x86) { /* no current EF is selected => we have a DF */ bIsDF = 1; + } else { + isFCP = 1; + } } if (apdu.sw1 != 0x61 && (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); /* update cache */ - if (bIsDF) { + if (bIsDF || isMF) { card->cache.current_path.type = SC_PATH_TYPE_PATH; card->cache.current_path.value[0] = 0x3f; card->cache.current_path.value[1] = 0x00; @@ -342,8 +585,18 @@ static int starcos_select_fid(sc_card_t *card, *file_out = file; } else { /* ok, assume we have a EF */ - r = process_fci(card->ctx, file, apdu.resp, - apdu.resplen); + if (card->type == SC_CARD_TYPE_STARCOS_V3_4) { + if (isFCP) { + r = process_fcp_v3_4(card->ctx, file, apdu.resp, + apdu.resplen); + } else { + r = process_fci_v3_4(card->ctx, file, apdu.resp, + apdu.resplen); + } + } else { + r = process_fci(card->ctx, file, apdu.resp, + apdu.resplen); + } if (r != SC_SUCCESS) { sc_file_free(file); return r; @@ -385,7 +638,7 @@ static int starcos_select_file(sc_card_t *card, /* Select with 2byte File-ID */ if (pathlen != 2) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS); - return starcos_select_fid(card, path[0], path[1], file_out); + return starcos_select_fid(card, path[0], path[1], file_out, 1); } else if (in_path->type == SC_PATH_TYPE_DF_NAME) { /* SELECT DF with AID */ @@ -418,15 +671,18 @@ static int starcos_select_file(sc_card_t *card, if (pathlen == 6 && ( path[0] != 0x3f || path[1] != 0x00 )) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS); - /* unify path (the first FID should be MF) */ - if (path[0] != 0x3f || path[1] != 0x00) - { - n_pathbuf[0] = 0x3f; - n_pathbuf[1] = 0x00; - for (i=0; i< pathlen; i++) - n_pathbuf[i+2] = pathbuf[i]; - path = n_pathbuf; - pathlen += 2; + if (card->type != SC_CARD_TYPE_STARCOS_V3_4 || + (pathlen == 0 && card->cache.current_path.type != SC_PATH_TYPE_DF_NAME)) { + /* unify path (the first FID should be MF) */ + if (path[0] != 0x3f || path[1] != 0x00) + { + n_pathbuf[0] = 0x3f; + n_pathbuf[1] = 0x00; + for (i=0; i< pathlen; i++) + n_pathbuf[i+2] = pathbuf[i]; + path = n_pathbuf; + pathlen += 2; + } } /* check current working directory */ @@ -440,20 +696,28 @@ static int starcos_select_file(sc_card_t *card, if (card->cache.current_path.value[i] == path[i] && card->cache.current_path.value[i+1] == path[i+1] ) bMatch += 2; + + if (card->type == SC_CARD_TYPE_STARCOS_V3_4 && + bMatch > 0 && + (size_t) bMatch < card->cache.current_path.len) { + /* we're in the wrong folder, start traversing from root */ + bMatch = 0; + card->cache.current_path.len = 0; + } } if ( card->cache.valid && bMatch >= 0 ) { if ( pathlen - bMatch == 2 ) /* we are in the rigth directory */ - return starcos_select_fid(card, path[bMatch], path[bMatch+1], file_out); + return starcos_select_fid(card, path[bMatch], path[bMatch+1], file_out, 1); else if ( pathlen - bMatch > 2 ) { /* two more steps to go */ sc_path_t new_path; /* first step: change directory */ - r = starcos_select_fid(card, path[bMatch], path[bMatch+1], NULL); + r = starcos_select_fid(card, path[bMatch], path[bMatch+1], NULL, 0); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "SELECT FILE (DF-ID) failed"); memset(&new_path, 0, sizeof(sc_path_t)); @@ -493,10 +757,10 @@ static int starcos_select_file(sc_card_t *card, /* no usable cache */ for ( i=0; ictx, SC_LOG_DEBUG_NORMAL, r, "SELECT FILE (DF-ID) failed"); } - return starcos_select_fid(card, path[pathlen-2], path[pathlen-1], file_out); + return starcos_select_fid(card, path[pathlen-2], path[pathlen-1], file_out, 1); } } else @@ -681,6 +945,8 @@ static int starcos_create_mf(sc_card_t *card, sc_starcos_create_data *data) sc_apdu_t apdu; sc_context_t *ctx = card->ctx; + CHECK_NOT_SUPPORTED_V3_4(card); + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "creating MF \n"); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00); apdu.cla |= 0x80; @@ -710,6 +976,8 @@ static int starcos_create_df(sc_card_t *card, sc_starcos_create_data *data) sc_apdu_t apdu; sc_context_t *ctx = card->ctx; + CHECK_NOT_SUPPORTED_V3_4(card); + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "creating DF\n"); /* first step: REGISTER DF */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "calling REGISTER DF\n"); @@ -753,6 +1021,8 @@ static int starcos_create_ef(sc_card_t *card, sc_starcos_create_data *data) sc_apdu_t apdu; sc_context_t *ctx = card->ctx; + CHECK_NOT_SUPPORTED_V3_4(card); + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "creating EF\n"); sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x03,0x00); @@ -784,6 +1054,8 @@ static int starcos_create_end(sc_card_t *card, sc_file_t *file) if (file->type != SC_FILE_TYPE_DF) return SC_ERROR_INVALID_ARGUMENTS; + CHECK_NOT_SUPPORTED_V3_4(card); + fid[0] = (file->id >> 8) & 0xff; fid[1] = file->id & 0xff; sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT, 0xE0, 0x02, 0x00); @@ -809,6 +1081,8 @@ static int starcos_create_file(sc_card_t *card, sc_file_t *file) int r; sc_starcos_create_data data; + CHECK_NOT_SUPPORTED_V3_4(card); + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); if (file->type == SC_FILE_TYPE_DF) { @@ -886,6 +1160,8 @@ static int starcos_write_key(sc_card_t *card, sc_starcos_wkey_data *data) size_t len = sizeof(sbuf), tlen, offset = 0; sc_apdu_t apdu; + CHECK_NOT_SUPPORTED_V3_4(card); + if (data->mode == 0) { /* mode == 0 => install */ /* install key header */ sbuf[0] = 0xc1; /* key header tag */ @@ -955,6 +1231,9 @@ static int starcos_gen_key(sc_card_t *card, sc_starcos_gen_key_data *data) sc_apdu_t apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[2], *p, *q; + + CHECK_NOT_SUPPORTED_V3_4(card); + /* generate key */ sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, data->key_id); @@ -1021,6 +1300,46 @@ static int starcos_set_security_env(sc_card_t *card, p = sbuf; + if (card->type == SC_CARD_TYPE_STARCOS_V3_4) { + if (operation != SC_SEC_OPERATION_SIGN) { + /* we only support signatures for now */ + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, + "not supported for STARCOS 3.4 cards"); + return SC_ERROR_NOT_SUPPORTED; \ + } + + if (!(env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) || + !(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) || env->key_ref_len != 1) { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS); + } + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB6); + /* don't know what these mean but doesn't matter as card seems to take + * algorithm / cipher from PKCS#1 padding prefix */ + *p++ = 0x84; + *p++ = 0x01; + *p++ = 0x84; + + /* algorithm / cipher selector? */ + *p++ = 0x89; + *p++ = 0x02; + *p++ = 0x13; + *p++ = 0x23; + + apdu.data = sbuf; + apdu.datalen = p - sbuf; + apdu.lc = p - sbuf; + apdu.le = 0; + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); + + ex_data->fix_digestInfo = env->algorithm_flags; + ex_data->sec_ops = SC_SEC_OPERATION_SIGN; + return SC_SUCCESS; + } + /* copy key reference, if present */ if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) @@ -1148,33 +1467,65 @@ static int starcos_compute_signature(sc_card_t *card, if (ex_data->sec_ops == SC_SEC_OPERATION_SIGN) { /* compute signature with the COMPUTE SIGNATURE command */ - /* set the hash value */ - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, - 0x90, 0x81); - apdu.resp = rbuf; - apdu.resplen = sizeof(rbuf); - apdu.le = 0; - memcpy(sbuf, data, datalen); - apdu.data = sbuf; - apdu.lc = datalen; - apdu.datalen = datalen; - r = sc_transmit_apdu(card, &apdu); - SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); - if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, - sc_check_sw(card, apdu.sw1, apdu.sw2)); + if (card->type == SC_CARD_TYPE_STARCOS_V3_4) { + size_t tmp_len; - /* call COMPUTE SIGNATURE */ - sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A, - 0x9E, 0x9A); - apdu.resp = rbuf; - apdu.resplen = sizeof(rbuf); - apdu.le = 256; + sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, + 0x9E, 0x9A); + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + apdu.le = 0; + if (ex_data->fix_digestInfo) { + // need to pad data + unsigned int flags = ex_data->fix_digestInfo & SC_ALGORITHM_RSA_HASHES; + if (flags == 0x00) { + flags = SC_ALGORITHM_RSA_HASH_NONE; + } + tmp_len = sizeof(sbuf); + r = sc_pkcs1_encode(card->ctx, flags, data, datalen, sbuf, &tmp_len, sizeof(sbuf)); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_pkcs1_encode failed"); + } else { + memcpy(sbuf, data, datalen); + tmp_len = datalen; + } - apdu.lc = 0; - apdu.datalen = 0; - r = sc_transmit_apdu(card, &apdu); - SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + apdu.data = sbuf; + apdu.datalen = tmp_len; + apdu.lc = tmp_len; + apdu.resp = out; + apdu.resplen = outlen; + apdu.le = 0; + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + } else { + /* set the hash value */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, + 0x90, 0x81); + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + apdu.le = 0; + memcpy(sbuf, data, datalen); + apdu.data = sbuf; + apdu.lc = datalen; + apdu.datalen = datalen; + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, + sc_check_sw(card, apdu.sw1, apdu.sw2)); + + /* call COMPUTE SIGNATURE */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A, + 0x9E, 0x9A); + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + apdu.le = 256; + + apdu.lc = 0; + apdu.datalen = 0; + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + } if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { size_t len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); @@ -1182,6 +1533,7 @@ static int starcos_compute_signature(sc_card_t *card, } } else if (ex_data->sec_ops == SC_SEC_OPERATION_AUTHENTICATE) { size_t tmp_len; + CHECK_NOT_SUPPORTED_V3_4(card); /* call INTERNAL AUTHENTICATE */ sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x10, 0x00); /* fix/create DigestInfo structure (if necessary) */ @@ -1265,6 +1617,7 @@ static int starcos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) memcpy(serial, &card->serialnr, sizeof(*serial)); return SC_SUCCESS; } + CHECK_NOT_SUPPORTED_V3_4(card); /* get serial number via GET CARD DATA */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xf6, 0x00, 0x00); apdu.cla |= 0x80; @@ -1341,6 +1694,20 @@ static int starcos_logout(sc_card_t *card) return sc_check_sw(card, apdu.sw1, apdu.sw2); } +static int starcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, + int *tries_left) +{ + int ret; + + CHECK_ONLY_SUPPORTED_V3_4(card); + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL); + data->flags |= SC_PIN_CMD_NEED_PADDING; + data->pin1.encoding = SC_PIN_ENCODING_GLP; + ret = iso_ops->pin_cmd(card, data, tries_left); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, ret); +} + static struct sc_card_driver * sc_get_driver(void) { struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); @@ -1359,6 +1726,7 @@ static struct sc_card_driver * sc_get_driver(void) starcos_ops.compute_signature = starcos_compute_signature; starcos_ops.card_ctl = starcos_card_ctl; starcos_ops.logout = starcos_logout; + starcos_ops.pin_cmd = starcos_pin_cmd; return &starcos_drv; } diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index 7be66671..122cd3c3 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -94,6 +94,7 @@ enum { /* starcos driver */ SC_CARD_TYPE_STARCOS_BASE = 7000, SC_CARD_TYPE_STARCOS_GENERIC, + SC_CARD_TYPE_STARCOS_V3_4, /* tcos driver */ SC_CARD_TYPE_TCOS_BASE = 8000, From 28ea6bc607dafa1f502d661d1ee6a855e678e7cc Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 20 Jan 2015 00:53:51 +0100 Subject: [PATCH 027/306] added DEFAULT_PKCS11_PROVIDER to winconfig.h.in --- win32/winconfig.h.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/win32/winconfig.h.in b/win32/winconfig.h.in index 57a313e0..c8e88770 100644 --- a/win32/winconfig.h.in +++ b/win32/winconfig.h.in @@ -95,4 +95,8 @@ #define OPENSC_FEATURES "N/A" #endif +#ifndef DEFAULT_PKCS11_PROVIDER +#define DEFAULT_PKCS11_PROVIDER "opensc-pkcs11.dll" +#endif + #endif From 87cc05c03fefdb0e00fe53546b3286ed048c60de Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Tue, 20 Jan 2015 16:49:11 +0100 Subject: [PATCH 028/306] Receive signature to temporary buffer, will be copied to output buffer later. --- src/libopensc/card-starcos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-starcos.c b/src/libopensc/card-starcos.c index 475d635d..0ae93622 100644 --- a/src/libopensc/card-starcos.c +++ b/src/libopensc/card-starcos.c @@ -1492,8 +1492,8 @@ static int starcos_compute_signature(sc_card_t *card, apdu.data = sbuf; apdu.datalen = tmp_len; apdu.lc = tmp_len; - apdu.resp = out; - apdu.resplen = outlen; + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); apdu.le = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); From 9543cdb121924b331bcf6cbfbccf9f3928472fa9 Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Tue, 20 Jan 2015 16:52:30 +0100 Subject: [PATCH 029/306] Handle case where input data is already padded. --- src/libopensc/card-starcos.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-starcos.c b/src/libopensc/card-starcos.c index 0ae93622..da283885 100644 --- a/src/libopensc/card-starcos.c +++ b/src/libopensc/card-starcos.c @@ -1335,7 +1335,12 @@ static int starcos_set_security_env(sc_card_t *card, if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); - ex_data->fix_digestInfo = env->algorithm_flags; + if (env->algorithm_flags == SC_ALGORITHM_RSA_PAD_PKCS1) { + // input data will be already padded + ex_data->fix_digestInfo = 0; + } else { + ex_data->fix_digestInfo = env->algorithm_flags; + } ex_data->sec_ops = SC_SEC_OPERATION_SIGN; return SC_SUCCESS; } From c3a0bbc71583e80f9e794aca0896040c693db53e Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Tue, 20 Jan 2015 23:14:36 -0800 Subject: [PATCH 030/306] Update email and year --- src/pkcs11/pkcs11-display.c | 2 +- src/pkcs11/pkcs11-display.h | 2 +- src/pkcs11/pkcs11-spy.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pkcs11/pkcs11-display.c b/src/pkcs11/pkcs11-display.c index 10403bdf..590b1493 100644 --- a/src/pkcs11/pkcs11-display.c +++ b/src/pkcs11/pkcs11-display.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 Mathias Brossard + * Copyright (C) 2015 Mathias Brossard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/pkcs11/pkcs11-display.h b/src/pkcs11/pkcs11-display.h index 7e1ae8e9..0f7bc5fb 100644 --- a/src/pkcs11/pkcs11-display.h +++ b/src/pkcs11/pkcs11-display.h @@ -2,7 +2,7 @@ #define PKCS11_DISPLAY_H /* - * Copyright (C) 2003 Mathias Brossard + * Copyright (C) 2015 Mathias Brossard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/pkcs11/pkcs11-spy.c b/src/pkcs11/pkcs11-spy.c index 52318e48..1dab64da 100644 --- a/src/pkcs11/pkcs11-spy.c +++ b/src/pkcs11/pkcs11-spy.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 Mathias Brossard + * Copyright (C) 2015 Mathias Brossard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public From 17c1cffb3d90739238dd3ffc3c73af2a1dc87bb3 Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Tue, 20 Jan 2015 22:58:13 -0800 Subject: [PATCH 031/306] Fix typo on CKF_EC_UNCOMPRESS --- src/pkcs11/framework-pkcs15.c | 2 +- src/pkcs11/pkcs11.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 15add105..c30167e5 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -4541,7 +4541,7 @@ static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, if (ext_flags & SC_ALGORITHM_EXT_EC_NAMEDCURVE) ec_flags |= CKF_EC_NAMEDCURVE; if (ext_flags & SC_ALGORITHM_EXT_EC_UNCOMPRESES) - ec_flags |= CKF_EC_UNCOMPRESES; + ec_flags |= CKF_EC_UNCOMPRESS; if (ext_flags & SC_ALGORITHM_EXT_EC_COMPRESS) ec_flags |= CKF_EC_COMPRESS; diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index 1a51a31e..fe3d6b10 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -715,7 +715,7 @@ struct ck_mechanism_info #define CKF_EC_F_2M (1UL << 21) #define CKF_EC_ECPARAMETERS (1UL << 22) #define CKF_EC_NAMEDCURVE (1UL << 23) -#define CKF_EC_UNCOMPRESES (1UL << 24) +#define CKF_EC_UNCOMPRESS (1UL << 24) #define CKF_EC_COMPRESS (1UL << 25) /* Flags for C_WaitForSlotEvent. */ From 3dadd3fba170db7dcfac7b80cdfa063520fd9da9 Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Tue, 20 Jan 2015 23:00:28 -0800 Subject: [PATCH 032/306] Add some missing PKCS#11 values --- src/pkcs11/pkcs11.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index fe3d6b10..9967025b 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -355,6 +355,8 @@ typedef unsigned long ck_key_type_t; #define CKK_BLOWFISH (0x20UL) #define CKK_TWOFISH (0x21UL) #define CKK_GOSTR3410 (0x30UL) +#define CKK_GOSTR3411 (0x31UL) +#define CKK_GOST28147 (0x32UL) #define CKK_VENDOR_DEFINED (1UL << 31) @@ -671,10 +673,27 @@ typedef unsigned long ck_mechanism_type_t; #define CKM_AES_MAC (0x1083UL) #define CKM_AES_MAC_GENERAL (0x1084UL) #define CKM_AES_CBC_PAD (0x1085UL) +#define CKM_AES_CTR (0x1086UL) +#define CKM_AES_GCM (0x1087UL) +#define CKM_AES_CCM (0x1088UL) +#define CKM_AES_CTS (0x1089UL) +#define CKM_BLOWFISH_KEY_GEN (0x1090UL) +#define CKM_BLOWFISH_CBC (0x1091UL) +#define CKM_TWOFISH_KEY_GEN (0x1092UL) +#define CKM_TWOFISH_CBC (0x1093UL) #define CKM_GOSTR3410_KEY_PAIR_GEN (0x1200UL) #define CKM_GOSTR3410 (0x1201UL) #define CKM_GOSTR3410_WITH_GOSTR3411 (0x1202UL) +#define CKM_GOSTR3410_KEY_WRAP (0x1203UL) +#define CKM_GOSTR3410_DERIVE (0x1204UL) #define CKM_GOSTR3411 (0x1210UL) +#define CKM_GOSTR3411_HMAC (0x1211UL) +#define CKM_GOST28147_KEY_GEN (0x1220UL) +#define CKM_GOST28147_ECB (0x1221UL) +#define CKM_GOST28147 (0x1222UL) +#define CKM_GOST28147_MAC (0x1223UL) +#define CKM_GOST28147_KEY_WRAP (0x1224UL) + #define CKM_DSA_PARAMETER_GEN (0x2000UL) #define CKM_DH_PKCS_PARAMETER_GEN (0x2001UL) #define CKM_X9_42_DH_PARAMETER_GEN (0x2002UL) From 7a455f64c79018e3bd6234ee19080047f3a11c81 Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Tue, 20 Jan 2015 23:01:30 -0800 Subject: [PATCH 033/306] Support of additional type, mechanisms and attributes --- src/pkcs11/pkcs11-display.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/pkcs11-display.c b/src/pkcs11/pkcs11-display.c index 590b1493..57b1de24 100644 --- a/src/pkcs11/pkcs11-display.c +++ b/src/pkcs11/pkcs11-display.c @@ -275,7 +275,12 @@ static enum_specs ck_key_s[] = { { CKK_BATON , "CKK_BATON " }, { CKK_JUNIPER , "CKK_JUNIPER " }, { CKK_CDMF , "CKK_CDMF " }, - { CKK_AES , "CKK_AES " } + { CKK_AES , "CKK_AES " }, + { CKK_BLOWFISH , "CKK_BLOWFISH " }, + { CKK_TWOFISH , "CKK_TWOFISH " }, + { CKK_GOSTR3410 , "CKK_GOSTR3410 " }, + { CKK_GOSTR3411 , "CKK_GOSTR3411 " }, + { CKK_GOST28147 , "CKK_GOST28147 " } }; static enum_specs ck_mec_s[] = { @@ -479,6 +484,26 @@ static enum_specs ck_mec_s[] = { { CKM_AES_MAC , "CKM_AES_MAC " }, { CKM_AES_MAC_GENERAL , "CKM_AES_MAC_GENERAL " }, { CKM_AES_CBC_PAD , "CKM_AES_CBC_PAD " }, + { CKM_AES_CTR , "CKM_AES_CTR " }, + { CKM_AES_GCM , "CKM_AES_GCM " }, + { CKM_AES_CCM , "CKM_AES_CCM " }, + { CKM_AES_CTS , "CKM_AES_CTS " }, + { CKM_BLOWFISH_KEY_GEN , "CKM_BLOWFISH_KEY_GEN " }, + { CKM_BLOWFISH_CBC , "CKM_BLOWFISH_CBC " }, + { CKM_TWOFISH_KEY_GEN , "CKM_TWOFISH_KEY_GEN " }, + { CKM_TWOFISH_CBC , "CKM_TWOFISH_CBC " }, + { CKM_GOSTR3410_KEY_PAIR_GEN , "CKM_GOSTR3410_KEY_PAIR_GEN " }, + { CKM_GOSTR3410 , "CKM_GOSTR3410 " }, + { CKM_GOSTR3410_WITH_GOSTR3411 , "CKM_GOSTR3410_WITH_GOSTR3411 " }, + { CKM_GOSTR3410_KEY_WRAP , "CKM_GOSTR3410_KEY_WRAP " }, + { CKM_GOSTR3410_DERIVE , "CKM_GOSTR3410_DERIVE " }, + { CKM_GOSTR3411 , "CKM_GOSTR3411 " }, + { CKM_GOSTR3411_HMAC , "CKM_GOSTR3411_HMAC " }, + { CKM_GOST28147_KEY_GEN , "CKM_GOST28147_KEY_GEN " }, + { CKM_GOST28147_ECB , "CKM_GOST28147_ECB " }, + { CKM_GOST28147 , "CKM_GOST28147 " }, + { CKM_GOST28147_MAC , "CKM_GOST28147_MAC " }, + { CKM_GOST28147_KEY_WRAP , "CKM_GOST28147_KEY_WRAP " }, { CKM_DSA_PARAMETER_GEN , "CKM_DSA_PARAMETER_GEN " }, { CKM_DH_PKCS_PARAMETER_GEN , "CKM_DH_PKCS_PARAMETER_GEN " }, { CKM_X9_42_DH_PARAMETER_GEN , "CKM_X9_42_DH_PARAMETER_GEN " }, @@ -682,6 +707,9 @@ type_spec ck_attribute_specs[] = { { CKA_WRAP_WITH_TRUSTED , "CKA_WRAP_WITH_TRUSTED ", print_generic, NULL }, { CKA_WRAP_TEMPLATE , "CKA_WRAP_TEMPLATE ", print_generic, NULL }, { CKA_UNWRAP_TEMPLATE , "CKA_UNWRAP_TEMPLATE ", print_generic, NULL }, + { CKA_GOSTR3410_PARAMS , "CKA_GOSTR3410_PARAMS ", print_generic, NULL }, + { CKA_GOSTR3411_PARAMS , "CKA_GOSTR3411_PARAMS ", print_generic, NULL }, + { CKA_GOST28147_PARAMS , "CKA_GOST28147_PARAMS ", print_generic, NULL }, { CKA_HW_FEATURE_TYPE , "CKA_HW_FEATURE_TYPE ", print_generic, NULL }, { CKA_RESET_ON_INIT , "CKA_RESET_ON_INIT ", print_generic, NULL }, { CKA_HAS_RESET , "CKA_HAS_RESET ", print_generic, NULL }, From 762d466b237409b23ab597df4a380b41e755b638 Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Tue, 20 Jan 2015 23:02:35 -0800 Subject: [PATCH 034/306] Add display of Elliptic Curve flags --- src/pkcs11/pkcs11-display.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pkcs11/pkcs11-display.c b/src/pkcs11/pkcs11-display.c index 57b1de24..652c6f63 100644 --- a/src/pkcs11/pkcs11-display.c +++ b/src/pkcs11/pkcs11-display.c @@ -919,7 +919,9 @@ print_mech_info(FILE *f, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR minfo) const char *name = lookup_enum(MEC_T, type); CK_ULONG known_flags = CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_DIGEST | CKF_SIGN | CKF_SIGN_RECOVER | CKF_VERIFY | CKF_VERIFY_RECOVER | - CKF_GENERATE | CKF_GENERATE_KEY_PAIR | CKF_WRAP | CKF_UNWRAP | CKF_DERIVE; + CKF_GENERATE | CKF_GENERATE_KEY_PAIR | CKF_WRAP | CKF_UNWRAP | + CKF_DERIVE | CKF_EC_F_P | CKF_EC_F_2M |CKF_EC_ECPARAMETERS | + CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS | CKF_EC_COMPRESS; if (name) fprintf(f, "%s : ", name); @@ -929,7 +931,7 @@ print_mech_info(FILE *f, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR minfo) fprintf(f, "min:%lu max:%lu flags:0x%lX ", (unsigned long) minfo->ulMinKeySize, (unsigned long) minfo->ulMaxKeySize, minfo->flags); - fprintf(f, "( %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n", + fprintf(f, "( %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n", (minfo->flags & CKF_HW) ? "Hardware " : "", (minfo->flags & CKF_ENCRYPT) ? "Encrypt " : "", (minfo->flags & CKF_DECRYPT) ? "Decrypt " : "", @@ -943,6 +945,12 @@ print_mech_info(FILE *f, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR minfo) (minfo->flags & CKF_WRAP) ? "Wrap " : "", (minfo->flags & CKF_UNWRAP) ? "Unwrap " : "", (minfo->flags & CKF_DERIVE) ? "Derive " : "", + (minfo->flags & CKF_EC_F_P) ? "F(P) " : "", + (minfo->flags & CKF_EC_F_2M) ? "F(2^M) " : "", + (minfo->flags & CKF_EC_ECPARAMETERS) ? "EcParams " : "", + (minfo->flags & CKF_EC_NAMEDCURVE) ? "NamedCurve " : "", + (minfo->flags & CKF_EC_UNCOMPRESS) ? "Uncompress " : "", + (minfo->flags & CKF_EC_COMPRESS) ? "Compress " : "", (minfo->flags & ~known_flags) ? "Unknown " : ""); } From 7a34c204c1904b789a1842003071b4da3d7c0932 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 22 Jan 2015 20:29:33 +0100 Subject: [PATCH 035/306] fixed dereference before null check silence warnings reported by coverity-scan --- src/common/compat_getopt_main.c | 2 +- src/libopensc/card-authentic.c | 2 +- src/libopensc/card-iasecc.c | 18 +++++++---- src/libopensc/card-oberthur.c | 7 +++-- src/libopensc/card-westcos.c | 17 ++++++----- src/libopensc/card.c | 11 ++++--- src/libopensc/cwa14890.c | 8 ++--- src/libopensc/sc.c | 21 ++++++------- src/pkcs11/framework-pkcs15.c | 10 ++++--- src/pkcs11/pkcs11-global.c | 2 +- src/pkcs15init/pkcs15-entersafe.c | 7 ++--- src/pkcs15init/pkcs15-epass2003.c | 3 +- src/pkcs15init/pkcs15-gpk.c | 3 +- src/pkcs15init/pkcs15-jcop.c | 13 ++++---- src/pkcs15init/pkcs15-lib.c | 45 ++++++++++++++-------------- src/pkcs15init/pkcs15-myeid.c | 5 ++-- src/pkcs15init/pkcs15-oberthur-awp.c | 11 +++---- src/pkcs15init/pkcs15-oberthur.c | 6 ++-- src/pkcs15init/pkcs15-setcos.c | 3 +- src/pkcs15init/profile.c | 2 +- src/scconf/parse.c | 37 +++++++++++++---------- src/scconf/sclex.c | 6 ++-- src/tests/base64.c | 3 +- src/tools/dnie-tool.c | 2 +- src/tools/piv-tool.c | 2 +- src/tools/pkcs15-init.c | 3 +- src/tools/pkcs15-tool.c | 26 ++++++++-------- src/tools/westcos-tool.c | 10 +++---- 28 files changed, 150 insertions(+), 135 deletions(-) diff --git a/src/common/compat_getopt_main.c b/src/common/compat_getopt_main.c index b5215118..827ba019 100644 --- a/src/common/compat_getopt_main.c +++ b/src/common/compat_getopt_main.c @@ -234,7 +234,7 @@ main(int argc, char * argv[]) case 'o': /* -output=FILE */ outfilename = optarg; /* we allow "-" as a synonym for stdout here */ - if (! strcmp(optarg, "-")) + if (optarg && !strcmp(optarg, "-")) { outfilename = 0; } diff --git a/src/libopensc/card-authentic.c b/src/libopensc/card-authentic.c index 744c534b..737574cd 100644 --- a/src/libopensc/card-authentic.c +++ b/src/libopensc/card-authentic.c @@ -650,7 +650,7 @@ authentic_reduce_path(struct sc_card *card, struct sc_path *path) LOG_FUNC_CALLED(ctx); - if (path->len <= 2 || path->type == SC_PATH_TYPE_DF_NAME || !path) + if (!path || path->len <= 2 || path->type == SC_PATH_TYPE_DF_NAME) LOG_FUNC_RETURN(ctx, SC_SUCCESS); if (!card->cache.valid || !card->cache.current_df) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 6e26c87d..318ff548 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -2565,7 +2565,8 @@ iasecc_sdo_create(struct sc_card *card, struct iasecc_sdo *sdo) rv = iasecc_sdo_put_data(card, &update); LOG_TEST_RET(ctx, rv, "failed to update 'Compulsory usage' data"); - field->on_card = 1; + if (field) + field->on_card = 1; } free(data); @@ -3252,14 +3253,19 @@ static int iasecc_compute_signature(struct sc_card *card, const unsigned char *in, size_t in_len, unsigned char *out, size_t out_len) { - struct sc_context *ctx = card->ctx; - struct iasecc_private_data *prv = (struct iasecc_private_data *) card->drv_data; - struct sc_security_env *env = &prv->security_env; + struct sc_context *ctx; + struct iasecc_private_data *prv; + struct sc_security_env *env; + + if (!card || !in || !out) + return SC_ERROR_INVALID_ARGUMENTS; + + ctx = card->ctx; + prv = (struct iasecc_private_data *) card->drv_data; + env = &prv->security_env; LOG_FUNC_CALLED(ctx); sc_log(ctx, "inlen %i, outlen %i", in_len, out_len); - if (!card || !in || !out) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid compute signature arguments"); if (env->operation == SC_SEC_OPERATION_SIGN) return iasecc_compute_signature_dst(card, in, in_len, out, out_len); diff --git a/src/libopensc/card-oberthur.c b/src/libopensc/card-oberthur.c index 2a9dbe3f..eb0820b1 100644 --- a/src/libopensc/card-oberthur.c +++ b/src/libopensc/card-oberthur.c @@ -1108,16 +1108,17 @@ auth_compute_signature(struct sc_card *card, const unsigned char *in, size_t ile unsigned char resp[SC_MAX_APDU_BUFFER_SIZE]; int rv; - SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "inlen %i, outlen %i\n", ilen, olen); if (!card || !in || !out) { - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS); + return SC_ERROR_INVALID_ARGUMENTS; } else if (ilen > 96) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Illegal input length %d\n", ilen); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Illegal input length"); } + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "inlen %i, outlen %i\n", ilen, olen); + sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A); apdu.datalen = ilen; apdu.data = in; diff --git a/src/libopensc/card-westcos.c b/src/libopensc/card-westcos.c index 1642eb7d..60bcb999 100644 --- a/src/libopensc/card-westcos.c +++ b/src/libopensc/card-westcos.c @@ -1109,6 +1109,15 @@ static int westcos_sign_decipher(int mode, sc_card_t *card, return SC_ERROR_INVALID_ARGUMENTS; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "westcos_sign_decipher outlen=%d\n", outlen); + +#ifndef ENABLE_OPENSSL + r = SC_ERROR_NOT_SUPPORTED; +#else + if (keyfile == NULL || mem == NULL || card->drv_data == NULL) { + r = SC_ERROR_OUT_OF_MEMORY; + goto out; + } + priv_data = (priv_data_t *) card->drv_data; if(priv_data->flags & RSA_CRYPTO_COMPONENT) @@ -1134,14 +1143,6 @@ static int westcos_sign_decipher(int mode, sc_card_t *card, r = apdu.resplen; goto out2; } - -#ifndef ENABLE_OPENSSL - r = SC_ERROR_NOT_SUPPORTED; -#else - if (keyfile == NULL || mem == NULL || priv_data == NULL) { - r = SC_ERROR_OUT_OF_MEMORY; - goto out; - } if ((priv_data->env.flags) & SC_ALGORITHM_RSA_PAD_PKCS1) pad = RSA_PKCS1_PADDING; diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 9a331728..5142d0c0 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -403,10 +403,11 @@ int sc_create_file(sc_card_t *card, sc_file_t *file) { int r; char pbuf[SC_MAX_PATH_STRING_SIZE]; - const sc_path_t *in_path = &file->path; + const sc_path_t *in_path; - assert(card != NULL); + assert(card != NULL && file != NULL); + in_path = &file->path; r = sc_path_print(pbuf, sizeof(pbuf), in_path); if (r != SC_SUCCESS) pbuf[0] = '\0'; @@ -864,14 +865,16 @@ sc_algorithm_info_t * sc_card_find_gostr3410_alg(sc_card_t *card, static int match_atr_table(sc_context_t *ctx, struct sc_atr_table *table, struct sc_atr *atr) { - u8 *card_atr_bin = atr->value; - size_t card_atr_bin_len = atr->len; + u8 *card_atr_bin; + size_t card_atr_bin_len; char card_atr_hex[3 * SC_MAX_ATR_SIZE]; size_t card_atr_hex_len; unsigned int i = 0; if (ctx == NULL || table == NULL || atr == NULL) return -1; + card_atr_bin = atr->value; + card_atr_bin_len = atr->len; sc_bin_to_hex(card_atr_bin, card_atr_bin_len, card_atr_hex, sizeof(card_atr_hex), ':'); card_atr_hex_len = strlen(card_atr_hex); diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index dbbd599b..c9515275 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -1434,10 +1434,6 @@ int cwa_encode_apdu(sc_card_t * card, u8 *msgbuf = NULL; /* to encrypt apdu data */ u8 *cryptbuf = NULL; - /* reserve extra bytes for padding and tlv header */ - msgbuf = calloc(12 + from->lc, sizeof(u8)); /* to encrypt apdu data */ - cryptbuf = calloc(12 + from->lc, sizeof(u8)); - /* mandatory check */ if (!card || !card->ctx || !provider) return SC_ERROR_INVALID_ARGUMENTS; @@ -1450,6 +1446,10 @@ int cwa_encode_apdu(sc_card_t * card, LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_INITIALIZED); if (sm_session->state != CWA_SM_ACTIVE) LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL); + + /* reserve extra bytes for padding and tlv header */ + msgbuf = calloc(12 + from->lc, sizeof(u8)); /* to encrypt apdu data */ + cryptbuf = calloc(12 + from->lc, sizeof(u8)); if (!msgbuf || !cryptbuf) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index a2be9b34..08375f0c 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -274,17 +274,18 @@ void sc_format_path(const char *str, sc_path_t *path) { int type = SC_PATH_TYPE_PATH; - memset(path, 0, sizeof(*path)); - if (*str == 'i' || *str == 'I') { - type = SC_PATH_TYPE_FILE_ID; - str++; + if (path) { + memset(path, 0, sizeof(*path)); + if (*str == 'i' || *str == 'I') { + type = SC_PATH_TYPE_FILE_ID; + str++; + } + path->len = sizeof(path->value); + if (sc_hex_to_bin(str, path->value, &path->len) >= 0) { + path->type = type; + } + path->count = -1; } - path->len = sizeof(path->value); - if (sc_hex_to_bin(str, path->value, &path->len) >= 0) { - path->type = type; - } - path->count = -1; - return; } int sc_append_path(sc_path_t *dest, const sc_path_t *src) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index c30167e5..2bf63774 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -3446,10 +3446,12 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session, check_attribute_buffer(attr, sizeof(CK_ULONG)); switch (prkey->prv_p15obj->type) { case SC_PKCS15_TYPE_PRKEY_EC: - if (key && key->u.ec.params.field_length > 0) - *(CK_ULONG *) attr->pValue = key->u.ec.params.field_length; - else - *(CK_ULONG *) attr->pValue = (key->u.ec.ecpointQ.len - 1) / 2 *8; + if (key) { + if (key->u.ec.params.field_length > 0) + *(CK_ULONG *) attr->pValue = key->u.ec.params.field_length; + else + *(CK_ULONG *) attr->pValue = (key->u.ec.ecpointQ.len - 1) / 2 *8; + } return CKR_OK; default: *(CK_ULONG *) attr->pValue = prkey->prv_info->modulus_length; diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 64abd1a7..aa507589 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -688,7 +688,7 @@ out: sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states); } - sc_log(context, "C_WaitForSlotEvent() = %s, event in 0x%lx", lookup_enum (RV_T, rv), *pSlot); + sc_log(context, "C_WaitForSlotEvent() = %s", lookup_enum (RV_T, rv)); sc_pkcs11_unlock(); return rv; } diff --git a/src/pkcs15init/pkcs15-entersafe.c b/src/pkcs15init/pkcs15-entersafe.c index 80c66698..12611179 100644 --- a/src/pkcs15init/pkcs15-entersafe.c +++ b/src/pkcs15init/pkcs15-entersafe.c @@ -292,10 +292,9 @@ static int entersafe_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card data.key_data.symmetric.key_len=16; r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); - if (pin_obj) { - /* Cache new PIN value. */ - sc_pkcs15_pincache_add(p15card, pin_obj, pin, pin_len); - } + + /* Cache new PIN value. */ + sc_pkcs15_pincache_add(p15card, pin_obj, pin, pin_len); } {/*puk*/ diff --git a/src/pkcs15init/pkcs15-epass2003.c b/src/pkcs15init/pkcs15-epass2003.c index a457ec93..d35cad63 100644 --- a/src/pkcs15init/pkcs15-epass2003.c +++ b/src/pkcs15init/pkcs15-epass2003.c @@ -470,8 +470,7 @@ static int epass2003_pkcs15_store_key(struct sc_profile *profile, SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "store key: cannot update private key"); - if (file) - sc_file_free(file); + sc_file_free(file); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); } diff --git a/src/pkcs15init/pkcs15-gpk.c b/src/pkcs15init/pkcs15-gpk.c index fdcf1871..e6502d96 100644 --- a/src/pkcs15init/pkcs15-gpk.c +++ b/src/pkcs15init/pkcs15-gpk.c @@ -458,8 +458,7 @@ gpk_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_objec #endif done: - if (keyfile) - sc_file_free(keyfile); + sc_file_free(keyfile); return r; } diff --git a/src/pkcs15init/pkcs15-jcop.c b/src/pkcs15init/pkcs15-jcop.c index b20e09f2..31854529 100644 --- a/src/pkcs15init/pkcs15-jcop.c +++ b/src/pkcs15init/pkcs15-jcop.c @@ -140,10 +140,10 @@ jcop_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_obje size_t bytes, mod_len, prv_len; int r; - if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { - sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "JCOP supports only RSA keys."); - return SC_ERROR_NOT_SUPPORTED; - } + if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) { + sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "JCOP supports only RSA keys."); + return SC_ERROR_NOT_SUPPORTED; + } /* The caller is supposed to have chosen a key file path for us */ if (key_info->path.len == 0 || key_info->modulus_length == 0) return SC_ERROR_INVALID_ARGUMENTS; @@ -155,7 +155,7 @@ jcop_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_obje mod_len = key_info->modulus_length / 8; bytes = mod_len / 2; - prv_len = 2 + 5 * bytes; + prv_len = 2 + 5 * bytes; keyfile->size = prv_len; /* Fix up PIN references in file ACL */ @@ -164,8 +164,7 @@ jcop_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_obje if (r >= 0) r = sc_pkcs15init_create_file(profile, p15card, keyfile); - if (keyfile) - sc_file_free(keyfile); + sc_file_free(keyfile); return r; } diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 913450a2..02422c73 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1888,8 +1888,7 @@ sc_pkcs15init_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *prof *path = file->path; - if (file) - sc_file_free(file); + sc_file_free(file); LOG_FUNC_RETURN(ctx, r); } @@ -2197,7 +2196,7 @@ sc_pkcs15init_select_intrinsic_id(struct sc_pkcs15_card *p15card, struct sc_prof { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_pubkey *pubkey = NULL; - unsigned id_style = profile->id_style; + unsigned id_style; struct sc_pkcs15_id id; unsigned char *id_data = NULL; size_t id_data_len = 0; @@ -2207,15 +2206,17 @@ sc_pkcs15init_select_intrinsic_id(struct sc_pkcs15_card *p15card, struct sc_prof #ifndef ENABLE_OPENSSL LOG_FUNC_RETURN(ctx, SC_SUCCESS); #else - if (!id_out) + if (!id_out || !profile) LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + id_style = profile->id_style; + /* ID already exists */ if (id_out->len) LOG_FUNC_RETURN(ctx, SC_SUCCESS); /* Native ID style is not intrisic one */ - if (profile->id_style == SC_PKCS15INIT_ID_STYLE_NATIVE) + if (id_style == SC_PKCS15INIT_ID_STYLE_NATIVE) LOG_FUNC_RETURN(ctx, SC_SUCCESS); memset(&id, 0, sizeof(id)); @@ -2283,7 +2284,7 @@ sc_pkcs15init_select_intrinsic_id(struct sc_pkcs15_card *p15card, struct sc_prof break; default: - sc_log(ctx, "Unsupported ID style: %i", profile->id_style); + sc_log(ctx, "Unsupported ID style: %i", id_style); LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Non supported ID style"); } @@ -3238,25 +3239,23 @@ sc_pkcs15init_verify_secret(struct sc_profile *profile, struct sc_pkcs15_card *p sc_log(ctx, "Symbolic PIN resolved to PIN(type:CHV,reference:%i)", type, reference); } - if (p15card) { - if (path && path->len) { - struct sc_path tmp_path = *path; - int iter; + if (path && path->len) { + struct sc_path tmp_path = *path; + int iter; - r = SC_ERROR_OBJECT_NOT_FOUND; - for (iter = tmp_path.len/2; iter >= 0 && r == SC_ERROR_OBJECT_NOT_FOUND; iter--, tmp_path.len -= 2) - r = sc_pkcs15_find_pin_by_type_and_reference(p15card, - tmp_path.len ? &tmp_path : NULL, - type, reference, &pin_obj); - } - else { - r = sc_pkcs15_find_pin_by_type_and_reference(p15card, NULL, type, reference, &pin_obj); - } + r = SC_ERROR_OBJECT_NOT_FOUND; + for (iter = tmp_path.len/2; iter >= 0 && r == SC_ERROR_OBJECT_NOT_FOUND; iter--, tmp_path.len -= 2) + r = sc_pkcs15_find_pin_by_type_and_reference(p15card, + tmp_path.len ? &tmp_path : NULL, + type, reference, &pin_obj); + } + else { + r = sc_pkcs15_find_pin_by_type_and_reference(p15card, NULL, type, reference, &pin_obj); + } - if (!r && pin_obj) { - memcpy(&auth_info, pin_obj->data, sizeof(auth_info)); - sc_log(ctx, "found PIN object '%s'", pin_obj->label); - } + if (!r && pin_obj) { + memcpy(&auth_info, pin_obj->data, sizeof(auth_info)); + sc_log(ctx, "found PIN object '%s'", pin_obj->label); } if (pin_obj) { diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index 4ade6974..1da4515a 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -189,7 +189,7 @@ myeid_init_card(sc_profile_t *profile, */ static int myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df) { - struct sc_context *ctx = p15card->card->ctx; + struct sc_context *ctx; struct sc_file *file = NULL; int r = 0, ii; static const char *create_dfs[] = { @@ -209,9 +209,10 @@ myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df SC_PKCS15_DODF }; - if (!profile || !p15card || !df) + if (!profile || !p15card || !p15card->card || !df) return SC_ERROR_INVALID_ARGUMENTS; + ctx = p15card->card->ctx; LOG_FUNC_CALLED(ctx); sc_log(ctx, "id (%x)", df->id); diff --git a/src/pkcs15init/pkcs15-oberthur-awp.c b/src/pkcs15init/pkcs15-oberthur-awp.c index 18032fba..aa4e20a1 100644 --- a/src/pkcs15init/pkcs15-oberthur-awp.c +++ b/src/pkcs15init/pkcs15-oberthur-awp.c @@ -330,12 +330,10 @@ awp_create_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, rv = awp_create_container_record(p15card, profile, file, acc); - if (clist) - sc_file_free(clist); - if (file) - sc_file_free(file); if (list) free(list); + sc_file_free(file); + sc_file_free(clist); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); } @@ -1669,8 +1667,8 @@ awp_delete_from_container(struct sc_pkcs15_card *p15card, rv = 0; if (buff) free(buff); - if (file) sc_file_free(file); if (clist) sc_file_free(clist); + sc_file_free(file); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); } @@ -1744,8 +1742,7 @@ awp_remove_from_object_list( struct sc_pkcs15_card *p15card, struct sc_profile * done: if (buff) free(buff); - if (lst) - sc_file_free(lst); + sc_file_free(lst); if (lst_file) sc_file_free(lst_file); diff --git a/src/pkcs15init/pkcs15-oberthur.c b/src/pkcs15init/pkcs15-oberthur.c index 34185987..15661e73 100644 --- a/src/pkcs15init/pkcs15-oberthur.c +++ b/src/pkcs15init/pkcs15-oberthur.c @@ -63,15 +63,17 @@ static int cosm_write_tokeninfo (struct sc_pkcs15_card *p15card, struct sc_profile *profile, char *label, unsigned flags) { - struct sc_context *ctx = p15card->card->ctx; + struct sc_context *ctx; struct sc_file *file = NULL; int rv; size_t sz; char *buffer = NULL; - if (!p15card || !profile) + if (!p15card || !p15card->card || !profile) return SC_ERROR_INVALID_ARGUMENTS; + ctx = p15card->card->ctx; + SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "cosm_write_tokeninfo() label '%s'; flags 0x%X", label, flags); if (sc_profile_get_file(profile, COSM_TITLE"-token-info", &file)) diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c index fdd185ce..d2e85f17 100644 --- a/src/pkcs15init/pkcs15-setcos.c +++ b/src/pkcs15init/pkcs15-setcos.c @@ -236,8 +236,7 @@ setcos_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot set MF into the activated state"); } - if(pinfile) - sc_file_free(pinfile); + sc_file_free(pinfile); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); } diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c index 1c560f89..433c7ae4 100644 --- a/src/pkcs15init/profile.c +++ b/src/pkcs15init/profile.c @@ -2059,7 +2059,7 @@ sc_profile_find_file_by_path(struct sc_profile *pro, const sc_path_t *path) sc_log(ctx, "find profile file by path:%s", sc_print_path(path)); #endif - if (!path->len && !path->aid.len) + if (!path || (!path->len && !path->aid.len)) return NULL; for (fi = pro->ef_list; fi; fi = fi->next) { diff --git a/src/scconf/parse.c b/src/scconf/parse.c index 2a9aed3f..043ab794 100644 --- a/src/scconf/parse.c +++ b/src/scconf/parse.c @@ -82,8 +82,9 @@ static scconf_item *scconf_item_find(scconf_parser * parser) scconf_item *item; for (item = parser->block->items; item; item = item->next) { - if (item->type == SCCONF_ITEM_TYPE_VALUE && - strcasecmp(item->key, parser->key) == 0) { + if (item && item->type == SCCONF_ITEM_TYPE_VALUE + && item->key && parser->key + && strcasecmp(item->key, parser->key) == 0) { return item; } } @@ -148,20 +149,24 @@ scconf_item *scconf_item_add(scconf_context * config, scconf_block * block, scco scconf_list_copy(dst->name, &parser.name); } scconf_item_add_internal(&parser, type); - switch (parser.current_item->type) { - case SCCONF_ITEM_TYPE_COMMENT: - parser.current_item->value.comment = strdup((const char *) data); - break; - case SCCONF_ITEM_TYPE_BLOCK: - if (!dst) - return NULL; - dst->parent = parser.block; - parser.current_item->value.block = dst; - scconf_list_destroy(parser.name); - break; - case SCCONF_ITEM_TYPE_VALUE: - scconf_list_copy((const scconf_list *) data, &parser.current_item->value.list); - break; + if (parser.current_item) { + switch (parser.current_item->type) { + case SCCONF_ITEM_TYPE_COMMENT: + parser.current_item->value.comment = strdup((const char *) data); + break; + case SCCONF_ITEM_TYPE_BLOCK: + if (!dst) + return NULL; + dst->parent = parser.block; + parser.current_item->value.block = dst; + scconf_list_destroy(parser.name); + break; + case SCCONF_ITEM_TYPE_VALUE: + scconf_list_copy((const scconf_list *) data, &parser.current_item->value.list); + break; + } + } else { + /* FIXME is it an error if item is NULL? */ } return parser.current_item; } diff --git a/src/scconf/sclex.c b/src/scconf/sclex.c index b16db4b7..c5a6758f 100644 --- a/src/scconf/sclex.c +++ b/src/scconf/sclex.c @@ -57,8 +57,10 @@ static void buf_addch(BUFHAN * bp, char ch) bp->bufmax += 256; bp->buf = (char *) realloc(bp->buf, bp->bufmax); } - bp->buf[bp->bufcur++] = ch; - bp->buf[bp->bufcur] = '\0'; + if (bp->buf) { + bp->buf[bp->bufcur++] = ch; + bp->buf[bp->bufcur] = '\0'; + } } static int buf_nextch(BUFHAN * bp) diff --git a/src/tests/base64.c b/src/tests/base64.c index ec9583dc..f868d12d 100644 --- a/src/tests/base64.c +++ b/src/tests/base64.c @@ -38,6 +38,7 @@ int main(int argc, char *argv[]) fwrite(outbuf, len, 1, stdout); r = 0; err: - fclose(inf); + if (inf) + fclose(inf); return r; } diff --git a/src/tools/dnie-tool.c b/src/tools/dnie-tool.c index 93f7c108..c856a7ba 100644 --- a/src/tools/dnie-tool.c +++ b/src/tools/dnie-tool.c @@ -146,7 +146,7 @@ int main(int argc, char* argv[]) if (r) { fprintf(stderr, "Error: Failed to establish context: %s\n", sc_strerror(r)); - return -1; + goto dnie_tool_end; } if (verbose > 1) { diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index c8455317..596b5a44 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -113,7 +113,7 @@ static int load_object(const char * object_id, const char * object_file) int r; struct stat stat_buf; - if((fp=fopen(object_file, "r"))==NULL){ + if(!object_file || (fp=fopen(object_file, "r")) == NULL){ printf("Cannot open object file, %s %s\n", (object_file)?object_file:"", strerror(errno)); return -1; diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index aa3474a6..21abbbf4 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -1296,8 +1296,7 @@ static int get_cert_info(sc_pkcs15_card_t *myp15card, sc_pkcs15_object_t *certob } done: - if (cert) - sc_pkcs15_free_certificate(cert); + sc_pkcs15_free_certificate(cert); if (othercert) sc_pkcs15_free_certificate(othercert); diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 603a7534..b357319a 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -783,17 +783,17 @@ static int read_ssh_key(void) struct sc_pkcs15_object *obj = NULL; sc_pkcs15_pubkey_t *pubkey = NULL; sc_pkcs15_cert_t *cert = NULL; - FILE *outf = NULL; + FILE *outf = NULL; - if (opt_outfile != NULL) { - outf = fopen(opt_outfile, "w"); - if (outf == NULL) { - fprintf(stderr, "Error opening file '%s': %s\n", opt_outfile, strerror(errno)); - goto fail2; - } - } + if (opt_outfile != NULL) { + outf = fopen(opt_outfile, "w"); + if (outf == NULL) { + fprintf(stderr, "Error opening file '%s': %s\n", opt_outfile, strerror(errno)); + goto fail2; + } + } else { - outf = stdout; + outf = stdout; } id.len = SC_PKCS15_MAX_ID_SIZE; @@ -988,8 +988,8 @@ static int read_ssh_key(void) free(uu); } - if (outf != stdout) - fclose(outf); + if (outf != stdout) + fclose(outf); if (cert) sc_pkcs15_free_certificate(cert); else if (pubkey) @@ -999,8 +999,8 @@ static int read_ssh_key(void) fail: printf("can't convert key: buffer too small\n"); fail2: - if (outf != stdout) - fclose(outf); + if (outf && outf != stdout) + fclose(outf); if (cert) sc_pkcs15_free_certificate(cert); else if (pubkey) diff --git a/src/tools/westcos-tool.c b/src/tools/westcos-tool.c index 54a5d65d..24136fbb 100644 --- a/src/tools/westcos-tool.c +++ b/src/tools/westcos-tool.c @@ -305,7 +305,7 @@ static int cert2der(X509 *cert, u8 **value) static int create_file_cert(sc_card_t *card) { int r; - int size; + int size = 0; sc_path_t path; sc_file_t *file = NULL; @@ -313,12 +313,13 @@ static int create_file_cert(sc_card_t *card) r = sc_select_file(card, &path, &file); if(r) goto out; - size = (file->size) - 32; - if(file) { + size = (file->size) - 32; sc_file_free(file); file = NULL; + } else { + size = 2048; } sc_format_path("0002", &path); @@ -903,8 +904,7 @@ out: sc_disconnect_card(card); } - if (ctx) - sc_release_context(ctx); + sc_release_context(ctx); return EXIT_SUCCESS; } From 1b53b59ed393057cc7840b916d4081ef64a1da74 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 24 Jan 2015 19:22:39 +0100 Subject: [PATCH 036/306] fixed potential use after free reported by coverity scan --- src/tools/sc-hsm-tool.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index ac94aa90..7e1eb707 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -1169,7 +1169,10 @@ static int wrap_key(sc_card_t *card, int keyid, const char *outf, const char *pi memcpy(ptr, key, key_len); ptr += key_len; + free(key); + key = NULL; + key_len = 0; // Add private key description if (ef_prkd_len > 0) { @@ -1184,7 +1187,6 @@ static int wrap_key(sc_card_t *card, int keyid, const char *outf, const char *pi } // Encode key, key decription and certificate object in sequence - key_len = 0; wrap_with_tag(0x30, keyblob, ptr - keyblob, &key, &key_len); out = fopen(outf, "wb"); From c9213164450775c0e32cec062150b67ee13af9d9 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 24 Jan 2015 19:23:33 +0100 Subject: [PATCH 037/306] coverity-scan: connect to GitHub --- .travis.yml | 25 +++++++++++++++++++++++++ README.md | 11 +++++++++++ 2 files changed, 36 insertions(+) create mode 100644 .travis.yml create mode 100644 README.md diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..3d295cab --- /dev/null +++ b/.travis.yml @@ -0,0 +1,25 @@ +language: C +compiler: gcc +before_install: sudo apt-get update +install: sudo apt-get install libpcsclite-dev +env: + - CONF="--prefix=/ --disable-openct --enable-pcsc --enable-strict --disable-man --disable-doc" +# script: ./bootstrap && ./configure $CONF && make + +env: + global: + # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created + # via the "travis encrypt" command using the project repo's public key + - secure: "UkHn7wy4im8V1nebCWbAetnDSOLRUbOlF6++ovk/7Bnso1/lnhXHelyzgRxfD/oI68wm9nnRV+RQEZ9+72Ug1CyvHxyyxxkwal/tPeHH4B/L+aGdPi0id+5OZSKIm77VP3m5s102sJMJgH7DFd03+nUd0K26p0tk8ad4j1geV4c=" + +addons: + coverity_scan: + project: + name: "OpenSC/OpenSC" + description: "Build submitted via Travis CI" + notification_email: viktor.tarasov@gmail.com + build_command_prepend: "./bootstrap && ./configure --disable-openct --enable-pcsc --enable-strict --disable-man --disable-doc; make clean" + build_command: "make -j 4" + branch_pattern: coverity_scan + +script: if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make ; fi diff --git a/README.md b/README.md new file mode 100644 index 00000000..f65aac1d --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +OpenSC documentation wiki is available online at + https://github.com/OpenSC/OpenSC/wiki + +Please take a look at the documentation before trying to use OpenSC. + +Coverity Scan: +[![Coverity Scan Build Status](https://scan.coverity.com/projects/4011/badge.svg)](https://scan.coverity.com/projects/4026) + +Travis CI: +[![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png?branch=coverity_scan)](https://travis-ci.org/OpenSC/OpenSC) + From 8df9896204f4d776bd312f725436f2f791abd377 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 24 Jan 2015 19:25:11 +0100 Subject: [PATCH 038/306] pass big parameter by reference reported by coverity scan --- src/tools/pkcs15-init.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 21abbbf4..81d883c8 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -1311,7 +1311,7 @@ done: */ static int do_delete_crypto_objects(sc_pkcs15_card_t *myp15card, struct sc_profile *profile, - const sc_pkcs15_id_t id, + const sc_pkcs15_id_t *id, unsigned int which) { sc_pkcs15_object_t *objs[10]; /* 1 priv + 1 pub + chain of at most 8 certs, should be enough */ @@ -1327,23 +1327,23 @@ static int do_delete_crypto_objects(sc_pkcs15_card_t *myp15card, } for (i = 0; i< r; i++) - if (sc_pkcs15_compare_id(&id, &((struct sc_pkcs15_prkey_info *)key_objs[i]->data)->id)) + if (sc_pkcs15_compare_id(id, &((struct sc_pkcs15_prkey_info *)key_objs[i]->data)->id)) objs[count++] = key_objs[i]; if (!count) - fprintf(stderr, "NOTE: couldn't find privkey %s to delete\n", sc_pkcs15_print_id(&id)); + fprintf(stderr, "NOTE: couldn't find privkey %s to delete\n", sc_pkcs15_print_id(id)); } if (which & SC_PKCS15INIT_TYPE_PUBKEY) { - if (sc_pkcs15_find_pubkey_by_id(myp15card, &id, &objs[count]) != 0) - fprintf(stderr, "NOTE: couldn't find pubkey %s to delete\n", sc_pkcs15_print_id(&id)); + if (sc_pkcs15_find_pubkey_by_id(myp15card, id, &objs[count]) != 0) + fprintf(stderr, "NOTE: couldn't find pubkey %s to delete\n", sc_pkcs15_print_id(id)); else count++; } if (which & SC_PKCS15INIT_TYPE_CERT) { - if (sc_pkcs15_find_cert_by_id(myp15card, &id, &objs[count]) != 0) - fprintf(stderr, "NOTE: couldn't find cert %s to delete\n", sc_pkcs15_print_id(&id)); + if (sc_pkcs15_find_cert_by_id(myp15card, id, &objs[count]) != 0) + fprintf(stderr, "NOTE: couldn't find cert %s to delete\n", sc_pkcs15_print_id(id)); else { count++; del_cert = 1; @@ -1416,7 +1416,7 @@ do_delete_objects(struct sc_profile *profile, unsigned int myopt_delete_flags) util_fatal("Specify the --id for key(s) or cert(s) to be deleted\n"); sc_pkcs15_format_id(opt_objectid, &id); - r = do_delete_crypto_objects(p15card, profile, id, myopt_delete_flags); + r = do_delete_crypto_objects(p15card, profile, &id, myopt_delete_flags); if (r >= 0) count += r; } From fca3a37097a7653dfc318ca8e99450cbd2747eea Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 24 Jan 2015 19:47:01 +0100 Subject: [PATCH 039/306] fixed truncated stdio return value --- src/tools/sc-hsm-tool.c | 2 +- src/tools/util.c | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index 7e1eb707..e9d7f474 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -424,7 +424,7 @@ void clearScreen() void waitForEnterKeyPressed() { - char c; + int c; fflush(stdout); while ((c = getchar()) != '\n' && c != EOF) { diff --git a/src/tools/util.c b/src/tools/util.c index 0b0cebd6..e11ffb02 100644 --- a/src/tools/util.c +++ b/src/tools/util.c @@ -376,7 +376,8 @@ util_getpass (char **lineptr, size_t *len, FILE *stream) { #define MAX_PASS_SIZE 128 char *buf; - unsigned int i; + size_t i; + int ch = 0; #ifndef _WIN32 struct termios old, new; @@ -395,26 +396,26 @@ util_getpass (char **lineptr, size_t *len, FILE *stream) for (i = 0; i < MAX_PASS_SIZE - 1; i++) { #ifndef _WIN32 - buf[i] = getchar(); + ch = getchar(); #else - buf[i] = _getch(); + ch = _getch(); #endif - if (buf[i] == 0 || buf[i] == 3) + if (ch == 0 || ch == 3) break; - if (buf[i] == '\n' || buf[i] == '\r') + if (ch == '\n' || ch == '\r') break; + + buf[i] = (char) ch; } #ifndef _WIN32 tcsetattr (fileno (stdout), TCSAFLUSH, &old); fputs("\n", stdout); #endif - if (buf[i] == 0 || buf[i] == 3) { + if (ch == 0 || ch == 3) { free(buf); return -1; } - buf[i] = 0; - if (*lineptr && (!len || *len < i+1)) { free(*lineptr); *lineptr = NULL; From 9a4b58800b8c1fc89f598d52b28994be2fbf8bd7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 24 Jan 2015 20:00:03 +0100 Subject: [PATCH 040/306] fixed Printf arg type mismatch --- src/tools/cardos-tool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/cardos-tool.c b/src/tools/cardos-tool.c index f171220c..e271fed6 100644 --- a/src/tools/cardos-tool.c +++ b/src/tools/cardos-tool.c @@ -593,7 +593,7 @@ static int cardos_format(const char *opt_startkey) if (check_apdu(&apdu)) return 1; if (apdu.resplen < 0x04) { - printf("expected 4-6 bytes form GET DATA for startkey data, but got only %u\n", apdu.resplen); + printf("expected 4-6 bytes form GET DATA for startkey data, but got only %zu\n", apdu.resplen); printf("aborting\n"); return 1; } @@ -914,7 +914,7 @@ static int cardos_change_startkey(const char *change_startkey_apdu) if (check_apdu(&apdu)) return 1; if (apdu.resplen < 0x04) { - printf("expected 4-6 bytes form GET DATA for startkey data, but got only %u\n", apdu.resplen); + printf("expected 4-6 bytes form GET DATA for startkey data, but got only %zu\n", apdu.resplen); printf("aborting\n"); return 1; } @@ -999,7 +999,7 @@ change_startkey: if (check_apdu(&apdu)) return 1; if (apdu.resplen < 0x04) { - printf("expected 4-6 bytes form GET DATA for startkey data, but got only %u\n", apdu.resplen); + printf("expected 4-6 bytes form GET DATA for startkey data, but got only %zu\n", apdu.resplen); printf("aborting\n"); return 1; } From 3f64d3a805b93f1c436c321c3fb832757d4c07b4 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 24 Jan 2015 20:11:16 +0100 Subject: [PATCH 041/306] fixed bad memory allocation --- src/tools/pkcs11-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index c07e61d9..55b3996d 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -2836,7 +2836,7 @@ get_mechanisms(CK_SLOT_ID slot, CK_MECHANISM_TYPE_PTR *pList, CK_FLAGS flags) CK_RV rv; rv = p11->C_GetMechanismList(slot, *pList, &ulCount); - *pList = calloc(ulCount, sizeof(*pList)); + *pList = calloc(ulCount, sizeof(**pList)); if (*pList == NULL) util_fatal("calloc failed: %m"); From 6641cbf45559050ebcc059ed3df33e26ea185c15 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 24 Jan 2015 20:17:26 +0100 Subject: [PATCH 042/306] fixed potential string overflow --- src/libopensc/pkcs15-tcos.c | 4 +++- src/tools/cryptoflex-tool.c | 5 +++-- src/tools/pkcs11-tool.c | 10 ++++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c index 4c98518e..c848fb83 100644 --- a/src/libopensc/pkcs15-tcos.c +++ b/src/libopensc/pkcs15-tcos.c @@ -25,6 +25,7 @@ #include #include "common/compat_strlcpy.h" +#include "common/compat_strlcat.h" #include "internal.h" #include "pkcs15.h" #include "cardctl.h" @@ -261,7 +262,8 @@ static char *dirpath(char *dir, const char *path){ static char buf[SC_MAX_PATH_STRING_SIZE]; strcpy(buf,dir); - return strcat(buf,path); + strlcat(buf,path,sizeof buf); + return buf; } static int detect_netkey( diff --git a/src/tools/cryptoflex-tool.c b/src/tools/cryptoflex-tool.c index 56113a83..fbc83b77 100644 --- a/src/tools/cryptoflex-tool.c +++ b/src/tools/cryptoflex-tool.c @@ -28,6 +28,7 @@ #include "libopensc/pkcs15.h" #include "common/compat_strlcpy.h" +#include "common/compat_strlcat.h" #include "util.h" static const char *app_name = "cryptoflex-tool"; @@ -145,7 +146,7 @@ static int select_app_df(void) strcpy(str, "3F00"); if (opt_appdf != NULL) - strcat(str, opt_appdf); + strlcat(str, opt_appdf, sizeof str); sc_format_path(str, &path); r = sc_select_file(card, &path, &file); if (r) { @@ -945,7 +946,7 @@ static int create_pin(void) } strcpy(buf, "3F00"); if (opt_appdf != NULL) - strcat(buf, opt_appdf); + strlcat(buf, opt_appdf, sizeof buf); sc_format_path(buf, &path); return create_pin_file(&path, opt_pin_num, ""); diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 55b3996d..0d00c4a4 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -47,6 +47,8 @@ #include "pkcs11/pkcs11.h" #include "pkcs11/pkcs11-opensc.h" #include "libopensc/asn1.h" +#include "common/compat_strlcat.h" +#include "common/compat_strlcpy.h" #include "util.h" extern void *C_LoadModule(const char *name, CK_FUNCTION_LIST_PTR_PTR); @@ -1145,7 +1147,7 @@ static void init_token(CK_SLOT_ID slot) util_fatal("No PIN entered, exiting\n"); if (!new_pin || !*new_pin || strlen(new_pin) > 20) util_fatal("Invalid SO PIN\n"); - strcpy(new_buf, new_pin); + strlcpy(new_buf, new_pin, sizeof new_buf); free(new_pin); new_pin = NULL; printf("Please enter the new SO PIN (again): "); r = util_getpass(&new_pin, &len, stdin); @@ -1318,7 +1320,7 @@ static int unlock_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess, int login_type) r = util_getpass(&new_pin, &len, stdin); if (r < 0) return 1; - strcpy(new_buf, new_pin); + strlcpy(new_buf, new_pin, sizeof new_buf); printf("Please enter the new PIN again: "); r = util_getpass(&new_pin, &len, stdin); @@ -4434,8 +4436,8 @@ static const char *p11_flag_names(struct flag_info *list, CK_FLAGS value) buffer[0] = '\0'; while (list->value) { if (list->value & value) { - strcat(buffer, sepa); - strcat(buffer, list->name); + strlcat(buffer, sepa, sizeof buffer); + strlcat(buffer, list->name, sizeof buffer); value &= ~list->value; sepa = ", "; } From 00330b2c7937bbceae3e3ebfae112c626c7ae231 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 24 Jan 2015 22:16:22 +0100 Subject: [PATCH 043/306] fixed resource leak --- src/libopensc/card.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 5142d0c0..f909bf85 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -222,18 +222,17 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) } if (card->name == NULL) card->name = card->driver->name; - *card_out = card; - /* Override card limitations with reader limitations. - * Note that zero means no limitations at all. + /* Override card limitations with reader limitations. + * Note that zero means no limitations at all. */ - if ((card->max_recv_size == 0) || - ((reader->driver->max_recv_size != 0) && (reader->driver->max_recv_size < card->max_recv_size))) - card->max_recv_size = reader->driver->max_recv_size; + if ((card->max_recv_size == 0) || + ((reader->driver->max_recv_size != 0) && (reader->driver->max_recv_size < card->max_recv_size))) + card->max_recv_size = reader->driver->max_recv_size; - if ((card->max_send_size == 0) || - ((reader->driver->max_send_size != 0) && (reader->driver->max_send_size < card->max_send_size))) - card->max_send_size = reader->driver->max_send_size; + if ((card->max_send_size == 0) || + ((reader->driver->max_send_size != 0) && (reader->driver->max_send_size < card->max_send_size))) + card->max_send_size = reader->driver->max_send_size; sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", card->name, card->type, card->flags, card->max_send_size, card->max_recv_size); @@ -246,6 +245,7 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) goto err; } #endif + *card_out = card; LOG_FUNC_RETURN(ctx, SC_SUCCESS); err: From b6a935a261d87fa77f1682763ff7c7f55189f246 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 24 Jan 2015 23:12:47 +0100 Subject: [PATCH 044/306] fixed memory leak --- src/libopensc/apdu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libopensc/apdu.c b/src/libopensc/apdu.c index 55f13d08..38c75153 100644 --- a/src/libopensc/apdu.c +++ b/src/libopensc/apdu.c @@ -203,8 +203,10 @@ int sc_apdu_get_octets(sc_context_t *ctx, const sc_apdu_t *apdu, u8 **buf, if (nbuf == NULL) return SC_ERROR_OUT_OF_MEMORY; /* encode the APDU in the buffer */ - if (sc_apdu2bytes(ctx, apdu, proto, nbuf, nlen) != SC_SUCCESS) + if (sc_apdu2bytes(ctx, apdu, proto, nbuf, nlen) != SC_SUCCESS) { + free(nbuf); return SC_ERROR_INTERNAL; + } *buf = nbuf; *len = nlen; From 02214dca86d44064939b8dff61bd571cb0c793ac Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Tue, 27 Jan 2015 08:54:32 +0100 Subject: [PATCH 045/306] coverity-scan: test build --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f65aac1d..ca03a8ac 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ OpenSC documentation wiki is available online at Please take a look at the documentation before trying to use OpenSC. + Coverity Scan: [![Coverity Scan Build Status](https://scan.coverity.com/projects/4011/badge.svg)](https://scan.coverity.com/projects/4026) From ea40322a30a8053ee859a3a5ae9d20d17af830da Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 21 Jan 2015 16:57:02 +0100 Subject: [PATCH 046/306] added travis-ci configuration --- .travis.yml | 56 ++++++++++++++++++++++++++++++++++++++ src/libopensc/iasecc-sdo.c | 11 ++++++++ 2 files changed, 67 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..ed63e92c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,56 @@ +language: C + +env: + global: + # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created + # via the "travis encrypt" command using the project repo's public key + - secure: "UkHn7wy4im8V1nebCWbAetnDSOLRUbOlF6++ovk/7Bnso1/lnhXHelyzgRxfD/oI68wm9nnRV+RQEZ9+72Ug1CyvHxyyxxkwal/tPeHH4B/L+aGdPi0id+5OZSKIm77VP3m5s102sJMJgH7DFd03+nUd0K26p0tk8ad4j1geV4c=" + +matrix: + include: + - compiler: clang + - compiler: gcc + - compiler: gcc + env: HOST=i686-w64-mingw32 + +before_install: + - if [ $TRAVIS_OS_NAME == linux ]; then + sudo apt-get update; + fi + +install: + - if [ $TRAVIS_OS_NAME == linux ]; then + if [ -z "$HOST" ]; then + sudo apt-get install libpcsclite-dev xsltproc docbook-xsl; + else + sudo apt-get install mingw-w64 binutils-mingw-w64-i686 gcc-mingw-w64-i686; + fi + fi + +before_script: + - ./bootstrap + - if [ -z "$HOST" ]; then + ./configure --enable-doc --enable-dnie-ui; + else + unset CC; + unset CXX; + ./configure --host=$HOST --disable-openssl; + fi + +addons: + coverity_scan: + project: + name: "OpenSC/OpenSC" + description: "Build submitted via Travis CI" + notification_email: viktor.tarasov@gmail.com + build_command: "make -j 4" + branch_pattern: coverity_scan + +script: + - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then + make; + fi + - if [ -z "$HOST" -a "${COVERITY_SCAN_BRANCH}" != 1 ]; then + make check; + make dist; + fi diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c index ea5aa971..b1d3096f 100644 --- a/src/libopensc/iasecc-sdo.c +++ b/src/libopensc/iasecc-sdo.c @@ -1287,4 +1287,15 @@ iasecc_docp_copy(struct sc_context *ctx, struct iasecc_sdo_docp *in, struct iase LOG_FUNC_RETURN(ctx, SC_SUCCESS); } +#else + +/* we need to define the functions below to export them */ +#include "errors.h" + +int +iasecc_sdo_encode_update_field() +{ + return SC_ERROR_NOT_SUPPORTED; +} + #endif /* ENABLE_OPENSSL */ From fdd38f6e0437077086a793dadc912f07c75d8774 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 04:30:40 +0100 Subject: [PATCH 047/306] fixed copy into fixed size buffer --- src/libopensc/pkcs15-tcos.c | 2 +- src/pkcs15init/pkcs15-lib.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c index c848fb83..30762156 100644 --- a/src/libopensc/pkcs15-tcos.c +++ b/src/libopensc/pkcs15-tcos.c @@ -261,7 +261,7 @@ static int insert_pin( static char *dirpath(char *dir, const char *path){ static char buf[SC_MAX_PATH_STRING_SIZE]; - strcpy(buf,dir); + strlcpy(buf,dir,sizeof buf); strlcat(buf,path,sizeof buf); return buf; } diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 02422c73..fb76ac98 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -350,7 +350,7 @@ sc_pkcs15init_bind(struct sc_card *card, const char *name, const char *profile_o * If none is defined, use the default profile name. */ if (!get_profile_from_config(card, card_profile, sizeof(card_profile))) - strcpy(card_profile, driver); + strclpy(card_profile, driver, sizeof card_profile); if (profile_option != NULL) strlcpy(card_profile, profile_option, sizeof(card_profile)); From 77752f442d90665b814f5a7fbbe5d3f28000860b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 05:47:20 +0100 Subject: [PATCH 048/306] fixed unused value --- src/libopensc/card-dnie.c | 3 +-- src/libopensc/pkcs15-itacns.c | 2 ++ src/pkcs11/framework-pkcs15.c | 5 ++++- src/pkcs11/pkcs11-object.c | 2 +- src/pkcs15init/pkcs15-lib.c | 3 ++- src/pkcs15init/pkcs15-sc-hsm.c | 3 ++- src/pkcs15init/pkcs15-westcos.c | 2 ++ src/tools/pkcs15-tool.c | 6 ++---- 8 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 7bd0df7f..9359de33 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -346,7 +346,6 @@ static int dnie_get_info(sc_card_t * card, char *data[]) } res = dnie_read_file(card, path, &file, &buffer, &bufferlen); if (res != SC_SUCCESS) { - msg = "Cannot read IDESP EF"; data[3]=NULL; goto get_info_ph3; } @@ -1195,7 +1194,7 @@ static int dnie_set_security_env(struct sc_card *card, sc_log(card->ctx, "checking key references"); if (env->key_ref_len != 1) { sc_log(card->ctx, "Null or invalid key ID reference"); - result = SC_ERROR_INVALID_ARGUMENTS; + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); } sc_log(card->ctx, "Using key reference '%s'", sc_dump_hex(env->key_ref, env->key_ref_len)); diff --git a/src/libopensc/pkcs15-itacns.c b/src/libopensc/pkcs15-itacns.c index c56f05c5..55e9f31b 100644 --- a/src/libopensc/pkcs15-itacns.c +++ b/src/libopensc/pkcs15-itacns.c @@ -499,6 +499,8 @@ static int itacns_add_data_files(sc_pkcs15_card_t *p15card) sizeof(obj.label)); data.path = path; rv = sc_pkcs15emu_add_data_object(p15card, &obj, &data); + SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, rv, + "Could not add data file"); } /* diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 2bf63774..45a57d7e 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -4669,8 +4669,11 @@ register_mechanisms(struct sc_pkcs11_card *p11card) alg_info++; } - if (flags & SC_ALGORITHM_ECDSA_RAW) + if (flags & SC_ALGORITHM_ECDSA_RAW) { rc = register_ec_mechanisms(p11card, flags, ec_ext_flags, ec_min_key_size, ec_max_key_size); + if (rc != CKR_OK) + return rc; + } if (flags & (SC_ALGORITHM_GOSTR3410_RAW | SC_ALGORITHM_GOSTR3410_HASH_NONE diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c index 90b5e1d5..70291b3a 100644 --- a/src/pkcs11/pkcs11-object.c +++ b/src/pkcs11/pkcs11-object.c @@ -394,7 +394,7 @@ C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */ sizeof(CK_OBJECT_HANDLE) * operation->allocated_handles); if (operation->handles == NULL) { rv = CKR_HOST_MEMORY; - break; + goto out; } } operation->handles[operation->num_handles++] = object->handle; diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index fb76ac98..5e61399f 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -350,7 +350,7 @@ sc_pkcs15init_bind(struct sc_card *card, const char *name, const char *profile_o * If none is defined, use the default profile name. */ if (!get_profile_from_config(card, card_profile, sizeof(card_profile))) - strclpy(card_profile, driver, sizeof card_profile); + strlcpy(card_profile, driver, sizeof card_profile); if (profile_option != NULL) strlcpy(card_profile, profile_option, sizeof(card_profile)); @@ -3159,6 +3159,7 @@ sc_pkcs15init_get_transport_key(struct sc_profile *profile, struct sc_pkcs15_car if (callbacks.get_key) { rv = callbacks.get_key(profile, type, reference, defbuf, defsize, pinbuf, pinsize); + LOG_TEST_RET(ctx, rv, "Cannot get key"); } else if (rv >= 0) { if (*pinsize < defsize) diff --git a/src/pkcs15init/pkcs15-sc-hsm.c b/src/pkcs15init/pkcs15-sc-hsm.c index 9e7ebbc8..0f2fd8af 100644 --- a/src/pkcs15init/pkcs15-sc-hsm.c +++ b/src/pkcs15init/pkcs15-sc-hsm.c @@ -271,9 +271,10 @@ static int sc_hsm_generate_key(struct sc_profile *profile, struct sc_pkcs15_card r = sc_hsm_encode_gakp_ec(p15card, &cvc, key_info); break; default: - LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_IMPLEMENTED); + r = SC_ERROR_NOT_IMPLEMENTED; break; } + LOG_TEST_RET(p15card->card->ctx, r, "Could not encode GAKP cdata"); r = sc_pkcs15emu_sc_hsm_encode_cvc(p15card, &cvc, &cvcbin, &cvclen); sc_pkcs15emu_sc_hsm_free_cvc(&cvc); diff --git a/src/pkcs15init/pkcs15-westcos.c b/src/pkcs15init/pkcs15-westcos.c index e75fb3ac..1fc70b4a 100644 --- a/src/pkcs15init/pkcs15-westcos.c +++ b/src/pkcs15init/pkcs15-westcos.c @@ -270,6 +270,8 @@ static int westcos_pkcs15init_generate_key(sc_profile_t *profile, pubkey->algorithm = SC_ALGORITHM_RSA; r = sc_pkcs15_decode_pubkey(p15card->card->ctx, pubkey, p, lg); + if (r < 0) + goto out; } (void) BIO_reset(mem); diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index b357319a..8c980bb6 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -306,7 +306,7 @@ print_pem_object(const char *kind, const u8*data, size_t data_len) return 0; } -static int +static void list_data_object(const char *kind, const unsigned char *data, size_t data_len) { char title[0x100]; @@ -321,8 +321,6 @@ list_data_object(const char *kind, const unsigned char *data, size_t data_len) printf("%02X", data[i]); } printf("\n"); - - return 0; } static int @@ -478,7 +476,7 @@ static int list_data_objects(void) continue; /* DEE emulation may say there is a file */ return 1; } - r = list_data_object("\tData", data_object->data, data_object->data_len); + list_data_object("\tData", data_object->data, data_object->data_len); sc_pkcs15_free_data_object(data_object); } else { From 7c497b324f8a79cec3dc374373efe6e2040bab2b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 05:51:00 +0100 Subject: [PATCH 049/306] fixed not null terminated buffer --- src/libopensc/card.c | 5 +++-- src/libopensc/iasecc-sm.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index f909bf85..6b384069 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -29,6 +29,7 @@ #include "internal.h" #include "asn1.h" +#include "common/compat_strlcpy.h" /* #define INVALIDATE_CARD_CACHE_IN_UNLOCK @@ -1258,8 +1259,8 @@ sc_card_sm_check(struct sc_card *card) rv = sc_card_sm_load(card, module_path, module_name); LOG_TEST_RET(ctx, rv, "Failed to load SM module"); - strncpy(card->sm_ctx.module.filename, module_name, sizeof(card->sm_ctx.module.filename)); - strncpy(card->sm_ctx.config_section, sm, sizeof(card->sm_ctx.config_section)); + strlcpy(card->sm_ctx.module.filename, module_name, sizeof(card->sm_ctx.module.filename)); + strlcpy(card->sm_ctx.config_section, sm, sizeof(card->sm_ctx.config_section)); /* allocate resources for the external SM module */ sc_log(ctx, "'module_init' handler %p", card->sm_ctx.module.ops.module_init); diff --git a/src/libopensc/iasecc-sm.c b/src/libopensc/iasecc-sm.c index 7fdffbdc..bfa57133 100644 --- a/src/libopensc/iasecc-sm.c +++ b/src/libopensc/iasecc-sm.c @@ -25,6 +25,7 @@ #include "internal.h" #include "asn1.h" #include "cardctl.h" +#include "common/compat_strlcpy.h" #include "sm.h" #include "iasecc.h" @@ -156,7 +157,7 @@ iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int * if (card->sm_ctx.sm_mode == SM_MODE_NONE) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Cannot do 'External Authentication' without SM activated "); - strncpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section)); + strlcpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section)); sm_info->cmd = SM_CMD_EXTERNAL_AUTH; sm_info->serialnr = card->serialnr; sm_info->card_type = card->type; @@ -296,7 +297,7 @@ iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd) LOG_FUNC_CALLED(ctx); - strncpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section)); + strlcpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section)); sm_info->cmd = cmd; sm_info->serialnr = card->serialnr; sm_info->card_type = card->type; From 027e4a08679c1bacb139e990ec33b8a61f3d416a Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 05:59:41 +0100 Subject: [PATCH 050/306] fixed out of bounds read --- src/libopensc/ctx.c | 2 +- src/libopensc/reader-pcsc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index daade137..fa94dc14 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -840,7 +840,7 @@ int sc_set_card_driver(sc_context_t *ctx, const char *short_name) if (short_name == NULL) { ctx->forced_driver = NULL; match = 1; - } else while (ctx->card_drivers[i] != NULL && i < SC_MAX_CARD_DRIVERS) { + } else while (i < SC_MAX_CARD_DRIVERS && ctx->card_drivers[i] != NULL) { struct sc_card_driver *drv = ctx->card_drivers[i]; if (strcmp(short_name, drv->short_name) == 0) { diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index b6a33c7a..da65c3fb 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -768,7 +768,7 @@ static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader) PACE_FUNCTION_GetReaderPACECapabilities, /* idxFunction */ 0, 0, /* lengthInputData */ }; - u8 rbuf[6]; + u8 rbuf[7]; u8 *p = rbuf; size_t rcount = sizeof rbuf; struct pcsc_private_data *priv; From b1b99ce7e5973569e743c3ce285b2730d759ed72 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 06:03:52 +0100 Subject: [PATCH 051/306] fixed integer underflow --- src/pkcs15init/pkcs15-myeid.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index 1da4515a..1c33a3b2 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -448,6 +448,9 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, file->ef_structure = SC_CARDCTL_MYEID_KEY_EC; memcpy(&key_info->path.value, &file->path.value, file->path.len); + if (!file->path.len) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, + "Cannot determine private key file"); key_info->key_reference = file->path.value[file->path.len - 1] & 0xFF; sc_log(ctx, "Path of MyEID private key file to create %s", From 68d86644fd642f71e0295a81aa356e7fde319abd Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 06:10:16 +0100 Subject: [PATCH 052/306] fixed use after free --- src/libopensc/cwa-dnie.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libopensc/cwa-dnie.c b/src/libopensc/cwa-dnie.c index 62060db0..73098f2d 100644 --- a/src/libopensc/cwa-dnie.c +++ b/src/libopensc/cwa-dnie.c @@ -265,8 +265,10 @@ int dnie_read_file(sc_card_t * card, res = SC_SUCCESS; goto dnie_read_file_end; dnie_read_file_err: - if (*file) + if (*file) { sc_file_free(*file); + *file = NULL; + } dnie_read_file_end: if (msg) sc_log(ctx, msg); From 87b2403673ca84870698b5d8ccf0efe831506c14 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:00:02 +0100 Subject: [PATCH 053/306] fixed out of bounds access/write --- src/libopensc/card-epass2003.c | 2 +- src/libopensc/card-myeid.c | 6 +++--- src/libopensc/card-setcos.c | 2 +- src/libopensc/ctbcs.c | 4 ++-- src/pkcs15init/pkcs15-asepcos.c | 2 +- src/pkcs15init/pkcs15-openpgp.c | 6 +++--- src/tools/cryptoflex-tool.c | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c index f3d79477..39e46f40 100644 --- a/src/libopensc/card-epass2003.c +++ b/src/libopensc/card-epass2003.c @@ -227,7 +227,7 @@ des3_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8], static int -des3_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8], +des3_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH], const unsigned char *input, size_t length, unsigned char *output) { unsigned char bKey[24] = { 0 }; diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 2e5f9c68..f9181ae3 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -305,8 +305,8 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, u8 *out, size_t *outlen) { const sc_acl_entry_t *read, *update, *delete, *generate; - u8 buf[40]; - int i; + u8 buf[41]; + size_t i; LOG_FUNC_CALLED(card->ctx); /* PrivateKey @@ -412,7 +412,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, buf[25] = 0x84; buf[26] = (u8)file->namelen; - for(i=0;i < (int)file->namelen;i++) + for(i=0;i < file->namelen;i++) buf[i + 26] = file->name[i]; buf[1] = 0x19 + file->namelen + 2; diff --git a/src/libopensc/card-setcos.c b/src/libopensc/card-setcos.c index eb9e936b..15da346e 100644 --- a/src/libopensc/card-setcos.c +++ b/src/libopensc/card-setcos.c @@ -438,7 +438,7 @@ static int setcos_create_file_44(sc_card_t *card, sc_file_t *file) const int* p_idx; int i; int len = 0; - u8 bBuf[32]; + u8 bBuf[64]; /* Get specific operation groups for specified file-type */ switch (file->type){ diff --git a/src/libopensc/ctbcs.c b/src/libopensc/ctbcs.c index 3dc773df..04420421 100644 --- a/src/libopensc/ctbcs.c +++ b/src/libopensc/ctbcs.c @@ -45,7 +45,7 @@ ctbcs_build_perform_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *d { const char *prompt; size_t buflen, count = 0, j = 0, len; - static u8 buf[254]; + static u8 buf[256]; u8 control; ctbcs_init_apdu(apdu, @@ -113,7 +113,7 @@ ctbcs_build_modify_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *da { const char *prompt; size_t buflen, count = 0, j = 0, len; - static u8 buf[254]; + static u8 buf[256]; u8 control; ctbcs_init_apdu(apdu, diff --git a/src/pkcs15init/pkcs15-asepcos.c b/src/pkcs15init/pkcs15-asepcos.c index 310c6f92..ddc72f52 100644 --- a/src/pkcs15init/pkcs15-asepcos.c +++ b/src/pkcs15init/pkcs15-asepcos.c @@ -510,7 +510,7 @@ static int asepcos_do_create_key(sc_card_t *card, size_t ksize, int fileid, int r; size_t len; sc_file_t *nfile = NULL; - u8 buf[512], *p = buf; + u8 buf[1024], *p = buf; if (sizeof(buf) < kdlen + 11) return SC_ERROR_BUFFER_TOO_SMALL; diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index f3a49621..4da415fe 100755 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -187,7 +187,7 @@ static int openpgp_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card /* The OpenPGP supports only 32-bit exponent. */ key_info.exponent_len = 32; - key_info.exponent = calloc(4, 1); + key_info.exponent = calloc(key_info.exponent_len>>3, 1); /* 1/8 */ if (key_info.exponent == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY); @@ -204,10 +204,10 @@ static int openpgp_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card sc_log(ctx, "Set output exponent info"); pubkey->u.rsa.exponent.len = key_info.exponent_len; - pubkey->u.rsa.exponent.data = calloc(key_info.exponent_len, 1); + pubkey->u.rsa.exponent.data = calloc(key_info.exponent_len>>3, 1); /* 1/8 */ if (pubkey->u.rsa.exponent.data == NULL) goto out; - memcpy(pubkey->u.rsa.exponent.data, key_info.exponent, key_info.exponent_len); + memcpy(pubkey->u.rsa.exponent.data, key_info.exponent, key_info.exponent_len>>3); /* 1/8 */ out: if (key_info.modulus) diff --git a/src/tools/cryptoflex-tool.c b/src/tools/cryptoflex-tool.c index fbc83b77..ea1e6a43 100644 --- a/src/tools/cryptoflex-tool.c +++ b/src/tools/cryptoflex-tool.c @@ -716,7 +716,7 @@ static int encode_private_key(RSA *rsa, u8 *key, size_t *keysize) static int encode_public_key(RSA *rsa, u8 *key, size_t *keysize) { - u8 buf[512], *p = buf; + u8 buf[1024], *p = buf; u8 bnbuf[256]; int base = 0; int r; From 08fcfcc8f0b4b3c7a987b25d22430acbe8868975 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:04:02 +0100 Subject: [PATCH 054/306] fixed wrong sizeof argument --- src/tools/sc-hsm-tool.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index e9d7f474..f0f56aeb 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -62,6 +62,8 @@ static int verbose = 0; #define MAX_KEY 1024 #define MAX_WRAPPED_KEY (MAX_CERT + MAX_PRKD + MAX_KEY) +#define SEED_LENGTH 16 + enum { OPT_SO_PIN = 0x100, OPT_PIN, @@ -139,14 +141,15 @@ static sc_card_t *card = NULL; * @param s Secret to share * @param n Maximum number of shares * @param rngSeed Seed value for CPRNG + * @param rngSeedLength Lenght of Seed value for CPRNG * */ -static void generatePrime(BIGNUM *prime, const BIGNUM *s, const unsigned int n, unsigned char *rngSeed) +static void generatePrime(BIGNUM *prime, const BIGNUM *s, const unsigned int n, unsigned char *rngSeed, const unsigned int rngSeedLength) { int bits = 0; // Seed the RNG - RAND_seed(rngSeed, sizeof(rngSeed)); + RAND_seed(rngSeed, rngSeedLength); // Determine minimum number of bits for prime >= max(2^r, n + 1) bits = BN_num_bits_word(n + 1) > BN_num_bits(s) ? (BN_num_bits_word(n + 1)) : (BN_num_bits(s)); @@ -851,7 +854,7 @@ static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int pas /* * Generate seed and calculate a prime depending on the size of the secret */ - r = sc_get_challenge(card, rngseed, 16); + r = sc_get_challenge(card, rngseed, SEED_LENGTH); if (r < 0) { printf("Error generating random seed failed with %s", sc_strerror(r)); OPENSSL_cleanse(*pwd, *pwdlen); @@ -859,7 +862,7 @@ static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int pas return r; } - generatePrime(&prime, &secret, password_shares_total, rngseed); + generatePrime(&prime, &secret, password_shares_total, rngseed, SEED_LENGTH); // Allocate data buffer for the generated shares shares = malloc(password_shares_total * sizeof(secret_share_t)); From b9f1fb333ccc2a3fbdc3d351c4253310e32720dc Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:07:33 +0100 Subject: [PATCH 055/306] fixed bad output data length --- src/libopensc/muscle.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libopensc/muscle.c b/src/libopensc/muscle.c index ef9322f2..29a2f562 100644 --- a/src/libopensc/muscle.c +++ b/src/libopensc/muscle.c @@ -662,8 +662,7 @@ int msc_compute_crypt_init(sc_card_t *card, SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { short receivedData = outputBuffer[0] << 8 | outputBuffer[1]; - *outputDataLength = receivedData; - *outputDataLength = 0; + *outputDataLength = receivedData; assert(receivedData <= MSC_MAX_APDU); memcpy(outputData, outputBuffer + 2, receivedData); From ac0424e947098a65a011368f1e13242aa0416e6b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:09:02 +0100 Subject: [PATCH 056/306] fixed pkcs11spy's version number --- src/pkcs11/pkcs11-spy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkcs11/pkcs11-spy.c b/src/pkcs11/pkcs11-spy.c index 1dab64da..49a6116c 100644 --- a/src/pkcs11/pkcs11-spy.c +++ b/src/pkcs11/pkcs11-spy.c @@ -68,7 +68,7 @@ init_spy(void) if (pkcs11_spy) { /* with our own pkcs11.h we need to maintain this ourself */ pkcs11_spy->version.major = 2; - pkcs11_spy->version.major = 11; + pkcs11_spy->version.minor = 11; pkcs11_spy->C_Initialize = C_Initialize; pkcs11_spy->C_Finalize = C_Finalize; pkcs11_spy->C_GetInfo = C_GetInfo; From 7fb495ac314b97e4196732a5b0bc6b789afdc2c7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:10:57 +0100 Subject: [PATCH 057/306] fixed self assignment --- src/pkcs15init/profile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c index 433c7ae4..9f87fc9c 100644 --- a/src/pkcs15init/profile.c +++ b/src/pkcs15init/profile.c @@ -507,7 +507,6 @@ sc_profile_get_pin_info(struct sc_profile *profile, if (pi == NULL) return; - pi->pin.tries_left = pi->pin.tries_left; pi->pin.max_tries = pi->pin.tries_left; *info = pi->pin; } From 92ad6eb63c5d32ac12331f2f8d13780f1b8a75e5 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:21:55 +0100 Subject: [PATCH 058/306] fixed determining ef type --- src/libopensc/card-dnie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 9359de33..53ce7281 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -1746,7 +1746,7 @@ static int dnie_process_fci(struct sc_card *card, case 0x15: /* EF for keys: linear variable simple TLV */ file->type = SC_FILE_TYPE_WORKING_EF; /* pin file 3F000000 has also this EF type */ - if ( ( file->prop_attr[3] == 0x00 ) && (file->prop_attr[3] == 0x00 ) ) { + if ( ( file->prop_attr[2] == 0x00 ) && (file->prop_attr[3] == 0x00 ) ) { sc_log(ctx,"Processing pin EF"); break; } From 3a557ad0dddcd89e569ef69c048ceae8955974a7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:22:03 +0100 Subject: [PATCH 059/306] fixed parsing pace output data --- src/libopensc/reader-pcsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index da65c3fb..46ef81f3 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -1797,7 +1797,7 @@ static int transform_pace_output(u8 *rbuf, size_t rbuflen, if (parsed+2 > rbuflen) return SC_ERROR_UNKNOWN_DATA_RECEIVED; pace_output->mse_set_at_sw1 = rbuf[parsed+0]; - pace_output->mse_set_at_sw1 = rbuf[parsed+1]; + pace_output->mse_set_at_sw2 = rbuf[parsed+1]; parsed += 2; /* length_CardAccess */ From 734cb67924be16d0d03a8dadd92043e1f4396fd4 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:23:34 +0100 Subject: [PATCH 060/306] fixed algo ref --- src/libopensc/card-gemsafeV1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-gemsafeV1.c b/src/libopensc/card-gemsafeV1.c index 7b6b87b8..9c6816b6 100644 --- a/src/libopensc/card-gemsafeV1.c +++ b/src/libopensc/card-gemsafeV1.c @@ -369,7 +369,7 @@ static u8 gemsafe_flags2algref(struct sc_card *card, const struct sc_security_en } else if (env->operation == SC_SEC_OPERATION_DECIPHER) { if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) ret = (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID || - card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) ? 0x02 : 0x12; + card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) ? 0x02 : 0x12; } return ret; From b94c16394f89b78f9d43ecd7a8fb25f3e25b842e Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:25:46 +0100 Subject: [PATCH 061/306] card-asepcos: fixed puk handling --- src/libopensc/card-asepcos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-asepcos.c b/src/libopensc/card-asepcos.c index 855c53a1..433c28fd 100644 --- a/src/libopensc/card-asepcos.c +++ b/src/libopensc/card-asepcos.c @@ -872,8 +872,8 @@ static int asepcos_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu, memcpy(p, data->pin1.data, data->pin1.len); p += data->pin1.len; } else { - memcpy(p, data->pin1.data, data->pin1.len); - p += data->pin1.len; + memcpy(p, data->pin2.data, data->pin2.len); + p += data->pin2.len; } apdu->lc = p - buf; apdu->datalen = p - buf; From bd3cfcf5ef9770535369f679351d256a8c1e8a6d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:26:34 +0100 Subject: [PATCH 062/306] fixed copy/paste error --- src/libopensc/iso7816.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index ab901fbe..85062651 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -657,7 +657,7 @@ iso7816_construct_fci(struct sc_card *card, const sc_file_t *file, p, *outlen - (p - out), &p); } if (file->sec_attr_len) { - assert(sizeof(buf) >= file->prop_attr_len); + assert(sizeof(buf) >= file->sec_attr_len); memcpy(buf, file->sec_attr, file->sec_attr_len); sc_asn1_put_tag(0x86, buf, file->sec_attr_len, p, *outlen - (p - out), &p); From 2e04fa99c11c47b2c5c7f5b4bd5474bc310e51ad Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 07:39:35 +0100 Subject: [PATCH 063/306] fixed pointless array comparisons --- src/libopensc/card-openpgp.c | 2 +- src/libopensc/card-piv.c | 2 -- src/libopensc/card-tcos.c | 2 -- src/pkcs15init/pkcs15-oberthur-awp.c | 12 ++++-------- src/tools/pkcs11-tool.c | 4 ++-- src/tools/pkcs15-init.c | 5 ++--- src/tools/pkcs15-tool.c | 2 +- 7 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 6774fe17..1e0773aa 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -883,7 +883,7 @@ static unsigned int pgp_strip_path(sc_card_t *card, const sc_path_t *path) { unsigned int start_point = 0; /* start_point will move through the path string */ - if (path->value == NULL || path->len == 0) + if (path->len == 0) return 0; /* Ignore 3F00 (MF) at the beginning */ diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index b1996541..ca3ebe44 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -784,8 +784,6 @@ static int piv_find_aid(sc_card_t * card, sc_file_t *aid_file) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NO_CARD_SUPPORT); card->ops->process_fci(card, aid_file, apdu.resp+2, apdu.resp[1]); - if (aid_file->name == NULL) - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NO_CARD_SUPPORT); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, i); } diff --git a/src/libopensc/card-tcos.c b/src/libopensc/card-tcos.c index d6362a38..e41db406 100644 --- a/src/libopensc/card-tcos.c +++ b/src/libopensc/card-tcos.c @@ -161,8 +161,6 @@ static int tcos_construct_fci(const sc_file_t *file, /* Directory name */ if (file->type == SC_FILE_TYPE_DF) { if (file->namelen) { - if (file->namelen > 16 || !file->name) - return SC_ERROR_INVALID_ARGUMENTS; sc_asn1_put_tag(0x84, file->name, file->namelen, p, 16, &p); } diff --git a/src/pkcs15init/pkcs15-oberthur-awp.c b/src/pkcs15init/pkcs15-oberthur-awp.c index aa4e20a1..eb0642e5 100644 --- a/src/pkcs15init/pkcs15-oberthur-awp.c +++ b/src/pkcs15init/pkcs15-oberthur-awp.c @@ -782,10 +782,8 @@ awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj if (obj->type == COSM_TYPE_PUBKEY_RSA || obj->type == COSM_TYPE_PRKEY_RSA) ki->flags |= COSM_GENERATED; - if (obj->label) { - ki->label.value = (unsigned char *)strdup(obj->label); - ki->label.len = strlen(obj->label); - } + ki->label.value = (unsigned char *)strdup(obj->label); + ki->label.len = strlen(obj->label); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "cosm_encode_key_info() label(%i):%s",ki->label.len, ki->label.value); /* @@ -1088,10 +1086,8 @@ awp_encode_data_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *ob di->flags = 0x0000; - if (obj->label) { - di->label.value = (unsigned char *)strdup(obj->label); - di->label.len = strlen(obj->label); - } + di->label.value = (unsigned char *)strdup(obj->label); + di->label.len = strlen(obj->label); di->app.len = strlen(data_info->app_label); if (di->app.len) { diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 0d00c4a4..9a445896 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4217,7 +4217,7 @@ static void test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session) return; tmp = getID(session, priv_key, (CK_ULONG *) &opt_object_id_len); - if (opt_object_id == NULL || opt_object_id_len == 0) { + if (opt_object_id_len == 0) { printf("ERR: newly generated private key has no (or an empty) CKA_ID\n"); return; } @@ -4372,7 +4372,7 @@ static void test_ec(CK_SLOT_ID slot, CK_SESSION_HANDLE session) return; tmp = getID(session, priv_key, (CK_ULONG *) &opt_object_id_len); - if (opt_object_id == NULL || opt_object_id_len == 0) { + if (opt_object_id_len == 0) { printf("ERR: newly generated private key has no (or an empty) CKA_ID\n"); return; } diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 81d883c8..c3d6818e 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -1010,8 +1010,7 @@ is_cacert_already_present(struct sc_pkcs15init_certargs *args) if (!cinfo->authority) continue; - if (args->label && objs[i]->label - && strcmp(args->label, objs[i]->label)) + if (strcmp(args->label, objs[i]->label)) continue; /* XXX we should also match the usage field here */ @@ -2839,7 +2838,7 @@ static int verify_pin(struct sc_pkcs15_card *p15card, char *auth_id_str) if (opt_no_prompt) return SC_ERROR_OBJECT_NOT_FOUND; - if (pin_obj->label) + if (0 < strnlen(pin_obj->label, sizeof pin_obj->label)) snprintf(pin_label, sizeof(pin_label), "User PIN [%s]", pin_obj->label); else snprintf(pin_label, sizeof(pin_label), "User PIN"); diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 8c980bb6..3a4fe622 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -455,7 +455,7 @@ static int list_data_objects(void) int idx; struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data; - if (objs[i]->label) + if (0 < strnlen(objs[i]->label, sizeof objs[i]->label)) printf("Data object '%s'\n", objs[i]->label); else printf("Data object <%i>\n", i); From 6759c04b26127b62fbe01f368daa764e94ffe08d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 28 Jan 2015 04:45:08 +0100 Subject: [PATCH 064/306] don't ignore errors --- src/libopensc/card-iasecc.c | 3 ++- src/libopensc/card-mcrd.c | 8 +++++--- src/libopensc/card-muscle.c | 4 +++- src/libopensc/card-oberthur.c | 3 ++- src/libopensc/card-piv.c | 12 +++++++----- src/libopensc/pkcs15-cache.c | 6 ++++-- src/libopensc/pkcs15-dnie.c | 4 +++- src/libopensc/pkcs15-sc-hsm.c | 9 ++++++--- src/libopensc/pkcs15-syn.c | 6 +++++- src/libopensc/pkcs15.c | 3 ++- src/libopensc/reader-pcsc.c | 10 +++++++--- src/pkcs11/framework-pkcs15.c | 10 ++++++---- src/pkcs15init/pkcs15-lib.c | 3 ++- src/tests/lottery.c | 8 ++++++-- src/tests/p15dump.c | 18 ++++++++++++------ src/tests/pintest.c | 22 ++++++++++++++++------ src/tools/openpgp-tool.c | 2 ++ src/tools/piv-tool.c | 12 +++++++++--- src/tools/pkcs11-tool.c | 3 ++- 19 files changed, 101 insertions(+), 45 deletions(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 318ff548..776bcf5a 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -414,7 +414,8 @@ iasecc_init_gemalto(struct sc_card *card) card->caps |= SC_CARD_CAP_USE_FCI_AC; sc_format_path("3F00", &path); - sc_select_file(card, &path, NULL); + rv = sc_select_file(card, &path, NULL); + LOG_TEST_RET(ctx, rv, "MF selection error"); rv = iasecc_parse_ef_atr(card); sc_log(ctx, "rv %i", rv); diff --git a/src/libopensc/card-mcrd.c b/src/libopensc/card-mcrd.c index 52d710f9..1f469b06 100644 --- a/src/libopensc/card-mcrd.c +++ b/src/libopensc/card-mcrd.c @@ -379,13 +379,13 @@ static int mcrd_init(sc_card_t * card) priv->curpathlen = 1; sc_format_path ("3f00", &tmppath); - sc_select_file (card, &tmppath, NULL); + r = sc_select_file (card, &tmppath, NULL); /* Not needed for the fixed EstEID profile */ if (!is_esteid_card(card)) load_special_files(card); - return SC_SUCCESS; + return r; } static int mcrd_finish(sc_card_t * card) @@ -1188,7 +1188,9 @@ static int mcrd_set_security_env(sc_card_t * card, /* Make sure we always start from MF */ sc_format_path ("3f00", &tmppath); - sc_select_file (card, &tmppath, NULL); + r = sc_select_file (card, &tmppath, NULL); + if (r < 0) + return r; /* We now know that cache is not valid */ select_esteid_df(card); switch (env->operation) { diff --git a/src/libopensc/card-muscle.c b/src/libopensc/card-muscle.c index 31304b8f..81a482e5 100644 --- a/src/libopensc/card-muscle.c +++ b/src/libopensc/card-muscle.c @@ -472,7 +472,9 @@ static int muscle_init(sc_card_t *card) card->caps |= SC_CARD_CAP_RNG; /* Card type detection */ - _sc_match_atr(card, muscle_atrs, &card->type); + if (SC_SUCCESS != _sc_match_atr(card, muscle_atrs, &card->type)) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD); + if(card->type == SC_CARD_TYPE_MUSCLE_ETOKEN_72K) { card->caps |= SC_CARD_CAP_APDU_EXT; } diff --git a/src/libopensc/card-oberthur.c b/src/libopensc/card-oberthur.c index eb0820b1..f6a4d335 100644 --- a/src/libopensc/card-oberthur.c +++ b/src/libopensc/card-oberthur.c @@ -397,7 +397,8 @@ auth_process_fci(struct sc_card *card, struct sc_file *file, case 0x38: file->type = SC_FILE_TYPE_DF; file->size = attr[0]; - sc_file_set_type_attr(file,attr,attr_len); + if (SC_SUCCESS != sc_file_set_type_attr(file,attr,attr_len)) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED); break; default: SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED); diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index ca3ebe44..21f83934 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -1557,7 +1557,7 @@ static int piv_general_mutual_authenticate(sc_card_t *card, r = sc_lock(card); if (r != SC_SUCCESS) - goto err; + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); locked = 1; p = sbuf; @@ -1827,7 +1827,7 @@ static int piv_general_external_authenticate(sc_card_t *card, r = sc_lock(card); if (r != SC_SUCCESS) - goto err; + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); locked = 1; p = sbuf; @@ -2141,7 +2141,9 @@ static int piv_get_challenge(sc_card_t *card, u8 *rnd, size_t len) sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"challenge len=%d",len); - sc_lock(card); + r = sc_lock(card); + if (r != SC_SUCCESS) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); p = sbuf; *p++ = 0x7c; @@ -2177,9 +2179,9 @@ static int piv_get_challenge(sc_card_t *card, u8 *rnd, size_t len) rbuf = NULL; } - sc_unlock(card); + r = sc_unlock(card); - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, 0); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); } diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c index 2e18bf9f..b0c8269d 100644 --- a/src/libopensc/pkcs15-cache.c +++ b/src/libopensc/pkcs15-cache.c @@ -112,8 +112,10 @@ int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, free(data); return SC_ERROR_FILE_NOT_FOUND; } - if (offset) - fseek(f, (long)offset, SEEK_SET); + if (offset) { + if (0 != fseek(f, (long)offset, SEEK_SET)) + return SC_ERROR_FILE_NOT_FOUND; + } if (data) *buf = data; got = fread(*buf, 1, count, f); diff --git a/src/libopensc/pkcs15-dnie.c b/src/libopensc/pkcs15-dnie.c index 1a98260d..acfce590 100644 --- a/src/libopensc/pkcs15-dnie.c +++ b/src/libopensc/pkcs15-dnie.c @@ -41,7 +41,9 @@ int dump_ef(sc_card_t * card, const char *path, u8 * buf, size_t * buf_len) int rv; sc_file_t *file = sc_file_new(); sc_format_path(path, &file->path); - sc_select_file(card, &file->path, &file); + rv = sc_select_file(card, &file->path, &file); + if (rv < 0) + return rv; if (file->size > *buf_len) return SC_ERROR_BUFFER_TOO_SMALL; rv = sc_read_binary(card, 0, buf, file->size, 0); diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index 0266637d..5e5fa570 100644 --- a/src/libopensc/pkcs15-sc-hsm.c +++ b/src/libopensc/pkcs15-sc-hsm.c @@ -504,9 +504,12 @@ static int sc_pkcs15emu_sc_hsm_add_pubkey(sc_pkcs15_card_t *p15card, sc_pkcs15_p memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); - sc_pkcs15_encode_pubkey(ctx, &pubkey, &pubkey_obj.content.value, &pubkey_obj.content.len); - sc_pkcs15_encode_pubkey(ctx, &pubkey, &pubkey_info.direct.raw.value, &pubkey_info.direct.raw.len); - sc_pkcs15_encode_pubkey_as_spki(ctx, &pubkey, &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len); + r = sc_pkcs15_encode_pubkey(ctx, &pubkey, &pubkey_obj.content.value, &pubkey_obj.content.len); + LOG_TEST_RET(ctx, r, "Could not encode public key"); + r = sc_pkcs15_encode_pubkey(ctx, &pubkey, &pubkey_info.direct.raw.value, &pubkey_info.direct.raw.len); + LOG_TEST_RET(ctx, r, "Could not encode public key"); + r = sc_pkcs15_encode_pubkey_as_spki(ctx, &pubkey, &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len); + LOG_TEST_RET(ctx, r, "Could not encode public key"); pubkey_info.id = key_info->id; strlcpy(pubkey_obj.label, label, sizeof(pubkey_obj.label)); diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index ffbf642d..3ebbd633 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -271,7 +271,11 @@ static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf) /* try to get version of the driver/api */ get_version = (const char *(*)(void)) sc_dlsym(handle, "sc_driver_version"); if (get_version) { - sscanf(get_version(), "%u.%u.%u", &major, &minor, &fix); + if (3 != sscanf(get_version(), "%u.%u.%u", &major, &minor, &fix)) { + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, + "unable to get modules version number\n"); + return SC_ERROR_INTERNAL; + } } if (!get_version || (major == 0 && minor <= 9 && fix < 3) < 0) { diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 5219ae5b..caa7a598 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -1311,7 +1311,8 @@ __sc_pkcs15_search_objects(struct sc_pkcs15_card *p15card, unsigned int class_ma /* Enumerate the DF's, so p15card->obj_list is * populated. */ /* FIXME dont ignore errors */ - sc_pkcs15_parse_df(p15card, df); + if (SC_SUCCESS != sc_pkcs15_parse_df(p15card, df)) + continue; } /* And now loop over all objects */ diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 46ef81f3..a54e2a8f 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -781,9 +781,13 @@ static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader) goto err; if (priv->pace_ioctl) { - pcsc_internal_transmit(reader, pace_capabilities_buf, - sizeof pace_capabilities_buf, rbuf, &rcount, - priv->pace_ioctl); + if (0 > pcsc_internal_transmit(reader, pace_capabilities_buf, + sizeof pace_capabilities_buf, rbuf, &rcount, + priv->pace_ioctl)) { + sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, + "PC/SC v2 part 10 amd1: Get PACE properties failed!"); + goto err; + } if (rcount != 7) goto err; diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 45a57d7e..ff198e64 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -867,7 +867,7 @@ check_cert_data_read(struct pkcs15_fw_data *fw_data, struct pkcs15_cert_object * /* now that we have the cert and pub key, lets see if we can bind anything else */ pkcs15_bind_related_objects(fw_data); - return 0; + return rv; } @@ -2087,7 +2087,9 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile return rv; /* CKA_TOKEN defaults to false */ - attr_find(pTemplate, ulCount, CKA_TOKEN, &_token, NULL); + rv = attr_find(pTemplate, ulCount, CKA_TOKEN, &_token, NULL); + if (rv != CKR_OK) + return rv; switch (key_type) { /* Only support GENERIC_SECRET for now */ @@ -3847,8 +3849,8 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ case CKA_EC_PARAMS: case CKA_EC_POINT: if (pubkey->pub_data == NULL) - /* FIXME: check the return value? */ - check_cert_data_read(fw_data, cert); + if (SC_SUCCESS != check_cert_data_read(fw_data, cert)) + return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "check_cert_data_read"); break; } diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 5e61399f..7f01e455 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -2673,7 +2673,8 @@ sc_pkcs15init_update_any_df(struct sc_pkcs15_card *p15card, int update_odf = is_new, r = 0; LOG_FUNC_CALLED(ctx); - sc_profile_get_file_by_path(profile, &df->path, &file); + r = sc_profile_get_file_by_path(profile, &df->path, &file); + LOG_TEST_RET(ctx, r, "Failed get file path"); if (file == NULL) sc_select_file(card, &df->path, &file); diff --git a/src/tests/lottery.c b/src/tests/lottery.c index ecbce269..cfd0cc57 100644 --- a/src/tests/lottery.c +++ b/src/tests/lottery.c @@ -32,8 +32,12 @@ int main(int argc, char *argv[]) for (i = 0; i < 39; i++) { nbuf[i] = i + 1; } - if (c == 0) - gettimeofday(&tv1, NULL); + if (c == 0) { + if (0 != gettimeofday(&tv1, NULL)) { + fprintf(stderr, "gettimeofday() failed: %s\n", sc_strerror(r)); + return 1; + } + } sc_lock(card); r = sc_get_challenge(card, buf, 14); sc_unlock(card); diff --git a/src/tests/p15dump.c b/src/tests/p15dump.c index 433f5db7..24f19fcd 100644 --- a/src/tests/p15dump.c +++ b/src/tests/p15dump.c @@ -23,18 +23,21 @@ static int dump_objects(const char *what, int type) printf("\nEnumerating %s... ", what); fflush(stdout); - sc_lock(card); + if (SC_SUCCESS != sc_lock(card)) + return 1; count = sc_pkcs15_get_objects(p15card, type, NULL, 0); if (count < 0) { printf("failed.\n"); fprintf(stderr, "Error enumerating %s: %s\n", what, sc_strerror(count)); - sc_unlock(card); + if (SC_SUCCESS != sc_unlock(card)) + return 1; return 1; } if (count == 0) { printf("none found.\n"); - sc_unlock(card); + if (SC_SUCCESS != sc_unlock(card)) + return 1; return 0; } printf("%u found.\n", count); @@ -48,7 +51,8 @@ static int dump_objects(const char *what, int type) sc_test_print_object(objs[i]); } free(objs); - sc_unlock(card); + if (SC_SUCCESS != sc_unlock(card)) + return 1; return (count < 0) ? 1 : 0; } @@ -111,7 +115,8 @@ int main(int argc, char *argv[]) return 1; printf("Looking for a PKCS#15 compatible Smart Card... "); fflush(stdout); - sc_lock(card); + if (SC_SUCCESS != sc_lock(card)) + return 1; i = sc_pkcs15_bind(card, NULL, &p15card); /* Keep card locked to prevent useless calls to sc_logout */ if (i) { @@ -129,7 +134,8 @@ int main(int argc, char *argv[]) dump_unusedspace(); sc_pkcs15_unbind(p15card); - sc_unlock(card); + if (SC_SUCCESS != sc_unlock(card)) + return 1; sc_test_cleanup(); return 0; } diff --git a/src/tests/pintest.c b/src/tests/pintest.c index d913a726..e0bb0ec3 100644 --- a/src/tests/pintest.c +++ b/src/tests/pintest.c @@ -36,6 +36,10 @@ static int enum_pins(struct sc_pkcs15_object ***ret) return 0; } objs = calloc(n, sizeof(*objs)); + if (!objs) { + fprintf(stderr, "Not enough memory!\n"); + return 1; + } sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, n); for (i = 0; i < n; i++) { sc_test_print_object(objs[i]); @@ -59,9 +63,11 @@ static int ask_and_verify_pin(struct sc_pkcs15_object *pin_obj) sprintf(prompt, "Please enter PIN code [%s]: ", pin_obj->label); pass = (u8 *) getpass(prompt); - sc_lock(card); + if (SC_SUCCESS != sc_lock(card)) + return 1; i = sc_pkcs15_verify_pin(p15card, pin_obj, pass, strlen((char *) pass)); - sc_unlock(card); + if (SC_SUCCESS != sc_unlock(card)) + return 1; if (i) { if (i == SC_ERROR_PIN_CODE_INCORRECT) fprintf(stderr, @@ -90,9 +96,11 @@ int main(int argc, char *argv[]) printf("Slot is capable of doing pinpad operations!\n"); printf("Looking for a PKCS#15 compatible Smart Card... "); fflush(stdout); - sc_lock(card); + if (SC_SUCCESS != sc_lock(card)) + return 1; i = sc_pkcs15_bind(card, NULL, &p15card); - sc_unlock(card); + if (SC_SUCCESS != sc_unlock(card)) + return 1; if (i) { fprintf(stderr, "failed: %s\n", sc_strerror(i)); sc_test_cleanup(); @@ -100,9 +108,11 @@ int main(int argc, char *argv[]) } printf("found.\n"); printf("Enumerating PIN codes...\n"); - sc_lock(card); + if (SC_SUCCESS != sc_lock(card)) + return 1; count = enum_pins(&objs); - sc_unlock(card); + if (SC_SUCCESS != sc_unlock(card)) + return 1; if (count < 0) { sc_pkcs15_unbind(p15card); sc_test_cleanup(); diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index a03fd375..fd9f4b3a 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -370,6 +370,8 @@ static int do_dump_do(sc_card_t *card, unsigned int tag) if(opt_raw) { r = 0; tmp = dup(fileno(stdout)); + if (tmp < 0) + return EXIT_FAILURE; fp = freopen(NULL, "wb", stdout); if(fp) { r = fwrite(buffer, sizeof(char), sizeof(buffer), fp); diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index 596b5a44..d0a6ba8e 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -119,7 +119,10 @@ static int load_object(const char * object_id, const char * object_file) return -1; } - stat(object_file, &stat_buf); + if (0 != stat(object_file, &stat_buf)) { + printf("unable to read file %s\n",object_file); + return -1; + } derlen = stat_buf.st_size; der = malloc(derlen); if (der == NULL) { @@ -173,13 +176,16 @@ static int load_cert(const char * cert_id, const char * cert_file, if (compress) { /* file is gziped already */ struct stat stat_buf; - stat(cert_file, &stat_buf); + if (0 != stat(cert_file, &stat_buf)) { + printf("unable to read file %s\n",cert_file); + return -1; + } derlen = stat_buf.st_size; der = malloc(derlen); if (der == NULL) { printf("file %s is too big, %lu\n", cert_file, (unsigned long)derlen); - return-1 ; + return -1 ; } if (1 != fread(der, derlen, 1, fp)) { printf("unable to read file %s\n",cert_file); diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 9a445896..6eabea7d 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -3846,7 +3846,8 @@ static int wrap_unwrap(CK_SESSION_HANDLE session, return 1; } - EVP_DecryptInit(&seal_ctx, algo, key, iv); + if (!EVP_DecryptInit(&seal_ctx, algo, key, iv)) + return 1; len = sizeof(cleartext); EVP_DecryptUpdate(&seal_ctx, cleartext, &len, ciphered, ciphered_len); From 8e9a2361c6819b7ac991acfe8034a2d8f14dfe70 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Mon, 2 Feb 2015 16:24:16 +0100 Subject: [PATCH 065/306] pkcs15-tool: print length of EC public key when this key is read from dedicated EF --- src/tools/pkcs15-tool.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 603a7534..9e9bd4ab 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -589,6 +589,7 @@ static void print_pubkey_info(const struct sc_pkcs15_object *obj) "neverExtract", "local" }; const unsigned int af_count = NELEMENTS(access_flags); + int have_path = (pubkey->path.len != 0) || (pubkey->path.aid.len != 0); printf("Public %s Key [%s]\n", types[7 & obj->type], obj->label); print_common_flags(obj); @@ -607,18 +608,29 @@ static void print_pubkey_info(const struct sc_pkcs15_object *obj) print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); - if (pubkey->modulus_length) + if (pubkey->modulus_length) { printf("\tModLength : %lu\n", (unsigned long)pubkey->modulus_length); - else - printf("\tFieldLength : %lu\n", (unsigned long)pubkey->field_length); + } + else if (pubkey->field_length) { + printf("\tFieldLength : %lu\n", (unsigned long)pubkey->field_length); + } + else if (obj->type == SC_PKCS15_TYPE_PUBKEY_EC && have_path) { + sc_pkcs15_pubkey_t *pkey = NULL; + if (!sc_pkcs15_read_pubkey(p15card, obj, &pkey)) { + printf("\tFieldLength : %lu\n", (unsigned long)pkey->u.ec.params.field_length); + sc_pkcs15_free_pubkey(pkey); + } + } + printf("\tKey ref : %d (0x%X)\n", pubkey->key_reference, pubkey->key_reference); printf("\tNative : %s\n", pubkey->native ? "yes" : "no"); - if (pubkey->path.len || pubkey->path.aid.len) + if (have_path) printf("\tPath : %s\n", sc_print_path(&pubkey->path)); if (obj->auth_id.len != 0) printf("\tAuth ID : %s\n", sc_pkcs15_print_id(&obj->auth_id)); printf("\tID : %s\n", sc_pkcs15_print_id(&pubkey->id)); - printf("\tDirectValue : <%s>\n", obj->content.len ? "present" : "absent"); + if (!have_path || obj->content.len) + printf("\tDirectValue : <%s>\n", obj->content.len ? "present" : "absent"); } static int list_public_keys(void) From 3047fe2c3b366c6e15f256e3a604f03c77779413 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Mon, 2 Feb 2015 16:25:54 +0100 Subject: [PATCH 066/306] log: implement 'dump OID' --- src/libopensc/log.c | 14 ++++++++++++++ src/libopensc/log.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libopensc/log.c b/src/libopensc/log.c index 70b67824..32f396d8 100644 --- a/src/libopensc/log.c +++ b/src/libopensc/log.c @@ -235,3 +235,17 @@ sc_dump_hex(const u8 * in, size_t count) return dump_buf; } + +char * +sc_dump_oid(const struct sc_object_id *oid) +{ + static char dump_buf[SC_MAX_OBJECT_ID_OCTETS * 20]; + size_t ii; + + memset(dump_buf, 0, sizeof(dump_buf)); + if (oid) + for (ii=0; iivalue[ii] != -1; ii++) + snprintf(dump_buf + strlen(dump_buf), sizeof(dump_buf) - strlen(dump_buf), "%s%i", (ii ? "." : ""), oid->value[ii]); + + return dump_buf; +} diff --git a/src/libopensc/log.h b/src/libopensc/log.h index d9b9c438..ccacefd5 100644 --- a/src/libopensc/log.h +++ b/src/libopensc/log.h @@ -60,7 +60,7 @@ void _sc_log(struct sc_context *ctx, const char *format, ...); void sc_hex_dump(struct sc_context *ctx, int level, const u8 * buf, size_t len, char *out, size_t outlen); char * sc_dump_hex(const u8 * in, size_t count); - +char * sc_dump_oid(const struct sc_object_id *oid); #define SC_FUNC_CALLED(ctx, level) do { \ sc_do_log(ctx, level, __FILE__, __LINE__, __FUNCTION__, "called\n"); \ } while (0) From 6a7875c4af474a474816fccbf17bbf2aa028bc9f Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Feb 2015 00:21:41 +0100 Subject: [PATCH 067/306] use general travis-ci badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca03a8ac..47431bf4 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,5 @@ Coverity Scan: [![Coverity Scan Build Status](https://scan.coverity.com/projects/4011/badge.svg)](https://scan.coverity.com/projects/4026) Travis CI: -[![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png?branch=coverity_scan)](https://travis-ci.org/OpenSC/OpenSC) +[![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png)](https://travis-ci.org/OpenSC/OpenSC) From 44ed1a3d6b84da6bac473c12d24acfcd462f3b41 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Tue, 3 Feb 2015 09:27:16 +0100 Subject: [PATCH 068/306] readme.md: fix url of status icon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47431bf4..86d45363 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Please take a look at the documentation before trying to use OpenSC. Coverity Scan: -[![Coverity Scan Build Status](https://scan.coverity.com/projects/4011/badge.svg)](https://scan.coverity.com/projects/4026) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/4026/badge.svg)](https://scan.coverity.com/projects/4026) Travis CI: [![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png)](https://travis-ci.org/OpenSC/OpenSC) From 9cb4a09e302cbe4f4055aac194bb0b029d5fe528 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Tue, 3 Feb 2015 09:45:40 +0100 Subject: [PATCH 069/306] readme.md: add jenkins build status --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 86d45363..714ad043 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,12 @@ OpenSC documentation wiki is available online at Please take a look at the documentation before trying to use OpenSC. - Coverity Scan: [![Coverity Scan Build Status](https://scan.coverity.com/projects/4026/badge.svg)](https://scan.coverity.com/projects/4026) +Jenkins CI: +[![Build Status](https://opensc.fr/jenkins/buildStatus/icon?job=OpenSC-master)](https://opensc.fr/jenkins/view/OpenSC-master/job/OpenSC-master/) + Travis CI: [![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png)](https://travis-ci.org/OpenSC/OpenSC) From 53e1992cc2c51f2fe701be2fa258fd06cf51d101 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Feb 2015 00:26:56 +0100 Subject: [PATCH 070/306] use strerror for failure of gettimeofday --- src/tests/lottery.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tests/lottery.c b/src/tests/lottery.c index cfd0cc57..eab40364 100644 --- a/src/tests/lottery.c +++ b/src/tests/lottery.c @@ -4,6 +4,8 @@ #include "config.h" +#include +#include #include #include #ifdef HAVE_UNISTD_H @@ -34,7 +36,7 @@ int main(int argc, char *argv[]) } if (c == 0) { if (0 != gettimeofday(&tv1, NULL)) { - fprintf(stderr, "gettimeofday() failed: %s\n", sc_strerror(r)); + fprintf(stderr, "gettimeofday() failed: %s\n", strerror(errno)); return 1; } } From ac4da89d0dfebfbf87be3f4936daa42a0ebc6477 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Feb 2015 00:30:50 +0100 Subject: [PATCH 071/306] use memmove for overlapping memory --- src/libopensc/card-authentic.c | 2 +- src/libopensc/card-iasecc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-authentic.c b/src/libopensc/card-authentic.c index 737574cd..37204854 100644 --- a/src/libopensc/card-authentic.c +++ b/src/libopensc/card-authentic.c @@ -749,7 +749,7 @@ authentic_select_file(struct sc_card *card, const struct sc_path *path, rv = authentic_select_mf(card, file_out); LOG_TEST_RET(ctx, rv, "cannot select MF"); - memcpy(&lpath.value[0], &lpath.value[2], lpath.len - 2); + memmove(&lpath.value[0], &lpath.value[2], lpath.len - 2); lpath.len -= 2; if (!lpath.len) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 776bcf5a..e05e80e8 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -813,7 +813,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, LOG_TEST_RET(ctx, rv, "MF selection error"); if (lpath.len >= 2 && lpath.value[0] == 0x3F && lpath.value[1] == 0x00) { - memcpy(&lpath.value[0], &lpath.value[2], lpath.len - 2); + memmove(&lpath.value[0], &lpath.value[2], lpath.len - 2); lpath.len -= 2; } } From 5e3d54186ac5ca24b0d6181b13888787610ba019 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Feb 2015 00:31:55 +0100 Subject: [PATCH 072/306] removed useless check for non-null array --- src/pkcs15init/pkcs15-oberthur-awp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pkcs15init/pkcs15-oberthur-awp.c b/src/pkcs15init/pkcs15-oberthur-awp.c index eb0642e5..d6c6534b 100644 --- a/src/pkcs15init/pkcs15-oberthur-awp.c +++ b/src/pkcs15init/pkcs15-oberthur-awp.c @@ -941,10 +941,8 @@ awp_encode_cert_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *ob sc_pkcs15_print_id(&cert_info->id), obj->content.value, obj->content.len); memset(&pubkey, 0, sizeof(pubkey)); - if (obj->label) { - ci->label.value = (unsigned char *)strdup(obj->label); - ci->label.len = strlen(obj->label); - } + ci->label.value = (unsigned char *)strdup(obj->label); + ci->label.len = strlen(obj->label); mem = BIO_new_mem_buf(obj->content.value, obj->content.len); if (!mem) From 47df45f5f260f0b89e23e44d1442f4f15d82cb6b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Feb 2015 00:34:42 +0100 Subject: [PATCH 073/306] set le instead of p2 twice --- src/libopensc/card-incrypto34.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-incrypto34.c b/src/libopensc/card-incrypto34.c index 317afe30..117596ee 100644 --- a/src/libopensc/card-incrypto34.c +++ b/src/libopensc/card-incrypto34.c @@ -722,7 +722,7 @@ incrypto34_generate_key(sc_card_t *card, apdu.ins = 0x46; apdu.p1 = 0x00; apdu.p2 = args->key_id;/* doc is not clear, it just says "ID" */ - apdu.p2 = 0x00; + apdu.le = 0x00; apdu.data= data; apdu.datalen = apdu.lc = sizeof(data); From ed9572422fa39e673cbbd260a28b079bd5c752a9 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Feb 2015 00:51:04 +0100 Subject: [PATCH 074/306] check return values --- src/libopensc/card-authentic.c | 4 +--- src/libopensc/pkcs15-syn.c | 4 +--- src/pkcs15init/pkcs15-epass2003.c | 4 +--- src/pkcs15init/pkcs15-oberthur-awp.c | 3 --- src/pkcs15init/pkcs15-oberthur.c | 4 ---- src/tests/pintest.c | 5 ++++- src/tools/pkcs11-tool.c | 31 +++++++++++++++++++++------- 7 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/libopensc/card-authentic.c b/src/libopensc/card-authentic.c index 37204854..81a43528 100644 --- a/src/libopensc/card-authentic.c +++ b/src/libopensc/card-authentic.c @@ -1654,9 +1654,7 @@ authentic_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tri } if (save_current) { - struct sc_file *dummy_file = NULL; - - rv = authentic_select_file(card, &save_current->path, &dummy_file); + rv = authentic_select_file(card, &save_current->path, NULL); LOG_TEST_RET(ctx, rv, "Cannot return to saved PATH"); } LOG_FUNC_RETURN(ctx, rv); diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index 3ebbd633..7771e32c 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -226,7 +226,7 @@ static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf) void *handle = NULL; int (*init_func)(sc_pkcs15_card_t *); int (*init_func_ex)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *); - int r, force = 0; + int r; const char *driver, *module_name; driver = conf->name->data; @@ -236,8 +236,6 @@ static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf) memset(&opts, 0, sizeof(opts)); opts.blk = conf; - if (force != 0) - opts.flags = SC_PKCS15EMU_FLAGS_NO_CHECK; module_name = scconf_get_str(conf, "module", builtin_name); if (!strcmp(module_name, "builtin")) { diff --git a/src/pkcs15init/pkcs15-epass2003.c b/src/pkcs15init/pkcs15-epass2003.c index d35cad63..47ed5d1a 100644 --- a/src/pkcs15init/pkcs15-epass2003.c +++ b/src/pkcs15init/pkcs15-epass2003.c @@ -487,7 +487,7 @@ static int epass2003_pkcs15_generate_key(struct sc_profile *profile, (struct sc_pkcs15_prkey_info *)obj->data; size_t idx = key_info->key_reference; size_t keybits = key_info->modulus_length; - struct sc_file *tfile = NULL, *prkf = NULL, *pukf = NULL; + struct sc_file *tfile = NULL, *pukf = NULL; struct sc_path path; struct sc_file *file = NULL; int fidl = 0; @@ -627,8 +627,6 @@ static int epass2003_pkcs15_generate_key(struct sc_profile *profile, failed: if (pukf) sc_file_free(pukf); - if (prkf) - sc_file_free(prkf); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); } diff --git a/src/pkcs15init/pkcs15-oberthur-awp.c b/src/pkcs15init/pkcs15-oberthur-awp.c index d6c6534b..fdb34c60 100644 --- a/src/pkcs15init/pkcs15-oberthur-awp.c +++ b/src/pkcs15init/pkcs15-oberthur-awp.c @@ -312,7 +312,6 @@ awp_create_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_context *ctx = p15card->card->ctx; struct sc_file *clist = NULL, *file = NULL; int rv = 0; - unsigned char *list = NULL; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "create container(%X:%X:%X)", acc->prkey_id, acc->cert_id, acc->pubkey_id); @@ -330,8 +329,6 @@ awp_create_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, rv = awp_create_container_record(p15card, profile, file, acc); - if (list) - free(list); sc_file_free(file); sc_file_free(clist); diff --git a/src/pkcs15init/pkcs15-oberthur.c b/src/pkcs15init/pkcs15-oberthur.c index 15661e73..c968984b 100644 --- a/src/pkcs15init/pkcs15-oberthur.c +++ b/src/pkcs15init/pkcs15-oberthur.c @@ -266,7 +266,6 @@ cosm_create_reference_data(struct sc_profile *profile, struct sc_pkcs15_card *p1 struct sc_card *card = p15card->card; struct sc_pkcs15_auth_info profile_auth_pin, profile_auth_puk; struct sc_cardctl_oberthur_createpin_info args; - unsigned char *puk_buff = NULL; int rv; unsigned char oberthur_puk[16] = { 0x6F, 0x47, 0xD9, 0x88, 0x4B, 0x6F, 0x9D, 0xC5, @@ -323,9 +322,6 @@ cosm_create_reference_data(struct sc_profile *profile, struct sc_pkcs15_card *p1 sc_file_free(file); } - if (puk_buff) - free(puk_buff); - SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); } diff --git a/src/tests/pintest.c b/src/tests/pintest.c index e0bb0ec3..9a911960 100644 --- a/src/tests/pintest.c +++ b/src/tests/pintest.c @@ -40,7 +40,10 @@ static int enum_pins(struct sc_pkcs15_object ***ret) fprintf(stderr, "Not enough memory!\n"); return 1; } - sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, n); + if (0 > sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, n)) { + fprintf(stderr, "Error enumerating PIN codes\n"); + return 1; + } for (i = 0; i < n; i++) { sc_test_print_object(objs[i]); } diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 6eabea7d..2cc3a636 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -3802,17 +3802,26 @@ static int wrap_unwrap(CK_SESSION_HANDLE session, printf(" %s: ", OBJ_nid2sn(EVP_CIPHER_nid(algo))); - EVP_SealInit(&seal_ctx, algo, + if (!EVP_SealInit(&seal_ctx, algo, &key, &key_len, - iv, &pkey, 1); + iv, &pkey, 1)) { + printf("Internal error.\n"); + return 1; + } /* Encrypt something */ len = sizeof(ciphered); - EVP_SealUpdate(&seal_ctx, ciphered, &len, (const unsigned char *) "hello world", 11); + if (!EVP_SealUpdate(&seal_ctx, ciphered, &len, (const unsigned char *) "hello world", 11)) { + printf("Internal error.\n"); + return 1; + } ciphered_len = len; len = sizeof(ciphered) - ciphered_len; - EVP_SealFinal(&seal_ctx, ciphered + ciphered_len, &len); + if (!EVP_SealFinal(&seal_ctx, ciphered + ciphered_len, &len)) { + printf("Internal error.\n"); + return 1; + } ciphered_len += len; EVP_PKEY_free(pkey); @@ -3846,15 +3855,23 @@ static int wrap_unwrap(CK_SESSION_HANDLE session, return 1; } - if (!EVP_DecryptInit(&seal_ctx, algo, key, iv)) + if (!EVP_DecryptInit(&seal_ctx, algo, key, iv)) { + printf("Internal error.\n"); return 1; + } len = sizeof(cleartext); - EVP_DecryptUpdate(&seal_ctx, cleartext, &len, ciphered, ciphered_len); + if (!EVP_DecryptUpdate(&seal_ctx, cleartext, &len, ciphered, ciphered_len)) { + printf("Internal error.\n"); + return 1; + } cleartext_len = len; len = sizeof(cleartext) - len; - EVP_DecryptFinal(&seal_ctx, cleartext + cleartext_len, &len); + if (!EVP_DecryptFinal(&seal_ctx, cleartext + cleartext_len, &len)) { + printf("Internal error.\n"); + return 1; + } cleartext_len += len; if (cleartext_len != 11 From 5cafbe0f4b6fe07abf002f1094bfafbd5244b25d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Feb 2015 08:50:19 +0100 Subject: [PATCH 075/306] fixed undefined shift behaviour --- src/libopensc/card-openpgp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 1e0773aa..5ae66f67 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -1873,7 +1873,10 @@ pgp_build_tlv(sc_context_t *ctx, unsigned int tag, u8 *data, size_t len, u8 **ou highest_order++; } highest_order--; - cla = tag >> 8*highest_order; + if (highest_order >= 4) + cla = 0x00; + else + cla = tag >> 8*highest_order; /* Restore class bits */ *out[0] |= cla; return SC_SUCCESS; From 761e1752122c789a58c620a645cace4652af9801 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Feb 2015 08:52:30 +0100 Subject: [PATCH 076/306] fixed sc_driver_version check --- src/libopensc/pkcs15-syn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index 7771e32c..a3a45349 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -276,7 +276,7 @@ static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf) } } - if (!get_version || (major == 0 && minor <= 9 && fix < 3) < 0) { + if (!get_version || (major == 0 && minor <= 9 && fix < 3)) { /* no sc_driver_version function => assume old style * init function (note: this should later give an error */ From a4c8d671108bca5ce93472f4e3555d59682aff55 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Feb 2015 09:03:27 +0100 Subject: [PATCH 077/306] fixed improper use of negative value --- src/tools/sc-hsm-tool.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index f0f56aeb..ce76bbf0 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -803,9 +803,10 @@ static void ask_for_password(char **pwd, int *pwdlen) -static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total) +static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, unsigned int password_shares_total) { - int r, i; + int r; + unsigned int i; BIGNUM prime; BIGNUM secret; unsigned char buf[64]; @@ -907,7 +908,7 @@ static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int pas -static int create_dkek_share(sc_card_t *card, const char *outf, int iter, const char *password, int password_shares_threshold, int password_shares_total) +static int create_dkek_share(sc_card_t *card, const char *outf, int iter, const char *password, int password_shares_threshold, unsigned int password_shares_total) { EVP_CIPHER_CTX ctx; FILE *out = NULL; @@ -1568,8 +1569,15 @@ int main(int argc, char * const argv[]) if (do_initialize && initialize(card, opt_so_pin, opt_pin, opt_retry_counter, opt_dkek_shares, opt_label)) goto fail; - if (do_create_dkek_share && create_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_threshold, opt_password_shares_total)) - goto fail; + if (do_create_dkek_share) { + if (opt_password_shares_total <= 0) { + fprintf(stderr, "The number of password shares must be bigger than 0."); + goto fail; + } + + if (create_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_threshold, opt_password_shares_total)) + goto fail; + } if (do_import_dkek_share && import_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_total)) goto fail; From 8d902d1ed3f0763d89e3b064f6c24d214818bf96 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Feb 2015 09:24:50 +0100 Subject: [PATCH 078/306] fixed out of bounds read/write/access --- src/libopensc/card-epass2003.c | 6 +++--- src/libopensc/card-myeid.c | 2 +- src/libopensc/card-oberthur.c | 4 ++-- src/libopensc/ctbcs.c | 4 ++-- src/libopensc/pkcs15-postecert.c | 2 +- src/pkcs15init/pkcs15-asepcos.c | 2 +- src/pkcs15init/profile.c | 2 +- src/tests/lottery.c | 2 +- src/tools/cryptoflex-tool.c | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c index 39e46f40..897271dd 100644 --- a/src/libopensc/card-epass2003.c +++ b/src/libopensc/card-epass2003.c @@ -209,7 +209,7 @@ des3_encrypt_ecb(const unsigned char *key, int keysize, static int -des3_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8], +des3_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH], const unsigned char *input, size_t length, unsigned char *output) { unsigned char bKey[24] = { 0 }; @@ -244,7 +244,7 @@ des3_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX static int -des_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8], +des_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH], const unsigned char *input, size_t length, unsigned char *output) { return openssl_enc(EVP_des_cbc(), key, iv, input, length, output); @@ -252,7 +252,7 @@ des_encrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8], static int -des_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[8], +des_decrypt_cbc(const unsigned char *key, int keysize, unsigned char iv[EVP_MAX_IV_LENGTH], const unsigned char *input, size_t length, unsigned char *output) { return openssl_dec(EVP_des_cbc(), key, iv, input, length, output); diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index f9181ae3..54a26f80 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -407,7 +407,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, case SC_FILE_TYPE_DF: buf[8] = 0x38; - if(file->namelen > 0 && file->namelen <= 16) + if(file->namelen > 0 && file->namelen < 16) { buf[25] = 0x84; buf[26] = (u8)file->namelen; diff --git a/src/libopensc/card-oberthur.c b/src/libopensc/card-oberthur.c index f6a4d335..99352e26 100644 --- a/src/libopensc/card-oberthur.c +++ b/src/libopensc/card-oberthur.c @@ -2014,7 +2014,7 @@ write_publickey (struct sc_card *card, unsigned int offset, sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "write_publickey in %d bytes :\n%s", count, debug_buf); - if (offset > sizeof(rsa_der)) + if (1+offset > sizeof(rsa_der)) SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Invalid offset value"); len = offset+count > sizeof(rsa_der) ? sizeof(rsa_der) - offset : count; @@ -2113,7 +2113,7 @@ auth_read_binary(struct sc_card *card, unsigned int offset, if (auth_current_ef->magic==SC_FILE_MAGIC && auth_current_ef->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC) { int jj; - unsigned char resp[0x100], *out = NULL; + unsigned char resp[SC_MAX_APDU_BUFFER_SIZE], *out = NULL; size_t resp_len, out_len; struct sc_pkcs15_bignum bn[2]; struct sc_pkcs15_pubkey_rsa key; diff --git a/src/libopensc/ctbcs.c b/src/libopensc/ctbcs.c index 04420421..16c43369 100644 --- a/src/libopensc/ctbcs.c +++ b/src/libopensc/ctbcs.c @@ -58,7 +58,7 @@ ctbcs_build_perform_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *d prompt = data->pin1.prompt; if (prompt && *prompt) { len = strlen(prompt); - if (count + len + 2 > buflen || len > 255) + if (count + len + 2 > buflen || len > 254) return SC_ERROR_BUFFER_TOO_SMALL; buf[count++] = CTBCS_TAG_PROMPT; buf[count++] = len; @@ -126,7 +126,7 @@ ctbcs_build_modify_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *da prompt = data->pin1.prompt; if (prompt && *prompt) { len = strlen(prompt); - if (count + len + 2 > buflen || len > 255) + if (count + len + 2 > buflen || len > 254) return SC_ERROR_BUFFER_TOO_SMALL; buf[count++] = CTBCS_TAG_PROMPT; buf[count++] = len; diff --git a/src/libopensc/pkcs15-postecert.c b/src/libopensc/pkcs15-postecert.c index 9288b511..a62edd3a 100644 --- a/src/libopensc/pkcs15-postecert.c +++ b/src/libopensc/pkcs15-postecert.c @@ -221,7 +221,7 @@ static int sc_pkcs15emu_postecert_init(sc_pkcs15_card_t * p15card) count_cert[o] = (*(certi + i + 2) << 8) + *(certi + i + 3) + 4; o++; - if (o > 4) + if (o >= 4) break; i += (*(certi + i + 2) << 8) + *(certi + i + 3); } diff --git a/src/pkcs15init/pkcs15-asepcos.c b/src/pkcs15init/pkcs15-asepcos.c index ddc72f52..7904fb5a 100644 --- a/src/pkcs15init/pkcs15-asepcos.c +++ b/src/pkcs15init/pkcs15-asepcos.c @@ -512,7 +512,7 @@ static int asepcos_do_create_key(sc_card_t *card, size_t ksize, int fileid, sc_file_t *nfile = NULL; u8 buf[1024], *p = buf; - if (sizeof(buf) < kdlen + 11) + if (sizeof(buf) < kdlen + 12) return SC_ERROR_BUFFER_TOO_SMALL; *p++ = 0x85; diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c index 9f87fc9c..a6a952e2 100644 --- a/src/pkcs15init/profile.c +++ b/src/pkcs15init/profile.c @@ -1301,7 +1301,7 @@ do_fileid(struct state *cur, int argc, char **argv) parse_error(cur, "No path/fileid set for parent DF\n"); return 1; } - if (df->path.len + 2 > sizeof(df->path)) { + if (df->path.len + 2 > sizeof(df->path.value)) { parse_error(cur, "File path too long\n"); return 1; } diff --git a/src/tests/lottery.c b/src/tests/lottery.c index eab40364..c64f093c 100644 --- a/src/tests/lottery.c +++ b/src/tests/lottery.c @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) printf("Lottery: "); for (i = 0; i < 7; i++) { unsigned short s = buf[2 * i] + (buf[2 * i + 1] << 8); - int lot = s % (left + 1); + int lot = s % left; int num = nbuf[lot]; nbuf[lot] = nbuf[left - 1]; diff --git a/src/tools/cryptoflex-tool.c b/src/tools/cryptoflex-tool.c index ea1e6a43..8cbbd856 100644 --- a/src/tools/cryptoflex-tool.c +++ b/src/tools/cryptoflex-tool.c @@ -642,7 +642,7 @@ static int read_rsa_privkey(RSA **rsa_out) static int encode_private_key(RSA *rsa, u8 *key, size_t *keysize) { - u8 buf[512], *p = buf; + u8 buf[1024], *p = buf; u8 bnbuf[256]; int base = 0; int r; From a3fc62f79ff867ca2a2c5be24aff1759d3476417 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Feb 2015 19:19:57 +0100 Subject: [PATCH 079/306] fixed NULL dereference (or warning thereof) --- src/libopensc/card-authentic.c | 10 ++++++---- src/libopensc/card-epass2003.c | 2 +- src/libopensc/card-iasecc.c | 3 ++- src/libopensc/card-mcrd.c | 2 ++ src/libopensc/iasecc-sdo.c | 3 ++- src/libopensc/iasecc-sm.c | 7 +++++-- src/libopensc/pkcs15-data.c | 2 +- src/libopensc/pkcs15-sc-hsm.c | 2 +- src/pkcs15init/pkcs15-iasecc.c | 17 ++++++++++------- src/pkcs15init/pkcs15-lib.c | 5 +++++ src/smm/sm-card-iasecc.c | 29 +++++++++++------------------ src/tools/piv-tool.c | 7 ++++++- src/tools/pkcs15-tool.c | 3 +-- 13 files changed, 53 insertions(+), 39 deletions(-) diff --git a/src/libopensc/card-authentic.c b/src/libopensc/card-authentic.c index 81a43528..4b3805d9 100644 --- a/src/libopensc/card-authentic.c +++ b/src/libopensc/card-authentic.c @@ -2110,14 +2110,16 @@ static int authentic_sm_acl_init (struct sc_card *card, struct sm_info *sm_info, int cmd, unsigned char *resp, size_t *resp_len) { - struct sc_context *ctx = card->ctx; - struct sm_type_params_gp *params_gp = &sm_info->session.gp.params; + struct sc_context *ctx; + struct sm_type_params_gp *params_gp; struct sc_remote_data rdata; int rv; - sc_log(ctx, "called; command 0x%X\n", cmd); if (!card || !sm_info || !resp || !resp_len) - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + return SC_ERROR_INVALID_ARGUMENTS; + + ctx = card->ctx; + params_gp = &sm_info->session.gp.params; if (!card->sm_ctx.module.ops.initialize || !card->sm_ctx.module.ops.get_apdus) LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c index 897271dd..af37b6ee 100644 --- a/src/libopensc/card-epass2003.c +++ b/src/libopensc/card-epass2003.c @@ -1141,7 +1141,7 @@ epass2003_select_fid(struct sc_card *card, unsigned int id_hi, unsigned int id_l LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); /* update cache */ - if (file->type == SC_FILE_TYPE_DF) { + if (file && file->type == SC_FILE_TYPE_DF) { card->cache.current_path.type = SC_PATH_TYPE_PATH; card->cache.current_path.value[0] = 0x3f; card->cache.current_path.value[1] = 0x00; diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index e05e80e8..3e3b03b9 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -3324,7 +3324,8 @@ iasecc_read_public_key(struct sc_card *card, unsigned type, rv = sc_pkcs15_encode_pubkey_rsa(ctx, &rsa_key, out, out_len); LOG_TEST_RET(ctx, rv, "failed to read public key: cannot encode RSA public key"); - sc_log(ctx, "encoded public key: %s", sc_dump_hex(*out, *out_len)); + if (out && out_len) + sc_log(ctx, "encoded public key: %s", sc_dump_hex(*out, *out_len)); if (bn[0].data) free(bn[0].data); diff --git a/src/libopensc/card-mcrd.c b/src/libopensc/card-mcrd.c index 1f469b06..a72f4da7 100644 --- a/src/libopensc/card-mcrd.c +++ b/src/libopensc/card-mcrd.c @@ -419,6 +419,8 @@ static int load_special_files(sc_card_t * card) if (dfi && dfi->rule_file) return 0; /* yes. */ clear_special_files(dfi); + if (!dfi) + SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); /* Read rule file. Note that we bypass our cache here. */ r = select_part(card, MCRD_SEL_EF, EF_Rule, NULL); diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c index b1d3096f..d274c74b 100644 --- a/src/libopensc/iasecc-sdo.c +++ b/src/libopensc/iasecc-sdo.c @@ -985,7 +985,8 @@ iasecc_sdo_encode_create(struct sc_context *ctx, struct iasecc_sdo *sdo, unsigne rv = sc_asn1_encode(ctx, asn1_create_data, out, &out_len); LOG_TEST_RET(ctx, rv, "Encode create data error"); - sc_debug(ctx, SC_LOG_DEBUG_ASN1,"Create data: %s", sc_dump_hex(*out, out_len)); + if (out) + sc_debug(ctx, SC_LOG_DEBUG_ASN1,"Create data: %s", sc_dump_hex(*out, out_len)); LOG_FUNC_RETURN(ctx, out_len); } diff --git a/src/libopensc/iasecc-sm.c b/src/libopensc/iasecc-sm.c index bfa57133..4996c234 100644 --- a/src/libopensc/iasecc-sm.c +++ b/src/libopensc/iasecc-sm.c @@ -37,12 +37,15 @@ static int sm_save_sc_context (struct sc_card *card, struct sm_info *sm_info) { - struct sc_context *ctx = card->ctx; - struct sc_card_cache *cache = &card->cache; + struct sc_context *ctx; + struct sc_card_cache *cache; if (!card || !sm_info) return SC_ERROR_INVALID_ARGUMENTS; + ctx = card->ctx; + cache = &card->cache; + sc_log(ctx, "SM save context: cache(valid:%i,current_df:%p)", cache->valid, cache->current_df); if (cache->valid && cache->current_df) { sm_info->current_path_df = cache->current_df->path; diff --git a/src/libopensc/pkcs15-data.c b/src/libopensc/pkcs15-data.c index e70d6684..5d7ad32a 100644 --- a/src/libopensc/pkcs15-data.c +++ b/src/libopensc/pkcs15-data.c @@ -61,7 +61,7 @@ sc_pkcs15_read_data_object(struct sc_pkcs15_card *p15card, sc_der_copy(&der, &info->data); data_object = calloc(sizeof(struct sc_pkcs15_data), 1); - if (!data_object && !der.value) + if (!data_object || !der.value) LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate memory for data object"); data_object->data = der.value; diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index 5e5fa570..03801cdb 100644 --- a/src/libopensc/pkcs15-sc-hsm.c +++ b/src/libopensc/pkcs15-sc-hsm.c @@ -426,7 +426,7 @@ static int sc_pkcs15emu_sc_hsm_get_ec_public_key(struct sc_context *ctx, sc_cvc_ int sc_pkcs15emu_sc_hsm_get_public_key(struct sc_context *ctx, sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey) { - if (cvc->publicPoint || cvc->publicPointlen) { + if (cvc->publicPoint && cvc->publicPointlen) { return sc_pkcs15emu_sc_hsm_get_ec_public_key(ctx, cvc, pubkey); } else { return sc_pkcs15emu_sc_hsm_get_rsa_public_key(ctx, cvc, pubkey); diff --git a/src/pkcs15init/pkcs15-iasecc.c b/src/pkcs15init/pkcs15-iasecc.c index 025f9ea0..e12f460e 100644 --- a/src/pkcs15init/pkcs15-iasecc.c +++ b/src/pkcs15init/pkcs15-iasecc.c @@ -573,16 +573,20 @@ iasecc_sdo_allocate_pubkey(struct sc_profile *profile, struct sc_card *card, str static int iasecc_sdo_convert_to_file(struct sc_card *card, struct iasecc_sdo *sdo, struct sc_file **out) { - struct sc_context *ctx = card->ctx; - struct sc_file *file = sc_file_new(); + struct sc_context *ctx; + struct sc_file *file; unsigned ii; int rv; + if (!card || !sdo) + return SC_ERROR_INVALID_ARGUMENTS; + + ctx = card->ctx; LOG_FUNC_CALLED(ctx); - if (file == NULL) + + file = sc_file_new(); + if (!file) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); - else if (!card || !sdo) - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); sc_log(ctx, "SDO class 0x%X", sdo->sdo_class); @@ -1761,8 +1765,7 @@ iasecc_store_data_object(struct sc_pkcs15_card *p15card, struct sc_profile *prof if (parent) sc_file_free(parent); - if (file) - sc_file_free(file); + sc_file_free(file); if (cfile) sc_file_free(cfile); diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 7f01e455..61e157c3 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1712,6 +1712,8 @@ sc_pkcs15init_store_data_object(struct sc_pkcs15_card *p15card, unsigned int tid = 0x01; LOG_FUNC_CALLED(ctx); + if (!profile) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Missing profile"); label = args->label; if (!args->id.len) { @@ -2673,6 +2675,9 @@ sc_pkcs15init_update_any_df(struct sc_pkcs15_card *p15card, int update_odf = is_new, r = 0; LOG_FUNC_CALLED(ctx); + if (!df) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "DF missing"); + r = sc_profile_get_file_by_path(profile, &df->path, &file); LOG_TEST_RET(ctx, r, "Failed get file path"); if (file == NULL) diff --git a/src/smm/sm-card-iasecc.c b/src/smm/sm-card-iasecc.c index d7b6998f..199e8a6a 100644 --- a/src/smm/sm-card-iasecc.c +++ b/src/smm/sm-card-iasecc.c @@ -152,14 +152,12 @@ sm_iasecc_get_apdu_create_file(struct sc_context *ctx, struct sm_info *sm_info, int rv = 0; LOG_FUNC_CALLED(ctx); + + if (!cmd_data || !cmd_data->data || !rdata || !rdata->alloc) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + sc_log(ctx, "SM get 'CREATE FILE' APDU: FCP(%i) %s", cmd_data->size, sc_dump_hex(cmd_data->data,cmd_data->size)); - if (!cmd_data || !cmd_data->data) - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - - if (!rdata || !rdata->alloc) - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - rv = rdata->alloc(rdata, &rapdu); LOG_TEST_RET(ctx, rv, "SM get 'UPDATE BINARY' APDUs: cannot allocate remote APDU"); @@ -229,14 +227,11 @@ sm_iasecc_get_apdu_verify_pin(struct sc_context *ctx, struct sm_info *sm_info, s int rv; LOG_FUNC_CALLED(ctx); + if (!pin_data || !rdata || !rdata->alloc) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + sc_log(ctx, "SM get 'VERIFY PIN' APDU: ", pin_data->pin_reference); - if (!pin_data) - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - - if (!rdata || !rdata->alloc) - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - rv = rdata->alloc(rdata, &rapdu); LOG_TEST_RET(ctx, rv, "SM get 'VERIFY PIN' APDUs: cannot allocate remote APDU"); @@ -272,14 +267,12 @@ sm_iasecc_get_apdu_reset_pin(struct sc_context *ctx, struct sm_info *sm_info, st int rv; LOG_FUNC_CALLED(ctx); + + if (!pin_data || !rdata || !rdata->alloc) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + sc_log(ctx, "SM get 'RESET PIN' APDU; reference %i", pin_data->pin_reference); - if (!pin_data) - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - - if (!rdata || !rdata->alloc) - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - rv = rdata->alloc(rdata, &rapdu); LOG_TEST_RET(ctx, rv, "SM get 'RESET PIN' APDUs: cannot allocate remote APDU"); diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index d0a6ba8e..bddbca8b 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -168,9 +168,14 @@ static int load_cert(const char * cert_id, const char * cert_file, size_t derlen; int r; + if (!cert_file) { + printf("Missing cert file\n"); + return -1; + } + if((fp=fopen(cert_file, "r"))==NULL){ printf("Cannot open cert file, %s %s\n", - cert_file?cert_file:"", strerror(errno)); + cert_file, strerror(errno)); return -1; } if (compress) { /* file is gziped already */ diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 03d5d671..409d9847 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -1002,8 +1002,7 @@ static int read_ssh_key(void) fclose(outf); if (cert) sc_pkcs15_free_certificate(cert); - else if (pubkey) - sc_pkcs15_free_pubkey(pubkey); + sc_pkcs15_free_pubkey(pubkey); return 0; fail: From 11881a61b8247bde7618cf0f842bf7fc0285e803 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 5 Feb 2015 00:43:05 +0100 Subject: [PATCH 080/306] removed/fixed dead code --- src/libopensc/card-asepcos.c | 2 +- src/libopensc/card-entersafe.c | 2 +- src/libopensc/card-ias.c | 2 -- src/libopensc/card-iasecc.c | 18 ++++------- src/libopensc/card-myeid.c | 32 ++------------------ src/libopensc/pkcs15-pubkey.c | 2 -- src/libopensc/pkcs15-syn.c | 12 ++++---- src/libopensc/pkcs15-westcos.c | 2 +- src/libopensc/sc.c | 32 ++++++++++---------- src/pkcs11/framework-pkcs15.c | 2 +- src/pkcs11/pkcs11-object.c | 50 ------------------------------- src/pkcs15init/pkcs15-authentic.c | 5 +--- src/pkcs15init/pkcs15-muscle.c | 6 ---- src/pkcs15init/pkcs15-myeid.c | 18 ----------- src/scconf/parse.c | 2 +- src/tools/opensc-tool.c | 4 +-- 16 files changed, 37 insertions(+), 154 deletions(-) diff --git a/src/libopensc/card-asepcos.c b/src/libopensc/card-asepcos.c index 433c28fd..f46be32b 100644 --- a/src/libopensc/card-asepcos.c +++ b/src/libopensc/card-asepcos.c @@ -662,7 +662,7 @@ static int asepcos_list_files(sc_card_t *card, u8 *buf, size_t blen) /* 1. get currently selected DF */ r = asepcos_get_current_df_path(card, &bpath); - if (rv != SC_SUCCESS) + if (r != SC_SUCCESS) return r; /* 2. re-select DF to get the FID of the child EFs/DFs */ r = sc_select_file(card, &bpath, &tfile); diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c index ca16a2d6..b024a283 100644 --- a/src/libopensc/card-entersafe.c +++ b/src/libopensc/card-entersafe.c @@ -339,7 +339,7 @@ static int entersafe_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu, blocks=(apdu->lc+2)/8+1; cipher_data_size=blocks*8; cipher_data=malloc(cipher_data_size); - if(!cipher) + if(!cipher_data) { r = SC_ERROR_OUT_OF_MEMORY; goto out; diff --git a/src/libopensc/card-ias.c b/src/libopensc/card-ias.c index 9c48a5f5..489087c5 100644 --- a/src/libopensc/card-ias.c +++ b/src/libopensc/card-ias.c @@ -473,8 +473,6 @@ static int ias_select_file(sc_card_t *card, const sc_path_t *in_path, r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if (file_out == NULL) { - if (apdu.sw1 == 0x61) - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, 0); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); } } diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 3e3b03b9..0673d281 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -2343,7 +2343,7 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_ if (scb & IASECC_SCB_METHOD_SM) { rv = iasecc_sm_pin_reset(card, se_num, data); - LOG_FUNC_RETURN(ctx, rv); + LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_reset() reset PUK error"); if (!need_all) break; @@ -2396,7 +2396,6 @@ static int iasecc_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left) { struct sc_context *ctx = card->ctx; - struct sc_apdu apdu; int rv; LOG_FUNC_CALLED(ctx); @@ -2407,29 +2406,24 @@ iasecc_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_le switch (data->cmd) { case SC_PIN_CMD_VERIFY: rv = iasecc_pin_verify(card, data->pin_type, data->pin_reference, data->pin1.data, data->pin1.len, tries_left); - LOG_FUNC_RETURN(ctx, rv); + break; case SC_PIN_CMD_CHANGE: if (data->pin_type == SC_AC_AUT) rv = iasecc_keyset_change(card, data, tries_left); else rv = iasecc_pin_change(card, data, tries_left); - LOG_FUNC_RETURN(ctx, rv); + break; case SC_PIN_CMD_UNBLOCK: rv = iasecc_pin_reset(card, data, tries_left); - LOG_FUNC_RETURN(ctx, rv); + break; case SC_PIN_CMD_GET_INFO: rv = iasecc_pin_get_policy(card, data); - LOG_FUNC_RETURN(ctx, rv); + break; default: sc_log(ctx, "Other pin commands not supported yet: 0x%X", data->cmd); - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Non-supported PIN command"); + rv = SC_ERROR_NOT_SUPPORTED; } - rv = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(ctx, rv, "APDU transmit failed"); - rv = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_RET(ctx, rv, "PIN cmd failed"); - LOG_FUNC_RETURN(ctx, rv); } diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 54a26f80..4b253f16 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -508,7 +508,7 @@ static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t * sc_apdu_t apdu; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 *p; - int r, locked = 0; + int r; assert(card != NULL && env != NULL); LOG_FUNC_CALLED(card->ctx); @@ -564,11 +564,6 @@ static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t * apdu.datalen = r; apdu.data = sbuf; apdu.resplen = 0; - if (se_num > 0) { - r = sc_lock(card); - LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); - locked = 1; - } if (apdu.datalen != 0) { r = sc_transmit_apdu(card, &apdu); @@ -586,16 +581,7 @@ static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t * goto err; } } - if (se_num <= 0) - return 0; - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num); - r = sc_transmit_apdu(card, &apdu); - sc_unlock(card); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - return sc_check_sw(card, apdu.sw1, apdu.sw2); err: - if (locked) - sc_unlock(card); LOG_FUNC_RETURN(card->ctx, r); } @@ -605,7 +591,7 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e sc_apdu_t apdu; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 *p; - int r, locked = 0; + int r; assert(card != NULL && env != NULL); LOG_FUNC_CALLED(card->ctx); @@ -661,11 +647,6 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e apdu.datalen = r; apdu.data = sbuf; apdu.resplen = 0; - if (se_num > 0) { - r = sc_lock(card); - LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); - locked = 1; - } if (apdu.datalen != 0) { r = sc_transmit_apdu(card, &apdu); @@ -683,16 +664,7 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e goto err; } } - if (se_num <= 0) - return 0; - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num); - r = sc_transmit_apdu(card, &apdu); - sc_unlock(card); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - return sc_check_sw(card, apdu.sw1, apdu.sw2); err: - if (locked) - sc_unlock(card); LOG_FUNC_RETURN(card->ctx, r); } diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 4afd3bbf..15ba3446 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1227,8 +1227,6 @@ sc_pkcs15_read_der_file(sc_context_t *ctx, char * filename, rbuf = NULL; r = rbuflen; out: - if (rbuf) - free(rbuf); if (f > 0) close(f); diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index a3a45349..3d758016 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -203,15 +203,13 @@ sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *p15card) free(blocks); } - /* Total failure */ - LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_CARD); - -out: if (r == SC_SUCCESS) { +out: + if (r == SC_SUCCESS) { p15card->magic = SC_PKCS15_CARD_MAGIC; p15card->flags |= SC_PKCS15_CARD_FLAG_EMULATED; - } - else if (r != SC_ERROR_WRONG_CARD) { - sc_log(ctx, "Failed to load card emulator: %s", sc_strerror(r)); + } else { + if (r != SC_ERROR_WRONG_CARD) + sc_log(ctx, "Failed to load card emulator: %s", sc_strerror(r)); } LOG_FUNC_RETURN(ctx, r); diff --git a/src/libopensc/pkcs15-westcos.c b/src/libopensc/pkcs15-westcos.c index 8bd4d645..ebc02cda 100644 --- a/src/libopensc/pkcs15-westcos.c +++ b/src/libopensc/pkcs15-westcos.c @@ -70,7 +70,7 @@ static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card) } else { - for (i = 0; i < 1; i++) { + for (i = 0; i <= 1; i++) { unsigned int flags; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 08375f0c..e747958b 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -108,7 +108,7 @@ int sc_bin_to_hex(const u8 *in, size_t in_len, char *out, size_t out_len, pos += 2; } *pos = '\0'; - return 0; + return SC_SUCCESS; } /* @@ -299,7 +299,7 @@ int sc_append_path_id(sc_path_t *dest, const u8 *id, size_t idlen) return SC_ERROR_INVALID_ARGUMENTS; memcpy(dest->value + dest->len, id, idlen); dest->len += idlen; - return 0; + return SC_SUCCESS; } int sc_append_file_id(sc_path_t *dest, unsigned int fid) @@ -417,21 +417,21 @@ int sc_file_add_acl_entry(sc_file_t *file, unsigned int operation, case SC_AC_NEVER: sc_file_clear_acl_entries(file, operation); file->acl[operation] = (sc_acl_entry_t *) 1; - return 0; + return SC_SUCCESS; case SC_AC_NONE: sc_file_clear_acl_entries(file, operation); file->acl[operation] = (sc_acl_entry_t *) 2; - return 0; + return SC_SUCCESS; case SC_AC_UNKNOWN: sc_file_clear_acl_entries(file, operation); file->acl[operation] = (sc_acl_entry_t *) 3; - return 0; + return SC_SUCCESS; default: /* NONE and UNKNOWN get zapped when a new AC is added. * If the ACL is NEVER, additional entries will be * dropped silently. */ if (file->acl[operation] == (sc_acl_entry_t *) 1) - return 0; + return SC_SUCCESS; if (file->acl[operation] == (sc_acl_entry_t *) 2 || file->acl[operation] == (sc_acl_entry_t *) 3) file->acl[operation] = NULL; @@ -441,7 +441,7 @@ int sc_file_add_acl_entry(sc_file_t *file, unsigned int operation, * of the card's AC with OpenSC's), don't add it again. */ for (p = file->acl[operation]; p != NULL; p = p->next) { if ((p->method == method) && (p->key_ref == key_ref)) - return 0; + return SC_SUCCESS; } _new = malloc(sizeof(sc_acl_entry_t)); @@ -454,13 +454,13 @@ int sc_file_add_acl_entry(sc_file_t *file, unsigned int operation, p = file->acl[operation]; if (p == NULL) { file->acl[operation] = _new; - return 0; + return SC_SUCCESS; } while (p->next != NULL) p = p->next; p->next = _new; - return 0; + return SC_SUCCESS; } const sc_acl_entry_t * sc_file_get_acl_entry(const sc_file_t *file, @@ -629,7 +629,7 @@ int sc_file_set_prop_attr(sc_file_t *file, const u8 *prop_attr, free(file->prop_attr); file->prop_attr = NULL; file->prop_attr_len = 0; - return 0; + return SC_SUCCESS; } tmp = (u8 *) realloc(file->prop_attr, prop_attr_len); if (!tmp) { @@ -643,7 +643,7 @@ int sc_file_set_prop_attr(sc_file_t *file, const u8 *prop_attr, memcpy(file->prop_attr, prop_attr, prop_attr_len); file->prop_attr_len = prop_attr_len; - return 0; + return SC_SUCCESS; } int sc_file_set_type_attr(sc_file_t *file, const u8 *type_attr, @@ -657,7 +657,7 @@ int sc_file_set_type_attr(sc_file_t *file, const u8 *type_attr, free(file->type_attr); file->type_attr = NULL; file->type_attr_len = 0; - return 0; + return SC_SUCCESS; } tmp = (u8 *) realloc(file->type_attr, type_attr_len); if (!tmp) { @@ -671,7 +671,7 @@ int sc_file_set_type_attr(sc_file_t *file, const u8 *type_attr, memcpy(file->type_attr, type_attr, type_attr_len); file->type_attr_len = type_attr_len; - return 0; + return SC_SUCCESS; } @@ -781,12 +781,12 @@ int _sc_parse_atr(sc_reader_t *reader) } } if (atr_len <= 0) - return 0; + return SC_SUCCESS; if (n_hist > atr_len) n_hist = atr_len; reader->atr_info.hist_bytes_len = n_hist; reader->atr_info.hist_bytes = p; - return 0; + return SC_SUCCESS; } void *sc_mem_alloc_secure(sc_context_t *ctx, size_t len) @@ -840,7 +840,7 @@ int sc_mem_reverse(unsigned char *buf, size_t len) *(buf + len - 1 - ii) = ch; } - return 0; + return SC_SUCCESS; } static int diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index ff198e64..fc7c4cf2 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -2031,7 +2031,7 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil } /* CKA_VALUE arrives in little endian form. pkcs15init framework expects it in a big endian one. */ rc = sc_mem_reverse(gost->d.data, gost->d.len); - if (rv) { + if (rc != SC_SUCCESS) { rv = sc_to_cryptoki_error(rc, "C_CreateObject"); goto out; } diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c index 70291b3a..a6b9236e 100644 --- a/src/pkcs11/pkcs11-object.c +++ b/src/pkcs11/pkcs11-object.c @@ -760,57 +760,7 @@ C_SignRecoverInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ CK_OBJECT_HANDLE hKey) /* handle of the signature key */ { - CK_RV rv; - CK_BBOOL can_sign; - CK_KEY_TYPE key_type; - CK_ATTRIBUTE sign_attribute = { CKA_SIGN, &can_sign, sizeof(can_sign) }; - CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) }; - struct sc_pkcs11_session *session; - struct sc_pkcs11_object *object; - - /* FIXME #47: C_SignRecover is not implemented */ return CKR_FUNCTION_NOT_SUPPORTED; - - if (pMechanism == NULL_PTR) - return CKR_ARGUMENTS_BAD; - - rv = sc_pkcs11_lock(); - if (rv != CKR_OK) - return rv; - - rv = get_object_from_session(hSession, hKey, &session, &object); - if (rv != CKR_OK) { - if (rv == CKR_OBJECT_HANDLE_INVALID) - rv = CKR_KEY_HANDLE_INVALID; - goto out; - } - - if (object->ops->sign == NULL_PTR) { - rv = CKR_KEY_TYPE_INCONSISTENT; - goto out; - } - - rv = object->ops->get_attribute(session, object, &sign_attribute); - if (rv != CKR_OK || !can_sign) { - rv = CKR_KEY_TYPE_INCONSISTENT; - goto out; - } - rv = object->ops->get_attribute(session, object, &key_type_attr); - if (rv != CKR_OK) { - rv = CKR_KEY_TYPE_INCONSISTENT; - goto out; - } - - /* XXX: need to tell the signature algorithm that we want - * to recover the signature */ - sc_log(context, "SignRecover operation initialized\n"); - - rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type); - -out: - sc_log(context, "C_SignRecoverInit() = %sn", lookup_enum ( RV_T, rv )); - sc_pkcs11_unlock(); - return rv; } diff --git a/src/pkcs15init/pkcs15-authentic.c b/src/pkcs15init/pkcs15-authentic.c index cdead033..f15506c9 100644 --- a/src/pkcs15init/pkcs15-authentic.c +++ b/src/pkcs15init/pkcs15-authentic.c @@ -363,10 +363,7 @@ authentic_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card, sc_log(ctx, "sdo(mech:%X,id:%X,acls:%s)", sdo->docp.mech, sdo->docp.id, sc_dump_hex(sdo->docp.acl_data, sdo->docp.acl_data_len)); - if (out) - *out = sdo; - else - free(sdo); + *out = sdo; LOG_FUNC_RETURN(ctx, SC_SUCCESS); } diff --git a/src/pkcs15init/pkcs15-muscle.c b/src/pkcs15init/pkcs15-muscle.c index 96a0afa8..bcd4fd31 100644 --- a/src/pkcs15init/pkcs15-muscle.c +++ b/src/pkcs15init/pkcs15-muscle.c @@ -283,12 +283,6 @@ muscle_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, pubkey->u.rsa.exponent.len = extArgs.expLength; pubkey->u.rsa.exponent.data = extArgs.expValue; - if (r < 0) { - if (pubkey->u.rsa.modulus.data) - free (pubkey->u.rsa.modulus.data); - if (pubkey->u.rsa.exponent.data) - free (pubkey->u.rsa.exponent.data); - } return r; } diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index 1c33a3b2..a7ce7ea3 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -423,9 +423,6 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, break; case SC_PKCS15_TYPE_PRKEY_EC: LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "20140202: waiting for cards and specification from Aventra. VTA"); - if (sc_card_find_ec_alg(p15card->card, keybits) == NULL) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, - "Unsupported EC key size"); break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, @@ -487,13 +484,6 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, break; case SC_PKCS15_TYPE_PRKEY_EC: LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "20140202: waiting for cards and specification from Aventra. VTA"); - if (sc_card_find_ec_alg(p15card->card, keybits) == NULL) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); - if(key_info->field_length != 0) - keybits = key_info->field_length; - else - key_info->field_length = keybits; - break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type"); @@ -576,14 +566,6 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, break; case SC_PKCS15_TYPE_PRKEY_EC: LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "20140202: waiting for cards and specification from Aventra. VTA"); - - if (sc_card_find_ec_alg(p15card->card, keybits) == NULL) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); - if(key_info->field_length != 0) - keybits = key_info->field_length; - else - key_info->field_length = keybits; - break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key type"); diff --git a/src/scconf/parse.c b/src/scconf/parse.c index 043ab794..2804d7d5 100644 --- a/src/scconf/parse.c +++ b/src/scconf/parse.c @@ -278,7 +278,7 @@ void scconf_parse_token(scconf_parser * parser, int token_type, const char *toke scconf_parse_warning_expect(parser, "\""); } else { /* stoken */ - stoken = token ? strdup(token) : NULL; + stoken = strdup(token); if (stoken) { stoken[len - 1] = '\0'; } diff --git a/src/tools/opensc-tool.c b/src/tools/opensc-tool.c index c1676988..d9079840 100644 --- a/src/tools/opensc-tool.c +++ b/src/tools/opensc-tool.c @@ -149,7 +149,7 @@ static int opensc_get_conf_entry(const char *config) } section = buffer; - name = section == NULL ? NULL : strchr(section+1, ':'); + name = strchr(section+1, ':'); key = name == NULL ? NULL : strchr(name+1, ':'); if (key == NULL) { r = EINVAL; @@ -203,7 +203,7 @@ static int opensc_set_conf_entry(const char *config) } section = buffer; - name = section == NULL ? NULL : strchr(section+1, ':'); + name = strchr(section+1, ':'); key = name == NULL ? NULL : strchr(name+1, ':'); value = key == NULL ? NULL : strchr(key+1, ':'); if (value == NULL) { From 3a92bf7af5aaa85fdbc0434d0a55393e68e0f98d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 5 Feb 2015 01:36:40 +0100 Subject: [PATCH 081/306] fixed resource leaks --- src/libopensc/cwa-dnie.c | 6 ++---- src/libopensc/cwa14890.c | 11 ++++++++--- src/libopensc/pkcs15-dnie.c | 7 ++++--- src/libopensc/pkcs15-pubkey.c | 2 +- src/libopensc/pkcs15.c | 1 + src/libopensc/sc.c | 2 +- src/pkcs11/slot.c | 6 +++++- src/pkcs15init/pkcs15-authentic.c | 2 ++ src/pkcs15init/pkcs15-iasecc.c | 9 +++++++++ src/pkcs15init/pkcs15-westcos.c | 3 --- src/tools/openpgp-tool.c | 1 + src/tools/piv-tool.c | 1 + src/tools/pkcs11-tool.c | 7 ++++++- src/tools/pkcs15-init.c | 7 ++++--- 14 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/libopensc/cwa-dnie.c b/src/libopensc/cwa-dnie.c index 73098f2d..f54ad22a 100644 --- a/src/libopensc/cwa-dnie.c +++ b/src/libopensc/cwa-dnie.c @@ -690,16 +690,14 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card) static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) { - u8 *buf = NULL; /* use for store partial le responses */ + u8 buf[2048]; /* use for store partial le responses */ int res = SC_SUCCESS; cwa_provider_t *provider = NULL; if ((card == NULL) || (card->ctx == NULL) || (apdu == NULL)) return SC_ERROR_INVALID_ARGUMENTS; LOG_FUNC_CALLED(card->ctx); provider = GET_DNIE_PRIV_DATA(card)->cwa_provider; - buf = calloc(2048, sizeof(u8)); - if (!buf) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + memset(buf, 0, sizeof(buf)); /* check if envelope is needed */ if (apdu->lc <= card->max_send_size) { diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index c9515275..174f1ef7 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -324,6 +324,7 @@ static int cwa_parse_tlv(sc_card_t * card, /* set index to next Tag to jump to */ next = tlv->buflen; } + free(buffer); LOG_FUNC_RETURN(ctx, SC_SUCCESS); /* mark no error */ } @@ -1418,9 +1419,9 @@ int cwa_create_secure_channel(sc_card_t * card, int cwa_encode_apdu(sc_card_t * card, cwa_provider_t * provider, sc_apdu_t * from, sc_apdu_t * to) { - u8 *apdubuf; /* to store resulting apdu */ + u8 *apdubuf = NULL; /* to store resulting apdu */ size_t apdulen; - u8 *ccbuf; /* where to store data to eval cryptographic checksum CC */ + u8 *ccbuf = NULL; /* where to store data to eval cryptographic checksum CC */ size_t cclen = 0; u8 macbuf[8]; /* to store and compute CC */ DES_key_schedule k1; @@ -1594,9 +1595,13 @@ int cwa_encode_apdu(sc_card_t * card, /* that's all folks */ res = SC_SUCCESS; - encode_end: +encode_end: if (msg) sc_log(ctx, msg); + free(msgbuf); + free(cryptbuf); + free(ccbuf); + free(apdubuf); LOG_FUNC_RETURN(ctx, res); } diff --git a/src/libopensc/pkcs15-dnie.c b/src/libopensc/pkcs15-dnie.c index acfce590..077215f4 100644 --- a/src/libopensc/pkcs15-dnie.c +++ b/src/libopensc/pkcs15-dnie.c @@ -102,8 +102,9 @@ int parse_odf(const u8 * buf, size_t buflen, struct sc_pkcs15_card *p15card) }; struct sc_asn1_entry asn1_odf[10]; - sc_path_t *path_prefix = calloc(1, sizeof(sc_path_t)); - sc_format_path("3F005015", path_prefix); + sc_path_t path_prefix; + + sc_format_path("3F005015", &path_prefix); sc_copy_asn1_entry(c_asn1_odf, asn1_odf); for (i = 0; asn1_odf[i].name != NULL; i++) @@ -116,7 +117,7 @@ int parse_odf(const u8 * buf, size_t buflen, struct sc_pkcs15_card *p15card) if (r < 0) return r; type = r; - r = sc_pkcs15_make_absolute_path(path_prefix, &path); + r = sc_pkcs15_make_absolute_path(&path_prefix, &path); if (r < 0) return r; r = sc_pkcs15_add_df(p15card, odf_indexes[type], &path); diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 15ba3446..63bd067d 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1227,7 +1227,7 @@ sc_pkcs15_read_der_file(sc_context_t *ctx, char * filename, rbuf = NULL; r = rbuflen; out: - if (f > 0) + if (f >= 0) close(f); LOG_FUNC_RETURN(ctx, r); diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index caa7a598..35174ba7 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -957,6 +957,7 @@ sc_pkcs15_get_application_by_type(struct sc_card * card, char *app_type) char *type = (char *)scconf_get_str(blocks[0], "type", app_type); if (!strcmp(type, app_type)) { out = app_info; + free(blocks); break; } } diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index e747958b..490b365b 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -47,7 +47,7 @@ const char *sc_get_version(void) int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen) { - int err = 0; + int err = SC_SUCCESS; size_t left, count = 0; assert(in != NULL && out != NULL && outlen != NULL); diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 87b1e3dd..336b3e26 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -183,7 +183,7 @@ CK_RV card_removed(sc_reader_t * reader) CK_RV card_detect(sc_reader_t *reader) { struct sc_pkcs11_card *p11card = NULL; - int rc; + int rc, free_p11card = 0; CK_RV rv; unsigned int i; int j; @@ -228,6 +228,7 @@ again: /* Detect the card if it's not known already */ if (p11card == NULL) { sc_log(context, "%s: First seen the card ", reader->name); + free_p11card = 1; p11card = (struct sc_pkcs11_card *)calloc(1, sizeof(struct sc_pkcs11_card)); if (!p11card) return CKR_HOST_MEMORY; @@ -316,6 +317,9 @@ again: } } + if (free_p11card) + free(p11card); + sc_log(context, "%s: Detection ended", reader->name); return CKR_OK; } diff --git a/src/pkcs15init/pkcs15-authentic.c b/src/pkcs15init/pkcs15-authentic.c index f15506c9..269379ac 100644 --- a/src/pkcs15init/pkcs15-authentic.c +++ b/src/pkcs15init/pkcs15-authentic.c @@ -258,6 +258,8 @@ authentic_pkcs15_new_file(struct sc_profile *profile, struct sc_card *card, file->path.type, sc_print_path(&file->path)); if (out) *out = file; + else + sc_file_free(file); LOG_FUNC_RETURN(ctx, SC_SUCCESS); } diff --git a/src/pkcs15init/pkcs15-iasecc.c b/src/pkcs15init/pkcs15-iasecc.c index e12f460e..99e70468 100644 --- a/src/pkcs15init/pkcs15-iasecc.c +++ b/src/pkcs15init/pkcs15-iasecc.c @@ -246,6 +246,8 @@ iasecc_pkcs15_new_file(struct sc_profile *profile, struct sc_card *card, if (out) *out = file; + else + sc_file_free(file); LOG_FUNC_RETURN(ctx, SC_SUCCESS); } @@ -503,6 +505,8 @@ iasecc_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card, if (out) *out = sdo; + else + free(sdo); LOG_FUNC_RETURN(ctx, SC_SUCCESS); } @@ -565,6 +569,8 @@ iasecc_sdo_allocate_pubkey(struct sc_profile *profile, struct sc_card *card, str if (out) *out = sdo; + else + free(sdo); LOG_FUNC_RETURN(ctx, SC_SUCCESS); } @@ -609,6 +615,9 @@ iasecc_sdo_convert_to_file(struct sc_card *card, struct iasecc_sdo *sdo, struct if (out) *out = file; + else + sc_file_free(file); + LOG_FUNC_RETURN(ctx, SC_SUCCESS); } diff --git a/src/pkcs15init/pkcs15-westcos.c b/src/pkcs15init/pkcs15-westcos.c index 1fc70b4a..023ede60 100644 --- a/src/pkcs15init/pkcs15-westcos.c +++ b/src/pkcs15init/pkcs15-westcos.c @@ -352,6 +352,3 @@ struct sc_pkcs15init_operations* sc_pkcs15init_get_westcos_ops(void) { return &sc_pkcs15init_westcos_operations; } - - - diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index fd9f4b3a..5d975d59 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -381,6 +381,7 @@ static int do_dump_do(sc_card_t *card, unsigned int tag) if (sizeof(buffer) != r) { return EXIT_FAILURE; } + close(tmp); } else { util_hex_dump_asc(stdout, buffer, sizeof(buffer), -1); } diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index bddbca8b..337e0b73 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -495,6 +495,7 @@ int main(int argc, char * const argv[]) break; case 'Z': compress_cert = 1; + break; case 'C': do_load_cert = 1; cert_id = optarg; diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 2cc3a636..05a5c40e 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -1327,12 +1327,17 @@ static int unlock_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess, int login_type) if (r < 0) return 1; if (!new_pin || !*new_pin || strcmp(new_buf, new_pin) != 0) { + if (new_pin != opt_new_pin) + free(new_pin); printf(" different new PINs, exiting\n"); return -1; } - if (!new_pin || !*new_pin || strlen(new_pin) > 20) + if (!new_pin || !*new_pin || strlen(new_pin) > 20) { + if (new_pin != opt_new_pin) + free(new_pin); return 1; + } } rv = p11->C_SetPIN(sess, diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index c3d6818e..98b285f8 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -684,10 +684,10 @@ do_erase(sc_card_t *in_card, struct sc_profile *profile) struct sc_aid aid; aid.len = sizeof(aid.value); - if (sc_hex_to_bin(opt_bind_to_aid, aid.value, &aid.len)) { + r = sc_hex_to_bin(opt_bind_to_aid, aid.value, &aid.len); + if (r < 0) { fprintf(stderr, "Invalid AID value: '%s'\n", opt_bind_to_aid); - return 1; - + goto err; } r = sc_pkcs15init_erase_card(p15card, profile, &aid); @@ -697,6 +697,7 @@ do_erase(sc_card_t *in_card, struct sc_profile *profile) } ignore_cmdline_pins--; +err: sc_pkcs15_card_free(p15card); return r; } From 08eb700b9749c17e8ff29ddb45b3132d8d38308e Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 7 Feb 2015 18:55:02 +0100 Subject: [PATCH 082/306] revert or partially revert some of recent commits b94c163 - invalid, non-tested 11881a6 -- src/libopensc/card-iasecc.c -- return from select has to be ignored, 3a92bf7 -- src/pkcs11/slot.c -- SEGFAULT issue #373 3a92bf7 -- src/tools/piv-tool.c -- confirmed by author 6759c04 -- src/pkcs15init/pkcs15-lib.c -- file instantiation error has to be ignored --- src/libopensc/card-asepcos.c | 4 ++-- src/libopensc/card-iasecc.c | 7 ++----- src/libopensc/pkcs15.c | 1 - src/pkcs11/slot.c | 6 +----- src/pkcs15init/pkcs15-lib.c | 3 +-- src/pkcs15init/pkcs15-myeid.c | 5 ++--- src/tools/piv-tool.c | 5 ++++- 7 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/libopensc/card-asepcos.c b/src/libopensc/card-asepcos.c index f46be32b..05f8b399 100644 --- a/src/libopensc/card-asepcos.c +++ b/src/libopensc/card-asepcos.c @@ -872,8 +872,8 @@ static int asepcos_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu, memcpy(p, data->pin1.data, data->pin1.len); p += data->pin1.len; } else { - memcpy(p, data->pin2.data, data->pin2.len); - p += data->pin2.len; + memcpy(p, data->pin1.data, data->pin1.len); + p += data->pin1.len; } apdu->lc = p - buf; apdu->datalen = p - buf; diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 0673d281..ea6d4973 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -415,7 +415,7 @@ iasecc_init_gemalto(struct sc_card *card) sc_format_path("3F00", &path); rv = sc_select_file(card, &path, NULL); - LOG_TEST_RET(ctx, rv, "MF selection error"); + /* Result ignored*/ rv = iasecc_parse_ef_atr(card); sc_log(ctx, "rv %i", rv); @@ -2343,10 +2343,7 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_ if (scb & IASECC_SCB_METHOD_SM) { rv = iasecc_sm_pin_reset(card, se_num, data); - LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_reset() reset PUK error"); - - if (!need_all) - break; + LOG_FUNC_RETURN(ctx, rv); } if (scb & IASECC_SCB_METHOD_EXT_AUTH) { diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 35174ba7..fa1120ee 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -1311,7 +1311,6 @@ __sc_pkcs15_search_objects(struct sc_pkcs15_card *p15card, unsigned int class_ma continue; /* Enumerate the DF's, so p15card->obj_list is * populated. */ - /* FIXME dont ignore errors */ if (SC_SUCCESS != sc_pkcs15_parse_df(p15card, df)) continue; } diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 336b3e26..87b1e3dd 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -183,7 +183,7 @@ CK_RV card_removed(sc_reader_t * reader) CK_RV card_detect(sc_reader_t *reader) { struct sc_pkcs11_card *p11card = NULL; - int rc, free_p11card = 0; + int rc; CK_RV rv; unsigned int i; int j; @@ -228,7 +228,6 @@ again: /* Detect the card if it's not known already */ if (p11card == NULL) { sc_log(context, "%s: First seen the card ", reader->name); - free_p11card = 1; p11card = (struct sc_pkcs11_card *)calloc(1, sizeof(struct sc_pkcs11_card)); if (!p11card) return CKR_HOST_MEMORY; @@ -317,9 +316,6 @@ again: } } - if (free_p11card) - free(p11card); - sc_log(context, "%s: Detection ended", reader->name); return CKR_OK; } diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 61e157c3..d073fff4 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -2679,8 +2679,7 @@ sc_pkcs15init_update_any_df(struct sc_pkcs15_card *p15card, LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "DF missing"); r = sc_profile_get_file_by_path(profile, &df->path, &file); - LOG_TEST_RET(ctx, r, "Failed get file path"); - if (file == NULL) + if (r < 0 || file == NULL) sc_select_file(card, &df->path, &file); r = sc_pkcs15_encode_df(card->ctx, p15card, df, &buf, &bufsize); diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index a7ce7ea3..ab7b2261 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -436,6 +436,8 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, r = myeid_new_file(profile, card, object->type, key_info->key_reference, &file); LOG_TEST_RET(ctx, r, "Cannot get new MyEID private key file"); + if (file || !file->path.len) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot determine private key file"); sc_log(ctx, "Key file size %d", keybits); file->size = keybits; @@ -445,9 +447,6 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, file->ef_structure = SC_CARDCTL_MYEID_KEY_EC; memcpy(&key_info->path.value, &file->path.value, file->path.len); - if (!file->path.len) - LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, - "Cannot determine private key file"); key_info->key_reference = file->path.value[file->path.len - 1] & 0xFF; sc_log(ctx, "Path of MyEID private key file to create %s", diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index 337e0b73..053c97ba 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -494,8 +494,11 @@ int main(int argc, char * const argv[]) action_count++; break; case 'Z': + /* + -Z is the same as -C but -Z says the cert is compressed. + https://github.com/OpenSC/OpenSC/commit/3a92bf7af5aaa85fdbc0434d0a55393e68e0f98d#commitcomment-9636487 + */ compress_cert = 1; - break; case 'C': do_load_cert = 1; cert_id = optarg; From faaa11e091001f063dac46f29f0aad28c2494a18 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Wed, 28 Jan 2015 22:59:28 +0100 Subject: [PATCH 083/306] Prefer serial number from EF(TokenInfo) and cached serials over CARDCTL sc_pkcs15_get_object_guid() should prefer the serial number from EF(TokenInfo) over card->serialnr because the user may override the card's serial number with "pkcs15-init -C --serial". The card->serialnr should be used before calling card CTL with SC_CARDCTL_GET_SERIALNR because it might contain a cached value. This change *should* allow cards to be used with the minidriver even if SC_CARDCTL_GET_SERIALNR is not implemented. For example, a driver might set card->serialnr at initialization or the user might initialize a PKCS#15 card with its own "--serial". See also the discussion at the mailing list: [Opensc-devel] AT_SIGNATURE and AT_EXCHANGE Problem --- src/libopensc/pkcs15.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index fa1120ee..346e30a6 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -2725,19 +2725,36 @@ sc_pkcs15_get_object_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15 rv = sc_pkcs15_get_object_id(obj, &id); LOG_TEST_RET(ctx, rv, "Cannot get object's ID"); - rv = sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &serialnr); - LOG_TEST_RET(ctx, rv, "'GET_SERIALNR' failed"); + if (p15card->tokeninfo && p15card->tokeninfo->serial_number) { + /* The serial from EF(TokenInfo) is preferred because of the + * "--serial" parameter of pkcs15-init. */ + serialnr.len = SC_MAX_SERIALNR; + rv = sc_hex_to_bin(p15card->tokeninfo->serial_number, serialnr.value, &serialnr.len); + if (rv) { + /* Fallback in case hex_to_bin fails due to unexpected characters */ + serialnr.len = strlen(p15card->tokeninfo->serial_number); + if (serialnr.len > SC_MAX_SERIALNR) + serialnr.len = SC_MAX_SERIALNR; + + memcpy(serialnr.value, p15card->tokeninfo->serial_number, serialnr.len); + } + } else if (p15card->card->serialnr.len) { + serialnr = p15card->card->serialnr; + } else { + rv = sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &serialnr); + LOG_TEST_RET(ctx, rv, "'GET_SERIALNR' CTL failed and other serial numbers not present"); + } memset(guid_bin, 0, sizeof(guid_bin)); memcpy(guid_bin, id.value, id.len); memcpy(guid_bin + id.len, serialnr.value, serialnr.len); - // If OpenSSL is available (SHA1), then rather use the hash of the data - // - this also protects against data being too short + // If OpenSSL is available (SHA1), then rather use the hash of the data + // - this also protects against data being too short #ifdef ENABLE_OPENSSL - SHA1(guid_bin, id.len + serialnr.len, guid_bin); - id.len = SHA_DIGEST_LENGTH; - serialnr.len = 0; + SHA1(guid_bin, id.len + serialnr.len, guid_bin); + id.len = SHA_DIGEST_LENGTH; + serialnr.len = 0; #endif rv = sc_pkcs15_serialize_guid(guid_bin, id.len + serialnr.len, flags, (char *)out, *out_size); From 9148f21cd1079c53796b420f16e42b3b365d41aa Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Mon, 2 Feb 2015 16:34:37 +0100 Subject: [PATCH 084/306] pkcs15-pubkey: possible NULL dereference, logs ... remove obsolete comments, minor coding style corrections --- src/libopensc/pkcs15-pubkey.c | 50 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 63bd067d..97870e36 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -75,7 +75,7 @@ static const struct sc_asn1_entry c_asn1_rsakey_value_choice[C_ASN1_RSAKEY_VALUE #define C_ASN1_RSAKEY_ATTR_SIZE 4 static const struct sc_asn1_entry c_asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE] = { - { "value", SC_ASN1_CHOICE, 0, 0, NULL, NULL }, + { "value", SC_ASN1_CHOICE, 0, 0, NULL, NULL }, { "modulusLength", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, { "keyInfo", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } @@ -90,9 +90,7 @@ static const struct sc_asn1_entry c_asn1_eckey_value_choice[C_ASN1_ECKEY_VALUE_C #define C_ASN1_ECKEY_ATTR_SIZE 3 static const struct sc_asn1_entry c_asn1_eckey_attr[C_ASN1_ECKEY_ATTR_SIZE] = { - { "value", SC_ASN1_CHOICE, 0, 0, NULL, NULL }, - /* VTA: 'fieldSize' is not in PKCS#15 specification */ - /* { "fieldSize", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, */ + { "value", SC_ASN1_CHOICE, 0, 0, NULL, NULL }, { "keyInfo", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; @@ -270,8 +268,6 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, sc_format_asn1_entry(asn1_eckey_value_choice + 1, &der->value, &der->len, 0); sc_format_asn1_entry(asn1_eckey_attr + 0, asn1_eckey_value_choice, NULL, 0); - /* VTA: TODO 'fieldSize' is not in PKCS#15 specification */ - /* sc_format_asn1_entry(asn1_eckey_attr + 1, &info.field_length, NULL, 0); */ sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 0); @@ -339,8 +335,8 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, sc_log(ctx, "PubKey path '%s'", sc_print_path(&info.path)); /* OpenSC 0.11.4 and older encoded "keyReference" as a negative - value. Fixed in 0.11.5 we need to add a hack, so old cards - continue to work. */ + value. Fixed in 0.11.5 we need to add a hack, so old cards + continue to work. */ if (info.key_reference < -1) info.key_reference += 256; @@ -491,8 +487,6 @@ sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx, const struct sc_pkcs15_obje } sc_format_asn1_entry(asn1_eckey_attr + 0, asn1_eckey_value_choice, NULL, 1); - /* VTA: TODO 'fieldSize' is not in PKCS#15 specification */ - /* sc_format_asn1_entry(asn1_eckey_attr + 1, &pubkey->field_length, NULL, 1); */ break; default: @@ -771,7 +765,7 @@ sc_pkcs15_encode_pubkey(sc_context_t *ctx, struct sc_pkcs15_pubkey *key, static const struct sc_asn1_entry c_asn1_spki_key_items[] = { { "algorithm", SC_ASN1_ALGORITHM_ID, SC_ASN1_CONS| SC_ASN1_TAG_SEQUENCE, 0, NULL, NULL}, - { "key", SC_ASN1_BIT_STRING_NI, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL }, + { "key", SC_ASN1_BIT_STRING_NI, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; @@ -1249,7 +1243,7 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke unsigned char *tmp_buf = NULL; int r; - sc_log(ctx, "sc_pkcs15_pubkey_from_spki_fields %p:%d %s", buf, buflen, sc_dump_hex(buf, buflen)); + sc_log(ctx, "sc_pkcs15_pubkey_from_spki_fields() called: %p:%d\n%s", buf, buflen, sc_dump_hex(buf, buflen)); tmp_buf = malloc(buflen); if (!tmp_buf) @@ -1294,7 +1288,8 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke memcpy(pubkey->u.ec.params.der.value, ecp->der, ecp->der_len); pubkey->u.ec.params.der.len = ecp->der_len; - sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); + r = sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); + LOG_TEST_RET(ctx, r, "failed to fix EC parameters"); } pubkey->u.ec.params.field_length = (pk.len - 1)/2 * 8; @@ -1321,42 +1316,45 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke int -sc_pkcs15_pubkey_from_spki_sequence(sc_context_t *ctx, const u8 *buf, size_t buflen, - sc_pkcs15_pubkey_t ** outpubkey) +sc_pkcs15_pubkey_from_spki_sequence(struct sc_context *ctx, const unsigned char *buf, size_t buflen, + struct sc_pkcs15_pubkey ** outpubkey) { - int r; - sc_pkcs15_pubkey_t * pubkey = NULL; + struct sc_pkcs15_pubkey * pubkey = NULL; struct sc_asn1_entry asn1_spki[] = { { "subjectPublicKeyInfo", SC_ASN1_CALLBACK, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, sc_pkcs15_pubkey_from_spki_fields, &pubkey}, { NULL, 0, 0, 0, NULL, NULL } }; + int r; - *outpubkey = NULL; + LOG_FUNC_CALLED(ctx); r = sc_asn1_decode(ctx, asn1_spki, buf, buflen, NULL, NULL); + LOG_TEST_RET(ctx, r, "ASN.1 cannot parse subjectPublicKeyInfo"); - *outpubkey = pubkey; - return r; + if(outpubkey) + *outpubkey = pubkey; + + LOG_FUNC_RETURN(ctx, r); } int -sc_pkcs15_pubkey_from_spki_file(sc_context_t *ctx, char * filename, - sc_pkcs15_pubkey_t ** outpubkey) +sc_pkcs15_pubkey_from_spki_file(struct sc_context *ctx, char * filename, + struct sc_pkcs15_pubkey ** outpubkey) { int r; u8 * buf = NULL; size_t buflen = 0; + LOG_FUNC_CALLED(ctx); + r = sc_pkcs15_read_der_file(ctx, filename, &buf, &buflen); - if (r < 0) - return r; + LOG_TEST_RET(ctx, r, "Cannot read SPKI DER file"); r = sc_pkcs15_pubkey_from_spki_sequence(ctx, buf, buflen, outpubkey); - if (buf) free(buf); - return r; + LOG_FUNC_RETURN(ctx, r); } From e374f88b82b047a55ce557f3e90a80b76eb0108e Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Mon, 2 Feb 2015 16:39:18 +0100 Subject: [PATCH 085/306] pkcs15-pubkey: add EC params in SPKI encoding --- src/libopensc/pkcs15-algo.c | 41 ++++++++++++++++++----------------- src/libopensc/pkcs15-pubkey.c | 23 ++++++++++++++++---- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index ce06f4e6..0bc69028 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -468,52 +468,51 @@ sc_asn1_get_algorithm_info(const struct sc_algorithm_id *id) return NULL; } -static const struct sc_asn1_entry c_asn1_alg_id[6] = { +static const struct sc_asn1_entry c_asn1_alg_id[3] = { { "algorithm", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL }, { "nullParam", SC_ASN1_NULL, SC_ASN1_TAG_NULL, SC_ASN1_OPTIONAL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; int -sc_asn1_decode_algorithm_id(sc_context_t *ctx, const u8 *in, +sc_asn1_decode_algorithm_id(struct sc_context *ctx, const unsigned char *in, size_t len, struct sc_algorithm_id *id, int depth) { - struct sc_asn1_pkcs15_algorithm_info *alg_info; + struct sc_asn1_pkcs15_algorithm_info *alg_info = NULL; struct sc_asn1_entry asn1_alg_id[3]; int r; + LOG_FUNC_CALLED(ctx); sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id); sc_format_asn1_entry(asn1_alg_id + 0, &id->oid, NULL, 0); memset(id, 0, sizeof(*id)); r = _sc_asn1_decode(ctx, asn1_alg_id, in, len, &in, &len, 0, depth + 1); - if (r < 0) - return r; + LOG_TEST_RET(ctx, r, "ASN.1 parsing of algo ID failed"); + + sc_log(ctx, "decoded OID '%s'", sc_dump_oid(&(id->oid))); /* See if we understand the algorithm, and if we do, check * whether we know how to decode any additional parameters */ id->algorithm = (unsigned int ) -1; - if ((alg_info = sc_asn1_get_algorithm_info(id)) != NULL) { + alg_info = sc_asn1_get_algorithm_info(id); + if (alg_info != NULL) { id->algorithm = alg_info->id; if (alg_info->decode) { -/* TODO: -DEE why the test for SC_ASN1_PRESENT? - * If it looking for SC_ASN1_NULL, thats valid for EC, in some cases - */ if (asn1_alg_id[1].flags & SC_ASN1_PRESENT) { - sc_debug( ctx,SC_LOG_DEBUG_NORMAL,"SC_ASN1_PRESENT was set, so invalid"); - return SC_ERROR_INVALID_ASN1_OBJECT; + sc_log(ctx, "SC_ASN1_PRESENT was set, so invalid"); + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ASN1_OBJECT); } r = alg_info->decode(ctx, &id->params, in, len, depth); } } - return r; + LOG_FUNC_RETURN(ctx, r); } int -sc_asn1_encode_algorithm_id(sc_context_t *ctx, - u8 **buf, size_t *len, +sc_asn1_encode_algorithm_id(struct sc_context *ctx, u8 **buf, size_t *len, const struct sc_algorithm_id *id, int depth) { @@ -525,10 +524,12 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx, int r; u8 *tmp; + LOG_FUNC_CALLED(ctx); + sc_log(ctx, "type of algorithm to encode: %i", id->algorithm); alg_info = sc_asn1_get_algorithm_info(id); if (alg_info == NULL) { sc_log(ctx, "Cannot encode unknown algorithm %u", id->algorithm); - return SC_ERROR_INVALID_ARGUMENTS; + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); } /* Set the oid if not yet given */ @@ -538,6 +539,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx, id = &temp_id; } + sc_log(ctx, "encode algo %s", sc_dump_oid(&(id->oid))); sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id); sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->oid, NULL, 1); @@ -546,8 +548,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx, asn1_alg_id[1].flags |= SC_ASN1_PRESENT; r = _sc_asn1_encode(ctx, asn1_alg_id, buf, len, depth + 1); - if (r < 0) - return r; + LOG_TEST_RET(ctx, r, "ASN.1 encode of algorithm failed"); /* Encode any parameters */ if (id->params && alg_info->encode) { @@ -555,7 +556,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx, if (r < 0) { if (obj) free(obj); - return r; + LOG_FUNC_RETURN(ctx, r); } } @@ -565,7 +566,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx, free(*buf); *buf = NULL; free(obj); - return SC_ERROR_OUT_OF_MEMORY; + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); } *buf = tmp; memcpy(*buf + *len, obj, obj_len); @@ -574,7 +575,7 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx, } sc_log(ctx, "return encoded algorithm ID: %s", sc_dump_hex(*buf, *len)); - return 0; + LOG_FUNC_RETURN(ctx, SC_SUCCESS); } void diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 97870e36..8b96d8e3 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -781,7 +781,7 @@ int sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubkey, u8 **buf, size_t *len) { - int r; + int r = 0; struct sc_asn1_entry asn1_spki_key[2], asn1_spki_key_items[3]; struct sc_pkcs15_u8 pkey; size_t key_len; @@ -810,9 +810,24 @@ sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubk key_len = pubkey->u.ec.ecpointQ.len * 8; pkey.value = pubkey->u.ec.ecpointQ.value; pkey.len = 0; /* flag as do not delete */ - /* TODO make sure algorithm params are available*/ - /* if not can we copy them from the u.ec */ - r = 0; + + if (pubkey->u.ec.params.named_curve || pubkey->u.ec.params.der.value) { + struct sc_ec_params *ec_params = NULL; + + r = sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); + LOG_TEST_RET(ctx, r, "failed to fix EC parameters"); + + ec_params = calloc(1, sizeof(struct sc_ec_params)); + if (!ec_params) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + ec_params->type = 1; + ec_params->der = calloc(pubkey->u.ec.params.der.len, 1); + if (!ec_params->der) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + memcpy(ec_params->der, pubkey->u.ec.params.der.value, pubkey->u.ec.params.der.len); + ec_params->der_len = pubkey->u.ec.params.der.len; + pubkey->alg_id->params = ec_params; + } break; case SC_ALGORITHM_GOSTR3410: /* TODO is this needed? does it cause mem leak? */ From 96265e6d08a0be51d7d83468d9e42bd54a7b409a Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Tue, 3 Feb 2015 19:05:19 +0100 Subject: [PATCH 086/306] pkcs15init: superpluous 'ec-params' in init data Pkcs15init data, used to import/generate key objects, includes twice the same EC parameters data: - explicit 'params' data - part of sc_pkcs15_pubkey/sc_pkcs15_prkey Explicit 'ec-params' data is removed. --- src/pkcs11/framework-pkcs15.c | 2 +- src/pkcs15init/pkcs15-init.h | 2 -- src/pkcs15init/pkcs15-lib.c | 22 +++++++++++++--------- src/tools/pkcs15-init.c | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index fc7c4cf2..dd707067 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -2751,7 +2751,7 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, /* TODO: check allowed values of keybits */ } else if (keytype == CKK_EC) { - struct sc_pkcs15_der *der = &keygen_args.prkey_args.params.ec.der; + struct sc_pkcs15_der *der = &keygen_args.prkey_args.key.u.ec.params.der; der->len = sizeof(struct sc_object_id); rv = attr_find_ptr(pPubTpl, ulPubCnt, CKA_EC_PARAMS, (void **)&der->value, &der->len); diff --git a/src/pkcs15init/pkcs15-init.h b/src/pkcs15init/pkcs15-init.h index a301b200..c40ff7f6 100644 --- a/src/pkcs15init/pkcs15-init.h +++ b/src/pkcs15init/pkcs15-init.h @@ -216,7 +216,6 @@ struct sc_pkcs15init_prkeyargs { union { struct sc_pkcs15init_keyarg_gost_params gost; - struct sc_pkcs15_ec_parameters ec; } params; struct sc_pkcs15_prkey key; @@ -236,7 +235,6 @@ struct sc_pkcs15init_pubkeyargs { union { struct sc_pkcs15init_keyarg_gost_params gost; - struct sc_pkcs15_ec_parameters ec; } params; struct sc_pkcs15_pubkey key; diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index d073fff4..e5d30a81 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1214,8 +1214,8 @@ sc_pkcs15init_init_prkdf(struct sc_pkcs15_card *p15card, struct sc_profile *prof keyinfo_gostparams->gost28147 = keyargs->params.gost.gost28147; } else if (key->algorithm == SC_ALGORITHM_EC) { - struct sc_pkcs15_ec_parameters *ecparams = &keyargs->params.ec; - key_info->params.data = &keyargs->params.ec; + struct sc_pkcs15_ec_parameters *ecparams = &keyargs->key.u.ec.params; + key_info->params.data = &keyargs->key.u.ec.params; key_info->params.free_params = sc_pkcs15init_empty_callback; key_info->field_length = ecparams->field_length; } @@ -1317,7 +1317,7 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr if (keygen_args->prkey_args.key.algorithm == SC_ALGORITHM_GOSTR3410) pubkey_args.params.gost = keygen_args->prkey_args.params.gost; else if (keygen_args->prkey_args.key.algorithm == SC_ALGORITHM_EC) - pubkey_args.params.ec = keygen_args->prkey_args.params.ec; + pubkey_args.key.u.ec.params = keygen_args->prkey_args.key.u.ec.params; /* Generate the private key on card */ r = profile->ops->create_key(profile, p15card, object); @@ -1504,8 +1504,9 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, struct sc_profile case SC_ALGORITHM_EC: type = SC_PKCS15_TYPE_PUBKEY_EC; - key.u.ec.params = keyargs->params.ec; - sc_pkcs15_fix_ec_parameters(ctx, &key.u.ec.params); + key.u.ec.params = keyargs->key.u.ec.params; + r = sc_pkcs15_fix_ec_parameters(ctx, &key.u.ec.params); + LOG_TEST_RET(ctx, r, "Failed to fix EC public key parameters"); keybits = key.u.ec.params.field_length; break; @@ -1974,7 +1975,7 @@ check_keygen_params_consistency(struct sc_card *card, struct sc_pkcs15init_keyge int i, rv; if (alg == SC_ALGORITHM_EC) { - struct sc_pkcs15_ec_parameters *ecparams = ¶ms->prkey_args.params.ec; + struct sc_pkcs15_ec_parameters *ecparams = ¶ms->prkey_args.key.u.ec.params; rv = sc_pkcs15_fix_ec_parameters(ctx, ecparams); LOG_TEST_RET(ctx, rv, "Cannot fix EC parameters"); @@ -2152,9 +2153,12 @@ prkey_bits(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *key) } return SC_PKCS15_GOSTR3410_KEYSIZE; case SC_ALGORITHM_EC: - /* calculation returns one bit too small, add one bu default */ - sc_log(ctx, "Private EC key length %u", sc_pkcs15init_keybits(&key->u.ec.privateD) + 1); - return sc_pkcs15init_keybits(&key->u.ec.privateD) + 1; + sc_log(ctx, "Private EC key length %u", key->u.ec.params.field_length); + if (key->u.ec.params.field_length == 0) { + sc_log(ctx, "Invalid EC key length"); + return SC_ERROR_OBJECT_NOT_VALID; + } + return key->u.ec.params.field_length; } sc_log(ctx, "Unsupported key algorithm."); return SC_ERROR_NOT_SUPPORTED; diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 98b285f8..6558593a 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -1525,7 +1525,7 @@ do_generate_key(struct sc_profile *profile, const char *spec) if (*spec) { if (isalpha(*spec) && keygen_args.prkey_args.key.algorithm == SC_ALGORITHM_EC) { - keygen_args.prkey_args.params.ec.named_curve = strdup(spec); + keygen_args.prkey_args.key.u.ec.params.named_curve = strdup(spec); keybits = 0; } else { From 22fb49b5545a09bf7b4be071ef189388e6a582b1 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Wed, 28 Jan 2015 17:57:58 +0100 Subject: [PATCH 087/306] PKCS#11: Improve compliance for public keys. * Key usage required when calling C_CreateObject for public key are not used. This adds the logic to convert from PKCS#11 attributes to PKCS#15 in the structure that is sent to underlying _store_pubkey functions. --- src/pkcs11/framework-pkcs15.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index dd707067..9111e510 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -2276,6 +2276,18 @@ pkcs15_create_public_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile bn = &rsa->modulus; break; case CKA_PUBLIC_EXPONENT: bn = &rsa->exponent; break; + case CKA_VERIFY: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_VERIFY); + break; + case CKA_VERIFY_RECOVER: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER); + break; + case CKA_ENCRYPT: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_ENCRYPT); + break; + case CKA_WRAP: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_WRAP); + break; default: /* ignore unknown attrs, or flag error? */ continue; From d1621439648f29b0b1a5306bdf108007e695380b Mon Sep 17 00:00:00 2001 From: Martin Campbell Date: Wed, 28 Jan 2015 11:54:58 +0000 Subject: [PATCH 088/306] Updating to fix failure of ePass2003 USB smart card due to failure to re-authenticate secure messaging when card is reset due to multiple applications using PKCS11 sessions --- src/libopensc/card-epass2003.c | 5 ++--- src/libopensc/card.c | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c index af37b6ee..162e00d0 100644 --- a/src/libopensc/card-epass2003.c +++ b/src/libopensc/card-epass2003.c @@ -450,7 +450,9 @@ epass2003_refresh(struct sc_card *card) int r = SC_SUCCESS; if (g_sm) { + card->sm_ctx.sm_mode = 0; r = mutual_auth(card, g_init_key_enc, g_init_key_mac); + card->sm_ctx.sm_mode = SM_MODE_TRANSMIT; LOG_TEST_RET(card->ctx, r, "mutual_auth failed"); } @@ -947,9 +949,6 @@ epass2003_init(struct sc_card *card) card->name = "epass2003"; card->cla = 0x00; card->drv_data = NULL; -/* VT - card->ctx->use_sm = 1; -*/ g_sm = SM_SCP01; /* g_sm = SM_PLAIN; */ diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 6b384069..d40dc821 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -335,6 +335,10 @@ int sc_lock(sc_card_t *card) /* invalidate cache */ memset(&card->cache, 0, sizeof(card->cache)); card->cache.valid = 0; +#ifdef ENABLE_SM + if (card->sm_ctx.ops.open) + card->sm_ctx.ops.open(card); +#endif r = card->reader->ops->lock(card->reader); } } From 3c1d8ad69557adf6aab08bc549188425c8b33a92 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 7 Feb 2015 21:14:17 +0100 Subject: [PATCH 089/306] accept no output for 'SELECT' MF and 'SELECT' DF_NAME PR #342 --- src/libopensc/iso7816.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 85062651..c37bbf04 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -453,6 +453,7 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct unsigned char buf[SC_MAX_APDU_BUFFER_SIZE]; unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf; int r, pathlen, pathtype; + int select_mf = 0; struct sc_file *file = NULL; assert(card != NULL && in_path != NULL); @@ -500,6 +501,7 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct apdu.p1 = 8; if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) { if (pathlen == 2) { /* only 3F00 supplied */ + select_mf = 1; apdu.p1 = 0; break; } @@ -552,6 +554,19 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct if (r) LOG_FUNC_RETURN(ctx, r); + if (file_out && (apdu.resplen == 0)) { + /* For some cards 'SELECT' MF or DF_NAME do not return FCI. */ + if (select_mf || pathtype == SC_PATH_TYPE_DF_NAME) { + file = sc_file_new(); + if (file == NULL) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + file->path = *in_path; + + *file_out = file; + LOG_FUNC_RETURN(ctx, SC_SUCCESS); + } + } + if (apdu.resplen < 2) LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); switch (apdu.resp[0]) { From 981a0fbbaf36b9f2e0b725e5c19c7a42e3e32c61 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 11 Feb 2015 13:39:59 -0600 Subject: [PATCH 090/306] Fix-up changes caused by Coverity scan piv-tool.c add /* fall through */ to avoif false warning card-piv.c - clean up if sc_lock fails. --- src/libopensc/card-piv.c | 6 ++++-- src/tools/piv-tool.c | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index 21f83934..d25c4406 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -1557,7 +1557,8 @@ static int piv_general_mutual_authenticate(sc_card_t *card, r = sc_lock(card); if (r != SC_SUCCESS) - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n"); + goto err; /* cleanup */ locked = 1; p = sbuf; @@ -1827,7 +1828,8 @@ static int piv_general_external_authenticate(sc_card_t *card, r = sc_lock(card); if (r != SC_SUCCESS) - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n"); + goto err; /* cleanup */ locked = 1; p = sbuf; diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index 053c97ba..f750c14f 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -494,10 +494,7 @@ int main(int argc, char * const argv[]) action_count++; break; case 'Z': - /* - -Z is the same as -C but -Z says the cert is compressed. - https://github.com/OpenSC/OpenSC/commit/3a92bf7af5aaa85fdbc0434d0a55393e68e0f98d#commitcomment-9636487 - */ + /* fall through */ compress_cert = 1; case 'C': do_load_cert = 1; From 0ffad3f3bb9c893ab5a06998c7c7f0d571e7918d Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Mon, 9 Feb 2015 02:13:37 -0800 Subject: [PATCH 091/306] Fix for bad caching behavior of PIV PKCS15 emulator. --- src/libopensc/pkcs15-piv.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index 7f465987..724987bd 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -735,11 +735,13 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) ckis[i].cert_found = 1; /* cache it using the PKCS15 emulation objects */ /* as it does not change */ - if (cert_der.value) { - cert_info.value.value = cert_der.value; - cert_info.value.len = cert_der.len; - cert_info.path.len = 0; /* use in mem cert from now on */ - } + if (cert_der.value) { + cert_info.value.value = cert_der.value; + cert_info.value.len = cert_der.len; + if (!p15card->opts.use_file_cache) { + cert_info.path.len = 0; /* use in mem cert from now on */ + } + } /* following will find the cached cert in cert_info */ r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); if (r < 0 || cert_out->key == NULL) { From 14ed749a88432f1b061302dd75a55e27b5d2be79 Mon Sep 17 00:00:00 2001 From: Martin Paljak Date: Fri, 13 Feb 2015 16:52:10 +0200 Subject: [PATCH 092/306] Create CONTRIBUTING.md So that new issues and pull requests could get some information. --- CONTRIBUTING.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..d587910a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Reporting Bugs + +Please read about [reporting bugs](https://github.com/OpenSC/OpenSC/wiki/How-to-report-bugs-so-that-they-can-be-fixed) before opening an issue. From 572218c59c8323c76a243763604801fb3587bf63 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Mon, 16 Feb 2015 10:11:24 -0600 Subject: [PATCH 093/306] Fall through comment before break --- src/tools/piv-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/piv-tool.c b/src/tools/piv-tool.c index f750c14f..acf79798 100644 --- a/src/tools/piv-tool.c +++ b/src/tools/piv-tool.c @@ -494,8 +494,8 @@ int main(int argc, char * const argv[]) action_count++; break; case 'Z': - /* fall through */ compress_cert = 1; + /* fall through */ case 'C': do_load_cert = 1; cert_id = optarg; From d7475c8180c7fe96a85f13184c05bbe0fec20c3c Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Mon, 16 Feb 2015 10:43:19 -0600 Subject: [PATCH 094/306] Add brackets in card-piv.c --- src/libopensc/card-piv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index d25c4406..62ac7df1 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -1556,9 +1556,10 @@ static int piv_general_mutual_authenticate(sc_card_t *card, } r = sc_lock(card); - if (r != SC_SUCCESS) + if (r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n"); goto err; /* cleanup */ + } locked = 1; p = sbuf; @@ -1827,9 +1828,10 @@ static int piv_general_external_authenticate(sc_card_t *card, } r = sc_lock(card); - if (r != SC_SUCCESS) + if (r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "sc_lock failed\n"); goto err; /* cleanup */ + } locked = 1; p = sbuf; From fa923831f8e8073f0b57ea492c9e2e93f661a373 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 14 Feb 2015 17:47:59 +0100 Subject: [PATCH 095/306] introduce EC curve OID into algorithm info data needed to store information about EC curve supported by card. Primary usage is when importing/generating key to get know if particular curve is supported by card. --- src/libopensc/asn1.c | 2 +- src/libopensc/card-myeid.c | 6 +-- src/libopensc/card-piv.c | 4 +- src/libopensc/card-sc-hsm.c | 8 ++-- src/libopensc/card.c | 44 ++++++++++++++++--- src/libopensc/internal.h | 3 +- src/libopensc/opensc.h | 22 ++++++++-- src/libopensc/pkcs15-algo.c | 79 +++++++++++++++++----------------- src/libopensc/pkcs15-pubkey.c | 22 +++++----- src/libopensc/pkcs15-sc-hsm.c | 22 +++++----- src/libopensc/pkcs15-sec.c | 4 +- src/libopensc/pkcs15.h | 19 ++------ src/pkcs11/framework-pkcs15.c | 12 +++--- src/pkcs15init/pkcs15-lib.c | 16 +++++-- src/pkcs15init/pkcs15-sc-hsm.c | 2 +- 15 files changed, 152 insertions(+), 113 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index bed2c04c..189075ba 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -1804,7 +1804,7 @@ sc_encode_oid (struct sc_context *ctx, struct sc_object_id *id, unsigned char **out, size_t *size) { static const struct sc_asn1_entry c_asn1_object_id[2] = { - { "oid", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_ALLOC, NULL, NULL }, + { "oid", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_ALLOC, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; struct sc_asn1_entry asn1_object_id[2]; diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 4b253f16..d906e0ef 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -119,9 +119,9 @@ static int myeid_init(struct sc_card *card) flags |= SC_ALGORITHM_ECDSA_RAW; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; - _sc_card_add_ec_alg(card, 192, flags, ext_flags); - _sc_card_add_ec_alg(card, 224, flags, ext_flags); - _sc_card_add_ec_alg(card, 256, flags, ext_flags); + _sc_card_add_ec_alg(card, 192, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 224, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); #endif /* State that we have an RNG */ diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index 62ac7df1..e397c599 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -2882,8 +2882,8 @@ static int piv_init(sc_card_t *card) flags = SC_ALGORITHM_ECDSA_RAW; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; - _sc_card_add_ec_alg(card, 256, flags, ext_flags); - _sc_card_add_ec_alg(card, 384, flags, ext_flags); + _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL); card->caps |= SC_CARD_CAP_RNG; diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index cb30ddcd..98f7b9e5 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -1053,10 +1053,10 @@ static int sc_hsm_init(struct sc_card *card) SC_ALGORITHM_EXT_EC_NAMEDCURVE| SC_ALGORITHM_EXT_EC_UNCOMPRESES| SC_ALGORITHM_ONBOARD_KEY_GEN; - _sc_card_add_ec_alg(card, 192, flags, ext_flags); - _sc_card_add_ec_alg(card, 224, flags, ext_flags); - _sc_card_add_ec_alg(card, 256, flags, ext_flags); - _sc_card_add_ec_alg(card, 320, flags, ext_flags); + _sc_card_add_ec_alg(card, 192, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 224, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 320, flags, ext_flags, NULL); card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT; diff --git a/src/libopensc/card.c b/src/libopensc/card.c index d40dc821..b0ae035f 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -95,15 +95,34 @@ static void sc_card_free(sc_card_t *card) { sc_free_apps(card); sc_free_ef_atr(card); + if (card->ef_dir != NULL) sc_file_free(card->ef_dir); + free(card->ops); - if (card->algorithms != NULL) + + if (card->algorithms != NULL) { + int i; + for (i=0; ialgorithm_count; i++) { + struct sc_algorithm_info *info = (card->algorithms + i); + if (info->algorithm == SC_ALGORITHM_EC) { + struct sc_ec_parameters ep = info->u._ec.params; + + free(ep.named_curve); + free(ep.der.value); + } + } + card->algorithms = NULL; + card->algorithm_count = 0; free(card->algorithms); + } + if (card->cache.current_ef) sc_file_free(card->cache.current_ef); + if (card->cache.current_df) sc_file_free(card->cache.current_df); + if (card->mutex != NULL) { int r = sc_mutex_destroy(card->ctx, card->mutex); if (r != SC_SUCCESS) @@ -806,21 +825,27 @@ int _sc_card_add_algorithm(sc_card_t *card, const sc_algorithm_info_t *info) } int _sc_card_add_ec_alg(sc_card_t *card, unsigned int key_length, - unsigned long flags, unsigned long ext_flags) + unsigned long flags, unsigned long ext_flags, + struct sc_object_id *curve_oid) { sc_algorithm_info_t info; memset(&info, 0, sizeof(info)); + sc_init_oid(&info.u._ec.params.id); + info.algorithm = SC_ALGORITHM_EC; info.key_length = key_length; info.flags = flags; + info.u._ec.ext_flags = ext_flags; + if (curve_oid) + info.u._ec.params.id = *curve_oid; return _sc_card_add_algorithm(card, &info); } static sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card, - unsigned int algorithm, unsigned int key_length) + unsigned int algorithm, unsigned int key_length, void *param) { int i; @@ -831,15 +856,20 @@ static sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card, continue; if (info->key_length != key_length) continue; + if (param) { + if (info->algorithm == SC_ALGORITHM_EC) + if(sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id)) + continue; + } return info; } return NULL; } sc_algorithm_info_t * sc_card_find_ec_alg(sc_card_t *card, - unsigned int key_length) + unsigned int key_length, struct sc_object_id *curve_name) { - return sc_card_find_alg(card, SC_ALGORITHM_EC, key_length); + return sc_card_find_alg(card, SC_ALGORITHM_EC, key_length, curve_name); } int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length, @@ -859,13 +889,13 @@ int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length, sc_algorithm_info_t * sc_card_find_rsa_alg(sc_card_t *card, unsigned int key_length) { - return sc_card_find_alg(card, SC_ALGORITHM_RSA, key_length); + return sc_card_find_alg(card, SC_ALGORITHM_RSA, key_length, NULL); } sc_algorithm_info_t * sc_card_find_gostr3410_alg(sc_card_t *card, unsigned int key_length) { - return sc_card_find_alg(card, SC_ALGORITHM_GOSTR3410, key_length); + return sc_card_find_alg(card, SC_ALGORITHM_GOSTR3410, key_length, NULL); } static int match_atr_table(sc_context_t *ctx, struct sc_atr_table *table, struct sc_atr *atr) diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h index 4edad3d8..2658428b 100644 --- a/src/libopensc/internal.h +++ b/src/libopensc/internal.h @@ -121,7 +121,8 @@ int _sc_card_add_algorithm(struct sc_card *card, const struct sc_algorithm_info int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length, unsigned long flags, unsigned long exponent); int _sc_card_add_ec_alg(struct sc_card *card, unsigned int key_length, - unsigned long flags, unsigned long ext_flags); + unsigned long flags, unsigned long ext_flags, + struct sc_object_id *curve_oid); /********************************************************************/ /* pkcs1 padding/encoding functions */ diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 5df97687..42d8bf10 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -191,10 +191,23 @@ struct sc_pbes2_params { struct sc_algorithm_id key_encr_alg; }; -struct sc_ec_params { +/* + * The ecParameters can be presented as + * - name of curve; + * - OID of named curve; + * - implicit parameters. + * + * type - type(choice) of 'EC domain parameters' as it present in CKA_EC_PARAMS (PKCS#11). + Recommended value '1' -- namedCurve. + * field_length - EC key size in bits. + */ +struct sc_ec_parameters { + char *named_curve; + struct sc_object_id id; + struct sc_lv_data der; + int type; - u8 * der; - size_t der_len; + size_t field_length; }; typedef struct sc_algorithm_info { @@ -208,6 +221,7 @@ typedef struct sc_algorithm_info { } _rsa; struct sc_ec_info { unsigned ext_flags; + struct sc_ec_parameters params; } _ec; } u; } sc_algorithm_info_t; @@ -1282,7 +1296,7 @@ void sc_print_cache(struct sc_card *card); struct sc_algorithm_info * sc_card_find_rsa_alg(struct sc_card *card, unsigned int key_length); struct sc_algorithm_info * sc_card_find_ec_alg(struct sc_card *card, - unsigned int field_length); + unsigned int field_length, struct sc_object_id *curve_oid); struct sc_algorithm_info * sc_card_find_gostr3410_alg(struct sc_card *card, unsigned int key_length); diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index 0bc69028..f66692de 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -249,8 +249,8 @@ asn1_free_pbes2_params(void *ptr) free(params); } -static const struct sc_asn1_entry c_asn1_ec_params[] = { - { "ecParameters", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, +static const struct sc_asn1_entry c_asn1_ec_params[] = { + { "ecParameters", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, { "namedCurve", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL}, { "implicityCA", SC_ASN1_NULL, SC_ASN1_TAG_NULL, 0, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } @@ -263,49 +263,43 @@ asn1_decode_ec_params(sc_context_t *ctx, void **paramp, int r; struct sc_object_id curve; struct sc_asn1_entry asn1_ec_params[4]; - struct sc_ec_params * ecp; + struct sc_ec_parameters *ecp; sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_decode_ec_params %p:%d %d", buf, buflen, depth); memset(&curve, 0, sizeof(curve)); - ecp = malloc(sizeof(struct sc_ec_params)); - if (ecp == NULL) - return SC_ERROR_OUT_OF_MEMORY; - memset(ecp,0,sizeof(struct sc_ec_params)); - - /* We only want to copy the parms if they are a namedCurve - * or ecParameters nullParam aka implicityCA is not to be + /* We only want to copy the parms if they are a namedCurve + * or ecParameters nullParam aka implicityCA is not to be * used with PKCS#11 2.20 */ sc_copy_asn1_entry(c_asn1_ec_params, asn1_ec_params); sc_format_asn1_entry(asn1_ec_params + 1, &curve, 0, 0); /* Some signature algorithms will not have any data */ - if (buflen == 0 || buf == NULL) { - free(ecp); + if (buflen == 0 || buf == NULL) return 0; - } + + ecp = calloc(sizeof(struct sc_ec_parameters), 1); + if (ecp == NULL) + return SC_ERROR_OUT_OF_MEMORY; r = sc_asn1_decode_choice(ctx, asn1_ec_params, buf, buflen, NULL, NULL); - /* r = index into asn1_ec_params */ - sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_decode_ec_params r=%d", r); - if (r < 0) { - free(ecp); + /* r = index in asn1_ec_params */ + sc_debug(ctx, SC_LOG_DEBUG_ASN1, "asn1_decode_ec_params r=%d", r); + if (r < 0) return r; - } + if (r <= 1) { - ecp->der = malloc(buflen); - - if (ecp->der == NULL) + ecp->der.value = malloc(buflen); + if (ecp->der.value == NULL) return SC_ERROR_OUT_OF_MEMORY; - - ecp->der_len = buflen; - - sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_decode_ec_params paramp=%p %p:%d %d", - ecp, ecp->der, ecp->der_len, ecp->type); - memcpy(ecp->der, buf, buflen); /* copy der parameters */ - } else + ecp->der.len = buflen; + memcpy(ecp->der.value, buf, buflen); + } + else { r = 0; + } + ecp->type = r; /* but 0 = ecparams if any, 1=named curve */ *paramp = ecp; return 0; @@ -313,23 +307,25 @@ asn1_decode_ec_params(sc_context_t *ctx, void **paramp, static int asn1_encode_ec_params(sc_context_t *ctx, void *params, -u8 **buf, size_t *buflen, int depth) +u8 **buf, size_t *buflen, int depth) { - struct sc_ec_params * ecp = (struct sc_ec_params *) params; + struct sc_ec_parameters *ecp = (struct sc_ec_parameters *) params; /* Only handle named curves. They may be absent too */ - sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - asn1_encode_ec_params"); + sc_debug(ctx, SC_LOG_DEBUG_ASN1, "asn1_encode_ec_params() called"); *buf = NULL; *buflen = 0; - if (ecp && ecp->type == 1 && ecp->der) { /* named curve */ - *buf = malloc(ecp->der_len); + if (ecp && ecp->type == 1 && ecp->der.value) { /* named curve */ + *buf = malloc(ecp->der.len); if (*buf == NULL) return SC_ERROR_OUT_OF_MEMORY; - memcpy(*buf, ecp->der, ecp->der_len); - *buflen = ecp->der_len; - } else - sc_debug(ctx, SC_LOG_DEBUG_ASN1, "DEE - Not named curve"); + memcpy(*buf, ecp->der.value, ecp->der.len); + *buflen = ecp->der.len; + } + else { + sc_debug(ctx, SC_LOG_DEBUG_ASN1, "Not named curve"); + } return 0; } @@ -337,10 +333,13 @@ u8 **buf, size_t *buflen, int depth) static void asn1_free_ec_params(void *params) { - struct sc_ec_params * ecp = (struct sc_ec_params *) params; + struct sc_ec_parameters *ecp = (struct sc_ec_parameters *) params; + if (ecp) { - if (ecp->der) - free(ecp->der); + if (ecp->der.value) + free(ecp->der.value); + if (ecp->named_curve) + free(ecp->named_curve); free(ecp); } } diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 8b96d8e3..16f01ade 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -812,20 +812,20 @@ sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubk pkey.len = 0; /* flag as do not delete */ if (pubkey->u.ec.params.named_curve || pubkey->u.ec.params.der.value) { - struct sc_ec_params *ec_params = NULL; + struct sc_ec_parameters *ec_params = NULL; r = sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); LOG_TEST_RET(ctx, r, "failed to fix EC parameters"); - ec_params = calloc(1, sizeof(struct sc_ec_params)); + ec_params = calloc(1, sizeof(struct sc_ec_parameters)); if (!ec_params) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); ec_params->type = 1; - ec_params->der = calloc(pubkey->u.ec.params.der.len, 1); - if (!ec_params->der) + ec_params->der.value = calloc(pubkey->u.ec.params.der.len, 1); + if (!ec_params->der.value) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); - memcpy(ec_params->der, pubkey->u.ec.params.der.value, pubkey->u.ec.params.der.len); - ec_params->der_len = pubkey->u.ec.params.der.len; + memcpy(ec_params->der.value, pubkey->u.ec.params.der.value, pubkey->u.ec.params.der.len); + ec_params->der.len = pubkey->u.ec.params.der.len; pubkey->alg_id->params = ec_params; } break; @@ -1295,14 +1295,14 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke if (pk_alg.algorithm == SC_ALGORITHM_EC) { /* EC public key is not encapsulated into BIT STRING -- it's a BIT STRING */ if (pubkey->alg_id->params) { - struct sc_ec_params *ecp = (struct sc_ec_params *)pubkey->alg_id->params; + struct sc_ec_parameters *ecp = (struct sc_ec_parameters *)pubkey->alg_id->params; - pubkey->u.ec.params.der.value = malloc(ecp->der_len); + pubkey->u.ec.params.der.value = malloc(ecp->der.len); if (pubkey->u.ec.params.der.value == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); - memcpy(pubkey->u.ec.params.der.value, ecp->der, ecp->der_len); - pubkey->u.ec.params.der.len = ecp->der_len; + memcpy(pubkey->u.ec.params.der.value, ecp->der.value, ecp->der.len); + pubkey->u.ec.params.der.len = ecp->der.len; r = sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); LOG_TEST_RET(ctx, r, "failed to fix EC parameters"); } @@ -1399,7 +1399,7 @@ static struct ec_curve_info { int -sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_pkcs15_ec_parameters *ecparams) +sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecparams) { int rv, ii; diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index 03801cdb..77d329bb 100644 --- a/src/libopensc/pkcs15-sc-hsm.c +++ b/src/libopensc/pkcs15-sc-hsm.c @@ -374,7 +374,7 @@ static int sc_pkcs15emu_sc_hsm_get_rsa_public_key(struct sc_context *ctx, sc_cvc static int sc_pkcs15emu_sc_hsm_get_ec_public_key(struct sc_context *ctx, sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey) { - struct sc_ec_params *ecp; + struct sc_ec_parameters *ecp; const struct sc_lv_data *oid; int r; @@ -384,18 +384,18 @@ static int sc_pkcs15emu_sc_hsm_get_ec_public_key(struct sc_context *ctx, sc_cvc_ if (r != SC_SUCCESS) return r; - ecp = calloc(1, sizeof(struct sc_ec_params)); + ecp = calloc(1, sizeof(struct sc_ec_parameters)); if (!ecp) return SC_ERROR_OUT_OF_MEMORY; - ecp->der_len = oid->len + 2; - ecp->der = calloc(ecp->der_len, 1); - if (!ecp->der) + ecp->der.len = oid->len + 2; + ecp->der.value = calloc(ecp->der.len, 1); + if (!ecp->der.value) return SC_ERROR_OUT_OF_MEMORY; - ecp->der[0] = 0x06; - ecp->der[1] = (u8)oid->len; - memcpy(ecp->der + 2, oid->value, oid->len); + *(ecp->der.value + 0) = 0x06; + *(ecp->der.value + 1) = (u8)oid->len; + memcpy(ecp->der.value + 2, oid->value, oid->len); ecp->type = 1; // Named curve pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id)); @@ -411,11 +411,11 @@ static int sc_pkcs15emu_sc_hsm_get_ec_public_key(struct sc_context *ctx, sc_cvc_ memcpy(pubkey->u.ec.ecpointQ.value, cvc->publicPoint, cvc->publicPointlen); pubkey->u.ec.ecpointQ.len = cvc->publicPointlen; - pubkey->u.ec.params.der.value = malloc(ecp->der_len); + pubkey->u.ec.params.der.value = malloc(ecp->der.len); if (!pubkey->u.ec.params.der.value) return SC_ERROR_OUT_OF_MEMORY; - memcpy(pubkey->u.ec.params.der.value, ecp->der, ecp->der_len); - pubkey->u.ec.params.der.len = ecp->der_len; + memcpy(pubkey->u.ec.params.der.value, ecp->der.value, ecp->der.len); + pubkey->u.ec.params.der.len = ecp->der.len; sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index e6ebafe0..3b8764ff 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -212,7 +212,7 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card, switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_EC: - alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length); + alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL); if (alg_info == NULL) { sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); @@ -352,7 +352,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, case SC_PKCS15_TYPE_PRKEY_EC: modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */ - alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length); + alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL); if (alg_info == NULL) { sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index 629902ce..b6958dd0 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -200,19 +200,6 @@ struct sc_pkcs15_prkey_dsa { sc_pkcs15_bignum_t priv; }; -/* - * The ecParameters can be presented as - * - named curve; - * - OID of named curve; - * - implicit parameters. - */ -struct sc_pkcs15_ec_parameters { - char *named_curve; - struct sc_object_id id; - struct sc_pkcs15_der der; - size_t field_length; /* in bits */ -}; - struct sc_pkcs15_gost_parameters { struct sc_object_id key; struct sc_object_id hash; @@ -220,12 +207,12 @@ struct sc_pkcs15_gost_parameters { }; struct sc_pkcs15_pubkey_ec { - struct sc_pkcs15_ec_parameters params; + struct sc_ec_parameters params; struct sc_pkcs15_u8 ecpointQ; /* This is NOT DER, just value and length */ }; struct sc_pkcs15_prkey_ec { - struct sc_pkcs15_ec_parameters params; + struct sc_ec_parameters params; sc_pkcs15_bignum_t privateD; /* note this is bignum */ struct sc_pkcs15_u8 ecpointQ; /* This is NOT DER, just value and length */ }; @@ -964,7 +951,7 @@ struct sc_supported_algo_info *sc_pkcs15_get_supported_algo(struct sc_pkcs15_car int sc_pkcs15_add_supported_algo_ref(struct sc_pkcs15_object *, struct sc_supported_algo_info *); -int sc_pkcs15_fix_ec_parameters(struct sc_context *, struct sc_pkcs15_ec_parameters *); +int sc_pkcs15_fix_ec_parameters(struct sc_context *, struct sc_ec_parameters *); /* Convert the OpenSSL key data type into the OpenSC key */ int sc_pkcs15_convert_bignum(sc_pkcs15_bignum_t *dst, const void *bignum); diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 9111e510..d3001658 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -2763,7 +2763,7 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, /* TODO: check allowed values of keybits */ } else if (keytype == CKK_EC) { - struct sc_pkcs15_der *der = &keygen_args.prkey_args.key.u.ec.params.der; + struct sc_lv_data *der = &keygen_args.prkey_args.key.u.ec.params.der; der->len = sizeof(struct sc_object_id); rv = attr_find_ptr(pPubTpl, ulPubCnt, CKA_EC_PARAMS, (void **)&der->value, &der->len); @@ -4379,7 +4379,7 @@ get_public_exponent(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) static CK_RV get_ec_pubkey_params(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) { - struct sc_ec_params * ecp; + struct sc_ec_parameters *ecp; if (key == NULL) return CKR_ATTRIBUTE_TYPE_INVALID; @@ -4396,10 +4396,10 @@ get_ec_pubkey_params(struct sc_pkcs15_pubkey *key, CK_ATTRIBUTE_PTR attr) return CKR_OK; } - ecp = (struct sc_ec_params *) key->alg_id->params; - if (ecp && ecp->der && ecp->der_len) { - check_attribute_buffer(attr, ecp->der_len); - memcpy(attr->pValue, ecp->der, ecp->der_len); + ecp = (struct sc_ec_parameters *) key->alg_id->params; + if (ecp && ecp->der.value && ecp->der.len) { + check_attribute_buffer(attr, ecp->der.len); + memcpy(attr->pValue, ecp->der.value, ecp->der.len); return CKR_OK; } } diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index e5d30a81..cc655f6a 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1214,7 +1214,7 @@ sc_pkcs15init_init_prkdf(struct sc_pkcs15_card *p15card, struct sc_profile *prof keyinfo_gostparams->gost28147 = keyargs->params.gost.gost28147; } else if (key->algorithm == SC_ALGORITHM_EC) { - struct sc_pkcs15_ec_parameters *ecparams = &keyargs->key.u.ec.params; + struct sc_ec_parameters *ecparams = &keyargs->key.u.ec.params; key_info->params.data = &keyargs->key.u.ec.params; key_info->params.free_params = sc_pkcs15init_empty_callback; key_info->field_length = ecparams->field_length; @@ -1975,7 +1975,7 @@ check_keygen_params_consistency(struct sc_card *card, struct sc_pkcs15init_keyge int i, rv; if (alg == SC_ALGORITHM_EC) { - struct sc_pkcs15_ec_parameters *ecparams = ¶ms->prkey_args.key.u.ec.params; + struct sc_ec_parameters *ecparams = ¶ms->prkey_args.key.u.ec.params; rv = sc_pkcs15_fix_ec_parameters(ctx, ecparams); LOG_TEST_RET(ctx, rv, "Cannot fix EC parameters"); @@ -2011,9 +2011,11 @@ static int check_key_compatibility(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *key, unsigned int x509_usage, unsigned int key_length, unsigned int flags) { + struct sc_context *ctx = p15card->card->ctx; struct sc_algorithm_info *info; unsigned int count; + LOG_FUNC_CALLED(ctx); count = p15card->card->algorithm_count; for (info = p15card->card->algorithms; count--; info++) { /* don't check flags if none was specified */ @@ -2039,12 +2041,18 @@ check_key_compatibility(struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey * } } else if (key->algorithm == SC_ALGORITHM_EC) { + if (!sc_valid_oid(&key->u.ec.params.id)) + if (sc_pkcs15_fix_ec_parameters(ctx, &key->u.ec.params)) + LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_VALID); + if (sc_valid_oid(&info->u._ec.params.id)) + if (!sc_compare_oid(&info->u._ec.params.id, &key->u.ec.params.id)) + continue; } - return SC_SUCCESS; + LOG_FUNC_RETURN(ctx, SC_SUCCESS); } - return SC_ERROR_OBJECT_NOT_VALID; + LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_VALID); } diff --git a/src/pkcs15init/pkcs15-sc-hsm.c b/src/pkcs15init/pkcs15-sc-hsm.c index 0f2fd8af..ddf84af9 100644 --- a/src/pkcs15init/pkcs15-sc-hsm.c +++ b/src/pkcs15init/pkcs15-sc-hsm.c @@ -173,7 +173,7 @@ static int sc_hsm_encode_gakp_rsa(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, static int sc_hsm_encode_gakp_ec(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, struct sc_pkcs15_prkey_info *key_info) { struct sc_object_id ecdsaWithSHA256 = { { 0,4,0,127,0,7,2,2,2,2,3,-1 } }; - struct sc_pkcs15_ec_parameters *ecparams = (struct sc_pkcs15_ec_parameters *)key_info->params.data; + struct sc_ec_parameters *ecparams = (struct sc_ec_parameters *)key_info->params.data; struct ec_curve *curve = NULL; u8 *curveoid; int curveoidlen,r; From 80c496671f5bb513a1298b462040ed12d549fb2b Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 15 Feb 2015 13:56:51 +0100 Subject: [PATCH 096/306] helper functions to change format of ECDSA signature --- src/libopensc/asn1.c | 79 ++++++++++++++++++++++++++++++++- src/libopensc/asn1.h | 11 ++++- src/libopensc/libopensc.exports | 2 + 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 189075ba..fb09a1f4 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -1002,7 +1002,7 @@ static const struct sc_asn1_entry c_asn1_se_info[4] = { }; static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen, - sc_pkcs15_sec_env_info_t ***se, size_t *num, int depth) + sc_pkcs15_sec_env_info_t ***se, size_t *num, int depth) { struct sc_pkcs15_sec_env_info **ses; const unsigned char *ptr = obj; @@ -1819,3 +1819,80 @@ sc_encode_oid (struct sc_context *ctx, struct sc_object_id *id, return SC_SUCCESS; } + +#define C_ASN1_SIG_VALUE_SIZE 2 +static struct sc_asn1_entry c_asn1_sig_value[C_ASN1_SIG_VALUE_SIZE] = { + { "ECDSA-Sig-Value", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + +#define C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE 3 +static struct sc_asn1_entry c_asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE] = { + { "r", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED, NULL, NULL }, + { "s", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC|SC_ASN1_UNSIGNED, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + + +int +sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx, unsigned char *in, size_t inlen, + unsigned char **buf, size_t *buflen) +{ + struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE]; + struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE]; + unsigned char *r = in, *s = in + inlen/2; + size_t r_len = inlen/2, s_len = inlen/2; + int rv; + + LOG_FUNC_CALLED(ctx); + sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value); + sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 1); + + sc_copy_asn1_entry(c_asn1_sig_value_coefficients, asn1_sig_value_coefficients); + sc_format_asn1_entry(asn1_sig_value_coefficients + 0, r, &r_len, 1); + sc_format_asn1_entry(asn1_sig_value_coefficients + 1, s, &s_len, 1); + + rv = sc_asn1_encode(ctx, asn1_sig_value, buf, buflen); + LOG_TEST_RET(ctx, rv, "ASN.1 encoding ECDSA-SIg-Value failed"); + + LOG_FUNC_RETURN(ctx, SC_SUCCESS); +} + + +int +sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, unsigned char *in, size_t inlen, + unsigned char **buf, size_t *buflen) +{ + struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE]; + struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE]; + unsigned char *r, *s; + size_t r_len, s_len; + int rv; + + LOG_FUNC_CALLED(ctx); + sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value); + sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 0); + + sc_copy_asn1_entry(c_asn1_sig_value_coefficients, asn1_sig_value_coefficients); + sc_format_asn1_entry(asn1_sig_value_coefficients + 0, &r, &r_len, 0); + sc_format_asn1_entry(asn1_sig_value_coefficients + 1, &s, &s_len, 0); + + rv = sc_asn1_decode(ctx, asn1_sig_value, in, inlen, NULL, NULL); + LOG_TEST_RET(ctx, rv, "ASN.1 decoding ECDSA-Sig-Value failed"); + + sc_log(ctx, "r(%i): %s", r_len, sc_dump_hex(r, r_len)); + sc_log(ctx, "s(%i): %s", s_len, sc_dump_hex(s, s_len)); + + *buf = malloc(r_len + s_len); + if (*buf == NULL) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + + memcpy(*buf, r, r_len); + memcpy(*buf + r_len, s, s_len); + *buflen = r_len + s_len; + + free(r); + free(s); + + LOG_FUNC_RETURN(ctx, SC_SUCCESS); +} diff --git a/src/libopensc/asn1.h b/src/libopensc/asn1.h index ef674d03..13958845 100644 --- a/src/libopensc/asn1.h +++ b/src/libopensc/asn1.h @@ -58,7 +58,7 @@ void sc_format_asn1_entry(struct sc_asn1_entry *entry, void *parm, void *arg, int set_present); void sc_copy_asn1_entry(const struct sc_asn1_entry *src, struct sc_asn1_entry *dest); - + /* DER tag and length parsing */ int sc_asn1_decode(struct sc_context *ctx, struct sc_asn1_entry *asn1, const u8 *in, size_t len, const u8 **newp, size_t *left); @@ -103,7 +103,7 @@ int sc_asn1_decode_bit_string_ni(const u8 * inbuf, size_t inlen, int sc_asn1_decode_integer(const u8 * inbuf, size_t inlen, int *out); int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen, struct sc_object_id *id); -int sc_asn1_encode_object_id(u8 **buf, size_t *buflen, +int sc_asn1_encode_object_id(u8 **buf, size_t *buflen, const struct sc_object_id *id); /* algorithm encoding/decoding */ @@ -120,6 +120,13 @@ void sc_asn1_clear_algorithm_id(struct sc_algorithm_id *); int sc_asn1_write_element(sc_context_t *ctx, unsigned int tag, const u8 * data, size_t datalen, u8 ** out, size_t * outlen); +int sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx, + unsigned char *in, size_t inlen, + unsigned char **buf, size_t *buflen); +int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, + unsigned char *in, size_t inlen, + unsigned char **buf, size_t *buflen); + #define SC_ASN1_CLASS_MASK 0x30000000 #define SC_ASN1_UNI 0x00000000 /* Universal */ #define SC_ASN1_APP 0x10000000 /* Application */ diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index 0b98db2a..23f6c05a 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -51,6 +51,8 @@ sc_asn1_put_tag sc_asn1_skip_tag sc_asn1_verify_tag sc_asn1_write_element +sc_asn1_sig_value_sequence_to_rs +sc_asn1_sig_value_rs_to_sequence sc_base64_decode sc_base64_encode sc_bin_to_hex From b08671fab5b500ed18e7fe189d8e6aadbaf22f4b Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 15 Feb 2015 13:57:47 +0100 Subject: [PATCH 097/306] pkcs15-crypt: option for output format of ECDSA signature --- src/tools/pkcs15-crypt.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/tools/pkcs15-crypt.c b/src/tools/pkcs15-crypt.c index 95b6593b..7c257c3f 100644 --- a/src/tools/pkcs15-crypt.c +++ b/src/tools/pkcs15-crypt.c @@ -36,6 +36,7 @@ #include "common/compat_getpass.h" #include "libopensc/opensc.h" #include "libopensc/pkcs15.h" +#include "libopensc/asn1.h" #include "util.h" static const char *app_name = "pkcs15-crypt"; @@ -45,10 +46,11 @@ static char * opt_reader; static char * opt_pincode = NULL, * opt_key_id = NULL; static char * opt_input = NULL, * opt_output = NULL; static char * opt_bind_to_aid = NULL; +static char * opt_sig_format = NULL; static int opt_crypt_flags = 0; enum { - OPT_SHA1 = 0x100, + OPT_SHA1 = 0x100, OPT_SHA256, OPT_SHA384, OPT_SHA512, @@ -65,6 +67,7 @@ static const struct option options[] = { { "reader", 1, NULL, 'r' }, { "input", 1, NULL, 'i' }, { "output", 1, NULL, 'o' }, + { "signature-format", 1, NULL, 'f' }, { "raw", 0, NULL, 'R' }, { "sha-1", 0, NULL, OPT_SHA1 }, { "sha-256", 0, NULL, OPT_SHA256 }, @@ -87,6 +90,7 @@ static const char *option_help[] = { "Uses reader number ", "Selects the input file to use", "Outputs to file ", + "Format for ECDSA signature : 'rs' (default), 'sequence', 'openssl'", "Outputs raw 8 bit data", "Input file is a SHA-1 hash", "Input file is a SHA-256 hash", @@ -142,8 +146,8 @@ static char * get_pin(struct sc_pkcs15_object *obj) if (strlen(pincode) == 0) return NULL; if (strlen(pincode) < pinfo->attrs.pin.min_length || - strlen(pincode) > pinfo->attrs.pin.max_length) - continue; + strlen(pincode) > pinfo->attrs.pin.max_length) + continue; return strdup(pincode); } } @@ -181,10 +185,12 @@ static int write_output(const u8 *buf, int len) } else { outf = stdout; } + if (output_binary == 0) util_print_binary(outf, buf, len); else fwrite(buf, len, 1, outf); + if (outf != stdout) fclose(outf); return 0; @@ -222,10 +228,28 @@ static int sign(struct sc_pkcs15_object *obj) fprintf(stderr, "Compute signature failed: %s\n", sc_strerror(r)); return 1; } + len = r; - r = write_output(out, r); + if (obj->type == SC_PKCS15_TYPE_PRKEY_EC) { + if (opt_sig_format && (!strcmp(opt_sig_format, "openssl") || !strcmp(opt_sig_format, "sequence"))) { + unsigned char *seq; + size_t seqlen; - return 0; + if (sc_asn1_sig_value_rs_to_sequence(ctx, out, len, &seq, &seqlen)) { + fprintf(stderr, "Failed to convert signature to ASN1 sequence format.\n"); + return 2; + } + + memcpy(out, seq, seqlen); + len = seqlen; + + free(seq); + } + } + + r = write_output(out, len); + + return r; } static int decipher(struct sc_pkcs15_object *obj) @@ -329,7 +353,7 @@ int main(int argc, char * const argv[]) sc_context_param_t ctx_param; while (1) { - c = getopt_long(argc, argv, "sck:r:i:o:Rp:vw", options, &long_optind); + c = getopt_long(argc, argv, "sck:r:i:o:f:Rp:vw", options, &long_optind); if (c == -1) break; if (c == '?') @@ -356,6 +380,9 @@ int main(int argc, char * const argv[]) case 'o': opt_output = optarg; break; + case 'f': + opt_sig_format = optarg; + break; case 'R': opt_raw = 1; break; From ced77ae6c7360914e746178b369561ad7fac84dc Mon Sep 17 00:00:00 2001 From: Pedro Martelletto Date: Tue, 17 Feb 2015 17:14:40 +0100 Subject: [PATCH 098/306] cardos: overwrite content of deleted private key when deleting a private key object, overwrite its contents so the key can no longer be used. (VTA: original commit touched to use LOG macros and add debug logs) --- src/pkcs15init/pkcs15-cardos.c | 58 +++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/pkcs15init/pkcs15-cardos.c b/src/pkcs15init/pkcs15-cardos.c index 160b975b..63f32a85 100644 --- a/src/pkcs15init/pkcs15-cardos.c +++ b/src/pkcs15init/pkcs15-cardos.c @@ -402,6 +402,62 @@ out: return r; } +/* + * Object deletion. + */ +static int +cardos_delete_object(sc_profile_t *profile, struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, const struct sc_path *path) +{ + int r, stored_in_ef = 0, algorithm = 0; + size_t keybits; + sc_file_t *file = NULL; + struct sc_pkcs15_prkey_info *key_info; + struct sc_pkcs15_prkey_rsa key_obj; + struct sc_context *ctx = p15card->card->ctx; + uint8_t abignum[256]; + + LOG_FUNC_CALLED(ctx); + /* + * If we are deleting a private key, overwrite it so it can't be used. + */ + if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY) { + key_info = obj->data; + keybits = key_info->modulus_length & ~7UL; + init_key_object(&key_obj, abignum, keybits >> 3); + r = cardos_key_algorithm(key_info->usage, keybits, &algorithm); + LOG_TEST_RET(ctx, r, "cardos_key_algorithm failed"); + + r = sc_select_file(p15card->card, &key_info->path, &file); + LOG_TEST_RET(ctx, r, "Failed to store key: cannot select parent DF"); + + r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); + sc_file_free(file); + LOG_TEST_RET(ctx, r, "Failed to store key: UPDATE authentication failed"); + + r = cardos_put_key(profile, p15card, algorithm, key_info, &key_obj); + LOG_TEST_RET(ctx, r, "cardos_put_key failed"); + } + + /* Delete object from the PKCS15 file system. */ + if (path->len || path->aid.len) { + r = sc_select_file(p15card->card, path, &file); + if (r != SC_ERROR_FILE_NOT_FOUND) + LOG_TEST_RET(ctx, r, "select object path failed"); + + stored_in_ef = (file->type != SC_FILE_TYPE_DF); + sc_file_free(file); + } + + /* If the object is stored in a normal EF, try to delete the EF. */ + if (r == SC_SUCCESS && stored_in_ef) { + r = sc_pkcs15init_delete_by_path(profile, p15card, path); + LOG_TEST_RET(ctx, r, "Failed to delete object by path"); + } + + LOG_FUNC_RETURN(ctx, SC_SUCCESS); +} + /* * Store a PIN or PUK */ @@ -851,7 +907,7 @@ static struct sc_pkcs15init_operations sc_pkcs15init_cardos_operations = { cardos_generate_key, NULL, NULL, /* encode private/public key */ NULL, /* finalize_card */ - NULL, /* delete_object */ + cardos_delete_object, NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */ NULL /* sanity_check */ }; From da07e22c97effe27d8decf4037f314e4015da1eb Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 5 Feb 2015 17:40:43 +0100 Subject: [PATCH 099/306] use memmove for overlapping memory --- src/libopensc/card-authentic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-authentic.c b/src/libopensc/card-authentic.c index 4b3805d9..87065849 100644 --- a/src/libopensc/card-authentic.c +++ b/src/libopensc/card-authentic.c @@ -660,7 +660,7 @@ authentic_reduce_path(struct sc_card *card, struct sc_path *path) cur_path = card->cache.current_df->path; if (!memcmp(cur_path.value, "\x3F\x00", 2) && memcmp(in_path.value, "\x3F\x00", 2)) { - memcpy(in_path.value + 2, in_path.value, in_path.len); + memmove(in_path.value + 2, in_path.value, in_path.len); memcpy(in_path.value, "\x3F\x00", 2); in_path.len += 2; } @@ -672,7 +672,7 @@ authentic_reduce_path(struct sc_card *card, struct sc_path *path) break; } - memcpy(in_path.value, in_path.value + offs, sizeof(in_path.value) - offs); + memmove(in_path.value, in_path.value + offs, sizeof(in_path.value) - offs); in_path.len -= offs; *path = in_path; From 236e68b17c85be8b7507615a99663f5f6da3438c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 5 Feb 2015 17:43:14 +0100 Subject: [PATCH 100/306] fixed NULL dereference --- src/libopensc/asn1.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index fb09a1f4..bfbdaa94 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -1440,6 +1440,8 @@ static int asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1, left, depth, choice ? ", choice" : ""); + if (!p) + return SC_ERROR_ASN1_OBJECT_NOT_FOUND; if (left < 2) { while (asn1->name && (asn1->flags & SC_ASN1_OPTIONAL)) asn1++; @@ -1788,6 +1790,8 @@ _sc_asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1, int sc_der_copy(sc_pkcs15_der_t *dst, const sc_pkcs15_der_t *src) { + if (!dst) + return SC_ERROR_INVALID_ARGUMENTS; memset(dst, 0, sizeof(*dst)); if (src->len) { dst->value = malloc(src->len); From 16ea926d2980ab9b92d94bd649cdb9a4ce6d769a Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 9 Feb 2015 23:11:58 +0100 Subject: [PATCH 101/306] fixed indentation --- src/pkcs11/pkcs11-object.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c index a6b9236e..48824cfc 100644 --- a/src/pkcs11/pkcs11-object.c +++ b/src/pkcs11/pkcs11-object.c @@ -1078,8 +1078,8 @@ CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, /* the session's handle */ rv = get_object_from_session(hSession, *phKey, &session, &key_object); if (rv != CKR_OK) { - if (rv == CKR_OBJECT_HANDLE_INVALID) - rv = CKR_KEY_HANDLE_INVALID; + if (rv == CKR_OBJECT_HANDLE_INVALID) + rv = CKR_KEY_HANDLE_INVALID; goto out; } From bff0ea483711a044f514ccee0e4ab5552dbea2bb Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 9 Feb 2015 23:16:31 +0100 Subject: [PATCH 102/306] fixed compiler warning --- src/tools/pkcs11-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 05a5c40e..15cee833 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -1138,7 +1138,7 @@ static void init_token(CK_SLOT_ID slot) get_token_info(slot, &info); if (opt_so_pin != NULL) { - new_pin = opt_so_pin; + new_pin = (char *) opt_so_pin; } else { if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { printf("Please enter the new SO PIN: "); From 9f3dbaa39dbb2c6c4515bb2ea0ec78023d10bdb4 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 9 Feb 2015 23:23:12 +0100 Subject: [PATCH 103/306] honour warnings --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ed63e92c..46c471b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,11 +30,11 @@ install: before_script: - ./bootstrap - if [ -z "$HOST" ]; then - ./configure --enable-doc --enable-dnie-ui; + ./configure --enable-pedantic --disable-strict --enable-doc --enable-dnie-ui; else unset CC; unset CXX; - ./configure --host=$HOST --disable-openssl; + ./configure --enable-pedantic --disable-strict --host=$HOST --disable-openssl; fi addons: From 48bd6b09645014365a2be8361d113757a1736814 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Thu, 28 Aug 2014 14:29:16 +0200 Subject: [PATCH 104/306] Add support for the IsoApplet (Java Card applet) The IsoApplet can be found here: https://github.com/philipWendland/IsoApplet Add read/write support for this applet, including RSA and ECC support. --- src/libopensc/Makefile.am | 1 + src/libopensc/Makefile.mak | 2 +- src/libopensc/card-isoApplet.c | 1223 +++++++++++++++++++++++++++++ src/libopensc/cardctl.h | 33 +- src/libopensc/cards.h | 7 +- src/libopensc/ctx.c | 1 + src/pkcs15init/Makefile.am | 6 +- src/pkcs15init/Makefile.mak | 3 +- src/pkcs15init/isoApplet.profile | 164 ++++ src/pkcs15init/pkcs15-init.h | 1 + src/pkcs15init/pkcs15-isoApplet.c | 871 ++++++++++++++++++++ src/pkcs15init/pkcs15-lib.c | 1 + 12 files changed, 2307 insertions(+), 6 deletions(-) create mode 100644 src/libopensc/card-isoApplet.c create mode 100644 src/pkcs15init/isoApplet.profile create mode 100644 src/pkcs15init/pkcs15-isoApplet.c diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 33bc3e6e..557c32ea 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -41,6 +41,7 @@ libopensc_la_SOURCES = \ card-itacns.c card-authentic.c \ card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ card-dnie.c cwa14890.c cwa-dnie.c user-interface.c \ + card-isoApplet.c \ \ pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \ pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \ diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak index 6a004e3b..4e572f7b 100644 --- a/src/libopensc/Makefile.mak +++ b/src/libopensc/Makefile.mak @@ -23,7 +23,7 @@ OBJECTS = \ card-rtecp.obj card-westcos.obj card-myeid.obj card-ias.obj \ card-itacns.obj card-authentic.obj \ card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \ - card-sc-hsm.obj card-dnie.obj user-interface.obj \ + card-sc-hsm.obj card-dnie.obj user-interface.obj card-isoApplet.obj \ \ pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \ pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \ diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c new file mode 100644 index 00000000..06509b59 --- /dev/null +++ b/src/libopensc/card-isoApplet.c @@ -0,0 +1,1223 @@ +/* + * Support for the IsoApplet JavaCard Applet. + * + * Copyright (C) 2014 Philip Wendland + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include "internal.h" +#include "opensc.h" +#include "cardctl.h" +#include "log.h" +#include "asn1.h" +#include "pkcs15.h" + +#define ISOAPPLET_ALG_REF_ECDSA 0x21 +#define ISOAPPLET_ALG_REF_RSA_PAD_PKCS1 0x11 + +#define ISOAPPLET_API_VERSION_MAJOR 0x00 +#define ISOAPPLET_API_VERSION_MINOR 0x03 +#define ISOAPPLET_API_FEATURE_EXT_APDU 0x01 + +#define ISOAPPLET_AID_LEN 12 +static const u8 isoAppletId[] = {0xf2,0x76,0xa2,0x88,0xbc,0xfb,0xa6,0x9d,0x34,0xf3,0x10,0x01}; + +struct isoApplet_drv_data +{ + unsigned int sec_env_alg_ref; +}; +#define DRVDATA(card) ((struct isoApplet_drv_data *) ((card)->drv_data)) + +static struct sc_card_operations isoApplet_ops; +static const struct sc_card_operations *iso_ops = NULL; +static struct sc_card_driver isoApplet_drv = +{ + "Javacard with IsoApplet", + "isoApplet", + &isoApplet_ops, + NULL, 0, NULL +}; + + +/* + * SELECT an applet on the smartcard. (Not in the emulated filesystem.) + * The response will be written to resp. + * + * @param[in] card + * @param[in] aid The applet ID. + * @param[in] aid_len The legth of aid. + * @param[out] resp The response of the applet upon selection. + * @param[in,out] resp_len In: The buffer size of resp. Out: The length of the response. + * + * @return SC_SUCCESS: The applet is present and could be selected. + * any other: Transmit failure or the card returned an error. + * The card will return an error when the applet is + * not present. + */ +static int +isoApplet_select_applet(sc_card_t *card, const u8 aid[], const size_t aid_len, u8* resp, size_t *resp_len) +{ + int rv; + sc_context_t *ctx = card->ctx; + sc_apdu_t apdu; + u8 aid_wc[SC_MAX_APDU_BUFFER_SIZE]; + + LOG_FUNC_CALLED(card->ctx); + + if(aid_len > SC_MAX_APDU_BUFFER_SIZE) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); + memcpy(aid_wc, aid, aid_len); + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xa4, 0x04, 0x00); + apdu.lc = aid_len; + apdu.data = aid_wc; + apdu.datalen = aid_len; + apdu.resp = resp; + apdu.resplen = *resp_len; + apdu.le = 0; + + rv = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(ctx, rv, "APDU transmit faiure."); + + rv = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(card->ctx, rv, "Card returned error"); + + *resp_len = apdu.resplen; + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +static int +isoApplet_finish(sc_card_t * card) +{ + struct isoApplet_drv_data *drvdata=DRVDATA(card); + + LOG_FUNC_CALLED(card->ctx); + if (drvdata) + { + free(drvdata); + card->drv_data=NULL; + } + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +static int +isoApplet_match_card(sc_card_t * card) +{ + size_t rlen = SC_MAX_APDU_BUFFER_SIZE; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + int rv; + + rv = isoApplet_select_applet(card, isoAppletId, ISOAPPLET_AID_LEN, rbuf, &rlen); + + if(rv != SC_SUCCESS) + { + return 0; + } + + /* If applet does not return API version, versions 0x00 will match */ + if(rlen == 0) + { + rbuf[0] = 0x00; + rbuf[1] = 0x00; + rbuf[2] = 0x00; + rlen = 3; + } + + /* We expect 3 bytes: MAJOR API version - MINOR API version - API feature bitmap */ + if(rlen != 3) + { + return 0; + } + + if(rbuf[0] != ISOAPPLET_API_VERSION_MAJOR) + { + sc_log(card->ctx, "IsoApplet: Mismatching major API version. Not proceeding. " + "API versions: Driver (%02X-%02X), applet (%02X-%02X). Please update accordingly.", + ISOAPPLET_API_VERSION_MAJOR, ISOAPPLET_API_VERSION_MINOR, rbuf[0], rbuf[1]); + return 0; + } + + if(rbuf[1] != ISOAPPLET_API_VERSION_MINOR) + { + sc_log(card->ctx, "IsoApplet: Mismatching minor API version. Proceeding anyway. " + "API versions: Driver (%02X-%02X), applet (%02X-%02X)." + "Please update accordingly whenever possible.", + ISOAPPLET_API_VERSION_MAJOR, ISOAPPLET_API_VERSION_MINOR, rbuf[0], rbuf[1]); + } + + if(rbuf[2] & ISOAPPLET_API_FEATURE_EXT_APDU) + { + card->caps |= SC_CARD_CAP_APDU_EXT; + } + + return 1; +} + +static int +isoApplet_init(sc_card_t * card) +{ + unsigned long flags = 0; + unsigned long ext_flags = 0; + struct isoApplet_drv_data *drvdata; + + LOG_FUNC_CALLED(card->ctx); + + drvdata=malloc(sizeof(struct isoApplet_drv_data)); + if (!drvdata) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + memset(drvdata, 0, sizeof(struct isoApplet_drv_data)); + drvdata->sec_env_alg_ref = 0; + + card->drv_data = drvdata; + card->cla = 0x00; + + /* ECDSA */ + flags = 0; + flags |= SC_ALGORITHM_ECDSA_RAW; + flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; + ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; + ext_flags |= SC_ALGORITHM_EXT_EC_F_P; + _sc_card_add_ec_alg(card, 192, flags, ext_flags); + _sc_card_add_ec_alg(card, 256, flags, ext_flags); + + /* RSA */ + flags = 0; + /* Padding schemes: */ + flags |= SC_ALGORITHM_RSA_PAD_PKCS1; + /* Hashes: */ + flags |= SC_ALGORITHM_RSA_HASH_NONE; + flags |= SC_ALGORITHM_RSA_HASH_SHA1; + flags |= SC_ALGORITHM_RSA_HASH_MD5; + flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1; + flags |= SC_ALGORITHM_RSA_HASH_SHA224; + flags |= SC_ALGORITHM_RSA_HASH_SHA256; + flags |= SC_ALGORITHM_RSA_HASH_SHA384; + flags |= SC_ALGORITHM_RSA_HASH_SHA512; + flags |= SC_ALGORITHM_RSA_HASH_RIPEMD160; + /* Key-generation: */ + flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; + /* Modulus lengths: */ + _sc_card_add_rsa_alg(card, 2048, flags, 0); + + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +/* + * @brief convert an OpenSC ACL entry to the security condition + * byte used by the IsoApplet. + * + * Used by IsoApplet_create_file to parse OpenSC ACL entries + * into ISO 7816-4 Table 20 security condition bytes. + * + * @param entry The OpenSC ACL entry. + * + * @return The security condition byte. No restriction (0x00) + * if unknown operation. + */ +static u8 +acl_to_security_condition_byte(const sc_acl_entry_t *entry) +{ + if(!entry) + return 0x00; + switch(entry->method) + { + case SC_AC_CHV: + return 0x90; + case SC_AC_NEVER: + return 0xFF; + case SC_AC_NONE: + default: + return 0x00; + } +} + +/* + * The reason for this function is that OpenSC doesn't set any + * Security Attribute Tag in the FCI upon file creation if there + * is no file->sec_attr. I set the file->sec_attr to a format + * understood by the applet (ISO 7816-4 tables 16, 17 and 20). + * The iso7816_create_file will then set this as Tag 86 - Sec. + * Attr. Prop. Format. + * The applet will then be able to set and enforce access rights + * for any file created by OpenSC. Without this function, the + * applet would not know where to enforce security rules and + * when. + * + * Note: IsoApplet currently only supports a "onepin" option. + * + * Format of the sec_attr: 8 Bytes: + * 7 - ISO 7816-4 table 16 or 17 + * 6 to 0 - ISO 7816-4 table 20 + */ +static int +isoApplet_create_file(sc_card_t *card, sc_file_t *file) +{ + int r = 0; + + LOG_FUNC_CALLED(card->ctx); + + if(file->sec_attr_len == 0) + { + u8 access_buf[8]; + int idx[8], i; + + if(file->type == SC_FILE_TYPE_DF) + { + const int df_idx[8] = /* These are the SC operations. */ + { + 0, /* Reserved. */ + SC_AC_OP_DELETE_SELF, //b6 + SC_AC_OP_LOCK, //b5 + SC_AC_OP_ACTIVATE, //b4 + SC_AC_OP_DEACTIVATE, //b3 + SC_AC_OP_CREATE_DF, //b2 + SC_AC_OP_CREATE_EF, //b1 + SC_AC_OP_DELETE //b0 + }; + for(i=0; i<8; i++) + { + idx[i] = df_idx[i]; + } + } + else //EF + { + const int ef_idx[8] = + { + 0, /* Reserved. */ + SC_AC_OP_DELETE_SELF, //b6 + SC_AC_OP_LOCK, //b5 + SC_AC_OP_ACTIVATE, //b4 + SC_AC_OP_DEACTIVATE, //b3 + SC_AC_OP_WRITE, //b2 + SC_AC_OP_UPDATE, //b1 + SC_AC_OP_READ //b0 + }; + for(i=0; i<8; i++) + { + idx[i] = ef_idx[i]; + } + } + /* Now idx contains the operation identifiers. + * We now search for the OPs. */ + access_buf[0] = 0xFF; /* A security condition byte is present for every OP. (Table 19) */ + for(i=1; i<8; i++) + { + const sc_acl_entry_t *entry; + entry = sc_file_get_acl_entry(file, idx[i]); + access_buf[i] = acl_to_security_condition_byte(entry); + } + + r = sc_file_set_sec_attr(file, access_buf, 8); + LOG_TEST_RET(card->ctx, r, "Error adding security attribute."); + } + + r = iso_ops->create_file(card, file); + LOG_FUNC_RETURN(card->ctx, r); +} + +/* + * Adds an ACL entry to the OpenSC file struct, according to the operation + * and the saByte (Encoded according to IsoApplet FCI proprietary security + * information, see also ISO 7816-4 table 20). + * + * @param[in,out] file + * @param[in] operation The OpenSC operation. + * @param[in] saByte The security condition byte return by the applet. + */ +static int +sa_to_acl(sc_file_t *file, unsigned int operation, u8 saByte) +{ + int r; + switch(saByte) + { + case 0x90: + r = sc_file_add_acl_entry(file, operation, SC_AC_CHV, 1); + if(r < 0) + return r; + break; + case 0xFF: + r = sc_file_add_acl_entry(file, operation, SC_AC_NEVER, SC_AC_KEY_REF_NONE); + if(r < 0) + return r; + break; + case 0x00: + r = sc_file_add_acl_entry(file, operation, SC_AC_NONE, SC_AC_KEY_REF_NONE); + if(r < 0) + return r; + break; + default: + r = sc_file_add_acl_entry(file, operation, SC_AC_UNKNOWN, SC_AC_KEY_REF_NONE); + if(r < 0) + return r; + } + return SC_SUCCESS; +} + + +/* + * This function first calls the iso7816.c process_fci() for any other FCI + * information and then updates the ACL of the OpenSC file struct according + * to the FCI from the applet. + */ +static int +isoApplet_process_fci(sc_card_t *card, sc_file_t *file, + const u8 *buf, size_t buflen) +{ + int r; + u8 *sa = NULL; + + LOG_FUNC_CALLED(card->ctx); + + r = iso_ops->process_fci(card, file, buf, buflen); + LOG_TEST_RET(card->ctx, r, "Error while processing the FCI."); + /* Construct the ACL from the sec_attr. */ + if(file->sec_attr && file->sec_attr_len == 8) + { + sa = file->sec_attr; + if(sa[0] != 0xFF) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, + "File security attribute does not contain a ACL byte for every operation."); + } + if(file->type == SC_FILE_TYPE_DF) + { + r = sa_to_acl(file, SC_AC_OP_DELETE_SELF, sa[1]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_LOCK, sa[2]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_ACTIVATE, sa[3]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_DEACTIVATE, sa[4]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_CREATE_DF, sa[5]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_CREATE_EF, sa[6]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_DELETE, sa[7]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + } + else if(file->type == SC_FILE_TYPE_INTERNAL_EF + || file->type == SC_FILE_TYPE_WORKING_EF) + { + r = sa_to_acl(file, SC_AC_OP_DELETE_SELF, sa[1]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_LOCK, sa[2]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_ACTIVATE, sa[3]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_DEACTIVATE, sa[4]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_WRITE, sa[5]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_UPDATE, sa[6]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + r = sa_to_acl(file, SC_AC_OP_READ, sa[7]); + LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); + } + + } + + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +static int +isoApplet_ctl_generate_key(sc_card_t *card, struct sc_cardctl_isoApplet_genkey *args) +{ + int r, len; + size_t tag_len; + sc_apdu_t apdu; + u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 *p; + const u8 *curr_pos; + + LOG_FUNC_CALLED(card->ctx); + + /* MANAGE SECURITY ENVIRONMENT (SET). Set the algorithm and key references. */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0x00); + + p = sbuf; + *p++ = 0x80; /* algorithm reference */ + *p++ = 0x01; + *p++ = args->algorithm_ref; + + *p++ = 0x84; /* Private key reference */ + *p++ = 0x01; + *p++ = args->priv_key_ref; + + r = p - sbuf; + p = NULL; + + apdu.lc = r; + apdu.datalen = r; + apdu.data = sbuf; + + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) + { + sc_log(card->ctx, "Key generation not supported by the card with that particular key type." + "Your card may not support the specified algorithm used by the applet / specified by you." + "In most cases, this happens when trying to generate EC keys not supported by your java card." + "In this case, look for supported field lengths and whether FP and/or F2M are supported."); + } + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + + /* GENERATE ASYMMETRIC KEY PAIR + * We use a larger buffer here, even if the card does not support extended apdus. + * There are two cases: + * 1) The card can do ext. apdus: The data fits in one apdu. + * 2) The card can't do ext. apdus: sc_transmit_apdu will handle that - the + * card will send SW_BYTES_REMAINING, OpenSC will automaticall do a + * GET RESPONSE to get the remaining data, and will append it to the data + * buffer. */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x46, 0x42, 0x00); + + apdu.resp = rbuf; + apdu.resplen = SC_MAX_EXT_APDU_BUFFER_SIZE; + apdu.le = 256; + + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + /* Parse the public key / response. */ + switch(args->algorithm_ref) + { + + case SC_ISOAPPLET_ALG_REF_RSA_GEN_2048: + /* We expect: + * - Tag: 7F 49 + * - Length: 82 01 09 (265 Bytes) */ + p = rbuf; + if(memcmp(p, "\x7F\x49\x82\x01\x09", 5) != 0) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, + "The data returned by the card is unexpected."); + } + else + { + len = 265; + } + p += 5; /* p points to the value field of the outer (7F 49) tag. + * This value field is a TLV-structure again. */ + + /* Search for the modulus tag (81). */ + curr_pos = sc_asn1_find_tag(card->ctx, p, len, (unsigned int) 0x81, &tag_len); + if(curr_pos == NULL || tag_len != 256) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid modulus."); + } + if(args->pubkey_len < 256) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); + } + args->pubkey_len = tag_len; + memcpy(args->pubkey, curr_pos, args->pubkey_len); + + /* Exponent tag (82) */ + curr_pos = sc_asn1_find_tag(card->ctx, p, len, (unsigned int) 0x82, &tag_len); + if(curr_pos == NULL || tag_len != 3) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); + } + if(args->exponent_len < 3) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid exponent."); + } + if(memcmp(curr_pos, "\x01\x00\x01", 3) != 0) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INCOMPATIBLE_KEY, + "Key generation error: Unexpected public key exponent."); + } + args->exponent_len = 3; + memcpy(args->exponent, curr_pos, args->exponent_len); + p = NULL; + break; + + case SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1: + p = rbuf; + if(args->pubkey_len >= apdu.resplen) + { + memcpy(args->pubkey, p, apdu.resplen); + } + else + { + LOG_TEST_RET(card->ctx, SC_ERROR_BUFFER_TOO_SMALL, + "Key generation error: Public key buffer too small."); + } + break; + + case SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1: + p = rbuf; + if(args->pubkey_len >= apdu.resplen) + { + memcpy(args->pubkey, p, apdu.resplen); + } + else + { + LOG_TEST_RET(card->ctx, SC_ERROR_BUFFER_TOO_SMALL, + "Key generation error: Public key buffer too small."); + } + break; + + default: + LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unable to parse public key: Unsupported algorithm."); + }// switch + + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +/* + * @brief Insert the length field of a TLV entry. + * + * The format is: + * 0..127: 1 byte, 00-7F + * 128..255: 2 bytes, 81; 00-FF + * 256..65535: 3 bytes, 82; 0000-FFFF + * + * @param[out] p The buffer where the length tag should be placed. + * @param[in] p_len The length of p. + * @param[in] len The length to be inserted. + * + * @return positive values: The length of the length field inserted. + * SC_ERROR_INVALID_ARGUMENTS: Incorrect length value or p == null. + * SC_ERROR_BUFFER_TOO_SMALL: The buffer p can not hold the length field. + */ +static int +tlv_insert_len(u8 *p, size_t p_len, size_t len) +{ + if(p == NULL) + return SC_ERROR_INVALID_ARGUMENTS; + + /* Note: len < 0 can not happen as it is size_t */ + if(len <= 127) + { + if(p_len < 1) + return SC_ERROR_BUFFER_TOO_SMALL; + *p++ = len & 0x7F; + return 1; + } + else if(len <= 255) + { + if(p_len < 2) + return SC_ERROR_BUFFER_TOO_SMALL; + *p++ = 0x81; + *p++ = len & 0xFF; + return 2; + } + else if(len <= 65535) + { + if(p_len < 3) + return SC_ERROR_BUFFER_TOO_SMALL; + *p++ = 0x82; + *p++ = (len >> 8) & 0xFF; /* MSB */ + *p++ = len & 0xFF; /* LSB */ + return 3; + } + else + { + return SC_ERROR_INVALID_ARGUMENTS; + } +} + +/* + * @brief Add a TLV-entry to a buffer. + * + * @param[out] buf The buffer at where the TLV entry should be placed. + * @param[in] buf_len The length of buf. + * @param[in] tag The one byte tag of the TLV entry. + * @param[in] tag_data The value field of the TLV entry. + * @param[in] tag_data_len The length of the tag_data. + * + */ +static int +tlv_add_tlv(u8 *buf, const size_t buf_len, const u8 tag, + const u8 *tag_data, const size_t tag_data_len) +{ + size_t l_len; /* Length of the length field itself. */ + int r; + + if(buf == NULL || tag_data == NULL) + return SC_ERROR_INVALID_ARGUMENTS; + + if(tag_data_len <= 127) + l_len = 1; + else if(tag_data_len <= 255) + l_len = 2; + else if(tag_data_len <= 65535) + l_len = 3; + else + return SC_ERROR_INVALID_ARGUMENTS; + + if(1 + l_len + tag_data_len > buf_len) + return SC_ERROR_BUFFER_TOO_SMALL; + + *buf++ = tag; + r = tlv_insert_len(buf, buf_len-1, tag_data_len); + if(r < 0) + return r; + else if((unsigned int)r != l_len) + return SC_ERROR_UNKNOWN; + + buf += l_len; + + memcpy(buf, tag_data, tag_data_len); + return 1 + l_len + tag_data_len; +} + +/* + * @brief Use PUT DATA to import a private RSA key. + * + * For simplicity, command chaining has to be used. One chunk (apdu) must contain + * one RSA field (P, Q, etc.). The first apdu must contain the outer tag (7F48). + * + * @param card + * @param rsa The RSA private key to import. + * + * @return SC_ERROR_INVALID_ARGUMENTS: The RSA key does not contain CRT fields. + * other errors: Transmit errors / errors returned by card. + */ +static int +isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) +{ + sc_apdu_t apdu; + const size_t sbuf_len = SC_MAX_APDU_BUFFER_SIZE; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 *p = NULL; + int r; + size_t tags_len; + + LOG_FUNC_CALLED(card->ctx); + + if(!rsa + || !rsa->p.data + || !rsa->q.data + || !rsa->iqmp.data + || !rsa->dmp1.data + || !rsa->dmq1.data) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Only CRT RSA keys may be imported."); + } + + + p = sbuf; + /* Note: The format is according to ISO 2-byte tag 7F48 */ + *p++ = 0x7F; /* T-L pair to indicate a private key data object */ + *p++ = 0x48; + /* Calculate the length of all inner tag-length-value entries. + * One entry consists of: tag (1 byte) + length (1 byte if < 128, 2 if >= 128) + value (len) + * It may actually happen that a parameter is 127 byte (leading zero) */ + tags_len = 1 + (rsa->p.len < 128 ? 1 : 2) + rsa->p.len + + 1 + (rsa->q.len < 128 ? 1 : 2) + rsa->q.len + + 1 + (rsa->iqmp.len < 128 ? 1 : 2) + rsa->iqmp.len + + 1 + (rsa->dmp1.len < 128 ? 1 : 2) + rsa->dmp1.len + + 1 + (rsa->dmq1.len < 128 ? 1 : 2) + rsa->dmq1.len; + r = tlv_insert_len(p, sbuf_len - (p - sbuf), tags_len); /* Private key data object length */ + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + p += r; + + /* p */ + r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x92, rsa->p.data, rsa->p.len); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + p += r; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDB, 0x3F, 0xFF); + apdu.cla |= 0x10; /* Chaining */ + apdu.data = sbuf; + apdu.datalen = p - sbuf; + apdu.lc = p - sbuf; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if(apdu.sw1 == 0x6D && apdu.sw2 == 0x00) + { + sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported." + "If you are using an older applet version and are trying to import keys, please update your applet first."); + } + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + /* q */ + p = sbuf; + r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x93, rsa->q.data, rsa->q.len); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + p += r; + + apdu.data = sbuf; + apdu.datalen = p - sbuf; + apdu.lc = p - sbuf; + r = sc_check_apdu(card, &apdu); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + /* 1/q mod p */ + p = sbuf; + r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x94, rsa->iqmp.data, rsa->iqmp.len); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + p += r; + + apdu.data = sbuf; + apdu.datalen = p - sbuf; + apdu.lc = p - sbuf; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + /* d mod (p-1) */ + p = sbuf; + r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x95, rsa->dmp1.data, rsa->dmp1.len); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + p += r; + + apdu.data = sbuf; + apdu.datalen = p - sbuf; + apdu.lc = p - sbuf; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + /* d mod (q-1) */ + p = sbuf; + r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x96, rsa->dmq1.data, rsa->dmq1.len); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + p += r; + + apdu.cla = 0x00; /* Last part of the chain. */ + apdu.data = sbuf; + apdu.datalen = p - sbuf; + apdu.lc = p - sbuf; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + LOG_FUNC_RETURN(card->ctx, r); +} + +/* + * @brief Use PUT DATA to import a private EC key. + * + * I use a simpler format for EC keys (compared to RSA) + * because the card has all the necessary information except the ecPointQ. + * Only the ecPointQ is sent to the card. It is BER-TLV-encoded. The tag is: + * 0xC1 - Private class, primitive encoding, number one. + * + * @param card + * @param ec The EC private key to import. + * + * @return SC_ERROR_INVALID_ARGUMENTS: The RSA key does not contain CRT fields. + * other errors: Transmit errors / errors returned by card. + */ +static int +isoApplet_put_data_prkey_ec(sc_card_t *card, struct sc_pkcs15_prkey_ec *ec) +{ + sc_apdu_t apdu; + size_t sbuf_len = SC_MAX_EXT_APDU_BUFFER_SIZE; + u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; + int r; + + LOG_FUNC_CALLED(card->ctx); + + if(!ec) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "No EC private key."); + } + + r = tlv_add_tlv(sbuf, sbuf_len, 0xC1, ec->privateD.data, ec->privateD.len); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + + /* Send to card. */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDB, 0x3F, 0xFF); + apdu.lc = r; + apdu.datalen = r; + apdu.data = sbuf; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if(apdu.sw1 == 0x6D && apdu.sw2 == 0x00) + { + sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported." + "If you are using an older applet version and are trying to import keys, please update your applet first."); + } + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + LOG_FUNC_RETURN(card->ctx, r); + +} + +/* + * @brief Import a private key. + */ +static int +isoApplet_ctl_import_key(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args) +{ + int r; + sc_apdu_t apdu; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 *p; + + LOG_FUNC_CALLED(card->ctx); + + /* + * Private keys are not stored in the filesystem. + * ISO 7816-8 - section C.2 describes: + * "Usage of the PUT DATA command for private key import" + * The applet uses this PUT DATA to import private keys, if private key import is allowed. + * + * The first step is to perform a MANAGE SECURITY ENVIRONMENT as it would be done + * with on-card key generation. The second step is PUT DATA (instead of + * GENERATE ASYMMETRIC KEYPAIR). + */ + + /* MANAGE SECURITY ENVIRONMENT (SET). Set the algorithm and key references. */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0x00); + + p = sbuf; + *p++ = 0x80; /* algorithm reference */ + *p++ = 0x01; + *p++ = args->algorithm_ref; + + *p++ = 0x84; /* Private key reference */ + *p++ = 0x01; + *p++ = args->priv_key_ref; + + r = p - sbuf; + p = NULL; + + apdu.lc = r; + apdu.datalen = r; + apdu.data = sbuf; + + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) + { + sc_log(card->ctx, "Key import not supported by the card with that particular key type." + "Your card may not support the specified algorithm used by the applet / specified by you." + "In most cases, this happens when trying to import EC keys not supported by your java card." + "In this case, look for supported field lengths and whether FP and/or F2M are supported." + "If you tried to import a private RSA key, check the key length."); + } + if(apdu.sw1 == 0x69 && apdu.sw2 == 0x00) + { + sc_log(card->ctx, "Key import not allowed by the applet's security policy." + "If you want to allow key import, set DEF_PRIVATE_KEY_IMPORT_ALLOWED in the IsoApplet," + " rebuild and reinstall the applet."); + } + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + + /* PUT DATA */ + switch(args->algorithm_ref) + { + + case SC_ISOAPPLET_ALG_REF_RSA_GEN_2048: + r = isoApplet_put_data_prkey_rsa(card, &args->prkey->u.rsa); + LOG_TEST_RET(card->ctx, r, "Error in PUT DATA."); + break; + + case SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1: + case SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1: + r = isoApplet_put_data_prkey_ec(card, &args->prkey->u.ec); + LOG_TEST_RET(card->ctx, r, "Error in PUT DATA."); + break; + + default: + LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Uknown algorithm refernce."); + } + + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +static int +isoApplet_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) +{ + int r = 0; + + LOG_FUNC_CALLED(card->ctx); + switch (cmd) + { + case SC_CARDCTL_ISOAPPLET_GENERATE_KEY: + r = isoApplet_ctl_generate_key(card, + (sc_cardctl_isoApplet_genkey_t *) ptr); + break; + case SC_CARDCTL_ISOAPPLET_IMPORT_KEY: + r = isoApplet_ctl_import_key(card, + (sc_cardctl_isoApplet_import_key_t *) ptr); + break; + default: + r = SC_ERROR_NOT_SUPPORTED; + } + LOG_FUNC_RETURN(card->ctx, r); +} + +static int +isoApplet_set_security_env(sc_card_t *card, + const sc_security_env_t *env, int se_num) +{ + sc_apdu_t apdu; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 *p; + int r, locked = 0; + struct isoApplet_drv_data *drvdata = DRVDATA(card); + + LOG_FUNC_CALLED(card->ctx); + + if(se_num != 0) + { + LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, + "IsoApplet does not support storing of security environments."); + } + assert(card != NULL && env != NULL); + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0); + switch (env->operation) + { + case SC_SEC_OPERATION_DECIPHER: + apdu.p2 = 0xB8; + break; + case SC_SEC_OPERATION_SIGN: + apdu.p2 = 0xB6; + break; + default: + return SC_ERROR_INVALID_ARGUMENTS; + } + p = sbuf; + + if (env->flags & SC_SEC_ENV_ALG_PRESENT) + { + + switch(env->algorithm) + { + + case SC_ALGORITHM_RSA: + if( env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1 ) + { + drvdata->sec_env_alg_ref = ISOAPPLET_ALG_REF_RSA_PAD_PKCS1; + } + else + { + LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "IsoApplet only supports RSA with PKCS1 padding."); + } + break; + + case SC_ALGORITHM_EC: + if( env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW ) + { + drvdata->sec_env_alg_ref = ISOAPPLET_ALG_REF_ECDSA; + } + else + { + LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "IsoApplet only supports raw ECDSA."); + } + break; + + default: + LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported algorithm."); + } + + *p++ = 0x80; /* algorithm reference */ + *p++ = 0x01; + *p++ = drvdata->sec_env_alg_ref; + } + + if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) + { + *p++ = 0x81; + *p++ = env->file_ref.len; + assert(sizeof(sbuf) - (p - sbuf) >= env->file_ref.len); + memcpy(p, env->file_ref.value, env->file_ref.len); + p += env->file_ref.len; + } + + if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) + { + if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) + *p++ = 0x83; + else + *p++ = 0x84; + *p++ = env->key_ref_len; + assert(sizeof(sbuf) - (p - sbuf) >= env->key_ref_len); + memcpy(p, env->key_ref, env->key_ref_len); + p += env->key_ref_len; + } + r = p - sbuf; + apdu.lc = r; + apdu.datalen = r; + apdu.data = sbuf; + + if (se_num > 0) + { + r = sc_lock(card); + LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); + locked = 1; + } + + if (apdu.datalen != 0) + { + r = sc_transmit_apdu(card, &apdu); + if (r) + { + sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r)); + goto err; + } + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if (r) + { + sc_log(card->ctx, "%s: Card returned error", sc_strerror(r)); + goto err; + } + } + + if (se_num <= 0) + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num); + r = sc_transmit_apdu(card, &apdu); + sc_unlock(card); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_FUNC_RETURN(card->ctx, r); +err: + if (locked) + sc_unlock(card); + LOG_FUNC_RETURN(card->ctx, r); +} + +static int +isoApplet_compute_signature(struct sc_card *card, + const u8 * data, size_t datalen, + u8 * out, size_t outlen) +{ + struct isoApplet_drv_data *drvdata = DRVDATA(card); + int r; + size_t xlen, ylen; + size_t i, offset; + + LOG_FUNC_CALLED(card->ctx); + + r = iso_ops->compute_signature(card, data, datalen, out, outlen); + if(r < 0) + { + LOG_FUNC_RETURN(card->ctx, r); + } + + /* If we used ECDSA for the signature op, OpenSC thinks it has to + * convert it to {sequence, sequence} which is already done by the + * card actually. + * To fix this, I strip the {sequence, sequence} structual information + * so that pkcs11-tool.c can add it again... */ + if(drvdata->sec_env_alg_ref == ISOAPPLET_ALG_REF_ECDSA) + { + /* Outer SEQUENCE tag and first INTEGER tag. */ + offset=0; + if(r < 2 + || out[offset++] != 0x30 + || out[offset++] != r-2 + || out[offset++] != 0x02) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + } + + /* X */ + xlen = out[offset++]; + assert(xlen+4 < outlen); + /* Remove the leading 0 of the coordinate, if present. */ + if(out[offset] == 0x00) + { + offset++; + xlen--; + } + for(i=0; i < xlen; i++) + { + out[i] = out[i+offset]; + } + + /* Y */ + assert(i+offset+3 < outlen); + if(out[i+offset++] != 0x02) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + } + ylen = out[i+offset++]; + /* Remove the leading 0 of the coordinate, if present. */ + if(out[i+offset] == 0x00) + { + offset++; + ylen--; + } + assert(offset+xlen+ylen <= outlen); + for(; i < xlen+ylen; i++) + { + out[i] = out[i+offset]; + } + r = xlen+ylen; + } + LOG_FUNC_RETURN(card->ctx, r); +} + +static struct sc_card_driver *sc_get_driver(void) +{ + sc_card_driver_t *iso_drv = sc_get_iso7816_driver(); + + if(iso_ops == NULL) + { + iso_ops = iso_drv->ops; + } + + isoApplet_ops = *iso_drv->ops; + + isoApplet_ops.match_card = isoApplet_match_card; + isoApplet_ops.init = isoApplet_init; + isoApplet_ops.finish = isoApplet_finish; + + isoApplet_ops.card_ctl = isoApplet_card_ctl; + + isoApplet_ops.create_file = isoApplet_create_file; + isoApplet_ops.process_fci = isoApplet_process_fci; + isoApplet_ops.set_security_env = isoApplet_set_security_env; + isoApplet_ops.compute_signature = isoApplet_compute_signature; + + /* unsupported functions */ + isoApplet_ops.write_binary = NULL; + isoApplet_ops.read_record = NULL; + isoApplet_ops.write_record = NULL; + isoApplet_ops.append_record = NULL; + isoApplet_ops.update_record = NULL; + isoApplet_ops.get_challenge = NULL; + isoApplet_ops.restore_security_env = NULL; + + return &isoApplet_drv; +} + +struct sc_card_driver * sc_get_isoApplet_driver(void) +{ + return sc_get_driver(); +} diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index b46185ab..98a34f0f 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -255,7 +255,14 @@ enum { */ SC_CARDCTL_DNIE_BASE = _CTL_PREFIX('D', 'N', 'I'), SC_CARDCTL_DNIE_GENERATE_KEY, - SC_CARDCTL_DNIE_GET_INFO + SC_CARDCTL_DNIE_GET_INFO, + + /* + * isoApplet Java Card Applet + */ + SC_CARDCTL_ISOAPPLET_BASE = _CTL_PREFIX('I','S','O'), + SC_CARDCTL_ISOAPPLET_GENERATE_KEY, + SC_CARDCTL_ISOAPPLET_IMPORT_KEY }; enum { @@ -957,6 +964,30 @@ typedef struct sc_cardctl_sc_hsm_wrapped_key { size_t wrapped_key_length; /* Length of key blob */ } sc_cardctl_sc_hsm_wrapped_key_t; +/* + * isoApplet + */ + +#define SC_ISOAPPLET_ALG_REF_RSA_GEN_2048 0xF3 +#define SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1 0xE0 +#define SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1 0xE1 + +typedef struct sc_cardctl_isoApplet_genkey { + u8 algorithm_ref; /* Algorithm reference sent to card */ + unsigned char *exponent; /* RSA public key exponent */ + unsigned int exponent_len; + unsigned int priv_key_ref; /* Private key refernce sent to card */ + unsigned char *pubkey; /* RSA public key modulus (or EC tlv-encoded public key) */ + unsigned int pubkey_len; +} sc_cardctl_isoApplet_genkey_t; + +typedef struct sc_cardctl_isoApplet_import_key { + u8 algorithm_ref; /*Algorithm reference sent to card */ + unsigned int priv_key_ref; /* Private key refernce sent to card */ + struct sc_pkcs15_prkey *prkey; +} sc_cardctl_isoApplet_import_key_t; + + #ifdef __cplusplus } #endif diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index 7be66671..229940b1 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -199,7 +199,11 @@ enum { SC_CARD_TYPE_DNIE_BLANK, /* ATR LC byte: 00 */ SC_CARD_TYPE_DNIE_ADMIN, /* ATR LC byte: 01 */ SC_CARD_TYPE_DNIE_USER, /* ATR LC byte: 03 */ - SC_CARD_TYPE_DNIE_TERMINATED /* ATR LC byte: 0F */ + SC_CARD_TYPE_DNIE_TERMINATED, /* ATR LC byte: 0F */ + + /* JavaCards with isoApplet */ + SC_CARD_TYPE_ISO_APPLET_BASE = 28000, + SC_CARD_TYPE_ISO_APPLET_GENERIC }; extern sc_card_driver_t *sc_get_default_driver(void); @@ -236,6 +240,7 @@ extern sc_card_driver_t *sc_get_authentic_driver(void); extern sc_card_driver_t *sc_get_iasecc_driver(void); extern sc_card_driver_t *sc_get_epass2003_driver(void); extern sc_card_driver_t *sc_get_dnie_driver(void); +extern sc_card_driver_t *sc_get_isoApplet_driver(void); #ifdef __cplusplus } diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index fa94dc14..19d23770 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -108,6 +108,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = { { "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver }, { "PIV-II", (void *(*)(void)) sc_get_piv_driver }, { "itacns", (void *(*)(void)) sc_get_itacns_driver }, + { "isoApplet", (void *(*)(void)) sc_get_isoApplet_driver }, /* The default driver should be last, as it handles all the * unrecognized cards. */ { "default", (void *(*)(void)) sc_get_default_driver }, diff --git a/src/pkcs15init/Makefile.am b/src/pkcs15init/Makefile.am index 1bffba0f..bf267df8 100644 --- a/src/pkcs15init/Makefile.am +++ b/src/pkcs15init/Makefile.am @@ -29,7 +29,8 @@ dist_pkgdata_DATA = \ iasecc.profile \ ias_adele_admin1.profile ias_adele_admin2.profile ias_adele_common.profile \ iasecc_generic_pki.profile iasecc_admin_eid.profile iasecc_generic_oberthur.profile \ - openpgp.profile sc-hsm.profile + openpgp.profile sc-hsm.profile \ + isoApplet.profile AM_CPPFLAGS = -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\" \ -I$(top_srcdir)/src @@ -46,4 +47,5 @@ libpkcs15init_la_SOURCES = \ pkcs15-rtecp.c pkcs15-myeid.c \ pkcs15-oberthur.c pkcs15-oberthur-awp.c \ pkcs15-authentic.c pkcs15-iasecc.c pkcs15-openpgp.c \ - pkcs15-sc-hsm.c + pkcs15-sc-hsm.c \ + pkcs15-isoApplet.c diff --git a/src/pkcs15init/Makefile.mak b/src/pkcs15init/Makefile.mak index 348534ee..fb4b28fb 100644 --- a/src/pkcs15init/Makefile.mak +++ b/src/pkcs15init/Makefile.mak @@ -9,7 +9,8 @@ OBJECTS = pkcs15-lib.obj profile.obj \ pkcs15-muscle.obj pkcs15-asepcos.obj pkcs15-rutoken.obj \ pkcs15-entersafe.obj pkcs15-rtecp.obj pkcs15-westcos.obj \ pkcs15-myeid.obj pkcs15-authentic.obj pkcs15-iasecc.obj \ - pkcs15-epass2003.obj pkcs15-openpgp.obj pkcs15-sc-hsm.obj + pkcs15-epass2003.obj pkcs15-openpgp.obj pkcs15-sc-hsm.obj \ + pkcs15-isoApplet.obj all: $(TARGET) diff --git a/src/pkcs15init/isoApplet.profile b/src/pkcs15init/isoApplet.profile new file mode 100644 index 00000000..acf252bf --- /dev/null +++ b/src/pkcs15init/isoApplet.profile @@ -0,0 +1,164 @@ +# +# PKCS15 profile for the isoApplet JavaCard Applet. +# - init driver: pkcs15-isoApplet.c +# - card driver: card-isoApplet.c +# + +cardinfo { + label = "JavaCard isoApplet"; + manufacturer = "unknown"; + min-pin-length = 4; + max-pin-length = 16; + pin-pad-char = 0x00; +} + +pkcs15 { + # Method to calculate ID of the crypto objects + # mozilla: SHA1(modulus) for RSA, SHA1(pub) for DSA + # rfc2459: SHA1(SequenceASN1 of public key components as ASN1 integers) + # native: 'E' + number_of_present_objects_of_the_same_type + # default value: 'native' + pkcs15-id-style = native; +} + +option default { + macros { + unusedspace-size = 128; + odf-size = 256; + aodf-size = 256; + cdf-size = 512; + prkdf-size = 512; + pukdf-size = 512; + dodf-size = 256; + } +} + +PIN so-pin { + attempts = 3; + max-length = 16; + min-length = 4; + reference = 1; + flags = case-sensitive, needs-padding; +} + +PIN so-puk { + attempts = 3; + max-length = 16; + min-length = 16; + reference = 2; + flags = unblockingPin, unblock-disabled, case-sensitive, change-disabled; +} + +filesystem { + DF MF { + path = 3F00; + type = DF; + + # This is the DIR file + EF DIR { + type = EF; + file-id = 2F00; + size = 128; + acl = *=NONE; + } + + # Here comes the application DF + DF PKCS15-AppDF { + type = DF; + file-id = 5015; + aid = A0:00:00:00:63:50:4B:43:53:2D:31:35; + acl = *=NONE, DELETE=$PIN; + size = 5000; + + EF PKCS15-ODF { + file-id = 5031; + size = $odf-size; + ACL = *=NONE; + } + + EF PKCS15-TokenInfo { + file-id = 5032; + ACL = *=NONE; + } + + EF PKCS15-UnusedSpace { + file-id = 5033; + size = $unusedspace-size; + ACL = *=NONE; + } + + EF PKCS15-AODF { + file-id = 4401; + size = $aodf-size; + ACL = *=$PIN, READ=NONE; + } + + EF PKCS15-PrKDF { + file-id = 4402; + size = $prkdf-size; + acl = *=$PIN, READ=NONE; + } + + EF PKCS15-PuKDF { + file-id = 4403; + size = $pukdf-size; + acl = *=$PIN, READ=NONE; + } + + EF PKCS15-CDF { + file-id = 4404; + size = $cdf-size; + acl = *=$PIN, READ=NONE; + } + + EF PKCS15-DODF { + file-id = 4405; + size = $dodf-size; + ACL = *=$PIN, READ=NONE; + } + + template key-domain { + + BSO private-key { + ACL = *=$PIN, READ=NEVER; + } + + # EF private-key { + # file-id = 3000; + # acl = *=NEVER, UPDATE=$PIN, ERASE=$PIN; + # } + + # EF extractable-key { + # file-id = 3100; + # acl = *=NEVER, READ=$PIN, UPDATE=$PIN, + # ERASE=$PIN; + # } + + EF data { + file-id = 3200; + acl = *=NEVER, UPDATE=$PIN, READ=NONE, + DELETE-SELF=$PIN, ERASE=$PIN; + } + + EF privdata { + file-id = 3500; + acl = *=NEVER, UPDATE=$PIN, READ=$PIN, + DELETE-SELF=$PIN, ERASE=$PIN; + } + + EF public-key { + file-id = 3300; + acl = *=NEVER, UPDATE=$PIN, READ=NONE, + DELETE-SELF=$PIN, ERASE=$PIN; + } + + EF certificate { + file-id = 3400; + acl = *=NEVER, UPDATE=$PIN, READ=NONE, + DELETE-SELF=$PIN, ERASE=$PIN; + } + + } + } + } +} diff --git a/src/pkcs15init/pkcs15-init.h b/src/pkcs15init/pkcs15-init.h index c40ff7f6..9fc9a97d 100644 --- a/src/pkcs15init/pkcs15-init.h +++ b/src/pkcs15init/pkcs15-init.h @@ -420,6 +420,7 @@ extern struct sc_pkcs15init_operations *sc_pkcs15init_get_iasecc_ops(void); extern struct sc_pkcs15init_operations *sc_pkcs15init_get_piv_ops(void); extern struct sc_pkcs15init_operations *sc_pkcs15init_get_openpgp_ops(void); extern struct sc_pkcs15init_operations *sc_pkcs15init_get_sc_hsm_ops(void); +extern struct sc_pkcs15init_operations *sc_pkcs15init_get_isoApplet_ops(void); #ifdef __cplusplus } diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c new file mode 100644 index 00000000..41410c50 --- /dev/null +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -0,0 +1,871 @@ +/* + * pkcs15-init driver for JavaCards with IsoApplet installed. + * + * Copyright (C) 2014 Philip Wendland + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "../libopensc/log.h" +#include "../libopensc/internal.h" +#include "../libopensc/opensc.h" +#include "../libopensc/cardctl.h" +#include "../libopensc/asn1.h" +#include "pkcs15-init.h" +#include "profile.h" + +#define ISOAPPLET_KEY_ID_MIN 0 +#define ISOAPPLET_KEY_ID_MAX 15 + + +struct ec_curve +{ + const struct sc_lv_data oid; + const struct sc_lv_data prime; + const struct sc_lv_data coefficientA; + const struct sc_lv_data coefficientB; + const struct sc_lv_data basePointG; + const struct sc_lv_data order; + const struct sc_lv_data coFactor; +}; + +static struct ec_curve curves[] = +{ + + { + { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x03", 9}, /* brainpoolP192r1 */ + { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x30\x93\xD1\x8D\xB7\x8F\xCE\x47\x6D\xE1\xA8\x62\x97", 24}, + { (unsigned char *) "\x6A\x91\x17\x40\x76\xB1\xE0\xE1\x9C\x39\xC0\x31\xFE\x86\x85\xC1\xCA\xE0\x40\xE5\xC6\x9A\x28\xEF", 24}, + { (unsigned char *) "\x46\x9A\x28\xEF\x7C\x28\xCC\xA3\xDC\x72\x1D\x04\x4F\x44\x96\xBC\xCA\x7E\xF4\x14\x6F\xBF\x25\xC9", 24}, + { (unsigned char *) "\xC0\xA0\x64\x7E\xAA\xB6\xA4\x87\x53\xB0\x33\xC5\x6C\xB0\xF0\x90\x0A\x2F\x5C\x48\x53\x37\x5F\xD6\x14\xB6\x90\x86\x6A\xBD\x5B\xB8\x8B\x5F\x48\x28\xC1\x49\x00\x02\xE6\x77\x3F\xA2\xFA\x29\x9B\x8F", 48}, + { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x2F\x9E\x9E\x91\x6B\x5B\xE8\xF1\x02\x9A\xC4\xAC\xC1", 24}, + { (unsigned char *) "\x00\x01", 2} + }, + + { + { (unsigned char *) "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8}, /* secp256r1 aka prime256v1 */ + { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 32}, + { (unsigned char *) "\x5A\xC6\x35\xD8\xAA\x3A\x93\xE7\xB3\xEB\xBD\x55\x76\x98\x86\xBC\x65\x1D\x06\xB0\xCC\x53\xB0\xF6\x3B\xCE\x3C\x3E\x27\xD2\x60\x4B", 32}, + { (unsigned char *) "\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5", 64}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", 32}, + { (unsigned char *) "\x00\x01", 2} + }, + + { + { NULL, 0}, + { NULL, 0}, + { NULL, 0}, + { NULL, 0}, + { NULL, 0}, + { NULL, 0}, + { NULL, 0} + } +}; + + +/* + * Create DF, using default pkcs15init functions. + */ +static int +isoApplet_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df) +{ + sc_card_t *card = p15card->card; + int r = SC_SUCCESS; + + LOG_FUNC_CALLED(card->ctx); + + if(!profile || !p15card || !df || !p15card->card || !p15card->card->ctx) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + } + r = sc_pkcs15init_create_file(profile, p15card, df); + LOG_FUNC_RETURN(card->ctx, r); +} + +/* + * Select a PIN reference. + * + * Basically (as I understand it) the caller passes an auth_info object and the + * auth_info->attrs.pin.reference is supposed to be set accordingly and return. + * + * The IsoApplet only supports a PIN and a PUK at the moment. + * The reference for the PIN is 1, for the PUK 2. + */ +static int +isoApplet_select_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card, + sc_pkcs15_auth_info_t *auth_info) +{ + sc_card_t *card = p15card->card; + int preferred, current; + + LOG_FUNC_CALLED(card->ctx); + + if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OBJECT_NOT_VALID); + } + + current = auth_info->attrs.pin.reference; + if (current < 0) + { + current = 0; + } + + if(current > 2) + { + /* Only two PINs supported: User PIN and PUK. */ + LOG_FUNC_RETURN(card->ctx, SC_ERROR_TOO_MANY_OBJECTS); + } + else + { + if(auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) + { + /* PUK */ + preferred = 2; + } + else + { + /* PIN */ + preferred = 1; + } + } + + auth_info->attrs.pin.reference = preferred; + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +/* + * Create a PIN and store it on the card using CHANGE REFERENCE DATA for PIN transmission. + * First, the PUK is transmitted, then the PIN. Now, the IsoApplet is in the + * "STATE_OPERATIONAL_ACTIVATED" lifecycle state. + */ +static int +isoApplet_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df, + sc_pkcs15_object_t *pin_obj, + const u8 *pin, size_t pin_len, + const u8 *puk, size_t puk_len) +{ + sc_card_t *card = p15card->card; + sc_pkcs15_auth_info_t *auth_info = (sc_pkcs15_auth_info_t *) pin_obj->data; + struct sc_pkcs15_pin_attributes *pin_attrs = &auth_info->attrs.pin; + int r; + + LOG_FUNC_CALLED(card->ctx); + + if(!pin || !pin_len || !p15card || !p15card->card || !df || !&df->path) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + } + + if(pin_attrs->reference != 1 && pin_attrs->reference != 2) + { + /* Reject PIN reference. */ + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_PIN_REFERENCE); + } + + /* If we have a PUK, set it first. */ + if(puk && puk_len) + { + /* The PUK has a incremented reference, i.e. pins are odd, puks are equal (+1). */ + r = sc_change_reference_data(p15card->card, SC_AC_CHV, + pin_attrs->reference+1, + NULL, 0, + puk, puk_len, NULL); + if(r < 0) + { + LOG_FUNC_RETURN(card->ctx, r); + } + } + + /* Store PIN: (use CHANGE REFERENCE DATA). */ + r = sc_change_reference_data(p15card->card, SC_AC_CHV, + pin_attrs->reference, + NULL, 0, + pin, pin_len, NULL); + + LOG_FUNC_RETURN(card->ctx, r); +} + +/* + * @brief Get the OID of the curve specified by a curve name. + * + * @param[in] named_curve The name of the curve to search the OID of. + * Supported values are: brainpoolP192r1, prime256v1. + * @param[out] oid The OID of the curve. + * + * @returns SC_SUCCESS: If the curve was found. + * SC_ERROR_INVALID_ARGUMENTS: If named_curve was null or the curve + * was not found + */ +static int +isoApplet_get_curve_oid(const char* named_curve, const struct sc_lv_data **oid) +{ + if(!named_curve) + return SC_ERROR_INVALID_ARGUMENTS; + + if(strncmp(named_curve, "brainpoolP192r1", 15) == 0) + { + *oid = &curves[0].oid; + return SC_SUCCESS; + } + else if(strncmp(named_curve, "prime256v1", 10) == 0) + { + *oid = &curves[1].oid; + return SC_SUCCESS; + } + return SC_ERROR_INVALID_ARGUMENTS; +} + +/* + * @brief Check the consistency of TLV-encoded EC curve parameters. + * + * Check the EC params in buf (length: len) that are structured according + * to ISO 7816-8 table 3 - Public key data objects. + * The params are compared with the ones given in the curve struct. + * + * @param[in] ctx + * @param[in] buf The buffer containing the TLV-encoded (ISO 7816-8 table 3) + * EC parameters. + * @param[in] len The length of buf. + * @param[in] curve An ec_curve struct that should be used to check the + * parameters in buf. + * + * @return SC_SUCCESS: If the EC parameters are consistent. + * SC_ERROR_INCOMPATIBLE_KEY: If the curve is unknown or the EC + * parameters are not consistent. + */ +static int +checkEcParams(sc_context_t* ctx, const u8* buf, size_t len, const struct ec_curve curve) +{ + const u8 *curr_pos = NULL; + size_t tag_len; + int r = SC_SUCCESS; + + LOG_FUNC_CALLED(ctx); + + /* Check the field. */ + curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x81, &tag_len); + if(curr_pos == NULL || tag_len != curve.prime.len) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "Could not find any EC field tag in the response template or the length was unexpected."); + } + if(memcmp(curr_pos, curve.prime.value, curve.prime.len) != 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "The EC field by the smartcard was unexpected."); + } + + /* Check the coefficient A. */ + curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x82, &tag_len); + if(curr_pos == NULL || tag_len != curve.coefficientA.len) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "Could not find any EC coefficient A tag in the response template or the length was unexpected."); + } + if(memcmp(curr_pos, curve.coefficientA.value, curve.coefficientA.len) != 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "The EC coefficient A returned by the smartcard was unexpected."); + } + + /* Check the coefficient B. */ + curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x83, &tag_len); + if(curr_pos == NULL || tag_len != curve.coefficientB.len) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "Could not find any EC coefficient B tag in the response template or the length was unexpected."); + } + if(memcmp(curr_pos, curve.coefficientB.value, curve.coefficientB.len) != 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "The EC coefficient B returned by the smartcard was unexpected."); + } + + /* Check the basepoint G. + * Note: The IsoApplet omits the 0x04 (uncompressed) tag. */ + curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x84, &tag_len); + if(curr_pos == NULL || tag_len != curve.basePointG.len) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "Could not find any EC basepoint G tag in the response template or the length was unexpected."); + } + if(memcmp(curr_pos, curve.basePointG.value, curve.basePointG.len) != 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "The EC basepoint G returned by the smartcard was unexpected."); + } + + /* Check the order. */ + curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x85, &tag_len); + if(curr_pos == NULL || tag_len != curve.order.len) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "Could not find any EC order tag in the response template or the length was unexpected."); + } + if(memcmp(curr_pos, curve.order.value, curve.order.len) != 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "The EC order returned by the smartcard was unexpected."); + } + + /* Check the coFactor. */ + curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x87, &tag_len); + if(curr_pos == NULL || tag_len != curve.coFactor.len) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "Could not find any EC cofactor tag in the response template or the length was unexpected."); + } + if(memcmp(curr_pos, curve.coFactor.value, curve.coFactor.len) != 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + LOG_TEST_RET(ctx, r, + "The EC cofactor returned by the smartcards was unexpected."); + } + + LOG_FUNC_RETURN(ctx, r); +} + +/* + * @brief Generate a RSA private key on the card. + * + * A MANAGE SECURITY ENVIRONMENT apdu must have been sent before. + * This function uses card_ctl to access the card-isoApplet driver. + * + * @param[in] key_info + * @param[in] card + * @param[in] pubkey The public key of the generated key pair + * returned by the card. + * + * @return SC_ERROR_INVALID_ARGURMENTS: Invalid key length. + * SC_ERROR_OUT_OF_MEMORY + */ +static int +generate_key_rsa(sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, + sc_pkcs15_pubkey_t *pubkey) +{ + int rv; + size_t keybits; + struct sc_cardctl_isoApplet_genkey args; + + LOG_FUNC_CALLED(card->ctx); + + /* Check key size: */ + keybits = key_info->modulus_length; + if (keybits != 2048) + { + rv = SC_ERROR_INVALID_ARGUMENTS; + sc_log(card->ctx, "%s: RSA private key length is unsupported, correct length is 2048", sc_strerror(rv)); + goto err; + } + + /* Generate the key. + * Note: keysize is not explicitly passed to the card. It assumes 2048 along with the algorithm reference. */ + memset(&args, 0, sizeof(args)); + args.algorithm_ref = SC_ISOAPPLET_ALG_REF_RSA_GEN_2048; + args.priv_key_ref = key_info->key_reference; + + args.pubkey_len = keybits / 8; + args.pubkey = malloc(args.pubkey_len); + if (!args.pubkey) + { + rv = SC_ERROR_OUT_OF_MEMORY; + sc_log(card->ctx, "%s: Unable to allocate public key buffer.", sc_strerror(rv)); + goto err; + } + + args.exponent_len = 3; + args.exponent = malloc(args.exponent_len); + if(!args.exponent) + { + rv = SC_ERROR_OUT_OF_MEMORY; + sc_log(card->ctx, "%s: Unable to allocate public key exponent buffer.", sc_strerror(rv)); + goto err; + } + + rv = sc_card_ctl(card, SC_CARDCTL_ISOAPPLET_GENERATE_KEY, &args); + if (rv < 0) + { + sc_log(card->ctx, "%s: Error in card_ctl", sc_strerror(rv)); + goto err; + } + + /* extract public key */ + pubkey->algorithm = SC_ALGORITHM_RSA; + pubkey->u.rsa.modulus.len = args.pubkey_len; + pubkey->u.rsa.modulus.data = args.pubkey; + pubkey->u.rsa.exponent.len = args.exponent_len; + pubkey->u.rsa.exponent.data = args.exponent; + rv = SC_SUCCESS; + LOG_FUNC_RETURN(card->ctx, rv); +err: + if (args.pubkey) + { + free(args.pubkey); + pubkey->u.rsa.modulus.data = NULL; + pubkey->u.rsa.modulus.len = 0; + } + if (args.exponent) + { + free(args.exponent); + pubkey->u.rsa.exponent.data = NULL; + pubkey->u.rsa.exponent.len = 0; + } + LOG_FUNC_RETURN(card->ctx, rv); +} + +/* + * @brief Generate a EC private key on the card. + * + * A MANAGE SECURITY ENVIRONMENT apdu must have been sent before. + * This function uses card_ctl to access the card-isoApplet driver. + * + * @param[in] key_info + * @param[in] card + * @param[in] pubkey The public key of the generated key pair + * returned by the card. + * + * @return SC_ERROR_INVALID_ARGURMENTS: Invalid key length or curve. + * SC_ERROR_OUT_OF_MEMORY + * SC_ERROR_INCOMPATIBLE_KEY: The data returned by the card + * was unexpected and can not be + * handled. + */ +static int +generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, + sc_pkcs15_pubkey_t *pubkey) +{ + int r; + u8* p = NULL; + u8* ecPubKeyPoint = NULL; + size_t tag_len; + size_t all_tags_len; + const u8* curr_pos = NULL; + struct sc_ec_params* ecp = NULL; + const struct sc_lv_data* oid = NULL; + sc_cardctl_isoApplet_genkey_t args; + const struct sc_pkcs15_ec_parameters* info_ecp = + (struct sc_pkcs15_ec_parameters *) key_info->params.data; + + LOG_FUNC_CALLED(card->ctx); + + /* Check key size: */ + if(key_info->field_length != 192 + && key_info->field_length != 256) + { + sc_log(card->ctx, "EC field length is unsupported, length provided was: %d.", key_info->field_length); + r = SC_ERROR_INVALID_ARGUMENTS; + goto err; + } + + if(info_ecp->named_curve && strncmp(info_ecp->named_curve, "brainpoolP192r1", 15) != 0 + && strncmp(info_ecp->named_curve, "prime256v1", 10) != 0) + { + sc_log(card->ctx, "EC key generation failed: Unsupported curve: [%s].", info_ecp->named_curve); + r = SC_ERROR_INVALID_ARGUMENTS; + goto err; + } + + /* Generate the key. + * Note: THe field size is not explicitly passed to the card. + * It assumes it along with the algorithm reference. */ + memset(&args, 0, sizeof(args)); + + args.pubkey_len = 512; + args.pubkey = malloc(args.pubkey_len); + if(!args.pubkey) + { + r = SC_ERROR_OUT_OF_MEMORY; + sc_log(card->ctx, "%s: Unable to allocate public key buffer.", sc_strerror(r)); + goto err; + } + + if(strncmp(info_ecp->named_curve, "brainpoolP192r1", 15) == 0) + { + args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1; + } + else if(strncmp(info_ecp->named_curve, "prime256v1", 10) == 0) + { + args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1; + } + args.priv_key_ref = key_info->key_reference; + + r = sc_card_ctl(card, SC_CARDCTL_ISOAPPLET_GENERATE_KEY, &args); + if (r < 0) + { + sc_log(card->ctx, "%s: Error in card_ctl.", sc_strerror(r)); + goto err; + } + + /* Extract the public key. */ + pubkey->algorithm = SC_ALGORITHM_EC; + + /* Get the curves OID. */ + r = isoApplet_get_curve_oid(info_ecp->named_curve, &oid); + if(r < 0) + { + sc_log(card->ctx, "Error obtaining the curve OID.", sc_strerror(r)); + goto err; + } + + /* der-encoded parameters */ + ecp = calloc(1, sizeof(struct sc_ec_params)); + if(!ecp) + { + r = SC_ERROR_OUT_OF_MEMORY; + goto err; + } + ecp->der_len = oid->len + 2; + ecp->der = calloc(ecp->der_len, 1); + if(!ecp->der) + { + r = SC_ERROR_OUT_OF_MEMORY; + sc_log(card->ctx, "%s: Unable to allocate public key buffer.", sc_strerror(r)); + goto err; + } + ecp->der[0] = 0x06; + ecp->der[1] = (u8)oid->len; + memcpy(ecp->der + 2, oid->value, oid->len); + ecp->type = 1; /* named curve */ + + pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id)); + if(!pubkey->alg_id) + { + r = SC_ERROR_OUT_OF_MEMORY; + sc_log(card->ctx, "%s: Unable to allocate public key sc_algorithm_id.", sc_strerror(r)); + goto err; + } + pubkey->alg_id->algorithm = SC_ALGORITHM_EC; + pubkey->alg_id->params = ecp; + + p = args.pubkey; + if(memcmp(info_ecp->named_curve, "brainpoolP192r1", 15) == 0) + { + /* The applet returns the public key encoded according to + * ISO 7816-8 table 3 - Public key data objects. This is a + * 2-byte tag. A length of 0xD0 = 208 is expected for BrainpoolP192r1. */ + if(memcmp(p, "\x7F\x49\x81\xD0", 4) != 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + sc_log(card->ctx, "%s: Key generation error: Unexpected EC public key received length.", sc_strerror(r)); + goto err; + } + else + { + p += 4; /* p points to the value field of the outer (7F 49) tag. + * This value field is a TLV-structure again. */ + all_tags_len = 208; /* 0xD0 bytes */ + } + + /* Check EC params. */ + r = checkEcParams(card->ctx, p, all_tags_len, curves[0]); + if(r != SC_SUCCESS) + { + goto err; + } + } + else if(memcmp(info_ecp->named_curve, "prime256v1", 10) == 0) + { + /* The applet returns the public key encoded according to + * ISO 7816-8 table 3 - Public key data objects. This is a + * 2-byte tag. A length of 0x011A = 282 is expected for Prime256v1. */ + if(memcmp(p, "\x7F\x49\x82\x01\x1A", 5) != 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + sc_log(card->ctx, "%s: Key generation error: Unexpected EC public key parameters.", sc_strerror(r)); + goto err; + } + else + { + p += 5; /* p points to the value field of the outer (7F 49) tag. + * This value field is a TLV-structure again. */ + all_tags_len = 282; /* 0x011A bytes */ + } + + /* Check EC params. */ + r = checkEcParams(card->ctx, p, all_tags_len, curves[1]); + if(r != SC_SUCCESS) + { + goto err; + } + } + + /* Extract ecpointQ */ + curr_pos = sc_asn1_find_tag(card->ctx, p, all_tags_len, (unsigned int) 0x86, &tag_len); + if(curr_pos == NULL || tag_len == 0) + { + r = SC_ERROR_INCOMPATIBLE_KEY; + sc_log(card->ctx, "%s: Could not find any EC pointQ tag in the response template.", sc_strerror(r)); + goto err; + } + ecPubKeyPoint = malloc(tag_len+1); + if(!ecPubKeyPoint) + { + r = SC_ERROR_OUT_OF_MEMORY; + sc_log(card->ctx, "%s: Unable to allocate public key ecpointQ buffer.", sc_strerror(r)); + goto err; + } + *ecPubKeyPoint = 0x04; /* uncompressed */ + memcpy(ecPubKeyPoint+1, curr_pos, tag_len); + pubkey->u.ec.ecpointQ.value = ecPubKeyPoint; + pubkey->u.ec.ecpointQ.len = tag_len+1; + + /* OID for the public key */ + pubkey->u.ec.params.der.value = malloc(ecp->der_len); + if(!pubkey->u.ec.params.der.value) + { + r = SC_ERROR_OUT_OF_MEMORY; + sc_log(card->ctx, "%s: Unable to allocate public key ec params buffer.", sc_strerror(r)); + goto err; + } + memcpy(pubkey->u.ec.params.der.value, ecp->der, ecp->der_len); + pubkey->u.ec.params.der.len = ecp->der_len; + + r = sc_pkcs15_fix_ec_parameters(card->ctx, &pubkey->u.ec.params); + LOG_FUNC_RETURN(card->ctx, r); +err: + if(pubkey) + { + if(pubkey->alg_id) + { + free(pubkey->alg_id); + pubkey->alg_id = NULL; + } + if(pubkey->u.ec.params.der.value) + { + free(pubkey->u.ec.params.der.value); + pubkey->u.ec.params.der.value = NULL; + pubkey->u.ec.params.der.len = 0; + } + memset(pubkey, 0, sizeof(sc_pkcs15_pubkey_t)); + } + if(args.pubkey) + { + free(args.pubkey); + args.pubkey = NULL; + args.pubkey_len = 0; + } + if(ecPubKeyPoint) + { + free(ecPubKeyPoint); + ecPubKeyPoint = NULL; + } + if(ecp) + { + if(ecp->der) + { + free(ecp->der); + ecp->der = NULL; + } + free(ecp); + ecp = NULL; + } + LOG_FUNC_RETURN(card->ctx, r); +} + +static int +isoApplet_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, + sc_pkcs15_object_t *obj, + sc_pkcs15_pubkey_t *pubkey) +{ + int r; + sc_pkcs15_prkey_info_t* key_info = (sc_pkcs15_prkey_info_t *) obj->data; + sc_file_t* privKeyFile=NULL; + sc_card_t* card = p15card->card; + + LOG_FUNC_CALLED(card->ctx); + + /* Authentication stuff. */ + r = sc_profile_get_file_by_path(profile, &key_info->path, &privKeyFile); + if(!privKeyFile) + { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); + } + r = sc_pkcs15init_authenticate(profile, p15card, privKeyFile, SC_AC_OP_CREATE_EF); + if(r < 0) + { + sc_file_free(privKeyFile); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); + } + sc_file_free(privKeyFile); + + /* Generate the key. */ + switch(obj->type) + { + case SC_PKCS15_TYPE_PRKEY_RSA: + r = generate_key_rsa(key_info, card, pubkey); + break; + + case SC_PKCS15_TYPE_PRKEY_EC: + r = generate_key_ec(key_info, card, pubkey); + break; + + default: + r = SC_ERROR_NOT_SUPPORTED; + sc_log(card->ctx, "%s: Key generation failed: Unknown/unsupported key type.", strerror(r)); + } + + LOG_FUNC_RETURN(card->ctx, r); +} + + +/* + * Create a new key file. This is a no-op, because private keys are stored as key objects on the javacard. + */ +static int +isoApplet_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj) +{ + sc_card_t *card = p15card->card; + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +/* + * Select a key reference. + */ +static int +isoApplet_select_key_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card, + sc_pkcs15_prkey_info_t *key_info) +{ + int rv = SC_SUCCESS; + sc_card_t *card = p15card->card; + + LOG_FUNC_CALLED(card->ctx); + + if(key_info->key_reference < ISOAPPLET_KEY_ID_MIN) + { + key_info->key_reference = ISOAPPLET_KEY_ID_MIN; + rv = SC_SUCCESS; + } + if(key_info->key_reference > ISOAPPLET_KEY_ID_MAX) + { + rv = SC_ERROR_TOO_MANY_OBJECTS; + } + LOG_FUNC_RETURN(card->ctx, rv); +} + +/* + * Store a usable private key on the card. + */ +static int +isoApplet_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *object, + sc_pkcs15_prkey_t *key) +{ + sc_card_t *card = p15card->card; + sc_pkcs15_prkey_info_t* key_info = (sc_pkcs15_prkey_info_t *) object->data; + sc_file_t* privKeyFile=NULL; + sc_cardctl_isoApplet_import_key_t args; + int r; + char *p = NULL; + + LOG_FUNC_CALLED(card->ctx); + + /* Authentication stuff. */ + r = sc_profile_get_file_by_path(profile, &key_info->path, &privKeyFile); + if(!privKeyFile) + { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); + } + r = sc_pkcs15init_authenticate(profile, p15card, privKeyFile, SC_AC_OP_CREATE_EF); + if(r < 0) + { + sc_file_free(privKeyFile); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); + } + sc_file_free(privKeyFile); + + /* Key import. */ + switch(object->type) + { + case SC_PKCS15_TYPE_PRKEY_RSA: + args.algorithm_ref = SC_ISOAPPLET_ALG_REF_RSA_GEN_2048; + break; + + case SC_PKCS15_TYPE_PRKEY_EC: + p = key->u.ec.params.named_curve; + if(!p) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + } + + if(strncmp(p, "brainpoolP192r1", 15) == 0) + { + args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1; + } + else if(strncmp(p, "prime256v1", 10) == 0) + { + args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1; + } + break; + + default: + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); + } + args.priv_key_ref = key_info->key_reference; + args.prkey = key; + + r = sc_card_ctl(card, SC_CARDCTL_ISOAPPLET_IMPORT_KEY, &args); + if (r < 0) + { + sc_log(card->ctx, "%s: Error in card_ctl", sc_strerror(r)); + LOG_FUNC_RETURN(card->ctx, r); + } + + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +static struct sc_pkcs15init_operations sc_pkcs15init_isoApplet_operations = +{ + NULL, /* erase_card */ + NULL, /* init_card */ + isoApplet_create_dir, /* create_dir */ + NULL, /* create_domain */ + isoApplet_select_pin_reference, /* pin_reference*/ + isoApplet_create_pin, /* create_pin */ + isoApplet_select_key_reference, /* key_reference */ + isoApplet_create_key, /* create_key */ + isoApplet_store_key, /* store_key */ + isoApplet_generate_key, /* generate_key */ + NULL, NULL, /* encode private/public key */ + NULL, /* finalize */ + NULL, /* delete_object */ + NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */ + NULL, /* sanity_check*/ +}; + +struct +sc_pkcs15init_operations *sc_pkcs15init_get_isoApplet_ops(void) +{ + return &sc_pkcs15init_isoApplet_operations; +} diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index cc655f6a..a051201b 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -154,6 +154,7 @@ static struct profile_operations { { "westcos", (void *) sc_pkcs15init_get_westcos_ops }, { "myeid", (void *) sc_pkcs15init_get_myeid_ops }, { "sc-hsm", (void *) sc_pkcs15init_get_sc_hsm_ops }, + { "isoApplet", (void *) sc_pkcs15init_get_isoApplet_ops }, #ifdef ENABLE_OPENSSL { "authentic", (void *) sc_pkcs15init_get_authentic_ops }, { "iasecc", (void *) sc_pkcs15init_get_iasecc_ops }, From 6f9e894ebe8189eaf64fc20f644c3683b3f42930 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Tue, 21 Oct 2014 16:05:06 +0200 Subject: [PATCH 105/306] IsoApplet: set lock when doing command chaining --- src/libopensc/card-isoApplet.c | 86 +++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 06509b59..e43a3ff2 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -707,6 +707,7 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 *p = NULL; int r; + int locked = 0; size_t tags_len; LOG_FUNC_CALLED(card->ctx); @@ -743,6 +744,10 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); p += r; + r = sc_lock(card); /* We will use several apdus */ + LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); + locked = 1; + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDB, 0x3F, 0xFF); apdu.cla |= 0x10; /* Chaining */ apdu.data = sbuf; @@ -756,12 +761,20 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported." "If you are using an older applet version and are trying to import keys, please update your applet first."); } - LOG_TEST_RET(card->ctx, r, "Card returned error"); + if(r < 0) + { + sc_log(card->ctx, "Card returned error"); + goto out; + } /* q */ p = sbuf; r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x93, rsa->q.data, rsa->q.len); - LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + if(r < 0) + { + sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); + goto out; + } p += r; apdu.data = sbuf; @@ -769,42 +782,78 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) apdu.lc = p - sbuf; r = sc_check_apdu(card, &apdu); r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + if(r < 0) + { + sc_log(card->ctx, "%s: APDU transmit failed.", strerror(r)); + goto out; + } r = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_RET(card->ctx, r, "Card returned error"); + if(r < 0) + { + sc_log(card->ctx, "%s: Card returned error.", strerror(r)); + goto out; + } /* 1/q mod p */ p = sbuf; r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x94, rsa->iqmp.data, rsa->iqmp.len); - LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + if(r < 0) + { + sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); + goto out; + } p += r; apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + if(r < 0) + { + sc_log(card->ctx, "%s: APDU transmit failed.", strerror(r)); + goto out; + } r = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_RET(card->ctx, r, "Card returned error"); + if(r < 0) + { + sc_log(card->ctx, "%s: Card returned error.", strerror(r)); + goto out; + } /* d mod (p-1) */ p = sbuf; r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x95, rsa->dmp1.data, rsa->dmp1.len); - LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + if(r < 0) + { + sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); + goto out; + } p += r; apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + if(r < 0) + { + sc_log(card->ctx, "%s: APDU transmit failed.", strerror(r)); + goto out; + } r = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_RET(card->ctx, r, "Card returned error"); + if(r < 0) + { + sc_log(card->ctx, "%s: Card returned error.", strerror(r)); + goto out; + } /* d mod (q-1) */ p = sbuf; r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x96, rsa->dmq1.data, rsa->dmq1.len); - LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + if(r < 0) + { + sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); + goto out; + } p += r; apdu.cla = 0x00; /* Last part of the chain. */ @@ -812,10 +861,21 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) apdu.datalen = p - sbuf; apdu.lc = p - sbuf; r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + if(r < 0) + { + sc_log(card->ctx, "%s: APDU transmit failed.", strerror(r)); + goto out; + } r = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_RET(card->ctx, r, "Card returned error"); + if(r < 0) + { + sc_log(card->ctx, "%s: Card returned error.", strerror(r)); + goto out; + } +out: + if(locked) + sc_unlock(card); LOG_FUNC_RETURN(card->ctx, r); } From e3cc851b728ce7c5e681f67c58ef9788f74ca2fd Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Tue, 28 Oct 2014 08:58:30 +0100 Subject: [PATCH 106/306] IsoApplet: EC key-gen rework and refactorings Rework the EC key generation mechanism to send the curve parameters to the card. In earlier versions, the applet had a copy of the curve parameters and there was a different algorithm reference for every curve. This is unfeasible when trying to support a larger number of curves because of size limitations of the applet. This commit additionally includes some refactorings that should not change the functionality. --- src/libopensc/card-isoApplet.c | 599 ++++++++++++++++-------------- src/libopensc/cardctl.h | 47 ++- src/pkcs15init/pkcs15-isoApplet.c | 575 ++++++++++++---------------- 3 files changed, 587 insertions(+), 634 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index e43a3ff2..ea81960f 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -32,20 +32,31 @@ #define ISOAPPLET_ALG_REF_RSA_PAD_PKCS1 0x11 #define ISOAPPLET_API_VERSION_MAJOR 0x00 -#define ISOAPPLET_API_VERSION_MINOR 0x03 +#define ISOAPPLET_API_VERSION_MINOR 0x04 #define ISOAPPLET_API_FEATURE_EXT_APDU 0x01 #define ISOAPPLET_AID_LEN 12 -static const u8 isoAppletId[] = {0xf2,0x76,0xa2,0x88,0xbc,0xfb,0xa6,0x9d,0x34,0xf3,0x10,0x01}; +static const u8 isoApplet_aid[] = {0xf2,0x76,0xa2,0x88,0xbc,0xfb,0xa6,0x9d,0x34,0xf3,0x10,0x01}; struct isoApplet_drv_data { + /* Save the current algorithm reference + * (ISOAPPLET_ALG_REF_ECDSA, ISOAPPLET_ALG_REF_RSA_PAD_PKCS1) + * to be able to distiguish between RSA and ECC operations. + * If ECC is being used, the signatures generated by the card + * have to be modified. */ unsigned int sec_env_alg_ref; }; #define DRVDATA(card) ((struct isoApplet_drv_data *) ((card)->drv_data)) +/* Operations supported by the applet. */ static struct sc_card_operations isoApplet_ops; + +/* A reference to the iso7816_* functions. + * Initialized in sc_get_driver. */ static const struct sc_card_operations *iso_ops = NULL; + +/* The description of the driver. */ static struct sc_card_driver isoApplet_drv = { "Javacard with IsoApplet", @@ -71,7 +82,7 @@ static struct sc_card_driver isoApplet_drv = * not present. */ static int -isoApplet_select_applet(sc_card_t *card, const u8 aid[], const size_t aid_len, u8* resp, size_t *resp_len) +isoApplet_select_applet(sc_card_t *card, const u8 aid[], const size_t aid_len, u8 *resp, size_t *resp_len) { int rv; sc_context_t *ctx = card->ctx; @@ -103,7 +114,7 @@ isoApplet_select_applet(sc_card_t *card, const u8 aid[], const size_t aid_len, u } static int -isoApplet_finish(sc_card_t * card) +isoApplet_finish(sc_card_t *card) { struct isoApplet_drv_data *drvdata=DRVDATA(card); @@ -117,20 +128,21 @@ isoApplet_finish(sc_card_t * card) } static int -isoApplet_match_card(sc_card_t * card) +isoApplet_match_card(sc_card_t *card) { size_t rlen = SC_MAX_APDU_BUFFER_SIZE; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; int rv; - rv = isoApplet_select_applet(card, isoAppletId, ISOAPPLET_AID_LEN, rbuf, &rlen); + rv = isoApplet_select_applet(card, isoApplet_aid, ISOAPPLET_AID_LEN, rbuf, &rlen); if(rv != SC_SUCCESS) { return 0; } - /* If applet does not return API version, versions 0x00 will match */ + /* The IsoApplet should return an API version (major and minor) and a feature bitmap. + * If applet does not return API version, versions 0x00 will match */ if(rlen == 0) { rbuf[0] = 0x00; @@ -170,7 +182,7 @@ isoApplet_match_card(sc_card_t * card) } static int -isoApplet_init(sc_card_t * card) +isoApplet_init(sc_card_t *card) { unsigned long flags = 0; unsigned long ext_flags = 0; @@ -178,10 +190,10 @@ isoApplet_init(sc_card_t * card) LOG_FUNC_CALLED(card->ctx); - drvdata=malloc(sizeof(struct isoApplet_drv_data)); + drvdata=malloc(sizeof(*drvdata)); if (!drvdata) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); - memset(drvdata, 0, sizeof(struct isoApplet_drv_data)); + memset(drvdata, 0, sizeof(*drvdata)); drvdata->sec_env_alg_ref = 0; card->drv_data = drvdata; @@ -194,7 +206,11 @@ isoApplet_init(sc_card_t * card) ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; ext_flags |= SC_ALGORITHM_EXT_EC_F_P; _sc_card_add_ec_alg(card, 192, flags, ext_flags); + _sc_card_add_ec_alg(card, 224, flags, ext_flags); _sc_card_add_ec_alg(card, 256, flags, ext_flags); + _sc_card_add_ec_alg(card, 320, flags, ext_flags); + _sc_card_add_ec_alg(card, 384, flags, ext_flags); + _sc_card_add_ec_alg(card, 512, flags, ext_flags); /* RSA */ flags = 0; @@ -231,7 +247,7 @@ isoApplet_init(sc_card_t * card) * if unknown operation. */ static u8 -acl_to_security_condition_byte(const sc_acl_entry_t *entry) +isoApplet_acl_to_security_condition_byte(const sc_acl_entry_t *entry) { if(!entry) return 0x00; @@ -320,7 +336,7 @@ isoApplet_create_file(sc_card_t *card, sc_file_t *file) { const sc_acl_entry_t *entry; entry = sc_file_get_acl_entry(file, idx[i]); - access_buf[i] = acl_to_security_condition_byte(entry); + access_buf[i] = isoApplet_acl_to_security_condition_byte(entry); } r = sc_file_set_sec_attr(file, access_buf, 8); @@ -332,18 +348,19 @@ isoApplet_create_file(sc_card_t *card, sc_file_t *file) } /* - * Adds an ACL entry to the OpenSC file struct, according to the operation + * Add an ACL entry to the OpenSC file struct, according to the operation * and the saByte (Encoded according to IsoApplet FCI proprietary security * information, see also ISO 7816-4 table 20). * * @param[in,out] file * @param[in] operation The OpenSC operation. - * @param[in] saByte The security condition byte return by the applet. + * @param[in] saByte The security condition byte returned by the applet. */ static int -sa_to_acl(sc_file_t *file, unsigned int operation, u8 saByte) +isoApplet_add_sa_to_acl(sc_file_t *file, unsigned int operation, u8 saByte) { int r; + switch(saByte) { case 0x90: @@ -397,37 +414,37 @@ isoApplet_process_fci(sc_card_t *card, sc_file_t *file, } if(file->type == SC_FILE_TYPE_DF) { - r = sa_to_acl(file, SC_AC_OP_DELETE_SELF, sa[1]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DELETE_SELF, sa[1]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_LOCK, sa[2]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_LOCK, sa[2]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_ACTIVATE, sa[3]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_ACTIVATE, sa[3]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_DEACTIVATE, sa[4]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DEACTIVATE, sa[4]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_CREATE_DF, sa[5]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_CREATE_DF, sa[5]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_CREATE_EF, sa[6]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_CREATE_EF, sa[6]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_DELETE, sa[7]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DELETE, sa[7]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); } else if(file->type == SC_FILE_TYPE_INTERNAL_EF || file->type == SC_FILE_TYPE_WORKING_EF) { - r = sa_to_acl(file, SC_AC_OP_DELETE_SELF, sa[1]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DELETE_SELF, sa[1]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_LOCK, sa[2]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_LOCK, sa[2]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_ACTIVATE, sa[3]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_ACTIVATE, sa[3]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_DEACTIVATE, sa[4]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DEACTIVATE, sa[4]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_WRITE, sa[5]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_WRITE, sa[5]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_UPDATE, sa[6]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_UPDATE, sa[6]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); - r = sa_to_acl(file, SC_AC_OP_READ, sa[7]); + r = isoApplet_add_sa_to_acl(file, SC_AC_OP_READ, sa[7]); LOG_TEST_RET(card->ctx, r, "Error adding ACL entry."); } @@ -436,16 +453,78 @@ isoApplet_process_fci(sc_card_t *card, sc_file_t *file, LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } +/* + * @brief Encode the EC parameters as a concatenation of TLV enrties. + * + * The format is: + * 81 - prime + * 82 - coefficient A + * 83 - coefficient B + * 84 - base point G + * 85 - order + * 87 - cofactor + * + * @param[in] card + * @param[in] params The ECparameters containing the information of the curve. + * @param[out] out The array the encoded parameters are written to. + * @param[in] out_len The size of out + * @param[out] ptr A pointer pointing to the end of the parameters in out + * (the first untouched byte behind the parameters). + */ static int -isoApplet_ctl_generate_key(sc_card_t *card, struct sc_cardctl_isoApplet_genkey *args) +isoApplet_put_ec_params(sc_card_t *card, sc_cardctl_isoApplet_ec_parameters_t *params, u8 *out, size_t out_len, u8 **ptr) { - int r, len; - size_t tag_len; + u8 *p = out; + int r; + + LOG_FUNC_CALLED(card->ctx); + + if(!params + || !params->prime.value + || !params->coefficientA.value + || !params->coefficientB.value + || !params->basePointG.value + || !params->order.value + || !params->coFactor.value) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Error: EC params not present."); + } + + r = sc_asn1_put_tag(0x81, params->prime.value, params->prime.len, p, out_len - (p - out), &p); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + r = sc_asn1_put_tag(0x82, params->coefficientA.value, params->coefficientA.len, p, out_len - (p - out), &p); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + r = sc_asn1_put_tag(0x83, params->coefficientB.value, params->coefficientB.len, p, out_len - (p - out), &p); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + r = sc_asn1_put_tag(0x84, params->basePointG.value, params->basePointG.len, p, out_len - (p - out), &p); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + r = sc_asn1_put_tag(0x85, params->order.value, params->order.len, p, out_len - (p - out), &p); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + r = sc_asn1_put_tag(0x87, params->coFactor.value, params->coFactor.len, p, out_len - (p - out), &p); + LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + + if (ptr != NULL) + *ptr = p; + LOG_FUNC_RETURN(card->ctx, r); +} + +/* + * @brief Generate a private key on the card. + */ +static int +isoApplet_ctl_generate_key(sc_card_t *card, sc_cardctl_isoApplet_genkey_t *args) +{ + int r; sc_apdu_t apdu; u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 *p; - const u8 *curr_pos; + const u8 *inner_tag_value; + const u8 *outer_tag_value; + unsigned int tag; + size_t outer_tag_len; + size_t inner_tag_len; + unsigned int cla; LOG_FUNC_CALLED(card->ctx); @@ -490,12 +569,30 @@ isoApplet_ctl_generate_key(sc_card_t *card, struct sc_cardctl_isoApplet_genkey * * card will send SW_BYTES_REMAINING, OpenSC will automaticall do a * GET RESPONSE to get the remaining data, and will append it to the data * buffer. */ - sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x46, 0x42, 0x00); + if(args->algorithm_ref == SC_ISOAPPLET_ALG_REF_EC_GEN) + { + sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x46, 0x00, 0x00); + apdu.data = sbuf; + p = sbuf; + r = isoApplet_put_ec_params(card, &args->pubkey.ec.params, p, sizeof(sbuf), &p); + LOG_TEST_RET(card->ctx, r, "Error composing EC params."); + apdu.datalen = p - sbuf; + apdu.lc = p - sbuf; + /* Use APDU chaining if the card does not support extended apdus + * and the data does not fit in one short apdu. */ + if ((apdu.datalen > 255) && !(card->caps & SC_CARD_CAP_APDU_EXT)) + { + apdu.flags |= SC_APDU_FLAGS_CHAINING; + } + } + else + { + sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x46, 0x42, 0x00); + } apdu.resp = rbuf; - apdu.resplen = SC_MAX_EXT_APDU_BUFFER_SIZE; + apdu.resplen = sizeof(rbuf); apdu.le = 256; - r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); @@ -503,190 +600,99 @@ isoApplet_ctl_generate_key(sc_card_t *card, struct sc_cardctl_isoApplet_genkey * LOG_TEST_RET(card->ctx, r, "Card returned error"); /* Parse the public key / response. */ + outer_tag_value = apdu.resp; + r = sc_asn1_read_tag(&outer_tag_value, apdu.resplen, &cla, &tag, &outer_tag_len); + LOG_TEST_RET(card->ctx, r, "Error in ASN1 handling."); + /* Interindustry template for nesting one set of public key data objects */ + if((tag != 0x1F49) || (cla != 0x60)) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, + "The data returned by the card is unexpected."); + } + switch(args->algorithm_ref) { case SC_ISOAPPLET_ALG_REF_RSA_GEN_2048: - /* We expect: - * - Tag: 7F 49 - * - Length: 82 01 09 (265 Bytes) */ - p = rbuf; - if(memcmp(p, "\x7F\x49\x82\x01\x09", 5) != 0) - { - LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, - "The data returned by the card is unexpected."); - } - else - { - len = 265; - } - p += 5; /* p points to the value field of the outer (7F 49) tag. - * This value field is a TLV-structure again. */ - /* Search for the modulus tag (81). */ - curr_pos = sc_asn1_find_tag(card->ctx, p, len, (unsigned int) 0x81, &tag_len); - if(curr_pos == NULL || tag_len != 256) + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x81, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != 256) { LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid modulus."); } - if(args->pubkey_len < 256) + if(inner_tag_len > args->pubkey.rsa.modulus.len) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); } - args->pubkey_len = tag_len; - memcpy(args->pubkey, curr_pos, args->pubkey_len); + memcpy(args->pubkey.rsa.modulus.value, inner_tag_value, inner_tag_len); + args->pubkey.rsa.modulus.len = inner_tag_len; /* Exponent tag (82) */ - curr_pos = sc_asn1_find_tag(card->ctx, p, len, (unsigned int) 0x82, &tag_len); - if(curr_pos == NULL || tag_len != 3) - { - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); - } - if(args->exponent_len < 3) + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x82, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != 3) { LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid exponent."); } - if(memcmp(curr_pos, "\x01\x00\x01", 3) != 0) + if(inner_tag_len > args->pubkey.rsa.exponent.len) + { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); + } + if(memcmp(inner_tag_value, "\x01\x00\x01", 3) != 0) { LOG_TEST_RET(card->ctx, SC_ERROR_INCOMPATIBLE_KEY, "Key generation error: Unexpected public key exponent."); } - args->exponent_len = 3; - memcpy(args->exponent, curr_pos, args->exponent_len); + memcpy(args->pubkey.rsa.exponent.value, inner_tag_value, inner_tag_len); + args->pubkey.rsa.exponent.len = inner_tag_len; p = NULL; break; - case SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1: - p = rbuf; - if(args->pubkey_len >= apdu.resplen) - { - memcpy(args->pubkey, p, apdu.resplen); - } - else - { - LOG_TEST_RET(card->ctx, SC_ERROR_BUFFER_TOO_SMALL, - "Key generation error: Public key buffer too small."); - } - break; + case SC_ISOAPPLET_ALG_REF_EC_GEN: + /* Compare the parameters received from the card to the ones sent to the card. */ + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x81, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.prime.len + || memcmp(inner_tag_value, args->pubkey.ec.params.prime.value, inner_tag_len) != 0) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid prime."); - case SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1: - p = rbuf; - if(args->pubkey_len >= apdu.resplen) - { - memcpy(args->pubkey, p, apdu.resplen); - } - else - { - LOG_TEST_RET(card->ctx, SC_ERROR_BUFFER_TOO_SMALL, - "Key generation error: Public key buffer too small."); - } - break; + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x82, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.coefficientA.len + || memcmp(inner_tag_value, args->pubkey.ec.params.coefficientA.value, inner_tag_len) != 0) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid coefficient A."); + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x83, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.coefficientB.len + || memcmp(inner_tag_value, args->pubkey.ec.params.coefficientB.value, inner_tag_len) != 0) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid coefficient B."); + + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x84, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.basePointG.len + || memcmp(inner_tag_value, args->pubkey.ec.params.basePointG.value, inner_tag_len) != 0) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid base point G."); + + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x85, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.order.len + || memcmp(inner_tag_value, args->pubkey.ec.params.order.value, inner_tag_len) != 0) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid order."); + + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x87, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.coFactor.len + || memcmp(inner_tag_value, args->pubkey.ec.params.coFactor.value, inner_tag_len) != 0) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid cofactor."); + + /* Extract public key */ + inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x86, &inner_tag_len); + if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.ecPointQ.len) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid EC point Q."); + memcpy(args->pubkey.ec.ecPointQ.value, inner_tag_value, inner_tag_len); + + break; default: LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unable to parse public key: Unsupported algorithm."); - }// switch + }/* switch */ LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } -/* - * @brief Insert the length field of a TLV entry. - * - * The format is: - * 0..127: 1 byte, 00-7F - * 128..255: 2 bytes, 81; 00-FF - * 256..65535: 3 bytes, 82; 0000-FFFF - * - * @param[out] p The buffer where the length tag should be placed. - * @param[in] p_len The length of p. - * @param[in] len The length to be inserted. - * - * @return positive values: The length of the length field inserted. - * SC_ERROR_INVALID_ARGUMENTS: Incorrect length value or p == null. - * SC_ERROR_BUFFER_TOO_SMALL: The buffer p can not hold the length field. - */ -static int -tlv_insert_len(u8 *p, size_t p_len, size_t len) -{ - if(p == NULL) - return SC_ERROR_INVALID_ARGUMENTS; - - /* Note: len < 0 can not happen as it is size_t */ - if(len <= 127) - { - if(p_len < 1) - return SC_ERROR_BUFFER_TOO_SMALL; - *p++ = len & 0x7F; - return 1; - } - else if(len <= 255) - { - if(p_len < 2) - return SC_ERROR_BUFFER_TOO_SMALL; - *p++ = 0x81; - *p++ = len & 0xFF; - return 2; - } - else if(len <= 65535) - { - if(p_len < 3) - return SC_ERROR_BUFFER_TOO_SMALL; - *p++ = 0x82; - *p++ = (len >> 8) & 0xFF; /* MSB */ - *p++ = len & 0xFF; /* LSB */ - return 3; - } - else - { - return SC_ERROR_INVALID_ARGUMENTS; - } -} - -/* - * @brief Add a TLV-entry to a buffer. - * - * @param[out] buf The buffer at where the TLV entry should be placed. - * @param[in] buf_len The length of buf. - * @param[in] tag The one byte tag of the TLV entry. - * @param[in] tag_data The value field of the TLV entry. - * @param[in] tag_data_len The length of the tag_data. - * - */ -static int -tlv_add_tlv(u8 *buf, const size_t buf_len, const u8 tag, - const u8 *tag_data, const size_t tag_data_len) -{ - size_t l_len; /* Length of the length field itself. */ - int r; - - if(buf == NULL || tag_data == NULL) - return SC_ERROR_INVALID_ARGUMENTS; - - if(tag_data_len <= 127) - l_len = 1; - else if(tag_data_len <= 255) - l_len = 2; - else if(tag_data_len <= 65535) - l_len = 3; - else - return SC_ERROR_INVALID_ARGUMENTS; - - if(1 + l_len + tag_data_len > buf_len) - return SC_ERROR_BUFFER_TOO_SMALL; - - *buf++ = tag; - r = tlv_insert_len(buf, buf_len-1, tag_data_len); - if(r < 0) - return r; - else if((unsigned int)r != l_len) - return SC_ERROR_UNKNOWN; - - buf += l_len; - - memcpy(buf, tag_data, tag_data_len); - return 1 + l_len + tag_data_len; -} - /* * @brief Use PUT DATA to import a private RSA key. * @@ -700,10 +706,9 @@ tlv_add_tlv(u8 *buf, const size_t buf_len, const u8 tag, * other errors: Transmit errors / errors returned by card. */ static int -isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) +isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args) { sc_apdu_t apdu; - const size_t sbuf_len = SC_MAX_APDU_BUFFER_SIZE; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 *p = NULL; int r; @@ -712,17 +717,15 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) LOG_FUNC_CALLED(card->ctx); - if(!rsa - || !rsa->p.data - || !rsa->q.data - || !rsa->iqmp.data - || !rsa->dmp1.data - || !rsa->dmq1.data) + if(!args->privkey.rsa.p.value + || !args->privkey.rsa.q.value + || !args->privkey.rsa.iqmp.value + || !args->privkey.rsa.dmp1.value + || !args->privkey.rsa.dmq1.value) { - LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Only CRT RSA keys may be imported."); + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "RSA key is missing information."); } - p = sbuf; /* Note: The format is according to ISO 2-byte tag 7F48 */ *p++ = 0x7F; /* T-L pair to indicate a private key data object */ @@ -730,31 +733,34 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) /* Calculate the length of all inner tag-length-value entries. * One entry consists of: tag (1 byte) + length (1 byte if < 128, 2 if >= 128) + value (len) * It may actually happen that a parameter is 127 byte (leading zero) */ - tags_len = 1 + (rsa->p.len < 128 ? 1 : 2) + rsa->p.len + - 1 + (rsa->q.len < 128 ? 1 : 2) + rsa->q.len + - 1 + (rsa->iqmp.len < 128 ? 1 : 2) + rsa->iqmp.len + - 1 + (rsa->dmp1.len < 128 ? 1 : 2) + rsa->dmp1.len + - 1 + (rsa->dmq1.len < 128 ? 1 : 2) + rsa->dmq1.len; - r = tlv_insert_len(p, sbuf_len - (p - sbuf), tags_len); /* Private key data object length */ - LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); - p += r; + tags_len = 1 + (args->privkey.rsa.p.len < 128 ? 1 : 2) + args->privkey.rsa.p.len + + 1 + (args->privkey.rsa.q.len < 128 ? 1 : 2) + args->privkey.rsa.q.len + + 1 + (args->privkey.rsa.iqmp.len < 128 ? 1 : 2) + args->privkey.rsa.iqmp.len + + 1 + (args->privkey.rsa.dmp1.len < 128 ? 1 : 2) + args->privkey.rsa.dmp1.len + + 1 + (args->privkey.rsa.dmq1.len < 128 ? 1 : 2) + args->privkey.rsa.dmq1.len; + *p++ = 0x82; + *p++ = (tags_len >> 8) & 0xFF; /* MSB */ + *p++ = tags_len & 0xFF; /* LSB */ /* p */ - r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x92, rsa->p.data, rsa->p.len); - LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); - p += r; - - r = sc_lock(card); /* We will use several apdus */ - LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); - locked = 1; - + r = sc_asn1_put_tag(0x92, args->privkey.rsa.p.value, args->privkey.rsa.p.len, p, sizeof(sbuf) - (p - sbuf), &p); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDB, 0x3F, 0xFF); apdu.cla |= 0x10; /* Chaining */ apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; + + r = sc_lock(card); /* We will use several apdus */ + LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); + locked = 1; + r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + if(r < 0) + { + sc_log(card->ctx, "%s: APDU transmit failed", strerror(r)); + goto out; + } r = sc_check_sw(card, apdu.sw1, apdu.sw2); if(apdu.sw1 == 0x6D && apdu.sw2 == 0x00) { @@ -763,24 +769,21 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) } if(r < 0) { - sc_log(card->ctx, "Card returned error"); + sc_log(card->ctx, "%s: Card returned error", strerror(r)); goto out; } /* q */ p = sbuf; - r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x93, rsa->q.data, rsa->q.len); + r = sc_asn1_put_tag(0x93, args->privkey.rsa.q.value, args->privkey.rsa.q.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) { sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); goto out; } - p += r; - apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; - r = sc_check_apdu(card, &apdu); r = sc_transmit_apdu(card, &apdu); if(r < 0) { @@ -796,14 +799,12 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) /* 1/q mod p */ p = sbuf; - r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x94, rsa->iqmp.data, rsa->iqmp.len); + r = sc_asn1_put_tag(0x94, args->privkey.rsa.iqmp.value, args->privkey.rsa.iqmp.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) { sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); goto out; } - p += r; - apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; @@ -822,14 +823,12 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) /* d mod (p-1) */ p = sbuf; - r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x95, rsa->dmp1.data, rsa->dmp1.len); + r = sc_asn1_put_tag(0x95, args->privkey.rsa.dmp1.value, args->privkey.rsa.dmp1.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) { sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); goto out; } - p += r; - apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; @@ -848,14 +847,12 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, struct sc_pkcs15_prkey_rsa *rsa) /* d mod (q-1) */ p = sbuf; - r = tlv_add_tlv(p, sbuf_len - (p - sbuf), 0x96, rsa->dmq1.data, rsa->dmq1.len); + r = sc_asn1_put_tag(0x96, args->privkey.rsa.dmq1.value, args->privkey.rsa.dmq1.len, p, sizeof(sbuf) - (p - sbuf), &p); if(r < 0) { sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); goto out; } - p += r; - apdu.cla = 0x00; /* Last part of the chain. */ apdu.data = sbuf; apdu.datalen = p - sbuf; @@ -882,39 +879,77 @@ out: /* * @brief Use PUT DATA to import a private EC key. * - * I use a simpler format for EC keys (compared to RSA) - * because the card has all the necessary information except the ecPointQ. - * Only the ecPointQ is sent to the card. It is BER-TLV-encoded. The tag is: - * 0xC1 - Private class, primitive encoding, number one. + * Format of transmitted data: + * 0xE0 - Private class, constructed encoding, number one. + * 0x81 - prime + * 0x82 - coefficient A + * 0x83 - coefficient B + * 0x84 - base point G + * 0x85 - order + * 0x87 - cofactor + * 0x88 - private D (private key) * * @param card * @param ec The EC private key to import. * - * @return SC_ERROR_INVALID_ARGUMENTS: The RSA key does not contain CRT fields. + * @return SC_ERROR_INVALID_ARGUMENTS: Curve parameters or private component is missing. * other errors: Transmit errors / errors returned by card. + * ASN1 errors. */ static int -isoApplet_put_data_prkey_ec(sc_card_t *card, struct sc_pkcs15_prkey_ec *ec) +isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args) { sc_apdu_t apdu; - size_t sbuf_len = SC_MAX_EXT_APDU_BUFFER_SIZE; u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; int r; + u8 *p; + size_t tags_len; LOG_FUNC_CALLED(card->ctx); - if(!ec) + if(!args->privkey.ec.privateD.value + || !args->privkey.ec.params.prime.value + || !args->privkey.ec.params.coefficientA.value + || !args->privkey.ec.params.coefficientB.value + || !args->privkey.ec.params.basePointG.value + || !args->privkey.ec.params.order.value + || !args->privkey.ec.params.coFactor.value + ) { - LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "No EC private key."); + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Missing information about EC private key."); } - r = tlv_add_tlv(sbuf, sbuf_len, 0xC1, ec->privateD.data, ec->privateD.len); + p = sbuf; + *p++ = 0xE0; + tags_len = 1 + (args->privkey.ec.params.prime.len < 128 ? 1 : 2) + args->privkey.ec.params.prime.len + + 1 + (args->privkey.ec.params.coefficientA.len < 128 ? 1 : 2) + args->privkey.ec.params.coefficientA.len + + 1 + (args->privkey.ec.params.coefficientB.len < 128 ? 1 : 2) + args->privkey.ec.params.coefficientB.len + + 1 + (args->privkey.ec.params.basePointG.len < 128 ? 1 : 2) + args->privkey.ec.params.basePointG.len + + 1 + (args->privkey.ec.params.order.len < 128 ? 1 : 2) + args->privkey.ec.params.order.len + + 1 + (args->privkey.ec.params.coFactor.len < 128 ? 1 : 2) + args->privkey.ec.params.coFactor.len + + 1 + (args->privkey.ec.privateD.len < 128 ? 1 : 2) + args->privkey.ec.privateD.len; + if(tags_len < 127) + *p++ = (tags_len & 0xFF); + else if (tags_len < 255) + { + *p++ = 0x81; + *p++ = (tags_len & 0xFF); + } + else + { + *p++ = 0x82; + *p++ = (tags_len >> 8) & 0xFF; /* MSB */ + *p++ = tags_len & 0xFF; /* LSB */ + } + r = isoApplet_put_ec_params(card, &args->privkey.ec.params, p, sizeof(sbuf) - (p - sbuf), &p); + LOG_TEST_RET(card->ctx, r, "Error composing EC params."); + r = sc_asn1_put_tag(0x88, args->privkey.ec.privateD.value, args->privkey.ec.privateD.len, p, sizeof(sbuf) - (p - sbuf), &p); LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); /* Send to card. */ - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDB, 0x3F, 0xFF); - apdu.lc = r; - apdu.datalen = r; + sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDB, 0x3F, 0xFF); + apdu.lc = p - sbuf; + apdu.datalen = p - sbuf; apdu.data = sbuf; r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); @@ -1000,13 +1035,12 @@ isoApplet_ctl_import_key(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *arg { case SC_ISOAPPLET_ALG_REF_RSA_GEN_2048: - r = isoApplet_put_data_prkey_rsa(card, &args->prkey->u.rsa); + r = isoApplet_put_data_prkey_rsa(card, args); LOG_TEST_RET(card->ctx, r, "Error in PUT DATA."); break; - case SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1: - case SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1: - r = isoApplet_put_data_prkey_ec(card, &args->prkey->u.ec); + case SC_ISOAPPLET_ALG_REF_EC_GEN: + r = isoApplet_put_data_prkey_ec(card, args); LOG_TEST_RET(card->ctx, r, "Error in PUT DATA."); break; @@ -1173,13 +1207,15 @@ err: static int isoApplet_compute_signature(struct sc_card *card, - const u8 * data, size_t datalen, - u8 * out, size_t outlen) + const u8 *data, size_t datalen, + u8 *out, size_t outlen) { struct isoApplet_drv_data *drvdata = DRVDATA(card); + const u8 * p; int r; - size_t xlen, ylen; - size_t i, offset; + size_t len; + size_t xlen; + size_t ylen; LOG_FUNC_CALLED(card->ctx); @@ -1190,55 +1226,52 @@ isoApplet_compute_signature(struct sc_card *card, } /* If we used ECDSA for the signature op, OpenSC thinks it has to - * convert it to {sequence, sequence} which is already done by the + * convert it to {sequence{integer,integer}} which is already done by the * card actually. - * To fix this, I strip the {sequence, sequence} structual information - * so that pkcs11-tool.c can add it again... */ + * To fix this, I strip the {sequence, sequence} structual information, + * which will be added again later.*/ if(drvdata->sec_env_alg_ref == ISOAPPLET_ALG_REF_ECDSA) { - /* Outer SEQUENCE tag and first INTEGER tag. */ - offset=0; - if(r < 2 - || out[offset++] != 0x30 - || out[offset++] != r-2 - || out[offset++] != 0x02) + len = r; + p = out; + if(*p++ != (SC_ASN1_TAG_SEQUENCE|SC_ASN1_TAG_CONSTRUCTED)) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); } + len = *p++; + if(len > outlen - (p - out)) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); /* X */ - xlen = out[offset++]; - assert(xlen+4 < outlen); - /* Remove the leading 0 of the coordinate, if present. */ - if(out[offset] == 0x00) + if(*p++ != SC_ASN1_TAG_INTEGER) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + xlen = *p++; + if(xlen > outlen - (p - out)) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); + /* Java Cards might return a leading zero, which needs to be stripped. */ + if(*p == 0x00) { - offset++; + p++; xlen--; } - for(i=0; i < xlen; i++) - { - out[i] = out[i+offset]; - } + memmove(out, p, xlen); + p += xlen; /* Y */ - assert(i+offset+3 < outlen); - if(out[i+offset++] != 0x02) - { + if(*p++ != SC_ASN1_TAG_INTEGER) LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); - } - ylen = out[i+offset++]; - /* Remove the leading 0 of the coordinate, if present. */ - if(out[i+offset] == 0x00) + ylen = *p++; + if(ylen > outlen - (p - out)) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); + /* Java Cards might return a leading zero, which needs to be stripped. */ + if(*p == 0x00) { - offset++; + p++; ylen--; } - assert(offset+xlen+ylen <= outlen); - for(; i < xlen+ylen; i++) - { - out[i] = out[i+offset]; - } - r = xlen+ylen; + memmove(out+xlen, p, ylen); + + r = xlen + ylen; } LOG_FUNC_RETURN(card->ctx, r); } diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index 98a34f0f..edfac57d 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -969,25 +969,54 @@ typedef struct sc_cardctl_sc_hsm_wrapped_key { */ #define SC_ISOAPPLET_ALG_REF_RSA_GEN_2048 0xF3 -#define SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1 0xE0 -#define SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1 0xE1 +#define SC_ISOAPPLET_ALG_REF_EC_GEN 0xEC + +typedef struct sc_cardctl_isoApplet_ec_parameters { + struct sc_lv_data prime; + struct sc_lv_data coefficientA; + struct sc_lv_data coefficientB; + struct sc_lv_data basePointG; + struct sc_lv_data order; + struct sc_lv_data coFactor; +} sc_cardctl_isoApplet_ec_parameters_t; typedef struct sc_cardctl_isoApplet_genkey { u8 algorithm_ref; /* Algorithm reference sent to card */ - unsigned char *exponent; /* RSA public key exponent */ - unsigned int exponent_len; unsigned int priv_key_ref; /* Private key refernce sent to card */ - unsigned char *pubkey; /* RSA public key modulus (or EC tlv-encoded public key) */ - unsigned int pubkey_len; + union { + struct + { + struct sc_lv_data modulus; + struct sc_lv_data exponent; + } rsa; + struct + { + sc_cardctl_isoApplet_ec_parameters_t params; + struct sc_lv_data ecPointQ; + } ec; + } pubkey; } sc_cardctl_isoApplet_genkey_t; typedef struct sc_cardctl_isoApplet_import_key { - u8 algorithm_ref; /*Algorithm reference sent to card */ + u8 algorithm_ref; /* Algorithm reference sent to card */ unsigned int priv_key_ref; /* Private key refernce sent to card */ - struct sc_pkcs15_prkey *prkey; + union { + struct + { + struct sc_lv_data p; + struct sc_lv_data q; + struct sc_lv_data iqmp; + struct sc_lv_data dmp1; + struct sc_lv_data dmq1; + } rsa; + struct + { + sc_cardctl_isoApplet_ec_parameters_t params; + struct sc_lv_data privateD; + } ec; + } privkey; } sc_cardctl_isoApplet_import_key_t; - #ifdef __cplusplus } #endif diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index 41410c50..971f9847 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -37,10 +37,10 @@ #define ISOAPPLET_KEY_ID_MIN 0 #define ISOAPPLET_KEY_ID_MAX 15 - +/* Curve parameters of a curve specified by the OID. */ struct ec_curve { - const struct sc_lv_data oid; + const struct sc_lv_data oid; /* Object ID in hex, including structural information */ const struct sc_lv_data prime; const struct sc_lv_data coefficientA; const struct sc_lv_data coefficientB; @@ -49,29 +49,87 @@ struct ec_curve const struct sc_lv_data coFactor; }; -static struct ec_curve curves[] = +/* OpenSC only works with named curves, but we need the + * explicit parameters for ECC key generation or import. */ +static const struct ec_curve curves[] = { - { - { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x03", 9}, /* brainpoolP192r1 */ + /* brainpoolP192r1 */ + { (unsigned char *) "\x06\x09\x2B\x24\x03\x03\x02\x08\x01\x01\x03", 11}, { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x30\x93\xD1\x8D\xB7\x8F\xCE\x47\x6D\xE1\xA8\x62\x97", 24}, { (unsigned char *) "\x6A\x91\x17\x40\x76\xB1\xE0\xE1\x9C\x39\xC0\x31\xFE\x86\x85\xC1\xCA\xE0\x40\xE5\xC6\x9A\x28\xEF", 24}, { (unsigned char *) "\x46\x9A\x28\xEF\x7C\x28\xCC\xA3\xDC\x72\x1D\x04\x4F\x44\x96\xBC\xCA\x7E\xF4\x14\x6F\xBF\x25\xC9", 24}, - { (unsigned char *) "\xC0\xA0\x64\x7E\xAA\xB6\xA4\x87\x53\xB0\x33\xC5\x6C\xB0\xF0\x90\x0A\x2F\x5C\x48\x53\x37\x5F\xD6\x14\xB6\x90\x86\x6A\xBD\x5B\xB8\x8B\x5F\x48\x28\xC1\x49\x00\x02\xE6\x77\x3F\xA2\xFA\x29\x9B\x8F", 48}, + { (unsigned char *) "\x04\xC0\xA0\x64\x7E\xAA\xB6\xA4\x87\x53\xB0\x33\xC5\x6C\xB0\xF0\x90\x0A\x2F\x5C\x48\x53\x37\x5F\xD6\x14\xB6\x90\x86\x6A\xBD\x5B\xB8\x8B\x5F\x48\x28\xC1\x49\x00\x02\xE6\x77\x3F\xA2\xFA\x29\x9B\x8F", 49}, { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x2F\x9E\x9E\x91\x6B\x5B\xE8\xF1\x02\x9A\xC4\xAC\xC1", 24}, { (unsigned char *) "\x00\x01", 2} }, { - { (unsigned char *) "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8}, /* secp256r1 aka prime256v1 */ + /* brainpoolP224r1 */ + { (unsigned char *) "\x06\x09\x2B\x24\x03\x03\x02\x08\x01\x01\x05", 11}, + { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD1\xD7\x87\xB0\x9F\x07\x57\x97\xDA\x89\xF5\x7E\xC8\xC0\xFF", 28}, + { (unsigned char *) "\x68\xA5\xE6\x2C\xA9\xCE\x6C\x1C\x29\x98\x03\xA6\xC1\x53\x0B\x51\x4E\x18\x2A\xD8\xB0\x04\x2A\x59\xCA\xD2\x9F\x43", 28}, + { (unsigned char *) "\x25\x80\xF6\x3C\xCF\xE4\x41\x38\x87\x07\x13\xB1\xA9\x23\x69\xE3\x3E\x21\x35\xD2\x66\xDB\xB3\x72\x38\x6C\x40\x0B", 28}, + { (unsigned char *) "\x04\x0D\x90\x29\xAD\x2C\x7E\x5C\xF4\x34\x08\x23\xB2\xA8\x7D\xC6\x8C\x9E\x4C\xE3\x17\x4C\x1E\x6E\xFD\xEE\x12\xC0\x7D\x58\xAA\x56\xF7\x72\xC0\x72\x6F\x24\xC6\xB8\x9E\x4E\xCD\xAC\x24\x35\x4B\x9E\x99\xCA\xA3\xF6\xD3\x76\x14\x02\xCD", 57}, + { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD0\xFB\x98\xD1\x16\xBC\x4B\x6D\xDE\xBC\xA3\xA5\xA7\x93\x9F", 28}, + { (unsigned char *) "\x00\x01", 2} + }, + + { + /* brainpoolP256r1 */ + { (unsigned char *) "\x06\x09\x2B\x24\x03\x03\x02\x08\x01\x01\x07", 11}, + { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, + { (unsigned char *) "\x7D\x5A\x09\x75\xFC\x2C\x30\x57\xEE\xF6\x75\x30\x41\x7A\xFF\xE7\xFB\x80\x55\xC1\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9", 32}, + { (unsigned char *) "\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9\xBB\xD7\x7C\xBF\x95\x84\x16\x29\x5C\xF7\xE1\xCE\x6B\xCC\xDC\x18\xFF\x8C\x07\xB6", 32}, + { (unsigned char *) "\x04\x8B\xD2\xAE\xB9\xCB\x7E\x57\xCB\x2C\x4B\x48\x2F\xFC\x81\xB7\xAF\xB9\xDE\x27\xE1\xE3\xBD\x23\xC2\x3A\x44\x53\xBD\x9A\xCE\x32\x62\x54\x7E\xF8\x35\xC3\xDA\xC4\xFD\x97\xF8\x46\x1A\x14\x61\x1D\xC9\xC2\x77\x45\x13\x2D\xED\x8E\x54\x5C\x1D\x54\xC7\x2F\x04\x69\x97", 65}, + { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x71\x8C\x39\x7A\xA3\xB5\x61\xA6\xF7\x90\x1E\x0E\x82\x97\x48\x56\xA7", 32}, + { (unsigned char *) "\x00\x01", 2} + }, + + { + /* brainpoolP320r1 */ + { (unsigned char *) "\x06\x09\x2B\x24\x03\x03\x02\x08\x01\x01\x09", 11}, + { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA6\xF6\xF4\x0D\xEF\x4F\x92\xB9\xEC\x78\x93\xEC\x28\xFC\xD4\x12\xB1\xF1\xB3\x2E\x27", 40}, + { (unsigned char *) "\x3E\xE3\x0B\x56\x8F\xBA\xB0\xF8\x83\xCC\xEB\xD4\x6D\x3F\x3B\xB8\xA2\xA7\x35\x13\xF5\xEB\x79\xDA\x66\x19\x0E\xB0\x85\xFF\xA9\xF4\x92\xF3\x75\xA9\x7D\x86\x0E\xB4", 40}, + { (unsigned char *) "\x52\x08\x83\x94\x9D\xFD\xBC\x42\xD3\xAD\x19\x86\x40\x68\x8A\x6F\xE1\x3F\x41\x34\x95\x54\xB4\x9A\xCC\x31\xDC\xCD\x88\x45\x39\x81\x6F\x5E\xB4\xAC\x8F\xB1\xF1\xA6", 40}, + { (unsigned char *) "\x04\x43\xBD\x7E\x9A\xFB\x53\xD8\xB8\x52\x89\xBC\xC4\x8E\xE5\xBF\xE6\xF2\x01\x37\xD1\x0A\x08\x7E\xB6\xE7\x87\x1E\x2A\x10\xA5\x99\xC7\x10\xAF\x8D\x0D\x39\xE2\x06\x11\x14\xFD\xD0\x55\x45\xEC\x1C\xC8\xAB\x40\x93\x24\x7F\x77\x27\x5E\x07\x43\xFF\xED\x11\x71\x82\xEA\xA9\xC7\x78\x77\xAA\xAC\x6A\xC7\xD3\x52\x45\xD1\x69\x2E\x8E\xE1", 81}, + { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA5\xB6\x8F\x12\xA3\x2D\x48\x2E\xC7\xEE\x86\x58\xE9\x86\x91\x55\x5B\x44\xC5\x93\x11", 40}, + { (unsigned char *) "\x00\x01", 2} + }, + + { + /* prime192r1, secp192r1, ansiX9p192r1 */ + { (unsigned char *) "\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x01", 10}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 24}, + { (unsigned char *) "\x64\x21\x05\x19\xE5\x9C\x80\xE7\x0F\xA7\xE9\xAB\x72\x24\x30\x49\xFE\xB8\xDE\xEC\xC1\x46\xB9\xB1", 24}, + { (unsigned char *) "\x04\x18\x8D\xA8\x0E\xB0\x30\x90\xF6\x7C\xBF\x20\xEB\x43\xA1\x88\x00\xF4\xFF\x0A\xFD\x82\xFF\x10\x12\x07\x19\x2B\x95\xFF\xC8\xDA\x78\x63\x10\x11\xED\x6B\x24\xCD\xD5\x73\xF9\x77\xA1\x1E\x79\x48\x11", 49}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x99\xDE\xF8\x36\x14\x6B\xC9\xB1\xB4\xD2\x28\x31", 24}, + { (unsigned char *) "\x00\x01", 1} + }, + + { + /* prime256v1, secp256r1, ansiX9p256r1 */ + { (unsigned char *) "\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x07", 10}, { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 32}, { (unsigned char *) "\x5A\xC6\x35\xD8\xAA\x3A\x93\xE7\xB3\xEB\xBD\x55\x76\x98\x86\xBC\x65\x1D\x06\xB0\xCC\x53\xB0\xF6\x3B\xCE\x3C\x3E\x27\xD2\x60\x4B", 32}, - { (unsigned char *) "\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5", 64}, + { (unsigned char *) "\x04\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5", 65}, { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", 32}, { (unsigned char *) "\x00\x01", 2} }, + { + /* prime384v1, secp384r1, ansiX9p384r1 */ + { (unsigned char *) "\x06\x05\x2B\x81\x04\x00\x22", 7}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 48}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFC", 48}, + { (unsigned char *) "\xB3\x31\x2F\xA7\xE2\x3E\xE7\xE4\x98\x8E\x05\x6B\xE3\xF8\x2D\x19\x18\x1D\x9C\x6E\xFE\x81\x41\x12\x03\x14\x08\x8F\x50\x13\x87\x5A\xC6\x56\x39\x8D\x8A\x2E\xD1\x9D\x2A\x85\xC8\xED\xD3\xEC\x2A\xEF", 48}, + { (unsigned char *) "\x04\xAA\x87\xCA\x22\xBE\x8B\x05\x37\x8E\xB1\xC7\x1E\xF3\x20\xAD\x74\x6E\x1D\x3B\x62\x8B\xA7\x9B\x98\x59\xF7\x41\xE0\x82\x54\x2A\x38\x55\x02\xF2\x5D\xBF\x55\x29\x6C\x3A\x54\x5E\x38\x72\x76\x0A\xB7\x36\x17\xDE\x4A\x96\x26\x2C\x6F\x5D\x9E\x98\xBF\x92\x92\xDC\x29\xF8\xF4\x1D\xBD\x28\x9A\x14\x7C\xE9\xDA\x31\x13\xB5\xF0\xB8\xC0\x0A\x60\xB1\xCE\x1D\x7E\x81\x9D\x7A\x43\x1D\x7C\x90\xEA\x0E\x5F", 97}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC7\x63\x4D\x81\xF4\x37\x2D\xDF\x58\x1A\x0D\xB2\x48\xB0\xA7\x7A\xEC\xEC\x19\x6A\xCC\xC5\x29\x73", 48}, + { (unsigned char *) "\x00\x01", 2} + }, + { { NULL, 0}, { NULL, 0}, @@ -117,7 +175,8 @@ isoApplet_select_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_auth_info_t *auth_info) { sc_card_t *card = p15card->card; - int preferred, current; + int preferred; + int current; LOG_FUNC_CALLED(card->ctx); @@ -208,155 +267,37 @@ isoApplet_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t } /* - * @brief Get the OID of the curve specified by a curve name. + * @brief Get the curve parameters associated with the curve specified by an OID. * - * @param[in] named_curve The name of the curve to search the OID of. - * Supported values are: brainpoolP192r1, prime256v1. - * @param[out] oid The OID of the curve. + * @param[in] oid The DER encoded OID of the curve. + * @param[in] oid_len The length of oid. + * @param[out] curve_out The ec_curve containing the set of parameters. * * @returns SC_SUCCESS: If the curve was found. * SC_ERROR_INVALID_ARGUMENTS: If named_curve was null or the curve * was not found */ static int -isoApplet_get_curve_oid(const char* named_curve, const struct sc_lv_data **oid) +isoApplet_get_curve(u8 *oid, size_t oid_len, const struct ec_curve **curve_out) { - if(!named_curve) + int i; + + if(!oid) return SC_ERROR_INVALID_ARGUMENTS; - if(strncmp(named_curve, "brainpoolP192r1", 15) == 0) + /* Search the curve parameters. */ + for (i = 0; curves[i].oid.value; i++) { - *oid = &curves[0].oid; - return SC_SUCCESS; - } - else if(strncmp(named_curve, "prime256v1", 10) == 0) - { - *oid = &curves[1].oid; - return SC_SUCCESS; + if (oid_len == curves[i].oid.len && memcmp(oid, curves[i].oid.value, curves[i].oid.len) == 0) + { + *curve_out = &curves[i]; + return SC_SUCCESS; + } } + return SC_ERROR_INVALID_ARGUMENTS; } -/* - * @brief Check the consistency of TLV-encoded EC curve parameters. - * - * Check the EC params in buf (length: len) that are structured according - * to ISO 7816-8 table 3 - Public key data objects. - * The params are compared with the ones given in the curve struct. - * - * @param[in] ctx - * @param[in] buf The buffer containing the TLV-encoded (ISO 7816-8 table 3) - * EC parameters. - * @param[in] len The length of buf. - * @param[in] curve An ec_curve struct that should be used to check the - * parameters in buf. - * - * @return SC_SUCCESS: If the EC parameters are consistent. - * SC_ERROR_INCOMPATIBLE_KEY: If the curve is unknown or the EC - * parameters are not consistent. - */ -static int -checkEcParams(sc_context_t* ctx, const u8* buf, size_t len, const struct ec_curve curve) -{ - const u8 *curr_pos = NULL; - size_t tag_len; - int r = SC_SUCCESS; - - LOG_FUNC_CALLED(ctx); - - /* Check the field. */ - curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x81, &tag_len); - if(curr_pos == NULL || tag_len != curve.prime.len) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "Could not find any EC field tag in the response template or the length was unexpected."); - } - if(memcmp(curr_pos, curve.prime.value, curve.prime.len) != 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "The EC field by the smartcard was unexpected."); - } - - /* Check the coefficient A. */ - curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x82, &tag_len); - if(curr_pos == NULL || tag_len != curve.coefficientA.len) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "Could not find any EC coefficient A tag in the response template or the length was unexpected."); - } - if(memcmp(curr_pos, curve.coefficientA.value, curve.coefficientA.len) != 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "The EC coefficient A returned by the smartcard was unexpected."); - } - - /* Check the coefficient B. */ - curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x83, &tag_len); - if(curr_pos == NULL || tag_len != curve.coefficientB.len) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "Could not find any EC coefficient B tag in the response template or the length was unexpected."); - } - if(memcmp(curr_pos, curve.coefficientB.value, curve.coefficientB.len) != 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "The EC coefficient B returned by the smartcard was unexpected."); - } - - /* Check the basepoint G. - * Note: The IsoApplet omits the 0x04 (uncompressed) tag. */ - curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x84, &tag_len); - if(curr_pos == NULL || tag_len != curve.basePointG.len) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "Could not find any EC basepoint G tag in the response template or the length was unexpected."); - } - if(memcmp(curr_pos, curve.basePointG.value, curve.basePointG.len) != 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "The EC basepoint G returned by the smartcard was unexpected."); - } - - /* Check the order. */ - curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x85, &tag_len); - if(curr_pos == NULL || tag_len != curve.order.len) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "Could not find any EC order tag in the response template or the length was unexpected."); - } - if(memcmp(curr_pos, curve.order.value, curve.order.len) != 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "The EC order returned by the smartcard was unexpected."); - } - - /* Check the coFactor. */ - curr_pos = sc_asn1_find_tag(ctx, buf, len, (unsigned int) 0x87, &tag_len); - if(curr_pos == NULL || tag_len != curve.coFactor.len) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "Could not find any EC cofactor tag in the response template or the length was unexpected."); - } - if(memcmp(curr_pos, curve.coFactor.value, curve.coFactor.len) != 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - LOG_TEST_RET(ctx, r, - "The EC cofactor returned by the smartcards was unexpected."); - } - - LOG_FUNC_RETURN(ctx, r); -} /* * @brief Generate a RSA private key on the card. @@ -373,8 +314,8 @@ checkEcParams(sc_context_t* ctx, const u8* buf, size_t len, const struct ec_curv * SC_ERROR_OUT_OF_MEMORY */ static int -generate_key_rsa(sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, - sc_pkcs15_pubkey_t *pubkey) +isoApplet_generate_key_rsa(sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, + sc_pkcs15_pubkey_t *pubkey) { int rv; size_t keybits; @@ -392,23 +333,23 @@ generate_key_rsa(sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, } /* Generate the key. - * Note: keysize is not explicitly passed to the card. It assumes 2048 along with the algorithm reference. */ + * Note: key size is not explicitly passed to the card. It assumes 2048 along with the algorithm reference. */ memset(&args, 0, sizeof(args)); args.algorithm_ref = SC_ISOAPPLET_ALG_REF_RSA_GEN_2048; args.priv_key_ref = key_info->key_reference; - args.pubkey_len = keybits / 8; - args.pubkey = malloc(args.pubkey_len); - if (!args.pubkey) + args.pubkey.rsa.modulus.len = keybits / 8; + args.pubkey.rsa.modulus.value = malloc(args.pubkey.rsa.modulus.len); + if (!args.pubkey.rsa.modulus.value) { rv = SC_ERROR_OUT_OF_MEMORY; sc_log(card->ctx, "%s: Unable to allocate public key buffer.", sc_strerror(rv)); goto err; } - args.exponent_len = 3; - args.exponent = malloc(args.exponent_len); - if(!args.exponent) + args.pubkey.rsa.exponent.len = 3; + args.pubkey.rsa.exponent.value = malloc(args.pubkey.rsa.exponent.len); + if(!args.pubkey.rsa.exponent.value) { rv = SC_ERROR_OUT_OF_MEMORY; sc_log(card->ctx, "%s: Unable to allocate public key exponent buffer.", sc_strerror(rv)); @@ -422,24 +363,24 @@ generate_key_rsa(sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, goto err; } - /* extract public key */ + /* extract the public key */ pubkey->algorithm = SC_ALGORITHM_RSA; - pubkey->u.rsa.modulus.len = args.pubkey_len; - pubkey->u.rsa.modulus.data = args.pubkey; - pubkey->u.rsa.exponent.len = args.exponent_len; - pubkey->u.rsa.exponent.data = args.exponent; + pubkey->u.rsa.modulus.len = args.pubkey.rsa.modulus.len; + pubkey->u.rsa.modulus.data = args.pubkey.rsa.modulus.value; + pubkey->u.rsa.exponent.len = args.pubkey.rsa.exponent.len; + pubkey->u.rsa.exponent.data = args.pubkey.rsa.exponent.value; rv = SC_SUCCESS; LOG_FUNC_RETURN(card->ctx, rv); err: - if (args.pubkey) + if (args.pubkey.rsa.modulus.value) { - free(args.pubkey); + free(args.pubkey.rsa.modulus.value); pubkey->u.rsa.modulus.data = NULL; pubkey->u.rsa.modulus.len = 0; } - if (args.exponent) + if (args.pubkey.rsa.exponent.value) { - free(args.exponent); + free(args.pubkey.rsa.exponent.value); pubkey->u.rsa.exponent.data = NULL; pubkey->u.rsa.exponent.len = 0; } @@ -452,10 +393,10 @@ err: * A MANAGE SECURITY ENVIRONMENT apdu must have been sent before. * This function uses card_ctl to access the card-isoApplet driver. * - * @param[in] key_info - * @param[in] card - * @param[in] pubkey The public key of the generated key pair - * returned by the card. + * @param[in] key_info + * @param[in] card + * @param[in/out] pubkey The public key of the generated key pair + * returned by the card. * * @return SC_ERROR_INVALID_ARGURMENTS: Invalid key length or curve. * SC_ERROR_OUT_OF_MEMORY @@ -464,199 +405,127 @@ err: * handled. */ static int -generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, - sc_pkcs15_pubkey_t *pubkey) +isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, + sc_pkcs15_pubkey_t *pubkey) { - int r; - u8* p = NULL; - u8* ecPubKeyPoint = NULL; - size_t tag_len; - size_t all_tags_len; - const u8* curr_pos = NULL; - struct sc_ec_params* ecp = NULL; - const struct sc_lv_data* oid = NULL; - sc_cardctl_isoApplet_genkey_t args; - const struct sc_pkcs15_ec_parameters* info_ecp = + int r; + const struct ec_curve *curve = NULL; + struct sc_ec_params *alg_id_params = NULL; + sc_cardctl_isoApplet_genkey_t args; + const struct sc_pkcs15_ec_parameters *info_ecp = (struct sc_pkcs15_ec_parameters *) key_info->params.data; LOG_FUNC_CALLED(card->ctx); /* Check key size: */ - if(key_info->field_length != 192 - && key_info->field_length != 256) + if(key_info->field_length == 0) { - sc_log(card->ctx, "EC field length is unsupported, length provided was: %d.", key_info->field_length); + sc_log(card->ctx, "Unknown field length."); r = SC_ERROR_INVALID_ARGUMENTS; - goto err; + goto out; } - if(info_ecp->named_curve && strncmp(info_ecp->named_curve, "brainpoolP192r1", 15) != 0 - && strncmp(info_ecp->named_curve, "prime256v1", 10) != 0) + r = isoApplet_get_curve(info_ecp->der.value, info_ecp->der.len, &curve); + if(r < 0) { sc_log(card->ctx, "EC key generation failed: Unsupported curve: [%s].", info_ecp->named_curve); - r = SC_ERROR_INVALID_ARGUMENTS; - goto err; + goto out; } /* Generate the key. - * Note: THe field size is not explicitly passed to the card. - * It assumes it along with the algorithm reference. */ + * Note: The field size is not explicitly passed to the card. + * As we only support FP curves, the field length can be calculated from any parameter. */ memset(&args, 0, sizeof(args)); - args.pubkey_len = 512; - args.pubkey = malloc(args.pubkey_len); - if(!args.pubkey) + args.pubkey.ec.params.prime.value = curve->prime.value; + args.pubkey.ec.params.prime.len = curve->prime.len; + args.pubkey.ec.params.coefficientA.value = curve->coefficientA.value; + args.pubkey.ec.params.coefficientA.len = curve->coefficientA.len; + args.pubkey.ec.params.coefficientB.value = curve->coefficientB.value; + args.pubkey.ec.params.coefficientB.len = curve->coefficientB.len; + args.pubkey.ec.params.basePointG.value = curve->basePointG.value; + args.pubkey.ec.params.basePointG.len = curve->basePointG.len; + args.pubkey.ec.params.order.value = curve->order.value; + args.pubkey.ec.params.order.len = curve->order.len; + args.pubkey.ec.params.coFactor.value = curve->coFactor.value; + args.pubkey.ec.params.coFactor.len = curve->coFactor.len; + /* The length of the public key point will be: + * Uncompressed tag + 2 * field length in bytes. */ + args.pubkey.ec.ecPointQ.len = 1 + 2 * key_info->field_length / 8; + args.pubkey.ec.ecPointQ.value = malloc(args.pubkey.ec.ecPointQ.len); + if(!args.pubkey.ec.ecPointQ.value) { r = SC_ERROR_OUT_OF_MEMORY; - sc_log(card->ctx, "%s: Unable to allocate public key buffer.", sc_strerror(r)); - goto err; + goto out; } - if(strncmp(info_ecp->named_curve, "brainpoolP192r1", 15) == 0) - { - args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1; - } - else if(strncmp(info_ecp->named_curve, "prime256v1", 10) == 0) - { - args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1; - } + args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN; args.priv_key_ref = key_info->key_reference; + /* On-card key generation */ r = sc_card_ctl(card, SC_CARDCTL_ISOAPPLET_GENERATE_KEY, &args); if (r < 0) { sc_log(card->ctx, "%s: Error in card_ctl.", sc_strerror(r)); - goto err; + goto out; } - /* Extract the public key. */ + /* Extract and compose the public key. */ pubkey->algorithm = SC_ALGORITHM_EC; - /* Get the curves OID. */ - r = isoApplet_get_curve_oid(info_ecp->named_curve, &oid); - if(r < 0) - { - sc_log(card->ctx, "Error obtaining the curve OID.", sc_strerror(r)); - goto err; - } - /* der-encoded parameters */ - ecp = calloc(1, sizeof(struct sc_ec_params)); - if(!ecp) + alg_id_params = calloc(1, sizeof(*alg_id_params)); + if(!alg_id_params) { r = SC_ERROR_OUT_OF_MEMORY; - goto err; + goto out; } - ecp->der_len = oid->len + 2; - ecp->der = calloc(ecp->der_len, 1); - if(!ecp->der) + alg_id_params->der_len = curve->oid.len; + alg_id_params->der = malloc(alg_id_params->der_len); + if(!alg_id_params->der) { r = SC_ERROR_OUT_OF_MEMORY; - sc_log(card->ctx, "%s: Unable to allocate public key buffer.", sc_strerror(r)); - goto err; + goto out; } - ecp->der[0] = 0x06; - ecp->der[1] = (u8)oid->len; - memcpy(ecp->der + 2, oid->value, oid->len); - ecp->type = 1; /* named curve */ + memcpy(alg_id_params->der, curve->oid.value, curve->oid.len); + alg_id_params->type = 1; /* named curve */ - pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id)); + pubkey->alg_id = malloc(sizeof(*pubkey->alg_id)); if(!pubkey->alg_id) { r = SC_ERROR_OUT_OF_MEMORY; - sc_log(card->ctx, "%s: Unable to allocate public key sc_algorithm_id.", sc_strerror(r)); - goto err; + goto out; } pubkey->alg_id->algorithm = SC_ALGORITHM_EC; - pubkey->alg_id->params = ecp; - - p = args.pubkey; - if(memcmp(info_ecp->named_curve, "brainpoolP192r1", 15) == 0) - { - /* The applet returns the public key encoded according to - * ISO 7816-8 table 3 - Public key data objects. This is a - * 2-byte tag. A length of 0xD0 = 208 is expected for BrainpoolP192r1. */ - if(memcmp(p, "\x7F\x49\x81\xD0", 4) != 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - sc_log(card->ctx, "%s: Key generation error: Unexpected EC public key received length.", sc_strerror(r)); - goto err; - } - else - { - p += 4; /* p points to the value field of the outer (7F 49) tag. - * This value field is a TLV-structure again. */ - all_tags_len = 208; /* 0xD0 bytes */ - } - - /* Check EC params. */ - r = checkEcParams(card->ctx, p, all_tags_len, curves[0]); - if(r != SC_SUCCESS) - { - goto err; - } - } - else if(memcmp(info_ecp->named_curve, "prime256v1", 10) == 0) - { - /* The applet returns the public key encoded according to - * ISO 7816-8 table 3 - Public key data objects. This is a - * 2-byte tag. A length of 0x011A = 282 is expected for Prime256v1. */ - if(memcmp(p, "\x7F\x49\x82\x01\x1A", 5) != 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - sc_log(card->ctx, "%s: Key generation error: Unexpected EC public key parameters.", sc_strerror(r)); - goto err; - } - else - { - p += 5; /* p points to the value field of the outer (7F 49) tag. - * This value field is a TLV-structure again. */ - all_tags_len = 282; /* 0x011A bytes */ - } - - /* Check EC params. */ - r = checkEcParams(card->ctx, p, all_tags_len, curves[1]); - if(r != SC_SUCCESS) - { - goto err; - } - } + pubkey->alg_id->params = alg_id_params; /* Extract ecpointQ */ - curr_pos = sc_asn1_find_tag(card->ctx, p, all_tags_len, (unsigned int) 0x86, &tag_len); - if(curr_pos == NULL || tag_len == 0) - { - r = SC_ERROR_INCOMPATIBLE_KEY; - sc_log(card->ctx, "%s: Could not find any EC pointQ tag in the response template.", sc_strerror(r)); - goto err; - } - ecPubKeyPoint = malloc(tag_len+1); - if(!ecPubKeyPoint) + pubkey->u.ec.ecpointQ.len = args.pubkey.ec.ecPointQ.len; + pubkey->u.ec.ecpointQ.value = malloc(pubkey->u.ec.ecpointQ.len); + if(!pubkey->u.ec.ecpointQ.value) { r = SC_ERROR_OUT_OF_MEMORY; - sc_log(card->ctx, "%s: Unable to allocate public key ecpointQ buffer.", sc_strerror(r)); - goto err; + goto out; } - *ecPubKeyPoint = 0x04; /* uncompressed */ - memcpy(ecPubKeyPoint+1, curr_pos, tag_len); - pubkey->u.ec.ecpointQ.value = ecPubKeyPoint; - pubkey->u.ec.ecpointQ.len = tag_len+1; + memcpy(pubkey->u.ec.ecpointQ.value, args.pubkey.ec.ecPointQ.value, args.pubkey.ec.ecPointQ.len); - /* OID for the public key */ - pubkey->u.ec.params.der.value = malloc(ecp->der_len); + /* The OID is also written to the pubkey->u.ec.params */ + pubkey->u.ec.params.der.value = malloc(alg_id_params->der_len); if(!pubkey->u.ec.params.der.value) { r = SC_ERROR_OUT_OF_MEMORY; - sc_log(card->ctx, "%s: Unable to allocate public key ec params buffer.", sc_strerror(r)); - goto err; + goto out; } - memcpy(pubkey->u.ec.params.der.value, ecp->der, ecp->der_len); - pubkey->u.ec.params.der.len = ecp->der_len; - + memcpy(pubkey->u.ec.params.der.value, alg_id_params->der, alg_id_params->der_len); + pubkey->u.ec.params.der.len = alg_id_params->der_len; r = sc_pkcs15_fix_ec_parameters(card->ctx, &pubkey->u.ec.params); - LOG_FUNC_RETURN(card->ctx, r); -err: - if(pubkey) +out: + if(args.pubkey.ec.ecPointQ.value) + { + free(args.pubkey.ec.ecPointQ.value); + args.pubkey.ec.ecPointQ.value = NULL; + } + if(r < 0 && pubkey) { if(pubkey->alg_id) { @@ -669,28 +538,23 @@ err: pubkey->u.ec.params.der.value = NULL; pubkey->u.ec.params.der.len = 0; } + if(r < 0 && pubkey->u.ec.ecpointQ.value) + { + free(pubkey->u.ec.ecpointQ.value); + pubkey->u.ec.ecpointQ.value = NULL; + pubkey->u.ec.ecpointQ.len = 0; + } memset(pubkey, 0, sizeof(sc_pkcs15_pubkey_t)); } - if(args.pubkey) + if(r < 0 && alg_id_params) { - free(args.pubkey); - args.pubkey = NULL; - args.pubkey_len = 0; - } - if(ecPubKeyPoint) - { - free(ecPubKeyPoint); - ecPubKeyPoint = NULL; - } - if(ecp) - { - if(ecp->der) + if(alg_id_params->der) { - free(ecp->der); - ecp->der = NULL; + free(alg_id_params->der); + alg_id_params->der = NULL; } - free(ecp); - ecp = NULL; + free(alg_id_params); + pubkey->alg_id->params = NULL; } LOG_FUNC_RETURN(card->ctx, r); } @@ -700,10 +564,10 @@ isoApplet_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { - int r; - sc_pkcs15_prkey_info_t* key_info = (sc_pkcs15_prkey_info_t *) obj->data; - sc_file_t* privKeyFile=NULL; - sc_card_t* card = p15card->card; + int r; + sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data; + sc_file_t *privKeyFile=NULL; + sc_card_t *card = p15card->card; LOG_FUNC_CALLED(card->ctx); @@ -725,11 +589,11 @@ isoApplet_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, switch(obj->type) { case SC_PKCS15_TYPE_PRKEY_RSA: - r = generate_key_rsa(key_info, card, pubkey); + r = isoApplet_generate_key_rsa(key_info, card, pubkey); break; case SC_PKCS15_TYPE_PRKEY_EC: - r = generate_key_ec(key_info, card, pubkey); + r = isoApplet_generate_key_ec(key_info, card, pubkey); break; default: @@ -783,11 +647,10 @@ isoApplet_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_ sc_pkcs15_prkey_t *key) { sc_card_t *card = p15card->card; - sc_pkcs15_prkey_info_t* key_info = (sc_pkcs15_prkey_info_t *) object->data; - sc_file_t* privKeyFile=NULL; + sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) object->data; + sc_file_t *privKeyFile=NULL; sc_cardctl_isoApplet_import_key_t args; int r; - char *p = NULL; LOG_FUNC_CALLED(card->ctx); @@ -810,30 +673,58 @@ isoApplet_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_ { case SC_PKCS15_TYPE_PRKEY_RSA: args.algorithm_ref = SC_ISOAPPLET_ALG_REF_RSA_GEN_2048; + if(!key->u.rsa.p.data + ||!key->u.rsa.q.data + ||!key->u.rsa.iqmp.data + ||!key->u.rsa.dmp1.data + ||!key->u.rsa.dmq1.data) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Only CRT RSA keys may be imported."); + } + args.privkey.rsa.p.value = key->u.rsa.p.data; + args.privkey.rsa.p.len = key->u.rsa.p.len; + args.privkey.rsa.q.value = key->u.rsa.q.data; + args.privkey.rsa.q.len = key->u.rsa.q.len; + args.privkey.rsa.iqmp.value = key->u.rsa.iqmp.data; + args.privkey.rsa.iqmp.len = key->u.rsa.iqmp.len; + args.privkey.rsa.dmp1.value = key->u.rsa.dmp1.data; + args.privkey.rsa.dmp1.len = key->u.rsa.dmp1.len; + args.privkey.rsa.dmq1.value = key->u.rsa.dmq1.data; + args.privkey.rsa.dmq1.len = key->u.rsa.dmq1.len; break; case SC_PKCS15_TYPE_PRKEY_EC: - p = key->u.ec.params.named_curve; - if(!p) - { - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); - } + { + const struct ec_curve *curve = NULL; - if(strncmp(p, "brainpoolP192r1", 15) == 0) + args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN; + if(!key->u.ec.params.named_curve) { - args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN_BRAINPOOLP192R1; + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Unspecified curve / no curve name."); } - else if(strncmp(p, "prime256v1", 10) == 0) - { - args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN_PRIME256V1; - } - break; + r = isoApplet_get_curve(key->u.ec.params.der.value, key->u.ec.params.der.len, &curve); + LOG_TEST_RET(card->ctx, r, "EC key generation failed: Unsupported curve"); + args.privkey.ec.params.prime.value = curve->prime.value; + args.privkey.ec.params.prime.len = curve->prime.len; + args.privkey.ec.params.coefficientA.value = curve->coefficientA.value; + args.privkey.ec.params.coefficientA.len = curve->coefficientA.len; + args.privkey.ec.params.coefficientB.value = curve->coefficientB.value; + args.privkey.ec.params.coefficientB.len = curve->coefficientB.len; + args.privkey.ec.params.basePointG.value = curve->basePointG.value; + args.privkey.ec.params.basePointG.len = curve->basePointG.len; + args.privkey.ec.params.order.value = curve->order.value; + args.privkey.ec.params.order.len = curve->order.len; + args.privkey.ec.params.coFactor.value = curve->coFactor.value; + args.privkey.ec.params.coFactor.len = curve->coFactor.len; + args.privkey.ec.privateD.value = key->u.ec.privateD.data; + args.privkey.ec.privateD.len = key->u.ec.privateD.len; + } + break; default: LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); } args.priv_key_ref = key_info->key_reference; - args.prkey = key; r = sc_card_ctl(card, SC_CARDCTL_ISOAPPLET_IMPORT_KEY, &args); if (r < 0) From c463f1a7a1e4bfa653c6d34f5ee4f0a2d41883b1 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Tue, 28 Oct 2014 11:17:45 +0100 Subject: [PATCH 107/306] IsoApplet: Do not set RSA hashes See: 189e998486a5813bca2f6737a465ad62abb318c7 The IsoApplet requires the host to do the hashes with RSA. OpenSC will add all hashes that are available in software and will not expect the card to do the hashing. --- src/libopensc/card-isoApplet.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index ea81960f..fb1487a8 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -216,16 +216,8 @@ isoApplet_init(sc_card_t *card) flags = 0; /* Padding schemes: */ flags |= SC_ALGORITHM_RSA_PAD_PKCS1; - /* Hashes: */ + /* Hashes are to be done by the host for RSA */ flags |= SC_ALGORITHM_RSA_HASH_NONE; - flags |= SC_ALGORITHM_RSA_HASH_SHA1; - flags |= SC_ALGORITHM_RSA_HASH_MD5; - flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1; - flags |= SC_ALGORITHM_RSA_HASH_SHA224; - flags |= SC_ALGORITHM_RSA_HASH_SHA256; - flags |= SC_ALGORITHM_RSA_HASH_SHA384; - flags |= SC_ALGORITHM_RSA_HASH_SHA512; - flags |= SC_ALGORITHM_RSA_HASH_RIPEMD160; /* Key-generation: */ flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; /* Modulus lengths: */ From 09acfd7ec00d6561a9561c243cc75470d414cd2e Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 31 Oct 2014 17:17:00 +0100 Subject: [PATCH 108/306] IsoApplet: ECDSA signatures - only strip excess zeroes It is required to strip excessive zeroes returned by some Java Cards when removeing the ASN1 structural information for PKCS#11 so that the x/y can be calculated by dividing the signature length by 2. However, the leading zero may only be stripped if it is excessive (outside the field length). Otherwise generated signatures are wrong in rare cases (1 out of 256). --- src/libopensc/card-isoApplet.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index fb1487a8..105ec2b2 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -1240,8 +1240,9 @@ isoApplet_compute_signature(struct sc_card *card, xlen = *p++; if(xlen > outlen - (p - out)) LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); - /* Java Cards might return a leading zero, which needs to be stripped. */ - if(*p == 0x00) + /* Java Cards might return a leading zero, + * which needs to be stripped when not using the ASN1 structural information. */ + if(*p == 0x00 && (xlen == 192/8+1 || xlen == 224/8+1 || xlen == 256/8+1 || xlen == 320/8+1 || xlen == 384/8+1)) { p++; xlen--; @@ -1255,8 +1256,9 @@ isoApplet_compute_signature(struct sc_card *card, ylen = *p++; if(ylen > outlen - (p - out)) LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); - /* Java Cards might return a leading zero, which needs to be stripped. */ - if(*p == 0x00) + /* Java Cards might return a leading zero, + * which needs to be stripped when not using the ASN1 structural information. */ + if(*p == 0x00 && (ylen == 192/8+1 || ylen == 224/8+1 || ylen == 256/8+1 || ylen == 320/8+1 || ylen == 384/8+1)) { p++; ylen--; From 6cdf6c08a598779903ff5eb81850d8cf574f6ba0 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Thu, 13 Nov 2014 13:51:10 +0100 Subject: [PATCH 109/306] IsoApplet: use AID directly when selecting applet Now that apdu.data is const (see ef94c6b875b7927bb80e49139a29a3ce2b4937b7), this can be done without discarding the const qualifier of the aid parameter. --- src/libopensc/card-isoApplet.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 105ec2b2..46203b2b 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -82,22 +82,20 @@ static struct sc_card_driver isoApplet_drv = * not present. */ static int -isoApplet_select_applet(sc_card_t *card, const u8 aid[], const size_t aid_len, u8 *resp, size_t *resp_len) +isoApplet_select_applet(sc_card_t *card, const u8 *aid, const size_t aid_len, u8 *resp, size_t *resp_len) { int rv; sc_context_t *ctx = card->ctx; sc_apdu_t apdu; - u8 aid_wc[SC_MAX_APDU_BUFFER_SIZE]; LOG_FUNC_CALLED(card->ctx); if(aid_len > SC_MAX_APDU_BUFFER_SIZE) LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); - memcpy(aid_wc, aid, aid_len); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xa4, 0x04, 0x00); apdu.lc = aid_len; - apdu.data = aid_wc; + apdu.data = aid; apdu.datalen = aid_len; apdu.resp = resp; apdu.resplen = *resp_len; From e791948e4230cad5d8def22f5148ceaf9248e837 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Wed, 19 Nov 2014 14:04:40 +0100 Subject: [PATCH 110/306] IsoApplet: Simplify the private key import Use the new features of sc_asn1_put_tag introduced in OpenSC/OpenSC#314. Additionally, a RSA private key is sent from one large buffer using either extended APDUs or chaining (in compliance to IsoApplet API version 00.05). --- src/libopensc/card-isoApplet.c | 235 +++++++++++---------------------- 1 file changed, 79 insertions(+), 156 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 46203b2b..b83adb24 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -32,7 +32,7 @@ #define ISOAPPLET_ALG_REF_RSA_PAD_PKCS1 0x11 #define ISOAPPLET_API_VERSION_MAJOR 0x00 -#define ISOAPPLET_API_VERSION_MINOR 0x04 +#define ISOAPPLET_API_VERSION_MINOR 0x05 #define ISOAPPLET_API_FEATURE_EXT_APDU 0x01 #define ISOAPPLET_AID_LEN 12 @@ -480,6 +480,11 @@ isoApplet_put_ec_params(sc_card_t *card, sc_cardctl_isoApplet_ec_parameters_t *p LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Error: EC params not present."); } + if(out == NULL || out_len == 0) + { + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Error: Parameter out is NULL or outlen is zero."); + } + r = sc_asn1_put_tag(0x81, params->prime.value, params->prime.len, p, out_len - (p - out), &p); LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); r = sc_asn1_put_tag(0x82, params->coefficientA.value, params->coefficientA.len, p, out_len - (p - out), &p); @@ -699,10 +704,9 @@ static int isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args) { sc_apdu_t apdu; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; u8 *p = NULL; int r; - int locked = 0; size_t tags_len; LOG_FUNC_CALLED(card->ctx); @@ -716,154 +720,65 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "RSA key is missing information."); } - p = sbuf; - /* Note: The format is according to ISO 2-byte tag 7F48 */ - *p++ = 0x7F; /* T-L pair to indicate a private key data object */ - *p++ = 0x48; - /* Calculate the length of all inner tag-length-value entries. - * One entry consists of: tag (1 byte) + length (1 byte if < 128, 2 if >= 128) + value (len) - * It may actually happen that a parameter is 127 byte (leading zero) */ - tags_len = 1 + (args->privkey.rsa.p.len < 128 ? 1 : 2) + args->privkey.rsa.p.len + - 1 + (args->privkey.rsa.q.len < 128 ? 1 : 2) + args->privkey.rsa.q.len + - 1 + (args->privkey.rsa.iqmp.len < 128 ? 1 : 2) + args->privkey.rsa.iqmp.len + - 1 + (args->privkey.rsa.dmp1.len < 128 ? 1 : 2) + args->privkey.rsa.dmp1.len + - 1 + (args->privkey.rsa.dmq1.len < 128 ? 1 : 2) + args->privkey.rsa.dmq1.len; - *p++ = 0x82; - *p++ = (tags_len >> 8) & 0xFF; /* MSB */ - *p++ = tags_len & 0xFF; /* LSB */ + /* Note: The format is according to ISO 2-byte tag 7F48 + * "T-L pair to indicate a private key data object" */ + /* Calculate the length of all inner tag-length-value entries, but do not write anything yet. */ + tags_len = 0; + r = sc_asn1_put_tag(0x92, NULL, args->privkey.rsa.p.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x93, NULL, args->privkey.rsa.q.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x94, NULL, args->privkey.rsa.iqmp.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x95, NULL, args->privkey.rsa.dmp1.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x96, NULL, args->privkey.rsa.dmq1.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + + /* Write the outer tag and length information. */ + p = sbuf; + r = sc_asn1_put_tag(0x7F48, NULL, tags_len, p, sizeof(sbuf), &p); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + + /* Write inner tags. */ /* p */ r = sc_asn1_put_tag(0x92, args->privkey.rsa.p.value, args->privkey.rsa.p.len, p, sizeof(sbuf) - (p - sbuf), &p); LOG_TEST_RET(card->ctx, r, "Error handling TLV."); - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDB, 0x3F, 0xFF); - apdu.cla |= 0x10; /* Chaining */ - apdu.data = sbuf; - apdu.datalen = p - sbuf; - apdu.lc = p - sbuf; - - r = sc_lock(card); /* We will use several apdus */ - LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); - locked = 1; - - r = sc_transmit_apdu(card, &apdu); - if(r < 0) - { - sc_log(card->ctx, "%s: APDU transmit failed", strerror(r)); - goto out; - } - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if(apdu.sw1 == 0x6D && apdu.sw2 == 0x00) - { - sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported." - "If you are using an older applet version and are trying to import keys, please update your applet first."); - } - if(r < 0) - { - sc_log(card->ctx, "%s: Card returned error", strerror(r)); - goto out; - } - /* q */ - p = sbuf; r = sc_asn1_put_tag(0x93, args->privkey.rsa.q.value, args->privkey.rsa.q.len, p, sizeof(sbuf) - (p - sbuf), &p); - if(r < 0) - { - sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); - goto out; - } - apdu.data = sbuf; - apdu.datalen = p - sbuf; - apdu.lc = p - sbuf; - r = sc_transmit_apdu(card, &apdu); - if(r < 0) - { - sc_log(card->ctx, "%s: APDU transmit failed.", strerror(r)); - goto out; - } - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if(r < 0) - { - sc_log(card->ctx, "%s: Card returned error.", strerror(r)); - goto out; - } - + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); /* 1/q mod p */ - p = sbuf; r = sc_asn1_put_tag(0x94, args->privkey.rsa.iqmp.value, args->privkey.rsa.iqmp.len, p, sizeof(sbuf) - (p - sbuf), &p); - if(r < 0) - { - sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); - goto out; - } - apdu.data = sbuf; - apdu.datalen = p - sbuf; - apdu.lc = p - sbuf; - r = sc_transmit_apdu(card, &apdu); - if(r < 0) - { - sc_log(card->ctx, "%s: APDU transmit failed.", strerror(r)); - goto out; - } - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if(r < 0) - { - sc_log(card->ctx, "%s: Card returned error.", strerror(r)); - goto out; - } - + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); /* d mod (p-1) */ - p = sbuf; r = sc_asn1_put_tag(0x95, args->privkey.rsa.dmp1.value, args->privkey.rsa.dmp1.len, p, sizeof(sbuf) - (p - sbuf), &p); - if(r < 0) - { - sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); - goto out; - } - apdu.data = sbuf; - apdu.datalen = p - sbuf; - apdu.lc = p - sbuf; - r = sc_transmit_apdu(card, &apdu); - if(r < 0) - { - sc_log(card->ctx, "%s: APDU transmit failed.", strerror(r)); - goto out; - } - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if(r < 0) - { - sc_log(card->ctx, "%s: Card returned error.", strerror(r)); - goto out; - } - + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); /* d mod (q-1) */ - p = sbuf; r = sc_asn1_put_tag(0x96, args->privkey.rsa.dmq1.value, args->privkey.rsa.dmq1.len, p, sizeof(sbuf) - (p - sbuf), &p); - if(r < 0) - { - sc_log(card->ctx, "%s: Error in handling TLV.", strerror(r)); - goto out; - } - apdu.cla = 0x00; /* Last part of the chain. */ + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + + /* Send to card, using chaining or extended APDUs. */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDB, 0x3F, 0xFF); apdu.data = sbuf; apdu.datalen = p - sbuf; apdu.lc = p - sbuf; + if ((card->caps & SC_CARD_CAP_APDU_EXT) == 0) + { + /* The lower layers will automatically do chaining */ + apdu.flags |= SC_APDU_FLAGS_CHAINING; + } r = sc_transmit_apdu(card, &apdu); - if(r < 0) - { - sc_log(card->ctx, "%s: APDU transmit failed.", strerror(r)); - goto out; - } + LOG_TEST_RET(card->ctx, r, "APDU transmit failed."); r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if(r < 0) - { - sc_log(card->ctx, "%s: Card returned error.", strerror(r)); - goto out; - } + LOG_TEST_RET(card->ctx, r, "Card returned error."); -out: - if(locked) - sc_unlock(card); - LOG_FUNC_RETURN(card->ctx, r); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } /* @@ -909,28 +824,36 @@ isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t * LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Missing information about EC private key."); } + /* Calculate the length of all inner tag-length-value entries, but do not write anything yet. */ + tags_len = 0; + r = sc_asn1_put_tag(0x81, NULL, args->privkey.ec.params.prime.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x82, NULL, args->privkey.ec.params.coefficientA.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x83, NULL, args->privkey.ec.params.coefficientB.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x84, NULL, args->privkey.ec.params.basePointG.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x85, NULL, args->privkey.ec.params.order.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x87, NULL, args->privkey.ec.params.coFactor.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + r = sc_asn1_put_tag(0x88, NULL, args->privkey.ec.privateD.len, NULL, 0, NULL); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + tags_len += r; + + /* Write the outer tag and length information. */ p = sbuf; - *p++ = 0xE0; - tags_len = 1 + (args->privkey.ec.params.prime.len < 128 ? 1 : 2) + args->privkey.ec.params.prime.len + - 1 + (args->privkey.ec.params.coefficientA.len < 128 ? 1 : 2) + args->privkey.ec.params.coefficientA.len + - 1 + (args->privkey.ec.params.coefficientB.len < 128 ? 1 : 2) + args->privkey.ec.params.coefficientB.len + - 1 + (args->privkey.ec.params.basePointG.len < 128 ? 1 : 2) + args->privkey.ec.params.basePointG.len + - 1 + (args->privkey.ec.params.order.len < 128 ? 1 : 2) + args->privkey.ec.params.order.len + - 1 + (args->privkey.ec.params.coFactor.len < 128 ? 1 : 2) + args->privkey.ec.params.coFactor.len + - 1 + (args->privkey.ec.privateD.len < 128 ? 1 : 2) + args->privkey.ec.privateD.len; - if(tags_len < 127) - *p++ = (tags_len & 0xFF); - else if (tags_len < 255) - { - *p++ = 0x81; - *p++ = (tags_len & 0xFF); - } - else - { - *p++ = 0x82; - *p++ = (tags_len >> 8) & 0xFF; /* MSB */ - *p++ = tags_len & 0xFF; /* LSB */ - } + r = sc_asn1_put_tag(0xE0, NULL, tags_len, p, sizeof(sbuf), &p); + LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + + /* Write inner tags. */ r = isoApplet_put_ec_params(card, &args->privkey.ec.params, p, sizeof(sbuf) - (p - sbuf), &p); LOG_TEST_RET(card->ctx, r, "Error composing EC params."); r = sc_asn1_put_tag(0x88, args->privkey.ec.privateD.value, args->privkey.ec.privateD.len, p, sizeof(sbuf) - (p - sbuf), &p); @@ -1238,7 +1161,7 @@ isoApplet_compute_signature(struct sc_card *card, xlen = *p++; if(xlen > outlen - (p - out)) LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); - /* Java Cards might return a leading zero, + /* Java Cards might return a leading zero, * which needs to be stripped when not using the ASN1 structural information. */ if(*p == 0x00 && (xlen == 192/8+1 || xlen == 224/8+1 || xlen == 256/8+1 || xlen == 320/8+1 || xlen == 384/8+1)) { @@ -1254,7 +1177,7 @@ isoApplet_compute_signature(struct sc_card *card, ylen = *p++; if(ylen > outlen - (p - out)) LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); - /* Java Cards might return a leading zero, + /* Java Cards might return a leading zero, * which needs to be stripped when not using the ASN1 structural information. */ if(*p == 0x00 && (ylen == 192/8+1 || ylen == 224/8+1 || ylen == 256/8+1 || ylen == 320/8+1 || ylen == 384/8+1)) { From 73b391731b49ad37625ef52ca60f84f56112963a Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Wed, 19 Nov 2014 21:54:10 +0100 Subject: [PATCH 111/306] IsoApplet: Don't set ECC field length of 512 512 is wrong for EC FP (correct would be 521 bit), and neither of those two are currently supported by OpenSC. --- src/libopensc/card-isoApplet.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index b83adb24..de8256cf 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -208,7 +208,6 @@ isoApplet_init(sc_card_t *card) _sc_card_add_ec_alg(card, 256, flags, ext_flags); _sc_card_add_ec_alg(card, 320, flags, ext_flags); _sc_card_add_ec_alg(card, 384, flags, ext_flags); - _sc_card_add_ec_alg(card, 512, flags, ext_flags); /* RSA */ flags = 0; From 0473decae4dbc3b463028c59015a6086f9e3fa00 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 28 Nov 2014 18:06:13 +0100 Subject: [PATCH 112/306] IsoApplet: clear memory after prkey import. Private key import via plain APDUs is dangerous and not recommended anyway, but clearing the apdu buffer does not hurt anyone. --- src/libopensc/card-isoApplet.c | 51 +++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index de8256cf..3fe763a3 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -748,19 +748,24 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t /* Write inner tags. */ /* p */ r = sc_asn1_put_tag(0x92, args->privkey.rsa.p.value, args->privkey.rsa.p.len, p, sizeof(sbuf) - (p - sbuf), &p); - LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + if(r < 0) + goto out; /* q */ r = sc_asn1_put_tag(0x93, args->privkey.rsa.q.value, args->privkey.rsa.q.len, p, sizeof(sbuf) - (p - sbuf), &p); - LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + if(r < 0) + goto out; /* 1/q mod p */ r = sc_asn1_put_tag(0x94, args->privkey.rsa.iqmp.value, args->privkey.rsa.iqmp.len, p, sizeof(sbuf) - (p - sbuf), &p); - LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + if(r < 0) + goto out; /* d mod (p-1) */ r = sc_asn1_put_tag(0x95, args->privkey.rsa.dmp1.value, args->privkey.rsa.dmp1.len, p, sizeof(sbuf) - (p - sbuf), &p); - LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + if(r < 0) + goto out; /* d mod (q-1) */ r = sc_asn1_put_tag(0x96, args->privkey.rsa.dmq1.value, args->privkey.rsa.dmq1.len, p, sizeof(sbuf) - (p - sbuf), &p); - LOG_TEST_RET(card->ctx, r, "Error handling TLV."); + if(r < 0) + goto out; /* Send to card, using chaining or extended APDUs. */ sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDB, 0x3F, 0xFF); @@ -773,11 +778,16 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t apdu.flags |= SC_APDU_FLAGS_CHAINING; } r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed."); + if(r < 0) + goto out; r = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_RET(card->ctx, r, "Card returned error."); + if(r < 0) + goto out; - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + r = SC_SUCCESS; +out: + sc_mem_clear(sbuf, sizeof(sbuf)); + LOG_FUNC_RETURN(card->ctx, r); } /* @@ -854,9 +864,14 @@ isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t * /* Write inner tags. */ r = isoApplet_put_ec_params(card, &args->privkey.ec.params, p, sizeof(sbuf) - (p - sbuf), &p); - LOG_TEST_RET(card->ctx, r, "Error composing EC params."); + if(r < 0) + { + sc_log(card->ctx, "Error composing EC params."); + goto out; + } r = sc_asn1_put_tag(0x88, args->privkey.ec.privateD.value, args->privkey.ec.privateD.len, p, sizeof(sbuf) - (p - sbuf), &p); - LOG_TEST_RET(card->ctx, r, "Error in handling TLV."); + if(r < 0) + goto out; /* Send to card. */ sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDB, 0x3F, 0xFF); @@ -864,7 +879,11 @@ isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t * apdu.datalen = p - sbuf; apdu.data = sbuf; r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); + if(r < 0) + { + sc_log(card->ctx, "APDU transmit failed"); + goto out; + } r = sc_check_sw(card, apdu.sw1, apdu.sw2); if(apdu.sw1 == 0x6D && apdu.sw2 == 0x00) @@ -872,10 +891,16 @@ isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t * sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported." "If you are using an older applet version and are trying to import keys, please update your applet first."); } - LOG_TEST_RET(card->ctx, r, "Card returned error"); + if(r < 0) + { + sc_log(card->ctx, "Card returned error"); + goto out; + } + r = SC_SUCCESS; +out: + sc_mem_clear(sbuf, sizeof(sbuf)); LOG_FUNC_RETURN(card->ctx, r); - } /* From 43fa99c0f2943fc86a241501919bba3491a8c1f7 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 28 Nov 2014 18:14:24 +0100 Subject: [PATCH 113/306] IsoApplet: Move the key gen debug info to the right places --- src/libopensc/card-isoApplet.c | 60 +++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 3fe763a3..1b500007 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -166,7 +166,7 @@ isoApplet_match_card(sc_card_t *card) if(rbuf[1] != ISOAPPLET_API_VERSION_MINOR) { sc_log(card->ctx, "IsoApplet: Mismatching minor API version. Proceeding anyway. " - "API versions: Driver (%02X-%02X), applet (%02X-%02X)." + "API versions: Driver (%02X-%02X), applet (%02X-%02X). " "Please update accordingly whenever possible.", ISOAPPLET_API_VERSION_MAJOR, ISOAPPLET_API_VERSION_MINOR, rbuf[0], rbuf[1]); } @@ -545,13 +545,6 @@ isoApplet_ctl_generate_key(sc_card_t *card, sc_cardctl_isoApplet_genkey_t *args) LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) - { - sc_log(card->ctx, "Key generation not supported by the card with that particular key type." - "Your card may not support the specified algorithm used by the applet / specified by you." - "In most cases, this happens when trying to generate EC keys not supported by your java card." - "In this case, look for supported field lengths and whether FP and/or F2M are supported."); - } LOG_TEST_RET(card->ctx, r, "Card returned error"); @@ -591,6 +584,13 @@ isoApplet_ctl_generate_key(sc_card_t *card, sc_cardctl_isoApplet_genkey_t *args) LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) + { + sc_log(card->ctx, "Key generation not supported by the card with that particular key type. " + "Your card may not support the specified algorithm used by the applet / specified by you. " + "In most cases, this happens when trying to generate EC keys not supported by your java card. " + "In this case, look for supported field lengths and whether FP and/or F2M are supported."); + } LOG_TEST_RET(card->ctx, r, "Card returned error"); /* Parse the public key / response. */ @@ -781,6 +781,20 @@ isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t if(r < 0) goto out; r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) + { + sc_log(card->ctx, "Key import not supported by the card with that particular key type. " + "Your card may not support the specified algorithm used by the applet / specified by you. " + "In most cases, this happens when trying to import EC keys not supported by your java card. " + "In this case, look for supported field lengths and whether FP and/or F2M are supported. " + "If you tried to import a private RSA key, check the key length."); + } + if(apdu.sw1 == 0x69 && apdu.sw2 == 0x00) + { + sc_log(card->ctx, "Key import not allowed by the applet's security policy. " + "If you want to allow key import, set DEF_PRIVATE_KEY_IMPORT_ALLOWED in the IsoApplet," + " rebuild and reinstall the applet."); + } if(r < 0) goto out; @@ -888,9 +902,23 @@ isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t * r = sc_check_sw(card, apdu.sw1, apdu.sw2); if(apdu.sw1 == 0x6D && apdu.sw2 == 0x00) { - sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported." + sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported. " "If you are using an older applet version and are trying to import keys, please update your applet first."); } + else if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) + { + sc_log(card->ctx, "Key import not supported by the card with that particular key type. " + "Your card may not support the specified algorithm used by the applet / specified by you. " + "In most cases, this happens when trying to import EC keys not supported by your java card. " + "In this case, look for supported field lengths and whether FP and/or F2M are supported. " + "If you tried to import a private RSA key, check the key length."); + } + else if(apdu.sw1 == 0x69 && apdu.sw2 == 0x00) + { + sc_log(card->ctx, "Key import not allowed by the applet's security policy. " + "If you want to allow key import, set DEF_PRIVATE_KEY_IMPORT_ALLOWED in the IsoApplet," + " rebuild and reinstall the applet."); + } if(r < 0) { sc_log(card->ctx, "Card returned error"); @@ -950,20 +978,6 @@ isoApplet_ctl_import_key(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *arg LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed"); r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81) - { - sc_log(card->ctx, "Key import not supported by the card with that particular key type." - "Your card may not support the specified algorithm used by the applet / specified by you." - "In most cases, this happens when trying to import EC keys not supported by your java card." - "In this case, look for supported field lengths and whether FP and/or F2M are supported." - "If you tried to import a private RSA key, check the key length."); - } - if(apdu.sw1 == 0x69 && apdu.sw2 == 0x00) - { - sc_log(card->ctx, "Key import not allowed by the applet's security policy." - "If you want to allow key import, set DEF_PRIVATE_KEY_IMPORT_ALLOWED in the IsoApplet," - " rebuild and reinstall the applet."); - } LOG_TEST_RET(card->ctx, r, "Card returned error"); From 5628a06353e34c5462b132a9f288a438204d52bd Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 28 Nov 2014 19:06:21 +0100 Subject: [PATCH 114/306] IsoApplet: Align comments with spaces instead of tabs Better view with tabstop=8. --- src/libopensc/card-isoApplet.c | 130 +++++++++++++++--------------- src/pkcs15init/pkcs15-isoApplet.c | 39 ++++----- 2 files changed, 85 insertions(+), 84 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 1b500007..4ed6aced 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -70,16 +70,16 @@ static struct sc_card_driver isoApplet_drv = * SELECT an applet on the smartcard. (Not in the emulated filesystem.) * The response will be written to resp. * - * @param[in] card - * @param[in] aid The applet ID. - * @param[in] aid_len The legth of aid. - * @param[out] resp The response of the applet upon selection. - * @param[in,out] resp_len In: The buffer size of resp. Out: The length of the response. + * @param[in] card + * @param[in] aid The applet ID. + * @param[in] aid_len The legth of aid. + * @param[out] resp The response of the applet upon selection. + * @param[in,out] resp_len In: The buffer size of resp. Out: The length of the response. * - * @return SC_SUCCESS: The applet is present and could be selected. - * any other: Transmit failure or the card returned an error. - * The card will return an error when the applet is - * not present. + * @return SC_SUCCESS: The applet is present and could be selected. + * any other: Transmit failure or the card returned an error. + * The card will return an error when the applet is + * not present. */ static int isoApplet_select_applet(sc_card_t *card, const u8 *aid, const size_t aid_len, u8 *resp, size_t *resp_len) @@ -232,8 +232,8 @@ isoApplet_init(sc_card_t *card) * * @param entry The OpenSC ACL entry. * - * @return The security condition byte. No restriction (0x00) - * if unknown operation. + * @return The security condition byte. No restriction (0x00) + * if unknown operation. */ static u8 isoApplet_acl_to_security_condition_byte(const sc_acl_entry_t *entry) @@ -267,8 +267,8 @@ isoApplet_acl_to_security_condition_byte(const sc_acl_entry_t *entry) * Note: IsoApplet currently only supports a "onepin" option. * * Format of the sec_attr: 8 Bytes: - * 7 - ISO 7816-4 table 16 or 17 - * 6 to 0 - ISO 7816-4 table 20 + * 7 - ISO 7816-4 table 16 or 17 + * 6 to 0 - ISO 7816-4 table 20 */ static int isoApplet_create_file(sc_card_t *card, sc_file_t *file) @@ -284,34 +284,34 @@ isoApplet_create_file(sc_card_t *card, sc_file_t *file) if(file->type == SC_FILE_TYPE_DF) { - const int df_idx[8] = /* These are the SC operations. */ + const int df_idx[8] = /* These are the SC operations. */ { 0, /* Reserved. */ - SC_AC_OP_DELETE_SELF, //b6 - SC_AC_OP_LOCK, //b5 - SC_AC_OP_ACTIVATE, //b4 - SC_AC_OP_DEACTIVATE, //b3 - SC_AC_OP_CREATE_DF, //b2 - SC_AC_OP_CREATE_EF, //b1 - SC_AC_OP_DELETE //b0 + SC_AC_OP_DELETE_SELF, /* b6 */ + SC_AC_OP_LOCK, /* b5 */ + SC_AC_OP_ACTIVATE, /* b4 */ + SC_AC_OP_DEACTIVATE, /* b3 */ + SC_AC_OP_CREATE_DF, /* b2 */ + SC_AC_OP_CREATE_EF, /* b1 */ + SC_AC_OP_DELETE /* b0 */ }; for(i=0; i<8; i++) { idx[i] = df_idx[i]; } } - else //EF + else /* EF */ { const int ef_idx[8] = { 0, /* Reserved. */ - SC_AC_OP_DELETE_SELF, //b6 - SC_AC_OP_LOCK, //b5 - SC_AC_OP_ACTIVATE, //b4 - SC_AC_OP_DEACTIVATE, //b3 - SC_AC_OP_WRITE, //b2 - SC_AC_OP_UPDATE, //b1 - SC_AC_OP_READ //b0 + SC_AC_OP_DELETE_SELF, /* b6 */ + SC_AC_OP_LOCK, /* b5 */ + SC_AC_OP_ACTIVATE, /* b4 */ + SC_AC_OP_DEACTIVATE, /* b3 */ + SC_AC_OP_WRITE, /* b2 */ + SC_AC_OP_UPDATE, /* b1 */ + SC_AC_OP_READ /* b0 */ }; for(i=0; i<8; i++) { @@ -341,9 +341,9 @@ isoApplet_create_file(sc_card_t *card, sc_file_t *file) * and the saByte (Encoded according to IsoApplet FCI proprietary security * information, see also ISO 7816-4 table 20). * - * @param[in,out] file - * @param[in] operation The OpenSC operation. - * @param[in] saByte The security condition byte returned by the applet. + * @param[in,out] file + * @param[in] operation The OpenSC operation. + * @param[in] saByte The security condition byte returned by the applet. */ static int isoApplet_add_sa_to_acl(sc_file_t *file, unsigned int operation, u8 saByte) @@ -446,19 +446,19 @@ isoApplet_process_fci(sc_card_t *card, sc_file_t *file, * @brief Encode the EC parameters as a concatenation of TLV enrties. * * The format is: - * 81 - prime - * 82 - coefficient A - * 83 - coefficient B - * 84 - base point G - * 85 - order - * 87 - cofactor + * 81 - prime + * 82 - coefficient A + * 83 - coefficient B + * 84 - base point G + * 85 - order + * 87 - cofactor * - * @param[in] card - * @param[in] params The ECparameters containing the information of the curve. - * @param[out] out The array the encoded parameters are written to. - * @param[in] out_len The size of out - * @param[out] ptr A pointer pointing to the end of the parameters in out - * (the first untouched byte behind the parameters). + * @param[in] card + * @param[in] params The ECparameters containing the information of the curve. + * @param[out] out The array the encoded parameters are written to. + * @param[in] out_len The size of out + * @param[out] ptr A pointer pointing to the end of the parameters in out + * (the first untouched byte behind the parameters). */ static int isoApplet_put_ec_params(sc_card_t *card, sc_cardctl_isoApplet_ec_parameters_t *params, u8 *out, size_t out_len, u8 **ptr) @@ -551,11 +551,11 @@ isoApplet_ctl_generate_key(sc_card_t *card, sc_cardctl_isoApplet_genkey_t *args) /* GENERATE ASYMMETRIC KEY PAIR * We use a larger buffer here, even if the card does not support extended apdus. * There are two cases: - * 1) The card can do ext. apdus: The data fits in one apdu. - * 2) The card can't do ext. apdus: sc_transmit_apdu will handle that - the - * card will send SW_BYTES_REMAINING, OpenSC will automaticall do a - * GET RESPONSE to get the remaining data, and will append it to the data - * buffer. */ + * 1) The card can do ext. apdus: The data fits in one apdu. + * 2) The card can't do ext. apdus: sc_transmit_apdu will handle that - the + * card will send SW_BYTES_REMAINING, OpenSC will automaticall do a + * GET RESPONSE to get the remaining data, and will append it to the data + * buffer. */ if(args->algorithm_ref == SC_ISOAPPLET_ALG_REF_EC_GEN) { sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x46, 0x00, 0x00); @@ -694,10 +694,10 @@ isoApplet_ctl_generate_key(sc_card_t *card, sc_cardctl_isoApplet_genkey_t *args) * one RSA field (P, Q, etc.). The first apdu must contain the outer tag (7F48). * * @param card - * @param rsa The RSA private key to import. + * @param rsa The RSA private key to import. * - * @return SC_ERROR_INVALID_ARGUMENTS: The RSA key does not contain CRT fields. - * other errors: Transmit errors / errors returned by card. + * @return SC_ERROR_INVALID_ARGUMENTS: The RSA key does not contain CRT fields. + * other errors: Transmit errors / errors returned by card. */ static int isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args) @@ -808,21 +808,21 @@ out: * @brief Use PUT DATA to import a private EC key. * * Format of transmitted data: - * 0xE0 - Private class, constructed encoding, number one. - * 0x81 - prime - * 0x82 - coefficient A - * 0x83 - coefficient B - * 0x84 - base point G - * 0x85 - order - * 0x87 - cofactor - * 0x88 - private D (private key) + * 0xE0 - Private class, constructed encoding, number one. + * 0x81 - prime + * 0x82 - coefficient A + * 0x83 - coefficient B + * 0x84 - base point G + * 0x85 - order + * 0x87 - cofactor + * 0x88 - private D (private key) * * @param card - * @param ec The EC private key to import. + * @param ec The EC private key to import. * - * @return SC_ERROR_INVALID_ARGUMENTS: Curve parameters or private component is missing. - * other errors: Transmit errors / errors returned by card. - * ASN1 errors. + * @return SC_ERROR_INVALID_ARGUMENTS: Curve parameters or private component is missing. + * other errors: Transmit errors / errors returned by card. + * ASN1 errors. */ static int isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args) @@ -1088,7 +1088,7 @@ isoApplet_set_security_env(sc_card_t *card, LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported algorithm."); } - *p++ = 0x80; /* algorithm reference */ + *p++ = 0x80; /* algorithm reference */ *p++ = 0x01; *p++ = drvdata->sec_env_alg_ref; } diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index 971f9847..a4e064d7 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -269,9 +269,9 @@ isoApplet_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t /* * @brief Get the curve parameters associated with the curve specified by an OID. * - * @param[in] oid The DER encoded OID of the curve. - * @param[in] oid_len The length of oid. - * @param[out] curve_out The ec_curve containing the set of parameters. + * @param[in] oid The DER encoded OID of the curve. + * @param[in] oid_len The length of oid. + * @param[out] curve_out The ec_curve containing the set of parameters. * * @returns SC_SUCCESS: If the curve was found. * SC_ERROR_INVALID_ARGUMENTS: If named_curve was null or the curve @@ -305,13 +305,13 @@ isoApplet_get_curve(u8 *oid, size_t oid_len, const struct ec_curve **curve_out) * A MANAGE SECURITY ENVIRONMENT apdu must have been sent before. * This function uses card_ctl to access the card-isoApplet driver. * - * @param[in] key_info - * @param[in] card - * @param[in] pubkey The public key of the generated key pair - * returned by the card. + * @param[in] key_info + * @param[in] card + * @param[in] pubkey The public key of the generated key pair + * returned by the card. * * @return SC_ERROR_INVALID_ARGURMENTS: Invalid key length. - * SC_ERROR_OUT_OF_MEMORY + * SC_ERROR_OUT_OF_MEMORY */ static int isoApplet_generate_key_rsa(sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, @@ -333,7 +333,8 @@ isoApplet_generate_key_rsa(sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, } /* Generate the key. - * Note: key size is not explicitly passed to the card. It assumes 2048 along with the algorithm reference. */ + * Note: key size is not explicitly passed to the card. + * It assumes 2048 along with the algorithm reference. */ memset(&args, 0, sizeof(args)); args.algorithm_ref = SC_ISOAPPLET_ALG_REF_RSA_GEN_2048; args.priv_key_ref = key_info->key_reference; @@ -393,16 +394,16 @@ err: * A MANAGE SECURITY ENVIRONMENT apdu must have been sent before. * This function uses card_ctl to access the card-isoApplet driver. * - * @param[in] key_info - * @param[in] card - * @param[in/out] pubkey The public key of the generated key pair - * returned by the card. + * @param[in] key_info + * @param[in] card + * @param[in/out] pubkey The public key of the generated key pair + * returned by the card. * - * @return SC_ERROR_INVALID_ARGURMENTS: Invalid key length or curve. - * SC_ERROR_OUT_OF_MEMORY - * SC_ERROR_INCOMPATIBLE_KEY: The data returned by the card - * was unexpected and can not be - * handled. + * @return SC_ERROR_INVALID_ARGURMENTS: Invalid key length or curve. + * SC_ERROR_OUT_OF_MEMORY + * SC_ERROR_INCOMPATIBLE_KEY: The data returned by the card + * was unexpected and can not be + * handled. */ static int isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *card, @@ -434,7 +435,7 @@ isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *car /* Generate the key. * Note: The field size is not explicitly passed to the card. - * As we only support FP curves, the field length can be calculated from any parameter. */ + * As we only support FP curves, the field length can be calculated from any parameter. */ memset(&args, 0, sizeof(args)); args.pubkey.ec.params.prime.value = curve->prime.value; From 44d724b012484b751bb24d40c20196ff29105242 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Sat, 29 Nov 2014 15:43:23 +0100 Subject: [PATCH 115/306] IsoApplet: fix more (comment) alignment issues with tabstop=8 --- src/pkcs15init/pkcs15-isoApplet.c | 78 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index a4e064d7..c70a0f17 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -682,16 +682,16 @@ isoApplet_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_ { LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Only CRT RSA keys may be imported."); } - args.privkey.rsa.p.value = key->u.rsa.p.data; - args.privkey.rsa.p.len = key->u.rsa.p.len; - args.privkey.rsa.q.value = key->u.rsa.q.data; - args.privkey.rsa.q.len = key->u.rsa.q.len; - args.privkey.rsa.iqmp.value = key->u.rsa.iqmp.data; - args.privkey.rsa.iqmp.len = key->u.rsa.iqmp.len; - args.privkey.rsa.dmp1.value = key->u.rsa.dmp1.data; - args.privkey.rsa.dmp1.len = key->u.rsa.dmp1.len; - args.privkey.rsa.dmq1.value = key->u.rsa.dmq1.data; - args.privkey.rsa.dmq1.len = key->u.rsa.dmq1.len; + args.privkey.rsa.p.value = key->u.rsa.p.data; + args.privkey.rsa.p.len = key->u.rsa.p.len; + args.privkey.rsa.q.value = key->u.rsa.q.data; + args.privkey.rsa.q.len = key->u.rsa.q.len; + args.privkey.rsa.iqmp.value = key->u.rsa.iqmp.data; + args.privkey.rsa.iqmp.len = key->u.rsa.iqmp.len; + args.privkey.rsa.dmp1.value = key->u.rsa.dmp1.data; + args.privkey.rsa.dmp1.len = key->u.rsa.dmp1.len; + args.privkey.rsa.dmq1.value = key->u.rsa.dmq1.data; + args.privkey.rsa.dmq1.len = key->u.rsa.dmq1.len; break; case SC_PKCS15_TYPE_PRKEY_EC: @@ -705,20 +705,20 @@ isoApplet_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_ } r = isoApplet_get_curve(key->u.ec.params.der.value, key->u.ec.params.der.len, &curve); LOG_TEST_RET(card->ctx, r, "EC key generation failed: Unsupported curve"); - args.privkey.ec.params.prime.value = curve->prime.value; - args.privkey.ec.params.prime.len = curve->prime.len; - args.privkey.ec.params.coefficientA.value = curve->coefficientA.value; - args.privkey.ec.params.coefficientA.len = curve->coefficientA.len; - args.privkey.ec.params.coefficientB.value = curve->coefficientB.value; - args.privkey.ec.params.coefficientB.len = curve->coefficientB.len; - args.privkey.ec.params.basePointG.value = curve->basePointG.value; - args.privkey.ec.params.basePointG.len = curve->basePointG.len; - args.privkey.ec.params.order.value = curve->order.value; - args.privkey.ec.params.order.len = curve->order.len; - args.privkey.ec.params.coFactor.value = curve->coFactor.value; - args.privkey.ec.params.coFactor.len = curve->coFactor.len; - args.privkey.ec.privateD.value = key->u.ec.privateD.data; - args.privkey.ec.privateD.len = key->u.ec.privateD.len; + args.privkey.ec.params.prime.value = curve->prime.value; + args.privkey.ec.params.prime.len = curve->prime.len; + args.privkey.ec.params.coefficientA.value = curve->coefficientA.value; + args.privkey.ec.params.coefficientA.len = curve->coefficientA.len; + args.privkey.ec.params.coefficientB.value = curve->coefficientB.value; + args.privkey.ec.params.coefficientB.len = curve->coefficientB.len; + args.privkey.ec.params.basePointG.value = curve->basePointG.value; + args.privkey.ec.params.basePointG.len = curve->basePointG.len; + args.privkey.ec.params.order.value = curve->order.value; + args.privkey.ec.params.order.len = curve->order.len; + args.privkey.ec.params.coFactor.value = curve->coFactor.value; + args.privkey.ec.params.coFactor.len = curve->coFactor.len; + args.privkey.ec.privateD.value = key->u.ec.privateD.data; + args.privkey.ec.privateD.len = key->u.ec.privateD.len; } break; @@ -739,21 +739,21 @@ isoApplet_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_ static struct sc_pkcs15init_operations sc_pkcs15init_isoApplet_operations = { - NULL, /* erase_card */ - NULL, /* init_card */ - isoApplet_create_dir, /* create_dir */ - NULL, /* create_domain */ - isoApplet_select_pin_reference, /* pin_reference*/ - isoApplet_create_pin, /* create_pin */ - isoApplet_select_key_reference, /* key_reference */ - isoApplet_create_key, /* create_key */ - isoApplet_store_key, /* store_key */ - isoApplet_generate_key, /* generate_key */ - NULL, NULL, /* encode private/public key */ - NULL, /* finalize */ - NULL, /* delete_object */ - NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */ - NULL, /* sanity_check*/ + NULL, /* erase_card */ + NULL, /* init_card */ + isoApplet_create_dir, /* create_dir */ + NULL, /* create_domain */ + isoApplet_select_pin_reference, /* pin_reference*/ + isoApplet_create_pin, /* create_pin */ + isoApplet_select_key_reference, /* key_reference */ + isoApplet_create_key, /* create_key */ + isoApplet_store_key, /* store_key */ + isoApplet_generate_key, /* generate_key */ + NULL, NULL, /* encode private/public key */ + NULL, /* finalize */ + NULL, /* delete_object */ + NULL, NULL, NULL, NULL, NULL, /* pkcs15init emulation */ + NULL, /* sanity_check*/ }; struct From da05fa2a473354ab8beb6edff89c9dc84d102148 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Tue, 3 Feb 2015 21:59:28 +0100 Subject: [PATCH 116/306] IsoApplet: try to fix EC parameters when importing private keys from file --- src/pkcs15init/pkcs15-isoApplet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index c70a0f17..637ba976 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -699,9 +699,9 @@ isoApplet_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_ const struct ec_curve *curve = NULL; args.algorithm_ref = SC_ISOAPPLET_ALG_REF_EC_GEN; - if(!key->u.ec.params.named_curve) - { - LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Unspecified curve / no curve name."); + if(key->u.ec.params.der.len == 0 || key->u.ec.params.der.value == NULL) { + r = sc_pkcs15_fix_ec_parameters(card->ctx, &key->u.ec.params); + LOG_TEST_RET(card->ctx, r, "EC key storing failed: Unkown curve."); } r = isoApplet_get_curve(key->u.ec.params.der.value, key->u.ec.params.der.len, &curve); LOG_TEST_RET(card->ctx, r, "EC key generation failed: Unsupported curve"); From 3312c1e2b9967942e04f498c7a84b939ec5f8b96 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Tue, 17 Feb 2015 23:24:42 +0100 Subject: [PATCH 117/306] IsoApplet: install isoApplet.profile on windows --- win32/OpenSC.wxs.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index eb793c11..8559708b 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -180,6 +180,9 @@ + + + @@ -245,6 +248,7 @@ + From a9d43af4bf08d46b369bf4f59ad892005e325085 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Thu, 19 Feb 2015 21:10:38 +0100 Subject: [PATCH 118/306] IsoApplet: use a buffer large enough when generating EC keys larger than 320 bit --- src/libopensc/card-isoApplet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 4ed6aced..1608035e 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -511,7 +511,7 @@ isoApplet_ctl_generate_key(sc_card_t *card, sc_cardctl_isoApplet_genkey_t *args) int r; sc_apdu_t apdu; u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; u8 *p; const u8 *inner_tag_value; const u8 *outer_tag_value; From 59eeacb74b3971c0f510230feba01516c5e8e9d1 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 20 Feb 2015 22:07:49 +0100 Subject: [PATCH 119/306] IsoApplet: react to removal of sc_pkcs15_ec_parameters in fa923831f8e8073f0b57ea492c9e2e93f661a373 --- src/pkcs15init/pkcs15-isoApplet.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index 637ba976..6f3861e6 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -411,10 +411,10 @@ isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *car { int r; const struct ec_curve *curve = NULL; - struct sc_ec_params *alg_id_params = NULL; + struct sc_ec_parameters *alg_id_params = NULL; sc_cardctl_isoApplet_genkey_t args; - const struct sc_pkcs15_ec_parameters *info_ecp = - (struct sc_pkcs15_ec_parameters *) key_info->params.data; + const struct sc_ec_parameters *info_ecp = + (struct sc_ec_parameters *) key_info->params.data; LOG_FUNC_CALLED(card->ctx); @@ -481,14 +481,14 @@ isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *car r = SC_ERROR_OUT_OF_MEMORY; goto out; } - alg_id_params->der_len = curve->oid.len; - alg_id_params->der = malloc(alg_id_params->der_len); - if(!alg_id_params->der) + alg_id_params->der.len = curve->oid.len; + alg_id_params->der.value = malloc(alg_id_params->der.len); + if(!alg_id_params->der.value) { r = SC_ERROR_OUT_OF_MEMORY; goto out; } - memcpy(alg_id_params->der, curve->oid.value, curve->oid.len); + memcpy(alg_id_params->der.value, curve->oid.value, curve->oid.len); alg_id_params->type = 1; /* named curve */ pubkey->alg_id = malloc(sizeof(*pubkey->alg_id)); @@ -511,14 +511,14 @@ isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *car memcpy(pubkey->u.ec.ecpointQ.value, args.pubkey.ec.ecPointQ.value, args.pubkey.ec.ecPointQ.len); /* The OID is also written to the pubkey->u.ec.params */ - pubkey->u.ec.params.der.value = malloc(alg_id_params->der_len); + pubkey->u.ec.params.der.value = malloc(alg_id_params->der.len); if(!pubkey->u.ec.params.der.value) { r = SC_ERROR_OUT_OF_MEMORY; goto out; } - memcpy(pubkey->u.ec.params.der.value, alg_id_params->der, alg_id_params->der_len); - pubkey->u.ec.params.der.len = alg_id_params->der_len; + memcpy(pubkey->u.ec.params.der.value, alg_id_params->der.value, alg_id_params->der.len); + pubkey->u.ec.params.der.len = alg_id_params->der.len; r = sc_pkcs15_fix_ec_parameters(card->ctx, &pubkey->u.ec.params); out: if(args.pubkey.ec.ecPointQ.value) @@ -549,10 +549,10 @@ out: } if(r < 0 && alg_id_params) { - if(alg_id_params->der) + if(alg_id_params->der.value) { - free(alg_id_params->der); - alg_id_params->der = NULL; + free(alg_id_params->der.value); + alg_id_params->der.value = NULL; } free(alg_id_params); pubkey->alg_id->params = NULL; From 1aeebdaf1c0ad1143329eac62aaf75cf3f0fe055 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 20 Feb 2015 22:56:23 +0100 Subject: [PATCH 120/306] IsoApplet: react to changes of _sc_card_add_ec_alg() in fa923831f8e8073f0b57ea492c9e2e93f661a373 --- src/libopensc/card-isoApplet.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 1608035e..7ac07839 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -203,11 +203,11 @@ isoApplet_init(sc_card_t *card) flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; ext_flags |= SC_ALGORITHM_EXT_EC_F_P; - _sc_card_add_ec_alg(card, 192, flags, ext_flags); - _sc_card_add_ec_alg(card, 224, flags, ext_flags); - _sc_card_add_ec_alg(card, 256, flags, ext_flags); - _sc_card_add_ec_alg(card, 320, flags, ext_flags); - _sc_card_add_ec_alg(card, 384, flags, ext_flags); + _sc_card_add_ec_alg(card, 192, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 224, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 320, flags, ext_flags, NULL); + _sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL); /* RSA */ flags = 0; From 85d16fbc57170bf2177e0d29d7c70993fb01d27c Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Tue, 17 Feb 2015 20:23:21 +0100 Subject: [PATCH 121/306] IsoApplet: use helper function sc_asn1_sig_value_sequence_to_rs() introduced in #381 --- src/libopensc/card-isoApplet.c | 54 +++++++--------------------------- 1 file changed, 10 insertions(+), 44 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 7ac07839..1e0694a0 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -1162,11 +1162,7 @@ isoApplet_compute_signature(struct sc_card *card, u8 *out, size_t outlen) { struct isoApplet_drv_data *drvdata = DRVDATA(card); - const u8 * p; int r; - size_t len; - size_t xlen; - size_t ylen; LOG_FUNC_CALLED(card->ctx); @@ -1183,48 +1179,18 @@ isoApplet_compute_signature(struct sc_card *card, * which will be added again later.*/ if(drvdata->sec_env_alg_ref == ISOAPPLET_ALG_REF_ECDSA) { - len = r; - p = out; - if(*p++ != (SC_ASN1_TAG_SEQUENCE|SC_ASN1_TAG_CONSTRUCTED)) - { - LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); - } - len = *p++; - if(len > outlen - (p - out)) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); + u8* p = NULL; + size_t len; - /* X */ - if(*p++ != SC_ASN1_TAG_INTEGER) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); - xlen = *p++; - if(xlen > outlen - (p - out)) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); - /* Java Cards might return a leading zero, - * which needs to be stripped when not using the ASN1 structural information. */ - if(*p == 0x00 && (xlen == 192/8+1 || xlen == 224/8+1 || xlen == 256/8+1 || xlen == 320/8+1 || xlen == 384/8+1)) - { - p++; - xlen--; + r = sc_asn1_sig_value_sequence_to_rs(card->ctx, out, r, &p, &len); + if(r < 0) { + if(p) + free(p); + LOG_FUNC_RETURN(card->ctx, r); } - memmove(out, p, xlen); - p += xlen; - - /* Y */ - if(*p++ != SC_ASN1_TAG_INTEGER) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); - ylen = *p++; - if(ylen > outlen - (p - out)) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); - /* Java Cards might return a leading zero, - * which needs to be stripped when not using the ASN1 structural information. */ - if(*p == 0x00 && (ylen == 192/8+1 || ylen == 224/8+1 || ylen == 256/8+1 || ylen == 320/8+1 || ylen == 384/8+1)) - { - p++; - ylen--; - } - memmove(out+xlen, p, ylen); - - r = xlen + ylen; + memcpy(out, p, len); + r = len; + free(p); } LOG_FUNC_RETURN(card->ctx, r); } From 74aeb8c92325ab7730f32712144c79c0ffee98bb Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Sun, 22 Feb 2015 23:08:18 +0100 Subject: [PATCH 122/306] IsoApplet: register supported EC curve *per curve* --- src/libopensc/card-isoApplet.c | 49 ++++++++++++++++++++++++------- src/pkcs15init/pkcs15-isoApplet.c | 2 +- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 1e0694a0..131ac08f 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -21,12 +21,13 @@ #include #include -#include "internal.h" -#include "opensc.h" -#include "cardctl.h" -#include "log.h" #include "asn1.h" +#include "cardctl.h" +#include "internal.h" +#include "log.h" +#include "opensc.h" #include "pkcs15.h" +#include "types.h" #define ISOAPPLET_ALG_REF_ECDSA 0x21 #define ISOAPPLET_ALG_REF_RSA_PAD_PKCS1 0x11 @@ -182,9 +183,11 @@ isoApplet_match_card(sc_card_t *card) static int isoApplet_init(sc_card_t *card) { + int r; unsigned long flags = 0; unsigned long ext_flags = 0; struct isoApplet_drv_data *drvdata; + struct sc_object_id curve_oid; LOG_FUNC_CALLED(card->ctx); @@ -197,17 +200,43 @@ isoApplet_init(sc_card_t *card) card->drv_data = drvdata; card->cla = 0x00; - /* ECDSA */ + /* ECDSA + * Curves supported by the pkcs15-init driver are indicated per curve. This + * should be kept in sync with the explicit parameters in the pkcs15-init + * driver. */ flags = 0; flags |= SC_ALGORITHM_ECDSA_RAW; flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; ext_flags |= SC_ALGORITHM_EXT_EC_F_P; - _sc_card_add_ec_alg(card, 192, flags, ext_flags, NULL); - _sc_card_add_ec_alg(card, 224, flags, ext_flags, NULL); - _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); - _sc_card_add_ec_alg(card, 320, flags, ext_flags, NULL); - _sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL); + /* secp192r1, prime192r1, ansiX9p192r1*/ + r = sc_format_oid(&curve_oid, "1.2.840.10045.3.1.1"); + LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); + _sc_card_add_ec_alg(card, 192, flags, ext_flags, &curve_oid); + /* prime256v1, secp256r1, ansiX9p256r1 */ + r = sc_format_oid(&curve_oid, "1.2.840.10045.3.1.7"); + LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); + _sc_card_add_ec_alg(card, 256, flags, ext_flags, &curve_oid); + /* secp384r1, prime384v1, ansiX9p384r1 */ + r = sc_format_oid(&curve_oid, "1.3.132.0.34"); + LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); + _sc_card_add_ec_alg(card, 384, flags, ext_flags, &curve_oid); + /* brainpoolP192r1 */ + r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.3"); + LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); + _sc_card_add_ec_alg(card, 192, flags, ext_flags, &curve_oid); + /* brainpoolP224r1 */ + r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.5"); + LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); + _sc_card_add_ec_alg(card, 224, flags, ext_flags, &curve_oid); + /* brainpoolP256r1 */ + r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.7"); + LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); + _sc_card_add_ec_alg(card, 256, flags, ext_flags, &curve_oid); + /* brainpoolP320r1 */ + r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.9"); + LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); + _sc_card_add_ec_alg(card, 320, flags, ext_flags, &curve_oid); /* RSA */ flags = 0; diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index 6f3861e6..b4095a85 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -105,7 +105,7 @@ static const struct ec_curve curves[] = { (unsigned char *) "\x64\x21\x05\x19\xE5\x9C\x80\xE7\x0F\xA7\xE9\xAB\x72\x24\x30\x49\xFE\xB8\xDE\xEC\xC1\x46\xB9\xB1", 24}, { (unsigned char *) "\x04\x18\x8D\xA8\x0E\xB0\x30\x90\xF6\x7C\xBF\x20\xEB\x43\xA1\x88\x00\xF4\xFF\x0A\xFD\x82\xFF\x10\x12\x07\x19\x2B\x95\xFF\xC8\xDA\x78\x63\x10\x11\xED\x6B\x24\xCD\xD5\x73\xF9\x77\xA1\x1E\x79\x48\x11", 49}, { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x99\xDE\xF8\x36\x14\x6B\xC9\xB1\xB4\xD2\x28\x31", 24}, - { (unsigned char *) "\x00\x01", 1} + { (unsigned char *) "\x00\x01", 2} }, { From 8cf99a93726e735e04ed2563f14e315a60a4a859 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Wed, 4 Mar 2015 19:20:12 +0100 Subject: [PATCH 123/306] asn1: fix error in EC signature encode helper The raw format of EC signature was invalid when 'r' and 's' had different length. https://github.com/OpenSC/OpenSC/pull/381#issuecomment-77016382 According to PKCS#11 v2.20: "If r and s have different octet length, the shorter of both must be padded with leading zero octets such that both have the same octet length." --- src/libopensc/asn1.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index bfbdaa94..ba4a0a16 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -1870,7 +1870,7 @@ sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, unsigned char *in, size struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE]; struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE]; unsigned char *r, *s; - size_t r_len, s_len; + size_t r_len, s_len, len; int rv; LOG_FUNC_CALLED(ctx); @@ -1884,16 +1884,18 @@ sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, unsigned char *in, size rv = sc_asn1_decode(ctx, asn1_sig_value, in, inlen, NULL, NULL); LOG_TEST_RET(ctx, rv, "ASN.1 decoding ECDSA-Sig-Value failed"); - sc_log(ctx, "r(%i): %s", r_len, sc_dump_hex(r, r_len)); - sc_log(ctx, "s(%i): %s", s_len, sc_dump_hex(s, s_len)); + len = r_len > s_len ? r_len : s_len; - *buf = malloc(r_len + s_len); + *buf = calloc(2 * len, 1); if (*buf == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); - memcpy(*buf, r, r_len); - memcpy(*buf + r_len, s, s_len); - *buflen = r_len + s_len; + memcpy(*buf + len - r_len, r, r_len); + memcpy(*buf + 2*len - s_len, s, s_len); + *buflen = 2 * len; + + sc_log(ctx, "r(%i): %s", len, sc_dump_hex(*buf, len)); + sc_log(ctx, "s(%i): %s", len, sc_dump_hex(*buf + len, len)); free(r); free(s); From 1123768ac3b722afe3a0d662967515c547530554 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Tue, 24 Feb 2015 18:13:53 +0100 Subject: [PATCH 124/306] libopensc: invalid 'free' and 'assign NULL' order --- src/libopensc/card.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index b0ae035f..25e36c22 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -112,9 +112,10 @@ static void sc_card_free(sc_card_t *card) free(ep.der.value); } } + free(card->algorithms); + card->algorithms = NULL; card->algorithm_count = 0; - free(card->algorithms); } if (card->cache.current_ef) From 31124ac4f906ba8a331bde47d23bc89757f1829f Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 1 Mar 2015 13:38:50 +0100 Subject: [PATCH 125/306] pkcs15init: allocate EC parameters --- src/libopensc/card.c | 25 +++++++++++++++++++++++++ src/libopensc/opensc.h | 9 +++++++++ src/pkcs15init/pkcs15-lib.c | 8 ++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 25e36c22..24d22d5b 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -1114,6 +1114,31 @@ void sc_print_cache(struct sc_card *card) { sc_print_path(&card->cache.current_df->path)); } +int sc_copy_ec_params(struct sc_ec_parameters *dst, struct sc_ec_parameters *src) +{ + if (!dst || !src) + return SC_ERROR_INVALID_ARGUMENTS; + + memset(dst, 0, sizeof(*dst)); + if (src->named_curve) { + dst->named_curve = strdup(src->named_curve); + if (!dst->named_curve) + return SC_ERROR_OUT_OF_MEMORY; + } + dst->id = src->id; + if (src->der.value && src->der.len) { + dst->der.value = malloc(src->der.len); + if (!dst->der.value) + return SC_ERROR_OUT_OF_MEMORY; + memcpy(dst->der.value, src->der.value, src->der.len); + dst->der.len = src->der.len; + } + src->type = dst->type; + src->field_length = dst->field_length; + + return SC_SUCCESS; +} + scconf_block * sc_match_atr_block(sc_context_t *ctx, struct sc_card_driver *driver, struct sc_atr *atr) { diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 42d8bf10..63298adb 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -1315,6 +1315,15 @@ unsigned sc_crc32(unsigned char *value, size_t len); */ void sc_remote_data_init(struct sc_remote_data *rdata); + +/** + * Copy and allocate if needed EC parameters data + * @dst destination + * @src source + */ +int sc_copy_ec_params(struct sc_ec_parameters *, struct sc_ec_parameters *); + + struct sc_card_error { unsigned int SWs; int errorno; diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index cc655f6a..5d554ba4 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1314,10 +1314,14 @@ sc_pkcs15init_generate_key(struct sc_pkcs15_card *p15card, struct sc_profile *pr pubkey_args.usage = keygen_args->prkey_args.usage; pubkey_args.x509_usage = keygen_args->prkey_args.x509_usage; - if (keygen_args->prkey_args.key.algorithm == SC_ALGORITHM_GOSTR3410) + if (keygen_args->prkey_args.key.algorithm == SC_ALGORITHM_GOSTR3410) { pubkey_args.params.gost = keygen_args->prkey_args.params.gost; - else if (keygen_args->prkey_args.key.algorithm == SC_ALGORITHM_EC) + } + else if (keygen_args->prkey_args.key.algorithm == SC_ALGORITHM_EC) { pubkey_args.key.u.ec.params = keygen_args->prkey_args.key.u.ec.params; + r = sc_copy_ec_params(&pubkey_args.key.u.ec.params, &keygen_args->prkey_args.key.u.ec.params); + LOG_TEST_RET(ctx, r, "Cannot allocate EC parameters"); + } /* Generate the private key on card */ r = profile->ops->create_key(profile, p15card, object); From 6f6286de99a62ab0d2edf6023f39cfa8db139420 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Tue, 24 Feb 2015 17:38:39 +0100 Subject: [PATCH 126/306] pkcs11: generate EC key: use allocated EC params For internal use allocate and copy the EC params data from the caller's template, rather then use them directly as a pointer in internal public key data. --- src/pkcs11/framework-pkcs15.c | 2 +- src/pkcs11/misc.c | 24 ++++++++++++++++++++++++ src/pkcs11/sc-pkcs11.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index d3001658..c5809753 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -2766,7 +2766,7 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, struct sc_lv_data *der = &keygen_args.prkey_args.key.u.ec.params.der; der->len = sizeof(struct sc_object_id); - rv = attr_find_ptr(pPubTpl, ulPubCnt, CKA_EC_PARAMS, (void **)&der->value, &der->len); + rv = attr_find_and_allocate_ptr(pPubTpl, ulPubCnt, CKA_EC_PARAMS, (void **)&der->value, &der->len); if (rv != CKR_OK) { sc_unlock(p11card->card); return sc_to_cryptoki_error(rc, "C_GenerateKeyPair"); diff --git a/src/pkcs11/misc.c b/src/pkcs11/misc.c index 8aab05cc..a2422db4 100644 --- a/src/pkcs11/misc.c +++ b/src/pkcs11/misc.c @@ -251,6 +251,30 @@ CK_RV attr_find2(CK_ATTRIBUTE_PTR pTemp1, CK_ULONG ulCount1, return rv; } +CK_RV attr_find_and_allocate_ptr(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void **out, size_t *out_len) +{ + void *ptr; + size_t len; + CK_RV rv; + + if (!out || !out_len) + return CKR_ARGUMENTS_BAD; + len = *out_len; + + rv = attr_find_ptr(pTemplate, ulCount, type, &ptr, &len); + if (rv != CKR_OK) + return rv; + + *out = calloc(1, len); + if (*out == NULL) + return CKR_HOST_MEMORY; + + memcpy(*out, ptr, len); + *out_len = len; + + return CKR_OK; +} + CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void **ptr, size_t * sizep) { unsigned int n; diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 3783fde8..9bac0630 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -369,6 +369,7 @@ CK_RV attr_find(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void *, size_t *); CK_RV attr_find2(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void *, size_t *); CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void **, size_t *); +CK_RV attr_find_and_allocate_ptr(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void **, size_t *); CK_RV attr_find_var(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void *, size_t *); CK_RV attr_extract(CK_ATTRIBUTE_PTR, void *, size_t *); From 1739300657dfa6148f82c39b5a062bc679357649 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Thu, 5 Mar 2015 10:31:13 +0100 Subject: [PATCH 127/306] pkcs15: fix name of EC curve, add new ones --- src/libopensc/pkcs15-pubkey.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 16f01ade..8fbf418c 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1380,14 +1380,26 @@ static struct ec_curve_info { size_t size; } ec_curve_infos[] = { {"secp192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, - {"prime192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, + {"prime192v1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, + {"nistp192", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, {"ansiX9p192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, - {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + + {"secp224r1", "1.3.132.0.33", "06052b81040021", 224}, + {"nistp224", "1.3.132.0.33", "06052b81040021", 224}, + {"secp256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + {"nistp256", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, {"ansiX9p256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + {"secp384r1", "1.3.132.0.34", "06052B81040022", 384}, {"prime384v1", "1.3.132.0.34", "06052B81040022", 384}, + {"nistp384", "1.3.132.0.34", "06052B81040022", 384}, {"ansiX9p384r1", "1.3.132.0.34", "06052B81040022", 384}, + + {"secp521r1", "1.3.132.0.35", "06052B81040023", 521}, + {"nistp521", "1.3.132.0.35", "06052B81040023", 521}, + {"brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", "06092B2403030208010103", 192}, {"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224}, {"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256}, @@ -1449,8 +1461,10 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_ec_parameters *ecp if (!strcmp(ec_curve_infos[ii].oid_str, ecparams->named_curve)) break; } - if (!ec_curve_infos[ii].name) - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported named curve"); + if (!ec_curve_infos[ii].name) { + sc_log(ctx, "Named curve '%s' not supported", ecparams->named_curve); + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); + } rv = sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); LOG_TEST_RET(ctx, rv, "Invalid OID format"); From 2abe135f971aca7a3ecc231d10f96b5fddee078a Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 7 Mar 2015 21:36:16 +0100 Subject: [PATCH 128/306] asn1: re-fix error in EC signature encode helper see comment for https://github.com/OpenSC/OpenSC/commit/8cf99a93726e735e04ed2563f14e315a60a4a859 --- src/libopensc/asn1.c | 30 +++++++++++++++++------------- src/libopensc/asn1.h | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index ba4a0a16..1eeb2ef2 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -1865,15 +1865,18 @@ sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx, unsigned char *in, size int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, unsigned char *in, size_t inlen, - unsigned char **buf, size_t *buflen) + unsigned char *buf, size_t buflen) { struct sc_asn1_entry asn1_sig_value[C_ASN1_SIG_VALUE_SIZE]; struct sc_asn1_entry asn1_sig_value_coefficients[C_ASN1_SIG_VALUE_COEFFICIENTS_SIZE]; unsigned char *r, *s; - size_t r_len, s_len, len; + size_t r_len, s_len, halflen = buflen/2; int rv; LOG_FUNC_CALLED(ctx); + if (!buf || !buflen) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + sc_copy_asn1_entry(c_asn1_sig_value, asn1_sig_value); sc_format_asn1_entry(asn1_sig_value + 0, asn1_sig_value_coefficients, NULL, 0); @@ -1884,21 +1887,22 @@ sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, unsigned char *in, size rv = sc_asn1_decode(ctx, asn1_sig_value, in, inlen, NULL, NULL); LOG_TEST_RET(ctx, rv, "ASN.1 decoding ECDSA-Sig-Value failed"); - len = r_len > s_len ? r_len : s_len; + if (halflen < r_len || halflen < s_len) { + rv = SC_ERROR_BUFFER_TOO_SMALL; + goto done; + } - *buf = calloc(2 * len, 1); - if (*buf == NULL) - LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + memset(buf, 0, buflen); + memcpy(buf + (halflen - r_len), r, r_len); + memcpy(buf + (buflen - s_len), s, s_len); - memcpy(*buf + len - r_len, r, r_len); - memcpy(*buf + 2*len - s_len, s, s_len); - *buflen = 2 * len; - - sc_log(ctx, "r(%i): %s", len, sc_dump_hex(*buf, len)); - sc_log(ctx, "s(%i): %s", len, sc_dump_hex(*buf + len, len)); + sc_log(ctx, "r(%i): %s", halflen, sc_dump_hex(buf, halflen)); + sc_log(ctx, "s(%i): %s", halflen, sc_dump_hex(buf + halflen, halflen)); + rv = SC_SUCCESS; +done: free(r); free(s); - LOG_FUNC_RETURN(ctx, SC_SUCCESS); + LOG_FUNC_RETURN(ctx, rv); } diff --git a/src/libopensc/asn1.h b/src/libopensc/asn1.h index 13958845..0fa23e18 100644 --- a/src/libopensc/asn1.h +++ b/src/libopensc/asn1.h @@ -125,7 +125,7 @@ int sc_asn1_sig_value_rs_to_sequence(struct sc_context *ctx, unsigned char **buf, size_t *buflen); int sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, unsigned char *in, size_t inlen, - unsigned char **buf, size_t *buflen); + unsigned char *buf, size_t buflen); #define SC_ASN1_CLASS_MASK 0x30000000 #define SC_ASN1_UNI 0x00000000 /* Universal */ From 877fa862d99ee6177973ac2d80178449836cb5c3 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 8 Mar 2015 11:26:16 +0100 Subject: [PATCH 129/306] isoApplet: prototype of asn1_sig_value_sequence_to_rs() has changed --- src/libopensc/card-isoApplet.c | 57 ++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 131ac08f..d3364cb1 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -47,6 +47,7 @@ struct isoApplet_drv_data * If ECC is being used, the signatures generated by the card * have to be modified. */ unsigned int sec_env_alg_ref; + unsigned int sec_env_ec_field_length; }; #define DRVDATA(card) ((struct isoApplet_drv_data *) ((card)->drv_data)) @@ -191,16 +192,14 @@ isoApplet_init(sc_card_t *card) LOG_FUNC_CALLED(card->ctx); - drvdata=malloc(sizeof(*drvdata)); + drvdata=calloc(1, sizeof(*drvdata)); if (!drvdata) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); - memset(drvdata, 0, sizeof(*drvdata)); - drvdata->sec_env_alg_ref = 0; card->drv_data = drvdata; card->cla = 0x00; - /* ECDSA + /* ECDSA * Curves supported by the pkcs15-init driver are indicated per curve. This * should be kept in sync with the explicit parameters in the pkcs15-init * driver. */ @@ -210,31 +209,31 @@ isoApplet_init(sc_card_t *card) ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; ext_flags |= SC_ALGORITHM_EXT_EC_F_P; /* secp192r1, prime192r1, ansiX9p192r1*/ - r = sc_format_oid(&curve_oid, "1.2.840.10045.3.1.1"); + r = sc_format_oid(&curve_oid, "1.2.840.10045.3.1.1"); LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); _sc_card_add_ec_alg(card, 192, flags, ext_flags, &curve_oid); /* prime256v1, secp256r1, ansiX9p256r1 */ - r = sc_format_oid(&curve_oid, "1.2.840.10045.3.1.7"); + r = sc_format_oid(&curve_oid, "1.2.840.10045.3.1.7"); LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); _sc_card_add_ec_alg(card, 256, flags, ext_flags, &curve_oid); /* secp384r1, prime384v1, ansiX9p384r1 */ - r = sc_format_oid(&curve_oid, "1.3.132.0.34"); + r = sc_format_oid(&curve_oid, "1.3.132.0.34"); LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); _sc_card_add_ec_alg(card, 384, flags, ext_flags, &curve_oid); /* brainpoolP192r1 */ - r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.3"); + r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.3"); LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); _sc_card_add_ec_alg(card, 192, flags, ext_flags, &curve_oid); /* brainpoolP224r1 */ - r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.5"); + r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.5"); LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); _sc_card_add_ec_alg(card, 224, flags, ext_flags, &curve_oid); /* brainpoolP256r1 */ - r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.7"); + r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.7"); LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); _sc_card_add_ec_alg(card, 256, flags, ext_flags, &curve_oid); /* brainpoolP320r1 */ - r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.9"); + r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.9"); LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); _sc_card_add_ec_alg(card, 320, flags, ext_flags, &curve_oid); @@ -1106,6 +1105,7 @@ isoApplet_set_security_env(sc_card_t *card, if( env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW ) { drvdata->sec_env_alg_ref = ISOAPPLET_ALG_REF_ECDSA; + drvdata->sec_env_ec_field_length = env->algorithm_ref; } else { @@ -1190,38 +1190,41 @@ isoApplet_compute_signature(struct sc_card *card, const u8 *data, size_t datalen, u8 *out, size_t outlen) { + struct sc_context *ctx = card->ctx; struct isoApplet_drv_data *drvdata = DRVDATA(card); int r; - LOG_FUNC_CALLED(card->ctx); + LOG_FUNC_CALLED(ctx); r = iso_ops->compute_signature(card, data, datalen, out, outlen); if(r < 0) { - LOG_FUNC_RETURN(card->ctx, r); + LOG_FUNC_RETURN(ctx, r); } - /* If we used ECDSA for the signature op, OpenSC thinks it has to - * convert it to {sequence{integer,integer}} which is already done by the - * card actually. - * To fix this, I strip the {sequence, sequence} structual information, - * which will be added again later.*/ + /* If ECDSA was used, the ASN.1 sequence of integers R,S returned by the + * card needs to be converted to the raw concatenation of R,S for PKCS#11. */ if(drvdata->sec_env_alg_ref == ISOAPPLET_ALG_REF_ECDSA) { u8* p = NULL; - size_t len; + size_t len = drvdata->sec_env_ec_field_length / 4; - r = sc_asn1_sig_value_sequence_to_rs(card->ctx, out, r, &p, &len); - if(r < 0) { - if(p) - free(p); - LOG_FUNC_RETURN(card->ctx, r); + if (len > outlen) + LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); + + p = calloc(1,len); + if (!p) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + + r = sc_asn1_sig_value_sequence_to_rs(ctx, out, r, p, len); + if (!r) { + memcpy(out, p, len); + r = len; } - memcpy(out, p, len); - r = len; + free(p); } - LOG_FUNC_RETURN(card->ctx, r); + LOG_FUNC_RETURN(ctx, r); } static struct sc_card_driver *sc_get_driver(void) From 1becc45c108f0934423e72da5cfda63c29c76079 Mon Sep 17 00:00:00 2001 From: Lau bakman Date: Tue, 10 Mar 2015 09:15:11 +0100 Subject: [PATCH 130/306] Updated dnie-tool.1.xml for consistency Experienced a problem with dnie-tool where I would receive a warning with the content of /etc/bash_completion.d/dnie-tool. The cause of the error was a missing case label which in turn was caused by the formatting of the dnie-tool.1.xml. Options were formatted like which were not handled by the sed regular expression in the makefiles. Modified the dnie-tool.1.xml file to be consistent with the other doc files and to generate the dnie-tool file correctly. --- doc/tools/dnie-tool.1.xml | 74 +++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/doc/tools/dnie-tool.1.xml b/doc/tools/dnie-tool.1.xml index f2d670f4..d58b25b2 100644 --- a/doc/tools/dnie-tool.1.xml +++ b/doc/tools/dnie-tool.1.xml @@ -3,20 +3,22 @@ dnie-tool 1 - opensc + OpenSC + OpenSC Tools + opensc dnie-tool displays information about DNIe based security tokens - - - Synopsis - - dnie-tool [OPTIONS] - - + + + + dnie-tool + OPTIONS + + Description @@ -30,33 +32,49 @@ - - Show the DNIe IDESP value. - + + , + + + Show the DNIe IDESP value. - + + , + + Show DNIe personal information. Reads and print DNIe number and User Name and SurName - + + , + + Displays every available information. - This command is equivalent to -d -i -s - + This command is equivalent to -d -i -s - + + , + + Displays DNIe Serial Number - + + , + + Show DNIe sw version. Displays sofware version for in-card DNIe OS - pin, pin + + pin, + pin + Specify the user pin pin to use. If set to env:VARIABLE, the value of the environment variable @@ -64,22 +82,34 @@ The default is do not enter pin - number, number + + number, + number + Specify the reader number to use. The default is reader 0. - driver, driver + + driver, + driver + Specify the card driver driver to use. Default is use driver from configuration file, or auto-detect if absent - + + , + + Causes dnie-tool to wait for the token to be inserted into reader. - + + , + + Causes dnie-tool to be more verbose. Specify this flag several times to enable debug output in the opensc library. From 2fffbce65cb4e616dacd5a9549379eac92e20687 Mon Sep 17 00:00:00 2001 From: Hannu Honkanen Date: Sun, 15 Feb 2015 13:59:11 +0100 Subject: [PATCH 131/306] myeid: update EC support for MyEID-v4 card --- src/libopensc/card-myeid.c | 516 +++++++++++++++++++++++----------- src/libopensc/cardctl.h | 5 +- src/pkcs15init/pkcs15-myeid.c | 70 +++-- 3 files changed, 401 insertions(+), 190 deletions(-) diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index d906e0ef..63a35119 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + */ #include "config.h" @@ -28,21 +28,21 @@ #include "cardctl.h" #include "types.h" -#define LOAD_KEY_MODULUS 0x80 -#define LOAD_KEY_PUBLIC_EXPONENT 0x81 -#define LOAD_KEY_PRIME_P 0x83 -#define LOAD_KEY_PRIME_Q 0x84 -#define LOAD_KEY_DP1 0x85 -#define LOAD_KEY_DQ1 0x86 -#define LOAD_KEY_INVQ 0x87 -#define LOAD_KEY_MODE_EC_PRIV 0x87 -#define LOAD_KEY_MODE_EC_PUB 0x86 +#define LOAD_KEY_MODULUS 0x80 +#define LOAD_KEY_PUBLIC_EXPONENT 0x81 +#define LOAD_KEY_PRIME_P 0x83 +#define LOAD_KEY_PRIME_Q 0x84 +#define LOAD_KEY_DP1 0x85 +#define LOAD_KEY_DQ1 0x86 +#define LOAD_KEY_INVQ 0x87 +#define LOAD_KEY_MODE_EC_PRIV 0x87 +#define LOAD_KEY_MODE_EC_PUB 0x86 -#define LOAD_KEY_EC_PRIVATE 0x97 -#define LOAD_KEY_EC_PUBLIC 0x96 +#define LOAD_KEY_EC_PRIVATE 0x97 +#define LOAD_KEY_EC_PUBLIC 0x96 -#define MYEID_STATE_CREATION 0x01 -#define MYEID_STATE_ACTIVATED 0x07 +#define MYEID_STATE_CREATION 0x01 +#define MYEID_STATE_ACTIVATED 0x07 #define MYEID_ECC_SUPPORT @@ -59,15 +59,37 @@ static struct sc_card_driver myeid_drv = { static const char *myeid_atrs[] = { "3B:F5:18:00:FF:81:31:FE:45:4D:79:45:49:44:65", "3B:F5:18:00:00:81:31:FE:45:4D:79:45:49:44:9A", - "3B:85:80:01:4D:79:45:49:44:78", - "3B:89:80:01:09:38:33:B1:4D:79:45:49:44:4C", - NULL + "3B:85:80:01:4D:79:45:49:44:78", + "3B:89:80:01:09:38:33:B1:4D:79:45:49:44:4C", + NULL }; typedef struct myeid_private_data { int card_state; + + unsigned short change_counter; + /* the driver sets sec_env pointer in myeid_set_security_env and + it is used immediately in myeid_decipher to differentiate between RSA decryption and + ECDH key agreement. Note that this pointer is usually not valid + after this pair of calls and must not be used elsewhere. */ + const struct sc_security_env* sec_env; } myeid_private_data_t; +static struct myeid_supported_ec_curves { + char *curve_name; + struct sc_object_id curve_oid; + size_t size; +} ec_curves[] = { + {"secp192r1", {{1, 2, 840, 10045, 3, 1, 1, -1}},192}, + /* {"secp224r1", {{1, 3, 132, 0, 33, -1}}, 224}, */ + {"secp256r1", {{1, 2, 840, 10045, 3, 1, 7, -1}},256}, + /* {"secp384r1", {{1, 3, 132, 0, 34, -1}}, 384}, */ + /* {"secp521r1", {{1, 3, 132, 0, 35, -1}}, 521}, */ + {NULL, {{-1}}, 0}, +}; + +static int myeid_get_info(struct sc_card *card, u8 *rbuf, size_t buflen); + static int myeid_match_card(struct sc_card *card) { int i, match = -1; @@ -95,20 +117,34 @@ static int myeid_match_card(struct sc_card *card) static int myeid_init(struct sc_card *card) { - unsigned long flags = 0, - ext_flags = 0; + unsigned long flags = 0, + ext_flags = 0; myeid_private_data_t *priv; + u8 appletInfo[20]; + size_t appletInfoLen; + int r; LOG_FUNC_CALLED(card->ctx); priv = calloc(1, sizeof(myeid_private_data_t)); if (!priv) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + priv->card_state = SC_FILE_STATUS_CREATION; card->drv_data = priv; + /* find out MyEID version */ + + appletInfoLen = 20; + + r = myeid_get_info(card, appletInfo, appletInfoLen); + + LOG_TEST_RET(card->ctx, r, "Failed to get MyEID applet information."); + + priv->change_counter = appletInfo[19] | appletInfo[18] << 8; + flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_ONBOARD_KEY_GEN; flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1; - + _sc_card_add_rsa_alg(card, 512, flags, 0); _sc_card_add_rsa_alg(card, 768, flags, 0); _sc_card_add_rsa_alg(card, 1024, flags, 0); @@ -116,14 +152,20 @@ static int myeid_init(struct sc_card *card) _sc_card_add_rsa_alg(card, 2048, flags, 0); #ifdef MYEID_ECC_SUPPORT - flags |= SC_ALGORITHM_ECDSA_RAW; - ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; - _sc_card_add_ec_alg(card, 192, flags, ext_flags, NULL); - _sc_card_add_ec_alg(card, 224, flags, ext_flags, NULL); - _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); + /* show ECC algorithms if the applet version of the inserted card supports them */ + if ((card->version.fw_major == 3 && card->version.fw_minor > 5) || + card->version.fw_major >= 4) { + int i; + + flags |= SC_ALGORITHM_ECDSA_RAW; + ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; + + for (i=0; ec_curves[i].curve_name != NULL; i++) + _sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].curve_oid); + } #endif - + /* State that we have an RNG */ card->caps |= SC_CARD_CAP_RNG; @@ -241,7 +283,7 @@ static int myeid_list_files(struct sc_card *card, u8 *buf, size_t buflen) struct sc_apdu apdu; int r; - LOG_FUNC_CALLED(card->ctx); + LOG_FUNC_CALLED(card->ctx); sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x01, 0xA1); apdu.resp = buf; @@ -257,7 +299,7 @@ static int myeid_list_files(struct sc_card *card, u8 *buf, size_t buflen) } static int myeid_process_fci(struct sc_card *card, struct sc_file *file, - const u8 *buf, size_t buflen) + const u8 *buf, size_t buflen) { myeid_private_data_t *priv = (myeid_private_data_t *) card->drv_data; size_t taglen = 0; @@ -279,8 +321,8 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file, } if(file->sec_attr_len >= 3) { - sc_log(card->ctx, "id (%X) sec_attr (%X %X %X)", file->id, - file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]); + sc_log(card->ctx, "id (%X) sec_attr (%X %X %X)", file->id, + file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]); } tag = sc_asn1_find_tag(NULL, buf, buflen, 0x8A, &taglen); if (tag != NULL && taglen > 0) @@ -305,13 +347,13 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, u8 *out, size_t *outlen) { const sc_acl_entry_t *read, *update, *delete, *generate; - u8 buf[41]; + u8 buf[42]; size_t i; LOG_FUNC_CALLED(card->ctx); /* PrivateKey * 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984 - * 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */ + * 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */ memset(buf, 0x0, sizeof(buf)); buf[0] = 0x62; @@ -340,17 +382,15 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, buf[16] = 0xFF; buf[17] = 0xFF; - if (file->sec_attr_len == 3 && file->sec_attr) - { + if (file->sec_attr_len == 3 && file->sec_attr) { buf[15] = file->sec_attr[0]; buf[16] = file->sec_attr[1]; buf[17] = file->sec_attr[2]; sc_log(card->ctx, "id (%X), sec_attr %X %X %X", file->id, - file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]); + file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]); } - else - { + else { delete = sc_file_get_acl_entry(file, SC_AC_OP_DELETE); switch (file->type) { @@ -407,7 +447,7 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, case SC_FILE_TYPE_DF: buf[8] = 0x38; - if(file->namelen > 0 && file->namelen < 16) + if(file->namelen > 0 && file->namelen <= 16) { buf[25] = 0x84; buf[26] = (u8)file->namelen; @@ -433,7 +473,7 @@ static int myeid_create_file(struct sc_card *card, struct sc_file *file) { sc_apdu_t apdu; u8 sbuf[32]; - size_t buflen; + size_t buflen; int r; LOG_FUNC_CALLED(card->ctx); @@ -479,14 +519,56 @@ static int myeid_delete_file(struct sc_card *card, const struct sc_path *path) LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); } +static int myeid_pin_info(sc_card_t *card, struct sc_pin_cmd_data *data, + int *tries_left) +{ + sc_apdu_t apdu; + int r; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, data->pin_reference); + + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + + if (r == SC_ERROR_PIN_CODE_INCORRECT) { + data->pin1.tries_left = apdu.sw2 & 0xF; + r = SC_SUCCESS; + } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { + data->pin1.tries_left = 0; + r = SC_SUCCESS; + } + LOG_TEST_RET(card->ctx, r, "Check SW error"); + + if (r == SC_SUCCESS) + { + data->pin1.pad_length = data->pin2.pad_length = 8; + data->pin1.pad_char = data->pin2.pad_char = 0xFF; + } + + + if (tries_left != NULL) { + *tries_left = data->pin1.tries_left; + } + + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, - int *tries_left) + int *tries_left) { myeid_private_data_t *priv = (myeid_private_data_t *) card->drv_data; LOG_FUNC_CALLED(card->ctx); + + if (data->cmd == SC_PIN_CMD_GET_INFO) + { + return myeid_pin_info(card, data, tries_left); + } + sc_log(card->ctx, "ref (%d), pin1 len(%d), pin2 len (%d)\n", - data->pin_reference, data->pin1.len, data->pin2.len); + data->pin_reference, data->pin1.len, data->pin2.len); if(data->pin1.len > 8 || data->pin2.len > 8) LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_PIN_LENGTH); @@ -585,7 +667,7 @@ err: LOG_FUNC_RETURN(card->ctx, r); } -static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *env, +static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *env, int se_num) { sc_apdu_t apdu; @@ -595,23 +677,23 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e assert(card != NULL && env != NULL); LOG_FUNC_CALLED(card->ctx); - - if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) + + if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) { sc_log(card->ctx, "asymmetric keyref not supported.\n"); return SC_ERROR_NOT_SUPPORTED; } - if (se_num > 0) + if (se_num > 0) { sc_log(card->ctx, "restore security environment not supported.\n"); return SC_ERROR_NOT_SUPPORTED; } sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); - switch (env->operation) + switch (env->operation) { case SC_SEC_OPERATION_DECIPHER: - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decipher operation is not supported with EC keys.\n"); + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Decipher operation is not supported with EC keys.\n"); return SC_ERROR_NOT_SUPPORTED; break; case SC_SEC_OPERATION_SIGN: @@ -623,20 +705,20 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e } apdu.le = 0; p = sbuf; - if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) + if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) { *p++ = 0x80; /* algorithm reference */ *p++ = 0x01; *p++ = env->algorithm_ref & 0xFF; } - if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) + if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) { *p++ = 0x81; *p++ = 0x02; memcpy(p, env->file_ref.value, 2); p += 2; } - if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) + if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { *p++ = 0x84; *p++ = 1; @@ -647,17 +729,17 @@ static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *e apdu.datalen = r; apdu.data = sbuf; apdu.resplen = 0; - if (apdu.datalen != 0) + if (apdu.datalen != 0) { r = sc_transmit_apdu(card, &apdu); - if (r) + if (r) { sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r)); goto err; } r = sc_check_sw(card, apdu.sw1, apdu.sw2); - if (r) + if (r) { sc_log(card->ctx, "%s: Card returned error", sc_strerror(r)); @@ -671,7 +753,14 @@ err: static int myeid_set_security_env(struct sc_card *card, const struct sc_security_env *env, int se_num) { - LOG_FUNC_CALLED(card->ctx); + struct sc_context *ctx = card->ctx; + myeid_private_data_t* priv; + + LOG_FUNC_CALLED(ctx); + + priv = (myeid_private_data_t*) card->drv_data; + /* store security environment to differentiate between ECDH and RSA in decipher - Hannu*/ + priv->sec_env = env; if (env->flags & SC_SEC_ENV_ALG_PRESENT) { @@ -680,8 +769,8 @@ static int myeid_set_security_env(struct sc_card *card, tmp = *env; tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT; tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT; - - if (tmp.algorithm == SC_ALGORITHM_RSA) + + if (tmp.algorithm == SC_ALGORITHM_RSA) { tmp.algorithm_ref = 0x00; /* potential FIXME: return an error, if an unsupported @@ -691,43 +780,78 @@ static int myeid_set_security_env(struct sc_card *card, if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) tmp.algorithm_ref |= 0x10; - return myeid_set_security_env_rsa(card, &tmp, se_num); + return myeid_set_security_env_rsa(card, &tmp, se_num); } - else if (tmp.algorithm == SC_ALGORITHM_EC) - { + else if (tmp.algorithm == SC_ALGORITHM_EC) + { #ifdef MYEID_ECC_SUPPORT - /* TODO: Update the algorithm_ref */ - tmp.algorithm_ref = 0xAA; - tmp.algorithm_flags = 0; - return myeid_set_security_env_ec(card, &tmp, se_num); + tmp.algorithm_ref = 0x04; + tmp.algorithm_flags = 0; + return myeid_set_security_env_ec(card, &tmp, se_num); #else - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Elliptic curves are not supported in this version.\n"); + sc_log(ctx, "Elliptic curves are not supported in this version."); return SC_ERROR_NOT_SUPPORTED; #endif - } + } else { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported algorithm.\n"); + sc_log(ctx, "Unsupported algorithm."); return SC_ERROR_NOT_SUPPORTED; - } + } } return myeid_set_security_env_rsa(card, env, se_num); } -static int myeid_compute_signature(struct sc_card *card, const u8 * data, - size_t datalen, u8 * out, size_t outlen) + +static int +myeid_convert_ec_signature(struct sc_context *ctx, size_t s_len, unsigned char *data, size_t datalen) { + unsigned char *buf; + size_t i, buflen; int r; + + assert(data && datalen); + + if (*data != 0x30 || *(data + 1) != (datalen - 2) || *(data + 2) != 0x02) + return SC_ERROR_INVALID_DATA; + + buf = calloc(1, s_len/4); + if (!buf) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + buflen = s_len/4; + + r = sc_asn1_sig_value_sequence_to_rs(ctx, data, datalen, buf, buflen); + LOG_TEST_RET(ctx, r, "Failed to cenvert Sig-Value to the raw RS format"); + + if (buflen > datalen) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + + memmove(data, buf, buflen); + return buflen; +} + + +static int +myeid_compute_signature(struct sc_card *card, const u8 * data, size_t datalen, + u8 * out, size_t outlen) +{ + struct sc_context *ctx = card->ctx; struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; - - LOG_FUNC_CALLED(card->ctx); + struct myeid_private_data* priv; + int r; assert(card != NULL && data != NULL && out != NULL); + ctx = card->ctx; + LOG_FUNC_CALLED(ctx); + + priv = (myeid_private_data_t*) card->drv_data; + sc_log(ctx, "key type %i, key length %i", priv->sec_env->algorithm, priv->sec_env->algorithm_ref); + if (datalen > 256) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); /* INS: 0x2A PERFORM SECURITY OPERATION * P1: 0x9E Resp: Digital Signature @@ -736,15 +860,13 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data, apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = 256; - if (datalen == 256) - { + if (datalen == 256) { apdu.p2 = data[0]; memcpy(sbuf, data+1, datalen-1); apdu.lc = datalen - 1; apdu.datalen = datalen - 1; } - else - { + else { memcpy(sbuf, data, datalen); apdu.lc = datalen; apdu.datalen = datalen; @@ -752,40 +874,107 @@ static int myeid_compute_signature(struct sc_card *card, const u8 * data, apdu.data = sbuf; r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + LOG_TEST_RET(ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(ctx, r, "compute_signature failed"); - if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) - { - int len = apdu.resplen > outlen ? outlen : apdu.resplen; - - memcpy(out, apdu.resp, len); - LOG_FUNC_RETURN(card->ctx, len); + if (priv->sec_env->algorithm == SC_ALGORITHM_EC) { + r = myeid_convert_ec_signature(ctx, priv->sec_env->algorithm_ref, apdu.resp, apdu.resplen); + LOG_TEST_RET(ctx, r, "compute_signature convert signature failed"); + apdu.resplen = r; } - LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); + if (apdu.resplen > outlen) + LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); + + memcpy(out, apdu.resp, apdu.resplen); + LOG_FUNC_RETURN(ctx, apdu.resplen); } + +/* takes other party's public key as input, performs ECDH key derivation and returns the shared secret in [out]. */ +int myeid_ecdh_derive(struct sc_card *card, const u8* pubkey, size_t pubkey_len, u8* out, size_t outlen) +{ + + /* MyEID uses GENERAL AUTHENTICATE ISO command for ECDH */ + + struct sc_apdu apdu; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + + int r; + + sc_format_apdu(card, &apdu, + SC_APDU_CASE_4_SHORT, + 0x86, 0x00, 0x00); + + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + + /* Fill in "Data objects in dynamic authentication template (tag 0x7C) structure */ + sbuf[0] = 0x7C; + sbuf[1] = pubkey_len + 4; + sbuf[2] = 0x85; + sbuf[3] = pubkey_len; + memcpy(&sbuf[4], pubkey, pubkey_len); + + apdu.lc = pubkey_len + 4; + apdu.datalen = apdu.lc; + apdu.data = sbuf; + + r = sc_transmit_apdu(card, &apdu); + + LOG_TEST_RET(card->ctx, r, "APDU transmit failed."); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(card->ctx, r, "ECDH operation failed - GENERAL AUTHENTICATE returned error."); + + if (outlen < apdu.resplen) + { + r = SC_ERROR_BUFFER_TOO_SMALL; + LOG_TEST_RET(card->ctx, r, "Buffer too small to hold shared secret."); + } + + memcpy(out, rbuf, apdu.resplen); + + LOG_FUNC_RETURN(card->ctx, r); +} + + static int myeid_decipher(struct sc_card *card, const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen) { - int r; - struct sc_apdu apdu; - u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + int r; + myeid_private_data_t* priv; + struct sc_apdu apdu; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; LOG_FUNC_CALLED(card->ctx); + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL); - assert(card != NULL && crgram != NULL && out != NULL); - SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL); - if (crgram_len > 256) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + assert(card != NULL && crgram != NULL && out != NULL); - /* INS: 0x2A PERFORM SECURITY OPERATION - * P1: 0x80 Resp: Plain value - * P2: 0x86 Cmd: Padding indicator byte followed by cryptogram */ - sc_format_apdu(card, &apdu, - (crgram_len < 256) ? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_3_SHORT, - 0x2A, 0x80, 0x86); + priv = (myeid_private_data_t*) card->drv_data; + + if (priv->sec_env && priv->sec_env->algorithm == SC_ALGORITHM_EC + && priv->sec_env->operation == SC_SEC_OPERATION_DERIVE + && priv->sec_env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW) + { + r = myeid_ecdh_derive(card, crgram, crgram_len, out, outlen); + priv->sec_env = NULL; /* clear after operation */ + LOG_FUNC_RETURN(card->ctx, r); + } + + if (crgram_len > 256) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + + /* INS: 0x2A PERFORM SECURITY OPERATION + * P1: 0x80 Resp: Plain value + * P2: 0x86 Cmd: Padding indicator byte followed by cryptogram */ + sc_format_apdu(card, &apdu, + (crgram_len < 256) ? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_3_SHORT, + 0x2A, 0x80, 0x86); apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); @@ -793,17 +982,17 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram, if (crgram_len == 256) { - apdu.le = 0; - /* padding indicator byte, 0x81 = first half of 2048 bit cryptogram */ - sbuf[0] = 0x81; - memcpy(sbuf + 1, crgram, crgram_len / 2); - apdu.lc = crgram_len / 2 + 1; + apdu.le = 0; + /* padding indicator byte, 0x81 = first half of 2048 bit cryptogram */ + sbuf[0] = 0x81; + memcpy(sbuf + 1, crgram, crgram_len / 2); + apdu.lc = crgram_len / 2 + 1; } else { - sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */ - memcpy(sbuf + 1, crgram, crgram_len); - apdu.lc = crgram_len + 1; + sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */ + memcpy(sbuf + 1, crgram, crgram_len); + apdu.lc = crgram_len + 1; } apdu.datalen = apdu.lc; @@ -813,43 +1002,44 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram, LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { - if (crgram_len == 256) - { - sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, - 0x2A, 0x80, 0x86); - apdu.resp = rbuf; - apdu.resplen = sizeof(rbuf); - apdu.le = crgram_len; - /* padding indicator byte, - * 0x82 = Second half of 2048 bit cryptogram */ - sbuf[0] = 0x82; - memcpy(sbuf + 1, crgram + crgram_len / 2, crgram_len / 2); - apdu.lc = crgram_len / 2 + 1; - apdu.datalen = apdu.lc; - apdu.data = sbuf; + if (crgram_len == 256) + { + sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, + 0x2A, 0x80, 0x86); + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + apdu.le = crgram_len; + /* padding indicator byte, + * 0x82 = Second half of 2048 bit cryptogram */ + sbuf[0] = 0x82; + memcpy(sbuf + 1, crgram + crgram_len / 2, crgram_len / 2); + apdu.lc = crgram_len / 2 + 1; + apdu.datalen = apdu.lc; + apdu.data = sbuf; - r = sc_transmit_apdu(card, &apdu); + r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) - { - int len = apdu.resplen > outlen ? outlen : apdu.resplen; - memcpy(out, apdu.resp, len); - LOG_FUNC_RETURN(card->ctx, len); - } - } - else - { - int len = apdu.resplen > outlen ? outlen : apdu.resplen; + if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) + { + int len = apdu.resplen > outlen ? outlen : apdu.resplen; + memcpy(out, apdu.resp, len); + LOG_FUNC_RETURN(card->ctx, len); + } + } + else + { + int len = apdu.resplen > outlen ? outlen : apdu.resplen; - memcpy(out, apdu.resp, len); - LOG_FUNC_RETURN(card->ctx, len); - } - } - LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); + memcpy(out, apdu.resp, len); + LOG_FUNC_RETURN(card->ctx, len); + } + } + LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); } + /* Write internal data, e.g. add default pin-records to pin */ static int myeid_putdata(struct sc_card *card, struct sc_cardctl_myeid_data_obj* data_obj) { @@ -984,7 +1174,7 @@ static int myeid_loadkey(sc_card_t *card, int mode, u8* value, int value_len) apdu.data = sbuf; apdu.datalen = len; apdu.lc = len; - + r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); @@ -1017,22 +1207,22 @@ static int myeid_generate_store_key(struct sc_card *card, memcpy(sbuf + len, data->pubexp, data->pubexp_len); len += data->pubexp_len; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00); - apdu.data = sbuf; + apdu.data = sbuf; } else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) { - + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x46, 0x00, 0x00); - + apdu.data = NULL; apdu.resp = sbuf; apdu.resplen = 0x00; apdu.le = 0x00; } - + apdu.cla = 0x00; apdu.datalen = len; apdu.lc = len; - + r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); @@ -1060,9 +1250,9 @@ static int myeid_generate_store_key(struct sc_card *card, LOG_FUNC_RETURN(card->ctx, r); } else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) { - if((r = myeid_loadkey(card, LOAD_KEY_EC_PRIVATE, data->d, + if((r = myeid_loadkey(card, LOAD_KEY_EC_PRIVATE, data->d, data->d_len)) >= 0 && - (r = myeid_loadkey(card, LOAD_KEY_EC_PUBLIC, data->ecpublic_point, + (r = myeid_loadkey(card, LOAD_KEY_EC_PUBLIC, data->ecpublic_point, data->ecpublic_point_len)) >= 0) LOG_FUNC_RETURN(card->ctx, r); } @@ -1202,25 +1392,25 @@ static struct sc_card_driver * sc_get_driver(void) if (iso_ops == NULL) iso_ops = iso_drv->ops; - myeid_ops = *iso_drv->ops; - myeid_ops.match_card = myeid_match_card; - myeid_ops.init = myeid_init; - myeid_ops.finish = myeid_finish; + myeid_ops = *iso_drv->ops; + myeid_ops.match_card = myeid_match_card; + myeid_ops.init = myeid_init; + myeid_ops.finish = myeid_finish; /* no record oriented file services */ - myeid_ops.read_record = NULL; - myeid_ops.write_record = NULL; - myeid_ops.append_record = NULL; - myeid_ops.update_record = NULL; - myeid_ops.select_file = myeid_select_file; - myeid_ops.create_file = myeid_create_file; - myeid_ops.delete_file = myeid_delete_file; - myeid_ops.list_files = myeid_list_files; - myeid_ops.set_security_env = myeid_set_security_env; - myeid_ops.compute_signature = myeid_compute_signature; - myeid_ops.decipher = myeid_decipher; - myeid_ops.process_fci = myeid_process_fci; - myeid_ops.card_ctl = myeid_card_ctl; - myeid_ops.pin_cmd = myeid_pin_cmd; + myeid_ops.read_record = NULL; + myeid_ops.write_record = NULL; + myeid_ops.append_record = NULL; + myeid_ops.update_record = NULL; + myeid_ops.select_file = myeid_select_file; + myeid_ops.create_file = myeid_create_file; + myeid_ops.delete_file = myeid_delete_file; + myeid_ops.list_files = myeid_list_files; + myeid_ops.set_security_env = myeid_set_security_env; + myeid_ops.compute_signature = myeid_compute_signature; + myeid_ops.decipher = myeid_decipher; + myeid_ops.process_fci = myeid_process_fci; + myeid_ops.card_ctl = myeid_card_ctl; + myeid_ops.pin_cmd = myeid_pin_cmd; return &myeid_drv; } diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index edfac57d..2f467c1d 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -839,10 +839,7 @@ typedef struct sc_rtecp_genkey_data { */ enum SC_CARDCTL_MYEID_KEY_TYPE { SC_CARDCTL_MYEID_KEY_RSA = 0x11, - SC_CARDCTL_MYEID_KEY_EC = 0x21, - /* SC_CARDCTL_MYEID_KEY_AES = 0x?, // for future use - SC_CARDCTL_MYEID_KEY_DES = 0x?, - SC_CARDCTL_MYEID_KEY_3DES = 0x?, */ + SC_CARDCTL_MYEID_KEY_EC = 0x22 }; struct sc_cardctl_myeid_data_obj { diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index ab7b2261..5bf7d2b2 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -48,7 +48,7 @@ myeid_delete_object(struct sc_profile *profile, struct sc_pkcs15_card *p15card, /* * Get 'Initialize Applet' data - * using the ACLs defined in card profile. + * using the ACLs defined in card profile. */ static int myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p15card, @@ -189,7 +189,7 @@ myeid_init_card(sc_profile_t *profile, */ static int myeid_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df) { - struct sc_context *ctx; + struct sc_context *ctx = NULL; struct sc_file *file = NULL; int r = 0, ii; static const char *create_dfs[] = { @@ -422,7 +422,10 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, "Unsupported RSA key size"); break; case SC_PKCS15_TYPE_PRKEY_EC: - LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "20140202: waiting for cards and specification from Aventra. VTA"); + /* Here the information about curve is not available, that's why algorithm is checked + without curve OID. */ + if (sc_card_find_ec_alg(p15card->card, keybits, NULL) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, @@ -436,8 +439,9 @@ myeid_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, r = myeid_new_file(profile, card, object->type, key_info->key_reference, &file); LOG_TEST_RET(ctx, r, "Cannot get new MyEID private key file"); - if (file || !file->path.len) + if (!file || !file->path.len) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot determine private key file"); + sc_log(ctx, "Key file size %d", keybits); file->size = keybits; @@ -482,7 +486,15 @@ myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size"); break; case SC_PKCS15_TYPE_PRKEY_EC: - LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "20140202: waiting for cards and specification from Aventra. VTA"); + if (!sc_valid_oid(&prkey->u.ec.params.id)) + if (sc_pkcs15_fix_ec_parameters(ctx, &prkey->u.ec.params)) + LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_VALID); + if (sc_card_find_ec_alg(p15card->card, keybits, &prkey->u.ec.params.id) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported algorithm or key size"); + if(key_info->field_length != 0) + keybits = key_info->field_length; + else + key_info->field_length = keybits; break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Store key failed: Unsupported key type"); @@ -564,7 +576,15 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported RSA key size"); break; case SC_PKCS15_TYPE_PRKEY_EC: - LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "20140202: waiting for cards and specification from Aventra. VTA"); + /* EC is supported in MyEID v > 3.5. TODO: set correct return value if older MyEID version. */ + /* Here the information about curve is not available, that's why supported algorithm is checked + without curve OID. */ + if (sc_card_find_ec_alg(p15card->card, keybits, NULL) == NULL) + LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported EC key size"); + if(key_info->field_length != 0) + keybits = key_info->field_length; + else + key_info->field_length = keybits; break; default: LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key type"); @@ -626,7 +646,9 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, memcpy(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); } else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) { + struct sc_ec_parameters *ecparams = (struct sc_pkcs15_ec_parameters *)key_info->params.data; + sc_log(ctx, "curve '%s', len %i, oid '%s'", ecparams->named_curve, ecparams->field_length, sc_dump_oid(&(ecparams->id))); pubkey->algorithm = SC_ALGORITHM_EC; r = sc_select_file(card, &file->path, NULL); @@ -640,25 +662,27 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj); LOG_TEST_RET(ctx, r, "Cannot get EC public key: 'MYEID_GETDATA' failed"); - /* - * TODO DEE - this looks like a bug... - * pubkey->u.ec.ecpointQ.value is just value. "04||X||Y" - * pubkey->data.value should be DER OCTET STRING - * but - * pubkey->data.value looks like TLV with TAG if 0x86 - * and single byte length. - * Could call sc_pkcs15_encode_pubkey - * to set pubkey->data.value - */ - + if (pubkey->u.ec.ecpointQ.value) + free(pubkey->u.ec.ecpointQ.value); pubkey->u.ec.ecpointQ.value = malloc(data_obj.DataLen - 2); - pubkey->u.ec.ecpointQ.len = data_obj.DataLen - 2; - //pubkey->data.value = malloc(data_obj.DataLen); - //pubkey->data.len = data_obj.DataLen; - pubkey->u.ec.params.field_length = keybits; - /* Omit the first 2 bytes (0x86??) */ + if (pubkey->u.ec.ecpointQ.value == NULL) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(pubkey->u.ec.ecpointQ.value, data_obj.Data + 2, data_obj.DataLen - 2); - //memcpy(pubkey->data.value, data_obj.Data, data_obj.DataLen); + pubkey->u.ec.ecpointQ.len = data_obj.DataLen - 2; + + if (pubkey->u.ec.params.named_curve) + free(pubkey->u.ec.params.named_curve); + pubkey->u.ec.params.named_curve = NULL; + if (pubkey->u.ec.params.der.value) + free(pubkey->u.ec.params.der.value); + pubkey->u.ec.params.der.value = NULL; + pubkey->u.ec.params.der.len = 0; + + pubkey->u.ec.params.named_curve = strdup(ecparams->named_curve); + if (!pubkey->u.ec.params.named_curve) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + r = sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); + LOG_TEST_RET(ctx, r, "Cannot fix EC parameters"); } } From c0c8a89126a0a11d315badcd778670d757b60f4c Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Fri, 20 Mar 2015 18:08:18 +0100 Subject: [PATCH 132/306] mcrd: move driver to the end of detection list the drivers that need to probe the AIDs to recognize its supported card have to be placed at the end of the list of internal drivers --- src/libopensc/ctx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 19d23770..ca05cc81 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -70,7 +70,6 @@ static const struct _sc_driver_entry internal_card_drivers[] = { #endif { "gemsafeV1", (void *(*)(void)) sc_get_gemsafeV1_driver }, { "miocos", (void *(*)(void)) sc_get_miocos_driver }, - { "mcrd", (void *(*)(void)) sc_get_mcrd_driver }, { "asepcos", (void *(*)(void)) sc_get_asepcos_driver }, { "starcos", (void *(*)(void)) sc_get_starcos_driver }, { "tcos", (void *(*)(void)) sc_get_tcos_driver }, @@ -103,6 +102,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = { /* Here should be placed drivers that need some APDU transactions to * recognise its cards. */ + { "mcrd", (void *(*)(void)) sc_get_mcrd_driver }, { "setcos", (void *(*)(void)) sc_get_setcos_driver }, { "muscle", (void *(*)(void)) sc_get_muscle_driver }, { "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver }, From 435291f2166935e741e67539a55f191695874268 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Fri, 27 Mar 2015 17:11:12 +0100 Subject: [PATCH 133/306] iasecc: initial support for Morpho IAS Agent Card * This commit adds initial support for Morpho French Agent card which is an IAS card. Signature operations are working. Since my test card was read-only, I was unable to test object management functions. * Add missing copy of AID in structure --- etc/opensc.conf.in | 8 +++++ src/libopensc/card-iasecc.c | 62 ++++++++++++++++++++++++++++++++++++- src/libopensc/cards.h | 1 + 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in index b4a28993..4f81b93d 100644 --- a/etc/opensc.conf.in +++ b/etc/opensc.conf.in @@ -301,6 +301,14 @@ app default { # name = "Morpho YpsID S3 IAS/ECC"; # # secure_messaging = local_morpho_YpsID_S3; #} + #card_atr 3B:DF:96:00:80:31:FE:45:00:31:B8:64:04:1F:EC:C1:73:94:01:80:82:90:00:EC { + # type = 25005; + # driver = "iasecc"; + # name = "Morpho MI IAS/ECC v1.0.1"; + # md_read_only = false; + # md_supports_X509_enrollment = true; + # secure_messaging = local_morpho_mi; + #} card_atr 3B:DF:18:FF:81:91:FE:1F:C3:00:31:B8:64:0C:01:EC:C1:73:94:01:80:82:90:00:B3 { type = 25004; driver = "iasecc"; diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index ea6d4973..c9d2518c 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -79,6 +79,8 @@ static struct sc_atr_table iasecc_known_atrs[] = { "IAS/ECC v1.0.1 Sagem MDW-IAS-CARD2", SC_CARD_TYPE_IASECC_SAGEM, 0, NULL }, { "3B:7F:18:00:00:00:31:B8:64:50:23:EC:C1:73:94:01:80:82:90:00", NULL, "IAS/ECC v1.0.1 Sagem ypsID S3", SC_CARD_TYPE_IASECC_SAGEM, 0, NULL }, + { "3B:DF:96:00:80:31:FE:45:00:31:B8:64:04:1F:EC:C1:73:94:01:80:82:90:00:EC", NULL, + "IAS/ECC Morpho MinInt - Agent Card", SC_CARD_TYPE_IASECC_MI, 0, NULL }, { "3B:DF:18:FF:81:91:FE:1F:C3:00:31:B8:64:0C:01:EC:C1:73:94:01:80:82:90:00:B3", NULL, "IAS/ECC v1.0.1 Amos", SC_CARD_TYPE_IASECC_AMOS, 0, NULL }, { "3B:DC:18:FF:81:91:FE:1F:C3:80:73:C8:21:13:66:02:04:03:55:00:02:34", NULL, @@ -98,6 +100,10 @@ static struct sc_aid OberthurIASECC_AID = { {0xA0,0x00,0x00,0x00,0x77,0x01,0x08,0x00,0x07,0x00,0x00,0xFE,0x00,0x00,0x01,0x00}, 16 }; +static struct sc_aid MIIASECC_AID = { + { 0x4D, 0x49, 0x4F, 0x4D, 0x43, 0x54}, 6 +}; + struct iasecc_pin_status { unsigned char sha1[SHA_DIGEST_LENGTH]; unsigned char reference; @@ -566,6 +572,53 @@ iasecc_init_amos(struct sc_card *card) LOG_FUNC_RETURN(ctx, SC_SUCCESS); } +iasecc_mi_match(struct sc_card *card) +{ + struct sc_context *ctx = card->ctx; + + LOG_FUNC_CALLED(ctx); + + if (!card->ef_atr) + card->ef_atr = calloc(1, sizeof(struct sc_ef_atr)); + if (!card->ef_atr) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + + memcpy(card->ef_atr->aid.value, MIIASECC_AID.value, MIIASECC_AID.len); + card->ef_atr->aid.len = MIIASECC_AID.len; + + LOG_FUNC_RETURN(ctx, SC_SUCCESS); +} + +static int +iasecc_init_mi(struct sc_card *card) +{ + struct sc_context *ctx = card->ctx; + unsigned int flags; + unsigned char resp[0x100]; + size_t resp_len; + int rv = 0; + + LOG_FUNC_CALLED(ctx); + + flags = IASECC_CARD_DEFAULT_FLAGS; + + _sc_card_add_rsa_alg(card, 1024, flags, 0x10001); + _sc_card_add_rsa_alg(card, 2048, flags, 0x10001); + + card->caps = SC_CARD_CAP_RNG; + card->caps |= SC_CARD_CAP_APDU_EXT; + card->caps |= SC_CARD_CAP_USE_FCI_AC; + + resp_len = sizeof(resp); + rv = iasecc_select_aid(card, &MIIASECC_AID, resp, &resp_len); + LOG_TEST_RET(ctx, rv, "Could not select MI's AID"); + + rv = iasecc_mi_match(card); + LOG_TEST_RET(ctx, rv, "Could not match MI's AID"); + + LOG_FUNC_RETURN(ctx, SC_SUCCESS); +} + static int iasecc_init(struct sc_card *card) { @@ -589,6 +642,8 @@ iasecc_init(struct sc_card *card) rv = iasecc_init_sagem(card); else if (card->type == SC_CARD_TYPE_IASECC_AMOS) rv = iasecc_init_amos(card); + else if (card->type == SC_CARD_TYPE_IASECC_MI) + rv = iasecc_init_mi(card); else LOG_FUNC_RETURN(ctx, SC_ERROR_NO_CARD_SUPPORT); @@ -879,7 +934,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, if (card->type != SC_CARD_TYPE_IASECC_GEMALTO && card->type != SC_CARD_TYPE_IASECC_OBERTHUR && card->type != SC_CARD_TYPE_IASECC_SAGEM - && card->type != SC_CARD_TYPE_IASECC_AMOS) + && card->type != SC_CARD_TYPE_IASECC_AMOS + && card->type != SC_CARD_TYPE_IASECC_MI) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported card"); if (lpath.type == SC_PATH_TYPE_FILE_ID) { @@ -890,6 +946,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, } if (card->type == SC_CARD_TYPE_IASECC_AMOS) apdu.p2 = 0x04; + if (card->type == SC_CARD_TYPE_IASECC_MI) + apdu.p2 = 0x04; } else if (lpath.type == SC_PATH_TYPE_FROM_CURRENT) { apdu.p1 = 0x09; @@ -897,6 +955,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, apdu.p2 = 0x04; if (card->type == SC_CARD_TYPE_IASECC_AMOS) apdu.p2 = 0x04; + if (card->type == SC_CARD_TYPE_IASECC_MI) + apdu.p2 = 0x04; } else if (lpath.type == SC_PATH_TYPE_PARENT) { apdu.p1 = 0x03; diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index 229940b1..fe629381 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -190,6 +190,7 @@ enum { SC_CARD_TYPE_IASECC_OBERTHUR, SC_CARD_TYPE_IASECC_SAGEM, SC_CARD_TYPE_IASECC_AMOS, + SC_CARD_TYPE_IASECC_MI, /* SmartCard-HSM */ SC_CARD_TYPE_SC_HSM = 26000, From c019a6230900e0703c2b701332f9cb34166adc0e Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 28 Mar 2015 01:36:52 +0100 Subject: [PATCH 134/306] pkcs11: parameter checking for 'get_mechanism_list' fixes #409 --- src/pkcs11/mechanism.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index 0dbcf394..63506382 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -83,6 +83,9 @@ sc_pkcs11_get_mechanism_list(struct sc_pkcs11_card *p11card, unsigned int n, count = 0; int rv; + if (!p11card) + return CKR_TOKEN_NOT_PRESENT; + for (n = 0; n < p11card->nmechanisms; n++) { if (!(mt = p11card->mechanisms[n])) continue; From 5149dd3e62594eb2477f699d834584991ab54d5f Mon Sep 17 00:00:00 2001 From: Wouter Verhelst Date: Thu, 26 Mar 2015 13:16:04 +0100 Subject: [PATCH 135/306] belpic: Support 2K cards Recent BELPIC cards (issued since March 2014) have a validity of 10 years (rather than 5 as before), and therefore also increased the key size from 1024 bits to 2048 bits. Key size can be detected by checking the applet version, for which we have to issue a "GetCardData" command. If the applet is version 0x17 or higher, keys are 2048 bits. Use #defines rather than magic numbers Keeps the code slightly more readable. While we're at it, refactor slightly so that the code which issues the GET CARD DATA command doesn't just keep the applet version, but also makes other things available. This latter in preparation of setting the serial number. --- src/libopensc/card-belpic.c | 84 +++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/src/libopensc/card-belpic.c b/src/libopensc/card-belpic.c index 73969d06..cfb963eb 100644 --- a/src/libopensc/card-belpic.c +++ b/src/libopensc/card-belpic.c @@ -127,6 +127,40 @@ static long t1, t2, tot_read = 0, tot_dur = 0, dur; #define BELPIC_PAD_CHAR 0xFF #define BELPIC_KEY_REF_NONREP 0x83 +/* Data in the return value for the GET CARD DATA command: + * All fields are one byte, except when noted otherwise. + * + * See §6.9 in + * https://github.com/Fedict/eid-mw/blob/master/doc/sdk/documentation/Public_Belpic_Applet_v1%207_Ref_Manual%20-%20A01.pdf + * for the full documentation on the GET CARD DATA command. + */ +// Card serial number (16 bytes) +#define BELPIC_CARDDATA_OFF_SERIALNUM 0 +// "Component code" +#define BELPIC_CARDDATA_OFF_COMPCODE 16 +// "OS number" +#define BELPIC_CARDDATA_OFF_OSNUM 17 +// "OS version" +#define BELPIC_CARDDATA_OFF_OSVER 18 +// "Softmask number" +#define BELPIC_CARDDATA_OFF_SMNUM 19 +// "Softmask version" +#define BELPIC_CARDDATA_OFF_SMVER 20 +// Applet version +#define BELPIC_CARDDATA_OFF_APPLETVERS 21 +// Global OS version (2 bytes) +#define BELPIC_CARDDATA_OFF_GL_OSVE 22 +// Applet interface version +#define BELPIC_CARDDATA_OFF_APPINTVERS 24 +// PKCS#1 support version +#define BELPIC_CARDDATA_OFF_PKCS1 25 +// Key exchange version +#define BELPIC_CARDDATA_OFF_KEYX 26 +// Applet life cycle (Should always be 0F for released cards, is 07 when not issued yet) +#define BELPIC_CARDDATA_OFF_APPLCYCLE 27 +// Full length of reply +#define BELPIC_CARDDATA_RESP_LEN 28 + /* Used for a trick in select file and read binary */ static size_t next_idx = (size_t)-1; @@ -577,6 +611,42 @@ static int str2lang(sc_context_t *ctx, char *lang) return -1; } +static int get_carddata(sc_card_t *card, u8* carddata_loc, unsigned int carddataloc_len) +{ + sc_apdu_t apdu; + u8 carddata_cmd[] = { 0x80, 0xE4, 0x00, 0x00, 0x1C }; + int r; + + assert(carddataloc_len == BELPIC_CARDDATA_RESP_LEN); + + r = sc_bytes2apdu(card->ctx, carddata_cmd, sizeof(carddata_cmd), &apdu); + if(r) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "bytes to APDU conversion failed: %d\n", r); + return r; + } + + apdu.resp = carddata_loc; + apdu.resplen = carddataloc_len; + + r = sc_transmit_apdu(card, &apdu); + if(r) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "GetCardData command failed: %d\n", r); + return r; + } + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if(r) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "GetCardData: card returned %d\n", r); + return r; + } + if(apdu.resplen < carddataloc_len) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "GetCardData: card returned %d bytes rather than expected %d\n", apdu.resplen, carddataloc_len); + return SC_ERROR_WRONG_LENGTH; + } + + return 0; +} + #ifdef GET_LANG_FROM_CARD /* str is in lower case, the case of buf can be both, and buf is large enough */ @@ -843,9 +913,10 @@ static int belpic_init(sc_card_t *card) { struct belpic_priv_data *priv = NULL; scconf_block *conf_block; -#ifdef BELPIC_PIN_PAD + u8 applet_version; + u8 carddata[BELPIC_CARDDATA_RESP_LEN]; + int key_size = 1024; int r; -#endif sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Belpic V%s", BELPIC_VERSION); #ifdef HAVE_GUI @@ -865,7 +936,14 @@ static int belpic_init(sc_card_t *card) card->drv_data = priv; card->cla = 0x00; if (card->type == SC_CARD_TYPE_BELPIC_EID) { - _sc_card_add_rsa_alg(card, 1024, + if((r = get_carddata(card, carddata, sizeof(carddata))) < 0) { + return r; + } + applet_version = carddata[BELPIC_CARDDATA_OFF_APPLETVERS]; + if(applet_version >= 0x17) { + key_size = 2048; + } + _sc_card_add_rsa_alg(card, key_size, SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE, 0); } From b1bdfae20094de41c5d8435dc4d64b8896e04773 Mon Sep 17 00:00:00 2001 From: Andreas Schwier Date: Sun, 22 Mar 2015 17:38:51 +0100 Subject: [PATCH 136/306] sc-hsm: revert broken a4c8d671 sc-hsm: Fixed minimum value for number of password shares --- src/tools/sc-hsm-tool.c | 67 +++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index ce76bbf0..b900db27 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -420,7 +420,11 @@ static int cleanUpShares(secret_share_t *shares, unsigned char n) void clearScreen() { - if (system( "clear" )) system( "cls" ); + if (system( "clear" )) { + if (system( "cls" )) { + fprintf(stderr, "Clearing the screen failed\n"); + } + } } @@ -591,6 +595,11 @@ static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_pas secret_share_t *shares = NULL; secret_share_t *sp; + if (num_of_password_shares < 2) { + fprintf(stderr, "--pwd-shares-total must 2 or larger\n"); + return -1; + } + /* * Initialize prime and secret */ @@ -605,7 +614,10 @@ static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_pas printf("\nPlease remember to present the share id as well as the share value."); printf("\n\nPlease enter prime: "); memset(inbuf, 0, sizeof(inbuf)); - fgets(inbuf, sizeof(inbuf), stdin); + if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) { + fprintf(stderr, "Input aborted\n"); + return -1; + } binlen = 64; sc_hex_to_bin(inbuf, bin, &binlen); BN_bin2bn(bin, binlen, &prime); @@ -626,13 +638,19 @@ static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_pas printf("Please enter share ID: "); memset(inbuf, 0, sizeof(inbuf)); - fgets(inbuf, sizeof(inbuf), stdin); + if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) { + fprintf(stderr, "Input aborted\n"); + return -1; + } p = &(sp->x); BN_hex2bn(&p, inbuf); printf("Please enter share value: "); memset(inbuf, 0, sizeof(inbuf)); - fgets(inbuf, sizeof(inbuf), stdin); + if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) { + fprintf(stderr, "Input aborted\n"); + return -1; + } binlen = 64; sc_hex_to_bin(inbuf, bin, &binlen); BN_bin2bn(bin, binlen, &(sp->y)); @@ -803,10 +821,9 @@ static void ask_for_password(char **pwd, int *pwdlen) -static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, unsigned int password_shares_total) +static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total) { - int r; - unsigned int i; + int r, i; BIGNUM prime; BIGNUM secret; unsigned char buf[64]; @@ -818,6 +835,26 @@ static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int pas u8 rngseed[16]; + if ((password_shares_threshold == -1) || (password_shares_total == -1)) { + fprintf(stderr, "Must specify both, --pwd-shares-total and --pwd-shares-threshold\n"); + return -1; + } + + if (password_shares_total < 3) { + fprintf(stderr, "--pwd-shares-total must be 3 or larger\n"); + return -1; + } + + if (password_shares_threshold < 2) { + fprintf(stderr, "--pwd-shares-threshold must 2 or larger\n"); + return -1; + } + + if (password_shares_threshold > password_shares_total) { + fprintf(stderr, "--pwd-shares-threshold must be smaller or equal to --pwd-shares-total\n"); + return -1; + } + printf( "\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n"); printf( "This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total); @@ -908,7 +945,7 @@ static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int pas -static int create_dkek_share(sc_card_t *card, const char *outf, int iter, const char *password, int password_shares_threshold, unsigned int password_shares_total) +static int create_dkek_share(sc_card_t *card, const char *outf, int iter, const char *password, int password_shares_threshold, int password_shares_total) { EVP_CIPHER_CTX ctx; FILE *out = NULL; @@ -923,8 +960,7 @@ static int create_dkek_share(sc_card_t *card, const char *outf, int iter, const } if (password == NULL) { - - if (password_shares_threshold == -1) { + if ((password_shares_threshold == -1) && (password_shares_total == -1)) { ask_for_password(&pwd, &pwdlen); } else { // create password using threshold scheme r = generate_pwd_shares(card, &pwd, &pwdlen, password_shares_threshold, password_shares_total); @@ -1569,15 +1605,8 @@ int main(int argc, char * const argv[]) if (do_initialize && initialize(card, opt_so_pin, opt_pin, opt_retry_counter, opt_dkek_shares, opt_label)) goto fail; - if (do_create_dkek_share) { - if (opt_password_shares_total <= 0) { - fprintf(stderr, "The number of password shares must be bigger than 0."); - goto fail; - } - - if (create_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_threshold, opt_password_shares_total)) - goto fail; - } + if (do_create_dkek_share && create_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_threshold, opt_password_shares_total)) + goto fail; if (do_import_dkek_share && import_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_total)) goto fail; From f3573ede0db55b1ce08a3d8d71d7236cfa618761 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 25 Mar 2015 06:04:34 +0100 Subject: [PATCH 137/306] fixed requesting PACE features --- src/libopensc/reader-pcsc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index a54e2a8f..06192cf3 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -762,7 +762,7 @@ static int pcsc_finish(sc_context_t *ctx) * * @return Bitmask of \c SC_READER_CAP_PACE_GENERIC, \c SC_READER_CAP_PACE_EID and \c * SC_READER_CAP_PACE_ESIGN logically OR'ed if supported */ -static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader) +static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader, SCARDHANDLE card_handle) { u8 pace_capabilities_buf[] = { PACE_FUNCTION_GetReaderPACECapabilities, /* idxFunction */ @@ -770,7 +770,7 @@ static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader) }; u8 rbuf[7]; u8 *p = rbuf; - size_t rcount = sizeof rbuf; + DWORD rcount = sizeof rbuf; struct pcsc_private_data *priv; unsigned long flags = 0; @@ -780,10 +780,11 @@ static unsigned long part10_detect_pace_capabilities(sc_reader_t *reader) if (!priv) goto err; - if (priv->pace_ioctl) { - if (0 > pcsc_internal_transmit(reader, pace_capabilities_buf, - sizeof pace_capabilities_buf, rbuf, &rcount, - priv->pace_ioctl)) { + if (priv->pace_ioctl && priv->gpriv) { + if (SCARD_S_SUCCESS != priv->gpriv->SCardControl(card_handle, + priv->pace_ioctl, pace_capabilities_buf, + sizeof pace_capabilities_buf, rbuf, sizeof(rbuf), + &rcount)) { sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "PC/SC v2 part 10 amd1: Get PACE properties failed!"); goto err; @@ -929,7 +930,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) if (priv->pace_ioctl) { const char *log_text = "Reader supports PACE"; if (priv->gpriv->enable_pace) { - reader->capabilities |= part10_detect_pace_capabilities(reader); + reader->capabilities |= part10_detect_pace_capabilities(reader, card_handle); if (reader->capabilities & SC_READER_CAP_PACE_GENERIC) sc_log(ctx, log_text); From 4b51b997482d30e62725176422a98689958d77fa Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Sun, 22 Mar 2015 13:49:00 +0100 Subject: [PATCH 138/306] pkcs11-tool: harmonize supported ECC curves pkcs15-pubkey.c holds a struct containing supported ECC curves. The contents of this struct are being harmonized with pkcs11-tool supported curves. --- src/libopensc/pkcs15-pubkey.c | 1 + src/tools/pkcs11-tool.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 8fbf418c..189e413e 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1404,6 +1404,7 @@ static struct ec_curve_info { {"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224}, {"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256}, {"brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", "06092B2403030208010109", 320}, + {"secp192k1", "1.3.132.0.31", "06052B8104001F", 192}, {"secp256k1", "1.3.132.0.10", "06052B8104000A", 256}, {NULL, NULL, NULL, 0}, diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 15cee833..f5eb7f63 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -64,19 +64,29 @@ static struct ec_curve_info { size_t size; } ec_curve_infos[] = { {"secp192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, - {"prime192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, {"prime192v1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, + {"nistp192", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, {"ansiX9p192r1", "1.2.840.10045.3.1.1", "06082A8648CE3D030101", 192}, + + {"secp224r1", "1.3.132.0.33", "06052b81040021", 224}, + {"nistp224", "1.3.132.0.33", "06052b81040021", 224}, + {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, {"secp256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, {"ansiX9p256r1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256}, + {"secp384r1", "1.3.132.0.34", "06052B81040022", 384}, {"prime384v1", "1.3.132.0.34", "06052B81040022", 384}, {"ansiX9p384r1", "1.3.132.0.34", "06052B81040022", 384}, + + {"secp521r1", "1.3.132.0.35", "06052B81040023", 521}, + {"nistp521", "1.3.132.0.35", "06052B81040023", 521}, + {"brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", "06092B2403030208010103", 192}, {"brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", "06092B2403030208010105", 224}, {"brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", "06092B2403030208010107", 256}, {"brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", "06092B2403030208010109", 320}, + {"secp192k1", "1.3.132.0.31", "06052B8104001F", 192}, {"secp256k1", "1.3.132.0.10", "06052B8104000A", 256}, {NULL, NULL, NULL, 0}, From 090aed2fc239e4a2eda2fac5b4f22a7b281da275 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 29 Mar 2015 13:08:01 +0200 Subject: [PATCH 139/306] ec: fix length of allocated mem for EC signature discussion in PR #398 --- src/libopensc/card-isoApplet.c | 2 +- src/libopensc/card-myeid.c | 4 ++-- src/libopensc/pkcs15-sec.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index d3364cb1..8b39f914 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -1207,7 +1207,7 @@ isoApplet_compute_signature(struct sc_card *card, if(drvdata->sec_env_alg_ref == ISOAPPLET_ALG_REF_ECDSA) { u8* p = NULL; - size_t len = drvdata->sec_env_ec_field_length / 4; + size_t len = (drvdata->sec_env_ec_field_length + 7) / 8 * 2; if (len > outlen) LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 63a35119..e8c28ec9 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -816,10 +816,10 @@ myeid_convert_ec_signature(struct sc_context *ctx, size_t s_len, unsigned char * if (*data != 0x30 || *(data + 1) != (datalen - 2) || *(data + 2) != 0x02) return SC_ERROR_INVALID_DATA; - buf = calloc(1, s_len/4); + buf = calloc(1, (s_len + 7)/8*2); if (!buf) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); - buflen = s_len/4; + buflen = (s_len + 7)/8*2; r = sc_asn1_sig_value_sequence_to_rs(ctx, data, datalen, buf, buflen); LOG_TEST_RET(ctx, r, "Failed to cenvert Sig-Value to the raw RS format"); diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index 3b8764ff..3b3366b0 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -218,8 +218,8 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card, LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } - if (out == NULL || *poutlen < (prkey->field_length +7) / 8) { - *poutlen = (prkey->field_length +7) / 8; + if (out == NULL || *poutlen < (prkey->field_length + 7) / 8) { + *poutlen = (prkey->field_length + 7) / 8; r = 0; /* say no data to return */ goto out; } From bba6e17aa982443a0a5337d21649d26201f899b0 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Sat, 21 Mar 2015 10:24:01 +0100 Subject: [PATCH 140/306] isoApplet: Fix indentation of isoApplet.profile --- src/pkcs15init/isoApplet.profile | 234 +++++++++++++++---------------- 1 file changed, 114 insertions(+), 120 deletions(-) diff --git a/src/pkcs15init/isoApplet.profile b/src/pkcs15init/isoApplet.profile index acf252bf..2f7df105 100644 --- a/src/pkcs15init/isoApplet.profile +++ b/src/pkcs15init/isoApplet.profile @@ -5,160 +5,154 @@ # cardinfo { - label = "JavaCard isoApplet"; - manufacturer = "unknown"; - min-pin-length = 4; - max-pin-length = 16; - pin-pad-char = 0x00; + label ="JavaCard isoApplet"; + manufacturer = "unknown"; + min-pin-length = 4; + max-pin-length = 16; + pin-pad-char = 0x00; } pkcs15 { - # Method to calculate ID of the crypto objects - # mozilla: SHA1(modulus) for RSA, SHA1(pub) for DSA - # rfc2459: SHA1(SequenceASN1 of public key components as ASN1 integers) - # native: 'E' + number_of_present_objects_of_the_same_type - # default value: 'native' - pkcs15-id-style = native; + # Method to calculate ID of the crypto objects + # mozilla: SHA1(modulus) for RSA, SHA1(pub) for DSA + # rfc2459: SHA1(SequenceASN1 of public key components as ASN1 integers) + # native: 'E' + number_of_present_objects_of_the_same_type + # default value: 'native' + pkcs15-id-style = native; } option default { macros { unusedspace-size = 128; - odf-size = 256; - aodf-size = 256; - cdf-size = 512; + odf-size = 256; + aodf-size = 256; + cdf-size = 512; prkdf-size = 512; pukdf-size = 512; - dodf-size = 256; + dodf-size = 256; } } PIN so-pin { - attempts = 3; + attempts = 3; max-length = 16; min-length = 4; - reference = 1; + reference = 1; flags = case-sensitive, needs-padding; } PIN so-puk { - attempts = 3; + attempts = 3; max-length = 16; min-length = 16; - reference = 2; + reference = 2; flags = unblockingPin, unblock-disabled, case-sensitive, change-disabled; } filesystem { - DF MF { - path = 3F00; - type = DF; - - # This is the DIR file - EF DIR { - type = EF; - file-id = 2F00; - size = 128; - acl = *=NONE; - } - - # Here comes the application DF - DF PKCS15-AppDF { + DF MF { + path = 3F00; type = DF; - file-id = 5015; - aid = A0:00:00:00:63:50:4B:43:53:2D:31:35; - acl = *=NONE, DELETE=$PIN; - size = 5000; + + # This is the DIR file + EF DIR { + type = EF; + file-id = 2F00; + size = 128; + acl = *=NONE; + } + + # Here comes the application DF + DF PKCS15-AppDF { + type = DF; + file-id = 5015; + aid = A0:00:00:00:63:50:4B:43:53:2D:31:35; + acl = *=NONE, DELETE=$PIN; + size = 5000; - EF PKCS15-ODF { - file-id = 5031; - size = $odf-size; - ACL = *=NONE; - } - - EF PKCS15-TokenInfo { - file-id = 5032; - ACL = *=NONE; - } - - EF PKCS15-UnusedSpace { - file-id = 5033; - size = $unusedspace-size; - ACL = *=NONE; - } - - EF PKCS15-AODF { - file-id = 4401; - size = $aodf-size; - ACL = *=$PIN, READ=NONE; - } - - EF PKCS15-PrKDF { - file-id = 4402; - size = $prkdf-size; - acl = *=$PIN, READ=NONE; - } - - EF PKCS15-PuKDF { - file-id = 4403; - size = $pukdf-size; - acl = *=$PIN, READ=NONE; - } - - EF PKCS15-CDF { - file-id = 4404; - size = $cdf-size; - acl = *=$PIN, READ=NONE; - } - - EF PKCS15-DODF { - file-id = 4405; - size = $dodf-size; - ACL = *=$PIN, READ=NONE; - } - - template key-domain { - - BSO private-key { - ACL = *=$PIN, READ=NEVER; + EF PKCS15-ODF { + file-id = 5031; + size = $odf-size; + ACL = *=NONE; } - # EF private-key { - # file-id = 3000; - # acl = *=NEVER, UPDATE=$PIN, ERASE=$PIN; - # } + EF PKCS15-TokenInfo { + file-id = 5032; + ACL = *=NONE; + } - # EF extractable-key { - # file-id = 3100; - # acl = *=NEVER, READ=$PIN, UPDATE=$PIN, - # ERASE=$PIN; - # } - - EF data { - file-id = 3200; - acl = *=NEVER, UPDATE=$PIN, READ=NONE, - DELETE-SELF=$PIN, ERASE=$PIN; - } + EF PKCS15-UnusedSpace { + file-id = 5033; + size = $unusedspace-size; + ACL = *=NONE; + } - EF privdata { - file-id = 3500; - acl = *=NEVER, UPDATE=$PIN, READ=$PIN, - DELETE-SELF=$PIN, ERASE=$PIN; - } + EF PKCS15-AODF { + file-id = 4401; + size = $aodf-size; + ACL = *=$PIN, READ=NONE; + } - EF public-key { - file-id = 3300; - acl = *=NEVER, UPDATE=$PIN, READ=NONE, - DELETE-SELF=$PIN, ERASE=$PIN; - } + EF PKCS15-PrKDF { + file-id = 4402; + size = $prkdf-size; + acl = *=$PIN, READ=NONE; + } - EF certificate { - file-id = 3400; - acl = *=NEVER, UPDATE=$PIN, READ=NONE, - DELETE-SELF=$PIN, ERASE=$PIN; - } + EF PKCS15-PuKDF { + file-id = 4403; + size = $pukdf-size; + acl = *=$PIN, READ=NONE; + } - } + EF PKCS15-CDF { + file-id = 4404; + size = $cdf-size; + acl = *=$PIN, READ=NONE; + } + + EF PKCS15-DODF { + file-id = 4405; + size = $dodf-size; + ACL = *=$PIN, READ=NONE; + } + + template key-domain { + + BSO private-key { + ACL = *=$PIN, READ=NEVER; + } + + # EF extractable-key { + # file-id = 3100; + # acl = *=NEVER, READ=$PIN, UPDATE=$PIN, + # ERASE=$PIN; + # } + + EF data { + file-id = 3200; + acl = *=NEVER, UPDATE=$PIN, READ=NONE, + DELETE-SELF=$PIN, ERASE=$PIN; + } + + EF privdata { + file-id = 3500; + acl = *=NEVER, UPDATE=$PIN, READ=$PIN, + DELETE-SELF=$PIN, ERASE=$PIN; + } + + EF public-key { + file-id = 3300; + acl = *=NEVER, UPDATE=$PIN, READ=NONE, + DELETE-SELF=$PIN, ERASE=$PIN; + } + + EF certificate { + file-id = 3400; + acl = *=NEVER, UPDATE=$PIN, READ=NONE, + DELETE-SELF=$PIN, ERASE=$PIN; + } + } + } } - } } From ab5ca331b2d8eb229bc83247fc69ab134ab5cd4f Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Sun, 22 Mar 2015 14:03:02 +0100 Subject: [PATCH 141/306] IsoApplet: Obtain applet version and card capabilities *after* match_card() --- src/libopensc/card-isoApplet.c | 35 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 8b39f914..3062ae94 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -48,6 +48,7 @@ struct isoApplet_drv_data * have to be modified. */ unsigned int sec_env_alg_ref; unsigned int sec_env_ec_field_length; + unsigned int isoapplet_version; }; #define DRVDATA(card) ((struct isoApplet_drv_data *) ((card)->drv_data)) @@ -142,19 +143,12 @@ isoApplet_match_card(sc_card_t *card) } /* The IsoApplet should return an API version (major and minor) and a feature bitmap. + * We expect 3 bytes: MAJOR API version - MINOR API version - API feature bitmap. * If applet does not return API version, versions 0x00 will match */ - if(rlen == 0) + if(rlen < 3) { - rbuf[0] = 0x00; - rbuf[1] = 0x00; - rbuf[2] = 0x00; - rlen = 3; - } - - /* We expect 3 bytes: MAJOR API version - MINOR API version - API feature bitmap */ - if(rlen != 3) - { - return 0; + assert(sizeof(rbuf) >= 3); + memset(rbuf, 0x00, 3); } if(rbuf[0] != ISOAPPLET_API_VERSION_MAJOR) @@ -173,11 +167,6 @@ isoApplet_match_card(sc_card_t *card) ISOAPPLET_API_VERSION_MAJOR, ISOAPPLET_API_VERSION_MINOR, rbuf[0], rbuf[1]); } - if(rbuf[2] & ISOAPPLET_API_FEATURE_EXT_APDU) - { - card->caps |= SC_CARD_CAP_APDU_EXT; - } - return 1; } @@ -187,6 +176,8 @@ isoApplet_init(sc_card_t *card) int r; unsigned long flags = 0; unsigned long ext_flags = 0; + size_t rlen = SC_MAX_APDU_BUFFER_SIZE; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; struct isoApplet_drv_data *drvdata; struct sc_object_id curve_oid; @@ -199,6 +190,18 @@ isoApplet_init(sc_card_t *card) card->drv_data = drvdata; card->cla = 0x00; + /* Obtain applet version and specific features */ + r = isoApplet_select_applet(card, isoApplet_aid, ISOAPPLET_AID_LEN, rbuf, &rlen); + LOG_TEST_RET(card->ctx, r, "Error obtaining applet version."); + if(rlen < 3) + { + assert(sizeof(rbuf) >= 3); + memset(rbuf, 0x00, 3); + } + drvdata->isoapplet_version = ((unsigned int)rbuf[0] << 8) | rbuf[1]; + if(rbuf[2] & ISOAPPLET_API_FEATURE_EXT_APDU) + card->caps |= SC_CARD_CAP_APDU_EXT; + /* ECDSA * Curves supported by the pkcs15-init driver are indicated per curve. This * should be kept in sync with the explicit parameters in the pkcs15-init From e258cec13e417ce10c05be6c40fe3539824301b7 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Sun, 22 Mar 2015 14:49:59 +0100 Subject: [PATCH 142/306] IsoApplet: Add nistp224, secp192k1 and secp256k1 curves secp*k1 curves are only supported applet version >= 0.6.0 because of an issue with encoding ECC public keys with small parameters. --- src/libopensc/card-isoApplet.c | 52 ++++++++++++++----------------- src/pkcs15init/pkcs15-isoApplet.c | 35 ++++++++++++++++++++- 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 3062ae94..38b8556e 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -68,6 +68,23 @@ static struct sc_card_driver isoApplet_drv = NULL, 0, NULL }; +static struct isoapplet_supported_ec_curves { + struct sc_object_id oid; + size_t size; + unsigned int min_applet_version; +} ec_curves[] = { + {{{1, 2, 840, 10045, 3, 1, 1, -1}}, 192, 0x0000}, /* secp192r1, nistp192, prime192v1, ansiX9p192r1 */ + {{{1, 3, 132, 0, 33, -1}}, 224, 0x0000}, /* secp224r1, nistp224 */ + {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, 0x0000}, /* secp256r1, nistp256, prime256v1, ansiX9p256r1 */ + {{{1, 3, 132, 0, 34, -1}}, 384, 0x0000}, /* secp384r1, nistp384, prime384v1, ansiX9p384r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 3, -1}}, 192, 0x0000}, /* brainpoolP192r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 5, -1}}, 224, 0x0000}, /* brainpoolP224r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256, 0x0000}, /* brainpoolP256r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 9, -1}}, 320, 0x0000}, /* brainpoolP320r1 */ + {{{1, 3, 132, 0, 31, -1}}, 192, 0x0006}, /* secp192k1 */ + {{{1, 3, 132, 0, 10, -1}}, 256, 0x0006}, /* secp256k1 */ + {{{-1}}, 0, 0} /* This entry must not be touched. */ +}; /* * SELECT an applet on the smartcard. (Not in the emulated filesystem.) @@ -174,12 +191,12 @@ static int isoApplet_init(sc_card_t *card) { int r; + int i; unsigned long flags = 0; unsigned long ext_flags = 0; size_t rlen = SC_MAX_APDU_BUFFER_SIZE; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; struct isoApplet_drv_data *drvdata; - struct sc_object_id curve_oid; LOG_FUNC_CALLED(card->ctx); @@ -211,34 +228,11 @@ isoApplet_init(sc_card_t *card) flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; ext_flags |= SC_ALGORITHM_EXT_EC_F_P; - /* secp192r1, prime192r1, ansiX9p192r1*/ - r = sc_format_oid(&curve_oid, "1.2.840.10045.3.1.1"); - LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); - _sc_card_add_ec_alg(card, 192, flags, ext_flags, &curve_oid); - /* prime256v1, secp256r1, ansiX9p256r1 */ - r = sc_format_oid(&curve_oid, "1.2.840.10045.3.1.7"); - LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); - _sc_card_add_ec_alg(card, 256, flags, ext_flags, &curve_oid); - /* secp384r1, prime384v1, ansiX9p384r1 */ - r = sc_format_oid(&curve_oid, "1.3.132.0.34"); - LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); - _sc_card_add_ec_alg(card, 384, flags, ext_flags, &curve_oid); - /* brainpoolP192r1 */ - r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.3"); - LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); - _sc_card_add_ec_alg(card, 192, flags, ext_flags, &curve_oid); - /* brainpoolP224r1 */ - r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.5"); - LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); - _sc_card_add_ec_alg(card, 224, flags, ext_flags, &curve_oid); - /* brainpoolP256r1 */ - r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.7"); - LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); - _sc_card_add_ec_alg(card, 256, flags, ext_flags, &curve_oid); - /* brainpoolP320r1 */ - r = sc_format_oid(&curve_oid, "1.3.36.3.3.2.8.1.1.9"); - LOG_TEST_RET(card->ctx, r, "Error obtaining EC curve OID"); - _sc_card_add_ec_alg(card, 320, flags, ext_flags, &curve_oid); + for (i=0; ec_curves[i].oid.value[0] >= 0; i++) + { + if(drvdata->isoapplet_version >= ec_curves[i].min_applet_version) + _sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].oid); + } /* RSA */ flags = 0; diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index b4095a85..bbcc7e17 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -98,7 +98,7 @@ static const struct ec_curve curves[] = }, { - /* prime192r1, secp192r1, ansiX9p192r1 */ + /* prime192v1, secp192r1, ansiX9p192r1 */ { (unsigned char *) "\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x01", 10}, { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 24}, @@ -108,6 +108,17 @@ static const struct ec_curve curves[] = { (unsigned char *) "\x00\x01", 2} }, + { + /* prime224v1, nistp224 */ + { (unsigned char *) "\x06\x05\x2b\x81\x04\x00\x21", 7}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 28}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE", 28}, + { (unsigned char *) "\xB4\x05\x0A\x85\x0C\x04\xB3\xAB\xF5\x41\x32\x56\x50\x44\xB0\xB7\xD7\xBF\xD8\xBA\x27\x0B\x39\x43\x23\x55\xFF\xB4", 28}, + { (unsigned char *) "\x04\xB7\x0E\x0C\xBD\x6B\xB4\xBF\x7F\x32\x13\x90\xB9\x4A\x03\xC1\xD3\x56\xC2\x11\x22\x34\x32\x80\xD6\x11\x5C\x1D\x21\xBD\x37\x63\x88\xB5\xF7\x23\xFB\x4C\x22\xDF\xE6\xCD\x43\x75\xA0\x5A\x07\x47\x64\x44\xD5\x81\x99\x85\x00\x7E\x34", 57}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\xA2\xE0\xB8\xF0\x3E\x13\xDD\x29\x45\x5C\x5C\x2A\x3D", 28}, + { (unsigned char *) "\x00\x01", 2} + }, + { /* prime256v1, secp256r1, ansiX9p256r1 */ { (unsigned char *) "\x06\x08\x2A\x86\x48\xCE\x3D\x03\x01\x07", 10}, @@ -130,6 +141,28 @@ static const struct ec_curve curves[] = { (unsigned char *) "\x00\x01", 2} }, + { + /* secp192k1 */ + { (unsigned char *) "\x06\x05\x2B\x81\x04\x00\x1F", 7}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xEE\x37", 24}, + { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 24}, + { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", 24}, + { (unsigned char *) "\x04\xDB\x4F\xF1\x0E\xC0\x57\xE9\xAE\x26\xB0\x7D\x02\x80\xB7\xF4\x34\x1D\xA5\xD1\xB1\xEA\xE0\x6C\x7D\x9B\x2F\x2F\x6D\x9C\x56\x28\xA7\x84\x41\x63\xD0\x15\xBE\x86\x34\x40\x82\xAA\x88\xD9\x5E\x2F\x9D", 49}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\x26\xF2\xFC\x17\x0F\x69\x46\x6A\x74\xDE\xFD\x8D", 24}, + { (unsigned char *) "\x00\x01", 2} + }, + + { + /* secp256k1 */ + { (unsigned char *) "\x06\x05\x2B\x81\x04\x00\x0A", 7}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFC\x2F", 32}, + { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32}, + { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07", 32}, + { (unsigned char *) "\x04\x79\xBE\x66\x7E\xF9\xDC\xBB\xAC\x55\xA0\x62\x95\xCE\x87\x0B\x07\x02\x9B\xFC\xDB\x2D\xCE\x28\xD9\x59\xF2\x81\x5B\x16\xF8\x17\x98\x48\x3A\xDA\x77\x26\xA3\xC4\x65\x5D\xA4\xFB\xFC\x0E\x11\x08\xA8\xFD\x17\xB4\x48\xA6\x85\x54\x19\x9C\x47\xD0\x8F\xFB\x10\xD4\xB8", 65}, + { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xBA\xAE\xDC\xE6\xAF\x48\xA0\x3B\xBF\xD2\x5E\x8C\xD0\x36\x41\x41", 32}, + { (unsigned char *) "\x00\x01", 2} + }, + { { NULL, 0}, { NULL, 0}, From 76facf0d73deea58bb15a8b8771006ef43e74bf3 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Mon, 23 Mar 2015 00:08:11 +0100 Subject: [PATCH 143/306] IsoApplet: add support for GET CHALLENGE --- src/libopensc/card-isoApplet.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 38b8556e..6b71bbf0 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -34,7 +34,9 @@ #define ISOAPPLET_API_VERSION_MAJOR 0x00 #define ISOAPPLET_API_VERSION_MINOR 0x05 + #define ISOAPPLET_API_FEATURE_EXT_APDU 0x01 +#define ISOAPPLET_API_FEATURE_SECURE_RANDOM 0x02 #define ISOAPPLET_AID_LEN 12 static const u8 isoApplet_aid[] = {0xf2,0x76,0xa2,0x88,0xbc,0xfb,0xa6,0x9d,0x34,0xf3,0x10,0x01}; @@ -218,6 +220,8 @@ isoApplet_init(sc_card_t *card) drvdata->isoapplet_version = ((unsigned int)rbuf[0] << 8) | rbuf[1]; if(rbuf[2] & ISOAPPLET_API_FEATURE_EXT_APDU) card->caps |= SC_CARD_CAP_APDU_EXT; + if(rbuf[2] & ISOAPPLET_API_FEATURE_SECURE_RANDOM) + card->caps |= SC_CARD_CAP_RNG; /* ECDSA * Curves supported by the pkcs15-init driver are indicated per curve. This @@ -1224,6 +1228,22 @@ isoApplet_compute_signature(struct sc_card *card, LOG_FUNC_RETURN(ctx, r); } +static int +isoApplet_get_challenge(struct sc_card *card, u8 *rnd, size_t len) +{ + struct sc_context *ctx = card->ctx; + int r; + + LOG_FUNC_CALLED(ctx); + + if(card->caps & SC_CARD_CAP_RNG) { + r = iso_ops->get_challenge(card, rnd, len); + } else { + r = SC_ERROR_NOT_SUPPORTED; + } + LOG_FUNC_RETURN(ctx, r); +} + static struct sc_card_driver *sc_get_driver(void) { sc_card_driver_t *iso_drv = sc_get_iso7816_driver(); @@ -1245,6 +1265,7 @@ static struct sc_card_driver *sc_get_driver(void) isoApplet_ops.process_fci = isoApplet_process_fci; isoApplet_ops.set_security_env = isoApplet_set_security_env; isoApplet_ops.compute_signature = isoApplet_compute_signature; + isoApplet_ops.get_challenge = isoApplet_get_challenge; /* unsupported functions */ isoApplet_ops.write_binary = NULL; @@ -1252,7 +1273,6 @@ static struct sc_card_driver *sc_get_driver(void) isoApplet_ops.write_record = NULL; isoApplet_ops.append_record = NULL; isoApplet_ops.update_record = NULL; - isoApplet_ops.get_challenge = NULL; isoApplet_ops.restore_security_env = NULL; return &isoApplet_drv; From 907885667596b50b4e5be28e6afbb54433b5ec48 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Mon, 23 Mar 2015 00:09:30 +0100 Subject: [PATCH 144/306] IsoApplet: register ECC mechanisms only when ECC is supported by card There are few Java Cards that do not support ECDSA at all. Starting with IsoApplet version 00.06, the applet returns whether the card supports ECDSA or not. This commit uses this information to decider whether to register ECDSA mechanisms or not. --- src/libopensc/card-isoApplet.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index 6b71bbf0..dae960d9 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -37,6 +37,7 @@ #define ISOAPPLET_API_FEATURE_EXT_APDU 0x01 #define ISOAPPLET_API_FEATURE_SECURE_RANDOM 0x02 +#define ISOAPPLET_API_FEATURE_ECC 0x04 #define ISOAPPLET_AID_LEN 12 static const u8 isoApplet_aid[] = {0xf2,0x76,0xa2,0x88,0xbc,0xfb,0xa6,0x9d,0x34,0xf3,0x10,0x01}; @@ -222,20 +223,25 @@ isoApplet_init(sc_card_t *card) card->caps |= SC_CARD_CAP_APDU_EXT; if(rbuf[2] & ISOAPPLET_API_FEATURE_SECURE_RANDOM) card->caps |= SC_CARD_CAP_RNG; - - /* ECDSA - * Curves supported by the pkcs15-init driver are indicated per curve. This - * should be kept in sync with the explicit parameters in the pkcs15-init - * driver. */ - flags = 0; - flags |= SC_ALGORITHM_ECDSA_RAW; - flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; - ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; - ext_flags |= SC_ALGORITHM_EXT_EC_F_P; - for (i=0; ec_curves[i].oid.value[0] >= 0; i++) + if(drvdata->isoapplet_version <= 0x0005 || rbuf[2] & ISOAPPLET_API_FEATURE_ECC) { - if(drvdata->isoapplet_version >= ec_curves[i].min_applet_version) - _sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].oid); + /* There are Java Cards that do not support ECDSA at all. The IsoApplet + * started to report this with version 00.06. + * + * Curves supported by the pkcs15-init driver are indicated per curve. This + * should be kept in sync with the explicit parameters in the pkcs15-init + * driver. */ + flags = 0; + flags |= SC_ALGORITHM_ECDSA_RAW; + flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; + flags |= SC_ALGORITHM_EXT_EC_UNCOMPRESES; + ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; + ext_flags |= SC_ALGORITHM_EXT_EC_F_P; + for (i=0; ec_curves[i].oid.value[0] >= 0; i++) + { + if(drvdata->isoapplet_version >= ec_curves[i].min_applet_version) + _sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].oid); + } } /* RSA */ From c8d206ece1e3dd22282cf91c5047d993e316273e Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Wed, 25 Mar 2015 11:21:29 +0100 Subject: [PATCH 145/306] IsoApplet: Increase indicated version to 00.06 Backward compatiblity with 00.05 is kept. --- src/libopensc/card-isoApplet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index dae960d9..b79f0b06 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -33,7 +33,7 @@ #define ISOAPPLET_ALG_REF_RSA_PAD_PKCS1 0x11 #define ISOAPPLET_API_VERSION_MAJOR 0x00 -#define ISOAPPLET_API_VERSION_MINOR 0x05 +#define ISOAPPLET_API_VERSION_MINOR 0x06 #define ISOAPPLET_API_FEATURE_EXT_APDU 0x01 #define ISOAPPLET_API_FEATURE_SECURE_RANDOM 0x02 From 3b873adad2e0fe22ff13cd7c2c9f5e87abe4ba4a Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 28 Mar 2015 10:00:47 +0100 Subject: [PATCH 146/306] win32: allows UNICODE built. UNICODE is set by default by Visual Studio (but can be deactived) The trick is to force ANSI version by appending a A to the function calls. --- src/common/libscdl.c | 6 +++--- src/libopensc/card.c | 8 ++++---- src/libopensc/ctx.c | 8 ++++---- src/libopensc/internal-winscard.h | 7 +++++++ src/libopensc/user-interface.c | 4 ++++ 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/common/libscdl.c b/src/common/libscdl.c index b66dbd5e..a78f9e2f 100644 --- a/src/common/libscdl.c +++ b/src/common/libscdl.c @@ -28,12 +28,12 @@ #include void *sc_dlopen(const char *filename) { - return (void *)LoadLibrary(filename); + return (void *)LoadLibraryA(filename); } void *sc_dlsym(void *handle, const char *symbol) { - return GetProcAddress((HANDLE)handle, symbol); + return GetProcAddress((HMODULE)handle, symbol); } const char *sc_dlerror() @@ -43,7 +43,7 @@ const char *sc_dlerror() int sc_dlclose(void *handle) { - return FreeLibrary((HANDLE)handle); + return FreeLibrary((HMODULE)handle); } #else #include diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 24d22d5b..b949b414 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -1183,20 +1183,20 @@ sc_card_sm_load(struct sc_card *card, const char *module_path, const char *in_mo #ifdef _WIN32 if (!module_path) { - rc = RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey ); + rc = RegOpenKeyExA( HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey ); if( rc == ERROR_SUCCESS ) { temp_len = PATH_MAX; - rc = RegQueryValueEx( hKey, "SmDir", NULL, NULL, (LPBYTE) temp_path, &temp_len); + rc = RegQueryValueExA( hKey, "SmDir", NULL, NULL, (LPBYTE) temp_path, &temp_len); if( (rc == ERROR_SUCCESS) && (temp_len < PATH_MAX) ) module_path = temp_path; RegCloseKey( hKey ); } } if (!module_path) { - rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey ); + rc = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey ); if( rc == ERROR_SUCCESS ) { temp_len = PATH_MAX; - rc = RegQueryValueEx( hKey, "SmDir", NULL, NULL, (LPBYTE) temp_path, &temp_len); + rc = RegQueryValueExA( hKey, "SmDir", NULL, NULL, (LPBYTE) temp_path, &temp_len); if(rc == ERROR_SUCCESS && temp_len < PATH_MAX) module_path = temp_path; RegCloseKey( hKey ); diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index ca05cc81..2297193e 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -245,7 +245,7 @@ load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options * if (val) { #ifdef _WIN32 expanded_len = PATH_MAX; - expanded_len = ExpandEnvironmentStrings(val, expanded_val, expanded_len); + expanded_len = ExpandEnvironmentStringsA(val, expanded_val, expanded_len); if (expanded_len > 0) val = expanded_val; #endif @@ -552,7 +552,7 @@ static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts) #ifdef _WIN32 conf_path = getenv("OPENSC_CONF"); if (!conf_path) { - rc = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey); + rc = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey); if (rc == ERROR_SUCCESS) { temp_len = PATH_MAX; rc = RegQueryValueEx( hKey, "ConfigFile", NULL, NULL, (LPBYTE) temp_path, &temp_len); @@ -563,7 +563,7 @@ static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts) } if (!conf_path) { - rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey ); + rc = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey ); if (rc == ERROR_SUCCESS) { temp_len = PATH_MAX; rc = RegQueryValueEx( hKey, "ConfigFile", NULL, NULL, (LPBYTE) temp_path, &temp_len); @@ -874,7 +874,7 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize) /* If USERPROFILE isn't defined, assume it's a single-user OS * and put the cache dir in the Windows dir (usually C:\\WINDOWS) */ if (homedir == NULL || homedir[0] == '\0') { - GetWindowsDirectory(temp_path, sizeof(temp_path)); + GetWindowsDirectoryA(temp_path, sizeof(temp_path)); homedir = temp_path; } #endif diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h index 7d0b6fdc..1e7bba14 100644 --- a/src/libopensc/internal-winscard.h +++ b/src/libopensc/internal-winscard.h @@ -20,6 +20,13 @@ typedef unsigned __int8 uint8_t; #ifdef __APPLE__ #include #endif +// allow unicode built where SCARD_READERSTATE is defined as SCARD_READERSTATEW and SCardGetStatusChange renamed to SCardGetStatusChangeW +#ifdef WIN32 +#ifdef UNICODE +#define SCARD_READERSTATE SCARD_READERSTATEA +#undef SCardGetStatusChange +#endif +#endif #else /* mingw32 does not have winscard.h */ diff --git a/src/libopensc/user-interface.c b/src/libopensc/user-interface.c index f88aee0f..a8719e7d 100644 --- a/src/libopensc/user-interface.c +++ b/src/libopensc/user-interface.c @@ -35,7 +35,11 @@ #include #ifdef _WIN32 + +#ifndef UNICODE #define UNICODE +#endif + #include #endif #ifdef __APPLE__ From 5007e9fc9fbcd866eef1eb54912fb1d97f805583 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 28 Mar 2015 13:04:41 +0100 Subject: [PATCH 147/306] md: fix build without OPENSSL_VERSION_NUMBER Fix the WCHAR / CHAR conversion problem in CardAuthenticateEx in case of PinPAD (vs->wzPinContext is UNICODE) Fix UNICODE compilation problem( MessageBoxA instead of MessageBox) --- src/minidriver/minidriver.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index a7f3dbe7..8d957d8e 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -323,12 +323,12 @@ check_reader_status(PCARD_DATA pCardData) if (pCardData->hSCardCtx != vs->hSCardCtx || pCardData->hScard != vs->hScard) { logprintf (pCardData, 1, "HANDLES CHANGED from 0x%08X 0x%08X\n", vs->hSCardCtx, vs->hScard); - // Basically a mini AcquireContext + /* Basically a mini AcquireContext */ r = disassociate_card(pCardData); logprintf(pCardData, 1, "disassociate_card r = 0x%08X\n", r); r = associate_card(pCardData); /* need to check return codes */ logprintf(pCardData, 1, "associate_card r = 0x%08X\n", r); - // Rebuild 'soft' fs - in case changed + /* Rebuild 'soft' fs - in case changed */ r = md_fs_init(pCardData); logprintf(pCardData, 1, "md_fs_init r = 0x%08X\n", r); } @@ -1519,7 +1519,11 @@ md_fs_init(PCARD_DATA pCardData) if (dwret != SCARD_S_SUCCESS) return dwret; +#ifdef OPENSSL_VERSION_NUMBER logprintf(pCardData, 3, "MD virtual file system initialized; OPENSSL_VERSION_NUMBER 0x%Xl\n", OPENSSL_VERSION_NUMBER); +#else + logprintf(pCardData, 3, "MD virtual file system initialized; Without OPENSSL\n"); +#endif return SCARD_S_SUCCESS; } @@ -3001,7 +3005,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, } logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r); - // Need to handle padding + /* Need to handle padding */ if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) { logprintf(pCardData, 2, "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%u\n", pInfo->dwVersion); if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) { @@ -3025,7 +3029,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, pbuf, pInfo->cbData, pbuf2, pInfo->cbData); logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r); if (r > 0) { - // No padding info, or padding info none + /* No padding info, or padding info none */ if ((pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) || ((pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) && (pInfo->dwPaddingType == CARD_PADDING_NONE))) { @@ -3041,7 +3045,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, } } else if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) { - // PKCS1 padding is already handled by the card... + /* PKCS1 padding is already handled by the card... */ pInfo->cbData = r; } /* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */ @@ -3335,13 +3339,18 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, vs->reader->capabilities & SC_READER_CAP_PIN_PAD ? "yes" : "no", pbPinData, vs->hwndParent); if ((vs->reader->capabilities & SC_READER_CAP_PIN_PAD) && NULL == pbPinData) { char buf[200]; - snprintf(buf, sizeof(buf), "Please enter PIN %s", - NULL == vs->wszPinContext ? "on reader pinpad." : vs->wszPinContext); + if (NULL == vs->wszPinContext ) { + strcpy(buf, "Please enter PIN on reader pinpad."); + } + else { + /* %S enable the use of UNICODE string (wsPinContext) inside an ANSI string (buf) */ + snprintf(buf, sizeof(buf), "Please enter PIN %S", vs->wszPinContext); + } logprintf(pCardData, 7, "About to display message box for external PIN verification\n"); /* @TODO: Ideally, this should probably be a non-modal dialog with just a cancel button * that goes away as soon as a key is pressed on the pinpad. */ - r = MessageBox(vs->hwndParent, buf, "PIN Entry Required", + r = MessageBoxA(vs->hwndParent, buf, "PIN Entry Required", MB_OKCANCEL | MB_ICONINFORMATION); if (IDCANCEL == r) { logprintf(pCardData, 2, "User canceled PIN verification\n"); @@ -3961,7 +3970,7 @@ BOOL APIENTRY DllMain( HMODULE hModule, CHAR name[MAX_PATH + 1] = "\0"; char *reason = ""; - GetModuleFileName(GetModuleHandle(NULL),name,MAX_PATH); + GetModuleFileNameA(GetModuleHandle(NULL),name,MAX_PATH); switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: From 548c2780d3faf9419c09aea5d5909b5d82685515 Mon Sep 17 00:00:00 2001 From: Robert Quattlebaum Date: Thu, 15 Jan 2015 14:44:21 -0800 Subject: [PATCH 148/306] Add support for ACOS5-64 cards. The ACOS5-64 cards have a different ATR than the original ACOS5-32 cards. This change simply adds this ATR so that it will be recognized properly. --- src/libopensc/card-acos5.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libopensc/card-acos5.c b/src/libopensc/card-acos5.c index 4bc08237..ff6ee3db 100644 --- a/src/libopensc/card-acos5.c +++ b/src/libopensc/card-acos5.c @@ -26,6 +26,8 @@ #include "cardctl.h" static struct sc_atr_table acos5_atrs[] = { + {"3b:be:96:00:00:41:05:20:00:00:00:00:00:00:00:00:00:90:00", NULL, NULL, + SC_CARD_TYPE_ACOS5_GENERIC, 0, NULL}, {"3b:be:18:00:00:41:05:10:00:00:00:00:00:00:00:00:00:90:00", NULL, NULL, SC_CARD_TYPE_ACOS5_GENERIC, 0, NULL}, {NULL, NULL, NULL, 0, 0, NULL} From 117f3a74beb715f7d0fd43bd11a378ecf9db928e Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Tue, 31 Mar 2015 15:33:43 +0200 Subject: [PATCH 149/306] iasecc: Fix key usage when provisioning card * Avoids overriding key_usage when creating objects on the card. --- src/pkcs15init/pkcs15-iasecc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pkcs15init/pkcs15-iasecc.c b/src/pkcs15init/pkcs15-iasecc.c index 99e70468..5f9e8955 100644 --- a/src/pkcs15init/pkcs15-iasecc.c +++ b/src/pkcs15init/pkcs15-iasecc.c @@ -950,9 +950,7 @@ iasecc_pkcs15_fix_private_key_attributes(struct sc_profile *profile, struct sc_p IASECC_ALGORITHM_RSA_PKCS | IASECC_ALGORITHM_SHA2); LOG_TEST_RET(ctx, rv, "Cannot add RSA_PKCS SHA2 supported mechanism"); - key_info->usage |= SC_PKCS15_PRKEY_USAGE_SIGN; if (sdo_prvkey->docp.non_repudiation.value && sdo_prvkey->docp.non_repudiation.value[0]) { - key_info->usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; object->user_consent = 1; } } @@ -960,14 +958,12 @@ iasecc_pkcs15_fix_private_key_attributes(struct sc_profile *profile, struct sc_p rv = iasecc_pkcs15_add_algorithm_reference(p15card, key_info, IASECC_ALGORITHM_RSA_PKCS); LOG_TEST_RET(ctx, rv, "Cannot add RSA_PKCS supported mechanism"); - key_info->usage |= SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER; } else if (ii == IASECC_ACLS_RSAKEY_PSO_DECIPHER) { rv = iasecc_pkcs15_add_algorithm_reference(p15card, key_info, IASECC_ALGORITHM_RSA_PKCS_DECRYPT | IASECC_ALGORITHM_SHA1); LOG_TEST_RET(ctx, rv, "Cannot add decipher RSA_PKCS supported mechanism"); - key_info->usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP; } } From 4a4d750e7383da4a4b71f55465efe3749df63735 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Tue, 31 Mar 2015 16:52:05 +0200 Subject: [PATCH 150/306] iasecc: Fix log output is always displayed * iasecc_read_public_key function uses SC_SUCCESS instead of log level value, hence the log output is always displayed. This uses SC_LOG_DEBUG_NORMAL instead. VTA: updated to use short form of LOG macro --- src/libopensc/card-iasecc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index c9d2518c..de7a3ecd 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -3385,7 +3385,7 @@ iasecc_read_public_key(struct sc_card *card, unsigned type, iasecc_sdo_free_fields(card, &sdo); - SC_FUNC_RETURN(ctx, SC_SUCCESS, rv); + LOG_FUNC_RETURN(ctx, SC_SUCCESS); } From a05e7ca84df68b21728ee11a5d1637bbacbd6ae9 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 31 Mar 2015 14:29:42 +0200 Subject: [PATCH 151/306] ignore errors on `apt-get update` --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 46c471b9..8cc7a698 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ matrix: before_install: - if [ $TRAVIS_OS_NAME == linux ]; then - sudo apt-get update; + sudo apt-get update || true; fi install: From 0790969b97083c1d90ec97292904d8fb7164d238 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 31 Mar 2015 14:17:40 +0200 Subject: [PATCH 152/306] recognize short EF identifier --- src/libopensc/iso7816.c | 4 ++++ src/libopensc/types.h | 3 ++- src/tools/opensc-explorer.c | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index c37bbf04..5ed0f17d 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -430,6 +430,10 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file, if (tag != NULL && taglen) sc_file_set_sec_attr(file, tag, taglen); + tag = sc_asn1_find_tag(ctx, p, len, 0x88, &taglen); + if (tag != NULL && taglen == 1) + file->sid = *tag; + tag = sc_asn1_find_tag(ctx, p, len, 0x8A, &taglen); if (tag != NULL && taglen==1) { if (tag[0] == 0x01) diff --git a/src/libopensc/types.h b/src/libopensc/types.h index 0bf0c29b..38f4c4bf 100644 --- a/src/libopensc/types.h +++ b/src/libopensc/types.h @@ -225,7 +225,8 @@ typedef struct sc_file { unsigned int type, ef_structure, status; /* See constant values defined above */ unsigned int shareable; /* true(1), false(0) according to ISO 7816-4:2005 Table 14 */ size_t size; /* Size of file (in bytes) */ - int id; /* Short file id (2 bytes) */ + int id; /* file identifier (2 bytes) */ + int sid; /* short EF identifier (1 byte) */ struct sc_acl_entry *acl[SC_MAX_AC_OPS]; /* Access Control List */ int record_length; /* In case of fixed-length or cyclic EF */ diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index cefc3e16..fa2581bb 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -786,8 +786,10 @@ static int do_info(int argc, char **argv) st = "Unknown File"; break; } - printf("\n%s ID %04X\n\n", st, file->id); - printf("%-15s%s\n", "File path:", path_to_filename(&path, '/')); + printf("\n%s ID %04X", st, file->id); + if (file->sid) + printf(", SFI %02X", file->sid); + printf("\n\n%-15s%s\n", "File path:", path_to_filename(&path, '/')); printf("%-15s%lu bytes\n", "File size:", (unsigned long) file->size); if (file->type == SC_FILE_TYPE_DF) { From 88ec461bc5b6041e0417df569de74875253f05d3 Mon Sep 17 00:00:00 2001 From: Dirk-Willem van Gulik Date: Tue, 17 Mar 2015 12:42:01 +0100 Subject: [PATCH 153/306] tool: RFC4716 compliant key output Add a comment field to the ssh key output if a label is set on the key. Add RFC4716 compliant key output for the new breed of modern (mobile) SSH clients. VTA: use short form of log call in iso7816 --- doc/tools/pkcs15-tool.1.xml | 16 ++++++++++- src/libopensc/iso7816.c | 3 +- src/tools/pkcs15-tool.c | 55 ++++++++++++++++++++++++++++--------- 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/doc/tools/pkcs15-tool.1.xml b/doc/tools/pkcs15-tool.1.xml index 9c588726..82ad7b91 100644 --- a/doc/tools/pkcs15-tool.1.xml +++ b/doc/tools/pkcs15-tool.1.xml @@ -185,7 +185,21 @@ Reads the public key with id id, writing the output in format suitable for - $HOME/.ssh/authorized_keys. + $HOME/.ssh/authorized_keys. + + The key label, if any will be shown in the 'Comment' field. + + + + + + + When used in conjunction with option the + output format of the public key follows rfc4716. + + + The default output format is a single line (openssh). + diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 5ed0f17d..37abd177 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -1016,8 +1016,7 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, * but expect the new one to be entered on the keypad. */ if (data->pin1.len && data->pin2.len == 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Special case - initial pin provided - but new pin asked on keypad"); + sc_log(card->ctx, "Special case - initial pin provided - but new pin asked on keypad"); data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE; }; len += r; diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 409d9847..abc64f43 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -57,6 +57,9 @@ static const char * opt_pin = NULL; static const char * opt_puk = NULL; static int verbose = 0; static int opt_no_prompt = 0; +#if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) +static int opt_rfc4716 = 0; +#endif enum { OPT_CHANGE_PIN = 0x100, @@ -68,6 +71,7 @@ enum { OPT_READ_PUB, #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) OPT_READ_SSH, + OPT_RFC4716, #endif OPT_PIN, OPT_NEWPIN, @@ -76,7 +80,7 @@ enum { OPT_BIND_TO_AID, OPT_LIST_APPLICATIONS, OPT_LIST_SKEYS, - OPT_NO_PROMPT + OPT_NO_PROMPT, }; #define NELEMENTS(x) (sizeof(x)/sizeof((x)[0])) @@ -100,6 +104,7 @@ static const struct option options[] = { { "read-public-key", required_argument, NULL, OPT_READ_PUB }, #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) { "read-ssh-key", required_argument, NULL, OPT_READ_SSH }, + { "rfc4716", no_argument, NULL, OPT_RFC4716 }, #endif { "test-update", no_argument, NULL, 'T' }, { "update", no_argument, NULL, 'U' }, @@ -786,6 +791,36 @@ static int list_skeys(void) #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) + +static void print_ssh_key(FILE *outf, const char * alg, struct sc_pkcs15_object *obj, unsigned char * buf, uint32_t len) { + unsigned char *uu; + int r; + + uu = malloc(len*2); // Way over - even if we have extra LFs; as each 6 bits take one byte. + + if (opt_rfc4716) { + r = sc_base64_encode(buf, len, uu, 2*len, 64); + + fprintf(outf,"---- BEGIN SSH2 PUBLIC KEY ----\n"); + + if (obj->label && strlen(obj->label)) + fprintf(outf,"Comment: \"%s\"\n", obj->label); + + fprintf(outf,"%s", uu); + fprintf(outf,"---- END SSH2 PUBLIC KEY ----\n"); + } else { + // Old style openssh - [ [ anything else] + // + r = sc_base64_encode(buf, len, uu, 2*len, 0); + if (obj->label && strlen(obj->label)) + fprintf(outf,"ssh-%s %s %s\n", alg, uu, obj->label); + else + fprintf(outf,"ssh-%s %s\n", alg, uu); + } + free(uu); + return; +} + static int read_ssh_key(void) { int r; @@ -844,7 +879,6 @@ static int read_ssh_key(void) if (pubkey->algorithm == SC_ALGORITHM_RSA) { unsigned char buf[2048]; - unsigned char *uu; uint32_t len, n; if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.modulus.len || @@ -895,16 +929,11 @@ static int read_ssh_key(void) memcpy(buf+len,pubkey->u.rsa.modulus.data, pubkey->u.rsa.modulus.len); len += pubkey->u.rsa.modulus.len; - uu = malloc(len*2); - r = sc_base64_encode(buf, len, uu, 2*len, 2*len); - - fprintf(outf,"ssh-rsa %s", uu); - free(uu); + print_ssh_key(outf, "rsa", obj, buf, len); } if (pubkey->algorithm == SC_ALGORITHM_DSA) { unsigned char buf[2048]; - unsigned char *uu; uint32_t len; uint32_t n; @@ -991,11 +1020,7 @@ static int read_ssh_key(void) memcpy(buf+len,pubkey->u.dsa.pub.data, pubkey->u.dsa.pub.len); len += pubkey->u.dsa.pub.len; - uu = malloc(len*2); - r = sc_base64_encode(buf, len, uu, 2*len, 2*len); - - fprintf(outf,"ssh-dss %s", uu); - free(uu); + print_ssh_key(outf, "dss", obj, buf, len); } if (outf != stdout) @@ -1016,6 +1041,7 @@ fail2: sc_pkcs15_free_pubkey(pubkey); return SC_ERROR_OUT_OF_MEMORY; } + #endif static sc_pkcs15_object_t * @@ -1900,6 +1926,9 @@ int main(int argc, char * const argv[]) do_read_sshkey = 1; action_count++; break; + case OPT_RFC4716: + opt_rfc4716 = 1; + break; #endif case 'L': do_learn_card = 1; From a251b9335c7b3c827685337e9498b3d4493d9c09 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 31 Mar 2015 23:57:19 +0200 Subject: [PATCH 154/306] use xcodebuild with `-target OpenSC` patch by Dirk-Willem van Gulik --- MacOSX/build-package.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index 4f671c45..c0db7daf 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -70,7 +70,7 @@ fi test -L OpenSC.tokend/build/opensc-src || ln -sf ${BUILDPATH}/src OpenSC.tokend/build/opensc-src # Build and copy OpenSC.tokend -xcodebuild -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj +xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj # Prepare target root # Copy Tokend From 311958e13f43abfe29d5ba15f62fdf4ad22b16b8 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 1 Apr 2015 00:13:19 +0200 Subject: [PATCH 155/306] Travis-ci: build dmg on OS X --- .travis.yml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8cc7a698..4864cad6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,17 @@ env: matrix: include: - compiler: clang + os: osx - compiler: gcc + os: osx + - compiler: clang + os: linux + env: ENABLE_DOC=--enable-doc - compiler: gcc + os: linux + env: ENABLE_DOC=--enable-doc + - compiler: gcc + os: linux env: HOST=i686-w64-mingw32 before_install: @@ -30,7 +39,7 @@ install: before_script: - ./bootstrap - if [ -z "$HOST" ]; then - ./configure --enable-pedantic --disable-strict --enable-doc --enable-dnie-ui; + ./configure --enable-pedantic --disable-strict $ENABLE_DOC --enable-dnie-ui; else unset CC; unset CXX; @@ -48,9 +57,13 @@ addons: script: - if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then - make; + if [ $TRAVIS_OS_NAME == osx ]; then + ./MacOSX/build; + else + make; + fi; fi - - if [ -z "$HOST" -a "${COVERITY_SCAN_BRANCH}" != 1 ]; then + - if [ -z "$HOST" -a "${COVERITY_SCAN_BRANCH}" != 1 -a "$TRAVIS_OS_NAME" != "osx" ]; then make check; make dist; fi From 88fa362b5b3e27d47ff2d57e4e04e694e5e07c87 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 1 Apr 2015 01:07:05 +0200 Subject: [PATCH 156/306] nobody likes being pedantic --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4864cad6..54a754d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,11 +39,11 @@ install: before_script: - ./bootstrap - if [ -z "$HOST" ]; then - ./configure --enable-pedantic --disable-strict $ENABLE_DOC --enable-dnie-ui; + ./configure $ENABLE_DOC --enable-dnie-ui; else unset CC; unset CXX; - ./configure --enable-pedantic --disable-strict --host=$HOST --disable-openssl; + ./configure --host=$HOST --disable-openssl; fi addons: From 30b24e79c08e6c027ffa3aa8136c10f689ce7a63 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 1 Apr 2015 02:01:41 +0200 Subject: [PATCH 157/306] fixed memory corruption in encode_file_structure as suggested by Peter Popovec --- src/libopensc/card-myeid.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index e8c28ec9..6a9fd752 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -344,17 +344,20 @@ static int myeid_process_fci(struct sc_card *card, struct sc_file *file, } static int encode_file_structure(sc_card_t *card, const sc_file_t *file, - u8 *out, size_t *outlen) + u8 *buf, size_t *outlen) { const sc_acl_entry_t *read, *update, *delete, *generate; - u8 buf[42]; size_t i; LOG_FUNC_CALLED(card->ctx); + + if (!buf || !outlen || *outlen < 45) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + /* PrivateKey * 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984 * 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */ - memset(buf, 0x0, sizeof(buf)); + memset(buf, 0x0, *outlen); buf[0] = 0x62; buf[1] = 0x17; @@ -453,9 +456,9 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, buf[26] = (u8)file->namelen; for(i=0;i < file->namelen;i++) - buf[i + 26] = file->name[i]; + buf[i + 27] = file->name[i]; - buf[1] = 0x19 + file->namelen + 2; + buf[1] = 27 + file->namelen; } break; default: @@ -464,16 +467,15 @@ static int encode_file_structure(sc_card_t *card, const sc_file_t *file, } *outlen = buf[1]+2; - memcpy(out, buf, *outlen); - LOG_FUNC_RETURN(card->ctx, 0); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } static int myeid_create_file(struct sc_card *card, struct sc_file *file) { sc_apdu_t apdu; - u8 sbuf[32]; - size_t buflen; + u8 sbuf[45]; + size_t buflen = sizeof sbuf; int r; LOG_FUNC_CALLED(card->ctx); @@ -808,7 +810,7 @@ static int myeid_convert_ec_signature(struct sc_context *ctx, size_t s_len, unsigned char *data, size_t datalen) { unsigned char *buf; - size_t i, buflen; + size_t buflen; int r; assert(data && datalen); From e07c4bcfbbc55eaca08eba625e189697ff18f3d5 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 1 Apr 2015 20:50:37 +0200 Subject: [PATCH 158/306] added sc_sm_stop implementation taken from the ISO SM driver of https://github.com/frankmorgner/vsmartcard/tree/master/npa --- src/libopensc/sm.c | 25 +++++++++++++++++++++++++ src/libopensc/sm.h | 12 ++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/libopensc/sm.c b/src/libopensc/sm.c index 5f4bd899..8e93ccce 100644 --- a/src/libopensc/sm.c +++ b/src/libopensc/sm.c @@ -159,22 +159,47 @@ sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu) LOG_FUNC_RETURN(ctx, rv); } + +int +sc_sm_stop(struct sc_card *card) +{ + int r = SC_SUCCESS; + + if (card) { + if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT + && card->sm_ctx.ops.close) + r = card->sm_ctx.ops.close(card); + card->sm_ctx.sm_mode = SM_MODE_NONE; + } + + return r; +} + #else + int sc_sm_parse_answer(struct sc_card *card, unsigned char *resp_data, size_t resp_len, struct sm_card_response *out) { return SC_ERROR_NOT_SUPPORTED; } + int sc_sm_update_apdu_response(struct sc_card *card, unsigned char *resp_data, size_t resp_len, int ref_rv, struct sc_apdu *apdu) { return SC_ERROR_NOT_SUPPORTED; } + int sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu) { return SC_ERROR_NOT_SUPPORTED; } + +int +sc_sm_stop(struct sc_card *card) +{ + return SC_ERROR_NOT_SUPPORTED; +} #endif diff --git a/src/libopensc/sm.h b/src/libopensc/sm.h index 8ff19887..e27725f4 100644 --- a/src/libopensc/sm.h +++ b/src/libopensc/sm.h @@ -353,6 +353,18 @@ int sc_sm_parse_answer(struct sc_card *, unsigned char *, size_t, struct sm_card int sc_sm_update_apdu_response(struct sc_card *, unsigned char *, size_t, int, struct sc_apdu *); int sc_sm_single_transmit(struct sc_card *, struct sc_apdu *); +/** + * @brief Stops SM and frees allocated ressources. + * + * Calls \a card->sm_ctx.ops.close() if available and \c card->sm_ctx.sm_mode + * is \c SM_MODE_TRANSMIT + * + * @param[in] card + * + * @return \c SC_SUCCESS or error code if an error occurred + */ +int sc_sm_stop(struct sc_card *card); + #ifdef __cplusplus } #endif From c0fac2a4f6c58b5f84c7b2e3344e8e19a765e3d7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 1 Apr 2015 21:03:25 +0200 Subject: [PATCH 159/306] stop SM in case of SM errors --- src/libopensc/sm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libopensc/sm.c b/src/libopensc/sm.c index 8e93ccce..4705ba62 100644 --- a/src/libopensc/sm.c +++ b/src/libopensc/sm.c @@ -140,6 +140,9 @@ sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu) * Send plain APDU to the reader driver */ rv = card->reader->ops->transmit(card->reader, apdu); LOG_FUNC_RETURN(ctx, rv); + } else { + if (rv < 0) + sc_sm_stop(card); } LOG_TEST_RET(ctx, rv, "get SM APDU error"); @@ -147,15 +150,22 @@ sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu) rv = sc_check_apdu(card, sm_apdu); if (rv < 0) { card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu); + sc_sm_stop(card); LOG_TEST_RET(ctx, rv, "cannot validate SM encoded APDU"); } /* send APDU to the reader driver */ rv = card->reader->ops->transmit(card->reader, sm_apdu); - LOG_TEST_RET(ctx, rv, "unable to transmit APDU"); + if (rv < 0) { + card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu); + sc_sm_stop(card); + LOG_TEST_RET(ctx, rv, "unable to transmit APDU"); + } /* decode SM answer and free temporary SM related data */ rv = card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu); + if (rv < 0) + sc_sm_stop(card); LOG_FUNC_RETURN(ctx, rv); } From 95ad11a2530c3d35fa8220c82391f3dd0e8869dd Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 4 Apr 2015 21:05:19 +0200 Subject: [PATCH 160/306] iasecc: special case for 'Gemalto GemPC Pinpad' issue 424 VTA: this pinpad, the only available, do not accept different values for min and max PIN lengths in P10 block. --- src/libopensc/card-iasecc.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index de7a3ecd..abe82451 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -1801,12 +1801,14 @@ iasecc_chv_verify_pinpad(struct sc_card *card, struct sc_pin_cmd_data *pin_cmd, LOG_FUNC_RETURN(ctx, SC_ERROR_READER); } - if (pin_cmd->pin1.min_length != pin_cmd->pin1.max_length) { - sc_log(ctx, "Different values for PIN min and max lengths is not actually compatible with PinPAD."); - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, - "Different values for PIN min and max lengths is not actually compatible with PinPAD."); + sc_log(ctx, "reader %s", card->reader->name); + if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name) { + sc_log(ctx, "reader %s", card->reader->name); + if (pin_cmd->pin1.min_length != pin_cmd->pin1.max_length) { + sc_log(ctx, "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths."); + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); + } } - pin_cmd->pin1.len = pin_cmd->pin1.min_length; memset(buffer, 0xFF, sizeof(buffer)); @@ -2037,8 +2039,10 @@ iasecc_chv_change_pinpad(struct sc_card *card, unsigned reference, int *tries_le rv = iasecc_pin_get_policy(card, &pin_cmd); LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error"); - if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length) - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Different values for PIN min and max lengths is not allowed with PinPAD."); + if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name) + if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length) + LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, + "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths."); if (pin_cmd.pin1.min_length < 4) pin_cmd.pin1.min_length = 4; @@ -2083,8 +2087,10 @@ iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference) rv = iasecc_pin_get_policy(card, &pin_cmd); LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error"); - if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length) - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Different values for PIN min and max lengths is not allowed with PinPAD."); + if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name) + if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length) + LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, + "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths."); if (pin_cmd.pin1.min_length < 4) pin_cmd.pin1.min_length = 4; From f93835add98343d454b8f4321c9a7f8708012b74 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 3 Apr 2015 21:07:49 +0200 Subject: [PATCH 161/306] Allow log functions to be called with ctx==NULL This change allows functions to be used from places where there is no sc_context (ctx) available. --- src/libopensc/log.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/libopensc/log.c b/src/libopensc/log.c index 32f396d8..9d98413b 100644 --- a/src/libopensc/log.c +++ b/src/libopensc/log.c @@ -73,9 +73,7 @@ static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int lin FILE *outf = NULL; int n; - assert(ctx != NULL); - - if (ctx->debug < level) + if (!ctx || ctx->debug < level) return; p = buf; @@ -167,9 +165,7 @@ void sc_hex_dump(struct sc_context *ctx, int level, const u8 * in, size_t count, char *p = buf; int lines = 0; - assert(ctx != NULL); - - if (ctx->debug < level) + if (!ctx || ctx->debug < level) return; assert(buf != NULL && (in != NULL || count == 0)); From fa045d44ecf7235b73d9fb55ed7261eb36252b0c Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Fri, 3 Apr 2015 14:01:41 +0200 Subject: [PATCH 162/306] pkcs11-tool: Let the user choose the ECDSA signature format Instead of hard-coding the format depending on whether OpenSC was compiled with OpenSSL or not, the user should be able to choose the format himself. The default format now is the normal concatenation of R,S both for CKM_ECDSA and CKM_ECDSA_SHA1. --- src/tools/pkcs11-tool.c | 44 +++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index f5eb7f63..b79beeec 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -166,6 +166,7 @@ static const struct option options[] = { { "attr-from", 1, NULL, OPT_ATTR_FROM }, { "input-file", 1, NULL, 'i' }, { "output-file", 1, NULL, 'o' }, + { "signature-format", 1, NULL, 'f' }, { "test", 0, NULL, 't' }, { "test-hotplug", 0, NULL, OPT_TEST_HOTPLUG }, @@ -223,6 +224,7 @@ static const char *option_help[] = { "Use to create some attributes when writing an object", "Specify the input file", "Specify the output file", + "Format for ECDSA signature : 'rs' (default), 'sequence', 'openssl'", "Test (best used with the --login or --pin option)", "Test hotplug capabilities (C_GetSlotList + C_WaitForSlotEvent)", @@ -262,6 +264,7 @@ static char * opt_application_id = NULL; static char * opt_issuer = NULL; static char * opt_subject = NULL; static char * opt_key_type = NULL; +static char * opt_sig_format = NULL; static int opt_is_private = 0; static int opt_test_hotplug = 0; static int opt_login_type = -1; @@ -420,7 +423,7 @@ int main(int argc, char * argv[]) CRYPTO_malloc_init(); #endif while (1) { - c = getopt_long(argc, argv, "ILMOTa:bd:e:hi:klm:o:p:scvty:w:z:r", + c = getopt_long(argc, argv, "ILMOTa:bd:e:hi:klm:o:p:scvf:ty:w:z:r", options, &long_optind); if (c == -1) break; @@ -543,6 +546,9 @@ int main(int argc, char * argv[]) do_sign = 1; action_count++; break; + case 'f': + opt_sig_format = optarg; + break; case 't': need_session |= NEED_SESSION_RO; do_test = 1; @@ -1424,33 +1430,23 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, util_fatal("failed to open %s: %m", opt_output); } -#if defined(ENABLE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_ECDSA) -/* - * PKCS11 implies the ECDSA sig is 2nLen, - * OpenSSL expects sequence of {integer, integer} - * so we will write it for OpenSSL if built with OpenSSL - */ - if (opt_mechanism == CKM_ECDSA) { - int nLen; - ECDSA_SIG * ecsig = NULL; - unsigned char *p = NULL; - int der_len; + if (opt_mechanism == CKM_ECDSA || opt_mechanism == CKM_ECDSA_SHA1) { + if (opt_sig_format && (!strcmp(opt_sig_format, "openssl") || !strcmp(opt_sig_format, "sequence"))) { + unsigned char *seq; + size_t seqlen; - nLen = sig_len/2; + if (sc_asn1_sig_value_rs_to_sequence(NULL, sig_buffer, sig_len, &seq, &seqlen)) { + util_fatal("Failed to convert signature to ASN.1 sequence format."); + } - ecsig = ECDSA_SIG_new(); - ecsig->r = BN_bin2bn(sig_buffer, nLen, ecsig->r); - ecsig->s = BN_bin2bn(sig_buffer + nLen, nLen, ecsig->s); + memcpy(sig_buffer, seq, seqlen); + sig_len = seqlen; - der_len = i2d_ECDSA_SIG(ecsig, &p); - printf("Writing OpenSSL ECDSA_SIG\n"); - r = write(fd, p, der_len); - free(p); - ECDSA_SIG_free(ecsig); - - } else -#endif /* ENABLE_OPENSSL && !OPENSSL_NO_EC && !OPENSSL_NO_ECDSA */ + free(seq); + } + } r = write(fd, sig_buffer, sig_len); + if (r < 0) util_fatal("Failed to write to %s: %m", opt_output); if (fd != 1) From db860c0d2aa58501375530f7bb0b364cda73d693 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 2 Apr 2015 08:05:24 +0200 Subject: [PATCH 163/306] export sc_sm_stop --- src/libopensc/libopensc.exports | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index 23f6c05a..7c64d9aa 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -317,6 +317,7 @@ sc_pkcs15_convert_pubkey sc_sm_parse_answer sc_sm_update_apdu_response sc_sm_single_transmit +sc_sm_stop iasecc_sm_create_file iasecc_sm_delete_file iasecc_sm_external_authentication From 8ea328ff7fb311e582f312fe4f145c1af0d52390 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sun, 29 Mar 2015 15:55:10 +0200 Subject: [PATCH 164/306] Minor code quality improvements. Basically checks that the memory allocation succeed. The ctbcs.c change improve the readability because count = 0 and len > 254 does not add any value. VTA: added few coding style changes --- src/libopensc/card-openpgp.c | 12 +++++- src/libopensc/ctbcs.c | 4 +- src/libopensc/muscle-filesystem.c | 2 + src/libopensc/pkcs15-gemsafeV1.c | 65 ++++++++++++++++--------------- src/libopensc/pkcs15-pubkey.c | 4 ++ src/pkcs11/mechanism.c | 3 ++ 6 files changed, 54 insertions(+), 36 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 5ae66f67..6c63a5e8 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -305,7 +305,7 @@ pgp_init(sc_card_t *card) sc_file_t *file = NULL; struct do_info *info; int r; - struct blob *child = NULL; + struct blob *child = NULL; priv = calloc (1, sizeof *priv); if (!priv) @@ -330,8 +330,14 @@ pgp_init(sc_card_t *card) return r; } + /* defensive programming check */ + if (!file) { + pgp_finish(card); + return SC_ERROR_OBJECT_NOT_FOUND; + } + /* read information from AID */ - if (file && file->namelen == 16) { + if (file->namelen == 16) { /* OpenPGP card spec 1.1 & 2.0, section 4.2.1 & 4.1.2.1 */ priv->bcd_version = bebytes2ushort(file->name + 6); /* kludge: get card's serial number from manufacturer ID + serial number */ @@ -2166,7 +2172,9 @@ out: /* ABI: card ctl: perform special card-specific operations */ static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) { +#ifdef ENABLE_OPENSSL int r; +#endif /* ENABLE_OPENSSL */ LOG_FUNC_CALLED(card->ctx); diff --git a/src/libopensc/ctbcs.c b/src/libopensc/ctbcs.c index 16c43369..ad51cac8 100644 --- a/src/libopensc/ctbcs.c +++ b/src/libopensc/ctbcs.c @@ -58,7 +58,7 @@ ctbcs_build_perform_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *d prompt = data->pin1.prompt; if (prompt && *prompt) { len = strlen(prompt); - if (count + len + 2 > buflen || len > 254) + if (len + 2 > buflen) return SC_ERROR_BUFFER_TOO_SMALL; buf[count++] = CTBCS_TAG_PROMPT; buf[count++] = len; @@ -126,7 +126,7 @@ ctbcs_build_modify_verification_apdu(sc_apdu_t *apdu, struct sc_pin_cmd_data *da prompt = data->pin1.prompt; if (prompt && *prompt) { len = strlen(prompt); - if (count + len + 2 > buflen || len > 254) + if (len + 2 > buflen) return SC_ERROR_BUFFER_TOO_SMALL; buf[count++] = CTBCS_TAG_PROMPT; buf[count++] = len; diff --git a/src/libopensc/muscle-filesystem.c b/src/libopensc/muscle-filesystem.c index f54d263f..dc618a67 100644 --- a/src/libopensc/muscle-filesystem.c +++ b/src/libopensc/muscle-filesystem.c @@ -42,6 +42,8 @@ static const u8* ignoredFiles[] = { mscfs_t *mscfs_new(void) { mscfs_t *fs = malloc(sizeof(mscfs_t)); + if (!fs) + return NULL; memset(fs, 0, sizeof(mscfs_t)); memcpy(fs->currentPath, "\x3F\x00", 2); return fs; diff --git a/src/libopensc/pkcs15-gemsafeV1.c b/src/libopensc/pkcs15-gemsafeV1.c index aa928421..c1191eef 100644 --- a/src/libopensc/pkcs15-gemsafeV1.c +++ b/src/libopensc/pkcs15-gemsafeV1.c @@ -183,11 +183,9 @@ static int gemsafe_get_cert_len(sc_card_t *card) * (allocated EF space is much greater!) */ objlen = (((size_t) ibuf[0]) << 8) | ibuf[1]; - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Stored object is of size: %d\n", objlen); + sc_log(card->ctx, "Stored object is of size: %d", objlen); if (objlen < 1 || objlen > GEMSAFE_MAX_OBJLEN) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Invalid object size: %d\n", objlen); + sc_log(card->ctx, "Invalid object size: %d", objlen); return SC_ERROR_INTERNAL; } @@ -209,15 +207,14 @@ static int gemsafe_get_cert_len(sc_card_t *card) while (ibuf[ind] == 0x01) { if (ibuf[ind+1] == 0xFE) { gemsafe_prkeys[i].ref = ibuf[ind+4]; - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Key container %d is allocated and uses key_ref %d\n", i+1, - gemsafe_prkeys[i].ref); + sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d", + i+1, gemsafe_prkeys[i].ref); ind += 9; - } else { + } + else { gemsafe_prkeys[i].label = NULL; gemsafe_cert[i].label = NULL; - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Key container %d is unallocated\n", i+1); + sc_log(card->ctx, "Key container %d is unallocated", i+1); ind += 8; } i++; @@ -239,8 +236,7 @@ static int gemsafe_get_cert_len(sc_card_t *card) r = sc_read_binary(card, iptr - ibuf, iptr, MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0); if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Could not read cert object\n"); + sc_log(card->ctx, "Could not read cert object"); return SC_ERROR_INTERNAL; } iptr += GEMSAFE_READ_QUANTUM; @@ -254,15 +250,12 @@ static int gemsafe_get_cert_len(sc_card_t *card) while (i < gemsafe_cert_max && gemsafe_cert[i].label == NULL) i++; if (i == gemsafe_cert_max) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Warning: Found orphaned certificate at offset %d\n", ind); + sc_log(card->ctx, "Warning: Found orphaned certificate at offset %d", ind); return SC_SUCCESS; } /* DER cert len is encoded this way */ certlen = ((((size_t) ibuf[ind+2]) << 8) | ibuf[ind+3]) + 4; - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Found certificate of key container %d at offset %d, len %d\n", - i+1, ind, certlen); + sc_log(card->ctx, "Found certificate of key container %d at offset %d, len %d", i+1, ind, certlen); gemsafe_cert[i].index = ind; gemsafe_cert[i].count = certlen; ind += certlen; @@ -276,8 +269,7 @@ static int gemsafe_get_cert_len(sc_card_t *card) */ for (; i < gemsafe_cert_max; i++) { if (gemsafe_cert[i].label) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, - "Warning: Certificate of key container %d is missing\n", i+1); + sc_log(card->ctx, "Warning: Certificate of key container %d is missing", i+1); gemsafe_prkeys[i].label = NULL; gemsafe_cert[i].label = NULL; } @@ -304,7 +296,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; - sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting pkcs15 parameters\n"); + sc_log(p15card->card->ctx, "Setting pkcs15 parameters"); if (p15card->tokeninfo->label) free(p15card->tokeninfo->label); @@ -330,7 +322,8 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) apdu.lc = 0; apdu.datalen = 0; r = sc_transmit_apdu(card, &apdu); - SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) return SC_ERROR_INTERNAL; if (r != SC_SUCCESS) @@ -350,7 +343,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) return SC_ERROR_INTERNAL; /* set certs */ - sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting certificates\n"); + sc_log(p15card->card->ctx, "Setting certificates"); for (i = 0; i < gemsafe_cert_max; i++) { struct sc_pkcs15_id p15Id; struct sc_path path; @@ -367,7 +360,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) } /* set gemsafe_pin */ - sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting PIN\n"); + sc_log(p15card->card->ctx, "Setting PIN"); for (i=0; i < gemsafe_pin_max; i++) { struct sc_pkcs15_id p15Id; struct sc_path path; @@ -388,11 +381,11 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) }; /* set private keys */ - sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting private keys\n"); + sc_log(p15card->card->ctx, "Setting private keys"); for (i = 0; i < gemsafe_cert_max; i++) { struct sc_pkcs15_id p15Id, authId, *pauthId; struct sc_path path; - int key_ref = 0x03; + int key_ref = 0x03; if (gemsafe_prkeys[i].label == NULL) continue; @@ -403,7 +396,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) } else pauthId = NULL; sc_format_path(gemsafe_prkeys[i].path, &path); - /* + /* * The key ref may be different for different sites; * by adding flags=n where the low order 4 bits can be * the key ref we can force it. @@ -423,7 +416,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) } /* select the application DF */ - sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,"Selecting application DF\n"); + sc_log(p15card->card->ctx, "Selecting application DF"); sc_format_path(GEMSAFE_APP_PATH, &path); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS || !file) @@ -511,8 +504,7 @@ sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type, df_type = SC_PKCS15_CDF; break; default: - sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, - "Unknown PKCS15 object type %d\n", type); + sc_log(p15card->card->ctx, "Unknown PKCS15 object type %d", type); free(obj); return SC_ERROR_INVALID_ARGUMENTS; } @@ -534,6 +526,9 @@ sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card, sc_pkcs15_auth_info_t *info; info = calloc(1, sizeof(*info)); + if (!info) + LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); + info->auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; info->auth_method = SC_AC_CHV; info->auth_id = *id; @@ -549,9 +544,7 @@ sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card, if (path) info->path = *path; - return sc_pkcs15emu_add_object(p15card, - SC_PKCS15_TYPE_AUTH_PIN, - label, info, NULL, obj_flags); + return sc_pkcs15emu_add_object(p15card, SC_PKCS15_TYPE_AUTH_PIN, label, info, NULL, obj_flags); } static int @@ -563,6 +556,10 @@ sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card, { sc_pkcs15_cert_info_t *info; info = calloc(1, sizeof(*info)); + if (!info) + { + LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); + } info->id = *id; info->authority = authority; if (path) @@ -582,6 +579,10 @@ sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card, sc_pkcs15_prkey_info_t *info; info = calloc(1, sizeof(*info)); + if (!info) + { + LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY); + } info->id = *id; info->modulus_length = modulus_length; info->usage = usage; diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 189e413e..9cf75e35 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1019,6 +1019,8 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv break; case SC_ALGORITHM_EC: pubkey->u.ec.ecpointQ.value = malloc(prvkey->u.ec.ecpointQ.len); + if (!pubkey->u.ec.ecpointQ.value) + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(pubkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.value, prvkey->u.ec.ecpointQ.len); pubkey->u.ec.ecpointQ.len = prvkey->u.ec.ecpointQ.len; break; @@ -1583,6 +1585,8 @@ sc_pkcs15_convert_pubkey(struct sc_pkcs15_pubkey *pkcs15_key, void *evp_key) /* copy the public key */ if (buflen > 0) { dst->ecpointQ.value = malloc(buflen); + if (!dst->ecpointQ.value) + return SC_ERROR_OUT_OF_MEMORY; memcpy(dst->ecpointQ.value, buf, buflen); dst->ecpointQ.len = buflen; /* calculate the field length */ diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index 63506382..fec1123a 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -990,6 +990,9 @@ sc_pkcs11_register_sign_and_hash_mechanism(struct sc_pkcs11_card *p11card, mech_info.flags &= (CKF_SIGN | CKF_SIGN_RECOVER | CKF_VERIFY | CKF_VERIFY_RECOVER); info = calloc(1, sizeof(*info)); + if (!info) + LOG_FUNC_RETURN(p11card->card->ctx, SC_ERROR_OUT_OF_MEMORY); + info->mech = mech; info->sign_type = sign_type; info->hash_type = hash_type; From 4000e6d5b0c6227f2621408fa15c9d1661d65b24 Mon Sep 17 00:00:00 2001 From: Dirk-Willem van Gulik Date: Tue, 7 Apr 2015 17:35:43 +0200 Subject: [PATCH 165/306] Add missed option debug info Fix misspelled key in --help output (thanks Philip Wendland). --- src/tools/pkcs15-tool.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index abc64f43..de3e6b33 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -21,6 +21,7 @@ #include "config.h" #include +#include #ifdef ENABLE_OPENSSL #if defined(HAVE_INTTYPES_H) @@ -140,6 +141,7 @@ static const char *option_help[] = { "Reads public key with ID ", #if defined(ENABLE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H)) "Reads public key with ID , outputs ssh format", + "Outputs the public key in RFC 4716 format (requires --read-ssh-key)", #endif "Test if the card needs a security update", "Update the card with a security update", @@ -155,6 +157,7 @@ static const char *option_help[] = { "Wait for card insertion", "Verbose operation. Use several times to enable debug output.", "Do not prompt the user; if no PINs supplied, pinpad will be used.", + NULL }; static sc_context_t *ctx = NULL; @@ -1856,6 +1859,8 @@ int main(int argc, char * const argv[]) int action_count = 0; sc_context_param_t ctx_param; + assert(sizeof(option_help)/sizeof(char *)==sizeof(options)/sizeof(struct option)); + c = OPT_PUK; while (1) { From ce962c14f4368c2e5be4d0f3fb0f85f4d96ea69c Mon Sep 17 00:00:00 2001 From: vletoux Date: Mon, 6 Apr 2015 16:43:17 +0200 Subject: [PATCH 166/306] fix #425: guid computation issue Compilation without OpenSSL - guid computation issue This case is triggered when: - built without OpenSSL - called from a minidriver where id.len = 1 - card number is less than 15 bytes (VTA: codding style slightly touched) --- src/libopensc/pkcs15.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 346e30a6..41e714d7 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -2697,7 +2697,7 @@ sc_pkcs15_get_object_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15 struct sc_serial_number serialnr; struct sc_pkcs15_id id; unsigned char guid_bin[SC_PKCS15_MAX_ID_SIZE + SC_MAX_SERIALNR]; - int rv; + int rv, guid_bin_size; LOG_FUNC_CALLED(ctx); if(!out || !out_size) @@ -2748,23 +2748,34 @@ sc_pkcs15_get_object_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15 memset(guid_bin, 0, sizeof(guid_bin)); memcpy(guid_bin, id.value, id.len); memcpy(guid_bin + id.len, serialnr.value, serialnr.len); + guid_bin_size = id.len + serialnr.len; - // If OpenSSL is available (SHA1), then rather use the hash of the data - // - this also protects against data being too short + /* + * If OpenSSL is available (SHA1), then rather use the hash of the data + * - this also protects against data being too short + */ #ifdef ENABLE_OPENSSL - SHA1(guid_bin, id.len + serialnr.len, guid_bin); - id.len = SHA_DIGEST_LENGTH; - serialnr.len = 0; + SHA1(guid_bin, guid_bin_size, guid_bin); + guid_bin_size = SHA_DIGEST_LENGTH; +#else + /* If guid_bin has a size larger than 16 bytes + * force the remaining bytes up to 16 bytes to be zero + * so sc_pkcs15_serialize_guid won't fail because the size is less than 16 + */ + if (guid_bin_size < 16) + guid_bin_size = 16; #endif - rv = sc_pkcs15_serialize_guid(guid_bin, id.len + serialnr.len, flags, (char *)out, *out_size); + rv = sc_pkcs15_serialize_guid(guid_bin, guid_bin_size, flags, (char *)out, *out_size); LOG_TEST_RET(ctx, rv, "Serialize GUID error"); *out_size = strlen((char *)out); LOG_FUNC_RETURN(ctx, rv); } -void sc_pkcs15_free_key_params(struct sc_pkcs15_key_params *params) + +void +sc_pkcs15_free_key_params(struct sc_pkcs15_key_params *params) { if (!params) return; From 49598b601631ec23df5512d21f77a9bb9be9e7e4 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Thu, 9 Apr 2015 11:48:59 +0200 Subject: [PATCH 167/306] libopensc: invalid OID comparison for EC keys Thanks to Peter Popovec --- src/libopensc/card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index b949b414..48f15579 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -859,7 +859,7 @@ static sc_algorithm_info_t * sc_card_find_alg(sc_card_t *card, continue; if (param) { if (info->algorithm == SC_ALGORITHM_EC) - if(sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id)) + if(!sc_compare_oid((struct sc_object_id *)param, &info->u._ec.params.id)) continue; } return info; From 5757d82cc965bf6851e2601cb1f48e84db02b8b2 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 11 Apr 2015 16:45:17 +0200 Subject: [PATCH 168/306] libopensc: stored-length member in PIN CMD data --- src/libopensc/opensc.h | 81 +++++------------------------------------- 1 file changed, 9 insertions(+), 72 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 63298adb..7964b311 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -324,7 +324,7 @@ typedef struct sc_reader { #define SC_PIN_CMD_GET_INFO 3 #define SC_PIN_CMD_USE_PINPAD 0x0001 -#define SC_PIN_CMD_NEED_PADDING 0x0002 +#define SC_PIN_CMD_NEED_PADDING 0x0002 #define SC_PIN_CMD_IMPLICIT_CHANGE 0x0004 #define SC_PIN_ENCODING_ASCII 0 @@ -334,14 +334,18 @@ typedef struct sc_reader { struct sc_pin_cmd_pin { const char *prompt; /* Prompt to display */ - const u8 *data; /* PIN, if given by the appliction */ + const unsigned char *data; /* PIN, if given by the appliction */ int len; /* set to -1 to get pin from pin pad */ - size_t min_length; /* min/max length of PIN */ - size_t max_length; + size_t min_length; /* min length of PIN */ + size_t max_length; /* max length of PIN */ + size_t stored_length; /* stored length of PIN */ + unsigned int encoding; /* ASCII-numeric, BCD, etc */ + size_t pad_length; /* filled in by the card driver */ - u8 pad_char; + unsigned char pad_char; + size_t offset; /* PIN offset in the APDU */ size_t length_offset; /* Effective PIN length offset in the APDU */ @@ -363,73 +367,6 @@ struct sc_pin_cmd_data { struct sc_apdu *apdu; /* APDU of the PIN command */ }; -#if 0 -#define PACE_PIN_ID_MRZ 0x01 -#define PACE_PIN_ID_CAN 0x02 -#define PACE_PIN_ID_PIN 0x03 -#define PACE_PIN_ID_PUK 0x04 -/** - * Input data for EstablishPACEChannel() - */ -struct establish_pace_channel_input { - /** Type of secret (CAN, MRZ, PIN or PUK). */ - unsigned char pin_id; - - /** Length of \a chat */ - size_t chat_length; - /** Card holder authorization template */ - const unsigned char *chat; - - /** Length of \a pin */ - size_t pin_length; - /** Secret */ - const unsigned char *pin; - - /** Length of \a certificate_description */ - size_t certificate_description_length; - /** Certificate description */ - const unsigned char *certificate_description; -}; - -/** - * Output data for EstablishPACEChannel() - */ -struct establish_pace_channel_output { - /** PACE result (TR-03119) */ - unsigned int result; - - /** MSE: Set AT status byte */ - unsigned char mse_set_at_sw1; - /** MSE: Set AT status byte */ - unsigned char mse_set_at_sw2; - - /** Length of \a ef_cardaccess */ - size_t ef_cardaccess_length; - /** EF.CardAccess */ - unsigned char *ef_cardaccess; - - /** Length of \a recent_car */ - size_t recent_car_length; - /** Most recent certificate authority reference */ - unsigned char *recent_car; - - /** Length of \a previous_car */ - size_t previous_car_length; - /** Previous certificate authority reference */ - unsigned char *previous_car; - - /** Length of \a id_icc */ - size_t id_icc_length; - /** ICC identifier */ - unsigned char *id_icc; - - /** Length of \a id_pcd */ - size_t id_pcd_length; - /** PCD identifier */ - unsigned char *id_pcd; -}; -#endif - struct sc_reader_operations { /* Called during sc_establish_context(), when the driver * is loaded */ From 3e2d51e0bacfef4a6cbaa1110874333772b9e598 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 11 Apr 2015 16:47:06 +0200 Subject: [PATCH 169/306] iasecc: use PIN PAD with variable PIN length --- src/libopensc/card-iasecc.c | 64 ++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index abe82451..45fe1f53 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -1801,15 +1801,14 @@ iasecc_chv_verify_pinpad(struct sc_card *card, struct sc_pin_cmd_data *pin_cmd, LOG_FUNC_RETURN(ctx, SC_ERROR_READER); } - sc_log(ctx, "reader %s", card->reader->name); - if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name) { - sc_log(ctx, "reader %s", card->reader->name); - if (pin_cmd->pin1.min_length != pin_cmd->pin1.max_length) { - sc_log(ctx, "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths."); - LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); - } - } - pin_cmd->pin1.len = pin_cmd->pin1.min_length; + /* When PIN stored length available + * P10 verify data contains full template of 'VERIFY PIN' APDU. + * Without PIN stored length + * pin-pad has to set the Lc and fill PIN data itself. + * Not all pin-pads support this case + */ + pin_cmd->pin1.len = pin_cmd->pin1.stored_length; + pin_cmd->pin1.length_offset = 5; memset(buffer, 0xFF, sizeof(buffer)); pin_cmd->pin1.data = buffer; @@ -2039,21 +2038,22 @@ iasecc_chv_change_pinpad(struct sc_card *card, unsigned reference, int *tries_le rv = iasecc_pin_get_policy(card, &pin_cmd); LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error"); - if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name) - if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length) - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, - "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths."); + /* Some pin-pads do not support mode with Lc=0. + * Give them a chance to work with some cards. + */ + if ((pin_cmd.pin1.min_length == pin_cmd.pin1.stored_length) && (pin_cmd.pin1.max_length == pin_cmd.pin1.min_length)) + pin_cmd.pin1.len = pin_cmd.pin1.stored_length; + else + pin_cmd.pin1.len = 0; - if (pin_cmd.pin1.min_length < 4) - pin_cmd.pin1.min_length = 4; - pin_cmd.pin1.len = pin_cmd.pin1.min_length; + pin_cmd.pin1.length_offset = 5; pin_cmd.pin1.data = pin1_data; memcpy(&pin_cmd.pin2, &pin_cmd.pin1, sizeof(pin_cmd.pin1)); pin_cmd.pin2.data = pin2_data; - sc_log(ctx, "PIN1 max/min: %i/%i", pin_cmd.pin1.max_length, pin_cmd.pin1.min_length); - sc_log(ctx, "PIN2 max/min: %i/%i", pin_cmd.pin2.max_length, pin_cmd.pin2.min_length); + sc_log(ctx, "PIN1 max/min/stored: %i/%i/%i", pin_cmd.pin1.max_length, pin_cmd.pin1.min_length, pin_cmd.pin1.stored_length); + sc_log(ctx, "PIN2 max/min/stored: %i/%i/%i", pin_cmd.pin2.max_length, pin_cmd.pin2.min_length, pin_cmd.pin2.stored_length); rv = iso_ops->pin_cmd(card, &pin_cmd, tries_left); LOG_FUNC_RETURN(ctx, rv); @@ -2087,18 +2087,17 @@ iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference) rv = iasecc_pin_get_policy(card, &pin_cmd); LOG_TEST_RET(ctx, rv, "Get 'PIN policy' error"); - if (strstr(card->reader->name, "Gemalto GemPC Pinpad") == card->reader->name) - if (pin_cmd.pin1.min_length != pin_cmd.pin1.max_length) - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, - "Bogus Gemalto GemPC Pinpad do not accept different values for min and max PIN lengths."); + if ((pin_cmd.pin1.min_length == pin_cmd.pin1.stored_length) && (pin_cmd.pin1.max_length == pin_cmd.pin1.min_length)) + pin_cmd.pin1.len = pin_cmd.pin1.stored_length; + else + pin_cmd.pin1.len = 0; - if (pin_cmd.pin1.min_length < 4) - pin_cmd.pin1.min_length = 4; - pin_cmd.pin1.len = pin_cmd.pin1.min_length; + pin_cmd.pin1.length_offset = 5; pin_cmd.pin1.data = pin_data; memcpy(&pin_cmd.pin2, &pin_cmd.pin1, sizeof(pin_cmd.pin1)); memset(&pin_cmd.pin1, 0, sizeof(pin_cmd.pin1)); + pin_cmd.flags |= SC_PIN_CMD_IMPLICIT_CHANGE; sc_log(ctx, "PIN1(max:%i,min:%i)", pin_cmd.pin1.max_length, pin_cmd.pin1.min_length); sc_log(ctx, "PIN2(max:%i,min:%i)", pin_cmd.pin2.max_length, pin_cmd.pin2.min_length); @@ -2158,6 +2157,7 @@ iasecc_pin_get_policy (struct sc_card *card, struct sc_pin_cmd_data *data) if (sdo.docp.acls_contact.size == 0) LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Extremely strange ... there is no ACLs"); + sc_log(ctx, "iasecc_pin_get_policy() sdo.docp.size.size %i %02X:%02X", sdo.docp.size.size, *(sdo.docp.size.value + 0), *(sdo.docp.size.value + 1)); for (ii=0; iipin1.max_tries = *sdo.docp.tries_maximum.value; if (sdo.docp.tries_remaining.value) data->pin1.tries_left = *sdo.docp.tries_remaining.value; + if (sdo.docp.size.value) { + for (ii=0; iipin1.stored_length = ((data->pin1.stored_length) << 8) + *(sdo.docp.size.value + ii); + } data->pin1.encoding = SC_PIN_ENCODING_ASCII; data->pin1.offset = 5; @@ -2400,6 +2404,7 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_ unsigned char se_num = scb & IASECC_SCB_METHOD_MASK_REF; if (scb & IASECC_SCB_METHOD_USER_AUTH) { + sc_log(ctx, "Verify PIN in SE %X", se_num); rv = iasecc_pin_verify(card, SC_AC_SEN, se_num, data->pin1.data, data->pin1.len, tries_left); LOG_TEST_RET(ctx, rv, "iasecc_pin_reset() verify PUK error"); @@ -2421,6 +2426,7 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_ iasecc_sdo_free_fields(card, &sdo); if (data->pin2.len) { + sc_log(ctx, "Reset PIN %X and set new value", reference); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2C, 0x02, reference); apdu.data = data->pin2.data; apdu.datalen = data->pin2.len; @@ -2432,6 +2438,7 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_ LOG_TEST_RET(ctx, rv, "PIN cmd failed"); } else if (data->pin2.data) { + sc_log(ctx, "Reset PIN %X and set new value", reference); sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2C, 3, reference); rv = sc_transmit_apdu(card, &apdu); @@ -2440,8 +2447,13 @@ iasecc_pin_reset(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_ LOG_TEST_RET(ctx, rv, "PIN cmd failed"); } else { + sc_log(ctx, "Reset PIN %X and set new value with PIN-PAD", reference); +#if 0 rv = iasecc_chv_set_pinpad(card, reference); - sc_log(ctx, "Set CHV with PIN pad returned %i", rv); + LOG_TEST_RET(ctx, rv, "Reset PIN failed"); +#else + LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Reset retry counter with PIN PAD not supported "); +#endif } if (save_current) { From d7ab0df51d3df026522f811e5d86809112e294d2 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 4 Apr 2015 03:02:54 +0200 Subject: [PATCH 170/306] export sc_pkcs15_bind_internal allows bootstrapping an external pkcs15 driver --- src/libopensc/libopensc.exports | 1 + src/libopensc/pkcs15.c | 2 +- src/libopensc/pkcs15.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index 7c64d9aa..0da5c53b 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -237,6 +237,7 @@ sc_pkcs15emu_add_ec_prkey sc_pkcs15emu_add_ec_pubkey sc_pkcs15emu_add_x509_cert sc_pkcs15emu_object_add +sc_pkcs15_bind_internal sc_print_path sc_put_data sc_read_binary diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 41e714d7..3852abc8 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -969,7 +969,7 @@ sc_pkcs15_get_application_by_type(struct sc_card * card, char *app_type) } -static int +int sc_pkcs15_bind_internal(struct sc_pkcs15_card *p15card, struct sc_aid *aid) { struct sc_path tmppath; diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index b6958dd0..1ceb9eb8 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -668,6 +668,7 @@ int sc_pkcs15_bind(struct sc_card *card, struct sc_aid *aid, /* sc_pkcs15_unbind: Releases a PKCS #15 card object, and frees any * memory allocations done on the card object. */ int sc_pkcs15_unbind(struct sc_pkcs15_card *card); +int sc_pkcs15_bind_internal(struct sc_pkcs15_card *p15card, struct sc_aid *aid); int sc_pkcs15_get_objects(struct sc_pkcs15_card *card, unsigned int type, struct sc_pkcs15_object **ret, size_t ret_count); From 643080baf9ffd404c88cb99493668eacfff3ab5e Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 10 Apr 2015 07:28:13 +0200 Subject: [PATCH 171/306] honour key capabilities for decryption/verification fixes #419 --- src/pkcs11/mechanism.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index fec1123a..fc6dcecf 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -609,6 +609,18 @@ sc_pkcs11_verify_init(sc_pkcs11_operation_t *operation, data->info = NULL; data->key = key; + if (key->ops->can_do) { + rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_SIGN); + if (rv == CKR_OK) { + /* Mechanism recognised and can be performed by pkcs#15 card */ + } + else { + /* Mechanism cannot be performed by pkcs#15 card, or some general error. */ + free(data); + LOG_FUNC_RETURN(context, rv); + } + } + /* If this is a verify with hash operation, set up the * hash operation */ info = (struct hash_signature_info *) operation->type->mech_data; @@ -869,12 +881,25 @@ sc_pkcs11_decrypt_init(sc_pkcs11_operation_t *operation, struct sc_pkcs11_object *key) { struct signature_data *data; + CK_RV rv; if (!(data = calloc(1, sizeof(*data)))) return CKR_HOST_MEMORY; data->key = key; + if (key->ops->can_do) { + rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_DECRYPT); + if (rv == CKR_OK) { + /* Mechanism recognised and can be performed by pkcs#15 card */ + } + else { + /* Mechanism cannot be performed by pkcs#15 card, or some general error. */ + free(data); + LOG_FUNC_RETURN(context, rv); + } + } + operation->priv_data = data; return CKR_OK; } From 6e84ee0ba779c4c527f5c979ef2751ee256da0ba Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 10 Apr 2015 07:42:00 +0200 Subject: [PATCH 172/306] pkcs11-tool: honour unsupported signature mechs --- src/tools/pkcs11-tool.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index b79beeec..bb781e9d 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -3494,6 +3494,9 @@ static int test_signature(CK_SESSION_HANDLE sess) ck_mech.mechanism = firstMechType; rv = p11->C_SignInit(sess, &ck_mech, privKeyObject); + /* mechanism not implemented, don't test */ + if (rv == CKR_MECHANISM_INVALID) + return errors; if (rv != CKR_OK) p11_fatal("C_SignInit", rv); From 6caa85f238d437198f92a70644675df7e2128c20 Mon Sep 17 00:00:00 2001 From: German Blanco Date: Wed, 8 Apr 2015 15:04:42 +0200 Subject: [PATCH 173/306] Issue 395. Avoiding a couple of memory leaks. --- .gitignore | 1 + src/libopensc/cwa14890.c | 52 ++++++++++++++++++++++++++++++---------- src/libopensc/cwa14890.h | 17 ------------- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 74d89dd3..f69bedbf 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,7 @@ doc/tools/pkcs15-init doc/tools/pkcs15-tool doc/tools/sc-hsm-tool doc/tools/westcos-tool +doc/tools/dnie-tool etc/opensc.conf.win etc/opensc.conf diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index 174f1ef7..dc88ff7b 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -43,6 +43,23 @@ #include "cwa14890.h" +/** + * Structure used to compose BER-TLV encoded data + * according to iso7816-4 sect 5.2.2. + * + * Notice that current implementation does not handle properly + * multibyte tag id. Just asume that tag is 1-byte length + * Also, encodings for data length longer than 0x01000000 bytes + * are not supported (tag 0x84) + */ +typedef struct cwa_tlv_st { + u8 *buf; /** local copy of TLV byte array */ + size_t buflen; /** lengt of buffer */ + unsigned int tag; /** tag ID */ + size_t len; /** length of data field */ + u8 *data; /** pointer to start of data in buf buffer */ +} cwa_tlv_t; + /*********************** utility functions ************************/ /** @@ -242,13 +259,13 @@ static int cwa_compose_tlv(sc_card_t * card, * @return SC_SUCCESS if OK; else error code */ static int cwa_parse_tlv(sc_card_t * card, - u8 * data, size_t datalen, cwa_tlv_t tlv_array[] + u8 * buffer, size_t datalen, + cwa_tlv_t tlv_array[] ) { size_t n = 0; size_t next = 0; sc_context_t *ctx = NULL; - u8 *buffer = NULL; /* preliminary checks */ if (!card || !card->ctx) @@ -257,14 +274,9 @@ static int cwa_parse_tlv(sc_card_t * card, ctx = card->ctx; LOG_FUNC_CALLED(ctx); - if (!data || !tlv_array) + if (!tlv_array) LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); - /* create buffer and copy data into */ - buffer = calloc(datalen, sizeof(u8)); - if (!buffer) - LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); - memcpy(buffer, data, datalen); for (n = 0; n < datalen; n += next) { cwa_tlv_t *tlv = NULL; /* pointer to TLV structure to store info */ size_t j = 2; /* TLV has at least two bytes */ @@ -324,7 +336,6 @@ static int cwa_parse_tlv(sc_card_t * card, /* set index to next Tag to jump to */ next = tlv->buflen; } - free(buffer); LOG_FUNC_RETURN(ctx, SC_SUCCESS); /* mark no error */ } @@ -1592,16 +1603,20 @@ int cwa_encode_apdu(sc_card_t * card, goto encode_end; } } + /* that's all folks */ res = SC_SUCCESS; + goto encode_end_apdu_valid; encode_end: + if (apdubuf) + free(apdubuf); +encode_end_apdu_valid: if (msg) sc_log(ctx, msg); free(msgbuf); free(cryptbuf); free(ccbuf); - free(apdubuf); LOG_FUNC_RETURN(ctx, res); } @@ -1629,6 +1644,7 @@ int cwa_decode_response(sc_card_t * card, cwa_tlv_t *e_tlv = &tlv_array[1]; /* to store pad encoded data (Tag 0x87) */ cwa_tlv_t *m_tlv = &tlv_array[2]; /* to store mac CC (Tag 0x8E) */ cwa_tlv_t *s_tlv = &tlv_array[3]; /* to store sw1-sw2 status (Tag 0x99) */ + u8 *buffer = NULL; /* buffer for data. pointers to this buffer are in tlv_array */ u8 *ccbuf = NULL; /* buffer for mac CC calculation */ size_t cclen = 0; /* ccbuf len */ u8 macbuf[8]; /* where to calculate mac */ @@ -1692,8 +1708,16 @@ int cwa_decode_response(sc_card_t * card, /* parse response to find TLV's data and check results */ memset(tlv_array, 0, 4 * sizeof(cwa_tlv_t)); + /* create buffer and copy data into */ + buffer = calloc(from->resplen, sizeof(u8)); + if (!buffer) { + msg = "Cannot allocate space for response buffer"; + res = SC_ERROR_OUT_OF_MEMORY; + goto response_decode_end; + } + memcpy(buffer, from->resp, from->resplen); - res = cwa_parse_tlv(card, from->resp, from->resplen, tlv_array); + res = cwa_parse_tlv(card, buffer, from->resplen, tlv_array); if (res != SC_SUCCESS) { msg = "Error in TLV parsing"; goto response_decode_end; @@ -1794,7 +1818,7 @@ int cwa_decode_response(sc_card_t * card, if (to->resp) { /* if response apdu provides buffer, try to use it */ if (to->resplen < resplen) { msg = - "Provided buffer has not enought size to store response"; + "Provided buffer has not enough size to store response"; res = SC_ERROR_OUT_OF_MEMORY; goto response_decode_end; } @@ -1862,7 +1886,7 @@ int cwa_decode_response(sc_card_t * card, res = provider->cwa_decode_post_ops(card, provider, from, to); if (res != SC_SUCCESS) { sc_log(ctx, "Decode APDU: provider post_ops() failed"); - LOG_FUNC_RETURN(ctx, res); + goto response_decode_end; } } @@ -1870,6 +1894,8 @@ int cwa_decode_response(sc_card_t * card, res = SC_SUCCESS; response_decode_end: + if (buffer) + free(buffer); if (ccbuf) free(ccbuf); if (msg) { diff --git a/src/libopensc/cwa14890.h b/src/libopensc/cwa14890.h index 10a0e0ee..5cebe728 100644 --- a/src/libopensc/cwa14890.h +++ b/src/libopensc/cwa14890.h @@ -51,23 +51,6 @@ #include #include -/** - * Structure used to compose BER-TLV encoded data - * according to iso7816-4 sect 5.2.2. - * - * Notice that current implementation does not handle properly - * multibyte tag id. Just asume that tag is 1-byte lenght - * Also, encodings for data lenght longer than 0x01000000 bytes - * are not supported (tag 0x84) - */ -typedef struct cwa_tlv_st { - u8 *buf; /** local copy of TLV byte array */ - size_t buflen; /** lengt of buffer */ - unsigned int tag; /** tag ID */ - size_t len; /** lenght of data field */ - u8 *data; /** pointer to start of data in buf buffer */ -} cwa_tlv_t; - /** * Structure used to handle keys and sequence counter once SM session * is stablished From 96556dea7bff431e794641fcae6b732395e00854 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 12 Apr 2015 13:35:20 +0200 Subject: [PATCH 174/306] fix #433: EC privateD octetstring may need leading zeros --- src/libopensc/pkcs15-prkey.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 7b8a6af3..6460f1f8 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -681,6 +681,7 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key) assert(EC_KEY_get0_public_key(src)); pkcs15_key->algorithm = SC_ALGORITHM_EC; + if (!sc_pkcs15_convert_bignum(&dst->privateD, EC_KEY_get0_private_key(src))) return SC_ERROR_INCOMPATIBLE_KEY; @@ -696,17 +697,29 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key) /* Decode EC_POINT from a octet string */ buflen = EC_POINT_point2oct(grp, (const EC_POINT *) EC_KEY_get0_public_key(src), POINT_CONVERSION_UNCOMPRESSED, buf, buflen, NULL); + if (!buflen) + return SC_ERROR_INCOMPATIBLE_KEY; /* copy the public key */ - if (buflen > 0) { - dst->ecpointQ.value = malloc(buflen); - memcpy(dst->ecpointQ.value, buf, buflen); - dst->ecpointQ.len = buflen; - /* calculate the field length */ - dst->params.field_length = (buflen - 1) / 2 * 8; - } - else { - return SC_ERROR_INCOMPATIBLE_KEY; + dst->ecpointQ.value = malloc(buflen); + memcpy(dst->ecpointQ.value, buf, buflen); + dst->ecpointQ.len = buflen; + + /* calculate the field length */ + dst->params.field_length = (buflen - 1) / 2 * 8; + + /* Octetstring may need leading zeros if BN is to short */ + if (dst->privateD.len < dst->params.field_length/8) { + size_t d = dst->params.field_length/8 - dst->privateD.len; + + dst->privateD.data = realloc(dst->privateD.data, dst->privateD.len + d); + if (!dst->privateD.data) + return SC_ERROR_OUT_OF_MEMORY; + + memmove(dst->privateD.data + d, dst->privateD.data, dst->privateD.len); + memset(dst->privateD.data, 0, d); + + dst->privateD.len += d; } break; From a7a903fd811fbe95606fad4b8087f936d6f711cf Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 14 Apr 2015 13:26:27 +0200 Subject: [PATCH 175/306] check ATRs even for forced card driver some card drivers depend on a card type which is initialized by matching the card's ATR --- src/libopensc/card.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 48f15579..33a55a89 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -190,10 +190,14 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) } if (driver != NULL) { - /* Forced driver, or matched via ATR mapping from - * config file */ + /* Forced driver, or matched via ATR mapping from config file */ card->driver = driver; + memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations)); + if (card->ops->match_card != NULL) + if (card->ops->match_card(card) != 1) + sc_log(ctx, "driver '%s' match_card() failed: %s (will continue anyway)", card->driver->name, sc_strerror(r)); + if (card->ops->init != NULL) { r = card->ops->init(card); if (r) { From 23ca1f101db0b4fca09bfb51b4fb4d67dbfc2435 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Tue, 14 Apr 2015 17:52:22 +0200 Subject: [PATCH 176/306] pkcs11-tool: Add support for creating EC privkey * This patch allows to create EC private keys. The feature re-use the GOST parsing function as instanciating an ECDSA key is the same as a GOST key. --- src/tools/pkcs11-tool.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index bb781e9d..0a419b86 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -1716,7 +1716,7 @@ do_read_private_key(unsigned char *data, size_t data_len, EVP_PKEY **key) mem = BIO_new(BIO_s_mem()); BIO_set_mem_buf(mem, &buf_mem, BIO_NOCLOSE); - if (!strstr((char *)data, "-----BEGIN PRIVATE KEY-----")) + if (!strstr((char *)data, "-----BEGIN PRIVATE KEY-----") && !strstr((char *)data, "-----BEGIN EC PRIVATE KEY-----")) *key = d2i_PrivateKey_bio(mem, NULL); else *key = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL); @@ -1895,7 +1895,8 @@ static int write_object(CK_SESSION_HANDLE session) rv = parse_rsa_private_key(&rsa, contents, contents_len); } #if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) - else if (evp_key->type == NID_id_GostR3410_2001) { + else if (evp_key->type == NID_id_GostR3410_2001 || evp_key->type == EVP_PKEY_EC) { + /* parsing ECDSA is identical to GOST */ rv = parse_gost_private_key(evp_key, &gost); } #endif @@ -1998,6 +1999,16 @@ static int write_object(CK_SESSION_HANDLE session) n_privkey_attr++; } #if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_EC) + else if (evp_key->type == EVP_PKEY_EC) { + type = CKK_EC; + + FILL_ATTR(privkey_templ[n_privkey_attr], CKA_KEY_TYPE, &type, sizeof(type)); + n_privkey_attr++; + FILL_ATTR(privkey_templ[n_privkey_attr], CKA_EC_PARAMS, gost.param_oid.value, gost.param_oid.len); + n_privkey_attr++; + FILL_ATTR(privkey_templ[n_privkey_attr], CKA_VALUE, gost.private.value, gost.private.len); + n_privkey_attr++; + } else if (evp_key->type == NID_id_GostR3410_2001) { type = CKK_GOSTR3410; From 17eb40e5f9eadc760945e7df3be2436d330ef592 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Wed, 15 Apr 2015 09:33:24 +0200 Subject: [PATCH 177/306] doc: add 'signature-format' option for pkcs15-crypt --- doc/tools/pkcs15-crypt.1.xml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/tools/pkcs15-crypt.1.xml b/doc/tools/pkcs15-crypt.1.xml index 2053ba12..40dd262b 100644 --- a/doc/tools/pkcs15-crypt.1.xml +++ b/doc/tools/pkcs15-crypt.1.xml @@ -159,6 +159,18 @@ (see also ). + + + , + + + When signing with ECDSA key this option indicates + to pkcs15-crypt the signature output format. + Possible values are 'rs'(default) -- two concatanated + integers (PKCS#11), 'sequence' or 'openssl' -- DER encoded sequence + of two integeres (OpenSSL). + + , @@ -168,7 +180,6 @@ verbose. Specify this flag several times to enable debug output in the OpenSC library. - From c45c90a337a3126f8e37031a552c23578d298c0b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 16:18:11 +0200 Subject: [PATCH 178/306] sc_pkcs11_close_all_sessions: close all sessions even if closing one fails --- src/pkcs11/pkcs11-session.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c index e6edf25c..143ab56e 100644 --- a/src/pkcs11/pkcs11-session.c +++ b/src/pkcs11/pkcs11-session.c @@ -120,17 +120,17 @@ static CK_RV sc_pkcs11_close_session(CK_SESSION_HANDLE hSession) * the global lock held */ CK_RV sc_pkcs11_close_all_sessions(CK_SLOT_ID slotID) { - CK_RV rv = CKR_OK; + CK_RV rv = CKR_OK, error; struct sc_pkcs11_session *session; unsigned int i; sc_log(context, "real C_CloseAllSessions(0x%lx) %d", slotID, list_size(&sessions)); for (i = 0; i < list_size(&sessions); i++) { session = list_get_at(&sessions, i); if (session->slot->id == slotID) - if ((rv = sc_pkcs11_close_session(session->handle)) != CKR_OK) - return rv; + if ((error = sc_pkcs11_close_session(session->handle)) != CKR_OK) + rv = error; } - return CKR_OK; + return rv; } CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) From 54f285d57ada65fc7774e82e2f0d10c35060d7ed Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 23:30:06 +0200 Subject: [PATCH 179/306] correctly handle readers that have been removed --- src/libopensc/opensc.h | 1 + src/libopensc/reader-pcsc.c | 23 +++++++++++++++-------- src/pkcs11/slot.c | 14 +++++++++----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 7964b311..90f0e2e0 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -286,6 +286,7 @@ struct sc_reader_driver { #define SC_READER_CARD_INUSE 0x00000004 #define SC_READER_CARD_EXCLUSIVE 0x00000008 #define SC_READER_HAS_WAITING_AREA 0x00000010 +#define SC_READER_REMOVED 0x00000020 /* reader capabilities */ #define SC_READER_CAP_DISPLAY 0x00000001 diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 06192cf3..32007394 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -949,6 +949,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) char *reader_buf = NULL, *reader_name; const char *mszGroups = NULL; int ret = SC_ERROR_INTERNAL; + size_t i; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); @@ -958,7 +959,13 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } - sc_log(ctx, "Probing pcsc readers"); + /* temporarily mark all readers as removed */ + for (i=0;i < sc_ctx_get_reader_count(ctx);i++) { + sc_reader_t *reader = sc_ctx_get_reader(ctx, i); + reader->flags |= SC_READER_REMOVED; + } + + sc_log(ctx, "Probing PC/SC readers"); do { if (gpriv->pcsc_ctx == -1) { @@ -980,7 +987,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } - sc_log(ctx, "Establish pcsc context"); + sc_log(ctx, "Establish PC/SC context"); rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_ctx); @@ -1007,28 +1014,28 @@ static int pcsc_detect_readers(sc_context_t *ctx) goto out; } for (reader_name = reader_buf; *reader_name != '\x0'; reader_name += strlen(reader_name) + 1) { - sc_reader_t *reader = NULL; + sc_reader_t *reader = NULL, *old_reader; struct pcsc_private_data *priv = NULL; - unsigned int i; int found = 0; for (i=0;i < sc_ctx_get_reader_count(ctx) && !found;i++) { - sc_reader_t *reader2 = sc_ctx_get_reader(ctx, i); - if (reader2 == NULL) { + old_reader = sc_ctx_get_reader(ctx, i); + if (old_reader == NULL) { ret = SC_ERROR_INTERNAL; goto err1; } - if (!strcmp(reader2->name, reader_name)) { + if (!strcmp(old_reader->name, reader_name)) { found = 1; } } /* Reader already available, skip */ if (found) { + old_reader->flags &= ~SC_READER_REMOVED; continue; } - sc_log(ctx, "Found new pcsc reader '%s'", reader_name); + sc_log(ctx, "Found new PC/SC reader '%s'", reader_name); if ((reader = calloc(1, sizeof(sc_reader_t))) == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 87b1e3dd..9f2ae484 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -330,9 +330,13 @@ card_detect_all(void) /* Detect cards in all initialized readers */ for (i=0; i< sc_ctx_get_reader_count(context); i++) { sc_reader_t *reader = sc_ctx_get_reader(context, i); - if (!reader_get_slot(reader)) - initialize_reader(reader); - card_detect(sc_ctx_get_reader(context, i)); + if (reader->flags & SC_READER_REMOVED) { + card_removed(reader); + } else { + if (!reader_get_slot(reader)) + initialize_reader(reader); + card_detect(sc_ctx_get_reader(context, i)); + } } sc_log(context, "All cards detected"); return CKR_OK; @@ -420,7 +424,7 @@ CK_RV slot_token_removed(CK_SLOT_ID id) /* Release framework stuff */ if (slot->card != NULL) { if (slot->fw_data != NULL && - slot->card->framework != NULL && slot->card->framework->release_token != NULL) + slot->card->framework != NULL && slot->card->framework->release_token != NULL) slot->card->framework->release_token(slot->card, slot->fw_data); } @@ -446,7 +450,7 @@ CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask) sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); sc_log(context, "slot 0x%lx token: %d events: 0x%02X",slot->id, (slot->slot_info.flags & CKF_TOKEN_PRESENT), slot->events); if ((slot->events & SC_EVENT_CARD_INSERTED) - && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) { + && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) { /* If a token has not been initialized, clear the inserted event */ slot->events &= ~SC_EVENT_CARD_INSERTED; } From c8a7c8bc7aec67f95254dd900f394f6c55429f4e Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 22:44:33 +0200 Subject: [PATCH 180/306] fixed typo --- src/pkcs15init/pkcs15-myeid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index 5bf7d2b2..063fd2c4 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -646,7 +646,7 @@ myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, memcpy(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); } else if (object->type == SC_PKCS15_TYPE_PRKEY_EC) { - struct sc_ec_parameters *ecparams = (struct sc_pkcs15_ec_parameters *)key_info->params.data; + struct sc_ec_parameters *ecparams = (struct sc_ec_parameters *)key_info->params.data; sc_log(ctx, "curve '%s', len %i, oid '%s'", ecparams->named_curve, ecparams->field_length, sc_dump_oid(&(ecparams->id))); pubkey->algorithm = SC_ALGORITHM_EC; From cbc43eeb88c619b1f488dd937d89b2fc5546ef83 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Apr 2015 23:04:47 +0200 Subject: [PATCH 181/306] fixed compiler warning --- src/libopensc/card-iasecc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 45fe1f53..43974897 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -572,6 +572,7 @@ iasecc_init_amos(struct sc_card *card) LOG_FUNC_RETURN(ctx, SC_SUCCESS); } +static int iasecc_mi_match(struct sc_card *card) { struct sc_context *ctx = card->ctx; @@ -2060,6 +2061,7 @@ iasecc_chv_change_pinpad(struct sc_card *card, unsigned reference, int *tries_le } +#if 0 static int iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference) { @@ -2105,6 +2107,7 @@ iasecc_chv_set_pinpad(struct sc_card *card, unsigned char reference) rv = iso_ops->pin_cmd(card, &pin_cmd, NULL); LOG_FUNC_RETURN(ctx, rv); } +#endif static int From e359b2a310c739c8f7f2447d716a65268cbb40cd Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 21 Apr 2015 00:57:22 +0200 Subject: [PATCH 182/306] handle unexpected meltdown of PC/SC service --- src/libopensc/reader-pcsc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 32007394..0765885c 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -979,6 +979,13 @@ static int pcsc_detect_readers(sc_context_t *ctx) else { rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, NULL, NULL, (LPDWORD) &reader_buf_size); + if (rv == SCARD_E_NO_SERVICE) { + gpriv->SCardReleaseContext(gpriv->pcsc_ctx); + gpriv->pcsc_ctx = -1; + gpriv->pcsc_wait_ctx = -1; + /* reconnecting below may may restart PC/SC service */ + rv = SCARD_E_INVALID_HANDLE; + } } if (rv != SCARD_S_SUCCESS) { if (rv != (LONG)SCARD_E_INVALID_HANDLE) { From 02f3997632d147ad3e55a51a74794602d38144eb Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 21 Apr 2015 01:32:37 +0200 Subject: [PATCH 183/306] added error handling to print_ssh_key --- src/tools/pkcs15-tool.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index de3e6b33..4f7c0e36 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -803,6 +803,8 @@ static void print_ssh_key(FILE *outf, const char * alg, struct sc_pkcs15_object if (opt_rfc4716) { r = sc_base64_encode(buf, len, uu, 2*len, 64); + if (r < 0) + return; fprintf(outf,"---- BEGIN SSH2 PUBLIC KEY ----\n"); @@ -815,6 +817,9 @@ static void print_ssh_key(FILE *outf, const char * alg, struct sc_pkcs15_object // Old style openssh - [ [ anything else] // r = sc_base64_encode(buf, len, uu, 2*len, 0); + if (r < 0) + return; + if (obj->label && strlen(obj->label)) fprintf(outf,"ssh-%s %s %s\n", alg, uu, obj->label); else From 9f318b829fb9e2fa42d875a4e2afd576d5fc73ad Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 21 Apr 2015 02:00:06 +0200 Subject: [PATCH 184/306] remove slots of removed readers --- src/libopensc/internal.h | 1 - src/libopensc/libopensc.exports | 1 + src/libopensc/opensc.h | 2 ++ src/pkcs11/slot.c | 16 ++++++++++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h index 2658428b..418e4179 100644 --- a/src/libopensc/internal.h +++ b/src/libopensc/internal.h @@ -74,7 +74,6 @@ struct sc_atr_table { /* Internal use only */ int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader); -int _sc_delete_reader(struct sc_context *ctx, struct sc_reader *reader); int _sc_parse_atr(struct sc_reader *reader); /* Add an ATR to the card driver's struct sc_atr_table */ diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index 0da5c53b..cea8d42f 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -77,6 +77,7 @@ sc_ctx_get_reader_by_name sc_ctx_get_reader_count sc_ctx_log_to_file sc_ctx_use_reader +_sc_delete_reader sc_decipher sc_delete_file sc_delete_record diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 90f0e2e0..ad5405d5 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -803,6 +803,8 @@ sc_reader_t *sc_ctx_get_reader_by_id(sc_context_t *ctx, unsigned int id); */ unsigned int sc_ctx_get_reader_count(sc_context_t *ctx); +int _sc_delete_reader(sc_context_t *ctx, sc_reader_t *reader); + /** * Redirects OpenSC debug log to the specified file * @param ctx existing OpenSC context diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 9f2ae484..1d9c1a41 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -20,6 +20,7 @@ */ #include "config.h" +#include "libopensc/opensc.h" #include #include @@ -100,6 +101,15 @@ CK_RV create_slot(sc_reader_t *reader) return CKR_OK; } +void delete_slot(struct sc_pkcs11_slot *slot) +{ + if (slot) { + list_destroy(&slot->objects); + list_delete(&virtual_slots, slot); + free(slot); + } +} + /* create slots associated with a reader, called whenever a reader is seen. */ CK_RV initialize_reader(sc_reader_t *reader) @@ -331,7 +341,13 @@ card_detect_all(void) for (i=0; i< sc_ctx_get_reader_count(context); i++) { sc_reader_t *reader = sc_ctx_get_reader(context, i); if (reader->flags & SC_READER_REMOVED) { + struct sc_pkcs11_slot *slot; card_removed(reader); + while ((slot = reader_get_slot(reader))) { + delete_slot(slot); + } + _sc_delete_reader(context, reader); + i--; } else { if (!reader_get_slot(reader)) initialize_reader(reader); From bcb5fc15e5b6224d2bdd8edb3c0346812dc89d38 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 22 Apr 2015 23:55:33 +0200 Subject: [PATCH 185/306] honour HAVE_CONFIG_H --- src/common/compat_getopt.c | 2 ++ src/common/compat_getpass.c | 2 ++ src/common/compat_strlcat.c | 2 ++ src/common/compat_strlcpy.c | 2 ++ src/common/libpkcs11.c | 2 ++ src/libopensc/apdu.c | 2 ++ src/libopensc/asn1.c | 2 ++ src/libopensc/base64.c | 2 ++ src/libopensc/card-acos5.c | 2 ++ src/libopensc/card-akis.c | 2 ++ src/libopensc/card-asepcos.c | 2 ++ src/libopensc/card-atrust-acos.c | 2 ++ src/libopensc/card-belpic.c | 2 ++ src/libopensc/card-cardos.c | 2 ++ src/libopensc/card-default.c | 2 ++ src/libopensc/card-entersafe.c | 2 ++ src/libopensc/card-epass2003.c | 2 ++ src/libopensc/card-flex.c | 2 ++ src/libopensc/card-gemsafeV1.c | 2 ++ src/libopensc/card-gpk.c | 2 ++ src/libopensc/card-ias.c | 2 ++ src/libopensc/card-incrypto34.c | 2 ++ src/libopensc/card-jcop.c | 2 ++ src/libopensc/card-mcrd.c | 2 ++ src/libopensc/card-miocos.c | 2 ++ src/libopensc/card-muscle.c | 2 ++ src/libopensc/card-myeid.c | 2 ++ src/libopensc/card-oberthur.c | 2 ++ src/libopensc/card-openpgp.c | 2 ++ src/libopensc/card-piv.c | 2 ++ src/libopensc/card-rtecp.c | 2 ++ src/libopensc/card-rutoken.c | 2 ++ src/libopensc/card-sc-hsm.c | 2 ++ src/libopensc/card-setcos.c | 2 ++ src/libopensc/card-starcos.c | 2 ++ src/libopensc/card-tcos.c | 2 ++ src/libopensc/card-westcos.c | 2 ++ src/libopensc/card.c | 2 ++ src/libopensc/compression.c | 2 ++ src/libopensc/ctbcs.c | 2 ++ src/libopensc/ctx.c | 2 ++ src/libopensc/dir.c | 2 ++ src/libopensc/errors.c | 2 ++ src/libopensc/log.c | 2 ++ src/libopensc/muscle-filesystem.c | 2 ++ src/libopensc/muscle.c | 2 ++ src/libopensc/p15card-helper.c | 2 ++ src/libopensc/padding.c | 2 ++ src/libopensc/pkcs15-actalis.c | 2 ++ src/libopensc/pkcs15-algo.c | 2 ++ src/libopensc/pkcs15-atrust-acos.c | 2 ++ src/libopensc/pkcs15-cache.c | 2 ++ src/libopensc/pkcs15-cert.c | 2 ++ src/libopensc/pkcs15-data.c | 2 ++ src/libopensc/pkcs15-dnie.c | 2 ++ src/libopensc/pkcs15-esinit.c | 2 ++ src/libopensc/pkcs15-esteid.c | 2 ++ src/libopensc/pkcs15-gemsafeGPK.c | 2 ++ src/libopensc/pkcs15-gemsafeV1.c | 2 ++ src/libopensc/pkcs15-infocamere.c | 2 ++ src/libopensc/pkcs15-openpgp.c | 2 ++ src/libopensc/pkcs15-pin.c | 2 ++ src/libopensc/pkcs15-piv.c | 2 ++ src/libopensc/pkcs15-postecert.c | 2 ++ src/libopensc/pkcs15-prkey.c | 2 ++ src/libopensc/pkcs15-pteid.c | 2 ++ src/libopensc/pkcs15-pubkey.c | 2 ++ src/libopensc/pkcs15-sc-hsm.c | 2 ++ src/libopensc/pkcs15-sec.c | 2 ++ src/libopensc/pkcs15-starcert.c | 2 ++ src/libopensc/pkcs15-syn.c | 2 ++ src/libopensc/pkcs15-tccardos.c | 2 ++ src/libopensc/pkcs15-tcos.c | 2 ++ src/libopensc/pkcs15-westcos.c | 2 ++ src/libopensc/reader-ctapi.c | 2 ++ src/libopensc/reader-openct.c | 2 ++ src/libopensc/reader-pcsc.c | 2 ++ src/libopensc/sc.c | 2 ++ src/libopensc/sec.c | 2 ++ src/libopensc/sm.c | 2 ++ 80 files changed, 160 insertions(+) diff --git a/src/common/compat_getopt.c b/src/common/compat_getopt.c index 688e6cc8..e44ebca6 100644 --- a/src/common/compat_getopt.c +++ b/src/common/compat_getopt.c @@ -23,7 +23,9 @@ * DEALINGS IN THE SOFTWARE. */ +#if HAVE_CONFIG_H #include "config.h" +#endif #if ! ( defined(HAVE_GETOPT_H) && defined(HAVE_GETOPT_LONG) && defined(HAVE_GETOPT_LONG_ONLY) ) diff --git a/src/common/compat_getpass.c b/src/common/compat_getpass.c index f0b09e92..22a1abd1 100644 --- a/src/common/compat_getpass.c +++ b/src/common/compat_getpass.c @@ -1,4 +1,6 @@ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifndef HAVE_GETPASS /* empty file if getpass is available */ #include diff --git a/src/common/compat_strlcat.c b/src/common/compat_strlcat.c index 7fe0cd6b..af373f11 100644 --- a/src/common/compat_strlcat.c +++ b/src/common/compat_strlcat.c @@ -27,7 +27,9 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifndef HAVE_STRLCAT #include diff --git a/src/common/compat_strlcpy.c b/src/common/compat_strlcpy.c index 3e09da73..88f3a5fb 100644 --- a/src/common/compat_strlcpy.c +++ b/src/common/compat_strlcpy.c @@ -16,7 +16,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifndef HAVE_STRLCPY /* empty file if strlcpy is available */ #include diff --git a/src/common/libpkcs11.c b/src/common/libpkcs11.c index b22d16de..58fb814c 100644 --- a/src/common/libpkcs11.c +++ b/src/common/libpkcs11.c @@ -5,7 +5,9 @@ * Copyright (C) 2002 Olaf Kirch */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/apdu.c b/src/libopensc/apdu.c index 38c75153..1a52d5a5 100644 --- a/src/libopensc/apdu.c +++ b/src/libopensc/apdu.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 1eeb2ef2..6938f193 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/base64.c b/src/libopensc/base64.c index 9152080c..961bd436 100644 --- a/src/libopensc/base64.c +++ b/src/libopensc/base64.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-acos5.c b/src/libopensc/card-acos5.c index ff6ee3db..3e392585 100644 --- a/src/libopensc/card-acos5.c +++ b/src/libopensc/card-acos5.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include diff --git a/src/libopensc/card-akis.c b/src/libopensc/card-akis.c index 684b8b0a..c84e5513 100644 --- a/src/libopensc/card-akis.c +++ b/src/libopensc/card-akis.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-asepcos.c b/src/libopensc/card-asepcos.c index 05f8b399..ad0f514d 100644 --- a/src/libopensc/card-asepcos.c +++ b/src/libopensc/card-asepcos.c @@ -16,7 +16,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-atrust-acos.c b/src/libopensc/card-atrust-acos.c index f0ac176b..9d3c41fd 100644 --- a/src/libopensc/card-atrust-acos.c +++ b/src/libopensc/card-atrust-acos.c @@ -20,7 +20,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-belpic.c b/src/libopensc/card-belpic.c index cfb963eb..bbfb0582 100644 --- a/src/libopensc/card-belpic.c +++ b/src/libopensc/card-belpic.c @@ -80,7 +80,9 @@ * language-selection functionality. */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index 52a90d94..b6b208ae 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -21,7 +21,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-default.c b/src/libopensc/card-default.c index b5501560..a17c2acb 100644 --- a/src/libopensc/card-default.c +++ b/src/libopensc/card-default.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c index b024a283..798d28fb 100644 --- a/src/libopensc/card-entersafe.c +++ b/src/libopensc/card-entersafe.c @@ -16,7 +16,9 @@ /* Initially written by Weitao Sun (weitao@ftsafe.com) 2008 */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_OPENSSL /* empty file without openssl */ #include diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c index 162e00d0..8c75a15e 100644 --- a/src/libopensc/card-epass2003.c +++ b/src/libopensc/card-epass2003.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_SM /* empty file without SM enabled */ #ifdef ENABLE_OPENSSL /* empty file without openssl */ diff --git a/src/libopensc/card-flex.c b/src/libopensc/card-flex.c index ff4c5085..3c031285 100644 --- a/src/libopensc/card-flex.c +++ b/src/libopensc/card-flex.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-gemsafeV1.c b/src/libopensc/card-gemsafeV1.c index 9c6816b6..be3ea5b5 100644 --- a/src/libopensc/card-gemsafeV1.c +++ b/src/libopensc/card-gemsafeV1.c @@ -17,7 +17,9 @@ /* Initially written by David Mattes (david.mattes@boeing.com) */ /* Portuguese eID card support by Joao Poupino (joao.poupino@ist.utl.pt) */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-gpk.c b/src/libopensc/card-gpk.c index 2b44884b..b7a2670a 100644 --- a/src/libopensc/card-gpk.c +++ b/src/libopensc/card-gpk.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_OPENSSL /* empty file without openssl */ #include diff --git a/src/libopensc/card-ias.c b/src/libopensc/card-ias.c index 489087c5..584d5d9d 100644 --- a/src/libopensc/card-ias.c +++ b/src/libopensc/card-ias.c @@ -22,7 +22,9 @@ * Thanks to Andre Cruz, Jorge Ferreira and Paulo F. Andrade */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-incrypto34.c b/src/libopensc/card-incrypto34.c index 117596ee..676a755d 100644 --- a/src/libopensc/card-incrypto34.c +++ b/src/libopensc/card-incrypto34.c @@ -21,7 +21,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-jcop.c b/src/libopensc/card-jcop.c index d01324c0..08a10972 100644 --- a/src/libopensc/card-jcop.c +++ b/src/libopensc/card-jcop.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-mcrd.c b/src/libopensc/card-mcrd.c index a72f4da7..3b4481ce 100644 --- a/src/libopensc/card-mcrd.c +++ b/src/libopensc/card-mcrd.c @@ -22,7 +22,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-miocos.c b/src/libopensc/card-miocos.c index 89638f5b..ad8add74 100644 --- a/src/libopensc/card-miocos.c +++ b/src/libopensc/card-miocos.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-muscle.c b/src/libopensc/card-muscle.c index 81a482e5..dc43029d 100644 --- a/src/libopensc/card-muscle.c +++ b/src/libopensc/card-muscle.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 6a9fd752..63eeaf03 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-oberthur.c b/src/libopensc/card-oberthur.c index 99352e26..b8a5cbc4 100644 --- a/src/libopensc/card-oberthur.c +++ b/src/libopensc/card-oberthur.c @@ -23,7 +23,9 @@ * best view with tabstop=4 */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_OPENSSL /* empty file without openssl */ #include diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 6c63a5e8..e819cf62 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -25,7 +25,9 @@ * http://www.g10code.de/docs/openpgp-card-2.0.pdf */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index e397c599..017a56b5 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -22,7 +22,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-rtecp.c b/src/libopensc/card-rtecp.c index d0634d04..8e3a4983 100644 --- a/src/libopensc/card-rtecp.c +++ b/src/libopensc/card-rtecp.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-rutoken.c b/src/libopensc/card-rutoken.c index efbf6b5b..295c23eb 100644 --- a/src/libopensc/card-rutoken.c +++ b/src/libopensc/card-rutoken.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index 98f7b9e5..efe43ab8 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -20,7 +20,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-setcos.c b/src/libopensc/card-setcos.c index 15da346e..2b0182a9 100644 --- a/src/libopensc/card-setcos.c +++ b/src/libopensc/card-setcos.c @@ -20,7 +20,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-starcos.c b/src/libopensc/card-starcos.c index 9d43e51d..db746aaf 100644 --- a/src/libopensc/card-starcos.c +++ b/src/libopensc/card-starcos.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-tcos.c b/src/libopensc/card-tcos.c index e41db406..f7d07f22 100644 --- a/src/libopensc/card-tcos.c +++ b/src/libopensc/card-tcos.c @@ -20,7 +20,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card-westcos.c b/src/libopensc/card-westcos.c index 60bcb999..76788bcf 100644 --- a/src/libopensc/card-westcos.c +++ b/src/libopensc/card-westcos.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 33a55a89..7daee5c5 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/compression.c b/src/libopensc/compression.c index d26ef1ff..9b38d822 100644 --- a/src/libopensc/compression.c +++ b/src/libopensc/compression.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_ZLIB /* empty file without zlib */ #include diff --git a/src/libopensc/ctbcs.c b/src/libopensc/ctbcs.c index ad51cac8..4b08ad6c 100644 --- a/src/libopensc/ctbcs.c +++ b/src/libopensc/ctbcs.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 2297193e..f6f7bde7 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/dir.c b/src/libopensc/dir.c index 4a3b1485..189fbee3 100644 --- a/src/libopensc/dir.c +++ b/src/libopensc/dir.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/errors.c b/src/libopensc/errors.c index adc55b87..b6c6eb48 100644 --- a/src/libopensc/errors.c +++ b/src/libopensc/errors.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include diff --git a/src/libopensc/log.c b/src/libopensc/log.c index 9d98413b..cac82803 100644 --- a/src/libopensc/log.c +++ b/src/libopensc/log.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/muscle-filesystem.c b/src/libopensc/muscle-filesystem.c index dc618a67..602c40dd 100644 --- a/src/libopensc/muscle-filesystem.c +++ b/src/libopensc/muscle-filesystem.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/muscle.c b/src/libopensc/muscle.c index 29a2f562..f0b1e921 100644 --- a/src/libopensc/muscle.c +++ b/src/libopensc/muscle.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include diff --git a/src/libopensc/p15card-helper.c b/src/libopensc/p15card-helper.c index 3bf698c8..1a16da7d 100644 --- a/src/libopensc/p15card-helper.c +++ b/src/libopensc/p15card-helper.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_OPENSSL /* empty file without openssl */ #include diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c index 21a56098..290e6160 100644 --- a/src/libopensc/padding.c +++ b/src/libopensc/padding.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-actalis.c b/src/libopensc/pkcs15-actalis.c index b8b2a0f7..9391418a 100644 --- a/src/libopensc/pkcs15-actalis.c +++ b/src/libopensc/pkcs15-actalis.c @@ -22,7 +22,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index f66692de..0465ccda 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-atrust-acos.c b/src/libopensc/pkcs15-atrust-acos.c index f59539bb..69bdb50e 100644 --- a/src/libopensc/pkcs15-atrust-acos.c +++ b/src/libopensc/pkcs15-atrust-acos.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c index b0c8269d..74d56431 100644 --- a/src/libopensc/pkcs15-cache.c +++ b/src/libopensc/pkcs15-cache.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index a930311a..80051b51 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-data.c b/src/libopensc/pkcs15-data.c index 5d7ad32a..1e0de8f7 100644 --- a/src/libopensc/pkcs15-data.c +++ b/src/libopensc/pkcs15-data.c @@ -20,7 +20,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-dnie.c b/src/libopensc/pkcs15-dnie.c index 077215f4..94d7f4cb 100644 --- a/src/libopensc/pkcs15-dnie.c +++ b/src/libopensc/pkcs15-dnie.c @@ -21,7 +21,9 @@ #include #include +#if HAVE_CONFIG_H #include "config.h" +#endif #include "libopensc/log.h" #include "libopensc/asn1.h" #include "libopensc/pkcs15.h" diff --git a/src/libopensc/pkcs15-esinit.c b/src/libopensc/pkcs15-esinit.c index f551b5bb..cabdb47e 100644 --- a/src/libopensc/pkcs15-esinit.c +++ b/src/libopensc/pkcs15-esinit.c @@ -15,7 +15,9 @@ */ /* Initially written by Weitao Sun (weitao@ftsafe.com) 2008*/ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-esteid.c b/src/libopensc/pkcs15-esteid.c index 6975fe10..3b4062f3 100644 --- a/src/libopensc/pkcs15-esteid.c +++ b/src/libopensc/pkcs15-esteid.c @@ -21,7 +21,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-gemsafeGPK.c b/src/libopensc/pkcs15-gemsafeGPK.c index 551b0a3b..f31d9af2 100644 --- a/src/libopensc/pkcs15-gemsafeGPK.c +++ b/src/libopensc/pkcs15-gemsafeGPK.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-gemsafeV1.c b/src/libopensc/pkcs15-gemsafeV1.c index c1191eef..b757b116 100644 --- a/src/libopensc/pkcs15-gemsafeV1.c +++ b/src/libopensc/pkcs15-gemsafeV1.c @@ -17,7 +17,9 @@ /* Initially written by David Mattes */ /* Support for multiple key containers by Lukas Wunner */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-infocamere.c b/src/libopensc/pkcs15-infocamere.c index 1ea1fefa..e51b37a9 100644 --- a/src/libopensc/pkcs15-infocamere.c +++ b/src/libopensc/pkcs15-infocamere.c @@ -21,7 +21,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c index 4daaa98c..044ed163 100644 --- a/src/libopensc/pkcs15-openpgp.c +++ b/src/libopensc/pkcs15-openpgp.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index 9ae07405..d73915a0 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index 724987bd..549a91b9 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -24,7 +24,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-postecert.c b/src/libopensc/pkcs15-postecert.c index a62edd3a..6842bda4 100644 --- a/src/libopensc/pkcs15-postecert.c +++ b/src/libopensc/pkcs15-postecert.c @@ -20,7 +20,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 6460f1f8..d96008f5 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-pteid.c b/src/libopensc/pkcs15-pteid.c index 028ef27d..da9c0887 100644 --- a/src/libopensc/pkcs15-pteid.c +++ b/src/libopensc/pkcs15-pteid.c @@ -35,7 +35,9 @@ * */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 9cf75e35..8fd8f533 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index 77d329bb..3e087d11 100644 --- a/src/libopensc/pkcs15-sc-hsm.c +++ b/src/libopensc/pkcs15-sc-hsm.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index 3b3366b0..df78f604 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-starcert.c b/src/libopensc/pkcs15-starcert.c index 19faefc8..96e0b8ac 100644 --- a/src/libopensc/pkcs15-starcert.c +++ b/src/libopensc/pkcs15-starcert.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index 3d758016..f4f0d193 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-tccardos.c b/src/libopensc/pkcs15-tccardos.c index 42103987..1715752d 100644 --- a/src/libopensc/pkcs15-tccardos.c +++ b/src/libopensc/pkcs15-tccardos.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c index 30762156..29712888 100644 --- a/src/libopensc/pkcs15-tcos.c +++ b/src/libopensc/pkcs15-tcos.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/pkcs15-westcos.c b/src/libopensc/pkcs15-westcos.c index ebc02cda..7974fe62 100644 --- a/src/libopensc/pkcs15-westcos.c +++ b/src/libopensc/pkcs15-westcos.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/reader-ctapi.c b/src/libopensc/reader-ctapi.c index a3d0cce1..919c3f0e 100644 --- a/src/libopensc/reader-ctapi.c +++ b/src/libopensc/reader-ctapi.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_CTAPI #include diff --git a/src/libopensc/reader-openct.c b/src/libopensc/reader-openct.c index c127306e..a276d52b 100644 --- a/src/libopensc/reader-openct.c +++ b/src/libopensc/reader-openct.c @@ -4,7 +4,9 @@ * Copyright (C) 2003 Olaf Kirch */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_OPENCT /* empty file without openct */ #include diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 06192cf3..87e47651 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -19,7 +19,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #ifdef ENABLE_PCSC /* empty file without pcsc */ #include diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 490b365b..052d6ebc 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/sec.c b/src/libopensc/sec.c index 1244e857..140c562a 100644 --- a/src/libopensc/sec.c +++ b/src/libopensc/sec.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include diff --git a/src/libopensc/sm.c b/src/libopensc/sm.c index 4705ba62..44cdfa48 100644 --- a/src/libopensc/sm.c +++ b/src/libopensc/sm.c @@ -18,7 +18,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#if HAVE_CONFIG_H #include "config.h" +#endif #include #include From de5c224201b54632a7c2a0d4bf629bca8c442c1c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 23 Apr 2015 00:09:19 +0200 Subject: [PATCH 186/306] silence some shell commands in Makefile --- doc/tools/Makefile.am | 4 ++-- etc/Makefile.am | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/tools/Makefile.am b/doc/tools/Makefile.am index aa0862ee..f4e64c79 100644 --- a/doc/tools/Makefile.am +++ b/doc/tools/Makefile.am @@ -25,8 +25,8 @@ tools.html: $(srcdir)/tools.xml $(wildcard $(srcdir)/*.1.xml) $(wildcard $(srcdi | $(XSLTPROC) --nonet --path "$(srcdir)/..:$(xslstylesheetsdir)/manpages" --xinclude -o $@ man.xsl $< %: $(srcdir)/%.1.xml - echo $< $@ - cat completion-template \ + @echo $< $@ + @cat completion-template \ | sed "s,ALLOPTS,\ $(shell sed -n 's,\s\s\s*.*,\1,pg' $< \ | sort -u | grep -- '^\-' | tr '\n' ' ')," \ diff --git a/etc/Makefile.am b/etc/Makefile.am index 59f2d29f..3816fbc3 100644 --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -15,7 +15,7 @@ force: opensc.conf: opensc.conf.in force .in: - sed \ + @sed \ -e 's|@pkgdatadir[@]|$(pkgdatadir)|g' \ -e 's|@libdir[@]|$(libdir)|g' \ -e 's|@DEFAULT_PCSC_PROVIDER[@]|$(DEFAULT_PCSC_PROVIDER)|g' \ From e456074fd98e45c0a3d69487e0f5a9d786bd9440 Mon Sep 17 00:00:00 2001 From: Shaun Schutte Date: Thu, 23 Apr 2015 16:54:11 +0200 Subject: [PATCH 187/306] Create minidriver-italian-cns These are the required registry values to get the Italian CNS card working under Windows 7 32 bit and 64 bit. --- src/minidriver/minidriver-italian-cns | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/minidriver/minidriver-italian-cns diff --git a/src/minidriver/minidriver-italian-cns b/src/minidriver/minidriver-italian-cns new file mode 100644 index 00000000..3bca8d4a --- /dev/null +++ b/src/minidriver/minidriver-italian-cns @@ -0,0 +1,33 @@ +Windows Registry Editor Version 5.00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\CPS] +"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" +"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider" +"80000001"="opensc-minidriver.dll" +"ATR"=hex:3b,ff,18,00,ff,c1,0a,31,fe,55,00,6b,05,08,c8,0c,01,11,01,43,4e,53,10,\ + 31,80,05 +"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,\ + ff,ff,ff,ff,ff + +[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\CPS-Athena] +"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" +"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider" +"80000001"="opensc-minidriver.dll" +"ATR"=hex:3b,df,18,00,81,31,fe,7d,00,6b,02,0c,01,82,01,11,01,43,4e,53,10,31,80,fc +"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff + +[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\CPS] +"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" +"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider" +"80000001"="opensc-minidriver.dll" +"ATR"=hex:3b,ff,18,00,ff,c1,0a,31,fe,55,00,6b,05,08,c8,0c,01,11,01,43,4e,53,10,\ + 31,80,05 +"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,\ + ff,ff,ff,ff,ff + +[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\CPS-Athena] +"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" +"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider" +"80000001"="opensc-minidriver.dll" +"ATR"=hex:3b,df,18,00,81,31,fe,7d,00,6b,02,0c,01,82,01,11,01,43,4e,53,10,31,80,fc +"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff From 665807d6de3f6494fe10f7f6fcf4ed5d3bd34210 Mon Sep 17 00:00:00 2001 From: Shaun Schutte Date: Fri, 24 Apr 2015 09:45:20 +0200 Subject: [PATCH 188/306] Rename minidriver-italian-cns to minidriver-italian-cns.reg --- .../{minidriver-italian-cns => minidriver-italian-cns.reg} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/minidriver/{minidriver-italian-cns => minidriver-italian-cns.reg} (100%) diff --git a/src/minidriver/minidriver-italian-cns b/src/minidriver/minidriver-italian-cns.reg similarity index 100% rename from src/minidriver/minidriver-italian-cns rename to src/minidriver/minidriver-italian-cns.reg From ee23d286547d730dc82011857b318186140b31f5 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 16 Apr 2015 19:40:22 -0500 Subject: [PATCH 189/306] EC field_length changes for non-multiple of 8 bits curves In OpenSC the EC field_length is the number of bits in the field. Most curves have a field_length which is a multiple of 8 bits but there are many that are not. The X and Y points and privateD are stored in octetstrings so there may need to be an extra byte in the octetstring. An OpenSSL BIGNUM will drop leading zero bytes, so its size can not be used to determine the field_length. fix #440 fix #433 --- src/libopensc/pkcs15-prkey.c | 12 ++++++++---- src/libopensc/pkcs15-pubkey.c | 12 +++++++++++- src/libopensc/pkcs15-sc-hsm.c | 1 + src/pkcs15init/pkcs15-isoApplet.c | 2 +- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index d96008f5..a7f2c84a 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -707,12 +707,16 @@ sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key) memcpy(dst->ecpointQ.value, buf, buflen); dst->ecpointQ.len = buflen; - /* calculate the field length */ - dst->params.field_length = (buflen - 1) / 2 * 8; + /* + * In OpenSC the field_length is in bits. Not all curves are a mutiple of 8. + * EC_POINT_point2oct handles this and returns octstrings that can handle + * these curves. Get real field_length from OpenSSL. + */ + dst->params.field_length = EC_GROUP_get_degree(grp); /* Octetstring may need leading zeros if BN is to short */ - if (dst->privateD.len < dst->params.field_length/8) { - size_t d = dst->params.field_length/8 - dst->privateD.len; + if (dst->privateD.len < (dst->params.field_length + 7) / 8) { + size_t d = (dst->params.field_length + 7) / 8 - dst->privateD.len; dst->privateD.data = realloc(dst->privateD.data, dst->privateD.len + d); if (!dst->privateD.data) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 8fd8f533..e7a26a8b 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -723,6 +723,11 @@ sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, key->ecpointQ.len = ecpoint_len; key->ecpointQ.value = ecpoint_data; + /* + * Only get here if raw point is stored in pkcs15 without curve name + * spki has the curvename, so we can get the field_length + * Following only true for curves that are multiple of 8 + */ key->params.field_length = (ecpoint_len - 1)/2 * 8; LOG_FUNC_RETURN(ctx, SC_SUCCESS); } @@ -1298,6 +1303,12 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke if (pk_alg.algorithm == SC_ALGORITHM_EC) { /* EC public key is not encapsulated into BIT STRING -- it's a BIT STRING */ + /* + * sc_pkcs15_fix_ec_parameters below will set field_length from curve. + * if no alg_id->params, assume field_length is multiple of 8 + */ + pubkey->u.ec.params.field_length = (pk.len - 1) / 2 * 8; + if (pubkey->alg_id->params) { struct sc_ec_parameters *ecp = (struct sc_ec_parameters *)pubkey->alg_id->params; @@ -1311,7 +1322,6 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke LOG_TEST_RET(ctx, r, "failed to fix EC parameters"); } - pubkey->u.ec.params.field_length = (pk.len - 1)/2 * 8; pubkey->u.ec.ecpointQ.value = malloc(pk.len); if (pubkey->u.ec.ecpointQ.value == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index 3e087d11..40411095 100644 --- a/src/libopensc/pkcs15-sc-hsm.c +++ b/src/libopensc/pkcs15-sc-hsm.c @@ -520,6 +520,7 @@ static int sc_pkcs15emu_sc_hsm_add_pubkey(sc_pkcs15_card_t *p15card, sc_pkcs15_p pubkey_info.modulus_length = pubkey.u.rsa.modulus.len << 3; r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); } else { + /* TODO fix if support of non multiple of 8 curves are added */ pubkey_info.field_length = cvc.primeOrModuluslen << 3; r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info); } diff --git a/src/pkcs15init/pkcs15-isoApplet.c b/src/pkcs15init/pkcs15-isoApplet.c index bbcc7e17..99db23a7 100644 --- a/src/pkcs15init/pkcs15-isoApplet.c +++ b/src/pkcs15init/pkcs15-isoApplet.c @@ -485,7 +485,7 @@ isoApplet_generate_key_ec(const sc_pkcs15_prkey_info_t *key_info, sc_card_t *car args.pubkey.ec.params.coFactor.len = curve->coFactor.len; /* The length of the public key point will be: * Uncompressed tag + 2 * field length in bytes. */ - args.pubkey.ec.ecPointQ.len = 1 + 2 * key_info->field_length / 8; + args.pubkey.ec.ecPointQ.len = 1 + (key_info->field_length + 7) / 8 * 2; args.pubkey.ec.ecPointQ.value = malloc(args.pubkey.ec.ecPointQ.len); if(!args.pubkey.ec.ecPointQ.value) { From 0a754b694ee8c95f51b7e1794bdf65f670b9ce74 Mon Sep 17 00:00:00 2001 From: Thomas Calderon Date: Wed, 22 Apr 2015 17:40:36 +0200 Subject: [PATCH 190/306] pkcs11-tool: pass key usage flags to created objs * Command-line parameters were introduced to specify key usage (--usage-{sign,decrypt,derive}). However, those are not used when importing external objects using C_CreateObject function. fix #445 --- src/tools/pkcs11-tool.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 0a419b86..f549c754 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -1973,6 +1973,19 @@ static int write_object(CK_SESSION_HANDLE session) FILL_ATTR(privkey_templ[n_privkey_attr], CKA_ID, opt_object_id, opt_object_id_len); n_privkey_attr++; } + if (opt_key_usage_sign != 0) { + FILL_ATTR(privkey_templ[n_privkey_attr], CKA_SIGN, &_true, sizeof(_true)); + n_privkey_attr++; + } + if (opt_key_usage_decrypt != 0) { + FILL_ATTR(privkey_templ[n_privkey_attr], CKA_DECRYPT, &_true, sizeof(_true)); + n_privkey_attr++; + } + if (opt_key_usage_derive != 0) { + FILL_ATTR(privkey_templ[n_privkey_attr], CKA_DERIVE, &_true, sizeof(_true)); + n_privkey_attr++; + } + #ifdef ENABLE_OPENSSL if (cert.subject_len != 0) { FILL_ATTR(privkey_templ[n_privkey_attr], CKA_SUBJECT, cert.subject, cert.subject_len); @@ -2052,6 +2065,19 @@ static int write_object(CK_SESSION_HANDLE session) opt_object_id, opt_object_id_len); n_pubkey_attr++; } + if (opt_key_usage_sign != 0) { + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_VERIFY, &_true, sizeof(_true)); + n_pubkey_attr++; + } + if (opt_key_usage_decrypt != 0) { + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_ENCRYPT, &_true, sizeof(_true)); + n_pubkey_attr++; + } + if (opt_key_usage_derive != 0) { + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_DERIVE, &_true, sizeof(_true)); + n_pubkey_attr++; + } + #ifdef ENABLE_OPENSSL if (cert.subject_len != 0) { FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_SUBJECT, From 0dba2d453fa50d0ff5e62b59aa9f67cbc057892e Mon Sep 17 00:00:00 2001 From: Andreas Schwier Date: Mon, 27 Apr 2015 22:31:19 +0200 Subject: [PATCH 191/306] sc-hsm: fix signed char for ARM platforms char is unsigned by default on ARM fix #450 --- src/libopensc/cardctl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index 2f467c1d..cad32219 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -943,7 +943,7 @@ typedef struct sc_cardctl_sc_hsm_init_param { size_t user_pin_len; /* Length of user PIN */ u8 user_pin_retry_counter; /* Retry counter default value */ u8 options[2]; /* Initialization options */ - char dkek_shares; /* Number of DKEK shares, 0 for card generated, -1 for none */ + signed char dkek_shares; /* Number of DKEK shares, 0 for card generated, -1 for none */ char *label; /* Token label to be set in EF.TokenInfo (2F03) */ } sc_cardctl_sc_hsm_init_param_t; From f0189e8378fb44403eb2e412e4346962298f441e Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Thu, 30 Apr 2015 13:50:28 +0200 Subject: [PATCH 192/306] pkcs11-tool: option to 'decrypt some data' --- doc/tools/pkcs11-tool.1.xml | 7 ++++ src/tools/pkcs11-tool.c | 79 ++++++++++++++++++++++++++++++++++--- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/doc/tools/pkcs11-tool.1.xml b/doc/tools/pkcs11-tool.1.xml index 23d5512e..3efcccc2 100644 --- a/doc/tools/pkcs11-tool.1.xml +++ b/doc/tools/pkcs11-tool.1.xml @@ -236,6 +236,13 @@ Sign some data. + + + , + + Decrypt some data. + + id diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index f549c754..aac68263 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -117,7 +117,8 @@ enum { OPT_NEW_PIN, OPT_LOGIN_TYPE, OPT_TEST_EC, - OPT_DERIVE + OPT_DERIVE, + OPT_DECRYPT }; static const struct option options[] = { @@ -129,6 +130,7 @@ static const struct option options[] = { { "list-objects", 0, NULL, 'O' }, { "sign", 0, NULL, 's' }, + { "decrypt", 0, NULL, OPT_DECRYPT }, { "hash", 0, NULL, 'h' }, { "derive", 0, NULL, OPT_DERIVE }, { "mechanism", 1, NULL, 'm' }, @@ -187,6 +189,7 @@ static const char *option_help[] = { "Show objects on token", "Sign some data", + "Decrypt some data", "Hash some data", "Derive a secret key using another key and some data", "Specify mechanism (use -M for a list of supported mechanisms)", @@ -334,8 +337,8 @@ static void show_object(CK_SESSION_HANDLE, CK_OBJECT_HANDLE); static void show_key(CK_SESSION_HANDLE, CK_OBJECT_HANDLE); static void show_cert(CK_SESSION_HANDLE, CK_OBJECT_HANDLE); static void show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj); -static void sign_data(CK_SLOT_ID, - CK_SESSION_HANDLE, CK_OBJECT_HANDLE); +static void sign_data(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE); +static void decrypt_data(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE); static void hash_data(CK_SLOT_ID, CK_SESSION_HANDLE); static void derive_key(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE); static int gen_keypair(CK_SESSION_HANDLE, @@ -388,6 +391,7 @@ int main(int argc, char * argv[]) int do_list_mechs = 0; int do_list_objects = 0; int do_sign = 0; + int do_decrypt = 0; int do_hash = 0; int do_derive = 0; int do_gen_keypair = 0; @@ -546,6 +550,11 @@ int main(int argc, char * argv[]) do_sign = 1; action_count++; break; + case OPT_DECRYPT: + need_session |= NEED_SESSION_RW; + do_decrypt = 1; + action_count++; + break; case 'f': opt_sig_format = optarg; break; @@ -754,7 +763,7 @@ int main(int argc, char * argv[]) if (do_list_mechs) list_mechs(opt_slot); - if (do_sign) { + if (do_sign || do_decrypt) { CK_TOKEN_INFO info; get_token_info(opt_slot, &info); @@ -811,7 +820,7 @@ int main(int argc, char * argv[]) goto end; } - if (do_sign || do_derive) { + if (do_sign || do_derive || do_decrypt) { if (!find_object(session, CKO_PRIVATE_KEY, &object, opt_object_id_len ? opt_object_id : NULL, opt_object_id_len, 0)) @@ -828,6 +837,9 @@ int main(int argc, char * argv[]) if (do_sign) sign_data(opt_slot, session, object); + if (do_decrypt) + decrypt_data(opt_slot, session, object); + if (do_hash) hash_data(opt_slot, session); @@ -1453,6 +1465,63 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, close(fd); } + +static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE key) +{ + unsigned char in_buffer[1024], out_buffer[1024]; + CK_MECHANISM mech; + CK_RV rv; + CK_ULONG in_len, out_len; + int fd, r; + + if (!opt_mechanism_used) + if (!find_mechanism(slot, CKF_DECRYPT|CKF_HW, NULL, 0, &opt_mechanism)) + util_fatal("Decrypt mechanism not supported\n"); + + printf("Using decrypt algorithm %s\n", p11_mechanism_to_name(opt_mechanism)); + memset(&mech, 0, sizeof(mech)); + mech.mechanism = opt_mechanism; + + if (opt_input == NULL) + fd = 0; + else if ((fd = open(opt_input, O_RDONLY|O_BINARY)) < 0) + util_fatal("Cannot open %s: %m", opt_input); + + r = read(fd, in_buffer, sizeof(in_buffer)); + if (r < 0) + util_fatal("Cannot read from %s: %m", opt_input); + in_len = r; + + rv = p11->C_DecryptInit(session, &mech, key); + if (rv != CKR_OK) + p11_fatal("C_DecryptInit", rv); + + out_len = sizeof(out_buffer); + rv = p11->C_Decrypt(session, in_buffer, in_len, out_buffer, &out_len); + if (rv != CKR_OK) + p11_fatal("C_Decrypt", rv); + + if (fd != 0) + close(fd); + + if (opt_output == NULL) { + fd = 1; + } + else { + fd = open(opt_output, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, S_IRUSR|S_IWUSR); + if (fd < 0) + util_fatal("failed to open %s: %m", opt_output); + } + + r = write(fd, out_buffer, out_len); + if (r < 0) + util_fatal("Failed to write to %s: %m", opt_output); + if (fd != 1) + close(fd); +} + + static void hash_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session) { unsigned char buffer[64]; From ed588d24434f5e7b2df9d0fc32f24fc7226db0ad Mon Sep 17 00:00:00 2001 From: Andreas Schwier Date: Mon, 27 Apr 2015 21:21:35 +0200 Subject: [PATCH 193/306] pkcs11: fixed broken C_Decrypt Fixed broken C_Decrypt from 643080baf9ffd404c88cb99493668eacfff3ab5e fix #449 --- src/pkcs11/mechanism.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index fc6dcecf..a49acdb6 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -593,7 +593,7 @@ done: } /* - * Initialize a signature operation + * Initialize a verify operation */ static CK_RV sc_pkcs11_verify_init(sc_pkcs11_operation_t *operation, @@ -611,10 +611,10 @@ sc_pkcs11_verify_init(sc_pkcs11_operation_t *operation, if (key->ops->can_do) { rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_SIGN); - if (rv == CKR_OK) { - /* Mechanism recognised and can be performed by pkcs#15 card */ + if ((rv == CKR_OK) || (rv == CKR_FUNCTION_NOT_SUPPORTED)) { + /* Mechanism recognized and can be performed by pkcs#15 card or algorithm references not supported */ } - else { + else { /* Mechanism cannot be performed by pkcs#15 card, or some general error. */ free(data); LOG_FUNC_RETURN(context, rv); @@ -874,7 +874,7 @@ out: /* - * Initialize a signature operation + * Initialize a decrypt operation */ static CK_RV sc_pkcs11_decrypt_init(sc_pkcs11_operation_t *operation, @@ -890,10 +890,10 @@ sc_pkcs11_decrypt_init(sc_pkcs11_operation_t *operation, if (key->ops->can_do) { rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_DECRYPT); - if (rv == CKR_OK) { - /* Mechanism recognised and can be performed by pkcs#15 card */ + if ((rv == CKR_OK) || (rv == CKR_FUNCTION_NOT_SUPPORTED)) { + /* Mechanism recognized and can be performed by pkcs#15 card or algorithm references not supported */ } - else { + else { /* Mechanism cannot be performed by pkcs#15 card, or some general error. */ free(data); LOG_FUNC_RETURN(context, rv); From 1586f240f43d134ab7225fbbf9624d445a925d0e Mon Sep 17 00:00:00 2001 From: vletoux Date: Sun, 3 May 2015 12:48:26 +0200 Subject: [PATCH 194/306] iso7816.c: fix SC_PIN_CMD_IMPLICIT_CHANGE with pinpad When a pinpad is used, the old pin is asked whatever, even if a previous authentication happenened or if the card doesn't support it. --- src/libopensc/iso7816.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 37abd177..9c8d85ef 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -999,7 +999,7 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, break; case SC_PIN_CMD_CHANGE: ins = 0x24; - if (data->pin1.len != 0 || use_pin_pad) { + if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) { if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0) return r; len += r; @@ -1023,7 +1023,7 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, break; case SC_PIN_CMD_UNBLOCK: ins = 0x2C; - if (data->pin1.len != 0 || use_pin_pad) { + if (data->pin1.len != 0 || (use_pin_pad && !( data->flags & SC_PIN_CMD_IMPLICIT_CHANGE))) { if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0) return r; len += r; From 976db5cb0400147e9108d434796d68c27f7b4c5c Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 2 May 2015 12:37:50 +0200 Subject: [PATCH 195/306] card-masktech: initial commit card-masktech.c: fix building issues on the integration platform card-masktech.c: fix linux compilation errors honour HAVE_CONFIG_H card-masktech.c: take in account Frank's remark about extended APDU in masktech_decipher remove trailing spaces --- src/libopensc/Makefile.am | 2 +- src/libopensc/Makefile.mak | 1 + src/libopensc/card-masktech.c | 481 ++++++++++++++++++++++++++++++++++ src/libopensc/cards.h | 7 +- src/libopensc/ctx.c | 1 + src/libopensc/dir.c | 3 +- 6 files changed, 492 insertions(+), 3 deletions(-) create mode 100644 src/libopensc/card-masktech.c diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 557c32ea..1d42b0d5 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -41,7 +41,7 @@ libopensc_la_SOURCES = \ card-itacns.c card-authentic.c \ card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ card-dnie.c cwa14890.c cwa-dnie.c user-interface.c \ - card-isoApplet.c \ + card-isoApplet.c card-masktech.c \ \ pkcs15-openpgp.c pkcs15-infocamere.c pkcs15-starcert.c \ pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \ diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak index 4e572f7b..a287f70f 100644 --- a/src/libopensc/Makefile.mak +++ b/src/libopensc/Makefile.mak @@ -24,6 +24,7 @@ OBJECTS = \ card-itacns.obj card-authentic.obj \ card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \ card-sc-hsm.obj card-dnie.obj user-interface.obj card-isoApplet.obj \ + card-masktech.obj \ \ pkcs15-openpgp.obj pkcs15-infocamere.obj pkcs15-starcert.obj \ pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-postecert.obj pkcs15-gemsafeGPK.obj \ diff --git a/src/libopensc/card-masktech.c b/src/libopensc/card-masktech.c new file mode 100644 index 00000000..6df80df0 --- /dev/null +++ b/src/libopensc/card-masktech.c @@ -0,0 +1,481 @@ +/* + * card-masktech.c: Support for Masktech smart cards using the MTCOS operating system. + * + * Copyright (C) 2011-2015 MaskTech GmbH Fischerstrasse 19, 87435 Kempten, Germany + * Copyright (C) 2011 Andrey Uvarov (X-Infotech) + * Copyright (C) 2015 Vincent Le Toux (My Smart Logon) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "internal.h" +#include "cardctl.h" +#include "iso7816.h" + +static struct sc_atr_table masktech_atrs[] = { + {"3B:89:80:01:4D:54:43:4F:53:70:02:02:05:3B", NULL, NULL, + SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, + {"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:02:05:41", NULL, NULL, + SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, + {NULL, NULL, NULL, 0, 0, NULL} +}; + +static struct sc_card_operations *iso_ops; +static struct sc_card_operations masktech_ops; +static struct sc_card_driver masktech_drv = { + "MaskTech Smart Card", + "MaskTech", + &masktech_ops, + masktech_atrs, 0, NULL +}; + +struct masktech_private_data { + /* save the key reference set at set_masktech_set_security_env to recover it as the signature step */ + int rsa_key_ref; + +}; + +/* function not used - remains just in case the inclusion of the application inside dir.c is denied */ +static int masktech_select_aid(struct sc_card *card) +{ + struct sc_apdu apdu; + unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE]; + int rv; + unsigned char cm[7] = {0xA0,0x00,0x00,0x00,0x03,0x00,0x00}; + unsigned char aid[15] = {0xE8,0x28,0xBD,0x08,0x0F,0xA0,0x00,0x00,0x01,0x67,0x45,0x53,0x49,0x47,0x4E}; + struct sc_path tmp_path; + + /* Select Card Manager (to deselect previously selected application) */ + card->cla = 0x00; + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C); + apdu.lc = sizeof(cm); + apdu.data = cm; + apdu.datalen = sizeof(cm); + apdu.resplen = sizeof(apdu_resp); + apdu.resp = apdu_resp; + + rv = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed"); + + memset(&tmp_path, 0, sizeof(struct sc_path)); + tmp_path.type = SC_PATH_TYPE_DF_NAME; + memcpy(tmp_path.value, aid, sizeof(aid)); + tmp_path.len = sizeof(aid); + + rv = iso_ops->select_file(card, &tmp_path, NULL); + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "rv %i\n", rv); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "select parent failed"); + + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "return %i\n", rv); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, rv); +} + + +static int masktech_match_card(sc_card_t * card) +{ + /* check if the ATR is in the known ATR */ + if (_sc_match_atr(card, masktech_atrs, &card->type) < 0) + return 0; + + /* load the smart card application */ + /* function not used - remains just in case the inclusion of the application inside dir.c is denied */ + /*if (masktech_select_aid(card)) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to select aid\n"); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD, "Failed to select aid"); + }*/ + + return 1; +} + +static int masktech_init(sc_card_t * card) +{ + unsigned long flags; + struct masktech_private_data *data; + + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_init()\n"); + + /* private data kept during the live of the driver */ + if (!(data = (struct masktech_private_data *) malloc(sizeof(*data)))) + return SC_ERROR_OUT_OF_MEMORY; + card->drv_data = data; + + /* supported RSA keys and how padding is done */ + flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE; + _sc_card_add_rsa_alg(card, 1024, flags, 0); + _sc_card_add_rsa_alg(card, 2048, flags, 0); + _sc_card_add_rsa_alg(card, 3072, flags, 0); + card->caps |= SC_CARD_CAP_APDU_EXT; + return SC_SUCCESS; +} + + +static int masktech_finish(sc_card_t *card) +{ + /* free the private data */ + if (card->drv_data) { + free(card->drv_data); + card->drv_data = NULL; + } + return 0; +} + +static int masktech_set_security_env(sc_card_t *card, + const sc_security_env_t *env, + int se_num) +{ + struct masktech_private_data *private_data; + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_set_security_env(), keyRef = 0x%0x, algo = 0x%0x\n", + *env->key_ref, env->algorithm_flags); + + private_data = (struct masktech_private_data *) card->drv_data; + if (!private_data) + return SC_ERROR_INTERNAL; + + /* save the key reference */ + if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { + if (env->key_ref_len != 1) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Invalid key reference supplied.\n"); + return SC_ERROR_NOT_SUPPORTED; + } + private_data->rsa_key_ref = env->key_ref[0]; + } + + return iso_ops->set_security_env(card, env, se_num); +} + +static int masktech_compute_signature(sc_card_t *card, + const u8 * data, + size_t datalen, + u8 * out, + size_t outlen) +{ + + struct masktech_private_data *private_data; + u8 sha256hash[32]; + static const u8 hdr_sha256[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, + 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 + }; + assert(card != NULL && data != NULL && out != NULL); + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_compute_signature()\n"); + + /* retrieve the key reference */ + private_data = (struct masktech_private_data *) card->drv_data; + if (!private_data) + return SC_ERROR_INTERNAL; + + if (private_data->rsa_key_ref == 0x88) + { + /* for this key reference, the card supports only SHA256 hash and the hash is computed using a digest info */ + /* check that it is a SHA256 with digest info*/ + if ((datalen != sizeof(hdr_sha256) + 32) || (memcmp(hdr_sha256, data, sizeof(hdr_sha256)) != 0)) + { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "It is not a SHA256 with digestinfo\n"); + return SC_ERROR_NOT_SUPPORTED; + } + /* extract the SHA-256 hash */ + memcpy(sha256hash, (u8 *)(data+(datalen-32)), 32);//only last 32 byte => sha256 + /* default ISO 7816 functions */ + return iso_ops->compute_signature(card, sha256hash, 32, out, outlen); + } + else + { + /* default ISO 7816 functions */ + return iso_ops->compute_signature(card, data, datalen, out, outlen); + } +} + +static int masktech_decipher(sc_card_t *card, + const u8 * crgram, + size_t crgram_len, + u8 * out, + size_t outlen) +{ + int r; + sc_apdu_t apdu; + u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; + u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; + + assert(card != NULL && crgram != NULL && out != NULL); + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_decipher()\n"); + + if (crgram_len > sizeof(sbuf)) SC_ERROR_INVALID_ARGUMENTS; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_4_EXT, 0x2A, 0x80, 0x86); + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + /* the card doesn't support anything else here (+1 / -1 is not working) */ + apdu.le = 65536; + + /* crgram is a const u8 while apdu.data is not a const => it cannot be used directly */ + memcpy(&sbuf, crgram, crgram_len); + apdu.data = sbuf; + apdu.lc = crgram_len; + apdu.datalen = crgram_len; + + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { + size_t len = apdu.resplen > outlen ? outlen : apdu.resplen; + + memcpy(out, apdu.resp, len); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len); + } + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); +} + +/* we built a special APDU to be compatible with pinpad readers */ +/* maybe patch opensc to strip the first pin in iso build APDU if SC_PIN_CMD_IMPLICIT_CHANGE is set */ +static int masktech_build_unblock_pin_apdu(sc_card_t *card, + sc_apdu_t *apdu, + struct sc_pin_cmd_data *data, + u8 *buf, + size_t buf_len) +{ + int r, len = 0; + int p1 = 0x02; + data->pin1.offset = 5; + + if (data->pin2.len != 0 || data->flags & SC_PIN_CMD_USE_PINPAD) { + data->pin2.offset = data->pin1.offset + buf_len; + if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, data->flags & SC_PIN_CMD_NEED_PADDING)) < 0) + return r; + len += r; + } else { + p1 |= 0x01; + } + sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, 0x2C, p1, data->pin_reference); + apdu->lc = len; + apdu->datalen = len; + apdu->data = buf; + apdu->resplen = 0; + return 0; +} + +/* we built a special APDU to be compatible with pinpad readers */ +/* maybe patch opensc to strip the first pin in iso build APDU if SC_PIN_CMD_IMPLICIT_CHANGE is set */ +static int masktech_build_change_pin_apdu(sc_card_t *card, + sc_apdu_t *apdu, + struct sc_pin_cmd_data *data, + u8 *buf, + size_t buf_len) +{ + int r, len = 0; + int p1 = 1; + data->pin1.offset = 5; + + data->pin2.offset = data->pin1.offset + len; + if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, data->flags & SC_PIN_CMD_NEED_PADDING)) < 0) + return r; + len += r; + sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, 0x24, p1, data->pin_reference); + apdu->lc = len; + apdu->datalen = len; + apdu->data = buf; + apdu->resplen = 0; + return 0; +} + +/* unblock pin cmd */ +static int masktech_pin_unblock(sc_card_t *card, + struct sc_pin_cmd_data *data, + int *tries_left) +{ + int rv = 0; + struct sc_pin_cmd_data verify_data; + struct sc_pin_cmd_data reset_data; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + sc_apdu_t reset_apdu; + + /* Build a SC_PIN_CMD_VERIFY APDU on PUK */ + memset(&verify_data, 0, sizeof(verify_data)); + verify_data.cmd = SC_PIN_CMD_VERIFY; + verify_data.pin_type = 1; + verify_data.pin_reference = 0x83; + verify_data.pin1 = data->pin1; + verify_data.flags = data->flags; + verify_data.pin1.prompt = data->pin1.prompt; + + rv = iso_ops->pin_cmd(card, &verify_data, tries_left); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - verify unblock PIN"); + + /* Build a SC_PIN_CMD_UNBLOCK APDU */ + memset(&reset_data, 0, sizeof(reset_data)); + reset_data.cmd = SC_PIN_CMD_UNBLOCK; + reset_data.pin_type = 1; + reset_data.pin_reference = 0x91; + /* pin1 is set to null on purpose and flag set to implicit change + => if there is a pinpad reader, do not ask for pin1 */ + reset_data.pin2 = data->pin2; + reset_data.flags = data->flags | SC_PIN_CMD_IMPLICIT_CHANGE; + reset_data.pin2.prompt = data->pin2.prompt; + + /* the APDU is overwritten to avoid requesting the UNBLOCK pin if a PIN PAD is used */ + masktech_build_unblock_pin_apdu(card, &reset_apdu, &reset_data, sbuf, sizeof(sbuf)); + reset_data.apdu = &reset_apdu; + + rv = iso_ops->pin_cmd(card, &reset_data, tries_left); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - reset unblock PIN"); + + return 0; +} + +static int masktech_pin_change(sc_card_t *card, + struct sc_pin_cmd_data *data, + int *tries_left) +{ + int rv = 0; + struct sc_pin_cmd_data verify_data; + struct sc_pin_cmd_data change_data; + u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; + sc_apdu_t change_apdu; + + /* Build a SC_PIN_CMD_VERIFY APDU */ + memset(&verify_data, 0, sizeof(verify_data)); + verify_data.cmd = SC_PIN_CMD_VERIFY; + verify_data.pin_type = 1; + verify_data.pin_reference = data->pin_reference; + verify_data.pin1 = data->pin1; + verify_data.flags = data->flags; + verify_data.pin1.prompt = data->pin1.prompt; + + rv = iso_ops->pin_cmd(card, &verify_data, tries_left); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - verify change PIN"); + + /* Build a SC_PIN_CMD_CHANGE APDU */ + memset(&change_data, 0, sizeof(change_data)); + change_data.cmd = SC_PIN_CMD_CHANGE; + change_data.pin_type = 1; + change_data.pin_reference = data->pin_reference; + /* pin1 is set to null on purpose and flag set to implicit change + => if there is a pinpad reader, do not ask for pin1 */ + change_data.pin2 = data->pin2; + change_data.flags = data->flags | SC_PIN_CMD_IMPLICIT_CHANGE; + change_data.pin2.prompt = data->pin2.prompt; + + /* the APDU is overwritten to avoid requesting the INITIAL pin if a PIN PAD is used */ + masktech_build_change_pin_apdu(card, &change_apdu, &change_data, sbuf, sizeof(sbuf)); + change_data.apdu = &change_apdu; + + rv = iso_ops->pin_cmd(card, &change_data, tries_left); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - chnage PIN"); + + return 0; +} + +static int masktech_pin_cmd(sc_card_t *card, + struct sc_pin_cmd_data *data, + int *tries_left) +{ + int rv; + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + switch(data->cmd) + { + case SC_PIN_CMD_UNBLOCK: + rv = masktech_pin_unblock(card, data, tries_left); + break; + case SC_PIN_CMD_CHANGE: + rv = masktech_pin_change(card, data, tries_left); + break; + default: + rv = iso_ops->pin_cmd(card, data, tries_left); + break; + } + return rv; + + +} + +static int masktech_get_serialnr(sc_card_t * card, sc_serial_number_t * serial) +{ + struct sc_apdu apdu; + unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE-2]; + int rv; + + if (!serial) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS); + + /* Get smart card serial number */ + card->cla = 0x80; + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x08, 0x00, 0x00); + apdu.resplen = sizeof(apdu_resp); + apdu.resp = apdu_resp; + + rv = sc_transmit_apdu(card, &apdu); + card->cla = 0x00; + + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed"); + + if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) + return SC_ERROR_INTERNAL; + + if (SC_MAX_SERIALNR < apdu.resplen) + { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); + } + /* cache serial number */ + card->serialnr.len = apdu.resplen; + memcpy(card->serialnr.value, apdu.resp, card->serialnr.len); + + /* copy and return serial number */ + if (serial) + memcpy(serial, &card->serialnr, sizeof(*serial)); + + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); +} + + +static int masktech_card_ctl(sc_card_t * card, unsigned long cmd, void *ptr) +{ + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_card_ctl()\n"); + switch (cmd) { + case SC_CARDCTL_GET_SERIALNR: + return masktech_get_serialnr(card, (sc_serial_number_t *) ptr); + default: + return SC_ERROR_NOT_SUPPORTED; + } +} + +static struct sc_card_driver *sc_get_driver(void) +{ + + if (iso_ops == NULL) + iso_ops = sc_get_iso7816_driver()->ops; + + masktech_ops = *iso_ops; + + masktech_ops.match_card = masktech_match_card; + masktech_ops.init = masktech_init; + masktech_ops.finish = masktech_finish; + masktech_ops.set_security_env = masktech_set_security_env; + masktech_ops.compute_signature = masktech_compute_signature; + masktech_ops.decipher = masktech_decipher; + masktech_ops.pin_cmd = masktech_pin_cmd; + masktech_ops.card_ctl = masktech_card_ctl; + return &masktech_drv; +} + +struct sc_card_driver *sc_get_masktech_driver(void) +{ + return sc_get_driver(); +} diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index fe629381..8c5c57e4 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -204,7 +204,11 @@ enum { /* JavaCards with isoApplet */ SC_CARD_TYPE_ISO_APPLET_BASE = 28000, - SC_CARD_TYPE_ISO_APPLET_GENERIC + SC_CARD_TYPE_ISO_APPLET_GENERIC, + + /* Masktech cards */ + SC_CARD_TYPE_MASKTECH_BASE = 29000, + SC_CARD_TYPE_MASKTECH_GENERIC }; extern sc_card_driver_t *sc_get_default_driver(void); @@ -242,6 +246,7 @@ extern sc_card_driver_t *sc_get_iasecc_driver(void); extern sc_card_driver_t *sc_get_epass2003_driver(void); extern sc_card_driver_t *sc_get_dnie_driver(void); extern sc_card_driver_t *sc_get_isoApplet_driver(void); +extern sc_card_driver_t *sc_get_masktech_driver(void); #ifdef __cplusplus } diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index f6f7bde7..46700084 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -101,6 +101,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = { #ifdef ENABLE_OPENSSL { "dnie", (void *(*)(void)) sc_get_dnie_driver }, #endif + { "masktech", (void *(*)(void)) sc_get_masktech_driver }, /* Here should be placed drivers that need some APDU transactions to * recognise its cards. */ diff --git a/src/libopensc/dir.c b/src/libopensc/dir.c index 189fbee3..5d448516 100644 --- a/src/libopensc/dir.c +++ b/src/libopensc/dir.c @@ -38,7 +38,8 @@ struct app_entry { static const struct app_entry apps[] = { { (const u8 *) "\xA0\x00\x00\x00\x63PKCS-15", 12, "PKCS #15" }, { (const u8 *) "\xA0\x00\x00\x01\x77PKCS-15", 12, "Belgian eID" }, - { (const u8 *) "\x44\x46\x20\x69\x73\x73\x75\x65\x72", 9, "Portugal eID" } + { (const u8 *) "\x44\x46\x20\x69\x73\x73\x75\x65\x72", 9, "Portugal eID" }, + { (const u8 *) "\xE8\x28\xBD\x08\x0F\xA0\x00\x00\x01\x67\x45\x53\x49\x47\x4E", 15, "ESIGN"} }; static const struct sc_asn1_entry c_asn1_dirrecord[] = { From 689ece205ae04ac65a9941b7568ab84b36f94475 Mon Sep 17 00:00:00 2001 From: vletoux Date: Thu, 7 May 2015 15:39:22 +0200 Subject: [PATCH 196/306] card-masktech.c: code improvements fixes #457 --- src/libopensc/card-masktech.c | 114 +--------------------------------- 1 file changed, 2 insertions(+), 112 deletions(-) diff --git a/src/libopensc/card-masktech.c b/src/libopensc/card-masktech.c index 6df80df0..ae620f1a 100644 --- a/src/libopensc/card-masktech.c +++ b/src/libopensc/card-masktech.c @@ -54,55 +54,12 @@ struct masktech_private_data { }; -/* function not used - remains just in case the inclusion of the application inside dir.c is denied */ -static int masktech_select_aid(struct sc_card *card) -{ - struct sc_apdu apdu; - unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE]; - int rv; - unsigned char cm[7] = {0xA0,0x00,0x00,0x00,0x03,0x00,0x00}; - unsigned char aid[15] = {0xE8,0x28,0xBD,0x08,0x0F,0xA0,0x00,0x00,0x01,0x67,0x45,0x53,0x49,0x47,0x4E}; - struct sc_path tmp_path; - - /* Select Card Manager (to deselect previously selected application) */ - card->cla = 0x00; - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C); - apdu.lc = sizeof(cm); - apdu.data = cm; - apdu.datalen = sizeof(cm); - apdu.resplen = sizeof(apdu_resp); - apdu.resp = apdu_resp; - - rv = sc_transmit_apdu(card, &apdu); - SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed"); - - memset(&tmp_path, 0, sizeof(struct sc_path)); - tmp_path.type = SC_PATH_TYPE_DF_NAME; - memcpy(tmp_path.value, aid, sizeof(aid)); - tmp_path.len = sizeof(aid); - - rv = iso_ops->select_file(card, &tmp_path, NULL); - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "rv %i\n", rv); - SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "select parent failed"); - - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "return %i\n", rv); - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, rv); -} - - static int masktech_match_card(sc_card_t * card) { /* check if the ATR is in the known ATR */ if (_sc_match_atr(card, masktech_atrs, &card->type) < 0) return 0; - /* load the smart card application */ - /* function not used - remains just in case the inclusion of the application inside dir.c is denied */ - /*if (masktech_select_aid(card)) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to select aid\n"); - SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD, "Failed to select aid"); - }*/ - return 1; } @@ -212,13 +169,12 @@ static int masktech_decipher(sc_card_t *card, { int r; sc_apdu_t apdu; - u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; assert(card != NULL && crgram != NULL && out != NULL); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_decipher()\n"); - if (crgram_len > sizeof(sbuf)) SC_ERROR_INVALID_ARGUMENTS; + if (crgram_len > SC_MAX_EXT_APDU_BUFFER_SIZE) SC_ERROR_INVALID_ARGUMENTS; sc_format_apdu(card, &apdu, SC_APDU_CASE_4_EXT, 0x2A, 0x80, 0x86); apdu.resp = rbuf; @@ -226,9 +182,7 @@ static int masktech_decipher(sc_card_t *card, /* the card doesn't support anything else here (+1 / -1 is not working) */ apdu.le = 65536; - /* crgram is a const u8 while apdu.data is not a const => it cannot be used directly */ - memcpy(&sbuf, crgram, crgram_len); - apdu.data = sbuf; + apdu.data = crgram; apdu.lc = crgram_len; apdu.datalen = crgram_len; @@ -243,58 +197,6 @@ static int masktech_decipher(sc_card_t *card, SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); } -/* we built a special APDU to be compatible with pinpad readers */ -/* maybe patch opensc to strip the first pin in iso build APDU if SC_PIN_CMD_IMPLICIT_CHANGE is set */ -static int masktech_build_unblock_pin_apdu(sc_card_t *card, - sc_apdu_t *apdu, - struct sc_pin_cmd_data *data, - u8 *buf, - size_t buf_len) -{ - int r, len = 0; - int p1 = 0x02; - data->pin1.offset = 5; - - if (data->pin2.len != 0 || data->flags & SC_PIN_CMD_USE_PINPAD) { - data->pin2.offset = data->pin1.offset + buf_len; - if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, data->flags & SC_PIN_CMD_NEED_PADDING)) < 0) - return r; - len += r; - } else { - p1 |= 0x01; - } - sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, 0x2C, p1, data->pin_reference); - apdu->lc = len; - apdu->datalen = len; - apdu->data = buf; - apdu->resplen = 0; - return 0; -} - -/* we built a special APDU to be compatible with pinpad readers */ -/* maybe patch opensc to strip the first pin in iso build APDU if SC_PIN_CMD_IMPLICIT_CHANGE is set */ -static int masktech_build_change_pin_apdu(sc_card_t *card, - sc_apdu_t *apdu, - struct sc_pin_cmd_data *data, - u8 *buf, - size_t buf_len) -{ - int r, len = 0; - int p1 = 1; - data->pin1.offset = 5; - - data->pin2.offset = data->pin1.offset + len; - if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, data->flags & SC_PIN_CMD_NEED_PADDING)) < 0) - return r; - len += r; - sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, 0x24, p1, data->pin_reference); - apdu->lc = len; - apdu->datalen = len; - apdu->data = buf; - apdu->resplen = 0; - return 0; -} - /* unblock pin cmd */ static int masktech_pin_unblock(sc_card_t *card, struct sc_pin_cmd_data *data, @@ -303,8 +205,6 @@ static int masktech_pin_unblock(sc_card_t *card, int rv = 0; struct sc_pin_cmd_data verify_data; struct sc_pin_cmd_data reset_data; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; - sc_apdu_t reset_apdu; /* Build a SC_PIN_CMD_VERIFY APDU on PUK */ memset(&verify_data, 0, sizeof(verify_data)); @@ -329,10 +229,6 @@ static int masktech_pin_unblock(sc_card_t *card, reset_data.flags = data->flags | SC_PIN_CMD_IMPLICIT_CHANGE; reset_data.pin2.prompt = data->pin2.prompt; - /* the APDU is overwritten to avoid requesting the UNBLOCK pin if a PIN PAD is used */ - masktech_build_unblock_pin_apdu(card, &reset_apdu, &reset_data, sbuf, sizeof(sbuf)); - reset_data.apdu = &reset_apdu; - rv = iso_ops->pin_cmd(card, &reset_data, tries_left); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - reset unblock PIN"); @@ -346,8 +242,6 @@ static int masktech_pin_change(sc_card_t *card, int rv = 0; struct sc_pin_cmd_data verify_data; struct sc_pin_cmd_data change_data; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; - sc_apdu_t change_apdu; /* Build a SC_PIN_CMD_VERIFY APDU */ memset(&verify_data, 0, sizeof(verify_data)); @@ -372,10 +266,6 @@ static int masktech_pin_change(sc_card_t *card, change_data.flags = data->flags | SC_PIN_CMD_IMPLICIT_CHANGE; change_data.pin2.prompt = data->pin2.prompt; - /* the APDU is overwritten to avoid requesting the INITIAL pin if a PIN PAD is used */ - masktech_build_change_pin_apdu(card, &change_apdu, &change_data, sbuf, sizeof(sbuf)); - change_data.apdu = &change_apdu; - rv = iso_ops->pin_cmd(card, &change_data, tries_left); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "APDU transmit failed - chnage PIN"); From 6523f3fcb9fe78650597be2710e69818e0c92b13 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 24 Apr 2015 18:13:34 +0200 Subject: [PATCH 197/306] added LOG_TEST_GOTO_ERR and SC_TEST_GOTO_ERR Don't forget to set the error label! --- src/libopensc/log.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libopensc/log.h b/src/libopensc/log.h index ccacefd5..e1e8c698 100644 --- a/src/libopensc/log.h +++ b/src/libopensc/log.h @@ -89,6 +89,16 @@ char * sc_dump_oid(const struct sc_object_id *oid); } while(0) #define LOG_TEST_RET(ctx, r, text) SC_TEST_RET((ctx), SC_LOG_DEBUG_NORMAL, (r), (text)) +#define SC_TEST_GOTO_ERR(ctx, level, r, text) do { \ + int _ret = (r); \ + if (_ret < 0) { \ + sc_do_log(ctx, level, __FILE__, __LINE__, __FUNCTION__, \ + "%s: %d (%s)\n", (text), _ret, sc_strerror(_ret)); \ + goto err; \ + } \ +} while(0) +#define LOG_TEST_GOTO_ERR(ctx, r, text) SC_TEST_GOTO_ERR((ctx), SC_LOG_DEBUG_NORMAL, (r), (text)) + #ifdef __cplusplus } #endif From 1f69a0d6879d969aaa88af0efba09810d3208567 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 24 Apr 2015 18:24:42 +0200 Subject: [PATCH 198/306] fixed indenting --- src/libopensc/card-authentic.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libopensc/card-authentic.c b/src/libopensc/card-authentic.c index 87065849..8af5eda5 100644 --- a/src/libopensc/card-authentic.c +++ b/src/libopensc/card-authentic.c @@ -2264,22 +2264,22 @@ authentic_sm_get_wrapped_apdu(struct sc_card *card, struct sc_apdu *plain, struc LOG_FUNC_CALLED(ctx); - if (!plain || !sm_apdu) + if (!plain || !sm_apdu) LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); sc_log(ctx, "called; CLA:%X, INS:%X, P1:%X, P2:%X, data(%i) %p", plain->cla, plain->ins, plain->p1, plain->p2, plain->datalen, plain->data); - *sm_apdu = NULL; + *sm_apdu = NULL; if ((plain->cla & 0x04) - || (plain->cla==0x00 && plain->ins==0x22) - || (plain->cla==0x00 && plain->ins==0x2A) - || (plain->cla==0x00 && plain->ins==0x84) - || (plain->cla==0x00 && plain->ins==0x88) - || (plain->cla==0x00 && plain->ins==0xA4) - || (plain->cla==0x00 && plain->ins==0xC0) - || (plain->cla==0x00 && plain->ins==0xCA) - || (plain->cla==0x80 && plain->ins==0x50) - ) { + || (plain->cla==0x00 && plain->ins==0x22) + || (plain->cla==0x00 && plain->ins==0x2A) + || (plain->cla==0x00 && plain->ins==0x84) + || (plain->cla==0x00 && plain->ins==0x88) + || (plain->cla==0x00 && plain->ins==0xA4) + || (plain->cla==0x00 && plain->ins==0xC0) + || (plain->cla==0x00 && plain->ins==0xCA) + || (plain->cla==0x80 && plain->ins==0x50) + ) { sc_log(ctx, "SM wrap is not applied for this APDU"); LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_APPLIED); } @@ -2290,19 +2290,19 @@ authentic_sm_get_wrapped_apdu(struct sc_card *card, struct sc_apdu *plain, struc if (!card->sm_ctx.module.ops.get_apdus) LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); - apdu = calloc(1, sizeof(struct sc_apdu)); - if (!apdu) + apdu = calloc(1, sizeof(struct sc_apdu)); + if (!apdu) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); memcpy((void *)apdu, (void *)plain, sizeof(struct sc_apdu)); - apdu->data = calloc (1, plain->datalen + 24); - if (!apdu->data) + apdu->data = calloc (1, plain->datalen + 24); + if (!apdu->data) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); if (plain->data && plain->datalen) memcpy((unsigned char *) apdu->data, plain->data, plain->datalen); - apdu->resp = calloc (1, plain->resplen + 32); - if (!apdu->resp) + apdu->resp = calloc (1, plain->resplen + 32); + if (!apdu->resp) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); card->sm_ctx.info.cmd = SM_CMD_APDU_TRANSMIT; From c7afbb4ca2bdeec80e5c60008bbf800d6916d86c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:27 +0200 Subject: [PATCH 199/306] pkcs15-algo: fixed resource leak --- src/libopensc/pkcs15-algo.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index 0465ccda..8fa1ca7b 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -281,20 +281,22 @@ asn1_decode_ec_params(sc_context_t *ctx, void **paramp, if (buflen == 0 || buf == NULL) return 0; - ecp = calloc(sizeof(struct sc_ec_parameters), 1); - if (ecp == NULL) - return SC_ERROR_OUT_OF_MEMORY; - r = sc_asn1_decode_choice(ctx, asn1_ec_params, buf, buflen, NULL, NULL); /* r = index in asn1_ec_params */ sc_debug(ctx, SC_LOG_DEBUG_ASN1, "asn1_decode_ec_params r=%d", r); if (r < 0) return r; + ecp = calloc(sizeof(struct sc_ec_parameters), 1); + if (ecp == NULL) + return SC_ERROR_OUT_OF_MEMORY; + if (r <= 1) { ecp->der.value = malloc(buflen); - if (ecp->der.value == NULL) + if (ecp->der.value == NULL) { + free(ecp); return SC_ERROR_OUT_OF_MEMORY; + } ecp->der.len = buflen; memcpy(ecp->der.value, buf, buflen); } @@ -304,7 +306,7 @@ asn1_decode_ec_params(sc_context_t *ctx, void **paramp, ecp->type = r; /* but 0 = ecparams if any, 1=named curve */ *paramp = ecp; - return 0; + return SC_SUCCESS; }; static int From 9263da49aaa33b3bc1d26e396a392eb9ca06400b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:27 +0200 Subject: [PATCH 200/306] pkcs15: fixed resource leak --- src/libopensc/pkcs15.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 3852abc8..ba9d6125 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -911,14 +911,19 @@ sc_dup_app_info(const struct sc_app_info *info) if (info->label) { out->label = strdup(info->label); - if (!out->label) + if (!out->label) { + free(out); return NULL; + } } else out->label = NULL; out->ddo.value = malloc(info->ddo.len); - if (!out->ddo.value) + if (!out->ddo.value) { + free(out->label); + free(out); return NULL; + } memcpy(out->ddo.value, info->ddo.value, info->ddo.len); return out; From 3a6c4a0e1d2a40b1746b5cd9f4212347a9dc364d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:27 +0200 Subject: [PATCH 201/306] pkcs15-cache: fixed resource leak --- src/libopensc/pkcs15-cache.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c index 74d56431..66f5fb76 100644 --- a/src/libopensc/pkcs15-cache.c +++ b/src/libopensc/pkcs15-cache.c @@ -115,13 +115,16 @@ int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, return SC_ERROR_FILE_NOT_FOUND; } if (offset) { - if (0 != fseek(f, (long)offset, SEEK_SET)) + if (0 != fseek(f, (long)offset, SEEK_SET)) { + fclose(f); + free(data); return SC_ERROR_FILE_NOT_FOUND; + } } if (data) *buf = data; got = fread(*buf, 1, count, f); - fclose(f); + fclose(f); if (got != count) { if (data) free(data); From 18e962942baddb943ae53c91b4ab061580e4636e Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Thu, 7 May 2015 18:52:57 +0200 Subject: [PATCH 202/306] pkcs15-data: fix memory leakage --- src/libopensc/pkcs15-data.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-data.c b/src/libopensc/pkcs15-data.c index 1e0de8f7..800cd60d 100644 --- a/src/libopensc/pkcs15-data.c +++ b/src/libopensc/pkcs15-data.c @@ -62,9 +62,14 @@ sc_pkcs15_read_data_object(struct sc_pkcs15_card *p15card, } sc_der_copy(&der, &info->data); + if (!der.value) + LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate memory for der value"); + data_object = calloc(sizeof(struct sc_pkcs15_data), 1); - if (!data_object || !der.value) + if (!data_object) { + free(der.value); LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate memory for data object"); + } data_object->data = der.value; data_object->data_len = der.len; From 841d89dda685c1698a0011a7b3c50d29527ade74 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:28 +0200 Subject: [PATCH 203/306] pkcs15-pubkey: fixed resource leak --- src/libopensc/pkcs15-pubkey.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index e7a26a8b..294c3125 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -829,8 +829,10 @@ sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubk LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); ec_params->type = 1; ec_params->der.value = calloc(pubkey->u.ec.params.der.len, 1); - if (!ec_params->der.value) + if (!ec_params->der.value) { + free(ec_params); LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + } memcpy(ec_params->der.value, pubkey->u.ec.params.der.value, pubkey->u.ec.params.der.len); ec_params->der.len = pubkey->u.ec.params.der.len; pubkey->alg_id->params = ec_params; @@ -931,18 +933,18 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_obj if (info->direct.spki.value && info->direct.spki.len) { sc_log(ctx, "Using direct SPKI value, tag 0x%X", *(info->direct.spki.value)); r = sc_pkcs15_pubkey_from_spki_sequence(ctx, info->direct.spki.value, info->direct.spki.len, &pubkey); - LOG_TEST_RET(ctx, r, "Failed to decode 'SPKI' direct value"); + LOG_TEST_GOTO_ERR(ctx, r, "Failed to decode 'SPKI' direct value"); } else if (info->direct.raw.value && info->direct.raw.len) { sc_log(ctx, "Using direct RAW value"); r = sc_pkcs15_decode_pubkey(ctx, pubkey, info->direct.raw.value, info->direct.raw.len); - LOG_TEST_RET(ctx, r, "Failed to decode 'RAW' direct value"); + LOG_TEST_GOTO_ERR(ctx, r, "Failed to decode 'RAW' direct value"); sc_log(ctx, "TODO: for EC keys 'raw' data needs to be completed with referenced algorithm from TokenInfo"); } else if (obj->content.value && obj->content.len) { sc_log(ctx, "Using object content"); r = sc_pkcs15_decode_pubkey(ctx, pubkey, obj->content.value, obj->content.len); - LOG_TEST_RET(ctx, r, "Failed to decode object content value"); + LOG_TEST_GOTO_ERR(ctx, r, "Failed to decode object content value"); sc_log(ctx, "TODO: for EC keys 'raw' data needs to be completed with referenced algorithm from TokenInfo"); } else if (p15card->card->ops->read_public_key) { @@ -950,28 +952,34 @@ sc_pkcs15_read_pubkey(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_obj r = p15card->card->ops->read_public_key(p15card->card, algorithm, (struct sc_path *)&info->path, info->key_reference, info->modulus_length, &data, &len); - LOG_TEST_RET(ctx, r, "Card specific 'read-public' procedure failed."); + LOG_TEST_GOTO_ERR(ctx, r, "Card specific 'read-public' procedure failed."); r = sc_pkcs15_decode_pubkey(ctx, pubkey, data, len); - LOG_TEST_RET(ctx, r, "Decode public key error"); + LOG_TEST_GOTO_ERR(ctx, r, "Decode public key error"); } else if (info->path.len) { sc_log(ctx, "Read from EF and decode"); r = sc_pkcs15_read_file(p15card, &info->path, &data, &len); - LOG_TEST_RET(ctx, r, "Failed to read public key file."); + LOG_TEST_GOTO_ERR(ctx, r, "Failed to read public key file."); if (algorithm == SC_ALGORITHM_EC && *data == (SC_ASN1_TAG_SEQUENCE | SC_ASN1_TAG_CONSTRUCTED)) r = sc_pkcs15_pubkey_from_spki_sequence(ctx, data, len, &pubkey); else r = sc_pkcs15_decode_pubkey(ctx, pubkey, data, len); - LOG_TEST_RET(ctx, r, "Decode public key error"); + LOG_TEST_GOTO_ERR(ctx, r, "Decode public key error"); } else { - LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "No way to get public key"); + r = SC_ERROR_NOT_IMPLEMENTED; + LOG_TEST_GOTO_ERR(ctx, r, "No way to get public key"); } - *out = pubkey; - LOG_FUNC_RETURN(ctx, SC_SUCCESS); +err: + if (r) + sc_pkcs15_free_pubkey(pubkey); + else + *out = pubkey; + + LOG_FUNC_RETURN(ctx, r); } @@ -1033,7 +1041,7 @@ sc_pkcs15_pubkey_from_prvkey(struct sc_context *ctx, struct sc_pkcs15_prkey *prv break; default: sc_log(ctx, "Unsupported private key algorithm"); - return SC_ERROR_NOT_SUPPORTED; + rv = SC_ERROR_NOT_SUPPORTED; } if (rv) @@ -1281,6 +1289,7 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke pubkey = calloc(1, sizeof(sc_pkcs15_pubkey_t)); if (pubkey == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + *outpubkey = pubkey; sc_copy_asn1_entry(c_asn1_pkinfo, asn1_pkinfo); @@ -1339,7 +1348,6 @@ sc_pkcs15_pubkey_from_spki_fields(struct sc_context *ctx, struct sc_pkcs15_pubke if (tmp_buf) free(tmp_buf); - *outpubkey = pubkey; LOG_FUNC_RETURN(ctx, SC_SUCCESS); } From 3cfb44d70464ad126e5a098a283a8c9c32135594 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:28 +0200 Subject: [PATCH 204/306] pkcs15-syn: fixed resource leak --- src/libopensc/pkcs15-syn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index f4f0d193..fea39ac8 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -272,6 +272,7 @@ static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf) if (3 != sscanf(get_version(), "%u.%u.%u", &major, &minor, &fix)) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "unable to get modules version number\n"); + sc_dlclose(handle); return SC_ERROR_INTERNAL; } } From e215b7b4fb5d51d72dc44bb7ac9dbc6fb5348426 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:28 +0200 Subject: [PATCH 205/306] sm-common: fixed resource leak --- src/libsm/sm-common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libsm/sm-common.c b/src/libsm/sm-common.c index cb500b4e..87d5907f 100644 --- a/src/libsm/sm-common.c +++ b/src/libsm/sm-common.c @@ -332,8 +332,10 @@ sm_encrypt_des_cbc3(struct sc_context *ctx, unsigned char *key, *out_len = data_len; *out = malloc(data_len + 8); - if (*out == NULL) + if (*out == NULL) { + free(data); LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "SM encrypt_des_cbc3: failure"); + } memcpy(&kk, key, 8); memcpy(&k2, key + 8, 8); From 4af4308d19ebcfccf757202e3bd0fc6eed49aefe Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:28 +0200 Subject: [PATCH 206/306] authentic: fixed resource leak pkcs15-authentic: fixed resource leak card-authentic: fixed resource leak --- src/libopensc/card-authentic.c | 8 +++++++- src/pkcs15init/pkcs15-authentic.c | 14 ++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/libopensc/card-authentic.c b/src/libopensc/card-authentic.c index 8af5eda5..1454767b 100644 --- a/src/libopensc/card-authentic.c +++ b/src/libopensc/card-authentic.c @@ -2302,13 +2302,19 @@ authentic_sm_get_wrapped_apdu(struct sc_card *card, struct sc_apdu *plain, struc memcpy((unsigned char *) apdu->data, plain->data, plain->datalen); apdu->resp = calloc (1, plain->resplen + 32); - if (!apdu->resp) + if (!apdu->resp) { + free(apdu); LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + } card->sm_ctx.info.cmd = SM_CMD_APDU_TRANSMIT; card->sm_ctx.info.cmd_data = (void *)apdu; rv = card->sm_ctx.module.ops.get_apdus(ctx, &card->sm_ctx.info, NULL, 0, NULL); + if (rv < 0) { + free(apdu->resp); + free(apdu); + } LOG_TEST_RET(ctx, rv, "SM: GET_APDUS failed"); *sm_apdu = apdu; diff --git a/src/pkcs15init/pkcs15-authentic.c b/src/pkcs15init/pkcs15-authentic.c index 269379ac..1f41747f 100644 --- a/src/pkcs15init/pkcs15-authentic.c +++ b/src/pkcs15init/pkcs15-authentic.c @@ -352,6 +352,7 @@ authentic_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card, sdo = calloc(1, sizeof(struct sc_authentic_sdo)); if (!sdo) LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate 'sc_authentic_sdo'"); + *out = sdo; sdo->magic = AUTHENTIC_SDO_MAGIC; sdo->docp.id = key_info->key_reference & ~AUTHENTIC_OBJECT_REF_FLAG_LOCAL; @@ -359,13 +360,11 @@ authentic_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card, rv = authentic_docp_set_acls(card, file, authentic_v3_rsa_ac_ops, sizeof(authentic_v3_rsa_ac_ops)/sizeof(authentic_v3_rsa_ac_ops[0]), &sdo->docp); - LOG_TEST_RET(ctx, rv, "Cannot set key ACLs from file"); - sc_file_free(file); + LOG_TEST_RET(ctx, rv, "Cannot set key ACLs from file"); sc_log(ctx, "sdo(mech:%X,id:%X,acls:%s)", sdo->docp.mech, sdo->docp.id, sc_dump_hex(sdo->docp.acl_data, sdo->docp.acl_data_len)); - *out = sdo; LOG_FUNC_RETURN(ctx, SC_SUCCESS); } @@ -719,12 +718,12 @@ authentic_pkcs15_delete_rsa_sdo (struct sc_profile *profile, struct sc_pkcs15_ca sc_log(ctx, "delete SDO RSA key (ref:%i,size:%i)", key_info->key_reference, key_info->modulus_length); rv = authentic_pkcs15_new_file(profile, p15card->card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file); - LOG_TEST_RET(ctx, rv, "PRKEY_RSA instantiation file error"); + LOG_TEST_GOTO_ERR(ctx, rv, "PRKEY_RSA instantiation file error"); p15card->card->caps &= ~SC_CARD_CAP_USE_FCI_AC; rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_DELETE); p15card->card->caps = caps; - LOG_TEST_RET(ctx, rv, "'DELETE' authentication failed for parent RSA key"); + LOG_TEST_GOTO_ERR(ctx, rv, "'DELETE' authentication failed for parent RSA key"); sdo.magic = AUTHENTIC_SDO_MAGIC; sdo.docp.id = key_info->key_reference & ~AUTHENTIC_OBJECT_REF_FLAG_LOCAL; @@ -733,8 +732,11 @@ authentic_pkcs15_delete_rsa_sdo (struct sc_profile *profile, struct sc_pkcs15_ca rv = sc_card_ctl(p15card->card, SC_CARDCTL_AUTHENTIC_SDO_DELETE, &sdo); if (rv == SC_ERROR_DATA_OBJECT_NOT_FOUND) rv = SC_SUCCESS; - LOG_TEST_RET(ctx, rv, "SC_CARDCTL_AUTHENTIC_SDO_DELETE failed for private key"); + LOG_TEST_GOTO_ERR(ctx, rv, "SC_CARDCTL_AUTHENTIC_SDO_DELETE failed for private key"); +err: + if (file) + sc_file_free(file); LOG_FUNC_RETURN(ctx, rv); } From d4fd135e2040670b35c79c9fbe5c641d31c9bd00 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:28 +0200 Subject: [PATCH 207/306] pkcs15-cflex: fixed resource leak --- src/pkcs15init/pkcs15-cflex.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkcs15init/pkcs15-cflex.c b/src/pkcs15init/pkcs15-cflex.c index 30cb3d49..1b85b880 100644 --- a/src/pkcs15init/pkcs15-cflex.c +++ b/src/pkcs15init/pkcs15-cflex.c @@ -224,7 +224,7 @@ cflex_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df struct sc_pkcs15_pin_attributes *pin_attrs = &auth_info->attrs.pin; sc_file_t *dummies[2]; int ndummies, pin_type, puk_type, r; - sc_file_t *file; + sc_file_t *file = NULL; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); @@ -250,6 +250,7 @@ cflex_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND, "profile does not define pin file ACLs"); ndummies = cflex_create_dummy_chvs(profile, p15card, file, SC_AC_OP_CREATE, dummies); + sc_file_free(file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, ndummies, "Unable to create dummy CHV file"); r = cflex_create_pin_file(profile, p15card, &df->path, pin_attrs->reference, From 68becc8fc491cc27a7eb3f8cd8e5291308457f7c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:28 +0200 Subject: [PATCH 208/306] pkcs15-gpk: fixed resource leak --- src/pkcs15init/pkcs15-gpk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkcs15init/pkcs15-gpk.c b/src/pkcs15init/pkcs15-gpk.c index e6502d96..c6cb63d9 100644 --- a/src/pkcs15init/pkcs15-gpk.c +++ b/src/pkcs15init/pkcs15-gpk.c @@ -717,7 +717,8 @@ gpk_pkfile_init_public(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file if (r >= 0) { if (r != 7 || buffer[0] != 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "first record of public key file is not Lsys0"); - return SC_ERROR_OBJECT_NOT_VALID; + r = SC_ERROR_OBJECT_NOT_VALID; + goto out; } r = sc_update_record(p15card->card, 1, sysrec, sizeof(sysrec), From 475ce71453080c190ffddaba38d04fe6c8d43087 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Thu, 7 May 2015 21:55:26 +0200 Subject: [PATCH 209/306] iasecc: fixed resource leak pkcs15-iasecc: fix memory leakage iasecc: fix memory leakage --- src/libopensc/card-iasecc.c | 10 +++++++-- src/pkcs15init/pkcs15-iasecc.c | 37 +++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 43974897..09d730d6 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -1501,12 +1501,18 @@ iasecc_se_cache_info(struct sc_card *card, struct iasecc_se_info *se) if (card->cache.valid && card->cache.current_df) { sc_file_dup(&se_info->df, card->cache.current_df); - if (se_info->df == NULL) + if (se_info->df == NULL) { + free(se_info); LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot duplicate current DF file"); + } } rv = iasecc_docp_copy(ctx, &se->docp, &se_info->docp); - LOG_TEST_RET(ctx, rv, "Cannot make copy of DOCP"); + if (rv < 0) { + free(se_info->df); + free(se_info); + LOG_TEST_RET(ctx, rv, "Cannot make copy of DOCP"); + } if (!prv->se_info) { prv->se_info = se_info; diff --git a/src/pkcs15init/pkcs15-iasecc.c b/src/pkcs15init/pkcs15-iasecc.c index 5f9e8955..a7571123 100644 --- a/src/pkcs15init/pkcs15-iasecc.c +++ b/src/pkcs15init/pkcs15-iasecc.c @@ -398,8 +398,11 @@ iasecc_sdo_set_key_acls_from_profile(struct sc_profile *profile, struct sc_card scb[cntr++] = 0x00; } else if (acl->method == SC_AC_SEN || acl->method == SC_AC_PRO || acl->method == SC_AC_AUT) { - if ((acl->key_ref & 0xF) == 0 || (acl->key_ref & 0xF) == 0xF) + if ((acl->key_ref & 0xF) == 0 || (acl->key_ref & 0xF) == 0xF) { + if (file) + sc_file_free(file); LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Invalid SE reference"); + } amb |= mask; @@ -411,10 +414,15 @@ iasecc_sdo_set_key_acls_from_profile(struct sc_profile *profile, struct sc_card scb[cntr++] = acl->key_ref | IASECC_SCB_METHOD_EXT_AUTH; } else { + if (file) + sc_file_free(file); LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Unknown SCB method"); } } + if (file) + sc_file_free(file); + /* Copy ACLs into the DOCP*/ sdo->docp.acls_contact.tag = IASECC_DOCP_TAG_ACLS_CONTACT; sdo->docp.acls_contact.size = cntr + 1; @@ -606,9 +614,12 @@ iasecc_sdo_convert_to_file(struct sc_card *card, struct iasecc_sdo *sdo, struct unsigned op_method, op_ref; rv = iasecc_sdo_convert_acl(card, sdo, ops[ii], &op_method, &op_ref); - LOG_TEST_RET(ctx, rv, "IasEcc: cannot convert ACL"); - sc_log(ctx, "ii:%i, method:%X, ref:%X", ii, op_method, op_ref); + if (rv < 0) { + sc_file_free(file); + LOG_TEST_RET(ctx, rv, "IasEcc: cannot convert ACL"); + } + sc_log(ctx, "ii:%i, method:%X, ref:%X", ii, op_method, op_ref); sc_file_add_acl_entry(file, ops[ii], op_method, op_ref); } } @@ -833,17 +844,18 @@ iasecc_sdo_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, if (!sdo_prvkey && !sdo_pubkey) LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "At least one SDO has to be supplied"); + rv = iasecc_sdo_convert_to_file(card, sdo_prvkey ? sdo_prvkey : sdo_pubkey, &dummy_file); LOG_TEST_RET(ctx, rv, "Cannot convert SDO PRIVATE KEY to file"); card->caps &= ~SC_CARD_CAP_USE_FCI_AC; rv = sc_pkcs15init_authenticate(profile, p15card, dummy_file, SC_AC_OP_UPDATE); card->caps = caps; - LOG_TEST_RET(ctx, rv, "SDO PRIVATE KEY UPDATE authentication failed"); - if (dummy_file) sc_file_free(dummy_file); + LOG_TEST_RET(ctx, rv, "SDO PRIVATE KEY UPDATE authentication failed"); + memset(&update, 0, sizeof(update)); update.sdo_prv_key = sdo_prvkey; @@ -1276,16 +1288,23 @@ iasecc_pkcs15_delete_sdo (struct sc_profile *profile, struct sc_pkcs15_card *p15 sc_log(ctx, "iasecc_pkcs15_delete_sdo() SDO class 0x%X, ref 0x%X", sdo->sdo_class, sdo->sdo_ref); rv = iasecc_sdo_convert_to_file(card, sdo, &dummy_file); - LOG_TEST_RET(ctx, rv, "iasecc_pkcs15_delete_sdo() Cannot convert SDO to file"); + if (rv < 0) { + iasecc_sdo_free(card, sdo); + LOG_TEST_RET(ctx, rv, "iasecc_pkcs15_delete_sdo() Cannot convert SDO to file"); + } card->caps &= ~SC_CARD_CAP_USE_FCI_AC; rv = sc_pkcs15init_authenticate(profile, p15card, dummy_file, SC_AC_OP_UPDATE); card->caps = save_card_caps; - LOG_TEST_RET(ctx, rv, "iasecc_pkcs15_delete_sdo() UPDATE authentication failed for SDO"); if (dummy_file) sc_file_free(dummy_file); + if (rv < 0) { + iasecc_sdo_free(card, sdo); + LOG_TEST_RET(ctx, rv, "iasecc_pkcs15_delete_sdo() UPDATE authentication failed for SDO"); + } + if (card->type == SC_CARD_TYPE_IASECC_OBERTHUR) { /* Oberthur's card supports creation/deletion of the key slots ... */ rv = sc_card_ctl(card, SC_CARDCTL_IASECC_SDO_DELETE, sdo); @@ -1309,7 +1328,6 @@ iasecc_pkcs15_delete_sdo (struct sc_profile *profile, struct sc_pkcs15_card *p15 /* Don't know why, but, clean public key do not working with Gemalto card */ rv = iasecc_sdo_store_key(profile, p15card, sdo, NULL, &rsa); - LOG_TEST_RET(ctx, rv, "iasecc_pkcs15_delete_sdo() store empty private key failed"); } iasecc_sdo_free(card, sdo); @@ -1322,7 +1340,7 @@ iasecc_pkcs15_delete_object (struct sc_profile *profile, struct sc_pkcs15_card * struct sc_pkcs15_object *object, const struct sc_path *path) { struct sc_context *ctx = p15card->card->ctx; - struct sc_file *file = sc_file_new(); + struct sc_file *file = NULL; int rv, key_ref; LOG_FUNC_CALLED(ctx); @@ -1364,6 +1382,7 @@ iasecc_pkcs15_delete_object (struct sc_profile *profile, struct sc_pkcs15_card * LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } + file = sc_file_new(); file->type = SC_FILE_TYPE_WORKING_EF; file->ef_structure = SC_FILE_EF_TRANSPARENT; file->id = path->value[path->len-2] * 0x100 + path->value[path->len-1]; From ac84d282b1a5e7aae8d68ea7b15a214d4f28687d Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Thu, 7 May 2015 22:04:25 +0200 Subject: [PATCH 210/306] myeid: fixed resource leak pkcs15-myeid: fix memory leakage myeid: fix memory leakage --- src/libopensc/card-myeid.c | 2 ++ src/pkcs15init/pkcs15-myeid.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 63eeaf03..69a3cf72 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -826,6 +826,8 @@ myeid_convert_ec_signature(struct sc_context *ctx, size_t s_len, unsigned char * buflen = (s_len + 7)/8*2; r = sc_asn1_sig_value_sequence_to_rs(ctx, data, datalen, buf, buflen); + if (r < 0) + free(buf); LOG_TEST_RET(ctx, r, "Failed to cenvert Sig-Value to the raw RS format"); if (buflen > datalen) diff --git a/src/pkcs15init/pkcs15-myeid.c b/src/pkcs15init/pkcs15-myeid.c index 063fd2c4..acd8c06b 100644 --- a/src/pkcs15init/pkcs15-myeid.c +++ b/src/pkcs15init/pkcs15-myeid.c @@ -70,7 +70,10 @@ myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p1 sc_file_dup(&tmp_file, profile->mf_info->file); if (tmp_file == NULL) LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot duplicate MF file"); + r = sc_pkcs15init_fixup_file(profile, p15card, tmp_file); + if (r < 0) + sc_file_free(tmp_file); LOG_TEST_RET(ctx, r, "MF fixup failed"); /* AC 'Create DF' and 'Create EF' */ @@ -100,6 +103,8 @@ myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p1 if (tmp_file == NULL) LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot duplicate Application DF file"); r = sc_pkcs15init_fixup_file(profile, p15card, tmp_file); + if (r < 0) + sc_file_free(tmp_file); LOG_TEST_RET(ctx, r, "Application DF fixup failed"); /* AC 'Create DF' and 'Create EF' */ @@ -118,8 +123,8 @@ myeid_get_init_applet_data(struct sc_profile *profile, struct sc_pkcs15_card *p1 else if (entry->method == SC_AC_NEVER) *(data + 6) = 0xFF; /* 'NEVER'. */ *(data + 7) = 0xFF; - sc_file_free(tmp_file); + sc_file_free(tmp_file); LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS); } From d636338eaf597e20e3e7c2a33146c5de7c9bc413 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Thu, 7 May 2015 22:33:39 +0200 Subject: [PATCH 211/306] pkcs15-oberthur: fix memory leakage --- src/pkcs15init/pkcs15-oberthur-awp.c | 89 ++++++++++++---------------- 1 file changed, 39 insertions(+), 50 deletions(-) diff --git a/src/pkcs15init/pkcs15-oberthur-awp.c b/src/pkcs15init/pkcs15-oberthur-awp.c index fdb34c60..2a382f58 100644 --- a/src/pkcs15init/pkcs15-oberthur-awp.c +++ b/src/pkcs15init/pkcs15-oberthur-awp.c @@ -279,7 +279,10 @@ awp_create_container_record (struct sc_pkcs15_card *p15card, struct sc_profile * memset(buff, 0, list_file->record_length); rv = awp_new_container_entry(p15card, buff, list_file->record_length); - SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot create container"); + if (rv < 0) { + free(buff); + SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot create container"); + } *(buff + 0) = (acc->pubkey_id >> 8) & 0xFF; *(buff + 1) = acc->pubkey_id & 0xFF; @@ -289,7 +292,6 @@ awp_create_container_record (struct sc_pkcs15_card *p15card, struct sc_profile * *(buff + 5) = acc->cert_id & 0xFF; rv = sc_select_file(p15card->card, &list_file->path, NULL); - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "rv:%i", rv); if (rv == SC_ERROR_FILE_NOT_FOUND) rv = sc_pkcs15init_create_file(profile, p15card, list_file); @@ -297,10 +299,6 @@ awp_create_container_record (struct sc_pkcs15_card *p15card, struct sc_profile * rv = sc_append_record(p15card->card, buff, list_file->record_length, SC_RECORD_BY_REC_NR); free(buff); - - SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "return after failure"); - - rv = 0; SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); } @@ -358,14 +356,15 @@ awp_update_container_entry (struct sc_pkcs15_card *p15card, struct sc_profile *p if (rec > list_file->record_count) { rv = awp_new_container_entry(p15card, buff, list_file->record_length); - SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot create container"); } else { rv = sc_select_file(p15card->card, &list_file->path, NULL); - SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot select list_file"); - - rv = sc_read_record(p15card->card, rec, buff, list_file->record_length, SC_RECORD_BY_REC_NR); - SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot read record"); + if (!rv) + rv = sc_read_record(p15card->card, rec, buff, list_file->record_length, SC_RECORD_BY_REC_NR); + } + if (rv < 0) { + free(buff); + SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); } switch (type) { @@ -390,7 +389,8 @@ awp_update_container_entry (struct sc_pkcs15_card *p15card, struct sc_profile *p *(buff + offs + 5) = file_id & 0xFF; break; default: - SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INCORRECT_PARAMETERS, "invalid object type"); + free(buff); + SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INCORRECT_PARAMETERS); } if (rec > list_file->record_count) { @@ -403,14 +403,9 @@ awp_update_container_entry (struct sc_pkcs15_card *p15card, struct sc_profile *p } else { rv = sc_update_record(p15card->card, rec, buff, list_file->record_length, SC_RECORD_BY_REC_NR); - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "rv:%i", rv); } free(buff); - - SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "return after failure"); - - rv = 0; SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); } @@ -443,17 +438,14 @@ awp_update_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, rv = awp_new_file(p15card, profile, COSM_CONTAINER_LIST, 0, &clist, NULL); if (rv) goto done; - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "contaner cfile(rcount:%i,rlength:%i)", clist->record_count, clist->record_length); rv = sc_select_file(p15card->card, &clist->path, &file); if (rv) goto done; file->record_length = clist->record_length; - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "contaner file(rcount:%i,rlength:%i)", file->record_count, file->record_length); if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == COSM_TYPE_PRKEY_RSA) { rec_offs = 0; - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Append new record %i for private key", file->record_count + 1); rv = awp_update_container_entry(p15card, profile, file, type, obj_id, file->record_count + 1, rec_offs); goto done; } @@ -490,46 +482,45 @@ awp_update_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_path path = private_path; struct sc_file *ff = NULL; - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "container contains PrKey %02X%02X", *(list + offs + 2), *(list + offs + 3)); path.value[path.len - 2] = *(list + offs + 2) | 0x01; path.value[path.len - 1] = *(list + offs + 3); rv = sc_select_file(p15card->card, &path, &ff); if (rv) continue; - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "file id %X; size %i", ff->id, ff->size); - buff = malloc(ff->size); - if (!buff) { - rv = SC_ERROR_OUT_OF_MEMORY; - break; - } - rv = sc_pkcs15init_authenticate(profile, p15card, ff, SC_AC_OP_READ); if (rv) { - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "sc_pkcs15init_authenticate(READ) failed"); + sc_file_free(ff); break; } - rv = sc_read_binary(p15card->card, 0, buff, ff->size, 0); - if ((unsigned)rv == ff->size) { - rv = 0; - id_offs = 5 + *(buff+3); - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "rec %i; id offset %i",rec, id_offs); - if (key_id->len == *(buff + id_offs) && - !memcmp(key_id->value, buff + id_offs + 1, key_id->len)) { - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "found key file friend"); - if (!rv) - rv = awp_update_container_entry(p15card, profile, file, type, obj_id, rec + 1, rec_offs); + buff = malloc(ff->size); + if (!buff) + rv = SC_ERROR_OUT_OF_MEMORY; - if (rv >= 0 && prkey_id) { - *prkey_id = *(list + offs + 2) * 0x100 + *(list + offs + 3); - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "*prkey_id 0x%X", *prkey_id); + if (!rv) { + rv = sc_read_binary(p15card->card, 0, buff, ff->size, 0); + if ((unsigned)rv == ff->size) { + rv = 0; + id_offs = 5 + *(buff+3); + + if (key_id->len == *(buff + id_offs) && + !memcmp(key_id->value, buff + id_offs + 1, key_id->len)) { + sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "found key file friend"); + if (!rv) + rv = awp_update_container_entry(p15card, profile, file, type, obj_id, rec + 1, rec_offs); + + if (rv >= 0 && prkey_id) + *prkey_id = *(list + offs + 2) * 0x100 + *(list + offs + 3); } } } free(buff); sc_file_free(ff); + + if (rv) + break; } } } @@ -568,16 +559,15 @@ awp_set_certificate_info (struct sc_pkcs15_card *p15card, blob_size = 2; if (!(blob = malloc(blob_size))) { r = SC_ERROR_OUT_OF_MEMORY; - goto done; + goto done; } /* TODO: cert flags */ *blob = (COSM_TAG_CERT >> 8) & 0xFF; *(blob + 1) = COSM_TAG_CERT & 0xFF; - if (ci->label.len - && ci->label.len != strlen(default_cert_label) - && memcmp(ci->label.value, default_cert_label, strlen(default_cert_label))) + if (ci->label.len && ci->label.len != strlen(default_cert_label) + && memcmp(ci->label.value, default_cert_label, strlen(default_cert_label))) r = awp_update_blob(ctx, &blob, &blob_size, &ci->label, TLV_TYPE_LLV); else r = awp_update_blob(ctx, &blob, &blob_size, &ci->cn, TLV_TYPE_LLV); @@ -586,11 +576,11 @@ awp_set_certificate_info (struct sc_pkcs15_card *p15card, r = awp_update_blob(ctx, &blob, &blob_size, &ci->id, TLV_TYPE_LLV); if (r) - goto done; + goto done; r = awp_update_blob(ctx, &blob, &blob_size, &ci->subject, TLV_TYPE_LLV); if (r) - goto done; + goto done; if (ci->issuer.len != ci->subject.len || memcmp(ci->issuer.value, ci->subject.value, ci->subject.len)) { @@ -1088,8 +1078,7 @@ awp_encode_data_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *ob if (di->app.len) { di->app.value = (unsigned char *)strdup(data_info->app_label); if (!di->app.value) - SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY, - "AWP encode data failed: cannot allocate App.Label"); + SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); } r = sc_asn1_encode_object_id(&buf, &buflen, &data_info->app_oid); From 44253c63d08f39c0ea35eab2b96d46719c3abcef Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:29 +0200 Subject: [PATCH 212/306] pkcs15-rtecp: fixed resource leak --- src/pkcs15init/pkcs15-rtecp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pkcs15init/pkcs15-rtecp.c b/src/pkcs15init/pkcs15-rtecp.c index d3b0bebd..572b55e6 100644 --- a/src/pkcs15init/pkcs15-rtecp.c +++ b/src/pkcs15init/pkcs15-rtecp.c @@ -208,11 +208,13 @@ static int rtecp_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, snprintf(pin_sname, sizeof(pin_sname), "CHV%i", auth_info->attrs.pin.reference); if (auth_info->attrs.pin.reference == RTECP_USER_PIN_REF) { - r = sc_profile_get_file(profile, pin_sname, &file); + r = sc_profile_get_file(profile, pin_sname, &file); if (!r) { const struct sc_acl_entry *acl = NULL; r = sc_pkcs15init_fixup_file(profile, p15card, file); + if (r < 0) + sc_file_free(file); SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot fixup the ACLs of PIN file"); acl = sc_file_get_acl_entry(file, SC_AC_OP_PIN_RESET); From 6cb99be8219026e7d1354ab3216af26596c66f49 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:29 +0200 Subject: [PATCH 213/306] pkcs15-setcos: fixed resource leak --- src/pkcs15init/pkcs15-setcos.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c index d2e85f17..0aadc3c1 100644 --- a/src/pkcs15init/pkcs15-setcos.c +++ b/src/pkcs15init/pkcs15-setcos.c @@ -123,12 +123,16 @@ setcos_init_card(sc_profile_t *profile, sc_pkcs15_card_t *p15card) /* Fix up the file's ACLs */ r = sc_pkcs15init_fixup_file(profile, p15card, pinfile); + if (r < 0) + sc_file_free(pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Pinfile fixup failed"); /* Set life cycle state to SC_FILE_STATUS_CREATION, * which means that all ACs are ignored. */ pinfile->status = SC_FILE_STATUS_CREATION; r = sc_create_file(p15card->card, pinfile); + if (r < 0) + sc_file_free(pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Pinfile creation failed"); } sc_file_free(pinfile); From 01e573b9876b6538d85e85c16d2a3f2085ebb1cd Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:29 +0200 Subject: [PATCH 214/306] profile: fixed resource leak --- src/pkcs15init/profile.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c index a6a952e2..922b76b4 100644 --- a/src/pkcs15init/profile.c +++ b/src/pkcs15init/profile.c @@ -380,11 +380,15 @@ sc_profile_load(struct sc_profile *profile, const char *filename) sc_log(ctx, "profile %s loaded ok", path); - if (res < 0) + if (res < 0) { + scconf_free(conf); LOG_FUNC_RETURN(ctx, SC_ERROR_FILE_NOT_FOUND); + } - if (res == 0) + if (res == 0) { + scconf_free(conf); LOG_FUNC_RETURN(ctx, SC_ERROR_SYNTAX_ERROR); + } res = process_conf(profile, conf); scconf_free(conf); From efbd4068af4e475ead56c295b85911af89959d0d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:29 +0200 Subject: [PATCH 215/306] sm-cwa14890: fixed resource leak --- src/smm/sm-cwa14890.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/smm/sm-cwa14890.c b/src/smm/sm-cwa14890.c index 810a5a9c..2ba4b635 100644 --- a/src/smm/sm-cwa14890.c +++ b/src/smm/sm-cwa14890.c @@ -160,17 +160,25 @@ sm_cwa_decode_authentication_data(struct sc_context *ctx, struct sm_cwa_keyset * sc_log(ctx, "sm_ecc_decode_auth_data() decrypted(%i) %s", decrypted_len, sc_dump_hex(decrypted, decrypted_len)); - if (memcmp(decrypted, session_data->icc.rnd, 8)) + if (memcmp(decrypted, session_data->icc.rnd, 8)) { + free(decrypted); LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + } - if (memcmp(decrypted + 8, session_data->icc.sn, 8)) + if (memcmp(decrypted + 8, session_data->icc.sn, 8)) { + free(decrypted); LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + } - if (memcmp(decrypted + 16, session_data->ifd.rnd, 8)) + if (memcmp(decrypted + 16, session_data->ifd.rnd, 8)) { + free(decrypted); LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + } - if (memcmp(decrypted + 24, session_data->ifd.sn, 8)) + if (memcmp(decrypted + 24, session_data->ifd.sn, 8)) { + free(decrypted); LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + } memcpy(session_data->icc.k, decrypted + 32, 32); From b0a708b0bb2f25be9d417e56b78ba6f20f2a1d78 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:29 +0200 Subject: [PATCH 216/306] pintest: fixed resource leak --- src/tests/pintest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/pintest.c b/src/tests/pintest.c index 9a911960..16f7947b 100644 --- a/src/tests/pintest.c +++ b/src/tests/pintest.c @@ -42,6 +42,7 @@ static int enum_pins(struct sc_pkcs15_object ***ret) } if (0 > sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, n)) { fprintf(stderr, "Error enumerating PIN codes\n"); + free(objs); return 1; } for (i = 0; i < n; i++) { From c65caed7f4ce3b3146054eafc5bb2ed426931a38 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:29 +0200 Subject: [PATCH 217/306] openpgp-tool: fixed resource leak VTA: slightly touched, original commit f0ddbf4 --- src/tools/openpgp-tool.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index 5d975d59..00ca0715 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -357,7 +357,7 @@ static int do_dump_do(sc_card_t *card, unsigned int tag) // Private DO are specified up to 254 bytes unsigned char buffer[254]; memset(buffer, '\0', sizeof(buffer)); - + r = sc_get_data(card, tag, buffer, sizeof(buffer)); if (r < 0) { printf("Failed to get data object: %s\n", sc_strerror(r)); @@ -378,10 +378,9 @@ static int do_dump_do(sc_card_t *card, unsigned int tag) } dup2(tmp, fileno(stdout)); clearerr(stdout); - if (sizeof(buffer) != r) { - return EXIT_FAILURE; - } close(tmp); + if (sizeof(buffer) != r) + return EXIT_FAILURE; } else { util_hex_dump_asc(stdout, buffer, sizeof(buffer), -1); } From a83da8a947232c0c6f084cbbfeb7b979fe554368 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:30 +0200 Subject: [PATCH 218/306] pkcs15-crypt: fixed resource leak --- src/tools/pkcs15-crypt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/pkcs15-crypt.c b/src/tools/pkcs15-crypt.c index 7c257c3f..bbc0008b 100644 --- a/src/tools/pkcs15-crypt.c +++ b/src/tools/pkcs15-crypt.c @@ -326,15 +326,17 @@ static int get_key(unsigned int usage, sc_pkcs15_object_t **result) pincode = get_pin(pin); if (((pincode == NULL || *pincode == '\0')) && - !(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)) - return 5; + !(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)) { + free(pincode); + return 5; + } r = sc_pkcs15_verify_pin(p15card, pin, (const u8 *)pincode, pincode ? strlen(pincode) : 0); + free(pincode); if (r) { fprintf(stderr, "PIN code verification failed: %s\n", sc_strerror(r)); return 5; } - free(pincode); if (verbose) fprintf(stderr, "PIN code correct.\n"); prev_pin = pin; From 1f16f24052d5567bb2de92f080378421fa9719e2 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:30 +0200 Subject: [PATCH 219/306] pkcs15-init: fixed resource leak --- src/tools/pkcs15-init.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 6558593a..2cf40ff9 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -1798,8 +1798,11 @@ get_pin_callback(struct sc_profile *profile, allocated = 1; } - if (len > *pinsize) + if (len > *pinsize) { + if (allocated) + free(secret); return SC_ERROR_BUFFER_TOO_SMALL; + } memcpy(pinbuf, secret, len + 1); *pinsize = len; if (allocated) From d96f25c147d1e19efab4f3141cf8ed8dbd55678c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:30 +0200 Subject: [PATCH 220/306] pkcs15-tool: fixed resource leak --- src/tools/pkcs15-tool.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 4f7c0e36..4b0cbd85 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -1399,12 +1399,17 @@ static int unblock_pin(void) printf("New PIN value will be prompted with pinpad.\n"); break; } - if (pin == NULL || strlen((char *) pin) == 0) + if (pin == NULL || strlen((char *) pin) == 0) { + free(pin); return 2; + } pin2 = get_pin("Enter new PIN again", pin_obj); - if (pin2 == NULL || strlen((char *) pin2) == 0) + if (pin2 == NULL || strlen((char *) pin2) == 0) { + free(pin); + free(pin2); return 2; + } if (strcmp((char *) pin, (char *) pin2) != 0) { printf("PIN codes do not match, try again.\n"); free(pin); @@ -1488,6 +1493,7 @@ static int change_pin(void) } if (newpin == NULL || strlen((char *) newpin) == 0) { fprintf(stderr, "No new PIN value supplied.\n"); + free(newpin); return 2; } From bbb803ff2e75d56e8e27d6973fde389a5f08d4f7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2015 23:22:30 +0200 Subject: [PATCH 221/306] sc-hsm-tool: fixed resource leak --- src/tools/sc-hsm-tool.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index b900db27..22680c33 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -345,6 +345,7 @@ static int reconstructSecret(secret_share_t *shares, unsigned char t, const BIGN * multiplication */ if (BN_mod_inverse(&denominator, &denominator, &prime, ctx) == NULL ) { + free(bValue); return -1; } @@ -664,6 +665,7 @@ static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_pas if (r < 0) { printf("\nError during reconstruction of secret. Wrong shares?\n"); + cleanUpShares(shares, num_of_password_shares); return r; } @@ -708,6 +710,7 @@ static int import_dkek_share(sc_card_t *card, const char *inf, int iter, const c if (fread(filebuff, 1, sizeof(filebuff), in) != sizeof(filebuff)) { perror(inf); + fclose(in); return -1; } @@ -1019,6 +1022,7 @@ static int create_dkek_share(sc_card_t *card, const char *outf, int iter, const if (fwrite(filebuff, 1, sizeof(filebuff), out) != sizeof(filebuff)) { perror(outf); + fclose(out); return -1; } @@ -1240,6 +1244,7 @@ static int wrap_key(sc_card_t *card, int keyid, const char *outf, const char *pi if (fwrite(key, 1, key_len, out) != key_len) { perror(outf); free(key); + fclose(out); return -1; } From 8838388ceb9818873227e399d4fca741df3659b9 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 30 Apr 2015 00:07:10 +0200 Subject: [PATCH 222/306] pkcs15-infocamere: fixed resource leak --- src/libopensc/pkcs15-infocamere.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libopensc/pkcs15-infocamere.c b/src/libopensc/pkcs15-infocamere.c index e51b37a9..208036da 100644 --- a/src/libopensc/pkcs15-infocamere.c +++ b/src/libopensc/pkcs15-infocamere.c @@ -242,6 +242,8 @@ static int infocamere_1200_init(sc_pkcs15_card_t * p15card) if (r != SC_SUCCESS || file->size > 255) { /* Not EF.GDO */ + if (file) + sc_file_free(file); return SC_ERROR_WRONG_CARD; } @@ -249,6 +251,7 @@ static int infocamere_1200_init(sc_pkcs15_card_t * p15card) if (ef_gdo[0] != 0x5A || file->size < 3) { /* Not EF.GDO */ + sc_file_free(file); return SC_ERROR_WRONG_CARD; } @@ -260,8 +263,10 @@ static int infocamere_1200_init(sc_pkcs15_card_t * p15card) if (file->size < (size_t) (len_iccsn + 5)) { /* Not CHN */ + sc_file_free(file); return SC_ERROR_WRONG_CARD; } + sc_file_free(file); if (! (ef_gdo[len_iccsn + 2] == 0x5F From ecc9b9dac9fe4edc08d55a5aad9a94b990f4f370 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 30 Apr 2015 00:07:10 +0200 Subject: [PATCH 223/306] openssl: fixed resource leak --- src/pkcs11/openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c index 88023d76..241a9cf2 100644 --- a/src/pkcs11/openssl.c +++ b/src/pkcs11/openssl.c @@ -227,7 +227,7 @@ static CK_RV sc_pkcs11_openssl_md_init(sc_pkcs11_operation_t *op) if (!op || !(mt = op->type) || !(md = (EVP_MD *) mt->mech_data)) return CKR_ARGUMENTS_BAD; - if (!(md_ctx = calloc(1, sizeof(*md_ctx)))) + if (!(md_ctx = EVP_MD_CTX_create())) return CKR_HOST_MEMORY; EVP_DigestInit(md_ctx, md); op->priv_data = md_ctx; @@ -263,7 +263,7 @@ static void sc_pkcs11_openssl_md_release(sc_pkcs11_operation_t *op) EVP_MD_CTX *md_ctx = DIGEST_CTX(op); if (md_ctx) - free(md_ctx); + EVP_MD_CTX_destroy(md_ctx); op->priv_data = NULL; } From 2c32575e8970a997223f201caeeef12b53fd0174 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 30 Apr 2015 00:07:11 +0200 Subject: [PATCH 224/306] pkcs11-tool: fixed resource leak --- src/tools/pkcs11-tool.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index aac68263..a2f0ad53 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -3367,9 +3367,9 @@ static EVP_PKEY *get_public_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE priv if ( !pkey || !rsa || !mod || !exp) { printf("public key not extractable\n"); if (pkey) - free(pkey); + EVP_PKEY_free(pkey); if (rsa) - free(rsa); + RSA_free(rsa); if (mod) free(mod); if (exp) @@ -3424,7 +3424,7 @@ static int sign_verify_openssl(CK_SESSION_HANDLE session, #ifdef ENABLE_OPENSSL int err; EVP_PKEY *pkey; - EVP_MD_CTX md_ctx; + EVP_MD_CTX *md_ctx; const EVP_MD *evp_mds[] = { EVP_sha1(), @@ -3468,9 +3468,16 @@ static int sign_verify_openssl(CK_SESSION_HANDLE session, if (!(pkey = get_public_key(session, privKeyObject))) return errors; - EVP_VerifyInit(&md_ctx, evp_mds[evp_md_index]); - EVP_VerifyUpdate(&md_ctx, verifyData, verifyDataLen); - err = EVP_VerifyFinal(&md_ctx, sig1, sigLen1, pkey); + md_ctx = EVP_MD_CTX_create(); + if (!md_ctx) + err = -1; + else { + EVP_VerifyInit(md_ctx, evp_mds[evp_md_index]); + EVP_VerifyUpdate(md_ctx, verifyData, verifyDataLen); + err = EVP_VerifyFinal(md_ctx, sig1, sigLen1, pkey); + EVP_MD_CTX_destroy(md_ctx); + EVP_PKEY_free(pkey); + } if (err == 0) { printf("ERR: verification failed\n"); errors++; From e84951a5bf7f65d20061b49b6ebd8d739dd76708 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 30 Apr 2015 01:45:23 +0200 Subject: [PATCH 225/306] fix resource leaks in while registering PKCS#11 mechanisms introduces a free_mech_data for sc_pkcs11_mechanism_type_t to clear the mechanisms private memory --- src/pkcs11/framework-pkcs15.c | 22 +++++++++++----------- src/pkcs11/mechanism.c | 11 +++++++++-- src/pkcs11/openssl.c | 21 ++++++++++++++------- src/pkcs11/pkcs11-object.c | 3 ++- src/pkcs11/sc-pkcs11.h | 6 ++++-- src/pkcs11/slot.c | 12 +++--------- src/tools/pkcs11-tool.c | 3 +-- 7 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index c5809753..d841fceb 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -4509,7 +4509,7 @@ register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags) if (flags & SC_ALGORITHM_GOSTR3410_HASH_NONE) { mt = sc_pkcs11_new_fw_mechanism(CKM_GOSTR3410, - &mech_info, CKK_GOSTR3410, NULL); + &mech_info, CKK_GOSTR3410, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); @@ -4518,7 +4518,7 @@ register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags) } if (flags & SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411) { mt = sc_pkcs11_new_fw_mechanism(CKM_GOSTR3410_WITH_GOSTR3411, - &mech_info, CKK_GOSTR3410, NULL); + &mech_info, CKK_GOSTR3410, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); @@ -4528,7 +4528,7 @@ register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags) if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { mech_info.flags = CKF_HW | CKF_GENERATE_KEY_PAIR; mt = sc_pkcs11_new_fw_mechanism(CKM_GOSTR3410_KEY_PAIR_GEN, - &mech_info, CKK_GOSTR3410, NULL); + &mech_info, CKK_GOSTR3410, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); @@ -4566,7 +4566,7 @@ static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, mech_info.ulMinKeySize = min_key_size; mech_info.ulMaxKeySize = max_key_size; - mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA, &mech_info, CKK_EC, NULL); + mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA, &mech_info, CKK_EC, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); @@ -4575,7 +4575,7 @@ static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, #if ENABLE_OPENSSL mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA_SHA1, - &mech_info, CKK_EC, NULL); + &mech_info, CKK_EC, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); @@ -4588,14 +4588,14 @@ static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, mech_info.flags &= ~CKF_SIGN; mech_info.flags |= CKF_DERIVE; - mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_COFACTOR_DERIVE, &mech_info, CKK_EC, NULL); + mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_COFACTOR_DERIVE, &mech_info, CKK_EC, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); if (rc != CKR_OK) return rc; - mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_DERIVE, &mech_info, CKK_EC, NULL); + mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_DERIVE, &mech_info, CKK_EC, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); @@ -4605,7 +4605,7 @@ static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { mech_info.flags = CKF_HW | CKF_GENERATE_KEY_PAIR; mech_info.flags |= ec_flags; - mt = sc_pkcs11_new_fw_mechanism(CKM_EC_KEY_PAIR_GEN, &mech_info, CKK_EC, NULL); + mt = sc_pkcs11_new_fw_mechanism(CKM_EC_KEY_PAIR_GEN, &mech_info, CKK_EC, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); @@ -4701,7 +4701,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) /* Check if we support raw RSA */ if (flags & SC_ALGORITHM_RSA_RAW) { - mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_X_509, &mech_info, CKK_RSA, NULL); + mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_X_509, &mech_info, CKK_RSA, NULL, NULL); rc = sc_pkcs11_register_mechanism(p11card, mt); if (rc != CKR_OK) return rc; @@ -4729,7 +4729,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) /* No need to Check for PKCS1 We support it in software and turned it on above so always added it */ if (flags & SC_ALGORITHM_RSA_PAD_PKCS1) { - mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS, &mech_info, CKK_RSA, NULL); + mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS, &mech_info, CKK_RSA, NULL, NULL); rc = sc_pkcs11_register_mechanism(p11card, mt); if (rc != CKR_OK) return rc; @@ -4776,7 +4776,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { mech_info.flags = CKF_GENERATE_KEY_PAIR; - mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, &mech_info, CKK_RSA, NULL); + mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, &mech_info, CKK_RSA, NULL, NULL); if (!mt) return CKR_HOST_MEMORY; rc = sc_pkcs11_register_mechanism(p11card, mt); diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index a49acdb6..720bce6f 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -942,7 +942,8 @@ sc_pkcs11_mechanism_type_t * sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR pInfo, CK_KEY_TYPE key_type, - void *priv_data) + const void *priv_data, + void (*free_priv_data)(const void *priv_data)) { sc_pkcs11_mechanism_type_t *mt; @@ -953,6 +954,7 @@ sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE mech, mt->mech_info = *pInfo; mt->key_type = key_type; mt->mech_data = priv_data; + mt->free_mech_data = free_priv_data; mt->obj_size = sizeof(sc_pkcs11_operation_t); mt->release = sc_pkcs11_signature_release; @@ -994,6 +996,11 @@ sc_pkcs11_register_generic_mechanisms(struct sc_pkcs11_card *p11card) return CKR_OK; } +void free_info(const void *info) +{ + free((void *) info); +} + /* * Register a sign+hash algorithm derived from an algorithm supported * by the token + a software hash mechanism @@ -1024,7 +1031,7 @@ sc_pkcs11_register_sign_and_hash_mechanism(struct sc_pkcs11_card *p11card, info->sign_mech = sign_type->mech; info->hash_mech = hash_mech; - new_type = sc_pkcs11_new_fw_mechanism(mech, &mech_info, sign_type->key_type, info); + new_type = sc_pkcs11_new_fw_mechanism(mech, &mech_info, sign_type->key_type, info, free_info); if (!new_type) return CKR_HOST_MEMORY; diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c index 241a9cf2..5120611e 100644 --- a/src/pkcs11/openssl.c +++ b/src/pkcs11/openssl.c @@ -48,7 +48,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha1_mech = { NULL, NULL, NULL, /* verif_* */ NULL, NULL, /* decrypt_* */ NULL, /* derive */ - NULL /* mech_data */ + NULL, /* mech_data */ + NULL, /* free_mech_data */ }; #if OPENSSL_VERSION_NUMBER >= 0x00908000L @@ -65,7 +66,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha256_mech = { NULL, NULL, NULL, /* verif_* */ NULL, NULL, /* decrypt_* */ NULL, /* derive */ - NULL /* mech_data */ + NULL, /* mech_data */ + NULL, /* free_mech_data */ }; static sc_pkcs11_mechanism_type_t openssl_sha384_mech = { @@ -81,7 +83,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha384_mech = { NULL, NULL, NULL, /* verif_* */ NULL, NULL, /* decrypt_* */ NULL, /* derive */ - NULL /* mech_data */ + NULL, /* mech_data */ + NULL, /* free_mech_data */ }; static sc_pkcs11_mechanism_type_t openssl_sha512_mech = { @@ -97,7 +100,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha512_mech = { NULL, NULL, NULL, /* verif_* */ NULL, NULL, /* decrypt_* */ NULL, /* derive */ - NULL /* mech_data */ + NULL, /* mech_data */ + NULL, /* free_mech_data */ }; #endif @@ -115,7 +119,8 @@ static sc_pkcs11_mechanism_type_t openssl_gostr3411_mech = { NULL, NULL, NULL, /* verif_* */ NULL, NULL, /* decrypt_* */ NULL, /* derive */ - NULL /* mech_data */ + NULL, /* mech_data */ + NULL, /* free_mech_data */ }; #endif @@ -132,7 +137,8 @@ static sc_pkcs11_mechanism_type_t openssl_md5_mech = { NULL, NULL, NULL, /* verif_* */ NULL, NULL, /* decrypt_* */ NULL, /* derive */ - NULL /* mech_data */ + NULL, /* mech_data */ + NULL, /* free_mech_data */ }; static sc_pkcs11_mechanism_type_t openssl_ripemd160_mech = { @@ -148,7 +154,8 @@ static sc_pkcs11_mechanism_type_t openssl_ripemd160_mech = { NULL, NULL, NULL, /* verif_* */ NULL, NULL, /* decrypt_* */ NULL, /* derive */ - NULL /* mech_data */ + NULL, /* mech_data */ + NULL, /* free_mech_data */ }; void diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c index 48824cfc..607bbba8 100644 --- a/src/pkcs11/pkcs11-object.c +++ b/src/pkcs11/pkcs11-object.c @@ -47,7 +47,8 @@ static sc_pkcs11_mechanism_type_t find_mechanism = { NULL, /* decrypt_init */ NULL, /* decrypt */ NULL, /* derive */ - NULL /* mech_data */ + NULL, /* mech_data */ + NULL, /* free_mech_data */ }; static void diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 9bac0630..af0557c8 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -275,7 +275,9 @@ struct sc_pkcs11_mechanism_type { CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR); /* mechanism specific data */ - const void * mech_data; + const void * mech_data; + /* free mechanism specific data */ + void (*free_mech_data)(const void *mech_data); }; typedef struct sc_pkcs11_mechanism_type sc_pkcs11_mechanism_type_t; @@ -403,7 +405,7 @@ sc_pkcs11_mechanism_type_t *sc_pkcs11_find_mechanism(struct sc_pkcs11_card *, CK_MECHANISM_TYPE, unsigned int); sc_pkcs11_mechanism_type_t *sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR, CK_KEY_TYPE, - void *); + const void *, void (*)(const void *)); sc_pkcs11_operation_t *sc_pkcs11_new_operation(sc_pkcs11_session_t *, sc_pkcs11_mechanism_type_t *); void sc_pkcs11_release_operation(sc_pkcs11_operation_t **); diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 1d9c1a41..e41f7a93 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -170,18 +170,12 @@ CK_RV card_removed(sc_reader_t * reader) if (card) { card->framework->unbind(card); sc_disconnect_card(card->card); - /* FIXME: free mechanisms - * spaces allocated by the - * sc_pkcs11_register_sign_and_hash_mechanism - * and sc_pkcs11_new_fw_mechanism. - * but see sc_pkcs11_register_generic_mechanisms for (i=0; i < card->nmechanisms; ++i) { - // if 'mech_data' is a pointer earlier returned by the ?alloc - free(card->mechanisms[i]->mech_data); - // if 'mechanisms[i]' is a pointer earlier returned by the ?alloc + if (card->mechanisms[i]->free_mech_data) { + card->mechanisms[i]->free_mech_data(card->mechanisms[i]->mech_data); + } free(card->mechanisms[i]); } - */ free(card->mechanisms); free(card); } diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index a2f0ad53..0014a030 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -2425,9 +2425,8 @@ find_mechanism(CK_SLOT_ID slot, CK_FLAGS flags, else { *result = mechs[0]; } - - free(mechs); } + free(mechs); return count; } From e338b7c1ab2b6d39bf9d57c85f789279abd0a1ca Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 30 Apr 2015 06:46:31 +0200 Subject: [PATCH 226/306] framework-pkcs15: fixed memory leak when encoding pubkey --- src/pkcs11/framework-pkcs15.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index d841fceb..daf9bcec 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -3972,7 +3972,17 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ if (sc_pkcs15_encode_pubkey(context, pubkey->pub_data, &value, &len)) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetAttributeValue"); - check_attribute_buffer(attr, len); + if (attr->pValue == NULL_PTR) { + attr->ulValueLen = len; + free(value); + return CKR_OK; + } + if (attr->ulValueLen < len) { + attr->ulValueLen = len; + free(value); + return CKR_BUFFER_TOO_SMALL; + } + attr->ulValueLen = len; memcpy(attr->pValue, value, len); free(value); From ef4edb74ba5dfb1830a3a21b0c895553e9d4eedc Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 1 May 2015 12:50:19 +0200 Subject: [PATCH 227/306] fixed invalid free We duplicate mechanisms based on OpenSSL so that they can be freed along all the card's algorithms created via sc_pkcs11_new_fw_mechanism. Fixes regression from eaf548aa3dab80a9bbf51da8291e7db978e3a2ad --- src/pkcs11/mechanism.c | 1 + src/pkcs11/openssl.c | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index 720bce6f..77c1c63b 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -934,6 +934,7 @@ sc_pkcs11_derive(sc_pkcs11_operation_t *operation, pmechParam, ulmechParamLen, pData, pulDataLen); } + /* * Create new mechanism type for a mechanism supported by * the card diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c index 5120611e..8f812fd2 100644 --- a/src/pkcs11/openssl.c +++ b/src/pkcs11/openssl.c @@ -158,6 +158,14 @@ static sc_pkcs11_mechanism_type_t openssl_ripemd160_mech = { NULL, /* free_mech_data */ }; +static void * dup_mem(void *in, size_t in_len) +{ + void *out = malloc(in_len); + if (out) + memcpy(out, in, in_len); + return out; +} + void sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *card) { @@ -199,22 +207,22 @@ sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *card) #endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_ENGINE) */ openssl_sha1_mech.mech_data = EVP_sha1(); - sc_pkcs11_register_mechanism(card, &openssl_sha1_mech); + sc_pkcs11_register_mechanism(card, dup_mem(&openssl_sha1_mech, sizeof openssl_sha1_mech)); #if OPENSSL_VERSION_NUMBER >= 0x00908000L openssl_sha256_mech.mech_data = EVP_sha256(); - sc_pkcs11_register_mechanism(card, &openssl_sha256_mech); + sc_pkcs11_register_mechanism(card, dup_mem(&openssl_sha256_mech, sizeof openssl_sha256_mech)); openssl_sha384_mech.mech_data = EVP_sha384(); - sc_pkcs11_register_mechanism(card, &openssl_sha384_mech); + sc_pkcs11_register_mechanism(card, dup_mem(&openssl_sha384_mech, sizeof openssl_sha384_mech)); openssl_sha512_mech.mech_data = EVP_sha512(); - sc_pkcs11_register_mechanism(card, &openssl_sha512_mech); + sc_pkcs11_register_mechanism(card, dup_mem(&openssl_sha512_mech, sizeof openssl_sha512_mech)); #endif openssl_md5_mech.mech_data = EVP_md5(); - sc_pkcs11_register_mechanism(card, &openssl_md5_mech); + sc_pkcs11_register_mechanism(card, dup_mem(&openssl_md5_mech, sizeof openssl_md5_mech)); openssl_ripemd160_mech.mech_data = EVP_ripemd160(); - sc_pkcs11_register_mechanism(card, &openssl_ripemd160_mech); + sc_pkcs11_register_mechanism(card, dup_mem(&openssl_ripemd160_mech, sizeof openssl_ripemd160_mech)); #if OPENSSL_VERSION_NUMBER >= 0x10000000L openssl_gostr3411_mech.mech_data = EVP_get_digestbynid(NID_id_GostR3411_94); - sc_pkcs11_register_mechanism(card, &openssl_gostr3411_mech); + sc_pkcs11_register_mechanism(card, dup_mem(&openssl_gostr3411_mech, sizeof openssl_gostr3411_mech)); #endif } From fd3d07a88496dc0adfa2f6ff7eca9078ec087985 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Wed, 6 May 2015 20:37:20 +0200 Subject: [PATCH 228/306] Issue #451: Newer DNIe not working with OpenSC. This patch fixes 3 issues which consecutively have shown up when debugging the original problem: 1 - Newer DNIe report a byte count for public certificates which is the compressed size, while older DNIe report the uncompressed size. This resulted in short-reading the x509 certificates, and in an error parsing. Therefore, during initialization we proceed to set path->count for public certificates to -1. This ensures that the lenght of the certificates for reading will be set to file-> length, which has the correct size. 2 - pkcs11-tool -t was broken for DNIe (old and new)as it tried to strip pcks11 padding from the data to sign and OpenSC tried signatures with non-padded data (as the card had SC_ALGORITHM_RSA_RAW). The new algoflags (SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_PAD_PKCS1) and the removal of the strip-padding call fix the issue. 3 - The new cards won't allow setting the LE bytes when calculating the TLV, when LE equals 256. This caused an wrong SM object error response (0x69 0x88). Therefore, we don't send the LE bytes anymore in this case. The patch has been tested to work on the new problematic card and on another old one. close #451 --- src/libopensc/card-dnie.c | 26 +++++--------------------- src/libopensc/cwa14890.c | 19 +++++++++++-------- src/libopensc/pkcs15-dnie.c | 10 ++++++++++ 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 53ce7281..f6f1692b 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -497,8 +497,8 @@ static inline void init_flags(struct sc_card *card) card->max_send_size = (255 - 12); /* manual says 255, but we need 12 extra bytes when encoding */ card->max_recv_size = 255; - algoflags = SC_ALGORITHM_RSA_RAW; /* RSA support */ - algoflags |= SC_ALGORITHM_RSA_HASH_NONE; + /* RSA Support with PKCS1.5 padding */ + algoflags = SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_PAD_PKCS1; _sc_card_add_rsa_alg(card, 1024, algoflags, 0); _sc_card_add_rsa_alg(card, 2048, algoflags, 0); } @@ -1356,8 +1356,6 @@ static int dnie_compute_signature(struct sc_card *card, { int result = SC_SUCCESS; struct sc_apdu apdu; - u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; /* to compose digest+hash data */ - size_t sbuflen = 0; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; /* to receive sign response */ /* some preliminar checks */ @@ -1391,20 +1389,6 @@ static int dnie_compute_signature(struct sc_card *card, sc_log(card->ctx, "Compute signature len: '%d' bytes:\n%s\n============================================================", datalen, sc_dump_hex(data, datalen)); - if (datalen != 256) { - sc_log(card->ctx, "Expected pkcs#1 v1.5 DigestInfo data"); - LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH); - } - - /* try to strip pkcs1 padding */ - sbuflen = sizeof(sbuf); - memset(sbuf, 0, sbuflen); - result = sc_pkcs1_strip_01_padding(card->ctx, data, datalen, sbuf, &sbuflen); - if (result != SC_SUCCESS) { - sc_log(card->ctx, "Provided data is not pkcs#1 padded"); - /* TODO: study what to do on plain data */ - LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_PADDING); - } /*INS: 0x2A PERFORM SECURITY OPERATION * P1: 0x9E Resp: Digital Signature @@ -1413,9 +1397,9 @@ static int dnie_compute_signature(struct sc_card *card, apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = 256; /* signature response size */ - apdu.data = sbuf; - apdu.lc = sbuflen; /* 15 SHA1 DigestInfo + 20 SHA1 computed Hash */ - apdu.datalen = sizeof(sbuf); + apdu.data = data; + apdu.lc = datalen; /* Caller determines the type of hash and its size */ + apdu.datalen = datalen; /* tell card to compute signature */ result = dnie_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, result, "compute_signature() failed"); diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index dc88ff7b..800ed6fc 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -1489,6 +1489,7 @@ int cwa_encode_apdu(sc_card_t * card, /* reserve enougth space for apdulen+tlv bytes * to-be-crypted buffer and result apdu buffer */ + /* TODO DEE add 4 more bytes for testing.... */ apdubuf = calloc(MAX(SC_MAX_APDU_BUFFER_SIZE, 20 + from->datalen), sizeof(u8)); @@ -1544,14 +1545,16 @@ int cwa_encode_apdu(sc_card_t * card, } /* if le byte is declared, compose and add Le TLV */ - /* TODO: study why original driver checks for le>=256? */ - if (from->le > 0) { - u8 le = 0xff & from->le; - res = cwa_compose_tlv(card, 0x97, 1, &le, &ccbuf, &cclen); - if (res != SC_SUCCESS) { - msg = "Encode APDU compose_tlv(0x97) failed"; - goto encode_end; - } + /* FIXME: For DNIe we must not send the le bytes + when le == 256 but this goes against the standard + and might break other cards reusing this code */ + if ((0xff & from->le) > 0) { + u8 le = 0xff & from->le; + res = cwa_compose_tlv(card, 0x97, 1, &le, &ccbuf, &cclen); + if (res != SC_SUCCESS) { + msg = "Encode APDU compose_tlv(0x97) failed"; + goto encode_end; + } } /* copy current data to apdu buffer (skip header and header padding) */ memcpy(apdubuf, ccbuf + 8, cclen - 8); diff --git a/src/libopensc/pkcs15-dnie.c b/src/libopensc/pkcs15-dnie.c index 94d7f4cb..c295c305 100644 --- a/src/libopensc/pkcs15-dnie.c +++ b/src/libopensc/pkcs15-dnie.c @@ -136,6 +136,7 @@ static int sc_pkcs15emu_dnie_init(sc_pkcs15_card_t * p15card) sc_pkcs15_object_t *p15_obj; size_t len = sizeof(buf); int rv; + struct sc_pkcs15_cert_info *p15_info = NULL; sc_context_t *ctx = p15card->card->ctx; LOG_FUNC_CALLED(ctx); @@ -225,6 +226,15 @@ static int sc_pkcs15emu_dnie_init(sc_pkcs15_card_t * p15card) && (p15_obj->auth_id.len == 0)) { p15_obj->auth_id.value[0] = 0x01; p15_obj->auth_id.len = 1; + }; + /* Set path count to -1 for public certificates, as they + will need to be decompressed and read_binary()'d, so + we make sure we end up reading the file->size and not the + path->count which is the compressed size on newer + DNIe versions */ + if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_CDF) ) { + p15_info = (struct sc_pkcs15_cert_info *) p15_obj ->data; + p15_info ->path.count = -1; } /* Remove found public keys as cannot be read_binary()'d */ if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PUKDF) ) { From 37b6f0bbdfcb88a3bd761209cab211d710cc3666 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Wed, 1 Apr 2015 23:26:40 +0200 Subject: [PATCH 229/306] IsoApplet: fix EC mechanism ext_flag --- src/libopensc/card-isoApplet.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index b79f0b06..a3565c47 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -233,9 +233,10 @@ isoApplet_init(sc_card_t *card) * driver. */ flags = 0; flags |= SC_ALGORITHM_ECDSA_RAW; + flags |= SC_ALGORITHM_ECDSA_HASH_NONE; flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; - flags |= SC_ALGORITHM_EXT_EC_UNCOMPRESES; - ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE; + ext_flags = SC_ALGORITHM_EXT_EC_UNCOMPRESES; + ext_flags |= SC_ALGORITHM_EXT_EC_NAMEDCURVE; ext_flags |= SC_ALGORITHM_EXT_EC_F_P; for (i=0; ec_curves[i].oid.value[0] >= 0; i++) { From 78e434da93077e5b002d364df308847c62cb76a2 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Wed, 1 Apr 2015 23:28:39 +0200 Subject: [PATCH 230/306] register EC mechanisms with flags independent of RSA flags Prior to this commit, all hashes registered for RSA or other key types were registered for ECDSA as well. register ECDH mechanism only when supported by card ECDH should only be registered if the card driver sets the SC_ALGORITHM_ECDH_CDH_RAW flag. register software PKCS#1 (1.5) padding only when RAW RSA is supported by card If OpenSC supports PSS/OAEP padding or other padding mechanisms in future, and there would be a card that enforces hardware PSS/OAEP padding, the PKCS#1 v1.5 padding mechanism should not be registered. --- src/pkcs11/framework-pkcs15.c | 145 +++++++++++++++++----------------- 1 file changed, 71 insertions(+), 74 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index daf9bcec..f1ab565b 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1224,7 +1224,7 @@ _add_public_objects(struct sc_pkcs11_slot *slot, struct pkcs15_fw_data *fw_data, * even if there is an auth_id to allow writting for example. * See bug issue #291 * treat pubkey and cert as readable.a - */ + */ if (obj->p15_object->auth_id.len && !(is_pubkey(obj) || is_cert(obj))) continue; @@ -4545,7 +4545,7 @@ register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags) if (rc != CKR_OK) return rc; } - + return CKR_OK; } @@ -4576,41 +4576,46 @@ static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags, mech_info.ulMinKeySize = min_key_size; mech_info.ulMaxKeySize = max_key_size; - mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA, &mech_info, CKK_EC, NULL, NULL); - if (!mt) - return CKR_HOST_MEMORY; - rc = sc_pkcs11_register_mechanism(p11card, mt); - if (rc != CKR_OK) - return rc; + if(flags & SC_ALGORITHM_ECDSA_HASH_NONE) { + mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA, &mech_info, CKK_EC, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } -#if ENABLE_OPENSSL - mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA_SHA1, - &mech_info, CKK_EC, NULL, NULL); - if (!mt) - return CKR_HOST_MEMORY; - rc = sc_pkcs11_register_mechanism(p11card, mt); - if (rc != CKR_OK) - return rc; +#ifdef ENABLE_OPENSSL + if(flags & SC_ALGORITHM_ECDSA_HASH_SHA1) { + mt = sc_pkcs11_new_fw_mechanism(CKM_ECDSA_SHA1, &mech_info, CKK_EC, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } #endif /* ADD ECDH mechanisms */ /* The PIV uses curves where CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE produce the same results */ - mech_info.flags &= ~CKF_SIGN; - mech_info.flags |= CKF_DERIVE; + if(flags & SC_ALGORITHM_ECDH_CDH_RAW) { + mech_info.flags &= ~CKF_SIGN; + mech_info.flags |= CKF_DERIVE; - mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_COFACTOR_DERIVE, &mech_info, CKK_EC, NULL, NULL); - if (!mt) - return CKR_HOST_MEMORY; - rc = sc_pkcs11_register_mechanism(p11card, mt); - if (rc != CKR_OK) - return rc; + mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_COFACTOR_DERIVE, &mech_info, CKK_EC, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; - mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_DERIVE, &mech_info, CKK_EC, NULL, NULL); - if (!mt) - return CKR_HOST_MEMORY; - rc = sc_pkcs11_register_mechanism(p11card, mt); - if (rc != CKR_OK) - return rc; + mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_DERIVE, &mech_info, CKK_EC, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { mech_info.flags = CKF_HW | CKF_GENERATE_KEY_PAIR; @@ -4641,7 +4646,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) unsigned long ec_ext_flags; sc_pkcs11_mechanism_type_t *mt; unsigned int num; - int rc, flags = 0; + int rc, rsa_flags = 0, ec_flags = 0, gostr_flags = 0; /* Register generic mechanisms */ sc_pkcs11_register_generic_mechanisms(p11card); @@ -4659,14 +4664,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) /* For now, we just OR all the algorithm specific * flags, based on the assumption that cards don't - * support different modes for different key sizes - * But we need to do this by type of key as - * each has different min/max and different flags. - * - * TODO: -DEE This code assumed RSA, but the GOST - * and EC code was forced in. There should be a - * routine for each key type. - */ + * support different modes for different key *sizes*. */ num = card->algorithm_count; alg_info = card->algorithms; while (num--) { @@ -4676,69 +4674,68 @@ register_mechanisms(struct sc_pkcs11_card *p11card) mech_info.ulMinKeySize = alg_info->key_length; if (alg_info->key_length > mech_info.ulMaxKeySize) mech_info.ulMaxKeySize = alg_info->key_length; - flags |= alg_info->flags; + rsa_flags |= alg_info->flags; break; case SC_ALGORITHM_EC: if (alg_info->key_length < ec_min_key_size) ec_min_key_size = alg_info->key_length; if (alg_info->key_length > ec_max_key_size) ec_max_key_size = alg_info->key_length; - flags |= alg_info->flags; + ec_flags |= alg_info->flags; ec_ext_flags |= alg_info->u._ec.ext_flags; break; case SC_ALGORITHM_GOSTR3410: - flags |= alg_info->flags; + gostr_flags |= alg_info->flags; break; } alg_info++; } - if (flags & SC_ALGORITHM_ECDSA_RAW) { - rc = register_ec_mechanisms(p11card, flags, ec_ext_flags, ec_min_key_size, ec_max_key_size); + if (ec_flags & SC_ALGORITHM_ECDSA_RAW) { + rc = register_ec_mechanisms(p11card, ec_flags, ec_ext_flags, ec_min_key_size, ec_max_key_size); if (rc != CKR_OK) return rc; } - if (flags & (SC_ALGORITHM_GOSTR3410_RAW + if (gostr_flags & (SC_ALGORITHM_GOSTR3410_RAW | SC_ALGORITHM_GOSTR3410_HASH_NONE | SC_ALGORITHM_GOSTR3410_HASH_GOSTR3411)) { - if (flags & SC_ALGORITHM_GOSTR3410_RAW) - flags |= SC_ALGORITHM_GOSTR3410_HASH_NONE; - rc = register_gost_mechanisms(p11card, flags); + if (gostr_flags & SC_ALGORITHM_GOSTR3410_RAW) + gostr_flags |= SC_ALGORITHM_GOSTR3410_HASH_NONE; + rc = register_gost_mechanisms(p11card, gostr_flags); if (rc != CKR_OK) return rc; } /* Check if we support raw RSA */ - if (flags & SC_ALGORITHM_RSA_RAW) { + if (rsa_flags & SC_ALGORITHM_RSA_RAW) { mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_X_509, &mech_info, CKK_RSA, NULL, NULL); rc = sc_pkcs11_register_mechanism(p11card, mt); if (rc != CKR_OK) return rc; + /* We support PKCS1 padding in software */ + /* either the card supports it or OpenSC does */ + rsa_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; } - /* We support PKCS1 padding in software */ - /* either the card supports it or OpenSC does */ - flags |= SC_ALGORITHM_RSA_PAD_PKCS1; - #ifdef ENABLE_OPENSSL /* all our software hashes are in OpenSSL */ - /* Only if card did not lists the hashs, will we + /* Only if card did not lists the hashs, will we * help it a little, by adding all the OpenSSL hashes * that have PKCS#11 mechanisms. - */ - if (!(flags & SC_ALGORITHM_RSA_HASHES)) { - flags |= SC_ALGORITHM_RSA_HASHES; + */ + if (!(rsa_flags & SC_ALGORITHM_RSA_HASHES)) { + rsa_flags |= SC_ALGORITHM_RSA_HASHES; #if OPENSSL_VERSION_NUMBER < 0x00908000L /* turn off hashes not in openssl 0.9.8 */ - flags &= ~(SC_ALGORITHM_RSA_HASH_SHA256 | SC_ALGORITHM_RSA_HASH_SHA384 | SC_ALGORITHM_RSA_HASH_SHA512 | SC_ALGORITHM_RSA_HASH_SHA224); + rsa_flags &= ~(SC_ALGORITHM_RSA_HASH_SHA256 | SC_ALGORITHM_RSA_HASH_SHA384 | SC_ALGORITHM_RSA_HASH_SHA512 | SC_ALGORITHM_RSA_HASH_SHA224); #endif } #endif /* No need to Check for PKCS1 We support it in software and turned it on above so always added it */ - if (flags & SC_ALGORITHM_RSA_PAD_PKCS1) { + if (rsa_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS, &mech_info, CKK_RSA, NULL, NULL); rc = sc_pkcs11_register_mechanism(p11card, mt); if (rc != CKR_OK) @@ -4749,32 +4746,32 @@ register_mechanisms(struct sc_pkcs11_card *p11card) /* All hashes are in OpenSSL * Either the card set the hashes or we helped it above */ - if (flags & SC_ALGORITHM_RSA_HASH_SHA1) { + if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA1) { rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA1_RSA_PKCS, CKM_SHA_1, mt); if (rc != CKR_OK) return rc; } - if (flags & SC_ALGORITHM_RSA_HASH_SHA256) { + if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA256) { rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA256_RSA_PKCS, CKM_SHA256, mt); if (rc != CKR_OK) return rc; } - if (flags & SC_ALGORITHM_RSA_HASH_SHA384) { + if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA384) { rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA384_RSA_PKCS, CKM_SHA384, mt); if (rc != CKR_OK) return rc; } - if (flags & SC_ALGORITHM_RSA_HASH_SHA512) { + if (rsa_flags & SC_ALGORITHM_RSA_HASH_SHA512) { rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_SHA512_RSA_PKCS, CKM_SHA512, mt); if (rc != CKR_OK) return rc; } - if (flags & SC_ALGORITHM_RSA_HASH_MD5) { + if (rsa_flags & SC_ALGORITHM_RSA_HASH_MD5) { rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_MD5_RSA_PKCS, CKM_MD5, mt); if (rc != CKR_OK) return rc; } - if (flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) { + if (rsa_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) { rc = sc_pkcs11_register_sign_and_hash_mechanism(p11card, CKM_RIPEMD160_RSA_PKCS, CKM_RIPEMD160, mt); if (rc != CKR_OK) return rc; @@ -4784,15 +4781,15 @@ register_mechanisms(struct sc_pkcs11_card *p11card) /* TODO support other padding mechanisms */ - if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { - mech_info.flags = CKF_GENERATE_KEY_PAIR; - mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, &mech_info, CKK_RSA, NULL, NULL); - if (!mt) - return CKR_HOST_MEMORY; - rc = sc_pkcs11_register_mechanism(p11card, mt); - if (rc != CKR_OK) - return rc; - } + if (rsa_flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { + mech_info.flags = CKF_GENERATE_KEY_PAIR; + mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, &mech_info, CKK_RSA, NULL, NULL); + if (!mt) + return CKR_HOST_MEMORY; + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) + return rc; + } return CKR_OK; } From 4142456c74a56c3f0a7a276f3a3711c52bb41f4b Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Sat, 4 Apr 2015 18:46:30 +0200 Subject: [PATCH 231/306] PIV, sc-hsm, myeid: register ECDH card capabilites Prior to 066132327c71300188aa66180fde2fb3d90c5140, CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE were always registered for cards that support SC_ALGORITHM_ECDSA_RAW. The mentioned commit changed this behavior, so that the ECDH mechanisms are only registered for cards that set the SC_ALGORITHM_ECDH_CDH_RAW capability flag. To keep the existing behavior for the cards, they need to set this flag in the card driver. --- src/libopensc/card-myeid.c | 2 +- src/libopensc/card-piv.c | 2 +- src/libopensc/card-sc-hsm.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 69a3cf72..32c6fca5 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -160,7 +160,7 @@ static int myeid_init(struct sc_card *card) card->version.fw_major >= 4) { int i; - flags |= SC_ALGORITHM_ECDSA_RAW; + flags |= SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; for (i=0; ec_curves[i].curve_name != NULL; i++) diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index 017a56b5..09c7040e 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -2881,7 +2881,7 @@ static int piv_init(sc_card_t *card) _sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */ _sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */ - flags = SC_ALGORITHM_ECDSA_RAW; + flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index efe43ab8..5c7c15b6 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -1044,6 +1044,7 @@ static int sc_hsm_init(struct sc_card *card) _sc_card_add_rsa_alg(card, 2048, flags, 0); flags = SC_ALGORITHM_ECDSA_RAW| + SC_ALGORITHM_ECDH_CDH_RAW| SC_ALGORITHM_ECDSA_HASH_NONE| SC_ALGORITHM_ECDSA_HASH_SHA1| SC_ALGORITHM_ECDSA_HASH_SHA224| From 254320e34cda81720b8a102c7bbf59deff5d68ba Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Mon, 6 Apr 2015 13:04:59 +0200 Subject: [PATCH 232/306] myeid: seperate ECC from RSA flags Should keep the existing behavior, but improve readability. --- src/libopensc/card-myeid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 32c6fca5..9d6417f1 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -160,7 +160,8 @@ static int myeid_init(struct sc_card *card) card->version.fw_major >= 4) { int i; - flags |= SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW; + flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN; + flags |= SC_ALGORITHM_ECDSA_HASH_NONE | SC_ALGORITHM_ECDSA_HASH_SHA1; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; for (i=0; ec_curves[i].curve_name != NULL; i++) From 3e0356b170a3a6d2f85fce231e9e2064336671c8 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Fri, 8 May 2015 20:41:47 +0200 Subject: [PATCH 233/306] register CKM_ECDSA and CKM_ECDSA_SHA1 depending on card capabilities fix #429 --- src/libopensc/card-isoApplet.c | 2 +- src/libopensc/card-piv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-isoApplet.c b/src/libopensc/card-isoApplet.c index a3565c47..06ccd098 100644 --- a/src/libopensc/card-isoApplet.c +++ b/src/libopensc/card-isoApplet.c @@ -233,7 +233,7 @@ isoApplet_init(sc_card_t *card) * driver. */ flags = 0; flags |= SC_ALGORITHM_ECDSA_RAW; - flags |= SC_ALGORITHM_ECDSA_HASH_NONE; + flags |= SC_ALGORITHM_ECDSA_HASH_SHA1; flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; ext_flags = SC_ALGORITHM_EXT_EC_UNCOMPRESES; ext_flags |= SC_ALGORITHM_EXT_EC_NAMEDCURVE; diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index 09c7040e..0f1ef155 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -2881,7 +2881,7 @@ static int piv_init(sc_card_t *card) _sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */ _sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */ - flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW; + flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ECDSA_HASH_NONE; ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); From f154cdcaa4ac3bb4a53b3ed9a886cd23d4ef4ec4 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 18 Apr 2015 22:13:12 +0200 Subject: [PATCH 234/306] pkcs15-pin: sc_pkcs15_unblock_pin: avoid to ask the PUK twice --- src/libopensc/pkcs15-pin.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index d73915a0..6f0239bd 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -500,15 +500,10 @@ int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card, if (!puk_info) { sc_log(ctx, "Unable to get puk object, using pin object instead!"); puk_info = auth_info; - - /* make sure the puk is in valid range */ - r = _validate_pin(p15card, puk_info, puklen); - LOG_TEST_RET(ctx, r, "PIN do not conforms PIN policy"); - } - else { - r = sc_pkcs15_verify_pin(p15card, puk_obj, puk, puklen); - LOG_TEST_RET(ctx, r, "cannot verify PUK"); } + /* make sure the puk is in valid range */ + r = _validate_pin(p15card, puk_info, puklen); + LOG_TEST_RET(ctx, r, "PIN do not conforms PIN policy"); r = sc_lock(card); LOG_TEST_RET(ctx, r, "sc_lock() failed"); From 3cf56d8fb7f8a54a16eb89ca3230b07bf3f7e4be Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 10 May 2015 11:44:04 +0200 Subject: [PATCH 235/306] pkcs15init: fix non-unique-ID control --- src/pkcs15init/pkcs15-lib.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 51a71b7a..6562dbc6 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -2332,8 +2332,12 @@ select_id(struct sc_pkcs15_card *p15card, int type, struct sc_pkcs15_id *id) /* If the user provided an ID, make sure we can use it */ if (id->len != 0) { r = sc_pkcs15_find_object_by_id(p15card, type, id, &obj); + if (r == SC_ERROR_OBJECT_NOT_FOUND) r = 0; + else if (!r) + r = SC_ERROR_NON_UNIQUE_ID; + LOG_FUNC_RETURN(ctx, r); } From e0aec3764ad4162631c07c1663b680575ca0eb08 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 10 May 2015 11:46:42 +0200 Subject: [PATCH 236/306] pkcs15init: 'store-or-update' certificate option --- src/pkcs15init/pkcs15-init.h | 1 + src/pkcs15init/pkcs15-lib.c | 28 ++++++++++++++++++++++++++-- src/tools/pkcs15-init.c | 14 ++++++++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/pkcs15init/pkcs15-init.h b/src/pkcs15init/pkcs15-init.h index 9fc9a97d..e4240096 100644 --- a/src/pkcs15init/pkcs15-init.h +++ b/src/pkcs15init/pkcs15-init.h @@ -265,6 +265,7 @@ struct sc_pkcs15init_skeyargs { struct sc_pkcs15init_certargs { struct sc_pkcs15_id id; const char * label; + int update; unsigned long x509_usage; unsigned char authority; diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 6562dbc6..09feb0ad 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1630,11 +1630,14 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card, struct sc_pkcs15_cert_info *cert_info = NULL; struct sc_pkcs15_object *object = NULL; struct sc_pkcs15_object *key_object = NULL; + struct sc_path existing_path; const char *label = NULL; int r; LOG_FUNC_CALLED(ctx); + memset(&existing_path, 0, sizeof(struct sc_path)); + label = args->label; if (!label) label = "Certificate"; @@ -1642,10 +1645,25 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card, r = sc_pkcs15init_select_intrinsic_id(p15card, profile, SC_PKCS15_TYPE_CERT_X509, &args->id, &args->der_encoded); LOG_TEST_RET(ctx, r, "Get certificate 'intrinsic ID' error"); + sc_log(ctx, "Cert(ID:%s) rv %i", sc_pkcs15_print_id(&args->id), r); - /* Select an ID if the user didn't specify one, otherwise - * make sure it's unique */ + /* Select an ID if the user didn't specify one, otherwise make sure it's unique */ r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id); + if (r == SC_ERROR_NON_UNIQUE_ID && args->update) { + struct sc_pkcs15_object *existing_obj = NULL; + + r = sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_CERT, &args->id, &existing_obj); + if (!r) { + sc_log(ctx, "Found cert(ID:%s)", sc_pkcs15_print_id(&args->id)); + existing_path = ((struct sc_pkcs15_cert_info *)existing_obj->data)->path; + + sc_pkcs15_remove_object(p15card, existing_obj); + sc_pkcs15_free_object(existing_obj); + } + + r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id); + } + sc_log(ctx, "Select ID Cert(ID:%s) rv %i", sc_pkcs15_print_id(&args->id), r); LOG_TEST_RET(ctx, r, "Select certificate ID error"); object = sc_pkcs15init_new_object(SC_PKCS15_TYPE_CERT_X509, label, NULL, NULL); @@ -1657,8 +1675,14 @@ sc_pkcs15init_store_certificate(struct sc_pkcs15_card *p15card, sc_der_copy(&object->content, &args->der_encoded); sc_der_copy(&cert_info->value, &args->der_encoded); + if (existing_path.len) { + sc_log(ctx, "Using existing path %s", sc_print_path(&existing_path)); + cert_info->path = existing_path; + } + sc_log(ctx, "Store cert(%s,ID:%s,der(%p,%i))", object->label, sc_pkcs15_print_id(&cert_info->id), args->der_encoded.value, args->der_encoded.len); + if (!profile->pkcs15.direct_certificates) r = sc_pkcs15init_store_data(p15card, profile, object, &args->der_encoded, &cert_info->path); diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 2cf40ff9..44c0f734 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -138,6 +138,7 @@ enum { OPT_UPDATE_LAST_UPDATE, OPT_ERASE_APPLICATION, OPT_IGNORE_CA_CERTIFICATES, + OPT_UPDATE_EXISTING, OPT_PIN1 = 0x10000, /* don't touch these values */ OPT_PUK1 = 0x10001, @@ -189,6 +190,7 @@ const struct option options[] = { { "finalize", no_argument, NULL, 'F' }, { "update-last-update", no_argument, NULL, OPT_UPDATE_LAST_UPDATE}, { "ignore-ca-certificates",no_argument, NULL, OPT_IGNORE_CA_CERTIFICATES}, + { "update-existing", no_argument, NULL, OPT_UPDATE_EXISTING}, { "extractable", no_argument, NULL, OPT_EXTRACTABLE }, { "insecure", no_argument, NULL, OPT_INSECURE }, @@ -249,6 +251,7 @@ static const char * option_help[] = { "Finish initialization phase of the smart card", "Update 'lastUpdate' attribut of tokenInfo", "When storing PKCS#12 ignore CA certificates", + "Store or update existing certificate", "Private key stored as an extractable key", "Insecure mode: do not require a PIN for private key", @@ -364,6 +367,7 @@ static int ignore_cmdline_pins = 0; static struct secret opt_secrets[MAX_SECRETS]; static unsigned int opt_secret_count; static int opt_ignore_ca_certs = 0; +static int opt_update_existing = 0; static int verbose = 0; static struct sc_pkcs15init_callbacks callbacks = { @@ -1074,8 +1078,12 @@ do_store_certificate(struct sc_profile *profile) memset(&args, 0, sizeof(args)); + if (opt_update_existing) + args.update = 1; + if (opt_objectid) sc_pkcs15_format_id(opt_objectid, &args.id); + args.label = (opt_cert_label != 0 ? opt_cert_label : opt_label); args.authority = opt_authority; @@ -1083,8 +1091,7 @@ do_store_certificate(struct sc_profile *profile) if (r >= 0) r = do_convert_cert(&args.der_encoded, cert); if (r >= 0) - r = sc_pkcs15init_store_certificate(p15card, profile, - &args, NULL); + r = sc_pkcs15init_store_certificate(p15card, profile, &args, NULL); if (args.der_encoded.value) free(args.der_encoded.value); @@ -2542,6 +2549,9 @@ handle_option(const struct option *opt) case OPT_IGNORE_CA_CERTIFICATES: opt_ignore_ca_certs = 1; break; + case OPT_UPDATE_EXISTING: + opt_update_existing = 1; + break; default: util_print_usage_and_die(app_name, options, option_help, NULL); } From 6a2e9aa3b6c1bdb4ff9e0da3757420b302f574f6 Mon Sep 17 00:00:00 2001 From: vletoux Date: Mon, 6 Apr 2015 19:38:15 +0200 Subject: [PATCH 237/306] Merge branch 'upstream/master' Conflicts: src/libopensc/card-openpgp.c src/libopensc/pkcs15-gemsafeV1.c src/pkcs11/mechanism.c --- src/minidriver/minidriver.c | 372 ++++++++++++++++++++++++++++++++++-- 1 file changed, 354 insertions(+), 18 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 8d957d8e..1ed5f9b2 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3394,9 +3394,39 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, __in DWORD cRetryCount, __out_opt PDWORD pcAttemptsRemaining) { + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); - logprintf(pCardData, 1, "CardChangeAuthenticatorEx - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + logprintf(pCardData, 1, "CardAuthenticateEx\n"); + + if (!pCardData) + return SCARD_E_INVALID_PARAMETER; + if (dwFlags != PIN_CHANGE_FLAG_UNBLOCK && dwFlags != PIN_CHANGE_FLAG_CHANGEPIN) + return SCARD_E_INVALID_PARAMETER; + if (dwFlags == PIN_CHANGE_FLAG_UNBLOCK && dwAuthenticatingPinId == dwTargetPinId) + return SCARD_E_INVALID_PARAMETER; + if (dwAuthenticatingPinId != ROLE_USER && dwAuthenticatingPinId != ROLE_ADMIN) + return SCARD_E_INVALID_PARAMETER; + if (dwTargetPinId != ROLE_USER && dwTargetPinId != ROLE_ADMIN) + return SCARD_E_INVALID_PARAMETER; + /* according to the spec: cRetryCount MUST be zero */ + if (cRetryCount) + return SCARD_E_INVALID_PARAMETER; + + logprintf(pCardData, 2, "CardChangeAuthenticatorEx: AuthenticatingPinId=%u, dwFlags=0x%08X, cbAuthenticatingPinData=%u, TargetPinId=%u, cbTargetData=%u, Attempts %s\n", + dwAuthenticatingPinId, dwFlags, cbAuthenticatingPinData, dwTargetPinId, cbTargetData, pcAttemptsRemaining ? "YES" : "NO"); + + if (dwFlags == PIN_CHANGE_FLAG_UNBLOCK) + { + return CardUnblockPin(pCardData, (dwTargetPinId == ROLE_USER ? wszCARD_USER_USER: wszCARD_USER_ADMIN), pbAuthenticatingPinData, cbAuthenticatingPinData, pbTargetData, cbTargetData, cRetryCount, CARD_AUTHENTICATE_PIN_PIN); + } + else if ( dwFlags == PIN_CHANGE_FLAG_CHANGEPIN) + { + return CardChangeAuthenticator(pCardData, (dwTargetPinId == ROLE_USER ? wszCARD_USER_USER: wszCARD_USER_ADMIN), pbAuthenticatingPinData, cbAuthenticatingPinData, pbTargetData, cbTargetData, cRetryCount, CARD_AUTHENTICATE_PIN_PIN, pcAttemptsRemaining); + } + else + { + return SCARD_E_UNSUPPORTED_FEATURE; + } } DWORD WINAPI CardDeauthenticateEx(__in PCARD_DATA pCardData, @@ -3750,6 +3780,264 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; } + +// 4.8 Secure key injection + + +/** The CardImportSessionKey function imports a temporary session key to the card. +The session key is encrypted with a key exchange key, and the function returns a +handle of the imported session key to the caller.*/ + +DWORD WINAPI CardImportSessionKey( + __in PCARD_DATA pCardData, + __in BYTE bContainerIndex, + __in VOID *pPaddingInfo, + __in LPCWSTR pwszBlobType, + __in LPCWSTR pwszAlgId, + __out CARD_KEY_HANDLE *phKey, + __in_bcount(cbInput) PBYTE pbInput, + __in DWORD cbInput, + __in DWORD dwFlags +) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(bContainerIndex); + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(pPaddingInfo); + UNREFERENCED_PARAMETER(pwszBlobType); + UNREFERENCED_PARAMETER(pwszAlgId); + UNREFERENCED_PARAMETER(phKey); + UNREFERENCED_PARAMETER(pbInput); + UNREFERENCED_PARAMETER(cbInput); + UNREFERENCED_PARAMETER(dwFlags); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "CardImportSessionKey - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + +/** The MDImportSessionKey function imports a temporary session key to the card minidriver +and returns a key handle to the caller.*/ + +DWORD WINAPI MDImportSessionKey( + __in PCARD_DATA pCardData, + __in LPCWSTR pwszBlobType, + __in LPCWSTR pwszAlgId, + __out PCARD_KEY_HANDLE phKey, + __in_bcount(cbInput) PBYTE pbInput, + __in DWORD cbInput +) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(pwszBlobType); + UNREFERENCED_PARAMETER(pwszAlgId); + UNREFERENCED_PARAMETER(phKey); + UNREFERENCED_PARAMETER(pbInput); + UNREFERENCED_PARAMETER(cbInput); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "MDImportSessionKey - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + +/** The MDEncryptData function uses a key handle to encrypt data with a symmetric key. +The data is encrypted in a format that the smart card supports.*/ + +DWORD WINAPI MDEncryptData( + __in PCARD_DATA pCardData, + __in CARD_KEY_HANDLE hKey, + __in LPCWSTR pwszSecureFunction, + __in_bcount(cbInput) PBYTE pbInput, + __in DWORD cbInput, + __in DWORD dwFlags, + __deref_out_ecount(*pcEncryptedData) + PCARD_ENCRYPTED_DATA *ppEncryptedData, + __out PDWORD pcEncryptedData +) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(hKey); + UNREFERENCED_PARAMETER(pwszSecureFunction); + UNREFERENCED_PARAMETER(pbInput); + UNREFERENCED_PARAMETER(cbInput); + UNREFERENCED_PARAMETER(dwFlags); + UNREFERENCED_PARAMETER(ppEncryptedData); + UNREFERENCED_PARAMETER(pcEncryptedData); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "MDEncryptData - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + + +/** The CardGetSharedKeyHandle function returns a session key handle to the caller. +Note: The manner in which this session key has been established is outside the +scope of this specification. For example, the session key could be established +by either a permanent shared key or a key derivation algorithm that has occurred +before the call to CardGetSharedKeyHandle.*/ + +DWORD WINAPI CardGetSharedKeyHandle( + __in PCARD_DATA pCardData, + __in_bcount(cbInput) PBYTE pbInput, + __in DWORD cbInput, + __deref_opt_out_bcount(*pcbOutput) + PBYTE *ppbOutput, + __out_opt PDWORD pcbOutput, + __out PCARD_KEY_HANDLE phKey +) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(pbInput); + UNREFERENCED_PARAMETER(cbInput); + UNREFERENCED_PARAMETER(ppbOutput); + UNREFERENCED_PARAMETER(pcbOutput); + UNREFERENCED_PARAMETER(phKey); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "CardGetSharedKeyHandle - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + +/** The CardDestroyKey function releases a temporary key on the card. The card +should delete all of the key material that is associated with that key handle.*/ + +DWORD WINAPI CardDestroyKey( + __in PCARD_DATA pCardData, + __in CARD_KEY_HANDLE hKey +) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(hKey); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "CardDestroyKey - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + +/** This function can be used to get properties for a cryptographic algorithm.*/ +DWORD WINAPI CardGetAlgorithmProperty ( + __in PCARD_DATA pCardData, + __in LPCWSTR pwszAlgId, + __in LPCWSTR pwszProperty, + __out_bcount_part_opt(cbData, *pdwDataLen) + PBYTE pbData, + __in DWORD cbData, + __out PDWORD pdwDataLen, + __in DWORD dwFlags +) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(pwszAlgId); + UNREFERENCED_PARAMETER(pwszProperty); + UNREFERENCED_PARAMETER(pbData); + UNREFERENCED_PARAMETER(cbData); + UNREFERENCED_PARAMETER(pdwDataLen); + UNREFERENCED_PARAMETER(dwFlags); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "CardGetAlgorithmProperty - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + +/** This function is used to get the properties of a key.*/ +DWORD WINAPI CardGetKeyProperty( + __in PCARD_DATA pCardData, + __in CARD_KEY_HANDLE hKey, + __in LPCWSTR pwszProperty, + __out_bcount_part_opt(cbData, *pdwDataLen) PBYTE pbData, + __in DWORD cbData, + __out PDWORD pdwDataLen, + __in DWORD dwFlags + ) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(hKey); + UNREFERENCED_PARAMETER(pwszProperty); + UNREFERENCED_PARAMETER(pbData); + UNREFERENCED_PARAMETER(cbData); + UNREFERENCED_PARAMETER(pdwDataLen); + UNREFERENCED_PARAMETER(dwFlags); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "CardGetKeyProperty - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + +/** This function is used to set the properties of a key.*/ +DWORD WINAPI CardSetKeyProperty( + __in PCARD_DATA pCardData, + __in CARD_KEY_HANDLE hKey, + __in LPCWSTR pwszProperty, + __in_bcount(cbInput) PBYTE pbInput, + __in DWORD cbInput, + __in DWORD dwFlags +) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(dwFlags); + UNREFERENCED_PARAMETER(hKey); + UNREFERENCED_PARAMETER(pwszProperty); + UNREFERENCED_PARAMETER(pbInput); + UNREFERENCED_PARAMETER(cbInput); + UNREFERENCED_PARAMETER(dwFlags); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "CardSetKeyProperty - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + +/** CardProcessEncryptedData processes a set of encrypted data BLOBs by +sending them to the card where the data BLOBs are decrypted.*/ + +DWORD WINAPI CardProcessEncryptedData( + __in PCARD_DATA pCardData, + __in CARD_KEY_HANDLE hKey, + __in LPCWSTR pwszSecureFunction, + __in_ecount(cEncryptedData) + PCARD_ENCRYPTED_DATA pEncryptedData, + __in DWORD cEncryptedData, + __out_bcount_part_opt(cbOutput, *pdwOutputLen) + PBYTE pbOutput, + __in DWORD cbOutput, + __out_opt PDWORD pdwOutputLen, + __in DWORD dwFlags +) +{ + UNREFERENCED_PARAMETER(pCardData); + UNREFERENCED_PARAMETER(hKey); + UNREFERENCED_PARAMETER(pwszSecureFunction); + UNREFERENCED_PARAMETER(pEncryptedData); + UNREFERENCED_PARAMETER(cEncryptedData); + UNREFERENCED_PARAMETER(pbOutput); + UNREFERENCED_PARAMETER(cbOutput); + UNREFERENCED_PARAMETER(pdwOutputLen); + UNREFERENCED_PARAMETER(dwFlags); + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); + logprintf(pCardData, 1, "CardProcessEncryptedData - unsupported\n"); + return SCARD_E_UNSUPPORTED_FEATURE; +} + +/** The CardCreateContainerEx function creates a new key container that the +container index identifies and the bContainerIndex parameter specifies. The function +associates the key container with the PIN that the PinId parameter specified. +This function is useful if the card-edge does not allow for changing the key attributes +after the key container is created. This function replaces the need to call +CardSetContainerProperty to set the CCP_PIN_IDENTIFIER property CardCreateContainer +is called. +The caller of this function can provide the key material that the card imports. +This is useful in those situations in which the card either does not support internal +key generation or the caller requests that the key be archived in the card.*/ + +DWORD WINAPI CardCreateContainerEx( + __in PCARD_DATA pCardData, + __in BYTE bContainerIndex, + __in DWORD dwFlags, + __in DWORD dwKeySpec, + __in DWORD dwKeySize, + __in PBYTE pbKeyData, + __in PIN_ID PinId +) +{ + if (PinId == ROLE_ADMIN) + return SCARD_W_SECURITY_VIOLATION; + if (PinId != ROLE_USER) + return SCARD_E_INVALID_PARAMETER; + /* basically CardCreateContainerEx is CardCreateContainer + the PinId */ + return CardCreateContainer(pCardData, bContainerIndex, dwFlags, dwKeySpec, dwKeySize, pbKeyData); +} + DWORD WINAPI CardAcquireContext(IN PCARD_DATA pCardData, __in DWORD dwFlags) { VENDOR_SPECIFIC *vs; @@ -3759,9 +4047,44 @@ DWORD WINAPI CardAcquireContext(IN PCARD_DATA pCardData, __in DWORD dwFlags) return SCARD_E_INVALID_PARAMETER; if (dwFlags) return SCARD_E_INVALID_PARAMETER; + if (!(dwFlags & CARD_SECURE_KEY_INJECTION_NO_CARD_MODE)) { + if( pCardData->hSCardCtx == 0) { + logprintf(pCardData, 0, "Invalide handle.\n"); + return SCARD_E_INVALID_HANDLE; + } + if( pCardData->hScard == 0) { + logprintf(pCardData, 0, "Invalide handle.\n"); + return SCARD_E_INVALID_HANDLE; + } + } + else + { + /* secure key injection not supported */ + return SCARD_E_UNSUPPORTED_FEATURE; + } + + if (pCardData->pbAtr == NULL) + return SCARD_E_INVALID_PARAMETER; + if ( pCardData->pwszCardName == NULL ) + return SCARD_E_INVALID_PARAMETER; + /* <2 lenght or >=0x22 are not ISO compliant */ + if (pCardData->cbAtr >= 0x22 || pCardData->cbAtr <= 0x2) + return SCARD_E_INVALID_PARAMETER; + /* ATR beginning by 0x00 or 0xFF are not ISO compliant */ + if (pCardData->pbAtr[0] == 0xFF || pCardData->pbAtr[0] == 0x00) + return SCARD_E_UNKNOWN_CARD; + /* Memory management functions */ + if ( ( pCardData->pfnCspAlloc == NULL ) || + ( pCardData->pfnCspReAlloc == NULL ) || + ( pCardData->pfnCspFree == NULL ) ) + return SCARD_E_INVALID_PARAMETER; + + /* The lowest supported version is 4 - maximum is 7. */ + if (pCardData->dwVersion < MD_MINIMUM_VERSION_SUPPORTED) + return (DWORD) ERROR_REVISION_MISMATCH; suppliedVersion = pCardData->dwVersion; - + /* VENDOR SPECIFIC */ vs = pCardData->pvVendorSpecific = pCardData->pfnCspAlloc(sizeof(VENDOR_SPECIFIC)); memset(vs, 0, sizeof(VENDOR_SPECIFIC)); @@ -3774,22 +4097,16 @@ DWORD WINAPI CardAcquireContext(IN PCARD_DATA pCardData, __in DWORD dwFlags) vs->hScard = pCardData->hScard; vs->hSCardCtx = pCardData->hSCardCtx; - /* The lowest supported version is 4. */ - if (pCardData->dwVersion < MD_MINIMUM_VERSION_SUPPORTED) - return (DWORD) ERROR_REVISION_MISMATCH; - - if( pCardData->hScard == 0) { - logprintf(pCardData, 0, "Invalide handle.\n"); - return SCARD_E_INVALID_HANDLE; - } - logprintf(pCardData, 2, "request version pCardData->dwVersion = %d\n", pCardData->dwVersion); pCardData->dwVersion = min(pCardData->dwVersion, MD_CURRENT_VERSION_SUPPORTED); logprintf(pCardData, 2, "pCardData->dwVersion = %d\n", pCardData->dwVersion); dwret = md_create_context(pCardData, vs); - if (dwret != SCARD_S_SUCCESS) + if (dwret != SCARD_S_SUCCESS) { + pCardData->pfnCspFree(pCardData->pvVendorSpecific); + pCardData->pvVendorSpecific = NULL; return dwret; + } md_static_data.flags &= ~MD_STATIC_FLAG_CONTEXT_DELETED; pCardData->pfnCardDeleteContext = CardDeleteContext; @@ -3820,22 +4137,28 @@ DWORD WINAPI CardAcquireContext(IN PCARD_DATA pCardData, __in DWORD dwFlags) pCardData->pfnCardConstructDHAgreement = CardConstructDHAgreement; dwret = associate_card(pCardData); - if (dwret != SCARD_S_SUCCESS) + if (dwret != SCARD_S_SUCCESS) { + pCardData->pfnCspFree(pCardData->pvVendorSpecific); + pCardData->pvVendorSpecific = NULL; return dwret; + } dwret = md_fs_init(pCardData); - if (dwret != SCARD_S_SUCCESS) + if (dwret != SCARD_S_SUCCESS) { + pCardData->pfnCspFree(pCardData->pvVendorSpecific); + pCardData->pvVendorSpecific = NULL; return dwret; + } logprintf(pCardData, 1, "OpenSC init done.\n"); + logprintf(pCardData, 1, "Supplied version %u - version used %u.\n", suppliedVersion, pCardData->dwVersion); - if (suppliedVersion > 4) { + if (pCardData->dwVersion >= CARD_DATA_VERSION_FIVE) { pCardData->pfnCardDeriveKey = CardDeriveKey; pCardData->pfnCardDestroyDHAgreement = CardDestroyDHAgreement; pCardData->pfnCspGetDHAgreement = CspGetDHAgreement; - if (suppliedVersion > 5 ) { - logprintf(pCardData, 1, "Supplied version %i.\n", suppliedVersion); + if (pCardData->dwVersion >= CARD_DATA_VERSION_SIX) { pCardData->pfnCardGetChallengeEx = CardGetChallengeEx; pCardData->pfnCardAuthenticateEx = CardAuthenticateEx; @@ -3845,6 +4168,19 @@ DWORD WINAPI CardAcquireContext(IN PCARD_DATA pCardData, __in DWORD dwFlags) pCardData->pfnCardSetContainerProperty = CardSetContainerProperty; pCardData->pfnCardGetProperty = CardGetProperty; pCardData->pfnCardSetProperty = CardSetProperty; + if (pCardData->dwVersion >= CARD_DATA_VERSION_SEVEN) { + + pCardData->pfnMDImportSessionKey = MDImportSessionKey; + pCardData->pfnMDEncryptData = MDEncryptData; + pCardData->pfnCardImportSessionKey = CardImportSessionKey; + pCardData->pfnCardGetSharedKeyHandle = CardGetSharedKeyHandle; + pCardData->pfnCardGetAlgorithmProperty = CardGetAlgorithmProperty; + pCardData->pfnCardGetKeyProperty = CardGetKeyProperty; + pCardData->pfnCardSetKeyProperty = CardSetKeyProperty; + pCardData->pfnCardProcessEncryptedData = CardProcessEncryptedData; + pCardData->pfnCardDestroyKey = CardDestroyKey; + pCardData->pfnCardCreateContainerEx = CardCreateContainerEx; + } } } From 2667394f228f49c274787a753920e7838245620d Mon Sep 17 00:00:00 2001 From: vletoux Date: Tue, 7 Apr 2015 22:50:39 +0200 Subject: [PATCH 238/306] better parameter checks for CardGetProperty and CardSetProperty Added value for secure key injection (to reject it properly because it is not implemented) --- src/minidriver/minidriver.c | 56 +++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 1ed5f9b2..c450e312 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3703,6 +3703,14 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, return ERROR_INSUFFICIENT_BUFFER; *p = CARD_PIN_STRENGTH_PLAINTEXT; } + else if (wcscmp(CP_KEY_IMPORT_SUPPORT, wszProperty) == 0) { + DWORD *p = (DWORD *)pbData; + if (pdwDataLen) + *pdwDataLen = sizeof(*p); + if (cbData < sizeof(*p)) + return ERROR_INSUFFICIENT_BUFFER; + *p = 0; + } else { logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty); return SCARD_E_INVALID_PARAMETER; @@ -3736,29 +3744,36 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, if (!wszProperty) return SCARD_E_INVALID_PARAMETER; - if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY, wszProperty) == 0 || - wcscmp(CP_CARD_PIN_INFO, wszProperty) == 0) - return SCARD_E_INVALID_PARAMETER; - if (dwFlags) return SCARD_E_INVALID_PARAMETER; - if (wcscmp(CP_PIN_CONTEXT_STRING, wszProperty) == 0) { - vs->wszPinContext = (LPWSTR) pbData; - logprintf(pCardData, 3, "Saved PIN context string: %S\n", pbData); - return SCARD_S_SUCCESS; - } - - if (wcscmp(CP_CARD_CACHE_MODE, wszProperty) == 0 || - wcscmp(CP_SUPPORTS_WIN_X509_ENROLLMENT, wszProperty) == 0 || - wcscmp(CP_CARD_GUID, wszProperty) == 0 || - wcscmp(CP_CARD_SERIAL_NO, wszProperty) == 0) { - return SCARD_E_INVALID_PARAMETER; - } - if (!pbData || !cbDataLen) return SCARD_E_INVALID_PARAMETER; + /* the following properties cannot be set according to the minidriver specifications */ + if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0 || + wcscmp(wszProperty,CP_CARD_CAPABILITIES) == 0 || + wcscmp(wszProperty,CP_CARD_KEYSIZES) == 0 || + wcscmp(wszProperty,CP_CARD_LIST_PINS) == 0 || + wcscmp(wszProperty,CP_CARD_AUTHENTICATED_STATE) == 0 || + wcscmp(wszProperty,CP_KEY_IMPORT_SUPPORT) == 0 || + wcscmp(wszProperty,CP_ENUM_ALGORITHMS) == 0 || + wcscmp(wszProperty,CP_PADDING_SCHEMES) == 0 || + wcscmp(wszProperty,CP_CHAINING_MODES) == 0 || + wcscmp(wszProperty,CP_SUPPORTS_WIN_X509_ENROLLMENT) == 0 || + wcscmp(wszProperty,CP_CARD_CACHE_MODE) == 0 || + wcscmp(wszProperty,CP_CARD_SERIAL_NO) == 0 + ) { + return SCARD_E_UNSUPPORTED_FEATURE; + } + + /* the following properties can be set, but are not implemented by the minidriver */ + if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY, wszProperty) == 0 || + wcscmp(CP_CARD_PIN_INFO, wszProperty) == 0 || + wcscmp(CP_CARD_GUID, wszProperty) == 0 ) { + return SCARD_E_UNSUPPORTED_FEATURE; + } + /* This property and CP_PIN_CONTEXT_STRING are set just prior to a call to * CardAuthenticateEx if the PIN required is declared of type ExternalPinType. */ @@ -3775,7 +3790,12 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, logprintf(pCardData, 3, "Saved parent window (%u)\n", vs->hwndParent); return SCARD_S_SUCCESS; } - + + if (wcscmp(CP_PIN_CONTEXT_STRING, wszProperty) == 0) { + vs->wszPinContext = (LPWSTR) pbData; + logprintf(pCardData, 3, "Saved PIN context string: %S\n", pbData); + return SCARD_S_SUCCESS; + } logprintf(pCardData, 3, "INVALID PARAMETER\n"); return SCARD_E_INVALID_PARAMETER; } From b7f000d6b8ce28a8724e381b23bdc1f9d5f1902a Mon Sep 17 00:00:00 2001 From: vletoux Date: Thu, 9 Apr 2015 22:02:10 +0200 Subject: [PATCH 239/306] add parameter checking for CardSignData --- src/minidriver/minidriver.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index c450e312..c5acfb38 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3089,6 +3089,15 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn if (!pCardData || !pInfo) return SCARD_E_INVALID_PARAMETER; + if ( ( pInfo->dwVersion != CARD_SIGNING_INFO_BASIC_VERSION ) && + ( pInfo->dwVersion != CARD_SIGNING_INFO_CURRENT_VERSION ) ) + return ERROR_REVISION_MISMATCH; + if ( pInfo->pbData == NULL ) + return SCARD_E_INVALID_PARAMETER; + if (pInfo->dwKeySpec != AT_SIGNATURE && pInfo->dwKeySpec != AT_KEYEXCHANGE) + return SCARD_E_INVALID_PARAMETER; + if (pInfo->dwSigningFlags & ~(CARD_PADDING_INFO_PRESENT | CARD_PADDING_NONE)) + return SCARD_E_INVALID_PARAMETER; logprintf(pCardData, 2, "CardSignData dwVersion=%u, bContainerIndex=%u, dwKeySpec=%u, dwSigningFlags=0x%08X, aiHashAlg=0x%08X\n", pInfo->dwVersion,pInfo->bContainerIndex ,pInfo->dwKeySpec, pInfo->dwSigningFlags, pInfo->aiHashAlg); @@ -3118,10 +3127,15 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn if (CARD_PADDING_INFO_PRESENT & pInfo->dwSigningFlags) { BCRYPT_PKCS1_PADDING_INFO *pinf = (BCRYPT_PKCS1_PADDING_INFO *)pInfo->pPaddingInfo; - if (CARD_PADDING_PKCS1 != pInfo->dwPaddingType) { - logprintf(pCardData, 0, "unsupported paddingtype\n"); + if (CARD_PADDING_PSS == pInfo->dwPaddingType) { + logprintf(pCardData, 0, "unsupported paddingtype CARD_PADDING_PSS\n"); return SCARD_E_UNSUPPORTED_FEATURE; } + else if (CARD_PADDING_PKCS1 != pInfo->dwPaddingType) { + logprintf(pCardData, 0, "unsupported paddingtype\n"); + return SCARD_E_INVALID_PARAMETER; + } + if (!pinf->pszAlgId) { /* hashAlg = CALG_SSL3_SHAMD5; */ logprintf(pCardData, 3, "Using CALG_SSL3_SHAMD5 hashAlg\n"); From 6aaf9d462c6488fa2d21143bf15007842661783b Mon Sep 17 00:00:00 2001 From: vletoux Date: Thu, 9 Apr 2015 22:29:50 +0200 Subject: [PATCH 240/306] fix a problem: CardDeauthenticate(ex) do nothing, but the base CSP think that the user is deauthenticate from the card. The user is still authenticated ! --- src/minidriver/minidriver.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index c5acfb38..d91237e9 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -2591,7 +2591,10 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, return SCARD_S_SUCCESS; } - +/* this function is not called on purpose. +If a deauthentication is not possible, it should be set to NULL in CardAcquireContext. +Because this function do nothing - it is not called. +Note: the PIN freshnesh will be managed by the Base CSP*/ DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData, __in LPWSTR pwszUserId, __in DWORD dwFlags) @@ -2625,7 +2628,9 @@ DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData, logprintf(pCardData, 5, "PinsFreshness = %d\n", cardcf->bPinsFreshness); /* TODO Reset PKCS#15 PIN object 'validated' flag */ - return SCARD_S_SUCCESS; + + /* force a reset of a card - SCARD_S_SUCCESS do not lead to the reset of the card and leave it still authenticated */ + return SCARD_E_UNSUPPORTED_FEATURE; } DWORD WINAPI CardCreateDirectory(__in PCARD_DATA pCardData, @@ -3468,7 +3473,9 @@ DWORD WINAPI CardDeauthenticateEx(__in PCARD_DATA pCardData, logprintf(pCardData, 1, "CardDeauthenticateEx bPinsFreshness:%d\n", cardcf->bPinsFreshness); /* TODO Reset PKCS#15 PIN object 'validated' flag */ - return SCARD_S_SUCCESS; + + /* force a reset of a card - SCARD_S_SUCCESS does not lead to the reset of the card and leave it still authenticated */ + return SCARD_E_UNSUPPORTED_FEATURE; } DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, @@ -4153,7 +4160,8 @@ DWORD WINAPI CardAcquireContext(IN PCARD_DATA pCardData, __in DWORD dwFlags) pCardData->pfnCardAuthenticateChallenge = CardAuthenticateChallenge; pCardData->pfnCardUnblockPin = CardUnblockPin; pCardData->pfnCardChangeAuthenticator = CardChangeAuthenticator; - pCardData->pfnCardDeauthenticate = CardDeauthenticate; /* NULL */ + /* the minidriver does not perform a deauthentication - set it to NULL according to the specification */ + pCardData->pfnCardDeauthenticate = NULL; pCardData->pfnCardCreateDirectory = CardCreateDirectory; pCardData->pfnCardDeleteDirectory = CardDeleteDirectory; pCardData->pvUnused3 = NULL; From 54f462368b170e5a026b8dbf723f8cb2dc72cbf2 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 11 Apr 2015 08:52:22 +0200 Subject: [PATCH 241/306] Fix CardSignData "invalid signature" bug when called from CryptSignHash(CRYPT_NOHASHOID) --- src/minidriver/minidriver.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index d91237e9..5b7e25ee 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3181,6 +3181,16 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn else if (hashAlg !=0) return SCARD_E_UNSUPPORTED_FEATURE; } + + if (pInfo->dwSigningFlags & CARD_PADDING_NONE) + { + /* do not add the digest info when called from CryptSignHash(CRYPT_NOHASHOID) + + Note: SC_ALGORITHM_RSA_HASH_MD5_SHA1 aka CALG_SSL3_SHAMD5 do not have a digest info to be added + CryptSignHash(CALG_SSL3_SHAMD5,CRYPT_NOHASHOID) is the same than CryptSignHash(CALG_SSL3_SHAMD5) + */ + opt_hash_flags = 0; + } /* From sc-minidriver_specs_v7.docx pp.76: * 'The Base CSP/KSP performs the hashing operation on the data before passing it From 9544844d83e56891c5f164ddcd2418c337164868 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 11 Apr 2015 10:34:33 +0200 Subject: [PATCH 242/306] CardSignData: better error message if the card do not support the signing operation with the algorithm (replace the return code from internal error to unsupported) --- src/minidriver/minidriver.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 5b7e25ee..2f42e17c 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3241,7 +3241,13 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn logprintf(pCardData, 2, "sc_pkcs15_compute_signature return %d\n", r); if(r < 0) { logprintf(pCardData, 2, "sc_pkcs15_compute_signature erreur %s\n", sc_strerror(r)); - return SCARD_F_INTERNAL_ERROR; + switch (r) + { + case SC_ERROR_NOT_SUPPORTED: + return SCARD_E_UNSUPPORTED_FEATURE; + default: + return SCARD_F_INTERNAL_ERROR; + } } pInfo->cbSignedData = r; From c5efcae0292ee86b1bc800ca06626998a25ef881 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 11 Apr 2015 11:08:52 +0200 Subject: [PATCH 243/306] CardRSADecrypt: better parameter checking CardRSADecrypt & CardSignData: better OpenSC -> minidriver error code translation --- src/minidriver/minidriver.c | 67 ++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 2f42e17c..33277949 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -2961,9 +2961,22 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; if (!pInfo) return SCARD_E_INVALID_PARAMETER; + if ( pInfo->pbData == NULL ) + return SCARD_E_INVALID_PARAMETER; + if (pInfo->dwVersion > CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION) + return ERROR_REVISION_MISMATCH; + if ( pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION + && pCardData->dwVersion == CARD_DATA_CURRENT_VERSION) + return ERROR_REVISION_MISMATCH; + if (pInfo->dwKeySpec != AT_KEYEXCHANGE) + return SCARD_E_INVALID_PARAMETER; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + /* check if the container exists */ + if (pInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS) + return SCARD_E_NO_KEY_CONTAINER; + check_reader_status(pCardData); logprintf(pCardData, 2, "CardRSADecrypt dwVersion=%u, bContainerIndex=%u,dwKeySpec=%u pbData=%p, cbData=%u\n", @@ -2975,7 +2988,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, pkey = vs->p15_containers[pInfo->bContainerIndex].prkey_obj; if (!pkey) { logprintf(pCardData, 2, "CardRSADecrypt prkey not found\n"); - return SCARD_E_INVALID_PARAMETER; + return SCARD_E_NO_KEY_CONTAINER; } /* input and output buffers are always the same size */ @@ -3001,31 +3014,37 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, return SCARD_F_INTERNAL_ERROR; } + /* filter boggus input: the data to decrypt is shorter than the RSA key ? */ + if ( pInfo->cbData < prkey_info->modulus_length / 8) + { + /* according to the minidriver specs, this is the error code to return + (instead of invalid parameter when the call is forwarded to the card implementation) */ + return SCARD_E_INSUFFICIENT_BUFFER; + } + if (alg_info->flags & SC_ALGORITHM_RSA_RAW) { logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA-RAW mechanism\n"); r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags, pbuf, pInfo->cbData, pbuf2, pInfo->cbData); - if (r < 0) { - logprintf(pCardData, 2, "PKCS#15 decipher failed: %i\n", r); - return SCARD_F_INTERNAL_ERROR; - } logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r); - /* Need to handle padding */ - if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) { - logprintf(pCardData, 2, "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%u\n", pInfo->dwVersion); - if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) { - logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n"); - r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &pInfo->cbData); - if (r < 0) { - logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r); + if (r > 0) { + /* Need to handle padding */ + if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) { + logprintf(pCardData, 2, "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%u\n", pInfo->dwVersion); + if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) { + logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n"); + r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &pInfo->cbData); + if (r < 0) { + logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r); + return SCARD_F_INTERNAL_ERROR; + } + } + else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) { + /* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */ + logprintf(pCardData, 2, "OAEP padding not implemented\n"); return SCARD_F_INTERNAL_ERROR; } } - else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) { - /* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */ - logprintf(pCardData, 2, "OAEP padding not implemented\n"); - return SCARD_F_INTERNAL_ERROR; - } } } else if (alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1) { @@ -3063,7 +3082,15 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, if ( r < 0) { logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r)); - return SCARD_E_INVALID_VALUE; + switch (r) + { + case SC_ERROR_NOT_ALLOWED: + return SCARD_W_SECURITY_VIOLATION; + case SC_ERROR_NOT_SUPPORTED: + return SCARD_E_UNSUPPORTED_FEATURE; + default: + return SCARD_E_INVALID_VALUE; + } } logprintf(pCardData, 2, "decrypted data(%i):\n", pInfo->cbData); @@ -3245,6 +3272,8 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn { case SC_ERROR_NOT_SUPPORTED: return SCARD_E_UNSUPPORTED_FEATURE; + case SC_ERROR_NOT_ALLOWED: + return SCARD_W_SECURITY_VIOLATION; default: return SCARD_F_INTERNAL_ERROR; } From cb38657d47ad0bebfb7ae9763d746ce1c0018532 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 11 Apr 2015 14:17:20 +0200 Subject: [PATCH 244/306] CardSignData: add support for missing hash algorithm --- src/minidriver/minidriver.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 33277949..587abcfc 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3180,8 +3180,16 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA1; else if (wcscmp(pinf->pszAlgId, L"SHAMD5") == 0) opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5_SHA1; + else if (wcscmp(pinf->pszAlgId, L"SHA224") == 0) + opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA224; else if (wcscmp(pinf->pszAlgId, L"SHA256") == 0) opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA256; + else if (wcscmp(pinf->pszAlgId, L"SHA384") == 0) + opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA384; + else if (wcscmp(pinf->pszAlgId, L"SHA512") == 0) + opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA512; + else if (wcscmp(pinf->pszAlgId, L"RIPEMD160") == 0) + opt_hash_flags = SC_ALGORITHM_RSA_HASH_RIPEMD160; else { logprintf(pCardData, 0,"unknown AlgId %S\n",NULLWSTR(pinf->pszAlgId)); @@ -3205,6 +3213,12 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn opt_hash_flags = SC_ALGORITHM_RSA_HASH_MD5_SHA1; else if (hashAlg == CALG_SHA_256) opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA256; + else if (hashAlg == CALG_SHA_384) + opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA384; + else if (hashAlg == CALG_SHA_512) + opt_hash_flags = SC_ALGORITHM_RSA_HASH_SHA512; + else if (hashAlg == (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_RIPEMD160)) + opt_hash_flags = SC_ALGORITHM_RSA_HASH_RIPEMD160; else if (hashAlg !=0) return SCARD_E_UNSUPPORTED_FEATURE; } From 8036388f292b13cd2df36dd6b8b08c5a34093321 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 11 Apr 2015 16:30:17 +0200 Subject: [PATCH 245/306] minidriver PINPAD: fix a regression issue (the parameter - message - can be set to null) Improve the error code when the user cancel the operation ("The operation was canceled by the user" instead of "invalid parameter") Signed-off-by: vletoux --- src/minidriver/minidriver.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 587abcfc..5178e784 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3432,8 +3432,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, MB_OKCANCEL | MB_ICONINFORMATION); if (IDCANCEL == r) { logprintf(pCardData, 2, "User canceled PIN verification\n"); - /* @TODO: is this the right code to return? */ - return SCARD_E_INVALID_PARAMETER; + return ERROR_CANCELLED; } } @@ -3827,7 +3826,7 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, if (dwFlags) return SCARD_E_INVALID_PARAMETER; - if (!pbData || !cbDataLen) + if (!cbDataLen) return SCARD_E_INVALID_PARAMETER; /* the following properties cannot be set according to the minidriver specifications */ @@ -3858,7 +3857,7 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, * CardAuthenticateEx if the PIN required is declared of type ExternalPinType. */ if (wcscmp(CP_PARENT_WINDOW, wszProperty) == 0) { - if (cbDataLen != sizeof(HWND)) { + if (cbDataLen != sizeof(HWND) || !pbData) { return SCARD_E_INVALID_PARAMETER; } else { From 9601041f75392c11521201dd509be60ef0f7d900 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sun, 12 Apr 2015 08:47:09 +0200 Subject: [PATCH 246/306] win32 setup: * change the default wix background image (aka brand the setup) * add the missing ARPCONTACT property --- win32/OpenSC.wxs.in | 4 ++++ win32/bannrbmp.bmp | Bin 0 -> 85894 bytes win32/dlgbmp.bmp | Bin 0 -> 461814 bytes 3 files changed, 4 insertions(+) create mode 100644 win32/bannrbmp.bmp create mode 100644 win32/dlgbmp.bmp diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index 8559708b..37992774 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -32,10 +32,14 @@ InstallScope="perMachine"/> + + + + diff --git a/win32/bannrbmp.bmp b/win32/bannrbmp.bmp new file mode 100644 index 0000000000000000000000000000000000000000..84bed88a6ddc8558e37c0b2cd2015e96ccd61eb2 GIT binary patch literal 85894 zcmeI53sjV48pl5bWSHURrNq=kEi=~y6j1K>%fNuZ49tb$BG~10q08ph)@D{lH!U?% zE+Q$Q;1ZdMDK}AZ6|LPZI&PV^NtpsdsmGJ9>$cDE&iO_MV;E+t8U1sH@%`TKdEfW> ze(#(=&w0M*8zT}67T9o_A3yq?LBG9p7(oBpaPIWZamjSP&4ug#?eCzspYa0%AOHd& zV9f-ew&0qD4O?;pGe0T2KI=r}$DAOHd&VBG|udtq+g#fulsdok6@5oL0_=OixXo%VO14Lbh2Zvh+t0T9p-`0(@v$8){6)OQFk z{2=`C45@kC!u-z8PBYRePv+KTxIH5lnQ=}_m>3A+FvK;UL4@YXkH9WR^__4PXa z@FPh%3A)pnUg4$lUQfNz-rjC5I+bd>Ql;?OSm?O9h+-ZP009u_C-C&~K9|prQ4Frp z@$O#NGv`FRj#0z8OC#&I7u8o+R}UT4QpL1l_2~C=?B7wiD}3CZ&W+*6G9BNVW4kVA z?B+aSsmk@S=&@O1AKrj9UcNu1Hdk1w8c~z&P?cf3Dp9yBX&gJXD)YAWs&R8XZ22KO z3nZ^gU1WaO#Kgg~U(1L&loHgK;9oa=N>-YDA#cwbNrBtNbGNIb+r_@MUX$)iS7qxN z7am9e4S@&#mk1)D{RDa&wLo}|0axj|v~uH5GN zk?!hUQnf8S#THPPG+)9P0T0SDhOBau?lX3JnV~NC#8E1waj_^4+&wD95T=Kxz ziQ&5=z4m*}Sj2jQ@7a+WdMGSVYw*IepT&eXM0@SMW0Gp%azpHajt>zO%s>DH%t_$F zNQjYlCHq$4SRulIRRRcwlU~O0-%zmJKOZxm7B-g5**B40??snZxExd-+v5 zUM}a>sYGu`Ml;Lg`ArG)TJQ1D{mF^-Y?p-X2)w(18AJ!wi$iwKn5yJwjtXjt^Zdl` z?mzN9#x|hi#u9@)2!Md81U~J%Nb*gQIO+8*%^hw>zhl{OQgFAgx>=iqTch3md6ir1 z{y`E?0Xr*VId!V*x*nLWKuEztFB+#=V;%TDHI~*~|X%hjRGkNXIv+?FQ=j z3W+PTi4ACo_St{O)GU5Tyzha8kexv@Uu8W^$EV#UX^jdILIcIz!9=0w7=n0ZOL`e(D=v zbCBx9NwQhoP014$o?orwnqa)MkLAZTrRB{X8XfO1Ete@C7`WsRb$nT(HqAma=;c+) zRHAaFeTh<=K>xb-soD&#QpT;2-^P|B9p9+nlymI))tQbL45&#jE!vj%ME=8BEpdLk z6T=#Ue6(p37LVUGA%UO4^aga?bcUD#1VF$D0;9gs6sXYsOv;vMRGU&O^&O<_EIg+} ziqPpr`mU)|+5H6t>15B&(rr)Y6DO(C-0#6Z4_tC>nnQ(3xF}F3(|Y;wN~N$|?)YZ< zE&SLw)oy=Pa4RyjS&_}^(VLXEZ>8%B%q#DmuqoZKNHvBHDNP?)t`goGsC%-1bt+ey zCRm)RH6Sw|ueEU@t&t(SqkIm8#5F|CZHw$YfZJCp#(j{@mB_fqv&3wM1p)Qa;KT8An=_Ml z)n?es`K>!4XNnp~~T`b&YBCe<7lnU3$_xW>_9A`-w zl64Bnul)DQbysCNp6f5*&+5hFTeG-IIai&_6=iU*DFmfiT(L~Fr|g>0e(zHMDkWE& z?O3i5)Tz0RO53V}`}qk=WHwdmkyUE0Qq65y$kiyhl~P?KPG*vz_QcSpP~R8%A30S3LyT=e$BiWhdk_Etvk{;t@(0G_?E6)ye1$@9N~f?~IZ1iS z(!#+P-jd2~$lx9c(Ux+Pah;MY%ye2Ibr^i08PAIS4n~AD&77Ra&lxlCgIJ#fQNG&x z@x-vU1plUK<1=^zv2R;^Xk+lqV!p@N26Wt5Vz37R5HJq`N{>*cn_g5($U<+*o0EKN zpA72mr8}aOU7_%tMEt?RN`tGGskqHK+>>Ftr+C&Ua~rZ0~f={S9_;ra9D*(`$o`a+7nsZLx|(9&O>;@WfBsPC<< zd;G476x(%jt};tln$E3~-CDo#g&}!qJ|ks(Ta@P>vH!jVzk{(sJ5$1I_2y2CY>f%r zCH8NM_ueCm*q0iqZ=h#y@DMs~5D^SO00f3lfQh(mXOCUy*?V5yK>syF`Sv!uW8D;q zJGP!Udi0t=n~GRiBu?2C*UwMV5MJet^5DywM~`e7ewxClwSLLC_@!gNbc*$_dFg1$ ztJhrq;P!)@g^mvb2d6*)1WYABU!_7)t`X&9-MUwQBu;`paCRzUq2fZSAE%go;92xs zmjHD9x>(Q&0w7>c0wm>{ki0*aA~>%3Qo})Jr^E|=8{!}aIHgAbI<5x|8UtvtG+)`5=SP}_-%0RhV- zK&9f8?;c|Lpk-cyC3^)Ox8&V{Zy*2yAYhmPblfl_SbzWsfPf_vfR0=8?!Y$?009s% zOaMA=m=P>M00cn5k_kY^EqQm~8wh{^2pA>+9XHGf79aouAYjP^pyQUjJMawzKmY^` z6M&8zW&{fm009uNWCGA}OWqy$1_B@e0)`1d#|<-r1qgru2v{-!=(r{C4txUv5C8$g z1fb)F8NmVsKmY_RnE-U$l6MEbfdB}AfMEjAal?#Y0RkWZ0+vhwI&R6k1K&UZ1VF$r z0qD44Mz8<@5C8#7CIB6`-gRu{TVPEAc_WpvY0 zBjqB30t$|inV51D6-UvUnWE*CX_J&GAe6eCbR4I74)0m}BsAP)*Z#kLT)^6A?|1L_ z_kP#^_vKm7c@LgH>c1-66dM2Qm42U^es6D4D4dgiw zCs=v}5a4kh*8&6(h)saUc|7(6OOF5oJkH})d0Yz+Kp-{& z9_R7c6D&Of2=F+MYXJfX#3sPwJRW<3rAGh(9_Mi_KmdW*1bCdsV^6U32q3`YJgx-@ zAP}1XkMnr!36>rK1bCdswEzJGViVwT9*;f2(j$NXkMp<|Ab>z@0zA&+u_su11Q6hH z9@hc{5Qt5H$9X*V1WS(q0zA&+T7Uoou?g@vkH?;1=@CGH$9Y@}5I`U{0Uqb^*b^*0 z0toOpk81$}2*f79<2)XFf~7|Q0UqaZEkFQ)*aUc-$74^h^avop<2z@z@hAJpu^uIFD-q z0tmz=z~ej~dxE7$00AE7aVCs=v}5a4kh*8&6(h)saUc|7(6OOF5oJkH}< zfB*uq3Gg_N$DUy65kP>)d0Yz+Kp-{&9_R7c6D&Of2=F+MYXJfX#3sPwJRW<3rAGh( z9_Mi_KmdW*1bCdsV^6U32q3`YJgx-@AP}1XkMnr!36>rK1bCdswEzJGViVwT9*;f2 z(j$NXkMp<|Ab>z@0zA&+u_su11Q6hH9@hc{5Qt5H$9X*V1WS(q0zA&+T7Uoou?g@v zkH?;1=@CGH$9Y@}5I`U{0Uqb^*b^*00toOpk81$}2*f79<2)XFf~7|Q0UqaZEkFQ) z*aUc-$74^h^avop<2z@z@hAJpu^uIFD-q0tmz=z~ej~dxE7$00AE7aVCs=v} z5a4kh*8&6(h)saUc|7(6OOF5oJkH})d0Yz+Kp-{&9_R7c z6D&Of2=F+MYXJfX#3sPwJRW<3rAGh(9_Mi_KmdW*1bCdsV^6U32q3`YJgx-@AP}1X zkMnr!36>rK1bCdswEzJGViVwT9*;f2(j$NXkMp<|Ab>z@0zA&+u_su11Q6hH9@hc{ z5Qt5H$9X*V1WS(q0zA&+T7Uoou?g@vkH?;1=@CGH$9Y@}5I`U{0Uqb^*b^*00toOp zk81$}2*f79<2)XFf~7|Q0UqaZEkFQ)*aUc-$74^h^avop<2z@z@hAJpu^uIFD-q0tmz= zz~ej~dxE7$00AE7aVCs=v}5a4kh*8&6(h)saUc|7(6OOF5oJkH})d0Yz+Kp-{&9_R7c6D&Of2=F+MYXJfX#3sPwJRW<3rAGh(9_Mi_ zKmdW*1bCdsV^6U32q3`YJgx-@AP}1XkMnr!36>rK1bCdswEzJGViVwT9*;f2(j$NX zkMp<|Ab>z@0zA&+u_su11Q6hH9@hc{5Qt5H$9X*V1WS(q0zA&+T7Uoou?g@vkH?;1 z=@CGH$9Y@}5I`U{0Uqb^*b^*00toOpk81$}2*f79<2)XFf~7|Q0UqaZEkFQ)*aUc- z$74^h^avop<2z@z@hAJpu^uIFD-q0tmz=z~ej~dxE7$00AE7aV2lF zM2>-C@OUoU>!J|I2pmk0@A%`Zhi%(d@!Ee^Y~6a%^cgR|{PMvy-Lkqv7Sy!*+{g|G z_ha7-pT^?~k3fzI95j#r;Mtejy|Dc)D>qfV^!tiGJeO=f?4p^QH*Y?OmRvZdaQ&oC zpQ)-mh@bf;`6wRGafe+R0td(A-}?3Q?OuAWa>w@ezyCv0c@ld2=eAe8@?y77ePiRs zjR(t>OB!0uudDd%P#)iJqCBqZ2;`W+LGbvepWM;mXHTRxc%#R+ZtwWq3zhdgkschj zrBUl|pR;n=vSs@&p37=ap4)K5_olV}PHpGf9-Tft{et3qGmqast>yL8j=E(=#r*n? z9~*Mil&T)Z1F{ESe*b{mrdKSfKVJhzHoO0rn2{jiLkIx>A?t5p|S$8%J*;v){wrFL^x29d>C5yv|<-V4t2(ZcPU7_~bK3-?=gKc!%HZ=(Oee6K+_0#D6^7 z@i#jTf4Xsn{=kL}`|{z}*A;HRxG=9aIl9xzh8DM9e8l|e$9FxcefHkPlUk~d=*!XtejU@xMpmd+2h-#U)N5koLkpo&d2&@pD?es z%`IaKRi`u`zj(qSi>FmyIqEW=N=x?6)dgp+KKGm-Uf6rpMWfgDA9!JQKzaVjq-c;9a zMxS;?{Vl0&ePdnaRTG;Q%V|BHJpQGT%?Et{14k{aue_%2sO&9s>pLx}EzBBoc<~c< zc`&EC%`KB#*Zi5s7uFQ6udn>Z$Rn~N$DFff#M$fL)1~>ZoS|JejvRPb-*?Z-4j9sJ zWz~SYPd%xw_{oF&tsB<$$GzVD_r+(*@BxpjIs!Q+a3CK4$&QzkzSBxP`T8wuH+6da zx7luZGI*z7Zp|JiaW}eq=f28YSNvO2d|I$)H?chP%$C1sx;O6eWz*V!dt96EUDRq} zbz#w@%F8e8G^ShYkAG-d@pQ@KH#fA}-Q!n|?3f)hw9l#`Jsy0=NmGh%8Q$}u5d-e- zciLC8XEKkU{I>DM1I7zIn&tn|Gw`^7K8=^lEk!%cf16c9-2j@OZ-^->Ext<>bPG z>WcX_?H5cs?1m{7bH*Ki`iU*F(_J_I(DeP!+U~82XV2E-SBz>};}7X^-;mQE8GPQS ziw9iLW9{(%KRo-?f6AU2oW8?3;O=)HS6w_H!~-5zbp&!uV81<{wo}^vamO*sA5Qm) zCuL{r?zDN5Ezkelb6haHmR_rx^QL9+p^OokKa^Vs5`TD@$8w$XYF=R`usU}%=pC2 z4^LS)tk=Dx2CnMYqiNeDTaUl%*b&7~2=Rc&bKGHC3c2Prs7i8}C%P_vdMmo{rC6P2cuB?5U^Io#wqh_>a5m@45+X7S~r? z+_zcNyX=oIsjFC6)9#xS-%@<Dlwe93!{y?J80 zIrT?oZ<#;w(1rCC@9o?Cll|9>E6ktJ_L6Z;2c*M#bh~cYfc1k0+&j3(Lj#7b8hpA68_L1N2*s)`G{be5C!}mFtO=^AZ#EvT_w|!raiVvTA z%(v@LURqzcc5K_J=O3Sa+P_|Q@>eDvdh677msA}&^7OV>PC9Y^#5OCYclzXzrtf^t zo!DkcL)&zJdPAS~WBR=Ps@kK!KeaHgy72KSRoN$8*k|SV{*MknYwhGQcg+~T?uw5- zwoA^;<0o_;w9E5l{w0s+xWg_Df&KP)CamLswIy3_XAG?dkT%D&O_-$h zv?PD+e_s2G*2_FTy?5Ke&D?77E2orUD{As(onedqQdgJ!d2s&SK{fgk^MG~ zI(N;vJ-=9d%jai4IR3obI(HnJJ(GF-#AAjP4+!yq$5kDH91}P|k0*JJ{l&KQ-OlXB zl|T1*lK3gh?r;C>vrSK?pYVMCmGo1cX)7i@zX$8>)#H13?=CMrd&fWg_}0(w^5njJ zIke}xLA^J2edi~N2M_N0@Q^zoZoBRh=FUmbeUK@Y3lY+Ul`qTL0{K$>Vqa=$Fae9e(~)`hlQy6HD3(FMe0E@h3cQSep*m z7qzYZ=y5mC=&*c7mucs;`N;6MUooNcebZYnfB#V*8+pdQy#1gYGp6^(;r-Uv3|ZCn z)DInd#Dwv~HjL{3(D1X?U3TfR?DNO;zkgWo2WkfXwEN$E_|%i@tIob-SkH%sbzk}A zFD^eQ0ZQ~CJg({puU;2rc}(ISh%|Stt)T(LW$J& z|9x!T@C}2z-dEN8ff2nP9@_8jvFF{k%aIcXt-qk}JypHe4DWtl_4yBs8?@^IyBuE* zU-Ed4JM7XB*o((AiMQOmt<~n|-}BWQ)BhS`;hh^=J+U>d#M`ZZ>hZ^4x6n>Ev1BXp zw7b&rXHTcM6fM7BF8jsuk3M$m-*}s1?w6j}bLMNm^!U85zV7n(eEi?`RUTJ$1aeGZ zFCI_-luA;0qm-Z6+Wc$hN<0aDcQ>V*Skldf>HhJwX5al)&-|?j@OX|p?9vd}i^ntX zB$YQV$#?Fhw0*MiA2r;AkJ83V`qvQmaDbQo`UH4f)e*=sfqn9L@=n?cPaEP%;%Rr~ zudg9ze1imdJjWe&X$b6-$J6~PX;URhe6RO_zd_x2dx;3}xT+(NV*>l+@pP+r+V9@S z+XqWzA|Lxk2=I80JM7XB*e8#_5rcSdIS}A+RYxGl1bDn0G+XivJf7nYyEFuNyyOlo zhZFF)sw0qN0z6(0nk{(-9?x-yT^a&BUUG+)!wGm?)e*=s0Uj?0&6Yd^kLS3ImeR0FRf0W=o!d$8+3amxch3m)xP{Z~`7zbp&!ufXB;0vn9{K<2mlI zOGALiOYYEeI028VIs!Q+z~kkh*^+1A@f>&9r6IuMC3k2!oPftw9f2GZ;PGl(h%VBk~_2{)l4s!Y9Cz5IA;9A$cW61B bfX7uGfgBUy@p8~?$usbHjyvqq5Gec~ Date: Sun, 12 Apr 2015 13:34:18 +0200 Subject: [PATCH 247/306] fix memory leak in minidriver: the virtual filesystem is never freed and in some case when an error occurs --- src/minidriver/minidriver.c | 57 +++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 5178e784..57416052 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -679,6 +679,7 @@ md_fs_free_file(PCARD_DATA pCardData, struct md_file *file) pCardData->pfnCspFree(file->blob); file->blob = NULL; file->size = 0; + pCardData->pfnCspFree(file); } @@ -750,6 +751,40 @@ md_fs_delete_file(PCARD_DATA pCardData, char *parent, char *name) return dwret; } +static DWORD +md_fs_finalize(PCARD_DATA pCardData) +{ + VENDOR_SPECIFIC *vs; + struct md_file *file = NULL, *file_to_rm; + struct md_directory *dir = NULL, *dir_to_rm; + + if (!pCardData) + return SCARD_E_INVALID_PARAMETER; + + vs = pCardData->pvVendorSpecific; + + file = vs->root.files; + while (file != NULL) { + file_to_rm = file; + file = file->next; + md_fs_free_file(pCardData, file_to_rm); + } + + dir = vs->root.subdirs; + while(dir) { + file = dir->files; + while (file != NULL) { + file_to_rm = file; + file = file->next; + md_fs_free_file(pCardData, file_to_rm); + } + dir_to_rm = dir; + dir = dir->next; + pCardData->pfnCspFree(dir_to_rm); + } + return 0; +} + static DWORD md_pkcs15_encode_cardcf(PCARD_DATA pCardData, unsigned char *in, size_t in_size, unsigned char *out, size_t *out_size) @@ -2048,6 +2083,7 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) logprintf(pCardData, 1, "**********************************************************************\n"); + md_fs_finalize(pCardData); pCardData->pfnCspFree(pCardData->pvVendorSpecific); pCardData->pvVendorSpecific = NULL; @@ -2423,7 +2459,7 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, random_len = 8; *pcbChallengeData = 0; - random = malloc(random_len); + random = pCardData->pfnCspAlloc(random_len); if (!random) return SCARD_E_NO_MEMORY; @@ -2439,7 +2475,7 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, memcpy(*ppbChallengeData, random, random_len); *pcbChallengeData = random_len; - free(random); + pCardData->pfnCspFree(random); logprintf(pCardData, 7, "returns %i bytes:\n", *pcbChallengeData); loghex(pCardData, 7, *ppbChallengeData, *pcbChallengeData); @@ -2998,8 +3034,10 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, lg2 = pInfo->cbData; pbuf2 = pCardData->pfnCspAlloc(pInfo->cbData); - if (!pbuf2) + if (!pbuf2) { + pCardData->pfnCspFree(pbuf); return SCARD_E_NO_MEMORY; + } /*inversion donnees*/ for(ui = 0; ui < pInfo->cbData; ui++) @@ -3011,6 +3049,8 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, alg_info = sc_card_find_rsa_alg(vs->p15card->card, prkey_info->modulus_length); if (!alg_info) { logprintf(pCardData, 2, "Cannot get appropriate RSA card algorithm for key size %i\n", prkey_info->modulus_length); + pCardData->pfnCspFree(pbuf); + pCardData->pfnCspFree(pbuf2); return SCARD_F_INTERNAL_ERROR; } @@ -3019,6 +3059,8 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, { /* according to the minidriver specs, this is the error code to return (instead of invalid parameter when the call is forwarded to the card implementation) */ + pCardData->pfnCspFree(pbuf); + pCardData->pfnCspFree(pbuf2); return SCARD_E_INSUFFICIENT_BUFFER; } @@ -3036,12 +3078,16 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &pInfo->cbData); if (r < 0) { logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r); + pCardData->pfnCspFree(pbuf); + pCardData->pfnCspFree(pbuf2); return SCARD_F_INTERNAL_ERROR; } } else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) { /* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */ logprintf(pCardData, 2, "OAEP padding not implemented\n"); + pCardData->pfnCspFree(pbuf); + pCardData->pfnCspFree(pbuf2); return SCARD_F_INTERNAL_ERROR; } } @@ -3077,11 +3123,15 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, } else { logprintf(pCardData, 2, "CardRSADecrypt: no usable RSA algorithm\n"); + pCardData->pfnCspFree(pbuf); + pCardData->pfnCspFree(pbuf2); return SCARD_E_INVALID_PARAMETER; } if ( r < 0) { logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r)); + pCardData->pfnCspFree(pbuf); + pCardData->pfnCspFree(pbuf2); switch (r) { case SC_ERROR_NOT_ALLOWED: @@ -3282,6 +3332,7 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn logprintf(pCardData, 2, "sc_pkcs15_compute_signature return %d\n", r); if(r < 0) { logprintf(pCardData, 2, "sc_pkcs15_compute_signature erreur %s\n", sc_strerror(r)); + pCardData->pfnCspFree(pbuf); switch (r) { case SC_ERROR_NOT_SUPPORTED: From a5593afc781ee7bffb3b061618b9086273099e6c Mon Sep 17 00:00:00 2001 From: vletoux Date: Sun, 12 Apr 2015 14:06:36 +0200 Subject: [PATCH 248/306] minidriver: better parameter checking with CardQueryKeySizes and CardGetContainerProperty --- src/minidriver/minidriver.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 57416052..c60072c5 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -2963,10 +2963,27 @@ DWORD WINAPI CardQueryKeySizes(__in PCARD_DATA pCardData, DWORD dwret; logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); - logprintf(pCardData, 1, "CardQueryKeySizes dwKeySpec=%X, dwFlags=%X, version=%X\n", dwKeySpec, dwFlags, pKeySizes->dwVersion); + logprintf(pCardData, 1, "CardQueryKeySizes dwKeySpec=%X, dwFlags=%X, version=%X\n", dwKeySpec, dwFlags, (pKeySizes?pKeySizes->dwVersion:0)); if (!pCardData) return SCARD_E_INVALID_PARAMETER; + if ( dwFlags != 0 ) + return SCARD_E_INVALID_PARAMETER; + switch(dwKeySpec) + { + case AT_ECDHE_P256 : + case AT_ECDHE_P384 : + case AT_ECDHE_P521 : + case AT_ECDSA_P256 : + case AT_ECDSA_P384 : + case AT_ECDSA_P521 : + return SCARD_E_UNSUPPORTED_FEATURE; + case AT_KEYEXCHANGE: + case AT_SIGNATURE : + break; + default: + return SCARD_E_INVALID_PARAMETER; + } dwret = md_query_key_sizes(pKeySizes); if (dwret != SCARD_S_SUCCESS) @@ -3595,6 +3612,9 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, __out PDWORD pdwDataLen, __in DWORD dwFlags) { + VENDOR_SPECIFIC *vs = NULL; + struct md_pkcs15_container *cont = NULL; + logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetContainerProperty\n"); @@ -3609,6 +3629,17 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; if (!pbData || !pdwDataLen) return SCARD_E_INVALID_PARAMETER; + if (bContainerIndex >= MD_MAX_KEY_CONTAINERS) + return SCARD_E_NO_KEY_CONTAINER; + + /* the test for the existence of containers is redondant with the one made in CardGetContainerInfo but CCP_PIN_IDENTIFIER does not do it */ + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + cont = &vs->p15_containers[bContainerIndex]; + + if (!cont->prkey_obj) { + logprintf(pCardData, 7, "Container %i is empty\n", bContainerIndex); + return SCARD_E_NO_KEY_CONTAINER; + } if (wcscmp(CCP_CONTAINER_INFO,wszProperty) == 0) { PCONTAINER_INFO p = (PCONTAINER_INFO) pbData; From f331b35c4ee80a71acc7cbdcb5c873a012b24a9f Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 17 Apr 2015 16:39:48 +0200 Subject: [PATCH 249/306] minidriver: make the parameter check be aware of pinpad capabilities --- src/minidriver/minidriver.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index c60072c5..a91a261d 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -2377,17 +2377,17 @@ DWORD WINAPI CardAuthenticatePin(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; if (wcscmp(wszCARD_USER_USER,pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN,pwszUserId) != 0) return SCARD_E_INVALID_PARAMETER; - if (NULL == pbPin) + if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD) && NULL == pbPin) return SCARD_E_INVALID_PARAMETER; - if (cbPin < 4 || cbPin > 12) + if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD) && (cbPin < 4 || cbPin > 12)) return SCARD_W_WRONG_CHV; if (wcscmp(wszCARD_USER_ADMIN, pwszUserId) == 0) return SCARD_W_WRONG_CHV; if(pcAttemptsRemaining) - (*pcAttemptsRemaining) = 0; + (*pcAttemptsRemaining) = (DWORD) -1; wcstombs(type, pwszUserId, 100); type[10] = 0; @@ -2516,8 +2516,6 @@ DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData, if (pwszUserId == NULL) return SCARD_E_INVALID_PARAMETER; - if (pbAuthenticationData == NULL) - return SCARD_E_INVALID_PARAMETER; if (wcscmp(wszCARD_USER_USER, pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN,pwszUserId) != 0) return SCARD_E_INVALID_PARAMETER; if (wcscmp(wszCARD_USER_ADMIN, pwszUserId) == 0) @@ -2529,6 +2527,9 @@ DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData, vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if ((!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) && pbAuthenticationData == NULL) + return SCARD_E_INVALID_PARAMETER; + dw_rv = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj); if (dw_rv != SCARD_S_SUCCESS) { logprintf(pCardData, 2, "Cannot get User PIN object"); @@ -2574,14 +2575,19 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, if (pwszUserId == NULL) return SCARD_E_INVALID_PARAMETER; - if (pbCurrentAuthenticator == NULL || cbCurrentAuthenticator == 0) { - logprintf(pCardData, 1, "Invalid current PIN data\n"); - return SCARD_E_INVALID_PARAMETER; - } + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) return SCARD_E_INVALID_PARAMETER; - if (pbNewAuthenticator == NULL || cbNewAuthenticator == 0) { - logprintf(pCardData, 1, "Invalid new PIN data\n"); - return SCARD_E_INVALID_PARAMETER; + if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) { + if (pbCurrentAuthenticator == NULL || cbCurrentAuthenticator == 0) { + logprintf(pCardData, 1, "Invalid current PIN data\n"); + return SCARD_E_INVALID_PARAMETER; + } + + if (pbNewAuthenticator == NULL || cbNewAuthenticator == 0) { + logprintf(pCardData, 1, "Invalid new PIN data\n"); + return SCARD_E_INVALID_PARAMETER; + } } if (dwFlags != CARD_AUTHENTICATE_PIN_PIN) { @@ -2599,8 +2605,6 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, pwszUserId, pbCurrentAuthenticator, cbCurrentAuthenticator, pbNewAuthenticator, cbNewAuthenticator, cRetryCount, dwFlags); - vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - if (wcscmp(wszCARD_USER_USER, pwszUserId) == 0) dw_rv = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj); else if (wcscmp(wszCARD_USER_ADMIN,pwszUserId) == 0) @@ -3468,7 +3472,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; if(pcAttemptsRemaining) - (*pcAttemptsRemaining) = 0; + (*pcAttemptsRemaining) = (DWORD) -1; r = md_get_pin_by_role(pCardData, PinId, &pin_obj); if (r != SCARD_S_SUCCESS) { From 8062eac14575611cb70e2cfc431fed2507180f2f Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 17 Apr 2015 18:04:05 +0200 Subject: [PATCH 250/306] minidriver: fix CardQueryCapabilities and CardGetProperty fKeyGen flag. A read only card cannot generate keys --- src/minidriver/minidriver.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index a91a261d..3ac9b30a 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -1600,7 +1600,8 @@ md_card_capabilities(PCARD_CAPABILITIES pCardCapabilities) pCardCapabilities->dwVersion = CARD_CAPABILITIES_CURRENT_VERSION; pCardCapabilities->fCertificateCompression = TRUE; - pCardCapabilities->fKeyGen = TRUE; + /* a read only card cannot generate new keys */ + pCardCapabilities->fKeyGen = ! md_is_read_only(pCardData); return SCARD_S_SUCCESS; } @@ -2101,7 +2102,7 @@ DWORD WINAPI CardQueryCapabilities(__in PCARD_DATA pCardData, if (!pCardData || !pCardCapabilities) return SCARD_E_INVALID_PARAMETER; - dwret = md_card_capabilities(pCardCapabilities); + dwret = md_card_capabilities(pCardData, pCardCapabilities); if (dwret != SCARD_S_SUCCESS) return dwret; @@ -3725,7 +3726,7 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, *pdwDataLen = sizeof(*pCardCapabilities); if (cbData < sizeof(*pCardCapabilities)) return ERROR_INSUFFICIENT_BUFFER; - dwret = md_card_capabilities(pCardCapabilities); + dwret = md_card_capabilities(pCardData, pCardCapabilities); if (dwret != SCARD_S_SUCCESS) return dwret; } From ad47d4d043f11122f75cc3de18037fcc0d0b2c27 Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 17 Apr 2015 21:39:41 +0200 Subject: [PATCH 251/306] minidriver: * factorize the code from CardAuthenticatePIN into CardAuthenticateEx * allows authentication with the PINPAD without a UI minidriver: fix some code analysis warnings --- src/libopensc/reader-pcsc.c | 4 +- src/minidriver/minidriver.c | 201 ++++++++++++++---------------------- 2 files changed, 78 insertions(+), 127 deletions(-) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index dccb7f8f..73824525 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -1511,8 +1511,8 @@ static int part10_build_modify_pin_block(struct sc_reader *reader, u8 * buf, siz /* Ignore language and T=1 parameters. */ pin_modify->wLangId = HOST_TO_CCID_16(0x0000); - pin_modify->bMsgIndex1 = 0x00; /* Default message indexes */ - pin_modify->bMsgIndex2 = 0x01; + pin_modify->bMsgIndex1 = (data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? 0x01: 0x00); /* Default message indexes */ + pin_modify->bMsgIndex2 = (data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? 0x02: 0x01); pin_modify->bMsgIndex3 = 0x02; pin_modify->bTeoPrologue[0] = 0x00; pin_modify->bTeoPrologue[1] = 0x00; diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 3ac9b30a..39f00db9 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -173,6 +173,7 @@ typedef struct _VENDOR_SPECIFIC #define MD_STATIC_FLAG_CREATE_CONTAINER_KEY_IMPORT 32 #define MD_STATIC_FLAG_CREATE_CONTAINER_KEY_GEN 64 #define MD_STATIC_FLAG_IGNORE_PIN_LENGTH 128 +#define MD_STATIC_FLAG_ALLOW_PINPAD_IF_SILENT_CONTEXT 256 #define MD_STATIC_PROCESS_ATTACHED 0xA11AC4EDL struct md_opensc_static_data { @@ -205,7 +206,7 @@ static DWORD md_get_cardcf(PCARD_DATA pCardData, CARD_CACHE_FILE_FORMAT **out); static DWORD md_pkcs15_delete_object(PCARD_DATA pCardData, struct sc_pkcs15_object *obj); static DWORD md_fs_init(PCARD_DATA pCardData); -static void logprintf(PCARD_DATA pCardData, int level, const char* format, ...) +static void logprintf(PCARD_DATA pCardData, int level, _Printf_format_string_ const char* format, ...) { va_list arg; VENDOR_SPECIFIC *vs; @@ -286,14 +287,14 @@ static void loghex(PCARD_DATA pCardData, int level, PBYTE data, int len) logprintf(pCardData, level, " %04X %s\n", a, line); } -static void print_werror(PCARD_DATA pCardData, char *str) +static void print_werror(PCARD_DATA pCardData, PSTR str) { void *buf; - FormatMessage( + FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), 0, (LPTSTR) &buf, 0, NULL); + NULL, GetLastError(), 0, (LPSTR) &buf, 0, NULL); - logprintf(pCardData, 0, "%s%s\n", str, buf); + logprintf(pCardData, 0, "%s%s\n", str, (PSTR) buf); LocalFree(buf); } @@ -485,6 +486,13 @@ md_is_supports_container_key_import(PCARD_DATA pCardData) return md_get_config_bool(pCardData, "md_supports_container_key_import", MD_STATIC_FLAG_CREATE_CONTAINER_KEY_IMPORT, TRUE); } +/* Get know if the minidriver can request a pin from the pinpad if the minidriver can't display a UI - typically windows smart card logon*/ +static BOOL +md_is_supports_use_pinpad_in_silent_context(PCARD_DATA pCardData) +{ + logprintf(pCardData, 2, "Can the minidriver request a pin from the pinpad if the minidriver can't display a UI?\n"); + return md_get_config_bool(pCardData, "md_supports_pinpad_in_silent_context", MD_STATIC_FLAG_ALLOW_PINPAD_IF_SILENT_CONTEXT, FALSE); +} /* Check if specified PIN has been verified */ static BOOL @@ -1590,7 +1598,7 @@ md_create_context(PCARD_DATA pCardData, VENDOR_SPECIFIC *vs) } static DWORD -md_card_capabilities(PCARD_CAPABILITIES pCardCapabilities) +md_card_capabilities(PCARD_DATA pCardData, PCARD_CAPABILITIES pCardCapabilities) { if (!pCardCapabilities) return SCARD_E_INVALID_PARAMETER; @@ -2092,12 +2100,12 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) } DWORD WINAPI CardQueryCapabilities(__in PCARD_DATA pCardData, - __in PCARD_CAPABILITIES pCardCapabilities) + __inout PCARD_CAPABILITIES pCardCapabilities) { DWORD dwret; logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); - logprintf(pCardData, 1, "pCardCapabilities=%X\n", pCardCapabilities); + logprintf(pCardData, 1, "pCardCapabilities=%p\n", pCardCapabilities); if (!pCardData || !pCardCapabilities) return SCARD_E_INVALID_PARAMETER; @@ -2198,7 +2206,7 @@ typedef struct { } PUBKEYSTRUCT_BASE; DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContainerIndex, __in DWORD dwFlags, - __in PCONTAINER_INFO pContainerInfo) + __inout PCONTAINER_INFO pContainerInfo) { VENDOR_SPECIFIC *vs = NULL; DWORD sz = 0; @@ -2347,82 +2355,27 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine DWORD WINAPI CardAuthenticatePin(__in PCARD_DATA pCardData, __in LPWSTR pwszUserId, - __in PBYTE pbPin, + __in_bcount(cbPin) PBYTE pbPin, __in DWORD cbPin, __out_opt PDWORD pcAttemptsRemaining) { - struct sc_pkcs15_object *pin_obj = NULL; - struct sc_pkcs15_auth_info *auth_info = NULL; - char type[256]; - VENDOR_SPECIFIC *vs; - struct md_file *cardcf_file = NULL; - CARD_CACHE_FILE_FORMAT *cardcf = NULL; - DWORD dwret; - int r; - - if(!pCardData) - return SCARD_E_INVALID_PARAMETER; - - vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - + PIN_ID PinId = 0; logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardAuthenticatePin '%S':%d\n", NULLWSTR(pwszUserId), cbPin); - check_reader_status(pCardData); - - dwret = md_get_cardcf(pCardData, &cardcf); - if (dwret != SCARD_S_SUCCESS) - return dwret; - - if (NULL == pwszUserId) - return SCARD_E_INVALID_PARAMETER; - if (wcscmp(wszCARD_USER_USER,pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN,pwszUserId) != 0) - return SCARD_E_INVALID_PARAMETER; - if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD) && NULL == pbPin) - return SCARD_E_INVALID_PARAMETER; - - if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD) && (cbPin < 4 || cbPin > 12)) - return SCARD_W_WRONG_CHV; - - if (wcscmp(wszCARD_USER_ADMIN, pwszUserId) == 0) - return SCARD_W_WRONG_CHV; - - if(pcAttemptsRemaining) - (*pcAttemptsRemaining) = (DWORD) -1; - - wcstombs(type, pwszUserId, 100); - type[10] = 0; - - logprintf(pCardData, 1, "CardAuthenticatePin %.20s, %d, %d\n", NULLSTR(type), - cbPin, (pcAttemptsRemaining==NULL?-2:*pcAttemptsRemaining)); - - r = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj); - if (r != SCARD_S_SUCCESS) { - logprintf(pCardData, 2, "Cannot get User PIN object"); - return r; + if (wcscmp(pwszUserId, wszCARD_USER_USER) == 0) { + PinId = ROLE_USER; } - - if (!pin_obj) - return SCARD_F_INTERNAL_ERROR; - auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; - - r = sc_pkcs15_verify_pin(vs->p15card, pin_obj, (const u8 *) pbPin, cbPin); - if (r) { - logprintf(pCardData, 1, "PIN code verification failed: %s; tries left %i\n", sc_strerror(r), auth_info->tries_left); - - if (r == SC_ERROR_AUTH_METHOD_BLOCKED) - return SCARD_W_CHV_BLOCKED; - - if(pcAttemptsRemaining) - (*pcAttemptsRemaining) = auth_info->tries_left; - return SCARD_W_WRONG_CHV; + else if (wcscmp(pwszUserId, wszCARD_USER_ADMIN) == 0) { + PinId = ROLE_ADMIN; } + else { + return SCARD_E_INVALID_PARAMETER; + } + if (pbPin == NULL) + return SCARD_E_INVALID_PARAMETER; - logprintf(pCardData, 3, "Pin code correct.\n"); - - SET_PIN(cardcf->bPinsFreshness, ROLE_USER); - logprintf(pCardData, 3, "PinsFreshness = %d\n", cardcf->bPinsFreshness); - return SCARD_S_SUCCESS; + return CardAuthenticateEx(pCardData, PinId, 0, pbPin, cbPin, NULL, NULL, pcAttemptsRemaining); } @@ -2431,8 +2384,6 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, __out PDWORD pcbChallengeData) { VENDOR_SPECIFIC *vs; - unsigned char *random = NULL; - size_t random_len; int rv; logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); @@ -2444,7 +2395,7 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; logprintf(pCardData, 1, "Asked challenge length %i, buffer %p\n", *pcbChallengeData, *ppbChallengeData); - if (pcbChallengeData == 0) { + if (pcbChallengeData == NULL) { *ppbChallengeData = NULL; logprintf(pCardData, 7, "returns zero bytes\n"); @@ -2455,29 +2406,20 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, check_reader_status(pCardData); - random_len = (size_t)(*pcbChallengeData); - if(random_len < 8) - random_len = 8; - *pcbChallengeData = 0; + *pcbChallengeData = 8; - random = pCardData->pfnCspAlloc(random_len); - if (!random) + *ppbChallengeData = (PBYTE) pCardData->pfnCspAlloc(8); + if (!*ppbChallengeData) return SCARD_E_NO_MEMORY; - rv = sc_get_challenge(vs->p15card->card, random, random_len); + rv = sc_get_challenge(vs->p15card->card, *ppbChallengeData, 8); if (rv) { logprintf(pCardData, 1, "Get challenge failed: %s\n", sc_strerror(rv)); + pCardData->pfnCspFree(*ppbChallengeData); + *ppbChallengeData = NULL; return SCARD_E_UNEXPECTED; } - *ppbChallengeData = pCardData->pfnCspAlloc(random_len); - if(!*ppbChallengeData) - return SCARD_E_NO_MEMORY; - - memcpy(*ppbChallengeData, random, random_len); - *pcbChallengeData = random_len; - pCardData->pfnCspFree(random); - logprintf(pCardData, 7, "returns %i bytes:\n", *pcbChallengeData); loghex(pCardData, 7, *ppbChallengeData, *pcbChallengeData); return SCARD_S_SUCCESS; @@ -2522,7 +2464,7 @@ DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData, if (wcscmp(wszCARD_USER_ADMIN, pwszUserId) == 0) return SCARD_W_WRONG_CHV; - logprintf(pCardData, 1, "UserID('%s'), AuthData(%p, %li), NewPIN(%p, %li), Retry(%li), dwFlags(0x%lX)\n", + logprintf(pCardData, 1, "UserID('%S'), AuthData(%p, %u), NewPIN(%p, %u), Retry(%u), dwFlags(0x%X)\n", pwszUserId, pbAuthenticationData, cbAuthenticationData, pbNewPinData, cbNewPinData, cRetryCount, dwFlags); @@ -2602,7 +2544,7 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, if(pcAttemptsRemaining) (*pcAttemptsRemaining) = 0; - logprintf(pCardData, 1, "UserID('%s'), CurrentPIN(%p, %li), NewPIN(%p, %li), Retry(%li), dwFlags(0x%lX)\n", + logprintf(pCardData, 1, "UserID('%S'), CurrentPIN(%p, %u), NewPIN(%p, %u), Retry(%u), dwFlags(0x%X)\n", pwszUserId, pbCurrentAuthenticator, cbCurrentAuthenticator, pbNewAuthenticator, cbNewAuthenticator, cRetryCount, dwFlags); @@ -2614,7 +2556,7 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, return SCARD_F_INTERNAL_ERROR; if (dw_rv != SCARD_S_SUCCESS) { - logprintf(pCardData, 2, "Cannot get %s PIN by role", pwszUserId); + logprintf(pCardData, 2, "Cannot get %S PIN by role", pwszUserId); return dw_rv; } if (!pin_obj) @@ -2624,7 +2566,7 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, pbCurrentAuthenticator, cbCurrentAuthenticator, pbNewAuthenticator, cbNewAuthenticator); if (rv) { - logprintf(pCardData, 2, "Failed to change %s PIN: '%s' (%i)\n", pwszUserId, sc_strerror(rv), rv); + logprintf(pCardData, 2, "Failed to change %S PIN: '%s' (%i)\n", pwszUserId, sc_strerror(rv), rv); return SCARD_F_INTERNAL_ERROR; } @@ -2692,7 +2634,7 @@ DWORD WINAPI CardDeleteDirectory(__in PCARD_DATA pCardData, } DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData, - __in LPSTR pszDirectoryName, + __in_opt LPSTR pszDirectoryName, __in LPSTR pszFileName, __in DWORD cbInitialCreationSize, __in CARD_FILE_ACCESS_CONDITION AccessCondition) @@ -2719,10 +2661,10 @@ DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData, DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData, - __in LPSTR pszDirectoryName, + __in_opt LPSTR pszDirectoryName, __in LPSTR pszFileName, __in DWORD dwFlags, - __deref_out_bcount(*pcbData) PBYTE *ppbData, + __deref_out_bcount_opt(*pcbData) PBYTE *ppbData, __out PDWORD pcbData) { VENDOR_SPECIFIC *vs; @@ -2739,7 +2681,7 @@ DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData, vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - logprintf(pCardData, 2, "pszDirectoryName = %s, pszFileName = %s, dwFlags = %X, pcbData=%d, *ppbData=%X\n", + logprintf(pCardData, 2, "pszDirectoryName = %s, pszFileName = %s, dwFlags = %X, pcbData=%u, *ppbData=%X\n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName), dwFlags, *pcbData, *ppbData); if (!pszFileName || !strlen(pszFileName)) @@ -2771,7 +2713,7 @@ DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData, DWORD WINAPI CardWriteFile(__in PCARD_DATA pCardData, - __in LPSTR pszDirectoryName, + __in_opt LPSTR pszDirectoryName, __in LPSTR pszFileName, __in DWORD dwFlags, __in_bcount(cbData) PBYTE pbData, @@ -2822,7 +2764,7 @@ DWORD WINAPI CardWriteFile(__in PCARD_DATA pCardData, } DWORD WINAPI CardDeleteFile(__in PCARD_DATA pCardData, - __in LPSTR pszDirectoryName, + __in_opt LPSTR pszDirectoryName, __in LPSTR pszFileName, __in DWORD dwFlags) { @@ -2848,8 +2790,8 @@ DWORD WINAPI CardDeleteFile(__in PCARD_DATA pCardData, DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData, - __in LPSTR pszDirectoryName, - __out_ecount(*pdwcbFileName) LPSTR *pmszFileNames, + __in_opt LPSTR pszDirectoryName, + __deref_out_ecount(*pdwcbFileName) LPSTR *pmszFileNames, __out LPDWORD pdwcbFileName, __in DWORD dwFlags) { @@ -2904,9 +2846,9 @@ DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData, DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData, - __in LPSTR pszDirectoryName, + __in_opt LPSTR pszDirectoryName, __in LPSTR pszFileName, - __in PCARD_FILE_INFO pCardFileInfo) + __inout PCARD_FILE_INFO pCardFileInfo) { VENDOR_SPECIFIC *vs = NULL; struct md_directory *dir = NULL; @@ -2932,7 +2874,7 @@ DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData, DWORD WINAPI CardQueryFreeSpace(__in PCARD_DATA pCardData, __in DWORD dwFlags, - __in PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo) + __inout PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo) { VENDOR_SPECIFIC *vs; DWORD dwret; @@ -2963,7 +2905,7 @@ DWORD WINAPI CardQueryFreeSpace(__in PCARD_DATA pCardData, __in DWORD dwFlags, DWORD WINAPI CardQueryKeySizes(__in PCARD_DATA pCardData, __in DWORD dwKeySpec, __in DWORD dwFlags, - __out PCARD_KEY_SIZES pKeySizes) + __inout PCARD_KEY_SIZES pKeySizes) { DWORD dwret; @@ -3178,7 +3120,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, } -DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pInfo) +DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO pInfo) { VENDOR_SPECIFIC *vs; ALG_ID hashAlg; @@ -3384,7 +3326,7 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __in PCARD_SIGNING_INFO pIn } DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData, - __in PCARD_DH_AGREEMENT_INFO pAgreementInfo) + __inout PCARD_DH_AGREEMENT_INFO pAgreementInfo) { logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardConstructDHAgreement - unsupported\n"); @@ -3392,7 +3334,7 @@ DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData, } DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, - __in PCARD_DERIVE_KEY pAgreementInfo) + __inout PCARD_DERIVE_KEY pAgreementInfo) { logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardDeriveKey - unsupported\n"); @@ -3432,9 +3374,9 @@ DWORD WINAPI CardGetChallengeEx(__in PCARD_DATA pCardData, DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, __in PIN_ID PinId, __in DWORD dwFlags, - __in PBYTE pbPinData, + __in_bcount(cbPinData) PBYTE pbPinData, __in DWORD cbPinData, - __deref_out_bcount_opt(*pcbSessionPin) PBYTE *ppbSessionPin, + __deref_opt_out_bcount(*pcbSessionPin) PBYTE *ppbSessionPin, __out_opt PDWORD pcbSessionPin, __out_opt PDWORD pcAttemptsRemaining) { @@ -3444,6 +3386,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, struct sc_pkcs15_object *pin_obj = NULL; struct sc_pkcs15_auth_info *auth_info = NULL; int r; + BOOL DisplayPinpadUI = TRUE; logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardAuthenticateEx\n"); @@ -3463,11 +3406,19 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, return SCARD_E_UNSUPPORTED_FEATURE; } - if (dwFlags && (dwFlags & CARD_PIN_SILENT_CONTEXT) && NULL == pbPinData) + if (dwFlags & ~(CARD_AUTHENTICATE_GENERATE_SESSION_PIN | CARD_AUTHENTICATE_SESSION_PIN | CARD_PIN_SILENT_CONTEXT)) return SCARD_E_INVALID_PARAMETER; - if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD) && NULL == pbPinData) - return SCARD_E_INVALID_PARAMETER; + /* using a pin pad */ + if (NULL == pbPinData) { + if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) + return SCARD_E_INVALID_PARAMETER; + if (dwFlags & CARD_PIN_SILENT_CONTEXT) { + if (!md_is_supports_use_pinpad_in_silent_context(pCardData)) + return SCARD_E_UNSUPPORTED_FEATURE; + DisplayPinpadUI = FALSE; + } + } if (PinId != ROLE_USER) return SCARD_E_INVALID_PARAMETER; @@ -3486,9 +3437,9 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; /* Do we need to display a prompt to enter PIN on pin pad? */ - logprintf(pCardData, 7, "PIN pad=%s, pbPinData=%p, hwndParent=%d\n", + logprintf(pCardData, 7, "PIN pad=%s, pbPinData=%p, hwndParent=%p\n", vs->reader->capabilities & SC_READER_CAP_PIN_PAD ? "yes" : "no", pbPinData, vs->hwndParent); - if ((vs->reader->capabilities & SC_READER_CAP_PIN_PAD) && NULL == pbPinData) { + if (DisplayPinpadUI && NULL == pbPinData) { char buf[200]; if (NULL == vs->wszPinContext ) { strcpy(buf, "Please enter PIN on reader pinpad."); @@ -3953,13 +3904,13 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; vs->hwndParent = cp; } - logprintf(pCardData, 3, "Saved parent window (%u)\n", vs->hwndParent); + logprintf(pCardData, 3, "Saved parent window (%p)\n", vs->hwndParent); return SCARD_S_SUCCESS; } if (wcscmp(CP_PIN_CONTEXT_STRING, wszProperty) == 0) { - vs->wszPinContext = (LPWSTR) pbData; - logprintf(pCardData, 3, "Saved PIN context string: %S\n", pbData); + vs->wszPinContext = (PWSTR) pbData; + logprintf(pCardData, 3, "Saved PIN context string: %S\n", (PWSTR) pbData); return SCARD_S_SUCCESS; } logprintf(pCardData, 3, "INVALID PARAMETER\n"); @@ -4224,7 +4175,7 @@ DWORD WINAPI CardCreateContainerEx( return CardCreateContainer(pCardData, bContainerIndex, dwFlags, dwKeySpec, dwKeySize, pbKeyData); } -DWORD WINAPI CardAcquireContext(IN PCARD_DATA pCardData, __in DWORD dwFlags) +DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags) { VENDOR_SPECIFIC *vs; DWORD dwret, suppliedVersion = 0; @@ -4510,7 +4461,7 @@ BOOL APIENTRY DllMain( HMODULE hModule, break; } - logprintf(NULL,8,"\n********** DllMain Module(handle:0x%X) '%s'; reason='%s'; Reserved=%p; P:%d; T:%d\n", + logprintf(NULL,8,"\n********** DllMain Module(handle:0x%p) '%s'; reason='%s'; Reserved=%p; P:%d; T:%d\n", hModule, name, reason, lpReserved, GetCurrentProcessId(), GetCurrentThreadId()); #endif switch (ul_reason_for_call) From d96e53b102fc73afd11d20b6bd8d372daac38bfe Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 17 Apr 2015 23:02:41 +0200 Subject: [PATCH 252/306] minidriver: better error code if CARD_PIN_SILENT_CONTEXT is set --- src/minidriver/minidriver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 39f00db9..795f9af8 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3415,7 +3415,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; if (dwFlags & CARD_PIN_SILENT_CONTEXT) { if (!md_is_supports_use_pinpad_in_silent_context(pCardData)) - return SCARD_E_UNSUPPORTED_FEATURE; + return NTE_SILENT_CONTEXT; DisplayPinpadUI = FALSE; } } From f3c9525137bcaf4a96576ba63a3d9b21a55875d9 Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 17 Apr 2015 23:04:39 +0200 Subject: [PATCH 253/306] fix attempt remaining regression if the card is blocked --- src/minidriver/minidriver.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 795f9af8..ffe0ed76 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3464,8 +3464,10 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if (r) { logprintf(pCardData, 1, "PIN code verification failed: %s; tries left %i\n", sc_strerror(r), auth_info->tries_left); - if (r == SC_ERROR_AUTH_METHOD_BLOCKED) + if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { + (*pcAttemptsRemaining) = 0; return SCARD_W_CHV_BLOCKED; + } if(pcAttemptsRemaining) (*pcAttemptsRemaining) = auth_info->tries_left; From 659da4f538fcf9d427779f42a0cd598c3076eced Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 18 Apr 2015 15:23:18 +0200 Subject: [PATCH 254/306] minidriver: CardSignData - better parameter checking --- src/minidriver/minidriver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index ffe0ed76..34d02924 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3142,7 +3142,7 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO return SCARD_E_INVALID_PARAMETER; if (pInfo->dwKeySpec != AT_SIGNATURE && pInfo->dwKeySpec != AT_KEYEXCHANGE) return SCARD_E_INVALID_PARAMETER; - if (pInfo->dwSigningFlags & ~(CARD_PADDING_INFO_PRESENT | CARD_PADDING_NONE)) + if (pInfo->dwSigningFlags & ~(CARD_PADDING_INFO_PRESENT | CARD_PADDING_NONE | CARD_BUFFER_SIZE_ONLY | CARD_PADDING_PKCS1 | CARD_PADDING_PSS | CARD_PADDING_OAEP)) return SCARD_E_INVALID_PARAMETER; logprintf(pCardData, 2, "CardSignData dwVersion=%u, bContainerIndex=%u, dwKeySpec=%u, dwSigningFlags=0x%08X, aiHashAlg=0x%08X\n", From a671cf8fe2e4ac2eb824aae395d9bc30fcc655a8 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 18 Apr 2015 15:26:42 +0200 Subject: [PATCH 255/306] CardAuthenticateEx: test for remaining attempts before ... --- src/minidriver/minidriver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 34d02924..6427fcc0 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -3465,7 +3465,8 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, logprintf(pCardData, 1, "PIN code verification failed: %s; tries left %i\n", sc_strerror(r), auth_info->tries_left); if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { - (*pcAttemptsRemaining) = 0; + if(pcAttemptsRemaining) + (*pcAttemptsRemaining) = 0; return SCARD_W_CHV_BLOCKED; } From 6b58b1db01a77754d6cefc39ca0a1f3ffa076869 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 18 Apr 2015 19:09:45 +0200 Subject: [PATCH 256/306] minidriver: merge CardUnblockPin and CardChangeAuthenticator into CardChangeAuthenticatorEx --- src/minidriver/minidriver.c | 207 +++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 86 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 6427fcc0..335cf026 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -2446,11 +2446,6 @@ DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData, __in DWORD cRetryCount, __in DWORD dwFlags) { - VENDOR_SPECIFIC *vs = NULL; - DWORD dw_rv; - struct sc_pkcs15_object *pin_obj = NULL; - int rv; - if(!pCardData) return SCARD_E_INVALID_PARAMETER; @@ -2462,35 +2457,17 @@ DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData, if (wcscmp(wszCARD_USER_USER, pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN,pwszUserId) != 0) return SCARD_E_INVALID_PARAMETER; if (wcscmp(wszCARD_USER_ADMIN, pwszUserId) == 0) - return SCARD_W_WRONG_CHV; + return SCARD_E_UNSUPPORTED_FEATURE; + if (dwFlags & CARD_AUTHENTICATE_PIN_CHALLENGE_RESPONSE) + return SCARD_E_UNSUPPORTED_FEATURE; + if (dwFlags) + return SCARD_E_INVALID_PARAMETER; logprintf(pCardData, 1, "UserID('%S'), AuthData(%p, %u), NewPIN(%p, %u), Retry(%u), dwFlags(0x%X)\n", pwszUserId, pbAuthenticationData, cbAuthenticationData, pbNewPinData, cbNewPinData, cRetryCount, dwFlags); - vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - - if ((!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) && pbAuthenticationData == NULL) - return SCARD_E_INVALID_PARAMETER; - - dw_rv = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj); - if (dw_rv != SCARD_S_SUCCESS) { - logprintf(pCardData, 2, "Cannot get User PIN object"); - return dw_rv; - } - if (!pin_obj) - return SCARD_F_INTERNAL_ERROR; - - rv = sc_pkcs15_unblock_pin(vs->p15card, pin_obj, - pbAuthenticationData, cbAuthenticationData, - pbNewPinData, cbNewPinData); - if (rv) { - logprintf(pCardData, 2, "Failed to unblock User PIN: '%s' (%i)\n", sc_strerror(rv), rv); - return SCARD_F_INTERNAL_ERROR; - } - - logprintf(pCardData, 7, "returns success\n"); - return SCARD_S_SUCCESS; + return CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_UNBLOCK, ROLE_ADMIN, pbAuthenticationData, cbAuthenticationData, ROLE_USER, pbNewPinData, cbNewPinData, cRetryCount, NULL); } @@ -2504,11 +2481,7 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, __in DWORD dwFlags, __out_opt PDWORD pcAttemptsRemaining) { - VENDOR_SPECIFIC *vs = NULL; - DWORD dw_rv; - struct sc_pkcs15_object *pin_obj = NULL; - int rv; - + PIN_ID pinid; if(!pCardData) return SCARD_E_INVALID_PARAMETER; @@ -2518,60 +2491,27 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, if (pwszUserId == NULL) return SCARD_E_INVALID_PARAMETER; - vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - if (!vs) return SCARD_E_INVALID_PARAMETER; - - if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) { - if (pbCurrentAuthenticator == NULL || cbCurrentAuthenticator == 0) { - logprintf(pCardData, 1, "Invalid current PIN data\n"); - return SCARD_E_INVALID_PARAMETER; - } - - if (pbNewAuthenticator == NULL || cbNewAuthenticator == 0) { - logprintf(pCardData, 1, "Invalid new PIN data\n"); - return SCARD_E_INVALID_PARAMETER; - } - } - - if (dwFlags != CARD_AUTHENTICATE_PIN_PIN) { + if (dwFlags == CARD_AUTHENTICATE_PIN_CHALLENGE_RESPONSE) { logprintf(pCardData, 1, "Other then 'authentication' the PIN are not supported\n"); return SCARD_E_UNSUPPORTED_FEATURE; } + else if (dwFlags != CARD_AUTHENTICATE_PIN_PIN){ + return SCARD_E_INVALID_PARAMETER; + } if (wcscmp(wszCARD_USER_USER, pwszUserId) != 0 && wcscmp(wszCARD_USER_ADMIN, pwszUserId) != 0) return SCARD_E_INVALID_PARAMETER; - if(pcAttemptsRemaining) - (*pcAttemptsRemaining) = 0; - logprintf(pCardData, 1, "UserID('%S'), CurrentPIN(%p, %u), NewPIN(%p, %u), Retry(%u), dwFlags(0x%X)\n", pwszUserId, pbCurrentAuthenticator, cbCurrentAuthenticator, pbNewAuthenticator, cbNewAuthenticator, cRetryCount, dwFlags); if (wcscmp(wszCARD_USER_USER, pwszUserId) == 0) - dw_rv = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj); - else if (wcscmp(wszCARD_USER_ADMIN,pwszUserId) == 0) - dw_rv = md_get_pin_by_role(pCardData, ROLE_ADMIN, &pin_obj); + pinid = ROLE_USER; else - return SCARD_F_INTERNAL_ERROR; + pinid = ROLE_ADMIN; - if (dw_rv != SCARD_S_SUCCESS) { - logprintf(pCardData, 2, "Cannot get %S PIN by role", pwszUserId); - return dw_rv; - } - if (!pin_obj) - return SCARD_F_INTERNAL_ERROR; - - rv = sc_pkcs15_change_pin(vs->p15card, pin_obj, - pbCurrentAuthenticator, cbCurrentAuthenticator, - pbNewAuthenticator, cbNewAuthenticator); - if (rv) { - logprintf(pCardData, 2, "Failed to change %S PIN: '%s' (%i)\n", pwszUserId, sc_strerror(rv), rv); - return SCARD_F_INTERNAL_ERROR; - } - - logprintf(pCardData, 7, "returns success\n"); - return SCARD_S_SUCCESS; + return CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_CHANGEPIN, pinid, pbCurrentAuthenticator, cbCurrentAuthenticator, pinid, pbNewAuthenticator, cbNewAuthenticator, cRetryCount, pcAttemptsRemaining); } /* this function is not called on purpose. @@ -3498,20 +3438,32 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, __in DWORD cRetryCount, __out_opt PDWORD pcAttemptsRemaining) { + VENDOR_SPECIFIC *vs = NULL; + DWORD dw_rv; + struct sc_pkcs15_object *pin_obj = NULL; + int rv; + struct sc_pkcs15_auth_info *auth_info; + BOOL DisplayPinpadUI = TRUE; logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); - logprintf(pCardData, 1, "CardAuthenticateEx\n"); + logprintf(pCardData, 1, "CardChangeAuthenticatorEx\n"); if (!pCardData) return SCARD_E_INVALID_PARAMETER; - if (dwFlags != PIN_CHANGE_FLAG_UNBLOCK && dwFlags != PIN_CHANGE_FLAG_CHANGEPIN) + if (!(dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && !(dwFlags & PIN_CHANGE_FLAG_CHANGEPIN)){ + logprintf(pCardData, 1, "Unknown flag\n"); return SCARD_E_INVALID_PARAMETER; - if (dwFlags == PIN_CHANGE_FLAG_UNBLOCK && dwAuthenticatingPinId == dwTargetPinId) + } + if ((dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN)) + return SCARD_E_INVALID_PARAMETER; + if (dwFlags & PIN_CHANGE_FLAG_UNBLOCK && dwAuthenticatingPinId == dwTargetPinId) return SCARD_E_INVALID_PARAMETER; if (dwAuthenticatingPinId != ROLE_USER && dwAuthenticatingPinId != ROLE_ADMIN) return SCARD_E_INVALID_PARAMETER; - if (dwTargetPinId != ROLE_USER && dwTargetPinId != ROLE_ADMIN) + if (dwTargetPinId != ROLE_USER && dwTargetPinId != ROLE_ADMIN) { + logprintf(pCardData, 1, "Only ROLE_USER or ROLE_ADMIN is supported\n"); return SCARD_E_INVALID_PARAMETER; + } /* according to the spec: cRetryCount MUST be zero */ if (cRetryCount) return SCARD_E_INVALID_PARAMETER; @@ -3519,18 +3471,101 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, logprintf(pCardData, 2, "CardChangeAuthenticatorEx: AuthenticatingPinId=%u, dwFlags=0x%08X, cbAuthenticatingPinData=%u, TargetPinId=%u, cbTargetData=%u, Attempts %s\n", dwAuthenticatingPinId, dwFlags, cbAuthenticatingPinData, dwTargetPinId, cbTargetData, pcAttemptsRemaining ? "YES" : "NO"); - if (dwFlags == PIN_CHANGE_FLAG_UNBLOCK) - { - return CardUnblockPin(pCardData, (dwTargetPinId == ROLE_USER ? wszCARD_USER_USER: wszCARD_USER_ADMIN), pbAuthenticatingPinData, cbAuthenticatingPinData, pbTargetData, cbTargetData, cRetryCount, CARD_AUTHENTICATE_PIN_PIN); + + check_reader_status(pCardData); + + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + + if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) { + if (pbAuthenticatingPinData == NULL || cbAuthenticatingPinData == 0) { + logprintf(pCardData, 1, "Invalid current PIN data\n"); + return SCARD_E_INVALID_PARAMETER; + } + + if (pbTargetData == NULL || cbTargetData == 0) { + logprintf(pCardData, 1, "Invalid new PIN data\n"); + return SCARD_E_INVALID_PARAMETER; + } } - else if ( dwFlags == PIN_CHANGE_FLAG_CHANGEPIN) - { - return CardChangeAuthenticator(pCardData, (dwTargetPinId == ROLE_USER ? wszCARD_USER_USER: wszCARD_USER_ADMIN), pbAuthenticatingPinData, cbAuthenticatingPinData, pbTargetData, cbTargetData, cRetryCount, CARD_AUTHENTICATE_PIN_PIN, pcAttemptsRemaining); + /* using a pin pad */ + if (NULL == pbAuthenticatingPinData) { + if (dwFlags & CARD_PIN_SILENT_CONTEXT) { + if (!md_is_supports_use_pinpad_in_silent_context(pCardData)) + return NTE_SILENT_CONTEXT; + DisplayPinpadUI = FALSE; + } } - else - { + + dw_rv = md_get_pin_by_role(pCardData, dwTargetPinId, &pin_obj); + if (dw_rv != SCARD_S_SUCCESS) { + logprintf(pCardData, 2, "Cannot get User PIN object %s", (dwTargetPinId==ROLE_ADMIN?"admin":"user")); + return dw_rv; + } + if (!pin_obj) + return SCARD_F_INTERNAL_ERROR; + + if(pcAttemptsRemaining) + (*pcAttemptsRemaining) = (DWORD) -1; + + if (DisplayPinpadUI && NULL == pbAuthenticatingPinData) { + char buf[200]; + PSTR title = NULL; + if (NULL == vs->wszPinContext ) { + strcpy(buf, "Please enter PIN on reader pinpad."); + } + else { + /* %S enable the use of UNICODE string (wsPinContext) inside an ANSI string (buf) */ + snprintf(buf, sizeof(buf), "Please enter PIN %S", vs->wszPinContext); + } + if (dwFlags & PIN_CHANGE_FLAG_UNBLOCK) { + title = "Unblock PIN - PIN Entry Required"; + } + else { + title = "Change PIN - PIN Entry Required"; + } + logprintf(pCardData, 7, "About to display message box for external PIN verification\n"); + /* @TODO: Ideally, this should probably be a non-modal dialog with just a cancel button + * that goes away as soon as a key is pressed on the pinpad. + */ + rv = MessageBoxA(vs->hwndParent, buf, title, + MB_OKCANCEL | MB_ICONINFORMATION); + if (IDCANCEL == rv) { + logprintf(pCardData, 2, "User canceled PIN verification\n"); + return ERROR_CANCELLED; + } + } + + if (dwFlags & PIN_CHANGE_FLAG_UNBLOCK) { + rv = sc_pkcs15_unblock_pin(vs->p15card, pin_obj, + pbAuthenticatingPinData, cbAuthenticatingPinData, + pbTargetData, cbTargetData); + } + else if ( dwFlags & PIN_CHANGE_FLAG_CHANGEPIN) { + rv = sc_pkcs15_change_pin(vs->p15card, pin_obj, + pbAuthenticatingPinData, cbAuthenticatingPinData, + pbTargetData, cbTargetData); + } + else { return SCARD_E_UNSUPPORTED_FEATURE; } + if (rv) { + logprintf(pCardData, 2, "Failed to %s %s PIN: '%s' (%i)\n", + (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN?"change":"unblock"), + (dwTargetPinId==ROLE_ADMIN?"admin":"user"), sc_strerror(rv), rv); + auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; + if (rv == SC_ERROR_AUTH_METHOD_BLOCKED) { + if(pcAttemptsRemaining) + (*pcAttemptsRemaining) = 0; + return SCARD_W_CHV_BLOCKED; + } + + if(pcAttemptsRemaining) + (*pcAttemptsRemaining) = auth_info->tries_left; + return SCARD_W_WRONG_CHV; + } + + logprintf(pCardData, 7, "returns success\n"); + return SCARD_S_SUCCESS; } DWORD WINAPI CardDeauthenticateEx(__in PCARD_DATA pCardData, From 7d225e28f7474f8837e7de3bde7f707ba7b1f8ad Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 18 Apr 2015 21:43:13 +0200 Subject: [PATCH 257/306] minidriver: add support for the special msroot file which contains the root certificates stored on the card. --- src/minidriver/minidriver.c | 121 ++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 335cf026..3bdf4deb 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -1162,6 +1162,89 @@ md_set_cardid(PCARD_DATA pCardData, struct md_file *file) return SCARD_S_SUCCESS; } +/* fill the msroot file from root certificates */ +static void +md_fs_read_msroot_file(PCARD_DATA pCardData, char *parent, struct md_file *file) +{ + CERT_BLOB dbStore = {0}; + HCERTSTORE hCertStore = NULL; + DWORD dwret = 0; + VENDOR_SPECIFIC *vs; + int rv, ii, cert_num; + struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS]; + + hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, NULL, 0, NULL); + if (!hCertStore) { + dwret = GetLastError(); + goto Ret; + } + + vs = (VENDOR_SPECIFIC *) pCardData->pvVendorSpecific; + + rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_CERT_X509, prkey_objs, MD_MAX_KEY_CONTAINERS); + if (rv < 0) { + logprintf(pCardData, 0, "certificate enumeration failed: %s\n", sc_strerror(rv)); + goto Ret; + } + cert_num = rv; + for(ii = 0; ii < cert_num; ii++) { + struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) prkey_objs[ii]->data; + struct sc_pkcs15_cert *cert = NULL; + PCCERT_CONTEXT wincert = NULL; + if (cert_info->authority) { + rv = sc_pkcs15_read_certificate(vs->p15card, cert_info, &cert); + if(rv) { + logprintf(pCardData, 2, "Cannot read certificate idx:%i: sc-error %d\n", ii, rv); + continue; + } + wincert = CertCreateCertificateContext(X509_ASN_ENCODING, cert->data.value, cert->data.len); + if (wincert) { + CertAddCertificateContextToStore(hCertStore, wincert, CERT_STORE_ADD_REPLACE_EXISTING, NULL); + CertFreeCertificateContext(wincert); + } + else { + logprintf(pCardData, 2, "unable to load the certificate from windows 0x%08X\n", GetLastError()); + } + sc_pkcs15_free_certificate(cert); + } + } + if (FALSE == CertSaveStore( hCertStore, + PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + CERT_STORE_SAVE_AS_PKCS7, + CERT_STORE_SAVE_TO_MEMORY, + &dbStore, + 0)) { + dwret = GetLastError(); + goto Ret; + } + + dbStore.pbData = (PBYTE) pCardData->pfnCspAlloc(dbStore.cbData); + + if (NULL == dbStore.pbData) { + dwret = ERROR_NOT_ENOUGH_MEMORY; + goto Ret; + } + + if (FALSE == CertSaveStore( hCertStore, + PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + CERT_STORE_SAVE_AS_PKCS7, + CERT_STORE_SAVE_TO_MEMORY, + &dbStore, + 0)) + { + dwret = GetLastError(); + goto Ret; + } + file->size = dbStore.cbData; + file->blob = dbStore.pbData; + dbStore.pbData = NULL; +Ret: + if (dbStore.pbData) + pCardData->pfnCspFree(dbStore.pbData); + if (hCertStore) + CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); +} + /* * Return content of the 'soft' file. */ @@ -1215,6 +1298,9 @@ md_fs_read_content(PCARD_DATA pCardData, char *parent, struct md_file *file) CopyMemory(file->blob, cert->data.value, cert->data.len); sc_pkcs15_free_certificate(cert); } + if (!strcmp(file->name, "msroot")) { + md_fs_read_msroot_file(pCardData, parent, file); + } } else { return; @@ -1316,6 +1402,37 @@ md_set_cardapps(PCARD_DATA pCardData, struct md_file *file) return SCARD_S_SUCCESS; } +/* check if the card has root certificates. If yes, notify the base csp by creating the msroot file */ +static DWORD +md_fs_add_msroot(PCARD_DATA pCardData, struct md_file **head) +{ + VENDOR_SPECIFIC *vs; + int rv, ii, cert_num; + DWORD dwret; + struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS]; + if (!pCardData || !head) + return SCARD_E_INVALID_PARAMETER; + + vs = (VENDOR_SPECIFIC *) pCardData->pvVendorSpecific; + + rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_CERT_X509, prkey_objs, MD_MAX_KEY_CONTAINERS); + if (rv < 0) { + logprintf(pCardData, 0, "certificate enumeration failed: %s\n", sc_strerror(rv)); + return SCARD_S_SUCCESS; + } + cert_num = rv; + for(ii = 0; ii < cert_num; ii++) { + struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) prkey_objs[ii]->data; + if (cert_info->authority) { + dwret = md_fs_add_file(pCardData, head, "msroot", EveryoneReadUserWriteAc, NULL, 0, NULL); + if (dwret != SCARD_S_SUCCESS) + return dwret; + return SCARD_S_SUCCESS; + } + } + return SCARD_S_SUCCESS; +} + /* * Set the content of the 'soft' 'cmapfile': * 1. Initialize internal p15_contaniers with the existing private keys PKCS#15 objects; @@ -1503,6 +1620,10 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) loghex(pCardData, 7, (PBYTE) (p+ii), sizeof(CONTAINER_MAP_RECORD)); } } + + dwret = md_fs_add_msroot(pCardData, &(file->next)); + if (dwret != SCARD_S_SUCCESS) + return dwret; dwret = md_fs_set_content(pCardData, file, cmap_buf, cmap_len); pCardData->pfnCspFree(cmap_buf); From 6127fe6b779227070c9a1f37feb2f6168832ed5e Mon Sep 17 00:00:00 2001 From: vletoux Date: Sun, 19 Apr 2015 19:51:22 +0200 Subject: [PATCH 258/306] minidriver: change the UI (remplace a messagebox by a nice dialog) ; add a translation function for errors --- src/minidriver/minidriver.c | 340 ++++++++++++++------ src/minidriver/versioninfo-minidriver.rc.in | 15 + 2 files changed, 250 insertions(+), 105 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 3bdf4deb..e0877fbd 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -56,6 +56,9 @@ #include "cardmod-mingw-compat.h" #endif +/* store the instance given at DllMain when attached to access internal resources */ +HINSTANCE g_inst; + #define MD_MINIMUM_VERSION_SUPPORTED 4 #define MD_CURRENT_VERSION_SUPPORTED 7 @@ -100,6 +103,12 @@ #define SCARD_F_UNKNOWN_ERROR 0x80100014L #endif + /* defined twice: in versioninfo-minidriver.rc.in and in minidriver.c */ +#define IDD_PINPAD 101 +#define IDC_PINPAD_TEXT 1001 +#define IDC_PINPAD_ICON 1000 + + struct md_directory { unsigned char parent[9]; unsigned char name[9]; @@ -173,7 +182,6 @@ typedef struct _VENDOR_SPECIFIC #define MD_STATIC_FLAG_CREATE_CONTAINER_KEY_IMPORT 32 #define MD_STATIC_FLAG_CREATE_CONTAINER_KEY_GEN 64 #define MD_STATIC_FLAG_IGNORE_PIN_LENGTH 128 -#define MD_STATIC_FLAG_ALLOW_PINPAD_IF_SILENT_CONTEXT 256 #define MD_STATIC_PROCESS_ATTACHED 0xA11AC4EDL struct md_opensc_static_data { @@ -486,13 +494,6 @@ md_is_supports_container_key_import(PCARD_DATA pCardData) return md_get_config_bool(pCardData, "md_supports_container_key_import", MD_STATIC_FLAG_CREATE_CONTAINER_KEY_IMPORT, TRUE); } -/* Get know if the minidriver can request a pin from the pinpad if the minidriver can't display a UI - typically windows smart card logon*/ -static BOOL -md_is_supports_use_pinpad_in_silent_context(PCARD_DATA pCardData) -{ - logprintf(pCardData, 2, "Can the minidriver request a pin from the pinpad if the minidriver can't display a UI?\n"); - return md_get_config_bool(pCardData, "md_supports_pinpad_in_silent_context", MD_STATIC_FLAG_ALLOW_PINPAD_IF_SILENT_CONTEXT, FALSE); -} /* Check if specified PIN has been verified */ static BOOL @@ -2185,6 +2186,211 @@ md_query_key_sizes(CARD_KEY_SIZES *pKeySizes) return SCARD_S_SUCCESS; } +static VOID CenterWindow(HWND hwndWindow, HWND hwndParent) +{ + RECT rectWindow, rectParent; + int nWidth,nHeight, nScreenWidth, nScreenHeight; + int nX, nY; + GetWindowRect(hwndWindow, &rectWindow); + + nWidth = rectWindow.right - rectWindow.left; + nHeight = rectWindow.bottom - rectWindow.top; + + nScreenWidth = GetSystemMetrics(SM_CXSCREEN); + nScreenHeight = GetSystemMetrics(SM_CYSCREEN); + + // make the window relative to its parent + if (hwndParent != NULL) { + GetWindowRect(hwndParent, &rectParent); + nX = ((rectParent.right - rectParent.left) - nWidth) / 2 + rectParent.left; + nY = ((rectParent.bottom - rectParent.top) - nHeight) / 2 + rectParent.top; + } + else { + nX = (nScreenWidth - nWidth) /2; + nY = (nScreenHeight - nHeight) /2; + } + // make sure that the dialog box never moves outside of the screen + if (nX < 0) nX = 0; + if (nY < 0) nY = 0; + if (nX + nWidth > nScreenWidth) nX = nScreenWidth - nWidth; + if (nY + nHeight > nScreenHeight) nY = nScreenHeight - nHeight; + + MoveWindow(hwndWindow, nX, nY, nWidth, nHeight, TRUE); +} + + +static DWORD WINAPI +md_dialog_perform_pin_operation_thread(PVOID lpParameter) +{ + /* unstack the parameters */ + LONG_PTR* parameter = (LONG_PTR*) lpParameter; + int operation = parameter[0]; + struct sc_pkcs15_card *p15card = (struct sc_pkcs15_card *) parameter[1]; + struct sc_pkcs15_object *pin_obj = (struct sc_pkcs15_object *) parameter[2]; + const u8 *pin1 = (const u8 *) parameter[3]; + size_t pin1len = parameter[4]; + const u8 *pin2 = (const u8 *) parameter[5]; + size_t pin2len = parameter[6]; + int rv = 0; + switch (operation) + { + case SC_PIN_CMD_VERIFY: + rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin1, pin1len); + break; + case SC_PIN_CMD_CHANGE: + rv = sc_pkcs15_change_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len); + break; + case SC_PIN_CMD_UNBLOCK: + rv = sc_pkcs15_unblock_pin(p15card, pin_obj, pin1, pin1len,pin2, pin2len); + break; + default: + rv = (DWORD) ERROR_INVALID_PARAMETER; + break; + } + if (parameter[9] != 0) { + EndDialog((HWND) parameter[9], rv); + } + return (DWORD) rv; +} + +static INT_PTR CALLBACK md_dialog_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + switch (message) + { + case WM_INITDIALOG: + { + HICON hIcon = NULL; + PCARD_DATA pCardData = (PCARD_DATA) (((LONG_PTR*)lParam)[7]); + VENDOR_SPECIFIC* vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific; + /* store parameter like pCardData for further use if needed */ + SetWindowLongPtr(hWnd, GWLP_USERDATA, lParam); + /* change the text shown on the screen */ + if (vs->wszPinContext ) { + SetWindowTextW(GetDlgItem(hWnd, IDC_PINPAD_TEXT), vs->wszPinContext ); + } + CenterWindow(hWnd, vs->hwndParent); + /* load the information icon */ + hIcon = (HICON) LoadImage(0, IDI_INFORMATION, IMAGE_ICON, 0, 0, LR_SHARED); + SendMessage(GetDlgItem(hWnd, IDC_PINPAD_ICON),STM_SETIMAGE,IMAGE_ICON, (LPARAM) hIcon); + /* launch the function in another thread context store the thread handle */ + ((LONG_PTR*)lParam)[9] = (LONG_PTR) hWnd; + ((LONG_PTR*)lParam)[8] = (LONG_PTR) CreateThread(NULL, 0, md_dialog_perform_pin_operation_thread, (PVOID) lParam, 0, NULL); + } + return TRUE; + case WM_DESTROY: + { + /* clean resources used */ + LPARAM param = GetWindowLongPtr(hWnd, GWLP_USERDATA); + if (param) { + HANDLE hThread = (HANDLE)((LONG_PTR*)param)[8]; + CloseHandle(hThread); + } + } + break; + } + return FALSE; +} + + + +static int +md_dialog_perform_pin_operation(PCARD_DATA pCardData, int operation, struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *pin_obj, + const u8 *pin1, size_t pin1len, + const u8 *pin2, size_t pin2len, BOOL displayUI) +{ + LONG_PTR parameter[10]; + INT_PTR result = 0; + HWND hWndDlg = 0; + int rv = 0; + VENDOR_SPECIFIC* pv = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + /* stack the parameters */ + parameter[0] = (LONG_PTR)operation; + parameter[1] = (LONG_PTR)p15card; + parameter[2] = (LONG_PTR)pin_obj; + parameter[3] = (LONG_PTR)pin1; + parameter[4] = (LONG_PTR)pin1len; + parameter[5] = (LONG_PTR)pin2; + parameter[6] = (LONG_PTR)pin2len; + parameter[7] = (LONG_PTR)pCardData; + parameter[8] = 0; /* place holder for thread handle */ + parameter[9] = 0; /* place holder for window handle */ + /* launch the function to perform in the same thread context */ + if (!displayUI) { + rv = md_dialog_perform_pin_operation_thread(parameter); + SecureZeroMemory(parameter, sizeof(parameter)); + return rv; + } + /* launch the UI in the same thread context than the parent and the function to perform in another thread context + this is the only way to display a modal dialog attached to a parent (hwndParent != 0) */ + result = DialogBoxParam(g_inst, MAKEINTRESOURCE(IDD_PINPAD), pv->hwndParent, md_dialog_proc, (LPARAM) parameter); + SecureZeroMemory(parameter, sizeof(parameter)); + return result; +} + +DWORD md_translate_OpenSC_to_Windows_error(int OpenSCerror, DWORD dwDefaulCode) +{ + switch(OpenSCerror) + { + /* Errors related to reader operation */ + case SC_ERROR_READER: + return SCARD_E_PROTO_MISMATCH; + case SC_ERROR_NO_READERS_FOUND: + return SCARD_E_NO_READERS_AVAILABLE; + case SC_ERROR_CARD_NOT_PRESENT: + return SCARD_E_NO_SMARTCARD; + case SC_ERROR_TRANSMIT_FAILED: + return SCARD_E_NOT_TRANSACTED; + case SC_ERROR_CARD_REMOVED: + return SCARD_W_REMOVED_CARD; + case SC_ERROR_CARD_RESET: + return SCARD_W_RESET_CARD; + case SC_ERROR_KEYPAD_CANCELLED: + return SCARD_W_CANCELLED_BY_USER; + case SC_ERROR_KEYPAD_MSG_TOO_LONG: + return SCARD_W_CARD_NOT_AUTHENTICATED; + case SC_ERROR_KEYPAD_PIN_MISMATCH: + return SCARD_E_INVALID_CHV; + case SC_ERROR_KEYPAD_TIMEOUT: + return ERROR_TIMEOUT; + case SC_ERROR_EVENT_TIMEOUT: + return SCARD_E_TIMEOUT; + case SC_ERROR_CARD_UNRESPONSIVE: + return SCARD_W_UNRESPONSIVE_CARD; + case SC_ERROR_READER_LOCKED: + return SCARD_E_SHARING_VIOLATION; + + /* Resulting from a card command or related to the card*/ + case SC_ERROR_INCORRECT_PARAMETERS: + return SCARD_E_INVALID_PARAMETER; + case SC_ERROR_MEMORY_FAILURE: + case SC_ERROR_NOT_ENOUGH_MEMORY: + return SCARD_E_NO_MEMORY; + case SC_ERROR_NOT_ALLOWED: + return SCARD_W_SECURITY_VIOLATION; + case SC_ERROR_AUTH_METHOD_BLOCKED: + return SCARD_W_CHV_BLOCKED; + case SC_ERROR_PIN_CODE_INCORRECT: + return SCARD_W_WRONG_CHV; + + /* Returned by OpenSC library when called with invalid arguments */ + case SC_ERROR_BUFFER_TOO_SMALL: + return NTE_BUFFER_TOO_SMALL; + + /* Resulting from OpenSC internal operation */ + case SC_ERROR_INTERNAL: + return ERROR_INTERNAL_ERROR; + case SC_ERROR_NOT_SUPPORTED: + return SCARD_E_UNSUPPORTED_FEATURE; + case SC_ERROR_NOT_IMPLEMENTED: + return ERROR_CALL_NOT_IMPLEMENTED; + + default: + return dwDefaulCode; + } +} + DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) { VENDOR_SPECIFIC *vs = NULL; @@ -2496,7 +2702,7 @@ DWORD WINAPI CardAuthenticatePin(__in PCARD_DATA pCardData, if (pbPin == NULL) return SCARD_E_INVALID_PARAMETER; - return CardAuthenticateEx(pCardData, PinId, 0, pbPin, cbPin, NULL, NULL, pcAttemptsRemaining); + return CardAuthenticateEx(pCardData, PinId, CARD_PIN_SILENT_CONTEXT, pbPin, cbPin, NULL, NULL, pcAttemptsRemaining); } @@ -2588,7 +2794,7 @@ DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData, pwszUserId, pbAuthenticationData, cbAuthenticationData, pbNewPinData, cbNewPinData, cRetryCount, dwFlags); - return CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_UNBLOCK, ROLE_ADMIN, pbAuthenticationData, cbAuthenticationData, ROLE_USER, pbNewPinData, cbNewPinData, cRetryCount, NULL); + return CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_UNBLOCK | CARD_PIN_SILENT_CONTEXT, ROLE_ADMIN, pbAuthenticationData, cbAuthenticationData, ROLE_USER, pbNewPinData, cbNewPinData, cRetryCount, NULL); } @@ -2632,7 +2838,7 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, else pinid = ROLE_ADMIN; - return CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_CHANGEPIN, pinid, pbCurrentAuthenticator, cbCurrentAuthenticator, pinid, pbNewAuthenticator, cbNewAuthenticator, cRetryCount, pcAttemptsRemaining); + return CardChangeAuthenticatorEx(pCardData, PIN_CHANGE_FLAG_CHANGEPIN | CARD_PIN_SILENT_CONTEXT, pinid, pbCurrentAuthenticator, cbCurrentAuthenticator, pinid, pbNewAuthenticator, cbNewAuthenticator, cRetryCount, pcAttemptsRemaining); } /* this function is not called on purpose. @@ -3157,15 +3363,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r)); pCardData->pfnCspFree(pbuf); pCardData->pfnCspFree(pbuf2); - switch (r) - { - case SC_ERROR_NOT_ALLOWED: - return SCARD_W_SECURITY_VIOLATION; - case SC_ERROR_NOT_SUPPORTED: - return SCARD_E_UNSUPPORTED_FEATURE; - default: - return SCARD_E_INVALID_VALUE; - } + return md_translate_OpenSC_to_Windows_error(r, SCARD_E_INVALID_VALUE); } logprintf(pCardData, 2, "decrypted data(%i):\n", pInfo->cbData); @@ -3358,15 +3556,7 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO if(r < 0) { logprintf(pCardData, 2, "sc_pkcs15_compute_signature erreur %s\n", sc_strerror(r)); pCardData->pfnCspFree(pbuf); - switch (r) - { - case SC_ERROR_NOT_SUPPORTED: - return SCARD_E_UNSUPPORTED_FEATURE; - case SC_ERROR_NOT_ALLOWED: - return SCARD_W_SECURITY_VIOLATION; - default: - return SCARD_F_INTERNAL_ERROR; - } + return md_translate_OpenSC_to_Windows_error(r, SCARD_F_INTERNAL_ERROR); } pInfo->cbSignedData = r; @@ -3447,7 +3637,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, struct sc_pkcs15_object *pin_obj = NULL; struct sc_pkcs15_auth_info *auth_info = NULL; int r; - BOOL DisplayPinpadUI = TRUE; + BOOL DisplayPinpadUI = FALSE; logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardAuthenticateEx\n"); @@ -3474,10 +3664,8 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if (NULL == pbPinData) { if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) return SCARD_E_INVALID_PARAMETER; - if (dwFlags & CARD_PIN_SILENT_CONTEXT) { - if (!md_is_supports_use_pinpad_in_silent_context(pCardData)) - return NTE_SILENT_CONTEXT; - DisplayPinpadUI = FALSE; + if (!(dwFlags & CARD_PIN_SILENT_CONTEXT)) { + DisplayPinpadUI = TRUE; } } @@ -3500,28 +3688,9 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, /* Do we need to display a prompt to enter PIN on pin pad? */ logprintf(pCardData, 7, "PIN pad=%s, pbPinData=%p, hwndParent=%p\n", vs->reader->capabilities & SC_READER_CAP_PIN_PAD ? "yes" : "no", pbPinData, vs->hwndParent); - if (DisplayPinpadUI && NULL == pbPinData) { - char buf[200]; - if (NULL == vs->wszPinContext ) { - strcpy(buf, "Please enter PIN on reader pinpad."); - } - else { - /* %S enable the use of UNICODE string (wsPinContext) inside an ANSI string (buf) */ - snprintf(buf, sizeof(buf), "Please enter PIN %S", vs->wszPinContext); - } - logprintf(pCardData, 7, "About to display message box for external PIN verification\n"); - /* @TODO: Ideally, this should probably be a non-modal dialog with just a cancel button - * that goes away as soon as a key is pressed on the pinpad. - */ - r = MessageBoxA(vs->hwndParent, buf, "PIN Entry Required", - MB_OKCANCEL | MB_ICONINFORMATION); - if (IDCANCEL == r) { - logprintf(pCardData, 2, "User canceled PIN verification\n"); - return ERROR_CANCELLED; - } - } - r = sc_pkcs15_verify_pin(vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData); + r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, 0, DisplayPinpadUI); + if (r) { logprintf(pCardData, 1, "PIN code verification failed: %s; tries left %i\n", sc_strerror(r), auth_info->tries_left); @@ -3533,7 +3702,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if(pcAttemptsRemaining) (*pcAttemptsRemaining) = auth_info->tries_left; - return SCARD_W_WRONG_CHV; + return md_translate_OpenSC_to_Windows_error(r, SCARD_W_WRONG_CHV); } logprintf(pCardData, 2, "Pin code correct.\n"); @@ -3564,7 +3733,7 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, struct sc_pkcs15_object *pin_obj = NULL; int rv; struct sc_pkcs15_auth_info *auth_info; - BOOL DisplayPinpadUI = TRUE; + BOOL DisplayPinpadUI = FALSE; logprintf(pCardData, 1, "\nP:%d T:%d pCardData:%p ",GetCurrentProcessId(), GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardChangeAuthenticatorEx\n"); @@ -3610,10 +3779,8 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, } /* using a pin pad */ if (NULL == pbAuthenticatingPinData) { - if (dwFlags & CARD_PIN_SILENT_CONTEXT) { - if (!md_is_supports_use_pinpad_in_silent_context(pCardData)) - return NTE_SILENT_CONTEXT; - DisplayPinpadUI = FALSE; + if (!(dwFlags & CARD_PIN_SILENT_CONTEXT)) { + DisplayPinpadUI = TRUE; } } @@ -3628,47 +3795,9 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, if(pcAttemptsRemaining) (*pcAttemptsRemaining) = (DWORD) -1; - if (DisplayPinpadUI && NULL == pbAuthenticatingPinData) { - char buf[200]; - PSTR title = NULL; - if (NULL == vs->wszPinContext ) { - strcpy(buf, "Please enter PIN on reader pinpad."); - } - else { - /* %S enable the use of UNICODE string (wsPinContext) inside an ANSI string (buf) */ - snprintf(buf, sizeof(buf), "Please enter PIN %S", vs->wszPinContext); - } - if (dwFlags & PIN_CHANGE_FLAG_UNBLOCK) { - title = "Unblock PIN - PIN Entry Required"; - } - else { - title = "Change PIN - PIN Entry Required"; - } - logprintf(pCardData, 7, "About to display message box for external PIN verification\n"); - /* @TODO: Ideally, this should probably be a non-modal dialog with just a cancel button - * that goes away as soon as a key is pressed on the pinpad. - */ - rv = MessageBoxA(vs->hwndParent, buf, title, - MB_OKCANCEL | MB_ICONINFORMATION); - if (IDCANCEL == rv) { - logprintf(pCardData, 2, "User canceled PIN verification\n"); - return ERROR_CANCELLED; - } - } - - if (dwFlags & PIN_CHANGE_FLAG_UNBLOCK) { - rv = sc_pkcs15_unblock_pin(vs->p15card, pin_obj, - pbAuthenticatingPinData, cbAuthenticatingPinData, - pbTargetData, cbTargetData); - } - else if ( dwFlags & PIN_CHANGE_FLAG_CHANGEPIN) { - rv = sc_pkcs15_change_pin(vs->p15card, pin_obj, - pbAuthenticatingPinData, cbAuthenticatingPinData, - pbTargetData, cbTargetData); - } - else { - return SCARD_E_UNSUPPORTED_FEATURE; - } + rv = md_dialog_perform_pin_operation(pCardData, (dwFlags & PIN_CHANGE_FLAG_UNBLOCK ? SC_PIN_CMD_UNBLOCK:SC_PIN_CMD_CHANGE), + vs->p15card, pin_obj, (const u8 *) pbAuthenticatingPinData, cbAuthenticatingPinData, pbTargetData, cbTargetData, DisplayPinpadUI); + if (rv) { logprintf(pCardData, 2, "Failed to %s %s PIN: '%s' (%i)\n", (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN?"change":"unblock"), @@ -3682,7 +3811,7 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, if(pcAttemptsRemaining) (*pcAttemptsRemaining) = auth_info->tries_left; - return SCARD_W_WRONG_CHV; + return md_translate_OpenSC_to_Windows_error(rv, SCARD_W_WRONG_CHV); } logprintf(pCardData, 7, "returns success\n"); @@ -4594,7 +4723,7 @@ static int disassociate_card(PCARD_DATA pCardData) } -BOOL APIENTRY DllMain( HMODULE hModule, +BOOL APIENTRY DllMain( HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved ) @@ -4621,11 +4750,12 @@ BOOL APIENTRY DllMain( HMODULE hModule, } logprintf(NULL,8,"\n********** DllMain Module(handle:0x%p) '%s'; reason='%s'; Reserved=%p; P:%d; T:%d\n", - hModule, name, reason, lpReserved, GetCurrentProcessId(), GetCurrentThreadId()); + hinstDLL, name, reason, lpReserved, GetCurrentProcessId(), GetCurrentThreadId()); #endif switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: + g_inst = hinstDLL; md_static_data.attach_check = MD_STATIC_PROCESS_ATTACHED; break; case DLL_PROCESS_DETACH: diff --git a/src/minidriver/versioninfo-minidriver.rc.in b/src/minidriver/versioninfo-minidriver.rc.in index cc02a9a0..cff733b9 100644 --- a/src/minidriver/versioninfo-minidriver.rc.in +++ b/src/minidriver/versioninfo-minidriver.rc.in @@ -1,5 +1,10 @@ #include +/* defined twice: in versioninfo-minidriver.rc.in and in minidriver.c */ +#define IDD_PINPAD 101 +#define IDC_PINPAD_TEXT 1001 +#define IDC_PINPAD_ICON 1000 + VS_VERSION_INFO VERSIONINFO FILEVERSION @OPENSC_VERSION_MAJOR@,@OPENSC_VERSION_MINOR@,@OPENSC_VERSION_FIX@,@OPENSC_VERSION_REVISION@ PRODUCTVERSION @OPENSC_VERSION_MAJOR@,@OPENSC_VERSION_MINOR@,@OPENSC_VERSION_FIX@,@OPENSC_VERSION_REVISION@ @@ -36,3 +41,13 @@ BEGIN END END +IDD_PINPAD DIALOGEX 0, 0, 309, 71 +STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +CAPTION "PIN Entry Required" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Please enter PIN on PINPAD",IDC_STATIC,46,9,256,31 + ICON "",IDC_PINPAD_ICON,6,11,20,20 + LTEXT "This window will be closed automatically after the PIN has been submitted on the PINPAD or if the PINPAD timeout occurs (in general 30 seconds).",IDC_STATIC,7,46,298,19 +END + From 33cf1619413c88f491d6ff5db2359b81faa2914b Mon Sep 17 00:00:00 2001 From: vletoux Date: Mon, 20 Apr 2015 23:25:57 +0200 Subject: [PATCH 259/306] minidriver: pinpad authentication is now working for smart card logon !!! (still needs 5 pinpad entries) minidriver: minor fixes --- src/minidriver/minidriver.c | 23 +++++++++++++++++++++ src/minidriver/versioninfo-minidriver.rc.in | 1 + 2 files changed, 24 insertions(+) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index e0877fbd..637e38ab 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -108,6 +108,8 @@ HINSTANCE g_inst; #define IDC_PINPAD_TEXT 1001 #define IDC_PINPAD_ICON 1000 +/* magic to determine previous pinpad authentication */ +#define MAGIC_SESSION_PIN "opensc-minidriver" struct md_directory { unsigned char parent[9]; @@ -2375,6 +2377,8 @@ DWORD md_translate_OpenSC_to_Windows_error(int OpenSCerror, DWORD dwDefaulCode) return SCARD_W_WRONG_CHV; /* Returned by OpenSC library when called with invalid arguments */ + case SC_ERROR_INVALID_ARGUMENTS: + return ERROR_INVALID_PARAMETER; case SC_ERROR_BUFFER_TOO_SMALL: return NTE_BUFFER_TOO_SMALL; @@ -3689,6 +3693,12 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, logprintf(pCardData, 7, "PIN pad=%s, pbPinData=%p, hwndParent=%p\n", vs->reader->capabilities & SC_READER_CAP_PIN_PAD ? "yes" : "no", pbPinData, vs->hwndParent); + /* check if the pin is the session pin generated by a previous authentication with a pinpad */ + if (pbPinData != NULL && cbPinData == sizeof(MAGIC_SESSION_PIN) && memcmp(MAGIC_SESSION_PIN, pbPinData, sizeof(MAGIC_SESSION_PIN)) == 0) { + pbPinData = NULL; + cbPinData = 0; + } + r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_VERIFY, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, NULL, 0, DisplayPinpadUI); if (r) { @@ -3707,6 +3717,19 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, logprintf(pCardData, 2, "Pin code correct.\n"); + /* set the session pin according to the minidriver specification */ + if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN && (vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) { + /* we set it to a special value for pinpad authentication to force a new pinpad authentication */ + if (pcbSessionPin) *pcbSessionPin = sizeof(MAGIC_SESSION_PIN); + if (ppbSessionPin) { + *ppbSessionPin = pCardData->pfnCspAlloc(sizeof(MAGIC_SESSION_PIN)); + if (ppbSessionPin) memcpy(*ppbSessionPin, MAGIC_SESSION_PIN, sizeof(MAGIC_SESSION_PIN)); + } + } else { + if (pcbSessionPin) *pcbSessionPin = 0; + if (ppbSessionPin) *ppbSessionPin = NULL; + } + dwret = md_get_cardcf(pCardData, &cardcf); if (dwret != SCARD_S_SUCCESS) return dwret; diff --git a/src/minidriver/versioninfo-minidriver.rc.in b/src/minidriver/versioninfo-minidriver.rc.in index cff733b9..a86e2b53 100644 --- a/src/minidriver/versioninfo-minidriver.rc.in +++ b/src/minidriver/versioninfo-minidriver.rc.in @@ -1,5 +1,6 @@ #include +#define IDC_STATIC -1 /* defined twice: in versioninfo-minidriver.rc.in and in minidriver.c */ #define IDD_PINPAD 101 #define IDC_PINPAD_TEXT 1001 From 017d98f87f5061116f0a48ba37f2c98b391aee8e Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 24 Apr 2015 14:46:24 +0200 Subject: [PATCH 260/306] trying to fix image path when compiling --- win32/OpenSC.wxs.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index 37992774..469b5814 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -33,8 +33,8 @@ - - + + From 5a1ca44c11e463b5ac6fe16c529f2266358ea589 Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 24 Apr 2015 15:58:54 +0200 Subject: [PATCH 261/306] custom action skeleton (without actions) - help welcome ... --- win32/Make.rules.mak | 18 ++++++++++- win32/Makefile.am | 22 +++++++++++-- win32/Makefile.mak | 9 +++++- win32/OpenSC.wxs.in | 4 +-- win32/customactions.c | 63 +++++++++++++++++++++++++++++++++++++ win32/customactions.exports | 0 6 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 win32/customactions.c create mode 100644 win32/customactions.exports diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index 316988cf..58408dff 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -6,10 +6,26 @@ MINIDRIVER_DEF = /DENABLE_MINIDRIVER #Build MSI with the Windows Installer XML (WIX) toolkit, requires WIX >= 3.6 !IF "$(BUILD_ON)" == "WIN64" WIX_PATH = "C:\Program Files (x86)\Windows Installer XML v3.6" +WIX_INCL_DIR = "/IC:\Program Files (x86)\Windows Installer XML v3.6\SDK\VS2010\inc" +!IF "$(BUILD_FOR)" == "WIN64" +WIX_LIB = "C:\Program Files (x86)\Windows Installer XML v3.6\SDK\VS2010\lib\x64" +!ELSE +WIX_LIB = "C:\Program Files (x86)\Windows Installer XML v3.6\SDK\VS2010\lib\x86" +!ENDIF + !ELSE WIX_PATH = "C:\Program Files\Windows Installer XML v3.6" +WIX_INCL_DIR = "/IC:\Program Files\Windows Installer XML v3.6\SDK\VS2010\inc" +!IF "$(BUILD_FOR)" == "WIN64" +WIX_LIB = "C:\Program Files\Windows Installer XML v3.6\SDK\VS2010\lib\x64" +!ELSE +WIX_LIB = "C:\Program Files\Windows Installer XML v3.6\SDK\VS2010\lib\x86" !ENDIF +!ENDIF + + + #Include support for Secure Messaging SM_DEF = /DENABLE_SM @@ -67,7 +83,7 @@ CNGSDK_INCL_DIR = "/IC:\Program Files\Microsoft CNG Development Kit\Include" # O1 - minimal code size CODE_OPTIMIZATION = /O1 -ALL_INCLUDES = /I$(TOPDIR)\win32 /I$(TOPDIR)\src $(OPENSSL_INCL_DIR) $(ZLIB_INCL_DIR) $(LIBLTDL_INCL) $(INTTYPES_INCL_DIR) $(CNGSDK_INCL_DIR) +ALL_INCLUDES = /I$(TOPDIR)\win32 /I$(TOPDIR)\src $(OPENSSL_INCL_DIR) $(ZLIB_INCL_DIR) $(LIBLTDL_INCL) $(INTTYPES_INCL_DIR) $(CNGSDK_INCL_DIR) $(WIX_INCL_DIR) !IF "$(DEBUG_DEF)" == "/DDEBUG" LINKDEBUGFLAGS = /NODEFAULTLIB:LIBCMT /DEBUG diff --git a/win32/Makefile.am b/win32/Makefile.am index c42d7be6..e2fc7397 100644 --- a/win32/Makefile.am +++ b/win32/Makefile.am @@ -1,9 +1,27 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in $(srcdir)/versioninfo.rc $(srcdir)/winconfig.h \ - $(srcdir)/OpenSC.iss $(srcdir)/OpenSC.wxs $(srcdir)/OpenSC.ico $(srcdir)/license.rtf + $(srcdir)/OpenSC.iss $(srcdir)/OpenSC.wxs $(srcdir)/OpenSC.ico $(srcdir)/license.rtf \ + $(srcdir)/dlgbmp.bmp $(srcdir)/bannrbmp.bmp EXTRA_DIST = ltrc.inc Makefile.mak Make.rules.mak opensc-install.bat \ versioninfo.rc.in winconfig.h.in OpenSC.iss.in OpenSC.wxs.in -dist_noinst_HEADERS = versioninfo.rc winconfig.h OpenSC.iss OpenSC.wxs license.rtf OpenSC.ico +dist_noinst_HEADERS = versioninfo.rc winconfig.h OpenSC.iss OpenSC.wxs license.rtf OpenSC.ico dlgbmp.bmp bannrbmp.bmp if WIN32 sbin_SCRIPTS = opensc-install.bat endif + +if ENABLE_MINIDRIVER +lib_LTLIBRARIES = customactions@LIBRARY_BITNESS@.la + +AM_CPPFLAGS = -I$(top_srcdir) + + +customactions@LIBRARY_BITNESS@_la_SOURCES = customactions.c customactions.exports +customactions@LIBRARY_BITNESS@_la_LIBADD = \ + $(top_builddir)/win32/customactions.la +customactions@LIBRARY_BITNESS@_la_LDFLAGS = $(AM_LDFLAGS) \ + -export-symbols "$(srcdir)/customactions.exports" \ + -module -avoid-version -no-undefined + +install-exec-hook: + mv "$(DESTDIR)$(libdir)/customactions@LIBRARY_BITNESS@.dll" "$(DESTDIR)$(bindir)/" +endif diff --git a/win32/Makefile.mak b/win32/Makefile.mak index f3be55bd..64645691 100644 --- a/win32/Makefile.mak +++ b/win32/Makefile.mak @@ -7,10 +7,17 @@ all: config.h config.h: winconfig.h copy /y winconfig.h config.h +customactions.dll: customactions.obj + echo LIBRARY $* > $*.def + echo EXPORTS >> $*.def + type customactions.exports >> $*.def + link /dll $(LINKFLAGS) /def:$*.def /out:customactions.dll customactions.obj msi.lib $(WIX_LIB)\dutil.lib $(WIX_LIB)\wcautil.lib + + OpenSC.msi: OpenSC.wixobj $(WIX_PATH)\bin\light.exe -sh -ext WixUIExtension -ext WiXUtilExtension $? -OpenSC.wixobj: OpenSC.wxs +OpenSC.wixobj: OpenSC.wxs customactions.dll $(WIX_PATH)\bin\candle.exe -ext WiXUtilExtension -dSOURCE_DIR=$(TOPDIR) $(CANDLEFLAGS) $? clean:: diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index 469b5814..37992774 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -33,8 +33,8 @@ - - + + diff --git a/win32/customactions.c b/win32/customactions.c new file mode 100644 index 00000000..f47aac84 --- /dev/null +++ b/win32/customactions.c @@ -0,0 +1,63 @@ +/* + * opensc-setup-custom-action.c: OpenSC setup custom action + * + * Copyright (C) 2015 vincent.letoux@mysmartlogon.com + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This module requires the WIX SDK to build. + */ + +#include "config.h" +#ifdef ENABLE_MINIDRIVER + +#ifdef _MANAGED +#pragma managed(push, off) +#endif + +#include +#include + +#include + +// WiX Header Files: +#include + +// first version - do nothing - see if it can compile + +// DllMain - Initialize and cleanup WiX custom action utils. +BOOL APIENTRY DllMain( + __in HINSTANCE hInst, + __in ULONG ulReason, + __in LPVOID + ) +{ + switch(ulReason) + { + case DLL_PROCESS_ATTACH: + WcaGlobalInitialize(hInst); + break; + + case DLL_PROCESS_DETACH: + WcaGlobalFinalize(); + break; + } + + return TRUE; +} + +#endif \ No newline at end of file diff --git a/win32/customactions.exports b/win32/customactions.exports new file mode 100644 index 00000000..e69de29b From 9e07a75968a3d829a072c12aa0c6b128bbec3310 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 25 Apr 2015 15:03:39 +0200 Subject: [PATCH 262/306] detect the wix components installed on the build machine --- configure.ac | 2 ++ win32/Make.rules.mak | 12 ++++++------ win32/Makefile.am | 2 +- win32/Makefile.mak | 5 ++--- win32/{customactions.c => customactions.cpp} | 4 ++++ 5 files changed, 15 insertions(+), 10 deletions(-) rename win32/{customactions.c => customactions.cpp} (95%) diff --git a/configure.ac b/configure.ac index a39e7284..09494768 100644 --- a/configure.ac +++ b/configure.ac @@ -52,6 +52,8 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_CANONICAL_HOST AC_PROG_CC +# AC_PROG_CXX is needed to built the win32 custom action. Indeed dutil.h use [extern "C"] definition which fails on pure c compiler +AC_PROG_CXX PKG_PROG_PKG_CONFIG AC_C_BIGENDIAN diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index 58408dff..84d71fed 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -6,20 +6,20 @@ MINIDRIVER_DEF = /DENABLE_MINIDRIVER #Build MSI with the Windows Installer XML (WIX) toolkit, requires WIX >= 3.6 !IF "$(BUILD_ON)" == "WIN64" WIX_PATH = "C:\Program Files (x86)\Windows Installer XML v3.6" -WIX_INCL_DIR = "/IC:\Program Files (x86)\Windows Installer XML v3.6\SDK\VS2010\inc" +WIX_INCL_DIR = "/IC:\Program Files (x86)\Windows Installer XML v3.6\SDK\inc" !IF "$(BUILD_FOR)" == "WIN64" -WIX_LIB = "C:\Program Files (x86)\Windows Installer XML v3.6\SDK\VS2010\lib\x64" +WIX_LIBS = "C:\Program Files (x86)\Windows Installer XML v3.6\SDK\lib\dutil_2010_x64.lib" "C:\Program Files (x86)\Windows Installer XML v3.6\SDK\lib\wcautil_2010_x64.lib" !ELSE -WIX_LIB = "C:\Program Files (x86)\Windows Installer XML v3.6\SDK\VS2010\lib\x86" +WIX_LIBS = "C:\Program Files (x86)\Windows Installer XML v3.6\SDK\lib\dutil_2010.lib" "C:\Program Files (x86)\Windows Installer XML v3.6\SDK\lib\wcautil_2010.lib" !ENDIF !ELSE WIX_PATH = "C:\Program Files\Windows Installer XML v3.6" -WIX_INCL_DIR = "/IC:\Program Files\Windows Installer XML v3.6\SDK\VS2010\inc" +WIX_INCL_DIR = "/IC:\Program Files\Windows Installer XML v3.6\SDK\inc" !IF "$(BUILD_FOR)" == "WIN64" -WIX_LIB = "C:\Program Files\Windows Installer XML v3.6\SDK\VS2010\lib\x64" +WIX_LIBS = "C:\Program Files\Windows Installer XML v3.6\SDK\lib\dutil_2010_x64.lib" "C:\Program Files\Windows Installer XML v3.6\SDK\lib\wcautil_2010_x64.lib" !ELSE -WIX_LIB = "C:\Program Files\Windows Installer XML v3.6\SDK\VS2010\lib\x86" +WIX_LIBS = "C:\Program Files\Windows Installer XML v3.6\SDK\lib\dutil_2010.lib" "C:\Program Files\Windows Installer XML v3.6\SDK\lib\wcautil_2010.lib" !ENDIF !ENDIF diff --git a/win32/Makefile.am b/win32/Makefile.am index e2fc7397..9723a35a 100644 --- a/win32/Makefile.am +++ b/win32/Makefile.am @@ -15,7 +15,7 @@ lib_LTLIBRARIES = customactions@LIBRARY_BITNESS@.la AM_CPPFLAGS = -I$(top_srcdir) -customactions@LIBRARY_BITNESS@_la_SOURCES = customactions.c customactions.exports +customactions@LIBRARY_BITNESS@_la_SOURCES = customactions.cpp customactions.exports customactions@LIBRARY_BITNESS@_la_LIBADD = \ $(top_builddir)/win32/customactions.la customactions@LIBRARY_BITNESS@_la_LDFLAGS = $(AM_LDFLAGS) \ diff --git a/win32/Makefile.mak b/win32/Makefile.mak index 64645691..c062d5c8 100644 --- a/win32/Makefile.mak +++ b/win32/Makefile.mak @@ -11,14 +11,13 @@ customactions.dll: customactions.obj echo LIBRARY $* > $*.def echo EXPORTS >> $*.def type customactions.exports >> $*.def - link /dll $(LINKFLAGS) /def:$*.def /out:customactions.dll customactions.obj msi.lib $(WIX_LIB)\dutil.lib $(WIX_LIB)\wcautil.lib - + link /dll $(LINKFLAGS) /def:$*.def /out:customactions.dll customactions.obj msi.lib $(WIX_LIBS) OpenSC.msi: OpenSC.wixobj $(WIX_PATH)\bin\light.exe -sh -ext WixUIExtension -ext WiXUtilExtension $? OpenSC.wixobj: OpenSC.wxs customactions.dll - $(WIX_PATH)\bin\candle.exe -ext WiXUtilExtension -dSOURCE_DIR=$(TOPDIR) $(CANDLEFLAGS) $? + $(WIX_PATH)\bin\candle.exe -ext WiXUtilExtension -dSOURCE_DIR=$(TOPDIR) $(CANDLEFLAGS) OpenSC.wxs clean:: del /Q config.h *.msi *.wixobj *.wixpdb diff --git a/win32/customactions.c b/win32/customactions.cpp similarity index 95% rename from win32/customactions.c rename to win32/customactions.cpp index f47aac84..55bda9cb 100644 --- a/win32/customactions.c +++ b/win32/customactions.cpp @@ -33,6 +33,10 @@ #include #include +#include +#include + +#include // WiX Header Files: #include From 0b683472b0749b45c14c181c22b1e86f0775dc64 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 25 Apr 2015 17:04:17 +0200 Subject: [PATCH 263/306] win32 setup: add basic minidriver card registration and unregistration via a custom action --- win32/Make.rules.mak | 3 + win32/Makefile.mak | 2 +- win32/OpenSC.wxs.in | 38 +++++++ win32/customactions.cpp | 191 +++++++++++++++++++++++++++++++++++- win32/customactions.exports | 2 + 5 files changed, 233 insertions(+), 3 deletions(-) diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index 84d71fed..e13eae2f 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -107,6 +107,9 @@ CANDLEFLAGS = -dPlatform=x86 .c.obj:: cl $(CODE_OPTIMIZATION) $(COPTS) /c $< +.cpp.obj:: + cl $(CODE_OPTIMIZATION) $(COPTS) /c $< + .rc.res:: rc /l 0x0409 $< diff --git a/win32/Makefile.mak b/win32/Makefile.mak index c062d5c8..f4d580fd 100644 --- a/win32/Makefile.mak +++ b/win32/Makefile.mak @@ -11,7 +11,7 @@ customactions.dll: customactions.obj echo LIBRARY $* > $*.def echo EXPORTS >> $*.def type customactions.exports >> $*.def - link /dll $(LINKFLAGS) /def:$*.def /out:customactions.dll customactions.obj msi.lib $(WIX_LIBS) + link /dll $(LINKFLAGS) /def:$*.def /out:customactions.dll customactions.obj msi.lib $(WIX_LIBS) Advapi32.lib User32.lib Version.lib Shell32.lib OpenSC.msi: OpenSC.wixobj $(WIX_PATH)\bin\light.exe -sh -ext WixUIExtension -ext WiXUtilExtension $? diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index 37992774..f70faa68 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -44,6 +44,10 @@ + + + + @@ -56,6 +60,23 @@ + + + + + + + + @@ -81,6 +102,7 @@ + @@ -216,6 +238,7 @@ + @@ -260,5 +283,20 @@ + + + + + + + + + + + + + + + diff --git a/win32/customactions.cpp b/win32/customactions.cpp index 55bda9cb..7e5e2de4 100644 --- a/win32/customactions.cpp +++ b/win32/customactions.cpp @@ -41,7 +41,184 @@ // WiX Header Files: #include -// first version - do nothing - see if it can compile +#define X86onX64_SC_DATABASE TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\Cryptography\\Calais\\SmartCards") +#define SC_DATABASE TEXT("SOFTWARE\\Microsoft\\Cryptography\\Calais\\SmartCards") +#define BASE_CSP TEXT("OpenSC CSP") +#define BASE_KSP TEXT("Microsoft Smart Card Key Storage Provider") + +typedef struct _MD_REGISTRATION +{ + TCHAR szName[256]; + BYTE pbAtr[256]; + DWORD dwAtrSize; + BYTE pbAtrMask[256]; +} MD_REGISTRATION, *PMD_REGISTRATION; + +/* note: we could have added the minidriver registration data directly in OpenSC.wxs but coding it allows for more checks. +For example, do not uninstall the minidriver for a card if a middleware is already installed */ + +MD_REGISTRATION minidriver_registration[] = { + /* from minidriver-feitian.reg */ + {TEXT("ePass2003"), {0x3b,0x9f,0x95,0x81,0x31,0xfe,0x9f,0x00,0x66,0x46,0x53,0x05,0x01,0x00,0x11,0x71,0xdf,0x00,0x00,0x03,0x6a,0x82,0xf8}, + 23, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("FTCOS/PK-01C"), {0x3b,0x9f,0x95,0x81,0x31,0xfe,0x9f,0x00,0x65,0x46,0x53,0x05,0x00,0x06,0x71,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 23, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00}}, + /* from minidriver-sc-hsm.reg */ + {TEXT("SmartCard-HSM"), {0x3b,0xfe,0x18,0x00,0x00,0x81,0x31,0xfe,0x45,0x80,0x31,0x81,0x54,0x48,0x53,0x4d,0x31,0x73,0x80,0x21,0x40,0x81,0x07,0xfa}, + 24, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("SmartCard-HSM-CL"), {0x3B,0x8E,0x80,0x01,0x80,0x31,0x81,0x54,0x48,0x53,0x4D,0x31,0x73,0x80,0x21,0x40,0x81,0x07,0x18}, + 19, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + /* from minidriver-westcos.reg */ + {TEXT("CEV WESTCOS"), {0x3f,0x69,0x00,0x00,0x00,0x64,0x01,0x00,0x00,0x00,0x80,0x90,0x00}, + 13, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xf0,0xff,0xff}}, + /* from card-openpgp.c */ + {TEXT("OpenPGP card v1.0/1.1"), {0x3b,0xfa,0x13,0x00,0xff,0x81,0x31,0x80,0x45,0x00,0x31,0xc1,0x73,0xc0,0x01,0x00,0x00,0x90,0x00,0xb1}, + 20, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("CryptoStick v1.2 (OpenPGP v2.0)"), {0x3b,0xda,0x18,0xff,0x81,0xb1,0xfe,0x75,0x1f,0x03,0x00,0x31,0xc5,0x73,0xc0,0x01,0x40,0x00,0x90,0x00,0x0c}, + 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, +}; + + +/* remove a card in the database if and only if the CSP match the OpenSC CSP +The program try to avoid any failure to not break the uninstall process */ +VOID RemoveKey(PTSTR szSubKey) +{ + HKEY hKey = NULL; + LONG lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_READ, &hKey); + + if (lResult != ERROR_SUCCESS) + { + WcaLog(LOGMSG_STANDARD, "RegOpenKeyEx %S 0x%08X", szSubKey, lResult); + return; + } + TCHAR szName[MAX_PATH]; + DWORD dwSize = MAX_PATH; + FILETIME ftWrite; + lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, + NULL, NULL, &ftWrite); + + if (lResult == ERROR_SUCCESS) + { + DWORD dwIndex = 0; + do { + HKEY hTempKey = NULL; + dwIndex++; + lResult = RegOpenKeyEx (hKey, szName, 0, KEY_READ, &hTempKey); + if (lResult == ERROR_SUCCESS) + { + TCHAR szCSP[MAX_PATH] = {0}; + dwSize = MAX_PATH; + lResult = RegQueryValueEx(hTempKey, TEXT("Crypto Provider"), NULL, NULL, (PBYTE) szCSP, &dwSize); + RegCloseKey(hTempKey); + if (lResult == ERROR_SUCCESS) + { + if ( _tcsstr(szCSP, TEXT("OpenSC CSP")) != 0) + { + lResult = RegDeleteKey(hKey, szName); + if (lResult != ERROR_SUCCESS) + { + WcaLog(LOGMSG_STANDARD, "RegDeleteKey %S 0x%08X", szName, lResult); + } + else + { + dwIndex--; + } + } + } + else + { + WcaLog(LOGMSG_STANDARD, "RegQueryValueEx %S 0x%08X", szName, lResult); + } + } + dwSize = MAX_PATH; + lResult = RegEnumKeyEx(hKey,dwIndex, szName, &dwSize, NULL, + NULL, NULL, &ftWrite); + + } while (lResult == ERROR_SUCCESS); + } + RegCloseKey(hKey); +} + +UINT WINAPI RemoveSmartCardConfiguration(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + + hr = WcaInitialize(hInstall, "RemoveSmartCardConfiguration"); + ExitOnFailure(hr, "Failed to initialize"); + + WcaLog(LOGMSG_STANDARD, "Initialized."); + + /* clean a smart card database. As today the x64 setup doesn't handle x86 installation on x64 machine */ + RemoveKey(SC_DATABASE); + /* when this happens, just uncomment the following line: +#ifdef _M_X64 + RemoveKey(X86onX64_SC_DATABASE); +#endif + */ + + /* never fails or only if the msi uninstall didn't work. If the uninstall custom action trigger a failure, the user is unable to uninstall the software */ +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +/* note: szKey is here in case the card has to be registered in the Calais and WOW3264node\Calais databases */ +void RegisterCardWithKey(PTSTR szKey, PTSTR szCard, PTSTR szPath, PBYTE pbATR, DWORD dwATRSize, PBYTE pbAtrMask) +{ + HKEY hKey = NULL; + HKEY hTempKey = NULL; + LONG lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey); + + if (lResult != ERROR_SUCCESS) + { + WcaLog(LOGMSG_STANDARD, "unable to open the calais database."); + return; + } + lResult = RegCreateKeyEx(hKey, szCard, 0,NULL,0,KEY_WRITE, NULL,&hTempKey,NULL); + if(!lResult) + { + RegSetValueEx( hTempKey,TEXT("Crypto Provider"),0, REG_SZ, (PBYTE)BASE_CSP,sizeof(BASE_CSP) - sizeof(TCHAR)); + RegSetValueEx( hTempKey,TEXT("Smart Card Key Storage Provider"),0, REG_SZ, (PBYTE)BASE_KSP,sizeof(BASE_KSP) - sizeof(TCHAR)); + RegSetValueEx( hTempKey,TEXT("80000001"),0, REG_SZ, (PBYTE)szPath,(DWORD) (sizeof(TCHAR) * _tcslen(szPath))); + RegSetValueEx( hTempKey,TEXT("ATR"),0, REG_BINARY, (PBYTE)pbATR, dwATRSize); + RegSetValueEx( hTempKey,TEXT("ATRMask"),0, REG_BINARY, (PBYTE)pbAtrMask, dwATRSize); + RegCloseKey(hTempKey); + } + else + { + WcaLog(LOGMSG_STANDARD, "unable to create the card entry"); + } + RegCloseKey(hKey); +} + +VOID RegisterSmartCard(PMD_REGISTRATION registration) +{ + RegisterCardWithKey(SC_DATABASE, registration->szName, TEXT("opensc-minidriver.dll"),registration->pbAtr, registration->dwAtrSize, registration->pbAtrMask ); + +} + +UINT WINAPI AddSmartCardConfiguration(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + int i ; + + hr = WcaInitialize(hInstall, "AddSmartCardConfiguration"); + ExitOnFailure(hr, "Failed to initialize"); + + WcaLog(LOGMSG_STANDARD, "Initialized."); + + for (i = 0; i < sizeof(minidriver_registration) / sizeof(MD_REGISTRATION); i++) + { + RegisterSmartCard(minidriver_registration + i); + } + + /* never fails or only if the msi install functions didn't work. If the install custom action trigger a failure, the user is unable to install the software */ +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} // DllMain - Initialize and cleanup WiX custom action utils. BOOL APIENTRY DllMain( @@ -63,5 +240,15 @@ BOOL APIENTRY DllMain( return TRUE; } +#else -#endif \ No newline at end of file +UINT WINAPI AddSmartCardConfiguration(unsigned long hInstall) +{ + return 0; +} + +UINT WINAPI RemoveSmartCardConfiguration(unsigned long hInstall) +{ + return 0; +} +#endif diff --git a/win32/customactions.exports b/win32/customactions.exports index e69de29b..614fd3cf 100644 --- a/win32/customactions.exports +++ b/win32/customactions.exports @@ -0,0 +1,2 @@ +AddSmartCardConfiguration +RemoveSmartCardConfiguration From 2f6d1b5c9783fcd52d73881baa61e5d2a895862b Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 25 Apr 2015 19:30:31 +0200 Subject: [PATCH 264/306] avoid the failure: "Failed to get file version of custom action dll" --- configure.ac | 1 + win32/Makefile.am | 8 +++--- win32/Makefile.mak | 6 ++--- win32/versioninfo-customactions.rc.in | 37 +++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 win32/versioninfo-customactions.rc.in diff --git a/configure.ac b/configure.ac index 09494768..941b534f 100644 --- a/configure.ac +++ b/configure.ac @@ -736,6 +736,7 @@ AC_CONFIG_FILES([ src/minidriver/opensc-minidriver.inf win32/Makefile win32/versioninfo.rc + win32/versioninfo-customactions.rc win32/winconfig.h win32/OpenSC.iss win32/OpenSC.wxs diff --git a/win32/Makefile.am b/win32/Makefile.am index 9723a35a..8bdb1df1 100644 --- a/win32/Makefile.am +++ b/win32/Makefile.am @@ -1,8 +1,10 @@ +include $(top_srcdir)/win32/ltrc.inc + MAINTAINERCLEANFILES = $(srcdir)/Makefile.in $(srcdir)/versioninfo.rc $(srcdir)/winconfig.h \ $(srcdir)/OpenSC.iss $(srcdir)/OpenSC.wxs $(srcdir)/OpenSC.ico $(srcdir)/license.rtf \ - $(srcdir)/dlgbmp.bmp $(srcdir)/bannrbmp.bmp + $(srcdir)/dlgbmp.bmp $(srcdir)/bannrbmp.bmp $(srcdir)/versioninfo-customactions.rc EXTRA_DIST = ltrc.inc Makefile.mak Make.rules.mak opensc-install.bat \ - versioninfo.rc.in winconfig.h.in OpenSC.iss.in OpenSC.wxs.in + versioninfo.rc.in winconfig.h.in OpenSC.iss.in OpenSC.wxs.in versioninfo-customactions.rc.in dist_noinst_HEADERS = versioninfo.rc winconfig.h OpenSC.iss OpenSC.wxs license.rtf OpenSC.ico dlgbmp.bmp bannrbmp.bmp if WIN32 @@ -15,7 +17,7 @@ lib_LTLIBRARIES = customactions@LIBRARY_BITNESS@.la AM_CPPFLAGS = -I$(top_srcdir) -customactions@LIBRARY_BITNESS@_la_SOURCES = customactions.cpp customactions.exports +customactions@LIBRARY_BITNESS@_la_SOURCES = customactions.cpp customactions.exports versioninfo-customactions.rc customactions@LIBRARY_BITNESS@_la_LIBADD = \ $(top_builddir)/win32/customactions.la customactions@LIBRARY_BITNESS@_la_LDFLAGS = $(AM_LDFLAGS) \ diff --git a/win32/Makefile.mak b/win32/Makefile.mak index f4d580fd..465e2f44 100644 --- a/win32/Makefile.mak +++ b/win32/Makefile.mak @@ -2,16 +2,16 @@ TOPDIR = .. !INCLUDE $(TOPDIR)\win32\Make.rules.mak -all: config.h +all: versioninfo-customactions.res config.h config.h: winconfig.h copy /y winconfig.h config.h -customactions.dll: customactions.obj +customactions.dll: versioninfo-customactions.res customactions.obj echo LIBRARY $* > $*.def echo EXPORTS >> $*.def type customactions.exports >> $*.def - link /dll $(LINKFLAGS) /def:$*.def /out:customactions.dll customactions.obj msi.lib $(WIX_LIBS) Advapi32.lib User32.lib Version.lib Shell32.lib + link /dll $(LINKFLAGS) /def:$*.def /out:customactions.dll versioninfo-customactions.res customactions.obj msi.lib $(WIX_LIBS) Advapi32.lib User32.lib Version.lib Shell32.lib OpenSC.msi: OpenSC.wixobj $(WIX_PATH)\bin\light.exe -sh -ext WixUIExtension -ext WiXUtilExtension $? diff --git a/win32/versioninfo-customactions.rc.in b/win32/versioninfo-customactions.rc.in new file mode 100644 index 00000000..757e9165 --- /dev/null +++ b/win32/versioninfo-customactions.rc.in @@ -0,0 +1,37 @@ +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @OPENSC_VERSION_MAJOR@,@OPENSC_VERSION_MINOR@,@OPENSC_VERSION_FIX@,@OPENSC_VERSION_REVISION@ + PRODUCTVERSION @OPENSC_VERSION_MAJOR@,@OPENSC_VERSION_MINOR@,@OPENSC_VERSION_FIX@,@OPENSC_VERSION_REVISION@ + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x21L +#else + FILEFLAGS 0x20L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "@OPENSC_VS_FF_COMMENTS@" + VALUE "CompanyName", "@OPENSC_VS_FF_COMPANY_NAME@" + VALUE "FileVersion", "@OPENSC_VERSION_MAJOR@.@OPENSC_VERSION_MINOR@.@OPENSC_VERSION_FIX@.@OPENSC_VERSION_REVISION@" + VALUE "InternalName", "@PACKAGE_NAME@" + VALUE "LegalCopyright", "@OPENSC_VS_FF_LEGAL_COPYRIGHT@" + VALUE "LegalTrademarks", "" + VALUE "PrivateBuild", "" + VALUE "ProductName", "@OPENSC_VS_FF_PRODUCT_NAME@" + VALUE "ProductVersion", "@OPENSC_VERSION_MAJOR@,@OPENSC_VERSION_MINOR@,@OPENSC_VERSION_FIX@,@OPENSC_VERSION_REVISION@" + VALUE "SpecialBuild", "" + VALUE "FileDescription", "OpenSC custom actions setup" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END From aede9b164beeb35cba493f3e00bb2136c455ee44 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 25 Apr 2015 23:29:03 +0200 Subject: [PATCH 265/306] minidriver: fix compilation warnings on x64 (size_t <> DWORD) --- src/minidriver/minidriver.c | 49 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 637e38ab..ddc5f6e6 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -1,4 +1,4 @@ -/* +/* * minidriver.c: OpenSC minidriver * * Copyright (C) 2009,2010 francois.leblanc@cev-sa.com @@ -140,7 +140,7 @@ struct md_pkcs15_container { struct sc_pkcs15_id id; char guid[MAX_CONTAINER_NAME_LEN + 1]; unsigned flags; - unsigned size_key_exchange, size_sign; + size_t size_key_exchange, size_sign; struct sc_pkcs15_object *cert_obj, *prkey_obj, *pubkey_obj; }; @@ -261,7 +261,7 @@ static void logprintf(PCARD_DATA pCardData, int level, _Printf_format_string_ co va_end(arg); } -static void loghex(PCARD_DATA pCardData, int level, PBYTE data, int len) +static void loghex(PCARD_DATA pCardData, int level, PBYTE data, size_t len) { char line[74]; char *c; @@ -917,7 +917,7 @@ md_pkcs15_update_containers(PCARD_DATA pCardData, unsigned char *blob, size_t si vs = pCardData->pvVendorSpecific; - nn_records = size/sizeof(CONTAINER_MAP_RECORD); + nn_records = (int) size/sizeof(CONTAINER_MAP_RECORD); if (nn_records > MD_MAX_KEY_CONTAINERS) nn_records = MD_MAX_KEY_CONTAINERS; @@ -969,7 +969,7 @@ md_pkcs15_update_container_from_do(PCARD_DATA pCardData, struct sc_pkcs15_object } id.len = *(ddata->data + offs++); memcpy(id.value, ddata->data + offs, id.len); - offs += id.len; + offs += (int) id.len; if (*(ddata->data + offs++) != 0x02) { sc_pkcs15_free_data_object(ddata); @@ -1176,7 +1176,7 @@ md_fs_read_msroot_file(PCARD_DATA pCardData, char *parent, struct md_file *file) int rv, ii, cert_num; struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS]; - hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, NULL, 0, NULL); + hCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, (HCRYPTPROV_LEGACY) NULL, 0, NULL); if (!hCertStore) { dwret = GetLastError(); goto Ret; @@ -1200,7 +1200,7 @@ md_fs_read_msroot_file(PCARD_DATA pCardData, char *parent, struct md_file *file) logprintf(pCardData, 2, "Cannot read certificate idx:%i: sc-error %d\n", ii, rv); continue; } - wincert = CertCreateCertificateContext(X509_ASN_ENCODING, cert->data.value, cert->data.len); + wincert = CertCreateCertificateContext(X509_ASN_ENCODING, cert->data.value, (DWORD) cert->data.len); if (wincert) { CertAddCertificateContextToStore(hCertStore, wincert, CERT_STORE_ADD_REPLACE_EXISTING, NULL); CertFreeCertificateContext(wincert); @@ -1598,8 +1598,8 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) mbstowcs((p+ii)->wszGuid, vs->p15_containers[ii].guid, MAX_CONTAINER_NAME_LEN + 1); (p+ii)->bFlags = vs->p15_containers[ii].flags; - (p+ii)->wSigKeySizeBits = vs->p15_containers[ii].size_sign; - (p+ii)->wKeyExchangeKeySizeBits = vs->p15_containers[ii].size_key_exchange; + (p+ii)->wSigKeySizeBits = (WORD) vs->p15_containers[ii].size_sign; + (p+ii)->wKeyExchangeKeySizeBits = (WORD) vs->p15_containers[ii].size_key_exchange; if (vs->p15_containers[ii].cert_obj) { char k_name[6]; @@ -1858,7 +1858,8 @@ md_pkcs15_generate_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, DWORD ke memset(&pub_args, 0, sizeof(pub_args)); memset(&keygen_args, 0, sizeof(keygen_args)); - keygen_args.prkey_args.label = keygen_args.pubkey_label = "TODO: key label"; + keygen_args.prkey_args.label = "TODO: key label"; + keygen_args.pubkey_label = "TODO: key label"; if (key_type == AT_SIGNATURE) { keygen_args.prkey_args.key.algorithm = SC_ALGORITHM_RSA; @@ -2226,7 +2227,7 @@ md_dialog_perform_pin_operation_thread(PVOID lpParameter) { /* unstack the parameters */ LONG_PTR* parameter = (LONG_PTR*) lpParameter; - int operation = parameter[0]; + int operation = (int) parameter[0]; struct sc_pkcs15_card *p15card = (struct sc_pkcs15_card *) parameter[1]; struct sc_pkcs15_object *pin_obj = (struct sc_pkcs15_object *) parameter[2]; const u8 *pin1 = (const u8 *) parameter[3]; @@ -2328,7 +2329,7 @@ md_dialog_perform_pin_operation(PCARD_DATA pCardData, int operation, struct sc_p this is the only way to display a modal dialog attached to a parent (hwndParent != 0) */ result = DialogBoxParam(g_inst, MAKEINTRESOURCE(IDD_PINPAD), pv->hwndParent, md_dialog_proc, (LPARAM) parameter); SecureZeroMemory(parameter, sizeof(parameter)); - return result; + return (int) result; } DWORD md_translate_OpenSC_to_Windows_error(int OpenSCerror, DWORD dwDefaulCode) @@ -2647,7 +2648,7 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine if (pubkey_der.len && pubkey_der.value) { sz = 0; /* get size */ CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, - pubkey_der.value, pubkey_der.len, 0, NULL, &sz); + pubkey_der.value, (DWORD) pubkey_der.len, 0, NULL, &sz); if (cont->size_sign) { PUBKEYSTRUCT_BASE *oh = (PUBKEYSTRUCT_BASE *)pCardData->pfnCspAlloc(sz); @@ -2655,7 +2656,7 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine return SCARD_E_NO_MEMORY; CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, - pubkey_der.value, pubkey_der.len, 0, oh, &sz); + pubkey_der.value, (DWORD) pubkey_der.len, 0, oh, &sz); oh->publickeystruc.aiKeyAlg = CALG_RSA_SIGN; pContainerInfo->cbSigPublicKey = sz; @@ -2670,7 +2671,7 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine return SCARD_E_NO_MEMORY; CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, - pubkey_der.value, pubkey_der.len, 0, oh, &sz); + pubkey_der.value, (DWORD) pubkey_der.len, 0, oh, &sz); oh->publickeystruc.aiKeyAlg = CALG_RSA_KEYX; pContainerInfo->cbKeyExPublicKey = sz; @@ -2974,7 +2975,7 @@ DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData, *ppbData = pCardData->pfnCspAlloc(file->size); if(!*ppbData) return SCARD_E_NO_MEMORY; - *pcbData = file->size; + *pcbData = (DWORD) file->size; memcpy(*ppbData, file->blob, file->size); logprintf(pCardData, 7, "returns '%s' content:\n", NULLSTR(pszFileName)); @@ -3111,7 +3112,7 @@ DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData, return SCARD_E_NO_MEMORY; CopyMemory(*pmszFileNames, mstr, offs); - *pdwcbFileName = offs; + *pdwcbFileName = (DWORD) offs; return SCARD_S_SUCCESS; } @@ -3137,7 +3138,7 @@ DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData, } pCardFileInfo->dwVersion = CARD_FILE_INFO_CURRENT_VERSION; - pCardFileInfo->cbFileSize = file->size; + pCardFileInfo->cbFileSize = (DWORD) file->size; pCardFileInfo->AccessCondition = file->acl; return SCARD_S_SUCCESS; @@ -3281,7 +3282,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, loghex(pCardData, 7, pbuf, pInfo->cbData); prkey_info = (struct sc_pkcs15_prkey_info *)(pkey->data); - alg_info = sc_card_find_rsa_alg(vs->p15card->card, prkey_info->modulus_length); + alg_info = sc_card_find_rsa_alg(vs->p15card->card, (unsigned int) prkey_info->modulus_length); if (!alg_info) { logprintf(pCardData, 2, "Cannot get appropriate RSA card algorithm for key size %i\n", prkey_info->modulus_length); pCardData->pfnCspFree(pbuf); @@ -3309,8 +3310,10 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) { logprintf(pCardData, 2, "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%u\n", pInfo->dwVersion); if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) { + size_t temp = pInfo->cbData; logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n"); - r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &pInfo->cbData); + r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &temp); + pInfo->cbData = (DWORD) temp; if (r < 0) { logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r); pCardData->pfnCspFree(pbuf); @@ -3532,7 +3535,7 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO } opt_crypt_flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE; - pInfo->cbSignedData = prkey_info->modulus_length / 8; + pInfo->cbSignedData = (DWORD) prkey_info->modulus_length / 8; logprintf(pCardData, 3, "pInfo->cbSignedData = %d\n", pInfo->cbSignedData); if(!(pInfo->dwSigningFlags&CARD_BUFFER_SIZE_ONLY)) { @@ -4038,7 +4041,7 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, } if (pdwDataLen) - *pdwDataLen = cardid->size; + *pdwDataLen = (DWORD) cardid->size; if (cbData < cardid->size) return ERROR_INSUFFICIENT_BUFFER; @@ -4058,7 +4061,7 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, } if (pdwDataLen) - *pdwDataLen = buf_len; + *pdwDataLen = (DWORD) buf_len; if (cbData < buf_len) return ERROR_INSUFFICIENT_BUFFER; From ac82a96ccc7cd2ef54d5d1cbc1fa7a32aee582ee Mon Sep 17 00:00:00 2001 From: vletoux Date: Sun, 26 Apr 2015 19:54:09 +0200 Subject: [PATCH 266/306] minidriver: add my name in the author list setup: change the url to match the new one --- src/minidriver/minidriver.c | 1 + win32/OpenSC.wxs.in | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index ddc5f6e6..b2f8c725 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -2,6 +2,7 @@ * minidriver.c: OpenSC minidriver * * Copyright (C) 2009,2010 francois.leblanc@cev-sa.com + * Copyright (C) 2015 vincent.letoux@mysmartlogon.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index f70faa68..6adfa316 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -23,7 +23,7 @@ Manufacturer="OpenSC Project"> - + From 8ec000e80d500d4b993f74465442cc509e1c90cb Mon Sep 17 00:00:00 2001 From: vletoux Date: Sat, 2 May 2015 23:44:05 +0200 Subject: [PATCH 267/306] minidriver: change the icon of the pinpad dialog --- src/minidriver/minidriver.c | 8 ++++++++ src/minidriver/versioninfo-minidriver.rc.in | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index b2f8c725..183592cb 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -106,6 +106,7 @@ HINSTANCE g_inst; /* defined twice: in versioninfo-minidriver.rc.in and in minidriver.c */ #define IDD_PINPAD 101 +#define IDI_LOGO 102 #define IDC_PINPAD_TEXT 1001 #define IDC_PINPAD_ICON 1000 @@ -2277,6 +2278,13 @@ static INT_PTR CALLBACK md_dialog_proc(HWND hWnd, UINT message, WPARAM wParam, L /* load the information icon */ hIcon = (HICON) LoadImage(0, IDI_INFORMATION, IMAGE_ICON, 0, 0, LR_SHARED); SendMessage(GetDlgItem(hWnd, IDC_PINPAD_ICON),STM_SETIMAGE,IMAGE_ICON, (LPARAM) hIcon); + /* change the icon */ + hIcon = LoadIcon(g_inst, MAKEINTRESOURCE(IDI_LOGO)); + if (hIcon) + { + SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIcon); + SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); + } /* launch the function in another thread context store the thread handle */ ((LONG_PTR*)lParam)[9] = (LONG_PTR) hWnd; ((LONG_PTR*)lParam)[8] = (LONG_PTR) CreateThread(NULL, 0, md_dialog_perform_pin_operation_thread, (PVOID) lParam, 0, NULL); diff --git a/src/minidriver/versioninfo-minidriver.rc.in b/src/minidriver/versioninfo-minidriver.rc.in index a86e2b53..f80f165f 100644 --- a/src/minidriver/versioninfo-minidriver.rc.in +++ b/src/minidriver/versioninfo-minidriver.rc.in @@ -3,6 +3,7 @@ #define IDC_STATIC -1 /* defined twice: in versioninfo-minidriver.rc.in and in minidriver.c */ #define IDD_PINPAD 101 +#define IDI_LOGO 102 #define IDC_PINPAD_TEXT 1001 #define IDC_PINPAD_ICON 1000 @@ -52,3 +53,4 @@ BEGIN LTEXT "This window will be closed automatically after the PIN has been submitted on the PINPAD or if the PINPAD timeout occurs (in general 30 seconds).",IDC_STATIC,7,46,298,19 END +IDI_LOGO ICON "..\\..\\win32\\OpenSC.ico" From 7784d24ee136c96a353ccc810ab2394887c9fefc Mon Sep 17 00:00:00 2001 From: vletoux Date: Thu, 7 May 2015 15:54:07 +0200 Subject: [PATCH 268/306] win32/customactions.cpp: add the MaskTech card minidriver registration data --- win32/customactions.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/win32/customactions.cpp b/win32/customactions.cpp index 7e5e2de4..4f4993de 100644 --- a/win32/customactions.cpp +++ b/win32/customactions.cpp @@ -76,6 +76,12 @@ MD_REGISTRATION minidriver_registration[] = { 20, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, {TEXT("CryptoStick v1.2 (OpenPGP v2.0)"), {0x3b,0xda,0x18,0xff,0x81,0xb1,0xfe,0x75,0x1f,0x03,0x00,0x31,0xc5,0x73,0xc0,0x01,0x40,0x00,0x90,0x00,0x0c}, 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + /* from card-masktech.c */ + /* note: the card name MUST be unique */ + {TEXT("MaskTech smart card (a)"), {0x3b,0x89,0x80,0x01,0x4d,0x54,0x43,0x4f,0x53,0x70,0x02,0x02,0x05,0x3b}, + 14, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("MaskTech smart card (b)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x37,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x02,0x05,0x41}, + 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, }; From 72b5d8fe9adcd5ae3ecb89b4c617151222e44c8b Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 10 May 2015 11:48:45 +0200 Subject: [PATCH 269/306] md: use 'store-or-update' store certificate mode --- src/minidriver/minidriver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 183592cb..f7318ec0 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -2124,6 +2124,7 @@ md_pkcs15_store_certificate(PCARD_DATA pCardData, char *file_name, unsigned char memset(&args, 0, sizeof(args)); args.der_encoded.value = blob; args.der_encoded.len = len; + args.update = 1; /* use container's ID as ID of certificate to store */ idx = -1; From c7af08c68a5bb3e753b008822e947d52016266c0 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Tue, 12 May 2015 12:59:37 -0500 Subject: [PATCH 270/306] PIV - read just length of object to get size card-piv.c tries to read the first 8 bytes of an object to get object size so it can allocate a buffer. It then reads the whole object. apdu.c has changed over the years, and apdu.c will keep reading as long as the card returns status of 61 XX thus apdu.c will read the whole object while discarding the extra data and returning to the caller only the first part of the data. This in effect causes a double read of objects. This patch sets SC_APDU_FLAGS_NO_GET_RESP to tell apdu to stop doing the extra get-response commands thus avoiding most of the extra overhead. This in not an optimal patch as it only works with T=1 cards/readers but the patch is confined to just card-piv.c. A better patch is in the works. Fixes #462 --- src/libopensc/card-piv.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index 0f1ef155..c12c9bd4 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -441,6 +441,7 @@ static int piv_general_io(sc_card_t *card, int ins, int p1, int p2, unsigned int cla_out, tag_out; const u8 *body; size_t bodylen; + int find_len = 0; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); @@ -465,6 +466,11 @@ static int piv_general_io(sc_card_t *card, int ins, int p1, int p2, recvbuf ? SC_APDU_CASE_4_SHORT: SC_APDU_CASE_3_SHORT, ins, p1, p2); apdu.flags |= SC_APDU_FLAGS_CHAINING; + /* if looking for length of object, dont try and read the rest of buffer here */ + if (rbuflen == 8 && card->reader->active_protocol == SC_PROTO_T1) { + apdu.flags |= SC_APDU_FLAGS_NO_GET_RESP; + find_len = 1; + } apdu.lc = sendbuflen; apdu.datalen = sendbuflen; @@ -493,7 +499,9 @@ static int piv_general_io(sc_card_t *card, int ins, int p1, int p2, goto err; } - r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if (!(find_len && apdu.sw1 == 0x61)) { + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + } /* TODO: - DEE look later at tag vs size read too */ if (r < 0) { From 8b62221abcaa8b32b5ffd9102bdec2995e660cba Mon Sep 17 00:00:00 2001 From: drew thomas Date: Thu, 7 May 2015 15:13:40 -0700 Subject: [PATCH 271/306] muscle: add ATR of Tyfone mSD card Add Tyfone Connected Smart Card ATR to list for MUSCLE support. SC_CARD_TYPE_MUSCLE_JCOP242_NO_APDU_EXT Fixes #463 --- src/libopensc/card-muscle.c | 73 ++++++++++++++++++++----------------- src/libopensc/cards.h | 1 + 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/libopensc/card-muscle.c b/src/libopensc/card-muscle.c index dc43029d..30f9dc6b 100644 --- a/src/libopensc/card-muscle.c +++ b/src/libopensc/card-muscle.c @@ -43,6 +43,8 @@ static struct sc_card_driver muscle_drv = { }; static struct sc_atr_table muscle_atrs[] = { + /* Tyfone JCOP 2.4.2 cards */ + { "3b:68:00:00:4a:43:4f:50:76:32:34:31", NULL, NULL, SC_CARD_TYPE_MUSCLE_JCOP242_NO_APDU_EXT, 0, NULL }, /* Aladdin eToken PRO USB 72K Java */ { "3b:d5:18:00:81:31:3a:7d:80:73:c8:21:10:30", NULL, NULL, SC_CARD_TYPE_MUSCLE_ETOKEN_72K, 0, NULL }, /* JCOP31 v2.4.1 contact interface */ @@ -59,7 +61,7 @@ typedef struct muscle_private { unsigned short verifiedPins; mscfs_t *fs; int rsa_key_ref; - + } muscle_private_t; static int muscle_finish(sc_card_t *card) @@ -78,13 +80,13 @@ static int muscle_match_card(sc_card_t *card) sc_apdu_t apdu; u8 response[64]; int r; - + /* Since we send an APDU, the card's logout function may be called... * however it's not always properly nulled out... */ card->ops->logout = NULL; if (msc_select_applet(card, muscleAppletId, sizeof muscleAppletId) == 1) { - /* Muscle applet is present, check the protocol version to be sure */ + /* Muscle applet is present, check the protocol version to be sure */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x3C, 0x00, 0x00); apdu.cla = 0xB0; apdu.le = 64; @@ -151,16 +153,16 @@ static int muscle_create_directory(sc_card_t *card, sc_file_t *file) int r; if(id == 0) /* No null name files */ return SC_ERROR_INVALID_ARGUMENTS; - + /* No nesting directories */ if(fs->currentPath[0] != 0x3F || fs->currentPath[1] != 0x00) return SC_ERROR_NOT_SUPPORTED; oid[0] = ((id & 0xFF00) >> 8) & 0xFF; oid[1] = id & 0xFF; oid[2] = oid[3] = 0; - + objectSize = file->size; - + muscle_parse_acls(file, &read_perm, &write_perm, &delete_perm); r = msc_create_object(card, objectId, objectSize, read_perm, write_perm, delete_perm); mscfs_clear_cache(fs); @@ -182,9 +184,9 @@ static int muscle_create_file(sc_card_t *card, sc_file_t *file) return SC_ERROR_NOT_SUPPORTED; if(file->id == 0) /* No null name files */ return SC_ERROR_INVALID_ARGUMENTS; - + muscle_parse_acls(file, &read_perm, &write_perm, &delete_perm); - + mscfs_lookup_local(fs, file->id, &objectId); r = msc_create_object(card, objectId, objectSize, read_perm, write_perm, delete_perm); mscfs_clear_cache(fs); @@ -199,7 +201,7 @@ static int muscle_read_binary(sc_card_t *card, unsigned int idx, u8* buf, size_t msc_id objectId; u8* oid = objectId.id; mscfs_file_t *file; - + r = mscfs_check_selection(fs, -1); if(r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); file = &fs->cache.array[fs->currentFileIndex]; @@ -225,7 +227,7 @@ static int muscle_update_binary(sc_card_t *card, unsigned int idx, const u8* buf r = mscfs_check_selection(fs, -1); if(r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); file = &fs->cache.array[fs->currentFileIndex]; - + objectId = file->objectId; /* memcpy(objectId.id, file->objectId.id, 4); */ if(!file->ef) { @@ -237,7 +239,7 @@ static int muscle_update_binary(sc_card_t *card, unsigned int idx, const u8* buf int newFileSize = idx + count; u8* buffer = malloc(newFileSize); if(buffer == NULL) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); - + r = msc_read_object(card, objectId, 0, buffer, file->size); /* TODO: RETREIVE ACLS */ if(r < 0) goto update_bin_free_buffer; @@ -272,7 +274,7 @@ static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data) mscfs_file_t *childFile; /* Delete children */ mscfs_check_cache(fs); - + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DELETING Children of: %02X%02X%02X%02X\n", oid[0],oid[1],oid[2],oid[3]); @@ -280,7 +282,7 @@ static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data) msc_id objectId; childFile = &fs->cache.array[x]; objectId = childFile->objectId; - + if(0 == memcmp(oid + 2, objectId.id, 2)) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DELETING: %02X%02X%02X%02X\n", @@ -367,11 +369,11 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f int r = 0; int objectIndex; u8* oid; - + mscfs_check_cache(fs); r = mscfs_loadFileInfo(fs, path_in->value, path_in->len, &file_data, &objectIndex); if(r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,r); - + /* Check if its the right type */ if(requiredType >= 0 && requiredType != file_data->ef) { SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS); @@ -389,7 +391,7 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f fs->currentFile[0] = 0; fs->currentFile[1] = 0; } - + fs->currentFileIndex = objectIndex; if(file_out) { sc_file_t *file; @@ -403,7 +405,7 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f file->type = SC_FILE_TYPE_WORKING_EF; file->ef_structure = SC_FILE_EF_TRANSPARENT; } - + /* Setup ACLS */ if(file_data->ef) { muscle_load_file_acls(file, file_data); @@ -411,7 +413,7 @@ static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** f muscle_load_dir_acls(file, file_data); /* Setup directory acls... */ } - + file->magic = SC_FILE_MAGIC; *file_out = file; } @@ -422,9 +424,9 @@ static int muscle_select_file(sc_card_t *card, const sc_path_t *path_in, sc_file_t **file_out) { int r; - + assert(card != NULL && path_in != NULL); - + switch (path_in->type) { case SC_PATH_TYPE_FILE_ID: r = select_item(card, path_in, file_out, 1); @@ -451,7 +453,7 @@ static int _listFile(mscfs_file_t *file, int reset, void *udata) static int muscle_init(sc_card_t *card) { muscle_private_t *priv; - + card->name = "MuscleApplet"; card->drv_data = malloc(sizeof(muscle_private_t)); if(!card->drv_data) { @@ -469,7 +471,7 @@ static int muscle_init(sc_card_t *card) priv->fs->listFile = _listFile; card->cla = 0xB0; - + card->flags |= SC_CARD_FLAG_RNG; card->caps |= SC_CARD_CAP_RNG; @@ -483,12 +485,15 @@ static int muscle_init(sc_card_t *card) if(card->type == SC_CARD_TYPE_MUSCLE_JCOP241) { card->caps |= SC_CARD_CAP_APDU_EXT; } + if(card->type == SC_CARD_TYPE_MUSCLE_JCOP242_NO_APDU_EXT) { + /* JCOP v2.4.2 card that doesn't support extended APDUs */ + } /* FIXME: Card type detection */ if (1) { unsigned long flags; - + flags = SC_ALGORITHM_RSA_RAW; flags |= SC_ALGORITHM_RSA_HASH_NONE; flags |= SC_ALGORITHM_ONBOARD_KEY_GEN; @@ -507,7 +512,7 @@ static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen) int count = 0; mscfs_check_cache(priv->fs); - + for(x = 0; x < fs->cache.size; x++) { u8* oid= fs->cache.array[x].objectId.id; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, @@ -589,7 +594,7 @@ static int muscle_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *cmd, return SC_ERROR_NOT_SUPPORTED; } - + } static int muscle_card_extract_key(sc_card_t *card, sc_cardctl_muscle_key_info_t *info) @@ -672,7 +677,7 @@ static int muscle_set_security_env(sc_card_t *card, /* ADJUST FOR PKCS1 padding support for decryption only */ if ((env->algorithm_flags & SC_ALGORITHM_RSA_PADS) || (env->algorithm_flags & SC_ALGORITHM_RSA_HASHES)) { - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Card supports only raw RSA.\n"); + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Card supports only raw RSA.\n"); return SC_ERROR_NOT_SUPPORTED; } if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { @@ -709,21 +714,21 @@ static int muscle_decipher(sc_card_t * card, size_t out_len) { muscle_private_t* priv = MUSCLE_DATA(card); - + u8 key_id; int r; /* saniti check */ if (priv->env.operation != SC_SEC_OPERATION_DECIPHER) return SC_ERROR_INVALID_ARGUMENTS; - + key_id = priv->rsa_key_ref * 2; /* Private key */ if (out_len < crgram_len) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Output buffer too small"); return SC_ERROR_BUFFER_TOO_SMALL; } - + r = msc_compute_crypt(card, key_id, 0x00, /* RSA NO PADDING */ @@ -742,14 +747,14 @@ static int muscle_compute_signature(sc_card_t *card, const u8 *data, muscle_private_t* priv = MUSCLE_DATA(card); u8 key_id; int r; - + key_id = priv->rsa_key_ref * 2; /* Private key */ - + if (outlen < data_len) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Output buffer too small"); return SC_ERROR_BUFFER_TOO_SMALL; } - + r = msc_compute_crypt(card, key_id, 0x00, /* RSA NO PADDING */ @@ -815,9 +820,9 @@ static struct sc_card_driver * sc_get_driver(void) muscle_ops.match_card = muscle_match_card; muscle_ops.init = muscle_init; muscle_ops.finish = muscle_finish; - + muscle_ops.get_challenge = muscle_get_challenge; - + muscle_ops.set_security_env = muscle_set_security_env; muscle_ops.restore_security_env = muscle_restore_security_env; muscle_ops.compute_signature = muscle_compute_signature; diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index 8c5c57e4..3ab69a31 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -139,6 +139,7 @@ enum { SC_CARD_TYPE_MUSCLE_V2, SC_CARD_TYPE_MUSCLE_ETOKEN_72K, SC_CARD_TYPE_MUSCLE_JCOP241, + SC_CARD_TYPE_MUSCLE_JCOP242_NO_APDU_EXT, /* ACOS5 driver */ SC_CARD_TYPE_ACOS5_BASE = 16000, From 492ffe0fd71d0bc2c6b0df7dfeb95f051b58d906 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sun, 10 May 2015 22:54:56 +0200 Subject: [PATCH 272/306] iso7816.c: allow file length stored in more than 2 bytes as indicated in iso7816-4 chapter 7.4.3 table 10 Fixes #459 --- src/libopensc/iso7816.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 9c8d85ef..83619300 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -31,7 +31,7 @@ static void fixup_transceive_length(const struct sc_card *card, - struct sc_apdu *apdu) + struct sc_apdu *apdu) { size_t max_send_size; size_t max_recv_size; @@ -105,7 +105,7 @@ static const struct sc_card_error iso7816_errors[] = { { 0x6A87, SC_ERROR_INCORRECT_PARAMETERS,"Lc inconsistent with P1-P2" }, { 0x6A88, SC_ERROR_DATA_OBJECT_NOT_FOUND,"Referenced data not found" }, { 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS, "File already exists"}, - { 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS, "DF name already exists"}, + { 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS, "DF name already exists"}, { 0x6B00, SC_ERROR_INCORRECT_PARAMETERS,"Wrong parameter(s) P1-P2" }, { 0x6D00, SC_ERROR_INS_NOT_SUPPORTED, "Instruction code not supported or invalid" }, @@ -350,6 +350,7 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file, { struct sc_context *ctx = card->ctx; size_t taglen, len = buflen; + int i; const unsigned char *tag = NULL, *p = buf; sc_log(ctx, "processing FCI bytes"); @@ -359,17 +360,25 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file, sc_log(ctx, " file identifier: 0x%02X%02X", tag[0], tag[1]); } - tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen); - if (tag == NULL) { - tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen); - } - if (tag != NULL && taglen > 0 && taglen < 3) { - file->size = tag[0]; - if (taglen == 2) - file->size = (file->size << 8) + tag[1]; + /* determine the file size */ + /* try the tag 0x80 then the tag 0x81 */ + file->size = 0; + for (i = 0x80; i <= 0x81; i++) { + int size = 0; + len = buflen; + tag = sc_asn1_find_tag(ctx, p, len, i, &taglen); + if (tag == NULL) + continue; + if (taglen == 0) + continue; + if (sc_asn1_decode_integer(tag, taglen, &size) < 0) + continue; + if (size <0) + continue; + + file->size = size; sc_log(ctx, " bytes in file: %d", file->size); - } else { - file->size = 0; + break; } tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen); From 6a6ef61d1acba7ab3363df4157dffce3eb935bbc Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Fri, 8 May 2015 15:49:30 +0200 Subject: [PATCH 273/306] some more error checks in minidriver in regards to card ejects --- src/minidriver/minidriver.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index f7318ec0..2d228960 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -319,7 +319,7 @@ static void print_werror(PCARD_DATA pCardData, PSTR str) static int check_reader_status(PCARD_DATA pCardData) { - int r; + int r = SCARD_S_SUCCESS; VENDOR_SPECIFIC *vs = NULL; logprintf(pCardData, 4, "check_reader_status\n"); @@ -340,6 +340,8 @@ check_reader_status(PCARD_DATA pCardData) r = disassociate_card(pCardData); logprintf(pCardData, 1, "disassociate_card r = 0x%08X\n", r); r = associate_card(pCardData); /* need to check return codes */ + if (r != SCARD_S_SUCCESS) + return r; logprintf(pCardData, 1, "associate_card r = 0x%08X\n", r); /* Rebuild 'soft' fs - in case changed */ r = md_fs_init(pCardData); @@ -351,7 +353,7 @@ check_reader_status(PCARD_DATA pCardData) logprintf(pCardData, 2, "check_reader_status r=%d flags 0x%08X\n", r, vs->reader->flags); } - return SCARD_S_SUCCESS; + return r; } static DWORD @@ -1274,6 +1276,9 @@ md_fs_read_content(PCARD_DATA pCardData, char *parent, struct md_file *file) logprintf(pCardData, 2, "directory '%s' not found\n", parent ? parent : ""); return; } + if (vs->p15card == NULL) { + return SCARD_F_INTERNAL_ERROR; + } if (!strcmp(dir->name, "mscp")) { int idx, rv; @@ -2585,6 +2590,10 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine return SCARD_E_NO_KEY_CONTAINER; } + if (vs->p15card == NULL) { + return SCARD_F_INTERNAL_ERROR; + } + check_reader_status(pCardData); pubkey_der.value = NULL; pubkey_der.len = 0; @@ -3667,7 +3676,10 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - check_reader_status(pCardData); + r = check_reader_status(pCardData); + + if ((vs->p15card) == NULL) + return SCARD_F_INTERNAL_ERROR; if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN || dwFlags == CARD_AUTHENTICATE_SESSION_PIN) { if (! (vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) From a09ca246a797230c14bc33a34f2dddc4a4dbff40 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Mon, 11 May 2015 14:17:54 +0200 Subject: [PATCH 274/306] libopensc: initialize value returned by sc_select_file several places in the code expect sc_select_file to set *file_out to NULL in case of failure. Adjust the function to behave like this. Fixes #460 --- src/libopensc/iso7816.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 83619300..19f9e7e3 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -475,6 +475,9 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct pathlen = in_path->len; pathtype = in_path->type; + if (file_out != NULL) { + *file_out = NULL; + } if (in_path->aid.len) { if (!pathlen) { memcpy(path, in_path->aid.value, in_path->aid.len); From 5be35fb3f40ecc651a4cfb88ca36ecdca5520eeb Mon Sep 17 00:00:00 2001 From: drew thomas Date: Fri, 15 May 2015 12:18:39 -0700 Subject: [PATCH 275/306] muscle: change TyfoneAT historical bytes to 'Tyfone 242R2' Fixes #467 --- src/libopensc/card-muscle.c | 8 ++++---- src/libopensc/cards.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libopensc/card-muscle.c b/src/libopensc/card-muscle.c index 30f9dc6b..8c92dcc1 100644 --- a/src/libopensc/card-muscle.c +++ b/src/libopensc/card-muscle.c @@ -43,8 +43,8 @@ static struct sc_card_driver muscle_drv = { }; static struct sc_atr_table muscle_atrs[] = { - /* Tyfone JCOP 2.4.2 cards */ - { "3b:68:00:00:4a:43:4f:50:76:32:34:31", NULL, NULL, SC_CARD_TYPE_MUSCLE_JCOP242_NO_APDU_EXT, 0, NULL }, + /* Tyfone JCOP 242R2 cards */ + { "3b:6d:00:00:ff:54:79:66:6f:6e:65:20:32:34:32:52:32", NULL, NULL, SC_CARD_TYPE_MUSCLE_JCOP242R2_NO_EXT_APDU, 0, NULL }, /* Aladdin eToken PRO USB 72K Java */ { "3b:d5:18:00:81:31:3a:7d:80:73:c8:21:10:30", NULL, NULL, SC_CARD_TYPE_MUSCLE_ETOKEN_72K, 0, NULL }, /* JCOP31 v2.4.1 contact interface */ @@ -485,8 +485,8 @@ static int muscle_init(sc_card_t *card) if(card->type == SC_CARD_TYPE_MUSCLE_JCOP241) { card->caps |= SC_CARD_CAP_APDU_EXT; } - if(card->type == SC_CARD_TYPE_MUSCLE_JCOP242_NO_APDU_EXT) { - /* JCOP v2.4.2 card that doesn't support extended APDUs */ + if(card->type == SC_CARD_TYPE_MUSCLE_JCOP242R2_NO_EXT_APDU) { + /* Tyfone JCOP v242R2 card that doesn't support extended APDUs */ } diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index 3ab69a31..e5a1529f 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -139,7 +139,7 @@ enum { SC_CARD_TYPE_MUSCLE_V2, SC_CARD_TYPE_MUSCLE_ETOKEN_72K, SC_CARD_TYPE_MUSCLE_JCOP241, - SC_CARD_TYPE_MUSCLE_JCOP242_NO_APDU_EXT, + SC_CARD_TYPE_MUSCLE_JCOP242R2_NO_EXT_APDU, /* ACOS5 driver */ SC_CARD_TYPE_ACOS5_BASE = 16000, From 6349836ba26acfe2f15ce7b9612672f1485b4cb7 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Fri, 15 May 2015 12:03:00 +0300 Subject: [PATCH 276/306] Include onepin-opensc-pkcs11.dll in installer Fixes #466 --- win32/OpenSC.wxs.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index 6adfa316..39db85ed 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -57,6 +57,9 @@ + + + @@ -232,6 +235,7 @@ + From 01b395e636b92411dac9d6eb3f77be7cde0decdb Mon Sep 17 00:00:00 2001 From: vletoux Date: Thu, 14 May 2015 10:24:01 +0200 Subject: [PATCH 277/306] card-masktech.c: add 2 more ATR Fixes #465 --- src/libopensc/card-masktech.c | 4 ++++ win32/customactions.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/libopensc/card-masktech.c b/src/libopensc/card-masktech.c index ae620f1a..2b036e75 100644 --- a/src/libopensc/card-masktech.c +++ b/src/libopensc/card-masktech.c @@ -34,8 +34,12 @@ static struct sc_atr_table masktech_atrs[] = { {"3B:89:80:01:4D:54:43:4F:53:70:02:02:05:3B", NULL, NULL, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, + {"3B:88:80:01:00:00:00:00:77:81:81:00:7E", NULL, NULL, + SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, {"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:02:05:41", NULL, NULL, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, + {"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:01:02:45", NULL, NULL, + SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, {NULL, NULL, NULL, 0, 0, NULL} }; diff --git a/win32/customactions.cpp b/win32/customactions.cpp index 4f4993de..988e1ffd 100644 --- a/win32/customactions.cpp +++ b/win32/customactions.cpp @@ -82,6 +82,10 @@ MD_REGISTRATION minidriver_registration[] = { 14, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, {TEXT("MaskTech smart card (b)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x37,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x02,0x05,0x41}, 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("MaskTech smart card (c)"), {0x3B,0x88,0x80,0x01,0x00,0x00,0x00,0x00,0x77,0x81,0x81,0x00,0x7E}, + 13, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("MaskTech smart card (d)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x37,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x01,0x02,0x45}, + 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, }; From 8c94662e9610ba7691a5dce06710ee305b163d70 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 14 May 2015 00:43:40 +0100 Subject: [PATCH 278/306] Add --test-fork option to pkcs11-tool The PKCS#11 Usage Guide, at least up to v2.40, says that calling C_Initialize() in the child after fork is "considered to be good Cryptoki programming practice, since it can prevent the existence of dangling duplicate resources that were created at the time of the fork() call." (It neglects to mention that doing so in the child of a multi-threaded process is a clear violation of POSIX, mind you. Not to mention being utterly pointless if all you're going to do in the child is exec something else anyway.) Regardless of the sagacity of this recommendation, we need to cope when it happens. Historically, we've been quite bad at that. Let's add a test to pkcs11-tool in the hope it'll help... Fixes #464 --- src/tools/pkcs11-tool.c | 56 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 0014a030..2a01cf0e 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -24,6 +24,11 @@ #include #include #include +#ifndef _WIN32 +#include +#include +#include +#endif #ifdef ENABLE_OPENSSL #include #if OPENSSL_VERSION_NUMBER >= 0x10000000L @@ -118,7 +123,8 @@ enum { OPT_LOGIN_TYPE, OPT_TEST_EC, OPT_DERIVE, - OPT_DECRYPT + OPT_DECRYPT, + OPT_TEST_FORK, }; static const struct option options[] = { @@ -176,6 +182,9 @@ static const struct option options[] = { { "verbose", 0, NULL, 'v' }, { "private", 0, NULL, OPT_PRIVATE }, { "test-ec", 0, NULL, OPT_TEST_EC }, +#ifndef _WIN32 + { "test-fork", 0, NULL, OPT_TEST_FORK }, +#endif { NULL, 0, NULL, 0 } }; @@ -234,7 +243,10 @@ static const char *option_help[] = { "Test Mozilla-like keypair gen and cert req, =certfile", "Verbose operation. (Set OPENSC_DEBUG to enable OpenSC specific debugging)", "Set the CKA_PRIVATE attribute (object is only viewable after a login)", - "Test EC (best used with the --login or --pin option)" + "Test EC (best used with the --login or --pin option)", +#ifndef _WIN32 + "Test forking and calling C_Initialize() in the child", +#endif }; static const char * app_name = "pkcs11-tool"; /* for utils.c */ @@ -371,6 +383,9 @@ static int test_card_detection(int); static int hex_to_bin(const char *in, CK_BYTE *out, size_t *outlen); static void test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session); static void test_ec(CK_SLOT_ID slot, CK_SESSION_HANDLE session); +#ifndef _WIN32 +static void test_fork(void); +#endif static CK_RV find_object_with_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *out, CK_ATTRIBUTE *attrs, CK_ULONG attrsLen, CK_ULONG obj_index); static CK_ULONG get_private_key_length(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE prkey); @@ -402,6 +417,9 @@ int main(int argc, char * argv[]) int do_test = 0; int do_test_kpgen_certwrite = 0; int do_test_ec = 0; +#ifndef _WIN32 + int do_test_fork = 0; +#endif int need_session = 0; int opt_login = 0; int do_init_token = 0; @@ -675,6 +693,12 @@ int main(int argc, char * argv[]) do_derive = 1; action_count++; break; +#ifndef _WIN32 + case OPT_TEST_FORK: + do_test_fork = 1; + action_count++; + break; +#endif default: util_print_usage_and_die(app_name, options, option_help, NULL); } @@ -693,6 +717,11 @@ int main(int argc, char * argv[]) else if (rv != CKR_OK) p11_fatal("C_Initialize", rv); +#ifndef _WIN32 + if (do_test_fork) + test_fork(); +#endif + if (do_show_info) show_cryptoki_info(); @@ -4571,6 +4600,29 @@ static void test_ec(CK_SLOT_ID slot, CK_SESSION_HANDLE session) printf("==> OK\n"); } +#ifndef _WIN32 +static void test_fork(void) +{ + CK_RV rv; + pid_t pid = fork(); + + if (!pid) { + printf("*** Calling C_Initialize in forked child process ***\n"); + rv = p11->C_Initialize(NULL); + if (rv != CKR_OK) + p11_fatal("C_Initialize in child\n", rv); + exit(0); + } else if (pid < 0) { + util_fatal("Failed to fork for test: %s", strerror(errno)); + } else { + int st; + waitpid(pid, &st, 0); + if (!WIFEXITED(st) || WEXITSTATUS(st)) + util_fatal("Child process exited with status %d", st); + } + +} +#endif static const char *p11_flag_names(struct flag_info *list, CK_FLAGS value) { From 31cb40db17cbb13595af1c03c19198b11ac7d649 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sat, 16 May 2015 21:31:47 +0200 Subject: [PATCH 279/306] revision: 0.15.0 --- NEWS | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index b1b63b89..1de0b8d4 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,68 @@ NEWS for OpenSC -- History of user visible changes +New in 0.15.0; 2015-05-11 +* new card drivers + AzeDIT 3.5 + IsoApplet + MaskTech +* libopensc + allow extended length APDUs + accept no output for 'SELECT' MF and 'SELECT' DF_NAME APDUs + fixed sc_driver_version check + adjusted send/receive size accoriding to card capabilities + in iso7816 make SELECT agnosting to sc_path_t's aid +* asn1 + support multi-bytes tags +* pkcs15 + reviewed support and tool functions for public key + public certs and pubkeys with an auth_id are treated as private +* pkcs11 + introduced default PKCS#11 provider + fetched real value of CKA_LOCAL for pubkey + removed inconsistent attributes + C_Digest issues + no check if buffer too small before update +* added support for Travis CI +* updated support of EC in libopensc, pkcs15 and pkcs11 +* fixed number of warnings, resource leaks, overity-scan issues +* macosx + target minimum OSX version to 10.7 + update the minimal building instructions. + locate and target the latest SDK to build against. + locate the best newest SDK present on the computer. +* build + disable Secure Messaging if OpenSSL is not used +* tools + util_get_pin helper function +* PIV + Add AES support for PIV General Authenticate + fixed invalid bit when writing PIV certificate object with gzipped certificate + fixed bad caching behavior of PIV PKCS15 emulator +* ePass2003 + fixed failure due to re-authenticate of secure messaging when card is accessed + by multiple PKCS11 sessions +* MyEID + EC support for MyEID-v4 card +* openpgp + extended options for openpgp-tool +* asepcos + fixed puk handling +* sc-hsm + support for Koblitz curves secp192k1 and secp256k1 (Bitcoin) + improved error detection and reporting in sc-hsm-tool + fixed Lc byte in VERIFY PIN block for PC/SC PIN PAD reader + fix certificate delete bug +* IAS/ECC + fixed PKCS#11 compliance issues + support for Morpho IAS Agent Card +* cardos + overwrite content of deleted private key +* win32 + setup improuvement + look & feel + custom actions with card registration + minidriver impouvement + fixed errors and warnings returned by Microsoft quality tool + pin-pad support New in 0.14.0; 2014-05-31 * new card driver DNIe diff --git a/configure.ac b/configure.ac index 941b534f..f0bbb3eb 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ define([PRODUCT_NAME], [OpenSC]) define([PRODUCT_TARNAME], [opensc]) define([PRODUCT_BUGREPORT], [opensc-devel@lists.sourceforge.net]) define([PACKAGE_VERSION_MAJOR], [0]) -define([PACKAGE_VERSION_MINOR], [14]) +define([PACKAGE_VERSION_MINOR], [15]) define([PACKAGE_VERSION_FIX], [0]) define([PACKAGE_SUFFIX], []) define([PACKAGE_VERSION_REVISION], [0]) From b48fa703085f723f2209a92f22136b5915bd87a4 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Wed, 11 Feb 2015 19:03:45 -0600 Subject: [PATCH 280/306] sc_pkcs11_card improvements This is name change only fix. The variable name "card" was being used to refer to a struct sc_card or a struct sc_pkcs11_card in some files including sc_pkcs11.h. In other files the variable name "p11card" is used for struct sc_pkcs11_card. This creates hard to read code, such as: slot->card->card. All definitations of sc_pkcs11_card *card now use p11card as the variable name. Fix #471 --- src/pkcs11/framework-pkcs15.c | 56 +++++++++++++++---------------- src/pkcs11/framework-pkcs15init.c | 6 ++-- src/pkcs11/mechanism.c | 10 +++--- src/pkcs11/openssl.c | 16 ++++----- src/pkcs11/pkcs11-global.c | 8 ++--- src/pkcs11/pkcs11-object.c | 10 +++--- src/pkcs11/pkcs11-session.c | 14 ++++---- src/pkcs11/sc-pkcs11.h | 2 +- src/pkcs11/slot.c | 42 +++++++++++------------ 9 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index f1ab565b..52f5a082 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -498,7 +498,7 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) data.pin_type = SC_AC_CHV; data.pin_reference = pin_info->attrs.pin.reference; - r = sc_pin_cmd(slot->card->card, &data, NULL); + r = sc_pin_cmd(slot->p11card->card, &data, NULL); if (r == SC_SUCCESS) { if (data.pin1.max_tries > 0) pin_info->max_tries = data.pin1.max_tries; @@ -906,7 +906,7 @@ pkcs15_add_object(struct sc_pkcs11_slot *slot, struct pkcs15_any_object *obj, case SC_PKCS15_TYPE_PRKEY_GOSTR3410: case SC_PKCS15_TYPE_PRKEY_EC: pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL); - card_fw_data = (struct pkcs15_fw_data *) slot->card->fws_data[slot->fw_data_idx]; + card_fw_data = (struct pkcs15_fw_data *) slot->p11card->fws_data[slot->fw_data_idx]; for (i = 0; i < card_fw_data->num_objects; i++) { struct pkcs15_any_object *obj2 = card_fw_data->objects[i]; struct pkcs15_cert_object *cert; @@ -1394,7 +1394,7 @@ static CK_RV pkcs15_login(struct sc_pkcs11_slot *slot, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_pkcs15_card *p15card = NULL; struct sc_pkcs15_object *auth_object = NULL; @@ -1568,7 +1568,7 @@ pkcs15_login(struct sc_pkcs11_slot *slot, CK_USER_TYPE userType, static CK_RV pkcs15_logout(struct sc_pkcs11_slot *slot) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; CK_RV ret = CKR_OK; int rc; @@ -1608,7 +1608,7 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct sc_pkcs15_card *p15card = NULL; struct pkcs15_fw_data *fw_data = NULL; struct sc_pkcs15_auth_info *auth_info = NULL; @@ -1685,7 +1685,7 @@ pkcs15_initialize(struct sc_pkcs11_slot *slot, void *ptr, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct sc_cardctl_pkcs11_init_token args; scconf_block *atrblock = NULL; int rc, enable_InitToken = 0; @@ -1811,7 +1811,7 @@ pkcs15_initialize(struct sc_pkcs11_slot *slot, void *ptr, static CK_RV pkcs15_init_pin(struct sc_pkcs11_slot *slot, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_pkcs15init_pinargs args; struct sc_profile *profile = NULL; @@ -1911,7 +1911,7 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_pkcs15init_prkeyargs args; struct pkcs15_any_object *key_any_obj = NULL; @@ -2065,7 +2065,7 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_pkcs15init_skeyargs args; struct pkcs15_any_object *key_any_obj = NULL; @@ -2215,7 +2215,7 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_pkcs15init_pubkeyargs args; struct pkcs15_any_object *key_any_obj = NULL; @@ -2322,7 +2322,7 @@ pkcs15_create_certificate(struct sc_pkcs11_slot *slot, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_pkcs15init_certargs args; struct pkcs15_any_object *cert_any_obj = NULL; @@ -2404,7 +2404,7 @@ pkcs15_create_data(struct sc_pkcs11_slot *slot, struct sc_profile *profile, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_pkcs15init_dataargs args; struct pkcs15_any_object *data_any_obj = NULL; @@ -2492,7 +2492,7 @@ static CK_RV pkcs15_create_object(struct sc_pkcs11_slot *slot, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_profile *profile = NULL; CK_OBJECT_CLASS _class; @@ -2679,7 +2679,7 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE_PTR phPubKey, CK_OBJECT_HANDLE_PTR phPrivKey) /* gets priv. key handle */ { struct sc_profile *profile = NULL; - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct sc_pkcs15_auth_info *pin = NULL; struct sc_aid *aid = NULL; struct pkcs15_fw_data *fw_data = NULL; @@ -2864,7 +2864,7 @@ pkcs15_skey_destroy(struct sc_pkcs11_session *session, void *object) return CKR_FUNCTION_NOT_SUPPORTED; #else struct pkcs15_any_object *any_obj = (struct pkcs15_any_object*) object; - struct sc_pkcs11_card *p11card = session->slot->card; + struct sc_pkcs11_card *p11card = session->slot->p11card; struct pkcs15_fw_data *fw_data = NULL; int rv; @@ -2900,7 +2900,7 @@ pkcs15_any_destroy(struct sc_pkcs11_session *session, void *object) struct pkcs15_data_object *obj = (struct pkcs15_data_object*) object; struct pkcs15_any_object *any_obj = (struct pkcs15_any_object*) object; struct sc_pkcs11_slot *slot = session->slot; - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_aid *aid = NULL; struct sc_profile *profile = NULL; @@ -2981,7 +2981,7 @@ pkcs15_any_destroy(struct sc_pkcs11_session *session, void *object) static CK_RV pkcs15_get_random(struct sc_pkcs11_slot *slot, CK_BYTE_PTR p, CK_ULONG len) { - struct sc_pkcs11_card *p11card = slot->card; + struct sc_pkcs11_card *p11card = slot->p11card; struct pkcs15_fw_data *fw_data = NULL; int rc; @@ -3026,7 +3026,7 @@ pkcs15_set_attrib(struct sc_pkcs11_session *session, struct sc_pkcs15_object *p1 #else struct sc_profile *profile = NULL; struct sc_pkcs11_slot *slot = session->slot; - struct sc_pkcs11_card *p11card = session->slot->card; + struct sc_pkcs11_card *p11card = session->slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct sc_aid *aid = NULL; struct sc_pkcs15_id id; @@ -3123,7 +3123,7 @@ pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT size_t len; sc_log(context, "pkcs15_cert_get_attribute() called"); - p11card = session->slot->card; + p11card = session->slot->p11card; fw_data = (struct pkcs15_fw_data *) p11card->fws_data[session->slot->fw_data_idx]; if (!fw_data) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetAttributeValue"); @@ -3215,7 +3215,7 @@ pkcs15_cert_cmp_attribute(struct sc_pkcs11_session *session, void *object, CK_ATTRIBUTE_PTR attr) { struct pkcs15_cert_object *cert = (struct pkcs15_cert_object*) object; - struct sc_pkcs11_card *p11card = session->slot->card; + struct sc_pkcs11_card *p11card = session->slot->p11card; struct pkcs15_fw_data *fw_data = NULL; const unsigned char *data = NULL, *_data = NULL; size_t len, _len; @@ -3318,7 +3318,7 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session, size_t len; sc_log(context, "pkcs15_prkey_get_attribute() called"); - p11card = session->slot->card; + p11card = session->slot->p11card; fw_data = (struct pkcs15_fw_data *) p11card->fws_data[session->slot->fw_data_idx]; if (!fw_data) return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GetAttributeValue"); @@ -3508,7 +3508,7 @@ pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj, CK_ULONG_PTR pulDataLen) { struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj; - struct sc_pkcs11_card *p11card = session->slot->card; + struct sc_pkcs11_card *p11card = session->slot->p11card; struct pkcs15_fw_data *fw_data = NULL; int rv, flags = 0, prkey_has_path = 0; unsigned sign_flags = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER @@ -3609,7 +3609,7 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { - struct sc_pkcs11_card *p11card = session->slot->card; + struct sc_pkcs11_card *p11card = session->slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct pkcs15_prkey_object *prkey; unsigned char decrypted[256]; /* FIXME: Will not work for keys above 2048 bits */ @@ -3680,7 +3680,7 @@ pkcs15_prkey_derive(struct sc_pkcs11_session *session, void *obj, CK_BYTE_PTR pParameters, CK_ULONG ulParametersLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { - struct sc_pkcs11_card *p11card = session->slot->card; + struct sc_pkcs11_card *p11card = session->slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj; int need_unlock = 0, prkey_has_path = 0; @@ -3752,7 +3752,7 @@ static CK_RV pkcs15_prkey_can_do(struct sc_pkcs11_session *session, void *obj, CK_MECHANISM_TYPE mech_type, unsigned int flags) { - struct sc_pkcs11_card *p11card = session->slot->card; + struct sc_pkcs11_card *p11card = session->slot->p11card; struct pkcs15_fw_data *fw_data = NULL; struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj; struct sc_pkcs15_prkey_info *pkinfo = NULL; @@ -3846,7 +3846,7 @@ pkcs15_pubkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ sc_log(context, "pkcs15_pubkey_get_attribute() called"); - p11card = session->slot->card; + p11card = session->slot->p11card; cert = pubkey->pub_genfrom; fw_data = (struct pkcs15_fw_data *) p11card->fws_data[session->slot->fw_data_idx]; @@ -4054,9 +4054,9 @@ pkcs15_dobj_get_value(struct sc_pkcs11_session *session, struct pkcs15_data_object *dobj, struct sc_pkcs15_data **out_data) { - struct sc_pkcs11_card *p11card = session->slot->card; + struct sc_pkcs11_card *p11card = session->slot->p11card; struct pkcs15_fw_data *fw_data = NULL; - struct sc_card *card = session->slot->card->card; + struct sc_card *card = session->slot->p11card->card; int rv; if (!out_data) diff --git a/src/pkcs11/framework-pkcs15init.c b/src/pkcs11/framework-pkcs15init.c index ad7ab415..582be36f 100644 --- a/src/pkcs11/framework-pkcs15init.c +++ b/src/pkcs11/framework-pkcs15init.c @@ -127,7 +127,7 @@ pkcs15init_initialize(struct sc_pkcs11_slot *pslot, void *ptr, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel) { - struct sc_pkcs11_card *p11card = pslot->card; + struct sc_pkcs11_card *p11card = pslot->p11card; struct sc_profile *profile = (struct sc_profile *) p11card->fws_data[0]; struct sc_pkcs15init_initargs args; struct sc_pkcs11_slot *slot; @@ -159,9 +159,9 @@ pkcs15init_initialize(struct sc_pkcs11_slot *pslot, void *ptr, * the flags. */ for (id = 0; slot_get_slot(id, &slot) == CKR_OK; id++) { - if (slot->card == p11card) + if (slot->p11card == p11card) slot->token_info.flags |= CKF_TOKEN_INITIALIZED; - if (slot->card->card->caps & SC_CARD_CAP_RNG) + if (slot->p11card->card->caps & SC_CARD_CAP_RNG) slot->token_info.flags |= CKF_RNG; } diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index 77c1c63b..40d07401 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -155,7 +155,7 @@ sc_pkcs11_md_init(struct sc_pkcs11_session *session, int rv; LOG_FUNC_CALLED(context); - if (!session || !session->slot || !(p11card = session->slot->card)) + if (!session || !session->slot || !(p11card = session->slot->p11card)) LOG_FUNC_RETURN(context, CKR_ARGUMENTS_BAD); /* See if we support this mechanism type */ @@ -234,7 +234,7 @@ sc_pkcs11_sign_init(struct sc_pkcs11_session *session, CK_MECHANISM_PTR pMechani int rv; LOG_FUNC_CALLED(context); - if (!session || !session->slot || !(p11card = session->slot->card)) + if (!session || !session->slot || !(p11card = session->slot->p11card)) LOG_FUNC_RETURN(context, CKR_ARGUMENTS_BAD); /* See if we support this mechanism type */ @@ -518,7 +518,7 @@ sc_pkcs11_verif_init(struct sc_pkcs11_session *session, CK_MECHANISM_PTR pMechan int rv; if (!session || !session->slot - || !(p11card = session->slot->card)) + || !(p11card = session->slot->p11card)) return CKR_ARGUMENTS_BAD; /* See if we support this mechanism type */ @@ -729,7 +729,7 @@ sc_pkcs11_decr_init(struct sc_pkcs11_session *session, CK_RV rv; if (!session || !session->slot - || !(p11card = session->slot->card)) + || !(p11card = session->slot->p11card)) return CKR_ARGUMENTS_BAD; /* See if we support this mechanism type */ @@ -799,7 +799,7 @@ sc_pkcs11_deri(struct sc_pkcs11_session *session, if (!session || !session->slot - || !(p11card = session->slot->card)) + || !(p11card = session->slot->p11card)) return CKR_ARGUMENTS_BAD; /* See if we support this mechanism type */ diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c index 8f812fd2..77d974bd 100644 --- a/src/pkcs11/openssl.c +++ b/src/pkcs11/openssl.c @@ -167,7 +167,7 @@ static void * dup_mem(void *in, size_t in_len) } void -sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *card) +sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *p11card) { #if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_ENGINE) void (*locking_cb)(int, int, const char *, int); @@ -207,22 +207,22 @@ sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *card) #endif /* OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_ENGINE) */ openssl_sha1_mech.mech_data = EVP_sha1(); - sc_pkcs11_register_mechanism(card, dup_mem(&openssl_sha1_mech, sizeof openssl_sha1_mech)); + sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_sha1_mech, sizeof openssl_sha1_mech)); #if OPENSSL_VERSION_NUMBER >= 0x00908000L openssl_sha256_mech.mech_data = EVP_sha256(); - sc_pkcs11_register_mechanism(card, dup_mem(&openssl_sha256_mech, sizeof openssl_sha256_mech)); + sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_sha256_mech, sizeof openssl_sha256_mech)); openssl_sha384_mech.mech_data = EVP_sha384(); - sc_pkcs11_register_mechanism(card, dup_mem(&openssl_sha384_mech, sizeof openssl_sha384_mech)); + sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_sha384_mech, sizeof openssl_sha384_mech)); openssl_sha512_mech.mech_data = EVP_sha512(); - sc_pkcs11_register_mechanism(card, dup_mem(&openssl_sha512_mech, sizeof openssl_sha512_mech)); + sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_sha512_mech, sizeof openssl_sha512_mech)); #endif openssl_md5_mech.mech_data = EVP_md5(); - sc_pkcs11_register_mechanism(card, dup_mem(&openssl_md5_mech, sizeof openssl_md5_mech)); + sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_md5_mech, sizeof openssl_md5_mech)); openssl_ripemd160_mech.mech_data = EVP_ripemd160(); - sc_pkcs11_register_mechanism(card, dup_mem(&openssl_ripemd160_mech, sizeof openssl_ripemd160_mech)); + sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_ripemd160_mech, sizeof openssl_ripemd160_mech)); #if OPENSSL_VERSION_NUMBER >= 0x10000000L openssl_gostr3411_mech.mech_data = EVP_get_digestbynid(NID_id_GostR3411_94); - sc_pkcs11_register_mechanism(card, dup_mem(&openssl_gostr3411_mech, sizeof openssl_gostr3411_mech)); + sc_pkcs11_register_mechanism(p11card, dup_mem(&openssl_gostr3411_mech, sizeof openssl_gostr3411_mech)); #endif } diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index aa507589..ee6cf7c4 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -533,7 +533,7 @@ CK_RV C_GetMechanismList(CK_SLOT_ID slotID, rv = slot_get_token(slotID, &slot); if (rv == CKR_OK) - rv = sc_pkcs11_get_mechanism_list(slot->card, pMechanismList, pulCount); + rv = sc_pkcs11_get_mechanism_list(slot->p11card, pMechanismList, pulCount); sc_pkcs11_unlock(); return rv; @@ -555,7 +555,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, rv = slot_get_token(slotID, &slot); if (rv == CKR_OK) - rv = sc_pkcs11_get_mechanism_info(slot->card, type, pInfo); + rv = sc_pkcs11_get_mechanism_info(slot->p11card, type, pInfo); sc_pkcs11_unlock(); return rv; @@ -582,7 +582,7 @@ CK_RV C_InitToken(CK_SLOT_ID slotID, goto out; } - if (slot->card->framework->init_token == NULL) { + if (slot->p11card->framework->init_token == NULL) { sc_log(context, "C_InitToken() not supported by framework"); rv = CKR_FUNCTION_NOT_SUPPORTED; goto out; @@ -597,7 +597,7 @@ CK_RV C_InitToken(CK_SLOT_ID slotID, } } - rv = slot->card->framework->init_token(slot,slot->fw_data, pPin, ulPinLen, pLabel); + rv = slot->p11card->framework->init_token(slot,slot->fw_data, pPin, ulPinLen, pLabel); if (rv == CKR_OK) { /* Now we should re-bind all tokens so they get the * corresponding function vector and flags */ diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c index 607bbba8..41bfe5c0 100644 --- a/src/pkcs11/pkcs11-object.c +++ b/src/pkcs11/pkcs11-object.c @@ -114,7 +114,7 @@ CK_RV sc_create_object_int(CK_SESSION_HANDLE hSession, /* the session's handle * goto out; } - card = session->slot->card; + card = session->slot->p11card; if (card->framework->create_object == NULL) rv = CKR_FUNCTION_NOT_SUPPORTED; else @@ -983,10 +983,10 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, /* the session's handle */ } slot = session->slot; - if (slot->card->framework->gen_keypair == NULL) + if (slot->p11card->framework->gen_keypair == NULL) rv = CKR_FUNCTION_NOT_SUPPORTED; else - rv = slot->card->framework->gen_keypair(slot, pMechanism, + rv = slot->p11card->framework->gen_keypair(slot, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); @@ -1120,10 +1120,10 @@ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, /* the session's handle */ rv = get_session(hSession, &session); if (rv == CKR_OK) { slot = session->slot; - if (slot->card->framework->get_random == NULL) + if (slot->p11card->framework->get_random == NULL) rv = CKR_RANDOM_NO_RNG; else - rv = slot->card->framework->get_random(slot, RandomData, ulRandomLen); + rv = slot->p11card->framework->get_random(slot, RandomData, ulRandomLen); } sc_pkcs11_unlock(); diff --git a/src/pkcs11/pkcs11-session.c b/src/pkcs11/pkcs11-session.c index 143ab56e..c4ab857f 100644 --- a/src/pkcs11/pkcs11-session.c +++ b/src/pkcs11/pkcs11-session.c @@ -107,7 +107,7 @@ static CK_RV sc_pkcs11_close_session(CK_SESSION_HANDLE hSession) slot->nsessions--; if (slot->nsessions == 0 && slot->login_user >= 0) { slot->login_user = -1; - slot->card->framework->logout(slot); + slot->p11card->framework->logout(slot); } if (list_delete(&sessions, session) != 0) @@ -272,7 +272,7 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */ goto out; } else { - rv = slot->card->framework->login(slot, userType, pPin, ulPinLen); + rv = slot->p11card->framework->login(slot, userType, pPin, ulPinLen); } } else { @@ -286,7 +286,7 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */ } sc_log(context, "C_Login() userType %li", userType); - rv = slot->card->framework->login(slot, userType, pPin, ulPinLen); + rv = slot->p11card->framework->login(slot, userType, pPin, ulPinLen); sc_log(context, "fLogin() rv %li", rv); if (rv == CKR_OK) slot->login_user = userType; @@ -319,7 +319,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) if (slot->login_user >= 0) { slot->login_user = -1; - rv = slot->card->framework->logout(slot); + rv = slot->p11card->framework->logout(slot); } else rv = CKR_USER_NOT_LOGGED_IN; @@ -355,10 +355,10 @@ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) slot = session->slot; if (slot->login_user != CKU_SO) { rv = CKR_USER_NOT_LOGGED_IN; - } else if (slot->card->framework->init_pin == NULL) { + } else if (slot->p11card->framework->init_pin == NULL) { rv = CKR_FUNCTION_NOT_SUPPORTED; } else { - rv = slot->card->framework->init_pin(slot, pPin, ulPinLen); + rv = slot->p11card->framework->init_pin(slot, pPin, ulPinLen); sc_log(context, "C_InitPIN() init-pin result %li", rv); } @@ -395,7 +395,7 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, goto out; } - rv = slot->card->framework->change_pin(slot, pOldPin, ulOldLen, pNewPin, ulNewLen); + rv = slot->p11card->framework->change_pin(slot, pOldPin, ulOldLen, pNewPin, ulNewLen); out: sc_pkcs11_unlock(); return rv; diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index af0557c8..b89185ce 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -208,7 +208,7 @@ struct sc_pkcs11_slot { CK_SLOT_INFO slot_info; /* Slot specific information (information about reader) */ CK_TOKEN_INFO token_info; /* Token specific information (information about card) */ sc_reader_t *reader; /* same as card->reader if there's a card present */ - struct sc_pkcs11_card *card; /* The card associated with this slot */ + struct sc_pkcs11_card *p11card; /* The card associated with this slot */ unsigned int events; /* Card events SC_EVENT_CARD_{INSERTED,REMOVED} */ void *fw_data; /* Framework specific data */ /* TODO: get know how it used */ list_t objects; /* Objects in this slot */ diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index e41f7a93..283e3b6a 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -152,7 +152,7 @@ CK_RV initialize_reader(sc_reader_t *reader) CK_RV card_removed(sc_reader_t * reader) { unsigned int i; - struct sc_pkcs11_card *card = NULL; + struct sc_pkcs11_card *p11card = NULL; /* Mark all slots as "token not present" */ sc_log(context, "%s: card removed", reader->name); @@ -161,23 +161,23 @@ CK_RV card_removed(sc_reader_t * reader) sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); if (slot->reader == reader) { /* Save the "card" object */ - if (slot->card) - card = slot->card; + if (slot->p11card) + p11card = slot->p11card; slot_token_removed(slot->id); } } - if (card) { - card->framework->unbind(card); - sc_disconnect_card(card->card); - for (i=0; i < card->nmechanisms; ++i) { - if (card->mechanisms[i]->free_mech_data) { - card->mechanisms[i]->free_mech_data(card->mechanisms[i]->mech_data); + if (p11card) { + p11card->framework->unbind(p11card); + sc_disconnect_card(p11card->card); + for (i=0; i < p11card->nmechanisms; ++i) { + if (p11card->mechanisms[i]->free_mech_data) { + p11card->mechanisms[i]->free_mech_data(p11card->mechanisms[i]->mech_data); } - free(card->mechanisms[i]); + free(p11card->mechanisms[i]); } - free(card->mechanisms); - free(card); + free(p11card->mechanisms); + free(p11card); } return CKR_OK; @@ -224,7 +224,7 @@ again: for (i=0; ireader == reader) { - p11card = slot->card; + p11card = slot->p11card; break; } } @@ -353,7 +353,7 @@ card_detect_all(void) } /* Allocates an existing slot to a card */ -CK_RV slot_allocate(struct sc_pkcs11_slot ** slot, struct sc_pkcs11_card * card) +CK_RV slot_allocate(struct sc_pkcs11_slot ** slot, struct sc_pkcs11_card * p11card) { unsigned int i; struct sc_pkcs11_slot *tmp_slot = NULL; @@ -361,13 +361,13 @@ CK_RV slot_allocate(struct sc_pkcs11_slot ** slot, struct sc_pkcs11_card * card) /* Locate a free slot for this reader */ for (i=0; i< list_size(&virtual_slots); i++) { tmp_slot = (struct sc_pkcs11_slot *)list_get_at(&virtual_slots, i); - if (tmp_slot->reader == card->reader && tmp_slot->card == NULL) + if (tmp_slot->reader == p11card->reader && tmp_slot->p11card == NULL) break; } if (!tmp_slot || (i == list_size(&virtual_slots))) return CKR_FUNCTION_FAILED; - sc_log(context, "Allocated slot 0x%lx for card in reader %s", tmp_slot->id, card->reader->name); - tmp_slot->card = card; + sc_log(context, "Allocated slot 0x%lx for card in reader %s", tmp_slot->id, p11card->reader->name); + tmp_slot->p11card = p11card; tmp_slot->events = SC_EVENT_CARD_INSERTED; *slot = tmp_slot; return CKR_OK; @@ -432,16 +432,16 @@ CK_RV slot_token_removed(CK_SLOT_ID id) } /* Release framework stuff */ - if (slot->card != NULL) { + if (slot->p11card != NULL) { if (slot->fw_data != NULL && - slot->card->framework != NULL && slot->card->framework->release_token != NULL) - slot->card->framework->release_token(slot->card, slot->fw_data); + slot->p11card->framework != NULL && slot->p11card->framework->release_token != NULL) + slot->p11card->framework->release_token(slot->p11card, slot->fw_data); } /* Reset relevant slot properties */ slot->slot_info.flags &= ~CKF_TOKEN_PRESENT; slot->login_user = -1; - slot->card = NULL; + slot->p11card = NULL; if (token_was_present) slot->events = SC_EVENT_CARD_REMOVED; From 76517b7d433f6d9e4a16a2217974804c339ef692 Mon Sep 17 00:00:00 2001 From: German Blanco Date: Tue, 26 May 2015 21:44:13 +0200 Subject: [PATCH 281/306] Fixing part of the memory allocation problems in DNIe module. --- src/libopensc/card-dnie.c | 30 +++++----- src/libopensc/cwa-dnie.c | 115 +++++++++++++++++++++--------------- src/libopensc/cwa14890.c | 4 ++ src/libopensc/pkcs15-dnie.c | 14 +++-- 4 files changed, 94 insertions(+), 69 deletions(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index f6f1692b..313377b6 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -293,7 +293,7 @@ data_found: static int dnie_get_info(sc_card_t * card, char *data[]) { sc_file_t *file = NULL; - sc_path_t *path = NULL; + sc_path_t path; u8 *buffer = NULL; size_t bufferlen = 0; char *msg = NULL; @@ -309,14 +309,8 @@ static int dnie_get_info(sc_card_t * card, char *data[]) /* phase 1: get DNIe number, Name and GivenName */ /* read EF(CDF) at 3F0050156004 */ - path = (sc_path_t *) calloc(1, sizeof(sc_path_t)); - if (!path) { - msg = "Cannot allocate path data for EF(CDF) read"; - res = SC_ERROR_OUT_OF_MEMORY; - goto get_info_end; - } - sc_format_path("3F0050156004", path); - res = dnie_read_file(card, path, &file, &buffer, &bufferlen); + sc_format_path("3F0050156004", &path); + res = dnie_read_file(card, &path, &file, &buffer, &bufferlen); if (res != SC_SUCCESS) { msg = "Cannot read EF(CDF)"; goto get_info_end; @@ -334,7 +328,7 @@ static int dnie_get_info(sc_card_t * card, char *data[]) } /* phase 2: get IDESP */ - sc_format_path("3F000006", path); + sc_format_path("3F000006", &path); if (file) { sc_file_free(file); file = NULL; @@ -344,7 +338,7 @@ static int dnie_get_info(sc_card_t * card, char *data[]) buffer=NULL; bufferlen=0; } - res = dnie_read_file(card, path, &file, &buffer, &bufferlen); + res = dnie_read_file(card, &path, &file, &buffer, &bufferlen); if (res != SC_SUCCESS) { data[3]=NULL; goto get_info_ph3; @@ -359,7 +353,7 @@ static int dnie_get_info(sc_card_t * card, char *data[]) get_info_ph3: /* phase 3: get DNIe software version */ - sc_format_path("3F002F03", path); + sc_format_path("3F002F03", &path); if (file) { sc_file_free(file); file = NULL; @@ -373,7 +367,7 @@ get_info_ph3: * Some old DNIe cards seems not to include SW version file, * so let this code fail without notice */ - res = dnie_read_file(card, path, &file, &buffer, &bufferlen); + res = dnie_read_file(card, &path, &file, &buffer, &bufferlen); if (res != SC_SUCCESS) { msg = "Cannot read DNIe Version EF"; data[4]=NULL; @@ -395,10 +389,12 @@ get_info_ph3: get_info_end: if (file) { sc_file_free(file); - free(buffer); file = NULL; - buffer = NULL; - bufferlen = 0; + } + if (buffer) { + free(buffer); + buffer=NULL; + bufferlen=0; } if (msg) sc_log(card->ctx,msg); @@ -905,6 +901,8 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa if (file == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); res = card->ops->process_fci(card, file, apdu.resp + 2, apdu.resp[1]); + if (*file_out != NULL) + sc_file_free(*file_out); *file_out = file; LOG_FUNC_RETURN(ctx, res); } diff --git a/src/libopensc/cwa-dnie.c b/src/libopensc/cwa-dnie.c index f54ad22a..bc4870b0 100644 --- a/src/libopensc/cwa-dnie.c +++ b/src/libopensc/cwa-dnie.c @@ -265,6 +265,8 @@ int dnie_read_file(sc_card_t * card, res = SC_SUCCESS; goto dnie_read_file_end; dnie_read_file_err: + if (data) + free(data); if (*file) { sc_file_free(*file); *file = NULL; @@ -289,39 +291,37 @@ int dnie_read_file(sc_card_t * card, static int dnie_read_certificate(sc_card_t * card, char *certpath, X509 ** cert) { sc_file_t *file = NULL; - sc_path_t *path = NULL; - u8 *buffer = NULL; + sc_path_t path; + u8 *buffer = NULL, *buffer2 = NULL; char *msg = NULL; size_t bufferlen = 0; int res = SC_SUCCESS; LOG_FUNC_CALLED(card->ctx); - path = (sc_path_t *) calloc(1, sizeof(sc_path_t)); - if (!path) { - msg = "Cannot allocate path data for cert read"; - res = SC_ERROR_OUT_OF_MEMORY; - goto read_cert_end; - } - sc_format_path(certpath, path); - res = dnie_read_file(card, path, &file, &buffer, &bufferlen); + sc_format_path(certpath, &path); + res = dnie_read_file(card, &path, &file, &buffer, &bufferlen); if (res != SC_SUCCESS) { msg = "Cannot get intermediate CA cert"; goto read_cert_end; } - *cert = d2i_X509(NULL, (const unsigned char **)&buffer, bufferlen); + buffer2 = buffer; + *cert = d2i_X509(NULL, (const unsigned char **)&buffer2, bufferlen); if (*cert == NULL) { /* received data is not a certificate */ res = SC_ERROR_OBJECT_NOT_VALID; - msg = "Readed data is not a certificate"; + msg = "Read data is not a certificate"; goto read_cert_end; } res = SC_SUCCESS; read_cert_end: + if (buffer) { + free(buffer); + buffer = NULL; + bufferlen = 0; + } if (file) { sc_file_free(file); file = NULL; - buffer = NULL; - bufferlen = 0; } if (msg) sc_log(card->ctx, msg); @@ -690,7 +690,7 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card) static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) { - u8 buf[2048]; /* use for store partial le responses */ + u8 buf[2*SC_MAX_APDU_BUFFER_SIZE]; /* use for store partial le responses */ int res = SC_SUCCESS; cwa_provider_t *provider = NULL; if ((card == NULL) || (card->ctx == NULL) || (apdu == NULL)) @@ -711,8 +711,10 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) if (tmp == SC_APDU_CASE_3_SHORT) apdu->cse = SC_APDU_CASE_4_SHORT; if (apdu->resplen == 0) { /* no response buffer: create */ - apdu->resp = buf; - apdu->resplen = 2048; + apdu->resp = calloc(1, 2*SC_MAX_APDU_BUFFER_SIZE); + if (apdu->resp == NULL) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + apdu->resplen = 2*SC_MAX_APDU_BUFFER_SIZE; apdu->le = card->max_recv_size; } } @@ -724,17 +726,12 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) size_t e_txlen = 0; size_t index = 0; - sc_apdu_t *e_apdu = NULL; - u8 *e_tx = NULL; + sc_apdu_t e_apdu; + u8 e_tx[2*SC_MAX_APDU_BUFFER_SIZE]; /* envelope needed */ sc_log(card->ctx, "envelope tx required: lc:%d", apdu->lc); - e_apdu = calloc(1, sizeof(sc_apdu_t)); /* enveloped apdu */ - e_tx = calloc(7 + apdu->datalen, sizeof(u8)); /* enveloped data */ - if (!e_apdu || !e_tx) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); - /* copy apdu info into enveloped data */ *(e_tx + 0) = apdu->cla; /* apdu header */ *(e_tx + 1) = apdu->ins; @@ -753,35 +750,37 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) index, len); /* compose envelope apdu command */ - sc_format_apdu(card, e_apdu, apdu->cse, 0xC2, 0x00, - 0x00); - e_apdu->cla = 0x90; /* propietary CLA */ - e_apdu->data = e_tx + index; - e_apdu->lc = len; - e_apdu->datalen = len; - e_apdu->le = apdu->le; - e_apdu->resp = apdu->resp; - e_apdu->resplen = apdu->resplen; + sc_format_apdu(card, &e_apdu, apdu->cse, 0xC2, 0x00, 0x00); + e_apdu.cla = 0x90; /* propietary CLA */ + e_apdu.data = e_tx + index; + e_apdu.lc = len; + e_apdu.datalen = len; + e_apdu.le = apdu->le; + e_apdu.resp = apdu->resp; + e_apdu.resplen = apdu->resplen; /* if SM is ON, ensure resp exists, and force getResponse() */ if (provider->status.session.state == CWA_SM_ACTIVE) { /* set up proper apdu type */ - if (e_apdu->cse == SC_APDU_CASE_3_SHORT) - e_apdu->cse = SC_APDU_CASE_4_SHORT; + if (e_apdu.cse == SC_APDU_CASE_3_SHORT) + e_apdu.cse = SC_APDU_CASE_4_SHORT; /* if no response buffer: create */ if (apdu->resplen == 0) { - e_apdu->resp = buf; - e_apdu->resplen = 2048; - e_apdu->le = card->max_recv_size; + e_apdu.resp = buf; + e_apdu.resplen = 2048; + e_apdu.le = card->max_recv_size; } } /* send data chunk bypassing apdu wrapping */ - res = sc_transmit_apdu(card, e_apdu); + res = sc_transmit_apdu(card, &e_apdu); LOG_TEST_RET(card->ctx, res, "Error in envelope() send apdu"); } /* for */ /* last apdu sent contains response to enveloped cmd */ - apdu->resp = e_apdu->resp; - apdu->resplen = e_apdu->resplen; + apdu->resp = calloc(1, 2*SC_MAX_APDU_BUFFER_SIZE); + if (apdu->resp == NULL) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + memcpy(apdu->resp, e_apdu.resp, e_apdu.resplen); + apdu->resplen = e_apdu.resplen; res = SC_SUCCESS; } LOG_FUNC_RETURN(card->ctx, res); @@ -817,6 +816,7 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu) sc_context_t *ctx; cwa_provider_t *provider = NULL; int retries = 3; + char * msg = NULL; if ((card == NULL) || (card->ctx == NULL) || (apdu == NULL)) return SC_ERROR_INVALID_ARGUMENTS; @@ -831,13 +831,18 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu) wrapped.resp = NULL; wrapped.resplen = 0; /* let get_response() assign space */ res = cwa_encode_apdu(card, provider, apdu, &wrapped); - LOG_TEST_RET(ctx, res, - "Error in cwa_encode_apdu process"); + if (res != SC_SUCCESS) { + msg = "Error in cwa_encode_apdu process"; + goto cleanup_and_return; + } } /* send apdu via envelope() cmd if needed */ res = dnie_transmit_apdu_internal(card, &wrapped); /* check for tx errors */ - LOG_TEST_RET(ctx, res, "Error in dnie_transmit_apdu process"); + if (res != SC_SUCCESS) { + msg = "Error in dnie_transmit_apdu process"; + goto cleanup_and_return; + } /* parse response and handle SM related errors */ res=card->ops->check_sw(card,wrapped.sw1,wrapped.sw2); @@ -852,7 +857,10 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu) /* SM was active: force restart SM and retry */ case CWA_SM_ACTIVE: res=cwa_create_secure_channel(card, provider, CWA_SM_COLD); - LOG_TEST_RET(ctx,res,"Cannot re-enable SM"); + if (res != SC_SUCCESS) { + msg = "Cannot re-enable SM"; + goto cleanup_and_return; + } continue; } } @@ -862,15 +870,24 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu) apdu->resp = NULL; apdu->resplen = 0; /* let cwa_decode_response() eval & create size */ res = cwa_decode_response(card, provider, &wrapped, apdu); - LOG_TEST_RET(ctx, res, "Error in cwa_decode_response process"); + if (res != SC_SUCCESS) + msg = "Error in cwa_decode_response process"; + goto cleanup_and_return; } else { + if (apdu->resp != wrapped.resp) free(apdu->resp); /* memcopy result to original apdu */ memcpy(apdu, &wrapped, sizeof(sc_apdu_t)); + LOG_FUNC_RETURN(ctx, res); } - LOG_FUNC_RETURN(ctx, res); } - sc_log(ctx,"Too many retransmissions. Abort and return"); - LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); + msg = "Too many retransmissions. Abort and return"; + res = SC_ERROR_INTERNAL; + +cleanup_and_return: + if (apdu->resp != wrapped.resp) free(wrapped.resp); + if (msg) + sc_log(ctx, msg); + LOG_FUNC_RETURN(ctx, res); } int dnie_transmit_apdu(sc_card_t * card, sc_apdu_t * apdu) diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index 800ed6fc..2d7e27f5 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -1397,6 +1397,10 @@ int cwa_create_secure_channel(sc_card_t * card, /* arriving here means ok: cleanup */ res = SC_SUCCESS; csc_end: + if (icc_cert) + X509_free(icc_cert); + if (ca_cert) + X509_free(ca_cert); if (icc_pubkey) EVP_PKEY_free(icc_pubkey); if (ifd_privkey) diff --git a/src/libopensc/pkcs15-dnie.c b/src/libopensc/pkcs15-dnie.c index c295c305..8be431fe 100644 --- a/src/libopensc/pkcs15-dnie.c +++ b/src/libopensc/pkcs15-dnie.c @@ -42,13 +42,19 @@ int dump_ef(sc_card_t * card, const char *path, u8 * buf, size_t * buf_len) { int rv; sc_file_t *file = sc_file_new(); - sc_format_path(path, &file->path); - rv = sc_select_file(card, &file->path, &file); - if (rv < 0) + sc_path_t scpath; + sc_format_path(path, &scpath); + rv = sc_select_file(card, &scpath, &file); + if (rv < 0) { + sc_file_free(file); return rv; - if (file->size > *buf_len) + } + if (file->size > *buf_len) { + sc_file_free(file); return SC_ERROR_BUFFER_TOO_SMALL; + } rv = sc_read_binary(card, 0, buf, file->size, 0); + sc_file_free(file); if (rv < 0) return rv; *buf_len = rv; From 0d14f3ffeed7e9c519df246b57b22d9501efccbc Mon Sep 17 00:00:00 2001 From: German Blanco Date: Mon, 1 Jun 2015 07:46:59 +0200 Subject: [PATCH 282/306] Correct initializing of a variable in card-dnie and revert buffer size change in cwa-dnie. --- src/libopensc/card-dnie.c | 4 ++-- src/libopensc/cwa-dnie.c | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 313377b6..f4d6991b 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -392,8 +392,8 @@ get_info_end: file = NULL; } if (buffer) { - free(buffer); - buffer=NULL; + free(buffer); + buffer=NULL; bufferlen=0; } if (msg) diff --git a/src/libopensc/cwa-dnie.c b/src/libopensc/cwa-dnie.c index bc4870b0..6f0a8a8e 100644 --- a/src/libopensc/cwa-dnie.c +++ b/src/libopensc/cwa-dnie.c @@ -42,6 +42,8 @@ #include #include +#define MAX_RESP_BUFFER_SIZE 2048 + /********************* Keys and certificates as published by DGP ********/ /** @@ -209,7 +211,7 @@ int dnie_read_file(sc_card_t * card, const sc_path_t * path, sc_file_t ** file, u8 ** buffer, size_t * length) { - u8 *data; + u8 *data = NULL; char *msg = NULL; int res = SC_SUCCESS; size_t fsize = 0; /* file size */ @@ -690,7 +692,7 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card) static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) { - u8 buf[2*SC_MAX_APDU_BUFFER_SIZE]; /* use for store partial le responses */ + u8 buf[MAX_RESP_BUFFER_SIZE]; /* use for store partial le responses */ int res = SC_SUCCESS; cwa_provider_t *provider = NULL; if ((card == NULL) || (card->ctx == NULL) || (apdu == NULL)) @@ -711,10 +713,10 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) if (tmp == SC_APDU_CASE_3_SHORT) apdu->cse = SC_APDU_CASE_4_SHORT; if (apdu->resplen == 0) { /* no response buffer: create */ - apdu->resp = calloc(1, 2*SC_MAX_APDU_BUFFER_SIZE); + apdu->resp = calloc(1, MAX_RESP_BUFFER_SIZE); if (apdu->resp == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); - apdu->resplen = 2*SC_MAX_APDU_BUFFER_SIZE; + apdu->resplen = MAX_RESP_BUFFER_SIZE; apdu->le = card->max_recv_size; } } @@ -776,7 +778,7 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) "Error in envelope() send apdu"); } /* for */ /* last apdu sent contains response to enveloped cmd */ - apdu->resp = calloc(1, 2*SC_MAX_APDU_BUFFER_SIZE); + apdu->resp = calloc(1, MAX_RESP_BUFFER_SIZE); if (apdu->resp == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(apdu->resp, e_apdu.resp, e_apdu.resplen); From 030f4d15597c2558c08175caec605716514a6eff Mon Sep 17 00:00:00 2001 From: German Blanco Date: Mon, 1 Jun 2015 08:21:25 +0200 Subject: [PATCH 283/306] Empty user-interface.c if there is no SSL support. --- src/libopensc/user-interface.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libopensc/user-interface.c b/src/libopensc/user-interface.c index a8719e7d..dd3c7c09 100644 --- a/src/libopensc/user-interface.c +++ b/src/libopensc/user-interface.c @@ -29,6 +29,8 @@ #include "config.h" #endif +#ifdef ENABLE_OPENSSL /* empty file without openssl */ + #include #include #include @@ -318,4 +320,6 @@ do_error: LOG_FUNC_RETURN(card->ctx, res); } -#endif +#endif /* ENABLE_DNIE_UI */ + +#endif /* ENABLE_OPENSSL */ From e5ae77cae32fdcc7a23d6bd0013c2fd115a43591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20Ho=CC=88rberg?= Date: Wed, 17 Jun 2015 16:27:03 +0200 Subject: [PATCH 284/306] Restore compability on os x Fallback to /System/Library/Frameworks/PCSC.framework/Versions/Current/Headers when there are no OS X SDKs installed. Fixes bugs introduced in #308 --- configure.ac | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index f0bbb3eb..67aa5c45 100644 --- a/configure.ac +++ b/configure.ac @@ -540,10 +540,13 @@ if test "${enable_pcsc}" = "yes"; then case "${host}" in *-*-darwin*) # Locate the latest SDK. - SDKS_PATH="$(xcode-select -p)/Platforms/MacOSX.platform/Developer/SDKs" - SDK_PATH="${SDK_PATH:-$SDKS_PATH/$(ls -1 ${SDKS_PATH} | sort -n -t. -k2 -r | head -1)}" - # and set the PC/SC include path - PCSC_CFLAGS="-I$SDK_PATH/System/Library/Frameworks/PCSC.framework/Versions/Current/Headers" + SDKS_PATH="$(xcode-select --print-path)/Platforms/MacOSX.platform/Developer/SDKs" + if test -d $SDKS_PATH; then + SDK_PATH="${SDK_PATH:-$SDKS_PATH/$(ls -1 ${SDKS_PATH} | sort -n -t. -k2 -r | head -1)}" + PCSC_CFLAGS="-I$SDK_PATH/System/Library/Frameworks/PCSC.framework/Versions/Current/Headers" + else + PCSC_CFLAGS="-I/System/Library/Frameworks/PCSC.framework/Headers" + fi ;; *) PCSC_CFLAGS="-I/usr/include/PCSC" From 5898eab3732f73550b36b6dae4a947dfd0c6f4e2 Mon Sep 17 00:00:00 2001 From: Hubitronic Date: Thu, 18 Jun 2015 16:28:11 +0200 Subject: [PATCH 285/306] Update card-muscle.c re-enable opensc.conf flexibility again --- src/libopensc/card-muscle.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libopensc/card-muscle.c b/src/libopensc/card-muscle.c index 8c92dcc1..d3e94a03 100644 --- a/src/libopensc/card-muscle.c +++ b/src/libopensc/card-muscle.c @@ -476,8 +476,7 @@ static int muscle_init(sc_card_t *card) card->caps |= SC_CARD_CAP_RNG; /* Card type detection */ - if (SC_SUCCESS != _sc_match_atr(card, muscle_atrs, &card->type)) - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_CARD); + _sc_match_atr(card, muscle_atrs, &card->type); if(card->type == SC_CARD_TYPE_MUSCLE_ETOKEN_72K) { card->caps |= SC_CARD_CAP_APDU_EXT; From 317cc302db8979d6365372a21774691aef857298 Mon Sep 17 00:00:00 2001 From: German Blanco Date: Fri, 10 Jul 2015 12:38:22 +0200 Subject: [PATCH 286/306] making the size of e_tx in cwa-dnie.c dynamic --- src/libopensc/cwa-dnie.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/libopensc/cwa-dnie.c b/src/libopensc/cwa-dnie.c index 6f0a8a8e..68a15a3f 100644 --- a/src/libopensc/cwa-dnie.c +++ b/src/libopensc/cwa-dnie.c @@ -729,11 +729,16 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) size_t e_txlen = 0; size_t index = 0; sc_apdu_t e_apdu; - u8 e_tx[2*SC_MAX_APDU_BUFFER_SIZE]; + u8 * e_tx = NULL; /* envelope needed */ sc_log(card->ctx, "envelope tx required: lc:%d", apdu->lc); + e_tx = calloc(7 + apdu->datalen, sizeof(u8)); /* enveloped data */ + + if (!e_tx) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + /* copy apdu info into enveloped data */ *(e_tx + 0) = apdu->cla; /* apdu header */ *(e_tx + 1) = apdu->ins; @@ -774,9 +779,19 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu) } /* send data chunk bypassing apdu wrapping */ res = sc_transmit_apdu(card, &e_apdu); - LOG_TEST_RET(card->ctx, res, - "Error in envelope() send apdu"); + if (res != SC_SUCCESS) { + if (e_tx) { + free(e_tx); + e_tx = NULL; + } + sc_log(card->ctx, "Error in envelope() send apdu"); + LOG_FUNC_RETURN(card->ctx, res); + } } /* for */ + if (e_tx) { + free(e_tx); + e_tx = NULL; + } /* last apdu sent contains response to enveloped cmd */ apdu->resp = calloc(1, MAX_RESP_BUFFER_SIZE); if (apdu->resp == NULL) From edc839e072a5b16abc52ab73d60748c87b0fd4e0 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 22 Jul 2015 01:28:48 +0200 Subject: [PATCH 287/306] restrict access to card handles after fork fixes #333 closes #493 --- src/libopensc/opensc.h | 10 ++++++++++ src/libopensc/reader-ctapi.c | 13 ++++++++++++- src/libopensc/reader-openct.c | 22 ++++++++++++++++++++-- src/libopensc/reader-pcsc.c | 32 +++++++++++++++++++++++++++----- src/pkcs11/pkcs11-global.c | 4 +++- 5 files changed, 72 insertions(+), 9 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index ad5405d5..083195a0 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -639,6 +639,16 @@ typedef struct { unsigned long (*thread_id)(void); } sc_thread_context_t; +/** Stop modifing or using external resources + * + * Currently this is used to avoid freeing duplicated external resources for a + * process that has been forked. For example, a child process may want to leave + * the duplicated card handles for the parent process. With this flag the child + * process indicates that shall the reader shall ignore those resources when + * calling sc_disconnect_card. + */ +#define SC_TERMINATE 0x00000001 + typedef struct sc_context { scconf_context *conf; scconf_block *conf_blocks[3]; diff --git a/src/libopensc/reader-ctapi.c b/src/libopensc/reader-ctapi.c index 919c3f0e..68de2b2d 100644 --- a/src/libopensc/reader-ctapi.c +++ b/src/libopensc/reader-ctapi.c @@ -116,6 +116,9 @@ static int refresh_attributes(sc_reader_t *reader) u8 cmd[5], rbuf[256], sad, dad; unsigned short lr; + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + cmd[0] = CTBCS_CLA; cmd[1] = CTBCS_INS_STATUS; cmd[2] = CTBCS_P1_CT_KERNEL; @@ -158,6 +161,9 @@ static int ctapi_internal_transmit(sc_reader_t *reader, u8 dad, sad; unsigned short lr; char rv; + + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; if (control) dad = 1; @@ -235,6 +241,9 @@ static int ctapi_connect(sc_reader_t *reader) unsigned short lr; int r; + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + cmd[0] = CTBCS_CLA; cmd[1] = CTBCS_INS_REQUEST; cmd[2] = CTBCS_P1_INTERFACE1; @@ -280,7 +289,9 @@ static int ctapi_release(sc_reader_t *reader) { struct ctapi_private_data *priv = GET_PRIV_DATA(reader); - priv->funcs.CT_close(priv->ctn); + + if (!(reader->ctx->magic & SC_TERMINATE)) + priv->funcs.CT_close(priv->ctn); free(priv); return 0; diff --git a/src/libopensc/reader-openct.c b/src/libopensc/reader-openct.c index a276d52b..faa8288a 100644 --- a/src/libopensc/reader-openct.c +++ b/src/libopensc/reader-openct.c @@ -154,7 +154,7 @@ static int openct_reader_release(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); if (data) { - if (data->h) + if (data->h && !(reader->ctx->magic & SC_TERMINATE)) ct_reader_disconnect(data->h); sc_mem_clear(data, sizeof(*data)); reader->drv_data = NULL; @@ -174,6 +174,9 @@ static int openct_reader_detect_card_presence(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + reader->flags = 0; if (!data->h && !(data->h = ct_reader_connect(data->num))) return 0; @@ -197,6 +200,9 @@ openct_reader_connect(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + if (data->h) ct_reader_disconnect(data->h); @@ -242,7 +248,7 @@ static int openct_reader_disconnect(sc_reader_t *reader) struct driver_data *data = (struct driver_data *) reader->drv_data; SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); - if (data->h) + if (data->h && !(reader->flags & SC_TERMINATE)) ct_reader_disconnect(data->h); data->h = NULL; return SC_SUCCESS; @@ -256,6 +262,9 @@ openct_reader_internal_transmit(sc_reader_t *reader, struct driver_data *data = (struct driver_data *) reader->drv_data; int rc; + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + /* Hotplug check */ if ((rc = openct_reader_reconnect(reader)) < 0) return rc; @@ -324,6 +333,9 @@ static int openct_reader_perform_verify(sc_reader_t *reader, struct sc_pin_cmd_d u8 buf[254]; int rc; + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + /* Hotplug check */ if ((rc = openct_reader_reconnect(reader)) < 0) return rc; @@ -382,6 +394,9 @@ static int openct_reader_lock(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + /* Hotplug check */ if ((rc = openct_reader_reconnect(reader)) < 0) return rc; @@ -408,6 +423,9 @@ static int openct_reader_unlock(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + /* Not connected */ if (data->h == NULL) return 0; diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 73824525..a5ff6975 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -184,6 +184,9 @@ static int pcsc_internal_transmit(sc_reader_t *reader, SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); card = priv->pcsc_card; + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + sSendPci.dwProtocol = opensc_proto_to_pcsc(reader->active_protocol); sSendPci.cbPciLength = sizeof(sSendPci); sRecvPci.dwProtocol = opensc_proto_to_pcsc(reader->active_protocol); @@ -284,6 +287,9 @@ static int refresh_attributes(sc_reader_t *reader) sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "%s check", reader->name); + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + if (priv->reader_state.szReader == NULL) { priv->reader_state.szReader = reader->name; priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE; @@ -505,7 +511,8 @@ static int pcsc_disconnect(sc_reader_t * reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); - priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action); + if (!(reader->ctx->magic & SC_TERMINATE)) + priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action); reader->flags = 0; return SC_SUCCESS; } @@ -518,6 +525,9 @@ static int pcsc_lock(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + rv = priv->gpriv->SCardBeginTransaction(priv->pcsc_card); switch (rv) { @@ -555,6 +565,9 @@ static int pcsc_unlock(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + rv = priv->gpriv->SCardEndTransaction(priv->pcsc_card, priv->gpriv->transaction_end_action); priv->locked = 0; @@ -597,12 +610,18 @@ static int pcsc_cancel(sc_context_t *ctx) struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *)ctx->reader_drv_data; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); + + if (ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + #ifndef _WIN32 if (gpriv->pcsc_wait_ctx != -1) { rv = gpriv->SCardCancel(gpriv->pcsc_wait_ctx); - if (rv == SCARD_S_SUCCESS) + if (rv == SCARD_S_SUCCESS) { /* Also close and clear the waiting context */ rv = gpriv->SCardReleaseContext(gpriv->pcsc_wait_ctx); + gpriv->pcsc_wait_ctx = -1; + } } #else rv = gpriv->SCardCancel(gpriv->pcsc_ctx); @@ -747,7 +766,7 @@ static int pcsc_finish(sc_context_t *ctx) SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); if (gpriv) { - if (gpriv->pcsc_ctx != -1) + if (gpriv->pcsc_ctx != -1 && !(ctx->magic & SC_TERMINATE)) gpriv->SCardReleaseContext(gpriv->pcsc_ctx); if (gpriv->dlhandle != NULL) sc_dlclose(gpriv->dlhandle); @@ -1643,6 +1662,9 @@ pcsc_pin_cmd(sc_reader_t *reader, struct sc_pin_cmd_data *data) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); + if (reader->ctx->magic & SC_TERMINATE) + return SC_ERROR_NOT_ALLOWED; + if (priv->gpriv->SCardControl == NULL) return SC_ERROR_NOT_SUPPORTED; @@ -1932,8 +1954,8 @@ static int transform_pace_output(u8 *rbuf, size_t rbuflen, static int pcsc_perform_pace(struct sc_reader *reader, void *input_pace, void *output_pace) { - struct establish_pace_channel_input *pace_input = (struct establish_pace_channel_input *) input_pace; - struct establish_pace_channel_output *pace_output = (struct establish_pace_channel_output *) output_pace; + struct establish_pace_channel_input *pace_input = (struct establish_pace_channel_input *) input_pace; + struct establish_pace_channel_output *pace_output = (struct establish_pace_channel_output *) output_pace; struct pcsc_private_data *priv; u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE], sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; size_t rcount = sizeof rbuf, scount = sizeof sbuf; diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index ee6cf7c4..364313bf 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -202,9 +202,11 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs) unsigned int i; sc_context_param_t ctx_opts; - /* Handle fork() exception */ #if !defined(_WIN32) + /* Handle fork() exception */ if (current_pid != initialized_pid) { + if (context) + context->magic |= SC_TERMINATE; C_Finalize(NULL_PTR); } initialized_pid = current_pid; From 7cec500e549471cdbac2905eb6f5ae50cba2a4ee Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 22 Jul 2015 17:25:35 +0200 Subject: [PATCH 288/306] added flags to sc_context_t - is initialized in sc_context_create with parm->flags - removes members paranoid_memory and enable_default_driver --- configure.ac | 4 ++-- src/libopensc/card.c | 3 ++- src/libopensc/ctx.c | 15 +++++++++------ src/libopensc/opensc.h | 10 ++++++---- src/libopensc/reader-ctapi.c | 8 ++++---- src/libopensc/reader-openct.c | 14 +++++++------- src/libopensc/reader-pcsc.c | 16 ++++++++-------- src/libopensc/sc.c | 2 +- src/pkcs11/pkcs11-global.c | 2 +- src/tools/opensc-explorer.c | 2 +- src/tools/opensc-tool.c | 2 +- 11 files changed, 42 insertions(+), 36 deletions(-) diff --git a/configure.ac b/configure.ac index f0bbb3eb..4953e206 100644 --- a/configure.ac +++ b/configure.ac @@ -39,8 +39,8 @@ OPENSC_VS_FF_PRODUCT_NAME="VS_FF_PRODUCT_NAME" # (Code changed: REVISION++) # (Oldest interface removed: OLDEST++) # (Interfaces added: CURRENT++, REVISION=0) -OPENSC_LT_CURRENT="3" -OPENSC_LT_OLDEST="3" +OPENSC_LT_CURRENT="4" +OPENSC_LT_OLDEST="4" OPENSC_LT_REVISION="0" OPENSC_LT_AGE="0" OPENSC_LT_AGE="$((${OPENSC_LT_CURRENT}-${OPENSC_LT_OLDEST}))" diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 7daee5c5..7e1d8ad2 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -218,7 +218,8 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) if (ops == NULL || ops->match_card == NULL) { continue; } - else if (!ctx->enable_default_driver && !strcmp("default", drv->short_name)) { + else if (!(ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER) + && !strcmp("default", drv->short_name)) { sc_log(ctx , "ignore 'default' card driver"); continue; } diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 46700084..71216685 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -186,8 +186,7 @@ static void set_defaults(sc_context_t *ctx, struct _sc_ctx_options *opts) if (ctx->debug_file && (ctx->debug_file != stderr && ctx->debug_file != stdout)) fclose(ctx->debug_file); ctx->debug_file = stderr; - ctx->paranoid_memory = 0; - ctx->enable_default_driver = 0; + ctx->flags = 0; #ifdef __APPLE__ /* Override the default debug log for OpenSC.tokend to be different from PKCS#11. @@ -258,11 +257,13 @@ load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options * sc_ctx_log_to_file(ctx, val); } - ctx->paranoid_memory = scconf_get_bool (block, "paranoid-memory", - ctx->paranoid_memory); + if (scconf_get_bool (block, "paranoid-memory", + ctx->flags & SC_CTX_FLAG_PARANOID_MEMORY)) + ctx->flags |= SC_CTX_FLAG_PARANOID_MEMORY; - ctx->enable_default_driver = scconf_get_bool (block, "enable_default_driver", - ctx->enable_default_driver); + if (scconf_get_bool (block, "enable_default_driver", + ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER)) + ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER; val = scconf_get_str(block, "force_card_driver", NULL); if (val) { @@ -710,7 +711,9 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm) return SC_ERROR_OUT_OF_MEMORY; } + ctx->flags = parm->flags; set_defaults(ctx, &opts); + list_init(&ctx->readers); list_attributes_seeker(&ctx->readers, reader_list_seeker); /* set thread context and create mutex object (if specified) */ diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 083195a0..c7074e58 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -647,15 +647,17 @@ typedef struct { * process indicates that shall the reader shall ignore those resources when * calling sc_disconnect_card. */ -#define SC_TERMINATE 0x00000001 +#define SC_CTX_FLAG_TERMINATE 0x00000001 +#define SC_CTX_FLAG_PARANOID_MEMORY 0x00000002 +#define SC_CTX_FLAG_DEBUG_MEMORY 0x00000004 +#define SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER 0x00000008 typedef struct sc_context { scconf_context *conf; scconf_block *conf_blocks[3]; char *app_name; int debug; - int paranoid_memory; - int enable_default_driver; + unsigned long flags; FILE *debug_file; char *debug_filename; @@ -729,7 +731,7 @@ typedef struct { * dependend configuration data). If NULL the name "default" * will be used. */ const char *app_name; - /** flags, currently unused */ + /** context flags */ unsigned long flags; /** mutex functions to use (optional) */ sc_thread_context_t *thread_ctx; diff --git a/src/libopensc/reader-ctapi.c b/src/libopensc/reader-ctapi.c index 68de2b2d..c526500d 100644 --- a/src/libopensc/reader-ctapi.c +++ b/src/libopensc/reader-ctapi.c @@ -116,7 +116,7 @@ static int refresh_attributes(sc_reader_t *reader) u8 cmd[5], rbuf[256], sad, dad; unsigned short lr; - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; cmd[0] = CTBCS_CLA; @@ -162,7 +162,7 @@ static int ctapi_internal_transmit(sc_reader_t *reader, unsigned short lr; char rv; - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; if (control) @@ -241,7 +241,7 @@ static int ctapi_connect(sc_reader_t *reader) unsigned short lr; int r; - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; cmd[0] = CTBCS_CLA; @@ -290,7 +290,7 @@ static int ctapi_release(sc_reader_t *reader) struct ctapi_private_data *priv = GET_PRIV_DATA(reader); - if (!(reader->ctx->magic & SC_TERMINATE)) + if (!(reader->ctx->flags & SC_CTX_FLAG_TERMINATE)) priv->funcs.CT_close(priv->ctn); free(priv); diff --git a/src/libopensc/reader-openct.c b/src/libopensc/reader-openct.c index faa8288a..2d7d6bd9 100644 --- a/src/libopensc/reader-openct.c +++ b/src/libopensc/reader-openct.c @@ -154,7 +154,7 @@ static int openct_reader_release(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); if (data) { - if (data->h && !(reader->ctx->magic & SC_TERMINATE)) + if (data->h && !(reader->ctx->flags & SC_CTX_FLAG_TERMINATE)) ct_reader_disconnect(data->h); sc_mem_clear(data, sizeof(*data)); reader->drv_data = NULL; @@ -174,7 +174,7 @@ static int openct_reader_detect_card_presence(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; reader->flags = 0; @@ -200,7 +200,7 @@ openct_reader_connect(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; if (data->h) @@ -262,7 +262,7 @@ openct_reader_internal_transmit(sc_reader_t *reader, struct driver_data *data = (struct driver_data *) reader->drv_data; int rc; - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; /* Hotplug check */ @@ -333,7 +333,7 @@ static int openct_reader_perform_verify(sc_reader_t *reader, struct sc_pin_cmd_d u8 buf[254]; int rc; - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; /* Hotplug check */ @@ -394,7 +394,7 @@ static int openct_reader_lock(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; /* Hotplug check */ @@ -423,7 +423,7 @@ static int openct_reader_unlock(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; /* Not connected */ diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index a5ff6975..67dc2802 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -184,7 +184,7 @@ static int pcsc_internal_transmit(sc_reader_t *reader, SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); card = priv->pcsc_card; - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; sSendPci.dwProtocol = opensc_proto_to_pcsc(reader->active_protocol); @@ -287,7 +287,7 @@ static int refresh_attributes(sc_reader_t *reader) sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "%s check", reader->name); - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; if (priv->reader_state.szReader == NULL) { @@ -511,7 +511,7 @@ static int pcsc_disconnect(sc_reader_t * reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); - if (!(reader->ctx->magic & SC_TERMINATE)) + if (!(reader->ctx->flags & SC_CTX_FLAG_TERMINATE)) priv->gpriv->SCardDisconnect(priv->pcsc_card, priv->gpriv->disconnect_action); reader->flags = 0; return SC_SUCCESS; @@ -525,7 +525,7 @@ static int pcsc_lock(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; rv = priv->gpriv->SCardBeginTransaction(priv->pcsc_card); @@ -565,7 +565,7 @@ static int pcsc_unlock(sc_reader_t *reader) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; rv = priv->gpriv->SCardEndTransaction(priv->pcsc_card, priv->gpriv->transaction_end_action); @@ -611,7 +611,7 @@ static int pcsc_cancel(sc_context_t *ctx) SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); - if (ctx->magic & SC_TERMINATE) + if (ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; #ifndef _WIN32 @@ -766,7 +766,7 @@ static int pcsc_finish(sc_context_t *ctx) SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); if (gpriv) { - if (gpriv->pcsc_ctx != -1 && !(ctx->magic & SC_TERMINATE)) + if (gpriv->pcsc_ctx != -1 && !(ctx->flags & SC_CTX_FLAG_TERMINATE)) gpriv->SCardReleaseContext(gpriv->pcsc_ctx); if (gpriv->dlhandle != NULL) sc_dlclose(gpriv->dlhandle); @@ -1662,7 +1662,7 @@ pcsc_pin_cmd(sc_reader_t *reader, struct sc_pin_cmd_data *data) SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_NORMAL); - if (reader->ctx->magic & SC_TERMINATE) + if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; if (priv->gpriv->SCardControl == NULL) diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 052d6ebc..5cddd32e 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -806,7 +806,7 @@ void *sc_mem_alloc_secure(sc_context_t *ctx, size_t len) locked = 1; #endif if (!locked) { - if (ctx->paranoid_memory) { + if (ctx->flags & SC_CTX_FLAG_PARANOID_MEMORY) { sc_do_log (ctx, 0, NULL, 0, NULL, "cannot lock memory, failing allocation because paranoid set"); free (pointer); pointer = NULL; diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 364313bf..2416f3fa 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -206,7 +206,7 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs) /* Handle fork() exception */ if (current_pid != initialized_pid) { if (context) - context->magic |= SC_TERMINATE; + context->flags |= SC_CTX_FLAG_TERMINATE; C_Finalize(NULL_PTR); } initialized_pid = current_pid; diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index fa2581bb..75588df7 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1836,7 +1836,7 @@ int main(int argc, char * const argv[]) return 1; } - ctx->enable_default_driver = 1; + ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER; if (verbose > 1) { ctx->debug = verbose; diff --git a/src/tools/opensc-tool.c b/src/tools/opensc-tool.c index d9079840..aea526e5 100644 --- a/src/tools/opensc-tool.c +++ b/src/tools/opensc-tool.c @@ -758,7 +758,7 @@ int main(int argc, char * const argv[]) return 1; } - ctx->enable_default_driver = 1; + ctx->flags |= SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER; if (verbose > 1) { ctx->debug = verbose; From 4dfbf24a3ef3eb9ee0760db401c14852c82370e1 Mon Sep 17 00:00:00 2001 From: Andreas Jellinghaus Date: Sun, 26 Jul 2015 21:34:51 +0200 Subject: [PATCH 289/306] Fix regression test suite: rename parameters to new names. Signed-off-by: Andreas Jellinghaus --- src/tests/regression/functions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/regression/functions b/src/tests/regression/functions index 1b0adab4..65189a1e 100755 --- a/src/tests/regression/functions +++ b/src/tests/regression/functions @@ -255,7 +255,7 @@ EOF function p15_erase { msg "Erasing card ($*)" - run_display_output $p15init --erase \ + run_display_output $p15init --erase-card \ --secret @FF=999999 \ "$@" >&3 >&4 success @@ -356,6 +356,6 @@ function p15_validate { msg "Validating card using pkcs11-tool" run_display_output $p11tool -t --login --pin 0000 \ --module $p11module \ - --slot-label "OpenSC Test Card" $* < /dev/null + --token-label "OpenSC Test Card" $* < /dev/null success } From 9fed9591caab588f3ca913eb1617f3571954c449 Mon Sep 17 00:00:00 2001 From: Andreas Jellinghaus Date: Sun, 26 Jul 2015 21:35:29 +0200 Subject: [PATCH 290/306] Fix regression test crypt0007: it deals with 1024 bit keys (not 1048). Signed-off-by: Andreas Jellinghaus --- src/tests/regression/crypt0007 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/regression/crypt0007 b/src/tests/regression/crypt0007 index 74409658..5f832439 100755 --- a/src/tests/regression/crypt0007 +++ b/src/tests/regression/crypt0007 @@ -10,7 +10,7 @@ msg < Date: Mon, 27 Jul 2015 16:15:33 +0200 Subject: [PATCH 291/306] avoid double detecting card on uninitialized reader initialize_reader already calls detect_card --- src/pkcs11/slot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 283e3b6a..857252c3 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -345,7 +345,8 @@ card_detect_all(void) } else { if (!reader_get_slot(reader)) initialize_reader(reader); - card_detect(sc_ctx_get_reader(context, i)); + else + card_detect(sc_ctx_get_reader(context, i)); } } sc_log(context, "All cards detected"); From b3dc5ea32a66d0429f3e2ef0f133ecfc619f8d4a Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 27 Jul 2015 18:43:51 +0200 Subject: [PATCH 292/306] fixed segfault for uninitialized IsoApplet fixes #400 --- src/pkcs11/pkcs11-global.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index ee6cf7c4..a01cbab7 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -582,7 +582,8 @@ CK_RV C_InitToken(CK_SLOT_ID slotID, goto out; } - if (slot->p11card->framework->init_token == NULL) { + if (!slot->p11card || !slot->p11card->framework + || !slot->p11card->framework->init_token) { sc_log(context, "C_InitToken() not supported by framework"); rv = CKR_FUNCTION_NOT_SUPPORTED; goto out; From 6d21903c907fff5d88314c962245776f37845dd8 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 27 Jul 2015 19:10:34 +0200 Subject: [PATCH 293/306] documented pkcs11_enable_InitToken flag --- etc/opensc.conf.in | 4 ++++ etc/opensc.conf.win.in | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in index 4f81b93d..c14107a8 100644 --- a/etc/opensc.conf.in +++ b/etc/opensc.conf.in @@ -202,6 +202,10 @@ app default { # # flags = "rng", "0x80000000"; + # Enable pkcs11 initialization. + # Default: no + # pkcs11_enable_InitToken = yes; + # # Context: PKCS#15 emulation layer # diff --git a/etc/opensc.conf.win.in b/etc/opensc.conf.win.in index fb648c75..b1efb221 100644 --- a/etc/opensc.conf.win.in +++ b/etc/opensc.conf.win.in @@ -202,6 +202,10 @@ app default { # # flags = "rng", "0x80000000"; + # Enable pkcs11 initialization. + # Default: no + # pkcs11_enable_InitToken = yes; + # # Context: PKCS#15 emulation layer # From b44c98e4d80d20451e015168a40ed8281392c4ed Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 28 Jul 2015 09:10:54 +0200 Subject: [PATCH 294/306] asn1: fixed parsing "end of content" fixes #190 --- src/libopensc/asn1.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 6938f193..bc8e9005 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -67,9 +67,12 @@ int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out, if (left < 2) return SC_ERROR_INVALID_ASN1_OBJECT; *buf = NULL; - if (*p == 0xff || *p == 0) + if (*p == 0xff || *p == 0) { /* end of data reached */ + *taglen = 0; + *tag_out = SC_ASN1_TAG_EOC; return SC_SUCCESS; + } /* parse tag byte(s) */ cla = (*p & SC_ASN1_TAG_CLASS) | (*p & SC_ASN1_TAG_CONSTRUCTED); tag = *p & SC_ASN1_TAG_PRIMITIVE; From c92e3b4f9820c39209bb63e9b484c8afd103fe20 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 28 Jul 2015 09:49:44 +0200 Subject: [PATCH 295/306] honour PC/SC pt 10 dwMaxAPDUDataSize closes #306 --- src/libopensc/card.c | 8 ++--- src/libopensc/ctx.c | 25 +++++++++++---- src/libopensc/internal-winscard.h | 1 + src/libopensc/opensc.h | 4 +-- src/libopensc/reader-pcsc.c | 52 ++++++++++++++++++++++++++++++- 5 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 7daee5c5..2cb16f69 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -254,12 +254,12 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) * Note that zero means no limitations at all. */ if ((card->max_recv_size == 0) || - ((reader->driver->max_recv_size != 0) && (reader->driver->max_recv_size < card->max_recv_size))) - card->max_recv_size = reader->driver->max_recv_size; + ((reader->max_recv_size != 0) && (reader->max_recv_size < card->max_recv_size))) + card->max_recv_size = reader->max_recv_size; if ((card->max_send_size == 0) || - ((reader->driver->max_send_size != 0) && (reader->driver->max_send_size < card->max_send_size))) - card->max_send_size = reader->driver->max_send_size; + ((reader->max_send_size != 0) && (reader->max_send_size < card->max_send_size))) + card->max_send_size = reader->max_send_size; sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", card->name, card->type, card->flags, card->max_send_size, card->max_recv_size); diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 46700084..5595dc4f 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -289,15 +289,28 @@ static void load_reader_driver_options(sc_context_t *ctx) { struct sc_reader_driver *driver = ctx->reader_driver; scconf_block *conf_block = NULL; - - driver->max_send_size = 0; - driver->max_recv_size = 0; + sc_reader_t *reader; + int max_send_size; + int max_recv_size; conf_block = sc_get_conf_block(ctx, "reader_driver", driver->short_name, 1); if (conf_block != NULL) { - driver->max_send_size = scconf_get_int(conf_block, "max_send_size", driver->max_send_size); - driver->max_recv_size = scconf_get_int(conf_block, "max_recv_size", driver->max_recv_size); + max_send_size = scconf_get_int(conf_block, "max_send_size", -1); + max_recv_size = scconf_get_int(conf_block, "max_recv_size", -1); + if (max_send_size >= 0 || max_recv_size >= 0) { + if (list_iterator_start(&ctx->readers)) { + reader = list_iterator_next(&ctx->readers); + while (reader) { + if (max_send_size >= 0) + reader->max_send_size = max_send_size; + if (max_recv_size >= 0) + reader->max_recv_size = max_recv_size; + reader = list_iterator_next(&ctx->readers); + } + list_iterator_stop(&ctx->readers); + } + } } } @@ -739,7 +752,6 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm) ctx->reader_driver = sc_get_openct_driver(); #endif - load_reader_driver_options(ctx); r = ctx->reader_driver->ops->init(ctx); if (r != SC_SUCCESS) { sc_release_context(ctx); @@ -755,6 +767,7 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm) } del_drvs(&opts); sc_ctx_detect_readers(ctx); + load_reader_driver_options(ctx); *ctx_out = ctx; return SC_SUCCESS; diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h index 1e7bba14..2389d0c5 100644 --- a/src/libopensc/internal-winscard.h +++ b/src/libopensc/internal-winscard.h @@ -200,6 +200,7 @@ typedef LONG (PCSC_API *SCardGetAttrib_t)(SCARDHANDLE hCard, DWORD dwAttrId,\ #define PCSCv2_PART10_PROPERTY_bMaxPINSize 7 #define PCSCv2_PART10_PROPERTY_sFirmwareID 8 #define PCSCv2_PART10_PROPERTY_bPPDUSupport 9 +#define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10 /* structures used (but not defined) in PCSC Part 10: * "IFDs with Secure Pin Entry Capabilities" */ diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index ad5405d5..8c4e81fa 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -275,8 +275,6 @@ struct sc_reader_driver { const char *short_name; struct sc_reader_operations *ops; - size_t max_send_size; /* Max Lc supported by the reader layer */ - size_t max_recv_size; /* Mac Le supported by the reader layer */ void *dll; }; @@ -305,6 +303,8 @@ typedef struct sc_reader { unsigned long flags, capabilities; unsigned int supported_protocols, active_protocol; + size_t max_send_size; /* Max Lc supported by the reader layer */ + size_t max_recv_size; /* Mac Le supported by the reader layer */ struct sc_atr atr; struct _atr_info { diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 73824525..666265d4 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -620,7 +620,7 @@ static struct sc_reader_driver pcsc_drv = { "PC/SC reader", "pcsc", &pcsc_ops, - 0, 0, NULL + NULL }; static int pcsc_init(sc_context_t *ctx) @@ -817,6 +817,50 @@ err: return flags; } +static int +part10_find_property_by_tag(unsigned char buffer[], int length, + int tag_searched); +/** + * @brief Detects reader's maximum data size + * + * @param reader reader to probe (\c get_tlv_properties must be initialized) + * + * @return maximum data size + */ +static size_t part10_detect_max_data(sc_reader_t *reader, SCARDHANDLE card_handle) +{ + u8 rbuf[256]; + DWORD rcount = sizeof rbuf; + struct pcsc_private_data *priv; + /* 0 means no limitations */ + size_t max_data = 0; + int r; + + if (!reader) + goto err; + priv = GET_PRIV_DATA(reader); + if (!priv) + goto err; + + if (priv->get_tlv_properties && priv->gpriv) { + if (SCARD_S_SUCCESS != priv->gpriv->SCardControl(card_handle, + priv->get_tlv_properties, NULL, 0, rbuf, sizeof(rbuf), + &rcount)) { + sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, + "PC/SC v2 part 10: Get TLV properties failed!"); + goto err; + } + + r = part10_find_property_by_tag(rbuf, rcount, + PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize); + if (r >= 0) + max_data = r; + } + +err: + return max_data; +} + static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) { sc_context_t *ctx = reader->ctx; struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data; @@ -940,6 +984,12 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) sc_log(ctx, "%s %s", log_text, log_disabled); } } + + /* Set reader max_send_size and max_recv_size based on detected max_data */ + if (priv->get_tlv_properties) { + reader->max_send_size = part10_detect_max_data(reader, card_handle); + reader->max_recv_size = reader->max_send_size; + } } static int pcsc_detect_readers(sc_context_t *ctx) From f71ef838e92a6999ca79d83ad5c94690d37d156b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 30 Jul 2015 08:18:07 +0200 Subject: [PATCH 296/306] implemented get_data for iso7816 mostly copied over from CardOS implementation --- src/libopensc/card-cardos.c | 30 ------------------------------ src/libopensc/iso7816.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index b6b208ae..1a716030 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -1217,35 +1217,6 @@ cardos_logout(sc_card_t *card) return SC_ERROR_NOT_SUPPORTED; } -static int cardos_get_data(struct sc_card *card, unsigned int tag, u8 *buf, size_t len) -{ - int r; - struct sc_apdu apdu; - - SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); - - sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, - (tag >> 8) & 0xff, tag & 0xff); - apdu.lc = 0; - apdu.datalen = 0; - apdu.le = len; - apdu.resp = buf; - apdu.resplen = len; - r = sc_transmit_apdu(card, &apdu); - SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); - - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "GET_DATA returned error"); - - if (apdu.resplen > len) - r = SC_ERROR_WRONG_LENGTH; - else - r = apdu.resplen; - - SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); -} - - /* eToken R2 supports WRITE_BINARY, PRO Tokens support UPDATE_BINARY */ static struct sc_card_driver * sc_get_driver(void) @@ -1266,7 +1237,6 @@ static struct sc_card_driver * sc_get_driver(void) cardos_ops.card_ctl = cardos_card_ctl; cardos_ops.pin_cmd = cardos_pin_cmd; cardos_ops.logout = cardos_logout; - cardos_ops.get_data = cardos_get_data; return &cardos_drv; } diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 19f9e7e3..baa15814 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -1128,6 +1128,38 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l } +static int iso7816_get_data(struct sc_card *card, unsigned int tag, u8 *buf, size_t len) +{ + int r, cse; + struct sc_apdu apdu; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + if (buf && len) + cse = SC_APDU_CASE_2; + else + cse = SC_APDU_CASE_1; + + sc_format_apdu(card, &apdu, cse, 0xCA, (tag >> 8) & 0xff, tag & 0xff); + apdu.le = len; + apdu.resp = buf; + apdu.resplen = len; + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "GET_DATA returned error"); + + if (apdu.resplen > len) + r = SC_ERROR_WRONG_LENGTH; + else + r = apdu.resplen; + + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); +} + + + static int iso7816_init(struct sc_card *card) { @@ -1175,7 +1207,7 @@ static struct sc_card_operations iso_ops = { iso7816_process_fci, iso7816_construct_fci, iso7816_pin_cmd, - NULL, /* get_data */ + iso7816_get_data, NULL, /* put_data */ NULL, /* delete_record */ NULL /* read_public_key */ From c6c8c6cdb027b288ff230d6965ee449ff102ff51 Mon Sep 17 00:00:00 2001 From: Martin Paljak Date: Thu, 30 Jul 2015 10:12:04 +0300 Subject: [PATCH 297/306] Fix dead code: ../../src/libopensc/errors.h:73:37: warning: statement with no effect [-Wunused-value] #define SC_ERROR_INVALID_ARGUMENTS -1300 ^ card-masktech.c:181:48: note: in expansion of macro 'SC_ERROR_INVALID_ARGUMENTS' if (crgram_len > SC_MAX_EXT_APDU_BUFFER_SIZE) SC_ERROR_INVALID_ARGUMENTS; --- src/libopensc/card-masktech.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-masktech.c b/src/libopensc/card-masktech.c index 2b036e75..9cd501e9 100644 --- a/src/libopensc/card-masktech.c +++ b/src/libopensc/card-masktech.c @@ -178,7 +178,9 @@ static int masktech_decipher(sc_card_t *card, assert(card != NULL && crgram != NULL && out != NULL); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "masktech_decipher()\n"); - if (crgram_len > SC_MAX_EXT_APDU_BUFFER_SIZE) SC_ERROR_INVALID_ARGUMENTS; + if (crgram_len > SC_MAX_EXT_APDU_BUFFER_SIZE) { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS); + } sc_format_apdu(card, &apdu, SC_APDU_CASE_4_EXT, 0x2A, 0x80, 0x86); apdu.resp = rbuf; From 24d91acf69d0071f8d924e2be976246d8a32e2a3 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 30 Jul 2015 08:19:01 +0200 Subject: [PATCH 298/306] opensc-explorer: added command find_tags --- doc/tools/opensc-explorer.1.xml | 8 ++++ src/tools/opensc-explorer.c | 71 +++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/doc/tools/opensc-explorer.1.xml b/doc/tools/opensc-explorer.1.xml index 40646fb7..85ab0857 100644 --- a/doc/tools/opensc-explorer.1.xml +++ b/doc/tools/opensc-explorer.1.xml @@ -292,6 +292,14 @@ Files are found by selecting all file identifiers in the range from start-fid to end-fid (by default from 0000 to FFFF). + + + find_tags [start-tag [end-tag]] + + Find all tags of data objects in the current context. + Tags are found by using GET DATA in the range from start-tag to end-tag (by default from 0000 to FFFF). + + mkdir file-id size diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index fa2581bb..cc938e77 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -85,6 +85,7 @@ static const char *option_help[] = { static int do_echo(int argc, char **argv); static int do_ls(int argc, char **argv); static int do_find(int argc, char **argv); +static int do_find_tags(int argc, char **argv); static int do_cd(int argc, char **argv); static int do_cat(int argc, char **argv); static int do_info(int argc, char **argv); @@ -127,6 +128,9 @@ static struct command cmds[] = { { do_find, "find", "[ []]", "find all files in the current DF" }, + { do_find_tags, + "find_tags", "[ []]", + "find all tags of data objects in the current context" }, { do_cd, "cd", "{.. | | aid:}", "change to another DF" }, @@ -579,6 +583,73 @@ static int do_find(int argc, char **argv) return 0; } +static int do_find_tags(int argc, char **argv) +{ + u8 start[2], end[2], rbuf[256]; + int r; + unsigned int tag, tag_end; + + start[0] = 0x00; + start[1] = 0x00; + end[0] = 0xFF; + end[1] = 0xFF; + switch (argc) { + case 2: + if (arg_to_fid(argv[1], end) != 0) + return usage(do_find_tags); + /* fall through */ + case 1: + if (arg_to_fid(argv[0], start) != 0) + return usage(do_find_tags); + /* fall through */ + case 0: + break; + default: + return usage(do_find_tags); + } + tag = (start[0] << 8) | start[1]; + tag_end = (end[0] << 8) | end[1]; + + printf("Tag\tType\n"); + while (1) { + printf("(%04X)\r", tag); + fflush(stdout); + + r = sc_get_data(card, tag, rbuf, sizeof rbuf); + if (r >= 0) { + printf(" %04X ", tag); + if (tag == 0) + printf("\tdump file"); + if ((0x0001 <= tag && tag <= 0x00FE) + || (0x1F1F <= tag && tag <= 0xFFFF)) + printf("\tBER-TLV"); + if (tag == 0x00FF || tag == 0x02FF) + printf("\tspecial function"); + if (0x0100 <= tag && tag <= 0x01FF) + printf("\tproprietary"); + if (tag == 0x0200) + printf("\tRFU"); + if (0x0201 <= tag && tag <= 0x02FE) + printf("\tSIMPLE-TLV"); + printf("\n"); + if (r > 0) + util_hex_dump_asc(stdout, rbuf, r, -1); + } else { + switch (r) { + case SC_ERROR_NOT_ALLOWED: + case SC_ERROR_SECURITY_STATUS_NOT_SATISFIED: + printf("(%04X)\t%s\n", tag, sc_strerror(r)); + break; + } + } + + if (tag >= tag_end) + break; + tag++; + } + return 0; +} + static int do_cd(int argc, char **argv) { sc_path_t path; From 97e41cb76ad7e567675ce0d5d4509aeca5de3ebe Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 30 Jul 2015 15:23:14 +0200 Subject: [PATCH 299/306] added completion-template to distribution fixes #505 --- doc/tools/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/tools/Makefile.am b/doc/tools/Makefile.am index f4e64c79..82c1ceb1 100644 --- a/doc/tools/Makefile.am +++ b/doc/tools/Makefile.am @@ -1,5 +1,7 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +EXTRA_DIST = completion-template + dist_noinst_DATA = $(wildcard $(srcdir)/*.xml) if ENABLE_DOC html_DATA = tools.html From 4fedad53dd3e36c3d2a43de7400f40dd4cd34b29 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Thu, 2 Jul 2015 16:17:51 +0300 Subject: [PATCH 300/306] Fix tokend install on OSX 10.11 Install to /Library/Security/tokend instead /System/Library/Security/tokend http://forums.macrumors.com/threads/os-x-10-11-all-the-little-things.1890519/ /System folder is readonly Depends https://github.com/OpenSC/OpenSC.tokend/pull/16 Signed-off-by: Raul Metsma --- MacOSX/build-package.in | 5 +---- MacOSX/opensc-uninstall | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index c0db7daf..86a2a729 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -70,12 +70,9 @@ fi test -L OpenSC.tokend/build/opensc-src || ln -sf ${BUILDPATH}/src OpenSC.tokend/build/opensc-src # Build and copy OpenSC.tokend -xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj +xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj install DSTROOT=${PWD}/target # Prepare target root -# Copy Tokend -mkdir -p target/System/Library/Security/tokend -mv OpenSC.tokend/build/OpenSC.tokend target/System/Library/Security/tokend # The "UnInstaller" mkdir -p target/usr/local/bin cp MacOSX/opensc-uninstall target/usr/local/bin diff --git a/MacOSX/opensc-uninstall b/MacOSX/opensc-uninstall index bd87839f..9dbc0059 100755 --- a/MacOSX/opensc-uninstall +++ b/MacOSX/opensc-uninstall @@ -16,6 +16,7 @@ test -L /usr/lib/opensc-pkcs11.so && rm -f /usr/lib/opensc-pkcs11.so # Remove installed files rm -rf /Library/OpenSC +rm -rf /Library/Security/tokend/OpenSC.tokend rm -rf /System/Library/Security/tokend/OpenSC.tokend # delete receipts on 10.6+ From d6774aae40710d5243a6a3ee86387343467a02f7 Mon Sep 17 00:00:00 2001 From: Andreas Schwier Date: Tue, 4 Aug 2015 17:51:46 +0200 Subject: [PATCH 301/306] Fixed wrong APDU case declaration detected after PR #500 --- src/libopensc/card-sc-hsm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index 5c7c15b6..87d563b2 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -236,7 +236,6 @@ static int sc_hsm_read_binary(sc_card_t *card, { sc_context_t *ctx = card->ctx; sc_apdu_t apdu; - u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 cmdbuff[4]; int r; @@ -251,13 +250,13 @@ static int sc_hsm_read_binary(sc_card_t *card, cmdbuff[3] = idx & 0xFF; assert(count <= (card->max_recv_size > 0 ? card->max_recv_size : 256)); - sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xB1, 0x00, 0x00); + sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB1, 0x00, 0x00); apdu.data = cmdbuff; apdu.datalen = 4; apdu.lc = 4; apdu.le = count; apdu.resplen = count; - apdu.resp = recvbuf; + apdu.resp = buf; r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(ctx, r, "APDU transmit failed"); @@ -267,8 +266,6 @@ static int sc_hsm_read_binary(sc_card_t *card, LOG_TEST_RET(ctx, r, "Check SW error"); } - memcpy(buf, recvbuf, apdu.resplen); - LOG_FUNC_RETURN(ctx, apdu.resplen); } @@ -1064,6 +1061,7 @@ static int sc_hsm_init(struct sc_card *card) card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT; card->max_send_size = 1431; // 1439 buffer size - 8 byte TLV because of odd ins in UPDATE BINARY + card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit return 0; } From c14be48ed94e59e6db61f4c1a0b8e070744c0c0b Mon Sep 17 00:00:00 2001 From: HenryJacques Date: Tue, 11 Aug 2015 18:03:31 +0200 Subject: [PATCH 302/306] really set the --login option when using --pin Until now, if -p was used without -l, we didn't authenticate to the token (see man pkcs11-tool) --- src/tools/pkcs11-tool.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 2a01cf0e..27813022 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -551,6 +551,8 @@ int main(int argc, char * argv[]) opt_output = optarg; break; case 'p': + need_session |= NEED_SESSION_RW; + opt_login = 1; util_get_pin(optarg, &opt_pin); break; case 'c': From 85b79a33320b615c923a6a03b6d295d7543b3f55 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 4 Aug 2015 23:06:25 +0200 Subject: [PATCH 303/306] don't always overwrite max_send_size/max_recv_size If the reader announces extended length support, but the card driver leaves max_send_size/max_recv_size at `0`, max_send_size/max_recv_size previously would have been overwritten with the reader's size though the card might not have set SC_CARD_CAP_APDU_EXT. This commit fixes this behavior. Additionally card->max_send_size/max_recv_size is always initialized to a value different from 0 after the card initialization. This removes the need to check for this special value in all subsequent calls. --- src/libopensc/apdu.c | 2 +- src/libopensc/card-dnie.c | 2 +- src/libopensc/card-sc-hsm.c | 2 +- src/libopensc/card.c | 32 +++++++++++++++++++++----------- src/libopensc/iso7816.c | 28 +++++----------------------- 5 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/libopensc/apdu.c b/src/libopensc/apdu.c index 1a52d5a5..39c0294b 100644 --- a/src/libopensc/apdu.c +++ b/src/libopensc/apdu.c @@ -581,7 +581,7 @@ int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu) * bytes using command chaining */ size_t len = apdu->datalen; const u8 *buf = apdu->data; - size_t max_send_size = card->max_send_size > 0 ? card->max_send_size : 255; + size_t max_send_size = card->max_send_size; while (len != 0) { size_t plen; diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index f4d6991b..90cb4241 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -871,7 +871,7 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa apdu.lc = pathlen; apdu.data = path; apdu.datalen = pathlen; - apdu.le = card->max_recv_size > 0 ? card->max_recv_size : 256; + apdu.le = card->max_recv_size; if (p1 == 3) apdu.cse= SC_APDU_CASE_1; diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index 87d563b2..e4fab7bd 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -249,7 +249,7 @@ static int sc_hsm_read_binary(sc_card_t *card, cmdbuff[2] = (idx >> 8) & 0xFF; cmdbuff[3] = idx & 0xFF; - assert(count <= (card->max_recv_size > 0 ? card->max_recv_size : 256)); + assert(count <= card->max_recv_size); sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB1, 0x00, 0x00); apdu.data = cmdbuff; apdu.datalen = 4; diff --git a/src/libopensc/card.c b/src/libopensc/card.c index f3cb152b..50da8ff8 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -251,15 +251,25 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) if (card->name == NULL) card->name = card->driver->name; - /* Override card limitations with reader limitations. - * Note that zero means no limitations at all. - */ - if ((card->max_recv_size == 0) || - ((reader->max_recv_size != 0) && (reader->max_recv_size < card->max_recv_size))) - card->max_recv_size = reader->max_recv_size; + /* initialize max_send_size/max_recv_size to a meaningfull value */ + if (card->caps & SC_CARD_CAP_APDU_EXT) { + if (!card->max_send_size) + card->max_send_size = 65535; + if (!card->max_recv_size) + card->max_recv_size = 65536; + } else { + if (!card->max_send_size) + card->max_send_size = 255; + if (!card->max_recv_size) + card->max_recv_size = 256; + } - if ((card->max_send_size == 0) || - ((reader->max_send_size != 0) && (reader->max_send_size < card->max_send_size))) + /* Override card limitations with reader limitations. */ + if (reader->max_recv_size != 0 + && (reader->max_recv_size < card->max_recv_size)) + card->max_recv_size = reader->max_recv_size; + if (reader->max_send_size != 0 + && (reader->max_send_size < card->max_send_size)) card->max_send_size = reader->max_send_size; sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", @@ -479,7 +489,7 @@ int sc_delete_file(sc_card_t *card, const sc_path_t *path) int sc_read_binary(sc_card_t *card, unsigned int idx, unsigned char *buf, size_t count, unsigned long flags) { - size_t max_le = card->max_recv_size > 0 ? card->max_recv_size : 256; + size_t max_le = card->max_recv_size; int r; assert(card != NULL && card->ops != NULL && buf != NULL); @@ -529,7 +539,7 @@ int sc_read_binary(sc_card_t *card, unsigned int idx, int sc_write_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { - size_t max_lc = card->max_send_size > 0 ? card->max_send_size : 255; + size_t max_lc = card->max_send_size; int r; assert(card != NULL && card->ops != NULL && buf != NULL); @@ -572,7 +582,7 @@ int sc_write_binary(sc_card_t *card, unsigned int idx, int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { - size_t max_lc = card->max_send_size > 0 ? card->max_send_size : 255; + size_t max_lc = card->max_send_size; int r; assert(card != NULL && card->ops != NULL && buf != NULL); diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index baa15814..39b71868 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -33,35 +33,17 @@ static void fixup_transceive_length(const struct sc_card *card, struct sc_apdu *apdu) { - size_t max_send_size; - size_t max_recv_size; - assert(card != NULL && apdu != NULL); - max_send_size = card->max_send_size; - max_recv_size = card->max_recv_size; - - if (card->caps & SC_CARD_CAP_APDU_EXT) { - if (!max_send_size) - max_send_size = 65535; - if (!max_recv_size) - max_recv_size = 65536; - } else { - if (!max_send_size) - max_send_size = 255; - if (!max_recv_size) - max_recv_size = 256; - } - - if (apdu->lc > max_send_size) { + if (apdu->lc > card->max_send_size) { /* The lower layers will automatically do chaining */ apdu->flags |= SC_APDU_FLAGS_CHAINING; } - if (apdu->le > max_recv_size) { + if (apdu->le > card->max_recv_size) { /* The lower layers will automatically do a GET RESPONSE, if possible. * All other workarounds must be carried out by the upper layers. */ - apdu->le = max_recv_size; + apdu->le = card->max_recv_size; } } @@ -544,7 +526,7 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct apdu.p2 = 0; /* first record, return FCI */ apdu.resp = buf; apdu.resplen = sizeof(buf); - apdu.le = card->max_recv_size > 0 && card->max_recv_size < 256 ? card->max_recv_size : 256; + apdu.le = card->max_recv_size < 256 ? card->max_recv_size : 256; } else { apdu.p2 = 0x0C; /* first record, return nothing */ @@ -737,7 +719,7 @@ iso7816_get_response(struct sc_card *card, size_t *count, u8 *buf) size_t rlen; /* request at most max_recv_size bytes */ - if (card->max_recv_size > 0 && *count > card->max_recv_size) + if (*count > card->max_recv_size) rlen = card->max_recv_size; else rlen = *count; From 2e21163273978475b31f664f80ad1ad3c02755c7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 11 Aug 2015 13:27:30 +0200 Subject: [PATCH 304/306] cardos: probe for transceive length --- src/libopensc/card-cardos.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index 1a716030..7b5b51fd 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -165,6 +165,9 @@ static int cardos_have_2048bit_package(sc_card_t *card) static int cardos_init(sc_card_t *card) { unsigned long flags, rsa_2048 = 0; + size_t data_field_length; + sc_apdu_t apdu; + u8 rbuf[2]; card->name = "CardOS M4"; card->cla = 0x00; @@ -195,6 +198,29 @@ static int cardos_init(sc_card_t *card) card->caps |= SC_CARD_CAP_APDU_EXT; } + /* probe DATA FIELD LENGTH with GET DATA */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x8D); + apdu.le = sizeof rbuf; + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, + sc_transmit_apdu(card, &apdu), + "APDU transmit failed"); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, + sc_check_sw(card, apdu.sw1, apdu.sw2), + "GET DATA command returned error"); + if (apdu.resplen != 2) + return SC_ERROR_WRONG_LENGTH; + data_field_length = ((rbuf[0] << 8) | rbuf[1]); + + /* strip the length of possible Lc and Le bytes */ + if (card->caps & SC_CARD_CAP_APDU_EXT) + card->max_send_size = data_field_length - 6; + else + card->max_send_size = data_field_length - 3; + /* strip the length of SW bytes */ + card->max_recv_size = data_field_length - 2; + if (rsa_2048 == 1) { _sc_card_add_rsa_alg(card, 1280, flags, 0); _sc_card_add_rsa_alg(card, 1536, flags, 0); From ff2d88a724d5a2dee9c915b7b46ccb6ede520bce Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 16 Aug 2015 20:18:29 +0200 Subject: [PATCH 305/306] libopensc: uncomplete changes in c48afdbf breaks windows builds --- src/libopensc/reader-ctapi.c | 44 +++++++++++++++++------------------ src/libopensc/reader-openct.c | 8 +++---- src/libopensc/reader-pcsc.c | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/libopensc/reader-ctapi.c b/src/libopensc/reader-ctapi.c index c526500d..9fa1f98e 100644 --- a/src/libopensc/reader-ctapi.c +++ b/src/libopensc/reader-ctapi.c @@ -164,7 +164,7 @@ static int ctapi_internal_transmit(sc_reader_t *reader, if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; - + if (control) dad = 1; else @@ -172,14 +172,14 @@ static int ctapi_internal_transmit(sc_reader_t *reader, sad = 2; lr = *recvsize; - + rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, (unsigned short)sendsize, (u8 *) sendbuf, &lr, recvbuf); if (rv != 0) { sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Error transmitting APDU: %d\n", rv); return SC_ERROR_TRANSMIT_FAILED; } *recvsize = lr; - + return 0; } @@ -219,14 +219,14 @@ out: sc_mem_clear(rbuf, rbuflen); free(rbuf); } - + return r; } static int ctapi_detect_card_presence(sc_reader_t *reader) { int r; - + r = refresh_attributes(reader); if (r) return r; @@ -303,7 +303,7 @@ static struct sc_reader_driver ctapi_drv = { "CT-API module", "ctapi", &ctapi_ops, - 0, 0, NULL + NULL }; static struct ctapi_module * add_module(struct ctapi_global_private_data *gpriv, @@ -317,7 +317,7 @@ static struct ctapi_module * add_module(struct ctapi_global_private_data *gpriv, gpriv->modules[i].dlhandle = dlhandle; gpriv->modules[i].ctn_count = 0; gpriv->module_count++; - + return &gpriv->modules[i]; } @@ -334,8 +334,8 @@ static int ctapi_load_module(sc_context_t *ctx, u8 cmd[5], rbuf[256], sad, dad; unsigned short lr; - - + + list = scconf_find_list(conf, "ports"); if (list == NULL) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "No ports configured.\n"); @@ -366,7 +366,7 @@ static int ctapi_load_module(sc_context_t *ctx, char rv; sc_reader_t *reader; struct ctapi_private_data *priv; - + if (sscanf(list->data, "%d", &port) != 1) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Port '%s' is not a number.\n", list->data); continue; @@ -376,7 +376,7 @@ static int ctapi_load_module(sc_context_t *ctx, sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "CT_init() failed with %d\n", rv); continue; } - + reader = calloc(1, sizeof(sc_reader_t)); priv = calloc(1, sizeof(struct ctapi_private_data)); if (!priv || !reader) { @@ -399,9 +399,9 @@ static int ctapi_load_module(sc_context_t *ctx, free(reader); break; } - - /* Detect functional units of the reader according to CT-BCS spec version 1.0 - (14.04.2004, http://www.teletrust.de/down/mct1-0_t4.zip) */ + + /* Detect functional units of the reader according to CT-BCS spec version 1.0 + (14.04.2004, http://www.teletrust.de/down/mct1-0_t4.zip) */ cmd[0] = CTBCS_CLA; cmd[1] = CTBCS_INS_STATUS; cmd[2] = CTBCS_P1_CT_KERNEL; @@ -410,7 +410,7 @@ static int ctapi_load_module(sc_context_t *ctx, dad = 1; sad = 2; lr = 256; - + rv = priv->funcs.CT_data(priv->ctn, &dad, &sad, 5, cmd, &lr, rbuf); if (rv || (lr < 4) || (rbuf[lr-2] != 0x90)) { sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Error getting status of terminal: %d, using defaults\n", rv); @@ -483,7 +483,7 @@ static int ctapi_load_module(sc_context_t *ctx, if (priv->ctapi_functional_units & CTAPI_FU_DISPLAY) reader->capabilities |= SC_READER_CAP_DISPLAY; } - + ctapi_reset(reader); refresh_attributes(reader); mod->ctn_count++; @@ -505,7 +505,7 @@ static int ctapi_init(sc_context_t *ctx) if (gpriv == NULL) return SC_ERROR_OUT_OF_MEMORY; ctx->reader_drv_data = gpriv; - + for (i = 0; ctx->conf_blocks[i] != NULL; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "reader_driver", "ctapi"); @@ -521,7 +521,7 @@ static int ctapi_init(sc_context_t *ctx) for (i = 0; blocks != NULL && blocks[i] != NULL; i++) ctapi_load_module(ctx, gpriv, blocks[i]); free(blocks); - + return 0; } @@ -531,10 +531,10 @@ static int ctapi_finish(sc_context_t *ctx) if (priv) { int i; - + for (i = 0; i < priv->module_count; i++) { struct ctapi_module *mod = &priv->modules[i]; - + free(mod->name); sc_dlclose(mod->dlhandle); } @@ -542,7 +542,7 @@ static int ctapi_finish(sc_context_t *ctx) free(priv->modules); free(priv); } - + return 0; } @@ -561,7 +561,7 @@ struct sc_reader_driver * sc_get_ctapi_driver(void) ctapi_ops.perform_verify = ctbcs_pin_cmd; ctapi_ops.perform_pace = NULL; ctapi_ops.use_reader = NULL; - + return &ctapi_drv; } #endif diff --git a/src/libopensc/reader-openct.c b/src/libopensc/reader-openct.c index 2d7d6bd9..d2038a2b 100644 --- a/src/libopensc/reader-openct.c +++ b/src/libopensc/reader-openct.c @@ -46,7 +46,7 @@ static struct sc_reader_driver openct_reader_driver = { "OpenCT reader", "openct", &openct_ops, - 0, 0, NULL + NULL }; /* private data structures */ @@ -119,7 +119,7 @@ openct_add_reader(sc_context_t *ctx, unsigned int num, ct_info_t *info) reader->drv_data = data; reader->name = strdup(data->info.ct_name); - if ((rc = _sc_add_reader(ctx, reader)) < 0) { + if ((rc = _sc_add_reader(ctx, reader)) < 0) { free(data); free(reader->name); free(reader); @@ -160,7 +160,7 @@ static int openct_reader_release(sc_reader_t *reader) reader->drv_data = NULL; free(data); } - + return SC_SUCCESS; } @@ -321,7 +321,7 @@ out: sc_mem_clear(rbuf, rbuflen); free(rbuf); } - + return r; } diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 7c26a253..b850db20 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -2093,7 +2093,7 @@ static struct sc_reader_driver cardmod_drv = { "PC/SC cardmod reader", "cardmod", &cardmod_ops, - 0, 0, NULL + NULL }; static int cardmod_init(sc_context_t *ctx) From 4df35b922c8eb7e0776a23260b65e570b33e4d42 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Tue, 11 Aug 2015 14:02:52 +0100 Subject: [PATCH 306/306] pkcs11: Fix to CKA_PRIVATE handling pcks11-tool There's a copy-and-paste bug in there, where the CKA_PRIVATE attribute is being set on the wrong variables! As well as fixing that, we should explicitly set CKA_PRIVATE to "false" for certificates and public keys, since the PKCS#11 spec doesn't specify a default and some drivers use "private" as the default, making it impossible to add a public key/cert using pkcs11-tool. --- src/tools/pkcs11-tool.c | 47 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 27813022..c3861d56 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -1923,6 +1923,7 @@ static int parse_gost_private_key(EVP_PKEY *evp_key, struct gostkey_info *gost) static int write_object(CK_SESSION_HANDLE session) { CK_BBOOL _true = TRUE; + CK_BBOOL _false = FALSE; unsigned char contents[MAX_OBJECT_SIZE + 1]; int contents_len = 0; unsigned char certdata[MAX_OBJECT_SIZE]; @@ -2026,28 +2027,24 @@ static int write_object(CK_SESSION_HANDLE session) FILL_ATTR(cert_templ[1], CKA_VALUE, contents, contents_len); FILL_ATTR(cert_templ[2], CKA_CLASS, &clazz, sizeof(clazz)); FILL_ATTR(cert_templ[3], CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)); - n_cert_attr = 4; + FILL_ATTR(cert_templ[4], CKA_PRIVATE, &_false, sizeof(_false)); + n_cert_attr = 5; if (opt_object_label != NULL) { - FILL_ATTR(cert_templ[n_cert_attr], CKA_LABEL, - opt_object_label, strlen(opt_object_label)); + FILL_ATTR(cert_templ[n_cert_attr], CKA_LABEL, opt_object_label, strlen(opt_object_label)); n_cert_attr++; } if (opt_object_id_len != 0) { - FILL_ATTR(cert_templ[n_cert_attr], CKA_ID, - opt_object_id, opt_object_id_len); + FILL_ATTR(cert_templ[n_cert_attr], CKA_ID, opt_object_id, opt_object_id_len); n_cert_attr++; } #ifdef ENABLE_OPENSSL /* according to PKCS #11 CKA_SUBJECT MUST be specified */ - FILL_ATTR(cert_templ[n_cert_attr], CKA_SUBJECT, - cert.subject, cert.subject_len); + FILL_ATTR(cert_templ[n_cert_attr], CKA_SUBJECT, cert.subject, cert.subject_len); n_cert_attr++; - FILL_ATTR(cert_templ[n_cert_attr], CKA_ISSUER, - cert.issuer, cert.issuer_len); + FILL_ATTR(cert_templ[n_cert_attr], CKA_ISSUER, cert.issuer, cert.issuer_len); n_cert_attr++; - FILL_ATTR(cert_templ[n_cert_attr], CKA_SERIAL_NUMBER, - cert.serialnum, cert.serialnum_len); + FILL_ATTR(cert_templ[n_cert_attr], CKA_SERIAL_NUMBER, cert.serialnum, cert.serialnum_len); n_cert_attr++; #endif } @@ -2150,9 +2147,12 @@ static int write_object(CK_SESSION_HANDLE session) n_pubkey_attr = 3; if (opt_is_private != 0) { - FILL_ATTR(data_templ[n_data_attr], CKA_PRIVATE, - &_true, sizeof(_true)); - n_data_attr++; + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_PRIVATE, &_true, sizeof(_true)); + n_pubkey_attr++; + } + else { + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_PRIVATE, &_false, sizeof(_false)); + n_pubkey_attr++; } if (opt_object_label != NULL) { @@ -2180,15 +2180,12 @@ static int write_object(CK_SESSION_HANDLE session) #ifdef ENABLE_OPENSSL if (cert.subject_len != 0) { - FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_SUBJECT, - cert.subject, cert.subject_len); + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_SUBJECT, cert.subject, cert.subject_len); n_pubkey_attr++; } - FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_MODULUS, - rsa.modulus, rsa.modulus_len); + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_MODULUS, rsa.modulus, rsa.modulus_len); n_pubkey_attr++; - FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_PUBLIC_EXPONENT, - rsa.public_exponent, rsa.public_exponent_len); + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_PUBLIC_EXPONENT, rsa.public_exponent, rsa.public_exponent_len); n_pubkey_attr++; #endif } @@ -2202,8 +2199,11 @@ static int write_object(CK_SESSION_HANDLE session) n_data_attr = 3; if (opt_is_private != 0) { - FILL_ATTR(data_templ[n_data_attr], CKA_PRIVATE, - &_true, sizeof(_true)); + FILL_ATTR(data_templ[n_data_attr], CKA_PRIVATE, &_true, sizeof(_true)); + n_data_attr++; + } + else { + FILL_ATTR(data_templ[n_data_attr], CKA_PRIVATE, &_false, sizeof(_false)); n_data_attr++; } @@ -2227,8 +2227,7 @@ static int write_object(CK_SESSION_HANDLE session) } if (opt_object_label != NULL) { - FILL_ATTR(data_templ[n_data_attr], CKA_LABEL, - opt_object_label, strlen(opt_object_label)); + FILL_ATTR(data_templ[n_data_attr], CKA_LABEL, opt_object_label, strlen(opt_object_label)); n_data_attr++; }