From 3d187d9ac45cbaf46d3f5211ccd4c6808456296d Mon Sep 17 00:00:00 2001 From: HAMANO Tsukasa Date: Wed, 2 Aug 2017 17:45:53 +0900 Subject: [PATCH 01/36] documentation for ignore_private_certificate parameter. --- etc/opensc.conf.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in index 63abba9b..ff87ee13 100644 --- a/etc/opensc.conf.in +++ b/etc/opensc.conf.in @@ -782,6 +782,11 @@ app tokend { # Default: 300 # # score = 10; + + # Tokend ignore to read PIN protected certificate that is set SC_PKCS15_CO_FLAG_PRIVATE flag. + # Default: true + # + # ignore_private_certificate = false; } } From 9b772ebdc45cfcf5de00470f9100bb9fe9919117 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 2 Aug 2017 18:14:25 +0200 Subject: [PATCH 02/36] win32: switch back to OpenSSL 1.0.2 as default AppVeyor changed the default version back to 1.0.2, see https://github.com/appveyor/ci/issues/1671 --- appveyor.yml | 5 ++++- win32/Make.rules.mak | 20 ++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 01762cb3..bf528b20 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -82,7 +82,10 @@ build_script: # build libeac.lib as a static library xcopy C:\openpace C:\openpace-${env:OPENSSL_PF} /e /i /y /s cd C:\openpace-${env:OPENSSL_PF}\src - cl /IC:\OpenSSL-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /DHAVE_ASN1_STRING_GET0_DATA=1 /DHAVE_DECL_OPENSSL_ZALLOC=1 /DHAVE_DH_GET0_KEY=1 /DHAVE_DH_GET0_PQG=1 /DHAVE_DH_SET0_KEY=1 /DHAVE_DH_SET0_PQG=1 /DHAVE_ECDSA_SIG_GET0=1 /DHAVE_ECDSA_SIG_SET0=1 /DHAVE_EC_KEY_METHOD=1 /DHAVE_RSA_GET0_KEY=1 /DHAVE_RSA_SET0_KEY=1 /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c + # OpenSSL 1.1.0 + #cl /IC:\OpenSSL-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /DHAVE_ASN1_STRING_GET0_DATA=1 /DHAVE_DECL_OPENSSL_ZALLOC=1 /DHAVE_DH_GET0_KEY=1 /DHAVE_DH_GET0_PQG=1 /DHAVE_DH_SET0_KEY=1 /DHAVE_DH_SET0_PQG=1 /DHAVE_ECDSA_SIG_GET0=1 /DHAVE_ECDSA_SIG_SET0=1 /DHAVE_EC_KEY_METHOD=1 /DHAVE_RSA_GET0_KEY=1 /DHAVE_RSA_SET0_KEY=1 /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c + # OpenSSL 1.0.2 + cl /IC:\OpenSSL-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c lib /out:libeac.lib ca_lib.obj cv_cert.obj cvc_lookup.obj x509_lookup.obj eac_asn1.obj eac.obj eac_ca.obj eac_dh.obj eac_ecdh.obj eac_kdf.obj eac_lib.obj eac_print.obj eac_util.obj misc.obj pace.obj pace_lib.obj pace_mappings.obj ri.obj ri_lib.obj ta.obj ta_lib.obj objects.obj ssl_compat.obj cd C:\projects\OpenSC } diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index b8e0adf6..62530f44 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -45,15 +45,27 @@ OPENSSL_STATIC_DIR = static !IF "$(DEBUG_DEF)" == "/DDEBUG" !IF "$(PLATFORM)" == "x86" -OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto32MTd.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +# OpenSSL 1.0.2 +OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libeay32MTd.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +# OpenSSL 1.1.0 +#OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto32MTd.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib !ELSE -OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto64MTd.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +# OpenSSL 1.0.2 +OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libeay32MTd.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +# OpenSSL 1.1.0 +#OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto64MTd.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib !ENDIF !ELSE !IF "$(PLATFORM)" == "x86" -OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto32MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +# OpenSSL 1.0.2 +OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libeay32MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +# OpenSSL 1.1.0 +#OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto32MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib !ELSE -OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto64MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +# OpenSSL 1.0.2 +OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libeay32MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +# OpenSSL 1.1.0 +#OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto64MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib !ENDIF !ENDIF From 0dcf6732960878f242e1922c14edfccb80027887 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 4 Aug 2017 08:48:24 +0200 Subject: [PATCH 03/36] CAC issues (#1120) * cac: Make the retransmitted APDU valid by restoring the resplen * cac: Check SWs for all the APDUs and report the errors to underlying layers * cac: Fallback from CACv1 to CACv2 when CACv1 instruction is not recognized for the lack of other pointers how to recongnize them * avoid goto --- src/libopensc/card-cac.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c index ed15ba0a..82f5c786 100644 --- a/src/libopensc/card-cac.c +++ b/src/libopensc/card-cac.c @@ -390,9 +390,7 @@ static int cac_apdu_io(sc_card_t *card, int ins, int p1, int p2, goto err; } - if (apdu.sw1 == 0x61) { - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - } + r = sc_check_sw(card, apdu.sw1, apdu.sw2); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Card returned error "); @@ -606,9 +604,14 @@ static int cac_read_binary(sc_card_t *card, unsigned int idx, /* SPICE smart card emulator only presents CAC-1 cards with the old CAC-1 interface as * certs. If we are a cac 1 card, use the old interface */ r = cac_cac1_get_certificate(card, &val, &val_len); - if (r < 0) + if (r == SC_ERROR_INS_NOT_SUPPORTED) { + /* The CACv1 instruction is not recognized. Try with CACv2 */ + card->type = SC_CARD_TYPE_CAC_II; + } else if (r < 0) goto done; + } + if ((card->type == SC_CARD_TYPE_CAC_I) && (priv->object_type == CAC_OBJECT_TYPE_CERT)) { r = cac_cac1_get_cert_tag(card, val_len, &tl, &tl_len); if (r < 0) goto done; @@ -1106,6 +1109,7 @@ static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc r = sc_check_sw(card, apdu.sw1, apdu.sw2); if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86) { apdu.p2 = 0x00; + apdu.resplen = sizeof(buf); if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS) r = sc_check_sw(card, apdu.sw1, apdu.sw2); } From e0eb5bf888323175e3ca601ea45b4f75fbcd4875 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 3 Aug 2017 09:52:43 +0200 Subject: [PATCH 04/36] Do not call list_init() twice (amend 6bfb39454) --- src/pkcs11/pkcs11-global.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 5f04a7f1..24074ab5 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -264,7 +264,6 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs) list_attributes_seeker(&sessions, session_list_seeker); /* List of slots */ - list_init(&virtual_slots); if (0 != list_init(&virtual_slots)) { rv = CKR_HOST_MEMORY; goto out; From a007ab7820357c466d28ac442b53ab71e5dbd4b5 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 30 Jun 2017 14:52:08 +0200 Subject: [PATCH 05/36] sc-hsm: New PIN commands for GoID 1.0 --- src/libopensc/card-sc-hsm.c | 125 ++++++++++++++++++++++------------ src/libopensc/cards.h | 1 + src/libopensc/pkcs15-sc-hsm.c | 6 +- 3 files changed, 86 insertions(+), 46 deletions(-) diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index 5a417913..ff9810c4 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -68,62 +68,62 @@ static struct sc_atr_table sc_hsm_atrs[] = { { "3B:84:80:01:47:6f:49:44:00", "FF:FF:FF:FF:FF:FF:FF:FF:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:85:80:01:47:6f:49:44:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:86:80:01:47:6f:49:44:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:87:80:01:47:6f:49:44:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:88:80:01:47:6f:49:44:00:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:89:80:01:47:6f:49:44:00:00:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:8a:80:01:47:6f:49:44:00:00:00:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:8b:80:01:47:6f:49:44:00:00:00:00:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:8c:80:01:47:6f:49:44:00:00:00:00:00:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:8d:80:01:47:6f:49:44:00:00:00:00:00:00:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:8e:80:01:47:6f:49:44:00:00:00:00:00:00:00:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, { "3B:8f:80:01:47:6f:49:44:00:00:00:00:00:00:00:00:00:00:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00:00:00:00:00:00", - "GoID", SC_CARD_TYPE_SC_HSM_SOC, 0, NULL + "GoID", SC_CARD_TYPE_SC_HSM_GOID, 0, NULL }, {NULL, NULL, NULL, 0, 0, NULL} }; @@ -305,30 +305,56 @@ static int sc_hsm_soc_change(sc_card_t *card, struct sc_pin_cmd_data *data, sc_path_t path; int r; - /* Select MinBioClient */ - r = sc_hsm_soc_select_minbioclient(card); - LOG_TEST_RET(card->ctx, r, "Could not select MinBioClient application"); + if (card->type == SC_CARD_TYPE_SC_HSM_SOC) { + /* Select MinBioClient */ + r = sc_hsm_soc_select_minbioclient(card); + LOG_TEST_RET(card->ctx, r, "Could not select MinBioClient application"); - /* verify PIN */ - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 0x80); - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_GOTO_ERR(card->ctx, r, "Could not verify PIN"); + /* verify PIN */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 0x80); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_GOTO_ERR(card->ctx, r, "Could not verify PIN"); - /* change PIN */ - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x24, 0x01, 0x80); - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - LOG_TEST_GOTO_ERR(card->ctx, r, "Could not change PIN"); + /* change PIN */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x24, 0x01, 0x80); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_GOTO_ERR(card->ctx, r, "Could not change PIN"); + } else { + unsigned sm_mode = card->sm_ctx.sm_mode; + + /* verify PIN */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 0x85); + apdu.cla = 0x80; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); + + /* temporary disable SM, change reference data does not reach the applet */ + card->sm_ctx.sm_mode = SM_MODE_NONE; + + /* change PIN */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x24, 0x01, 0x85); + apdu.cla = 0x80; + r = sc_transmit_apdu(card, &apdu); + /* restore SM if possible */ + card->sm_ctx.sm_mode = sm_mode; + LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_GOTO_ERR(card->ctx, r, "Could not change PIN"); + } err: - /* Select SC-HSM */ - sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); - LOG_TEST_RET(card->ctx, - sc_hsm_select_file_ex(card, &path, 1, NULL), - "Could not select SmartCard-HSM application"); + if (card->type == SC_CARD_TYPE_SC_HSM_SOC) { + /* Select SC-HSM */ + sc_path_set(&path, SC_PATH_TYPE_DF_NAME, + sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); + LOG_TEST_RET(card->ctx, + sc_hsm_select_file_ex(card, &path, 1, NULL), + "Could not select SmartCard-HSM application"); + } return r; } @@ -340,6 +366,10 @@ static int sc_hsm_soc_unblock(sc_card_t *card, struct sc_pin_cmd_data *data, sc_path_t path; int r; + if (card->type == SC_CARD_TYPE_SC_HSM_GOID) { + return SC_ERROR_NOT_SUPPORTED; + } + /* Select MinBioClient */ r = sc_hsm_soc_select_minbioclient(card); LOG_TEST_RET(card->ctx, r, "Could not select MinBioClient application"); @@ -375,19 +405,24 @@ static int sc_hsm_soc_biomatch(sc_card_t *card, struct sc_pin_cmd_data *data, u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; int r; - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0x00, 0x85); - apdu.cla = 0x80; - apdu.data = (unsigned char*)"\x7F\x24\x00"; - apdu.datalen = 3; - apdu.lc = 3; - apdu.resplen = 0; + if (card->type == SC_CARD_TYPE_SC_HSM_SOC) { + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0x00, 0x85); + apdu.cla = 0x80; + apdu.data = (unsigned char*)"\x7F\x24\x00"; + apdu.datalen = 3; + apdu.lc = 3; + apdu.resplen = 0; - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - /* ignore the actual status bytes */ + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + /* ignore the actual status bytes */ + } /* JCOP's SM accelerator is incapable of using case 1 APDU in SM */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x20, 0x00, 0x81); + if (card->type == SC_CARD_TYPE_SC_HSM_GOID) { + apdu.cla = 0x80; + } apdu.resp = rbuf; apdu.resplen = sizeof rbuf; r = sc_transmit_apdu(card, &apdu); @@ -564,8 +599,9 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, /* For contactless cards always establish a secure channel before PIN * verification. Also, Session PIN generation requires SM. */ - if ((card->type == SC_CARD_TYPE_SC_HSM_SOC || card->reader->uid.len - || cmd == SC_PIN_CMD_GET_SESSION_PIN) + if ((card->type == SC_CARD_TYPE_SC_HSM_SOC + || card->type == SC_CARD_TYPE_SC_HSM_GOID + || card->reader->uid.len || cmd == SC_PIN_CMD_GET_SESSION_PIN) && (data->cmd != SC_PIN_CMD_GET_INFO) #ifdef ENABLE_SM && card->sm_ctx.sm_mode != SM_MODE_TRANSMIT @@ -1575,7 +1611,8 @@ static int sc_hsm_init(struct sc_card *card) } card->max_send_size = 1431; // 1439 buffer size - 8 byte TLV because of odd ins in UPDATE BINARY - if (card->type == SC_CARD_TYPE_SC_HSM_SOC) { + if (card->type == SC_CARD_TYPE_SC_HSM_SOC + || card->type == SC_CARD_TYPE_SC_HSM_GOID) { card->max_recv_size = 0x0630; // SoC Proxy forces this limit } else { card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index f7c78dd8..fb4f9d6a 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -204,6 +204,7 @@ enum { /* SmartCard-HSM */ SC_CARD_TYPE_SC_HSM = 26000, SC_CARD_TYPE_SC_HSM_SOC = 26001, + SC_CARD_TYPE_SC_HSM_GOID = 26002, /* Spanish DNIe card */ SC_CARD_TYPE_DNIE_BASE = 27000, diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index 26eaa058..3829f2f3 100644 --- a/src/libopensc/pkcs15-sc-hsm.c +++ b/src/libopensc/pkcs15-sc-hsm.c @@ -941,7 +941,8 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) LOG_FUNC_RETURN(card->ctx, r); - if (card->type == SC_CARD_TYPE_SC_HSM_SOC) { + if (card->type == SC_CARD_TYPE_SC_HSM_SOC + || card->type == SC_CARD_TYPE_SC_HSM_GOID) { /* SC-HSM of this type always has a PIN-Pad */ r = SC_SUCCESS; } else { @@ -998,7 +999,8 @@ int sc_pkcs15emu_sc_hsm_init_ex(sc_pkcs15_card_t *p15card, return sc_pkcs15emu_sc_hsm_init(p15card); } else { if (p15card->card->type != SC_CARD_TYPE_SC_HSM - && p15card->card->type != SC_CARD_TYPE_SC_HSM_SOC) { + && p15card->card->type != SC_CARD_TYPE_SC_HSM_SOC + && p15card->card->type != SC_CARD_TYPE_SC_HSM_GOID) { return SC_ERROR_WRONG_CARD; } return sc_pkcs15emu_sc_hsm_init(p15card); From a1466f7395945cdde8be7b005d69de3875dd7d06 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 11 Jul 2017 15:13:53 +0200 Subject: [PATCH 06/36] sc-hsm: better error messages for optional files --- src/libopensc/pkcs15-sc-hsm.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index 3829f2f3..dd428fac 100644 --- a/src/libopensc/pkcs15-sc-hsm.c +++ b/src/libopensc/pkcs15-sc-hsm.c @@ -606,13 +606,13 @@ static int sc_pkcs15emu_sc_hsm_add_prkd(sc_pkcs15_card_t * p15card, u8 keyid) { /* Try to select a related EF containing the PKCS#15 description of the key */ len = sizeof efbin; r = read_file(p15card, fid, efbin, &len, 1); - LOG_TEST_RET(card->ctx, r, "Could not read EF.PRKD"); + LOG_TEST_RET(card->ctx, r, "Skipping optional EF.PRKD"); ptr = efbin; memset(&prkd, 0, sizeof(prkd)); r = sc_pkcs15_decode_prkdf_entry(p15card, &prkd, (const u8 **)&ptr, &len); - LOG_TEST_RET(card->ctx, r, "Could not decode EF.PRKD"); + LOG_TEST_RET(card->ctx, r, "Skipping optional EF.PRKD"); /* All keys require user PIN authentication */ prkd.auth_id.len = 1; @@ -642,8 +642,6 @@ static int sc_pkcs15emu_sc_hsm_add_prkd(sc_pkcs15_card_t * p15card, u8 keyid) { r = read_file(p15card, fid, efbin, &len, 0); LOG_TEST_RET(card->ctx, r, "Could not read EF"); - LOG_TEST_RET(card->ctx, r, "Could not read EF"); - if (efbin[0] == 0x67) { /* Decode CSR and create public key object */ sc_pkcs15emu_sc_hsm_add_pubkey(p15card, efbin, len, key_info, prkd.label); free(key_info); @@ -702,13 +700,13 @@ static int sc_pkcs15emu_sc_hsm_add_dcod(sc_pkcs15_card_t * p15card, u8 id) { /* Try to select a related EF containing the PKCS#15 description of the data */ len = sizeof efbin; r = read_file(p15card, fid, efbin, &len, 1); - LOG_TEST_RET(card->ctx, r, "Could not read EF.DCOD"); + LOG_TEST_RET(card->ctx, r, "Skipping optional EF.DCOD"); ptr = efbin; memset(&data_obj, 0, sizeof(data_obj)); r = sc_pkcs15_decode_dodf_entry(p15card, &data_obj, &ptr, &len); - LOG_TEST_RET(card->ctx, r, "Could not decode EF.DCOD"); + LOG_TEST_RET(card->ctx, r, "Could not decode optional EF.DCOD"); data_info = (sc_pkcs15_data_info_t *)data_obj.data; @@ -741,13 +739,13 @@ static int sc_pkcs15emu_sc_hsm_add_cd(sc_pkcs15_card_t * p15card, u8 id) { /* Try to select a related EF containing the PKCS#15 description of the data */ len = sizeof efbin; r = read_file(p15card, fid, efbin, &len, 1); - LOG_TEST_RET(card->ctx, r, "Could not read EF.DCOD"); + LOG_TEST_RET(card->ctx, r, "Skipping optional EF.DCOD"); ptr = efbin; memset(&obj, 0, sizeof(obj)); r = sc_pkcs15_decode_cdf_entry(p15card, &obj, &ptr, &len); - LOG_TEST_RET(card->ctx, r, "Could not decode EF.CD"); + LOG_TEST_RET(card->ctx, r, "Skipping optional EF.CDOD"); cert_info = (sc_pkcs15_cert_info_t *)obj.data; @@ -772,10 +770,10 @@ static int sc_pkcs15emu_sc_hsm_read_tokeninfo (sc_pkcs15_card_t * p15card) /* Read token info */ len = sizeof efbin; r = read_file(p15card, (u8 *) "\x2F\x03", efbin, &len, 1); - LOG_TEST_RET(card->ctx, r, "Could not read EF.TokenInfo"); + LOG_TEST_RET(card->ctx, r, "Skipping optional EF.TokenInfo"); r = sc_pkcs15_parse_tokeninfo(card->ctx, p15card->tokeninfo, efbin, len); - LOG_TEST_RET(card->ctx, r, "Could not decode EF.TokenInfo"); + LOG_TEST_RET(card->ctx, r, "Skipping optional EF.TokenInfo"); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } @@ -835,7 +833,7 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) } else { len = sizeof efbin; r = read_file(p15card, (u8 *) "\x2F\x02", efbin, &len, 1); - LOG_TEST_RET(card->ctx, r, "Could not select EF.C_DevAut"); + LOG_TEST_RET(card->ctx, r, "Skipping optional EF.C_DevAut"); /* save EF_C_DevAut for further use */ ptr = realloc(priv->EF_C_DevAut, len); From d5647fe53d18154489320cae31402bb602da12e3 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 16 Aug 2017 14:20:56 +0200 Subject: [PATCH 07/36] [pkcs11-tool] Properly define RSA-PSS mechanisms --- src/tools/pkcs11-tool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index f1ff0efb..edbf5ce2 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -5622,9 +5622,9 @@ static struct mech_info p11_mechanisms[] = { { CKM_SHA1_RSA_X9_31, "SHA1-RSA-X9-31", NULL }, { CKM_RSA_PKCS_PSS, "RSA-PKCS-PSS", NULL }, { CKM_SHA1_RSA_PKCS_PSS, "SHA1-RSA-PKCS-PSS", NULL }, - { CKM_SHA256_RSA_PKCS, "SHA256-RSA-PKCS-PSS", NULL }, - { CKM_SHA384_RSA_PKCS, "SHA384-RSA-PKCS-PSS", NULL }, - { CKM_SHA512_RSA_PKCS, "SHA512-RSA-PKCS-PSS", NULL }, + { CKM_SHA256_RSA_PKCS_PSS,"SHA256-RSA-PKCS-PSS", NULL }, + { CKM_SHA384_RSA_PKCS_PSS,"SHA384-RSA-PKCS-PSS", NULL }, + { CKM_SHA512_RSA_PKCS_PSS,"SHA512-RSA-PKCS-PSS", NULL }, { CKM_DSA_KEY_PAIR_GEN, "DSA-KEY-PAIR-GEN", NULL }, { CKM_DSA, "DSA", NULL }, { CKM_DSA_SHA1, "DSA-SHA1", NULL }, From 41796ff0ed3125bebe29479fc831165ba40c9a3b Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 16 Aug 2017 14:21:22 +0200 Subject: [PATCH 08/36] [pkcs11-tool] Add SHA2 HMAC mechanisms --- 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 edbf5ce2..53d26da1 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -5671,8 +5671,11 @@ static struct mech_info p11_mechanisms[] = { { CKM_SHA_1_HMAC, "SHA-1-HMAC", NULL }, { CKM_SHA_1_HMAC_GENERAL, "SHA-1-HMAC-GENERAL", NULL }, { CKM_SHA256, "SHA256", NULL }, + { CKM_SHA256_HMAC, "SHA256-HMAC", NULL }, { CKM_SHA384, "SHA384", NULL }, + { CKM_SHA384_HMAC, "SHA384-HMAC", NULL }, { CKM_SHA512, "SHA512", NULL }, + { CKM_SHA512_HMAC, "SHA512-HMAC", NULL }, { CKM_RIPEMD128, "RIPEMD128", NULL }, { CKM_RIPEMD128_HMAC, "RIPEMD128-HMAC", NULL }, { CKM_RIPEMD128_HMAC_GENERAL,"RIPEMD128-HMAC-GENERAL", NULL }, From 2765b7b1a097daa46e412b58933ec5a6e85f6ce3 Mon Sep 17 00:00:00 2001 From: Arnaud Fontaine Date: Tue, 22 Aug 2017 01:13:18 +0200 Subject: [PATCH 09/36] Support for new MinInt agent card (#1092) * Support for new MinInt agent card This card uses the same ATR as the existing card, but the applet installed does not have the same AID. This card actually works exactly as the IASECC_SAGEM. Unify iasecc_init for AMOS/SAGEM and MI cards --- src/libopensc/card-iasecc.c | 114 +++++++++++++----------------------- src/libopensc/cards.h | 1 + 2 files changed, 41 insertions(+), 74 deletions(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 9b97c18f..ea61db3c 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -264,6 +264,9 @@ iasecc_select_mf(struct sc_card *card, struct sc_file **file_out) apdu.resplen = sizeof(apdu_resp); apdu.resp = apdu_resp; + if (card->type == SC_CARD_TYPE_IASECC_MI2) + apdu.p2 = 0x04; + rv = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, rv, "APDU transmit failed"); rv = sc_check_sw(card, apdu.sw1, apdu.sw2); @@ -513,75 +516,21 @@ iasecc_init_oberthur(struct sc_card *card) } -static int -iasecc_init_sagem(struct sc_card *card) -{ - struct sc_context *ctx = card->ctx; - unsigned int flags; - 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; - - rv = iasecc_parse_ef_atr(card); - if (rv == SC_ERROR_FILE_NOT_FOUND) { - rv = iasecc_select_mf(card, NULL); - LOG_TEST_RET(ctx, rv, "MF selection error"); - - rv = iasecc_parse_ef_atr(card); - } - LOG_TEST_RET(ctx, rv, "IASECC: ATR parse failed"); - - LOG_FUNC_RETURN(ctx, SC_SUCCESS); -} - - -static int -iasecc_init_amos(struct sc_card *card) -{ - struct sc_context *ctx = card->ctx; - unsigned int flags; - 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; - - rv = iasecc_parse_ef_atr(card); - if (rv == SC_ERROR_FILE_NOT_FOUND) { - rv = iasecc_select_mf(card, NULL); - LOG_TEST_RET(ctx, rv, "MF selection error"); - - rv = iasecc_parse_ef_atr(card); - } - - LOG_TEST_RET(ctx, rv, "IASECC: ATR parse failed"); - LOG_FUNC_RETURN(ctx, SC_SUCCESS); -} - static int iasecc_mi_match(struct sc_card *card) { struct sc_context *ctx = card->ctx; + unsigned char resp[0x100]; + size_t resp_len; + int rv = 0; LOG_FUNC_CALLED(ctx); - if (!card->ef_atr) + resp_len = sizeof(resp); + rv = iasecc_select_aid(card, &MIIASECC_AID, resp, &resp_len); + LOG_TEST_RET(ctx, rv, "IASECC: failed to select MI IAS/ECC applet"); + + 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); @@ -592,13 +541,12 @@ iasecc_mi_match(struct sc_card *card) LOG_FUNC_RETURN(ctx, SC_SUCCESS); } + static int -iasecc_init_mi(struct sc_card *card) +iasecc_init_amos_or_sagem(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); @@ -612,16 +560,27 @@ iasecc_init_mi(struct sc_card *card) 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"); + if (card->type == SC_CARD_TYPE_IASECC_MI) { + rv = iasecc_mi_match(card); + if (rv) + card->type = SC_CARD_TYPE_IASECC_MI2; + else + LOG_FUNC_RETURN(ctx, SC_SUCCESS); + } - rv = iasecc_mi_match(card); - LOG_TEST_RET(ctx, rv, "Could not match MI's AID"); + rv = iasecc_parse_ef_atr(card); + if (rv == SC_ERROR_FILE_NOT_FOUND) { + rv = iasecc_select_mf(card, NULL); + LOG_TEST_RET(ctx, rv, "MF selection error"); + + rv = iasecc_parse_ef_atr(card); + } + LOG_TEST_RET(ctx, rv, "IASECC: ATR parse failed"); LOG_FUNC_RETURN(ctx, SC_SUCCESS); } + static int iasecc_init(struct sc_card *card) { @@ -642,11 +601,11 @@ iasecc_init(struct sc_card *card) else if (card->type == SC_CARD_TYPE_IASECC_OBERTHUR) rv = iasecc_init_oberthur(card); else if (card->type == SC_CARD_TYPE_IASECC_SAGEM) - rv = iasecc_init_sagem(card); + rv = iasecc_init_amos_or_sagem(card); else if (card->type == SC_CARD_TYPE_IASECC_AMOS) - rv = iasecc_init_amos(card); + rv = iasecc_init_amos_or_sagem(card); else if (card->type == SC_CARD_TYPE_IASECC_MI) - rv = iasecc_init_mi(card); + rv = iasecc_init_amos_or_sagem(card); else LOG_FUNC_RETURN(ctx, SC_ERROR_NO_CARD_SUPPORT); @@ -950,7 +909,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, && 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_MI) + && card->type != SC_CARD_TYPE_IASECC_MI + && card->type != SC_CARD_TYPE_IASECC_MI2) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported card"); if (lpath.type == SC_PATH_TYPE_FILE_ID) { @@ -963,6 +923,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, apdu.p2 = 0x04; if (card->type == SC_CARD_TYPE_IASECC_MI) apdu.p2 = 0x04; + if (card->type == SC_CARD_TYPE_IASECC_MI2) + apdu.p2 = 0x04; } else if (lpath.type == SC_PATH_TYPE_FROM_CURRENT) { apdu.p1 = 0x09; @@ -972,6 +934,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, apdu.p2 = 0x04; if (card->type == SC_CARD_TYPE_IASECC_MI) apdu.p2 = 0x04; + if (card->type == SC_CARD_TYPE_IASECC_MI2) + apdu.p2 = 0x04; } else if (lpath.type == SC_PATH_TYPE_PARENT) { apdu.p1 = 0x03; @@ -982,6 +946,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, apdu.p1 = 0x04; if (card->type == SC_CARD_TYPE_IASECC_AMOS) apdu.p2 = 0x04; + if (card->type == SC_CARD_TYPE_IASECC_MI2) + apdu.p2 = 0x04; } else { sc_log(ctx, "Invalid PATH type: 0x%X", lpath.type); diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index fb4f9d6a..0cc7650e 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -200,6 +200,7 @@ enum { SC_CARD_TYPE_IASECC_SAGEM, SC_CARD_TYPE_IASECC_AMOS, SC_CARD_TYPE_IASECC_MI, + SC_CARD_TYPE_IASECC_MI2, /* SmartCard-HSM */ SC_CARD_TYPE_SC_HSM = 26000, From 172f320c9a1b5664240be5fa3e143622941b2845 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 17 Jul 2017 22:53:07 +0200 Subject: [PATCH 10/36] win32: Dedicated md/pkcs11 installation folders Don't install non-permanent files (md/pkcs11) to system folder anymore. --- configure.ac | 6 +- src/minidriver/Makefile.am | 4 +- src/minidriver/minidriver-feitian.reg | 30 -------- src/minidriver/minidriver-italian-cns.reg | 33 --------- src/minidriver/minidriver-sc-hsm.reg | Bin 1460 -> 0 bytes src/minidriver/minidriver-westcos.reg | 7 -- src/pkcs11/pkcs11-spy.c | 2 +- src/pkcs11/sc-pkcs11.h | 6 -- src/tools/pkcs11-tool.c | 13 +++- win32/OpenSC.wxs.in | 80 +++++++++++----------- win32/customactions.cpp | 15 ++-- 11 files changed, 72 insertions(+), 124 deletions(-) delete mode 100644 src/minidriver/minidriver-feitian.reg delete mode 100644 src/minidriver/minidriver-italian-cns.reg delete mode 100644 src/minidriver/minidriver-sc-hsm.reg delete mode 100644 src/minidriver/minidriver-westcos.reg diff --git a/configure.ac b/configure.ac index ba45c210..e1c3f8a0 100644 --- a/configure.ac +++ b/configure.ac @@ -784,7 +784,11 @@ if test "${enable_sm}" = "yes"; then fi if test "${with_pkcs11_provider}" = "detect"; then - DEFAULT_PKCS11_PROVIDER="opensc-pkcs11${DYN_LIB_EXT}" + if test "${WIN32}" != "yes"; then + DEFAULT_PKCS11_PROVIDER="opensc-pkcs11${DYN_LIB_EXT}" + else + DEFAULT_PKCS11_PROVIDER="%PROGRAMFILES%\\\OpenSC Project\\\OpenSC\\\pkcs11\\\opensc-pkcs11.dll" + fi else DEFAULT_PKCS11_PROVIDER="${with_pkcs11_provider}" fi diff --git a/src/minidriver/Makefile.am b/src/minidriver/Makefile.am index 6448e7ae..d276f97e 100644 --- a/src/minidriver/Makefile.am +++ b/src/minidriver/Makefile.am @@ -7,9 +7,9 @@ if ENABLE_MINIDRIVER lib_LTLIBRARIES = opensc-minidriver@LIBRARY_BITNESS@.la # Do we need this on bin? Why can't we # put it in dedicated directory -dist_sbin_SCRIPTS = opensc-minidriver.inf minidriver-westcos.reg minidriver-sc-hsm.reg minidriver-feitian.reg +dist_sbin_SCRIPTS = opensc-minidriver.inf else -dist_noinst_DATA = opensc-minidriver.inf minidriver-westcos.reg minidriver-sc-hsm.reg minidriver-feitian.reg +dist_noinst_DATA = opensc-minidriver.inf endif AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) diff --git a/src/minidriver/minidriver-feitian.reg b/src/minidriver/minidriver-feitian.reg deleted file mode 100644 index 446ef1cf..00000000 --- a/src/minidriver/minidriver-feitian.reg +++ /dev/null @@ -1,30 +0,0 @@ -Windows Registry Editor Version 5.00 - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\ePass2003] -"ATR"=hex:3b,9f,95,81,31,fe,9f,00,66,46,53,05,01,00,11,71,df,00,00,03,6a,82,f8 -"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 -"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" -"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider" -"80000001"="opensc-minidriver.dll" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\ePass2003] -"ATR"=hex:3b,9f,95,81,31,fe,9f,00,66,46,53,05,01,00,11,71,df,00,00,03,6a,82,f8 -"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,00,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff -"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" -"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider" -"80000001"="opensc-minidriver.dll" - - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\FTCOS/PK-01C] -"ATR"=hex:3b,9f,95,81,31,fe,9f,00,65,46,53,05,00,06,71,df,00,00,00,00,00,00,00 -"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,00,ff,ff,ff,ff,ff,ff,00,00,00,00 -"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" -"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider" -"80000001"="opensc-minidriver.dll" - -[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\FTCOS/PK-01C] -"ATR"=hex:3b,9f,95,81,31,fe,9f,00,65,46,53,05,00,06,71,df,00,00,00,00,00,00,00 -"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,00,ff,ff,ff,ff,ff,ff,00,00,00,00 -"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" -"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider" -"80000001"="opensc-minidriver.dll" diff --git a/src/minidriver/minidriver-italian-cns.reg b/src/minidriver/minidriver-italian-cns.reg deleted file mode 100644 index 3bca8d4a..00000000 --- a/src/minidriver/minidriver-italian-cns.reg +++ /dev/null @@ -1,33 +0,0 @@ -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 diff --git a/src/minidriver/minidriver-sc-hsm.reg b/src/minidriver/minidriver-sc-hsm.reg deleted file mode 100644 index 38598b2cd21547baba26ef38c8cd7bfaa15c26f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1460 zcmd^|u?##oRreVNb9|+-KZN%B#Ry*P7cG zI?xd@=jy4h6VgMptk=Z&FkuyO) zxcc+lrY!$G&mvDxr+CJAT8woo&HBAQPgU5?@$nWa@IGoV?X&)6d9CX{9cdu2kd zCv9m{R|@Fi5Lu+kz}1(@3Rr-T$6T6G& Q? #ifndef _WIN32 -#include #include #include +#include #else +#include #include #endif @@ -537,6 +538,9 @@ int main(int argc, char * argv[]) CK_RV rv; #ifdef _WIN32 + char expanded_val[PATH_MAX]; + DWORD expanded_len; + if(_setmode(_fileno(stdout), _O_BINARY ) == -1) util_fatal("Cannot set FMODE to O_BINARY"); if(_setmode(_fileno(stdin), _O_BINARY ) == -1) @@ -844,6 +848,13 @@ int main(int argc, char * argv[]) if (action_count == 0) util_print_usage_and_die(app_name, options, option_help, NULL); +#ifdef _WIN32 + expanded_len = PATH_MAX; + expanded_len = ExpandEnvironmentStringsA(opt_module, expanded_val, expanded_len); + if (0 < expanded_len && expanded_len < sizeof expanded_val) + opt_module = expanded_val; +#endif + module = C_LoadModule(opt_module, &p11); if (module == NULL) util_fatal("Failed to load pkcs11 module"); diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index 9ae8b210..52121028 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -7,7 +7,6 @@ - @@ -17,7 +16,6 @@ - @@ -59,47 +57,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -113,6 +74,38 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -288,6 +281,15 @@ + + + + + + + + + diff --git a/win32/customactions.cpp b/win32/customactions.cpp index f576fc6e..f417d74b 100644 --- a/win32/customactions.cpp +++ b/win32/customactions.cpp @@ -64,12 +64,10 @@ typedef struct _MD_REGISTRATION 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}, @@ -100,7 +98,6 @@ MD_REGISTRATION minidriver_registration[] = { 19, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, {TEXT("GoID (11)"), {0x3B,0x8f,0x80,0x01,0x47,0x6f,0x49,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 20, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, - /* 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 */ @@ -254,8 +251,18 @@ void RegisterCardWithKey(PTSTR szKey, PTSTR szCard, PTSTR szPath, PBYTE pbATR, D VOID RegisterSmartCard(PMD_REGISTRATION registration) { - RegisterCardWithKey(SC_DATABASE, registration->szName, TEXT("opensc-minidriver.dll"),registration->pbAtr, registration->dwAtrSize, registration->pbAtrMask ); + DWORD expanded_len = PATH_MAX; + TCHAR expanded_val[PATH_MAX]; + PTSTR szPath = TEXT("C:\\Program Files\\OpenSC Project\\OpenSC\\minidriver\\opensc-minidriver.dll"); + /* cope with x86 installation on x64 */ + expanded_len = ExpandEnvironmentStrings( + TEXT("%ProgramFiles%\\OpenSC Project\\OpenSC\\minidriver\\opensc-minidriver.dll"), + expanded_val, expanded_len); + if (0 < expanded_len && expanded_len < sizeof expanded_val) + szPath = expanded_val; + + RegisterCardWithKey(SC_DATABASE, registration->szName, szPath, registration->pbAtr, registration->dwAtrSize, registration->pbAtrMask ); } UINT WINAPI AddSmartCardConfiguration(MSIHANDLE hInstall) From 555671b54d307a0b62cca8de63b74e2f248fd877 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 17 Aug 2017 21:46:21 +0200 Subject: [PATCH 11/36] sc_read_binary may return less bytes than requested Note, that there are a number of card drivers that still use `sc_read_binary` in the wrong way. Unfortunately, I don't have the time to go through all of them. Fixes https://github.com/OpenSC/OpenSC/issues/1112 --- src/libopensc/pkcs15.c | 33 ++++++++++++++++++--------------- src/pkcs15init/pkcs15-lib.c | 2 +- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 2ce34b6c..05fe0306 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -1059,15 +1059,17 @@ sc_pkcs15_bind_internal(struct sc_pkcs15_card *p15card, struct sc_aid *aid) } if (err < 0) { err = sc_read_binary(card, 0, buf, len, 0); - if (err < 0) { - sc_log(ctx, "read EF(ODF) file error: %s", sc_strerror(err)); - goto end; - } - else if (err < 2) { - err = SC_ERROR_PKCS15_APP_NOT_FOUND; - sc_log(ctx, "Invalid content of EF(ODF): %s", sc_strerror(err)); + if (err < 2) { + if (err < 0) { + sc_log(ctx, "read EF(ODF) file error: %s", sc_strerror(err)); + } else { + err = SC_ERROR_PKCS15_APP_NOT_FOUND; + sc_log(ctx, "Invalid content of EF(ODF): %s", sc_strerror(err)); + } goto end; } + /* sc_read_binary may return less than requested */ + len = err; if (p15card->opts.use_file_cache) { sc_pkcs15_cache_file(p15card, &tmppath, buf, len); @@ -1125,20 +1127,21 @@ sc_pkcs15_bind_internal(struct sc_pkcs15_card *p15card, struct sc_aid *aid) } if (err < 0) { err = sc_read_binary(card, 0, buf, len, 0); - if (err < 0) { - sc_log(ctx, "read EF(TokenInfo) file error: %s", sc_strerror(err)); - goto end; - } if (err <= 2) { - err = SC_ERROR_PKCS15_APP_NOT_FOUND; - sc_log(ctx, "Invalid content of EF(TokenInfo): %s", sc_strerror(err)); + if (err < 0) { + sc_log(ctx, "read EF(TokenInfo) file error: %s", sc_strerror(err)); + } else { + err = SC_ERROR_PKCS15_APP_NOT_FOUND; + sc_log(ctx, "Invalid content of EF(TokenInfo): %s", sc_strerror(err)); + } goto end; } + /* sc_read_binary may return less than requested */ + len = err; if (p15card->opts.use_file_cache) { sc_pkcs15_cache_file(p15card, &tmppath, buf, len); } - err = len; } memset(&tokeninfo, 0, sizeof(tokeninfo)); @@ -2392,7 +2395,7 @@ sc_pkcs15_read_file(struct sc_pkcs15_card *p15card, const struct sc_path *in_pat sc_file_free(file); - if (p15card->opts.use_file_cache) { + if (len && p15card->opts.use_file_cache) { sc_pkcs15_cache_file(p15card, in_path, data, len); } } diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 9339aebb..5dfe2be6 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -4211,7 +4211,7 @@ sc_pkcs15init_read_info(struct sc_card *card, struct sc_profile *profile) } if (r >= 0) - r = sc_pkcs15init_parse_info(card, mem, len, profile); + r = sc_pkcs15init_parse_info(card, mem, r, profile); if (mem) free(mem); From 1efc73fa2fe86678f8c89a36756cec634de1d7de Mon Sep 17 00:00:00 2001 From: Mouse Date: Thu, 24 Aug 2017 21:27:47 -0400 Subject: [PATCH 12/36] Fix typo in ECDSA-SHA384 for pkcs11-tool --- 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 8aa1cffe..64f11c89 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -5784,7 +5784,7 @@ static struct mech_info p11_mechanisms[] = { { CKM_ECDSA_SHA1, "ECDSA-SHA1", NULL }, { CKM_ECDSA_SHA224, "ECDSA-SHA224", NULL }, { CKM_ECDSA_SHA256, "ECDSA-SHA256", NULL }, - { CKM_ECDSA_SHA384, "ECDSA-SHA348", NULL }, + { CKM_ECDSA_SHA384, "ECDSA-SHA384", NULL }, { CKM_ECDSA_SHA512, "ECDSA-SHA512", NULL }, { CKM_ECDH1_DERIVE, "ECDH1-DERIVE", NULL }, { CKM_ECDH1_COFACTOR_DERIVE,"ECDH1-COFACTOR-DERIVE", NULL }, From f0e703be4935cadd76d8773c4ce5bd3ad7386da0 Mon Sep 17 00:00:00 2001 From: Mouse Date: Tue, 29 Aug 2017 00:31:39 -0400 Subject: [PATCH 13/36] Fix bug in pkcs11-tool (did not ASN.1-encode ECDSA-SHA-2 signature) --- 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 64f11c89..4240a0c3 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -1670,7 +1670,7 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, util_fatal("failed to open %s: %m", opt_output); } - if (opt_mechanism == CKM_ECDSA || opt_mechanism == CKM_ECDSA_SHA1) { + if (opt_mechanism == CKM_ECDSA || opt_mechanism == CKM_ECDSA_SHA1 || opt_mechanism == CKM_ECDSA_SHA256 || opt_mechanism == CKM_ECDSA_SHA384 || opt_mechanism == CKM_ECDSA_SHA512) { if (opt_sig_format && (!strcmp(opt_sig_format, "openssl") || !strcmp(opt_sig_format, "sequence"))) { unsigned char *seq; size_t seqlen; From 56c8f59b25c222cfe2b57dcf78c8bbc26eb595df Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 18 Aug 2017 13:49:57 +0200 Subject: [PATCH 14/36] Use shorter PIN name for default PIN to accomodate Card Holder name in future --- src/libopensc/pkcs15-piv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index d38d7ba7..7f9015dc 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -359,7 +359,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) }; static const pindata pins[] = { - { "01", "PIV Card Holder pin", "", 0x80, + { "01", "PIN", "", 0x80, /* label, flag and ref will change if using global pin */ SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, @@ -932,7 +932,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) pin_info.attrs.pin.reference = pin_ref; pin_info.attrs.pin.flags &= ~SC_PKCS15_PIN_FLAG_LOCAL; label = "Global PIN"; - } + } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE Adding pin %d label=%s",i, label); strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; From d018855b9ff638698ff063c0157039ae2f45721b Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 18 Aug 2017 14:18:00 +0200 Subject: [PATCH 15/36] Get cardholder name from the first certificate --- src/libopensc/pkcs15-piv.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index 7f9015dc..6f3c9199 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -613,7 +613,7 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) char buf[SC_MAX_SERIALNR * 2 + 1]; common_key_info ckis[PIV_NUM_CERTS_AND_KEYS]; int follows_nist_fascn = 0; - + char *token_name = NULL; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); @@ -765,6 +765,28 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) sc_pkcs15_free_certificate(cert_out); continue; } + + /* set the token name to the name of the CN of the first certificate */ + if (!token_name) { + u8 * cn_name = NULL; + size_t cn_len = 0; + static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }}; + r = sc_pkcs15_get_name_from_dn(card->ctx, cert_out->subject, + cert_out->subject_len, &cn_oid, &cn_name, &cn_len); + if (r == SC_SUCCESS) { + token_name = malloc (cn_len+1); + if (!token_name) { + SC_FUNC_RETURN(card->ctx, + SC_ERROR_OUT_OF_MEMORY, r); + } + memcpy(token_name, cn_name, cn_len); + free(cn_name); + token_name[cn_len] = 0; + free(p15card->tokeninfo->label); + p15card->tokeninfo->label = token_name; + } + } + /* * get keyUsage if present save in ckis[i] * Will only use it if this in a non FED issued card From 804f47b2988d3b21233d8e90dbe79dd22e5c9757 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 21 Aug 2017 13:43:08 +0200 Subject: [PATCH 16/36] Do not add non-informative PIN to the token label --- src/pkcs11/framework-pkcs15.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 5b3cb32e..8ded1125 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1024,6 +1024,7 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot, struct sc_pkcs15_auth_info *pin_info = NULL; char label[64]; + sc_log(context, "Called"); pkcs15_init_token_info(p15card, &slot->token_info); slot->token_info.flags |= CKF_TOKEN_INITIALIZED; if (auth != NULL) @@ -1048,9 +1049,10 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot, pin_info = NULL; } else { - if (auth->label[0]) + if (auth->label[0] && strncmp(auth->label, "PIN", 4) != 0) snprintf(label, sizeof(label), "%.*s (%s)", (int) sizeof auth->label, auth->label, p15card->tokeninfo->label); else + /* The PIN label is empty or says just non-useful "PIN" */ snprintf(label, sizeof(label), "%s", p15card->tokeninfo->label); slot->token_info.flags |= CKF_LOGIN_REQUIRED; } From eee4964d7fc9f134eb50caab2f011490dd05f281 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 22 Aug 2017 10:29:40 +0200 Subject: [PATCH 17/36] The cardos driver supports also CardOS 5 CardOS M4 is confusing since it refers to the old card versions --- src/libopensc/card-cardos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index 41e28835..bbdb814e 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -171,7 +171,7 @@ static int cardos_init(sc_card_t *card) sc_apdu_t apdu; u8 rbuf[2]; - card->name = "CardOS M4"; + card->name = "Atos CardOS"; card->cla = 0x00; /* Set up algorithm info. */ From 60dbebf511cf6112e5fc2c3549ce38881847b121 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 22 Aug 2017 10:46:26 +0200 Subject: [PATCH 18/36] Parse the ECC parameters from TokenInfo (CHOICE in AlgorithmInfo) Fixes #1134 --- src/libopensc/opensc.h | 1 + src/libopensc/pkcs15.c | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index f81f27e3..688c1400 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -163,6 +163,7 @@ extern "C" { struct sc_supported_algo_info { unsigned int reference; unsigned int mechanism; + struct sc_object_id *parameters; /* OID for ECC, NULL for RSA */ unsigned int operations; struct sc_object_id algo_id; unsigned int algo_ref; diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 05fe0306..ba99c8af 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -50,13 +50,19 @@ static const struct sc_asn1_entry c_asn1_twlabel[] = { static const struct sc_asn1_entry c_asn1_algorithm_info[7] = { { "reference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, { "algorithmPKCS#11", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, - { "parameters", SC_ASN1_NULL, SC_ASN1_TAG_NULL, 0, NULL, NULL }, + { "parameters", SC_ASN1_CHOICE, 0, 0, NULL, NULL }, { "supportedOperations",SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL }, { "objId", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, SC_ASN1_OPTIONAL, NULL, NULL }, { "algRef", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { NULL, 0, 0, 0, NULL, NULL } }; +static const struct sc_asn1_entry c_asn1_algorithm_info_parameters[3] = { + { "PKCS15RSAParameters",SC_ASN1_NULL, SC_ASN1_TAG_NULL, 0, NULL, NULL }, + { "PKCS15ECParameters", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, NULL, NULL }, + { NULL, 0, 0, 0, NULL, NULL } +}; + /* * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 */ @@ -134,9 +140,11 @@ int sc_pkcs15_parse_tokeninfo(sc_context_t *ctx, u8 preferred_language[3]; size_t lang_length = sizeof(preferred_language); struct sc_asn1_entry asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1], - asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7]; + asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7], + asn1_algo_infos_parameters[SC_MAX_SUPPORTED_ALGORITHMS][3]; size_t reference_len = sizeof(ti->supported_algos[0].reference); size_t mechanism_len = sizeof(ti->supported_algos[0].mechanism); + size_t parameter_len = sizeof(ti->supported_algos[0].parameters); size_t operations_len = sizeof(ti->supported_algos[0].operations); size_t algo_ref_len = sizeof(ti->supported_algos[0].algo_ref); @@ -152,14 +160,22 @@ int sc_pkcs15_parse_tokeninfo(sc_context_t *ctx, sc_format_asn1_entry(asn1_twlabel, label, &label_len, 0); sc_copy_asn1_entry(c_asn1_profile_indication, asn1_profile_indication); - for (ii=0; iisupported_algos[ii].reference, &reference_len, 0); sc_format_asn1_entry(asn1_algo_infos[ii] + 1, &ti->supported_algos[ii].mechanism, &mechanism_len, 0); - sc_format_asn1_entry(asn1_algo_infos[ii] + 2, NULL, NULL, 0); + sc_format_asn1_entry(asn1_algo_infos[ii] + 2, + asn1_algo_infos_parameters[ii], NULL, 0); + sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0, + NULL, NULL, 0); + sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 1, + &ti->supported_algos[ii].parameters, ¶meter_len, 0); sc_format_asn1_entry(asn1_algo_infos[ii] + 3, &ti->supported_algos[ii].operations, &operations_len, 0); sc_format_asn1_entry(asn1_algo_infos[ii] + 4, &ti->supported_algos[ii].algo_id, NULL, 1); sc_format_asn1_entry(asn1_algo_infos[ii] + 5, &ti->supported_algos[ii].algo_ref, &algo_ref_len, 0); @@ -270,9 +286,11 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, struct sc_asn1_entry asn1_toki_attrs[C_ASN1_TOKI_ATTRS_SIZE]; struct sc_asn1_entry asn1_tokeninfo[2]; struct sc_asn1_entry asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1], - asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7]; + asn1_algo_infos[SC_MAX_SUPPORTED_ALGORITHMS][7], + asn1_algo_infos_parameters[SC_MAX_SUPPORTED_ALGORITHMS][3]; size_t reference_len = sizeof(ti->supported_algos[0].reference); size_t mechanism_len = sizeof(ti->supported_algos[0].mechanism); + size_t parameter_len = sizeof(ti->supported_algos[0].parameters); size_t operations_len = sizeof(ti->supported_algos[0].operations); size_t algo_ref_len = sizeof(ti->supported_algos[0].algo_ref); struct sc_asn1_entry asn1_last_update[C_ASN1_LAST_UPDATE_SIZE]; @@ -283,14 +301,22 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, sc_copy_asn1_entry(c_asn1_last_update, asn1_last_update); sc_copy_asn1_entry(c_asn1_profile_indication, asn1_profile_indication); - for (ii=0; iisupported_algos[ii].reference; ii++) + for (ii=0; iisupported_algos[ii].reference; ii++) { sc_copy_asn1_entry(c_asn1_algorithm_info, asn1_algo_infos[ii]); + sc_copy_asn1_entry(c_asn1_algorithm_info_parameters, + asn1_algo_infos_parameters[ii]); + } sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms); for (ii=0; iisupported_algos[ii].reference; ii++) { sc_format_asn1_entry(asn1_algo_infos[ii] + 0, &ti->supported_algos[ii].reference, &reference_len, 1); sc_format_asn1_entry(asn1_algo_infos[ii] + 1, &ti->supported_algos[ii].mechanism, &mechanism_len, 1); - sc_format_asn1_entry(asn1_algo_infos[ii] + 2, NULL, NULL, 0); + sc_format_asn1_entry(asn1_algo_infos[ii] + 2, + asn1_algo_infos_parameters[ii], NULL, 0); + sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0, + NULL, NULL, 0); + sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 1, + &ti->supported_algos[ii].parameters, ¶meter_len, 0); sc_format_asn1_entry(asn1_algo_infos[ii] + 3, &ti->supported_algos[ii].operations, &operations_len, 1); sc_format_asn1_entry(asn1_algo_infos[ii] + 4, &ti->supported_algos[ii].algo_id, NULL, 1); sc_format_asn1_entry(asn1_algo_infos[ii] + 5, &ti->supported_algos[ii].algo_ref, &algo_ref_len, 1); From eeeefecf122e9a81ddc82ab3ec716953d2b1c387 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 22 Aug 2017 10:51:18 +0200 Subject: [PATCH 19/36] Add newly reported ATR for CardOS 5.3 --- src/libopensc/card-cardos.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index bbdb814e..07719173 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -59,6 +59,7 @@ static struct sc_atr_table cardos_atrs[] = { /* CardOS v5.0 */ { "3b:d2:18:00:81:31:fe:58:c9:01:14", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, /* CardOS v5.3 */ + { "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, { "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL}, { NULL, NULL, NULL, 0, 0, NULL } }; From 789dd16320ed449e4f60842791fe71282bbb77f3 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 22 Aug 2017 14:10:02 +0200 Subject: [PATCH 20/36] List human-readable version in the cardos-tool --- src/tools/cardos-tool.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/cardos-tool.c b/src/tools/cardos-tool.c index c3c6406b..cccc76d3 100644 --- a/src/tools/cardos-tool.c +++ b/src/tools/cardos-tool.c @@ -188,6 +188,9 @@ static int cardos_info(void) printf(" (that's CardOS M4.4)\n"); } else if (apdu.resp[0] == 0xc9 && apdu.resp[1] == 0x01) { printf(" (that's CardOS V5.0)\n"); + } else if (apdu.resp[0] == 0xc9 && + (apdu.resp[1] == 0x02 || apdu.resp[1] == 0x03)) { + printf(" (that's CardOS V5.3)\n"); } else { printf(" (unknown Version)\n"); } From 5882df745a746783a759e11bdeb1d38b73f18ee7 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Thu, 31 Aug 2017 15:20:41 -0400 Subject: [PATCH 21/36] Use |, not ||, when decoding CAC key_reference This quiets two compiler warnings and is almost surely what was actually meant. However, I do not have a CAC card to test. --- src/libopensc/pkcs15-cac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c index fa76ec34..609d5fad 100644 --- a/src/libopensc/pkcs15-cac.c +++ b/src/libopensc/pkcs15-cac.c @@ -323,8 +323,8 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) prkey_info.path.len += 2; } pubkey_info.native = 1; - pubkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 || obj_info.id.value[1]; - prkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 || obj_info.id.value[1]; + pubkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1]; + prkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1]; prkey_info.native = 1; memcpy(cert_obj.label, obj_info.app_label, sizeof(obj_info.app_label)); From ab8a51a1ab61057c66482d4f225c49888ef24ac3 Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 1 Sep 2017 11:01:04 +0200 Subject: [PATCH 22/36] Fix wrong padding for GIDS admin authentication --- src/libopensc/card-gids.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libopensc/card-gids.c b/src/libopensc/card-gids.c index 923cf3bd..930dd051 100644 --- a/src/libopensc/card-gids.c +++ b/src/libopensc/card-gids.c @@ -1879,8 +1879,6 @@ static int gids_authenticate_admin(sc_card_t *card, u8* key) { u8 apduSetRandomResponse[256]; u8* randomR2 = apduSetRandomResponse+4; u8 apduSendReponse[40 + 4] = {0x7C,0x2A,0x82,0x28}; - // according to the specification, the z size (z1||z2) should be 14 bytes - // but because the buffer must be a multiple of the 3DES block size (8 bytes), 7 isn't working u8 z1[8]; u8 buffer[16+16+8]; u8* buffer2 = apduSendReponse + 4; @@ -1923,8 +1921,10 @@ static int gids_authenticate_admin(sc_card_t *card, u8* key) { SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_check_sw(card, apdu.sw1, apdu.sw2), "invalid return"); // compute the half size of the mutual authentication secret - r = RAND_bytes(z1, sizeof(z1)); + r = RAND_bytes(z1, 7); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "unable to set computer random"); + // set the padding + z1[7] = 0x80; // Encrypt R2||R1||Z1 memcpy(buffer, randomR2, 16); From 00535f0174698300ca39c431fe34b7a9f76e5ed8 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Thu, 31 Aug 2017 15:27:47 -0400 Subject: [PATCH 23/36] sc_pkcs15_get_bitstring_extension: int, not long long Use the ASN.1 decoder's SC_ASN1_BIT_FIELD decoder to properly decode into a machine word. As _bitstring_extension is used only for the OID 2.5.29.15 by all callers, which is at most 9 bits wide, this is a reasonable thing to do. --- src/libopensc/pkcs15-cac.c | 6 +++--- src/libopensc/pkcs15-cert.c | 4 ++-- src/libopensc/pkcs15-piv.c | 6 ++---- src/libopensc/pkcs15.h | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c index 609d5fad..fd463a9b 100644 --- a/src/libopensc/pkcs15-cac.c +++ b/src/libopensc/pkcs15-cac.c @@ -139,7 +139,7 @@ cac_alg_flags_from_algorithm(int algorithm) /* map a cert usage and algorithm to public and private key usages */ static int -cac_map_usage(unsigned long long cert_usage, int algorithm, unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, int allow_nonrepudiation) +cac_map_usage(unsigned int cert_usage, int algorithm, unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, int allow_nonrepudiation) { unsigned int pub_usage = 0, pr_usage = 0; unsigned int alg_flags = cac_alg_flags_from_algorithm(algorithm); @@ -184,7 +184,7 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) }; /* oid for key usage */ static const struct sc_object_id usage_type = {{ 2, 5, 29, 15, -1 }}; - unsigned long long usage; + unsigned int usage; /* @@ -401,7 +401,7 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) usage = 0xd9ULL; /* basic default usage */ } cac_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); - sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "cert %s: cert_usage=0x%llx, pub_usage=0x%x priv_usage=0x%x\n", + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", sc_dump_hex(cert_info.id.value, cert_info.id.len), usage, pubkey_info.usage, prkey_info.usage); if (cert_out->key->algorithm != SC_ALGORITHM_RSA) { diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index 5a607e16..b7b16bb7 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -310,13 +310,13 @@ sc_pkcs15_get_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert, int sc_pkcs15_get_bitstring_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert, const struct sc_object_id *type, - unsigned long long *value, int *is_critical) + unsigned int *value, int *is_critical) { int r; u8 *bit_string = NULL; size_t bit_string_len=0, val_len = sizeof(*value); struct sc_asn1_entry asn1_bit_string[] = { - { "bitString", SC_ASN1_BIT_STRING, SC_ASN1_TAG_BIT_STRING, 0, value, &val_len }, + { "bitString", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, value, &val_len }, { NULL, 0, 0, 0, NULL, NULL } }; diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index 6f3c9199..73fc2d48 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -104,7 +104,7 @@ typedef struct common_key_info_st { int pubkey_from_file; int key_alg; unsigned int pubkey_len; - unsigned long long cert_keyUsage; /* x509 key usage as defined in certificate */ + unsigned int cert_keyUsage; /* x509 key usage as defined in certificate */ int cert_keyUsage_present; /* 1 if keyUsage found in certificate */ int pub_usage; int priv_usage; @@ -795,13 +795,11 @@ static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) if (follows_nist_fascn == 0) { struct sc_object_id keyUsage_oid={{2,5,29,15,-1}}; - unsigned long long *value; int r = 0; - value = &ckis[i].cert_keyUsage; r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &keyUsage_oid, - value, NULL); + &ckis[i].cert_keyUsage, NULL); if ( r >= 0) ckis[i].cert_keyUsage_present = 1; /* TODO if no key usage, we could set all uses */ diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index 7d922c39..b6a2dd34 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -738,7 +738,7 @@ int sc_pkcs15_get_extension(struct sc_context *ctx, int sc_pkcs15_get_bitstring_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert, const struct sc_object_id *type, - unsigned long long *value, + unsigned int *value, int *is_critical); /* sc_pkcs15_create_cdf: Creates a new certificate DF on a card pointed * by . Information about the file, such as the file ID, is read From 2cf0a119f428585469c1ec2258aacc343c28c8ff Mon Sep 17 00:00:00 2001 From: Pavel Cherezov Date: Tue, 12 Sep 2017 16:08:22 +0300 Subject: [PATCH 24/36] sensitive flag added to generate key with CKA_SENSITIVE flag --- src/tools/pkcs11-tool.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 4240a0c3..73023b48 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -134,6 +134,7 @@ enum { OPT_KEY_USAGE_DECRYPT, OPT_KEY_USAGE_DERIVE, OPT_PRIVATE, + OPT_SENSITIVE, OPT_TEST_HOTPLUG, OPT_UNLOCK_PIN, OPT_PUK, @@ -204,6 +205,7 @@ static const struct option options[] = { { "moz-cert", 1, NULL, 'z' }, { "verbose", 0, NULL, 'v' }, { "private", 0, NULL, OPT_PRIVATE }, + { "sensitive", 0, NULL, OPT_SENSITIVE }, { "test-ec", 0, NULL, OPT_TEST_EC }, #ifndef _WIN32 { "test-fork", 0, NULL, OPT_TEST_FORK }, @@ -269,6 +271,7 @@ 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)", + "Set the CKA_SENSITIVE attribute (object is protected by HSM)", "Test EC (best used with the --login or --pin option)", #ifndef _WIN32 "Test forking and calling C_Initialize() in the child", @@ -308,6 +311,7 @@ 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_is_sensitive = 0; static int opt_test_hotplug = 0; static int opt_login_type = -1; static int opt_key_usage_sign = 0; @@ -808,6 +812,9 @@ int main(int argc, char * argv[]) case OPT_PRIVATE: opt_is_private = 1; break; + case OPT_SENSITIVE: + opt_is_sensitive = 1; + break; case OPT_TEST_HOTPLUG: opt_test_hotplug = 1; action_count++; @@ -1329,7 +1336,7 @@ static int login(CK_SESSION_HANDLE session, int login_type) pin_flags=info.flags & ( CKF_SO_PIN_COUNT_LOW | CKF_SO_PIN_FINAL_TRY | - CKF_SO_PIN_LOCKED | + CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED); if(pin_flags) printf("WARNING: %s\n",p11_token_info_flags(pin_flags)); @@ -1340,7 +1347,7 @@ static int login(CK_SESSION_HANDLE session, int login_type) pin_flags=info.flags & ( CKF_USER_PIN_COUNT_LOW | CKF_USER_PIN_FINAL_TRY | - CKF_USER_PIN_LOCKED | + CKF_USER_PIN_LOCKED | CKF_USER_PIN_TO_BE_CHANGED); if(pin_flags) printf("WARNING: %s\n",p11_token_info_flags(pin_flags)); @@ -2039,6 +2046,7 @@ gen_key(CK_SLOT_ID slot, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hSecretKey CK_MECHANISM mechanism = {CKM_AES_KEY_GEN, NULL_PTR, 0}; CK_OBJECT_CLASS secret_key_class = CKO_SECRET_KEY; CK_BBOOL _true = TRUE; + CK_BBOOL _false = FALSE; CK_KEY_TYPE key_type = CKK_AES; CK_ULONG key_length; CK_ATTRIBUTE keyTemplate[20] = { @@ -2113,6 +2121,15 @@ gen_key(CK_SLOT_ID slot, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hSecretKey util_fatal("Unknown key type %s", type); } + if (opt_is_sensitive != 0) { + FILL_ATTR(keyTemplate[n_attr], CKA_SENSITIVE, &_true, sizeof(_true)); + n_attr++; + } + else { + FILL_ATTR(keyTemplate[n_attr], CKA_SENSITIVE, &_false, sizeof(_false)); + n_attr++; + } + FILL_ATTR(keyTemplate[n_attr], CKA_ENCRYPT, &_true, sizeof(_true)); n_attr++; FILL_ATTR(keyTemplate[n_attr], CKA_DECRYPT, &_true, sizeof(_true)); From ecb1656b91ce8de8de095f1ab1d5097304c02420 Mon Sep 17 00:00:00 2001 From: Pavel Cherezov Date: Tue, 12 Sep 2017 16:08:22 +0300 Subject: [PATCH 25/36] sensitive flag added to generate key with CKA_SENSITIVE flag. pull request issues fix: replace spaces with tabs and fix description of the argument. --- src/tools/pkcs11-tool.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 73023b48..93927608 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -271,7 +271,7 @@ 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)", - "Set the CKA_SENSITIVE attribute (object is protected by HSM)", + "Set the CKA_SENSITIVE attribute (object cannot be revealed in plaintext)", "Test EC (best used with the --login or --pin option)", #ifndef _WIN32 "Test forking and calling C_Initialize() in the child", @@ -2121,14 +2121,14 @@ gen_key(CK_SLOT_ID slot, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hSecretKey util_fatal("Unknown key type %s", type); } - if (opt_is_sensitive != 0) { - FILL_ATTR(keyTemplate[n_attr], CKA_SENSITIVE, &_true, sizeof(_true)); - n_attr++; - } - else { - FILL_ATTR(keyTemplate[n_attr], CKA_SENSITIVE, &_false, sizeof(_false)); - n_attr++; - } + if (opt_is_sensitive != 0) { + FILL_ATTR(keyTemplate[n_attr], CKA_SENSITIVE, &_true, sizeof(_true)); + n_attr++; + } + else { + FILL_ATTR(keyTemplate[n_attr], CKA_SENSITIVE, &_false, sizeof(_false)); + n_attr++; + } FILL_ATTR(keyTemplate[n_attr], CKA_ENCRYPT, &_true, sizeof(_true)); n_attr++; From 0a8213f3d418cc54b94511bd876288622c19503e Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 13 Sep 2017 17:41:20 +0200 Subject: [PATCH 26/36] Do not overwrite digestinfo + hash for RSA-PKCS Signature --- src/tools/pkcs11-tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 93927608..e7bf1d59 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4338,14 +4338,14 @@ static int test_signature(CK_SESSION_HANDLE sess) break; case CKM_RSA_X_509: dataLen = modLenBytes; + pseudo_randomize(data, dataLen); break; default: dataLen = sizeof(data); /* let's hope it's OK */ + pseudo_randomize(data, dataLen); break; } - pseudo_randomize(data, dataLen); - if (firstMechType == CKM_RSA_X_509) { /* make sure our data is smaller than the modulus */ data[0] = 0x00; From 41b55b93d48491b9eddcb4df9b605b702334cb8f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 13 Sep 2017 17:42:28 +0200 Subject: [PATCH 27/36] Print well formated report from decryption stage and do not fail with OAEP mechanisms --- src/tools/pkcs11-tool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index e7bf1d59..ec681a2d 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -4864,7 +4864,7 @@ static int encrypt_decrypt(CK_SESSION_HANDLE session, return 0; if (EVP_PKEY_size(pkey) > (int)sizeof(encrypted)) { - fprintf(stderr, "Ciphertext buffer too small\n"); + printf("Ciphertext buffer too small\n"); EVP_PKEY_free(pkey); return 0; } @@ -4875,14 +4875,14 @@ static int encrypt_decrypt(CK_SESSION_HANDLE session, #endif EVP_PKEY_free(pkey); if (((int) encrypted_len) <= 0) { - fprintf(stderr, "Encryption failed, returning\n"); + printf("Encryption failed, returning\n"); return 0; } mech.mechanism = mech_type; rv = p11->C_DecryptInit(session, &mech, privKeyObject); - if (rv == CKR_MECHANISM_INVALID) { - fprintf(stderr, "Mechanism not supported\n"); + if (rv == CKR_MECHANISM_INVALID || rv == CKR_MECHANISM_PARAM_INVALID) { + printf("Mechanism not supported\n"); return 0; } if (rv != CKR_OK) From 8965ee38dde5a394e0c1264136324b2d855a1d69 Mon Sep 17 00:00:00 2001 From: vletoux Date: Fri, 15 Sep 2017 21:22:26 +0200 Subject: [PATCH 28/36] Gids verified mutual auth --- src/libopensc/card-gids.c | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/libopensc/card-gids.c b/src/libopensc/card-gids.c index 930dd051..a10de902 100644 --- a/src/libopensc/card-gids.c +++ b/src/libopensc/card-gids.c @@ -1884,6 +1884,8 @@ static int gids_authenticate_admin(sc_card_t *card, u8* key) { u8* buffer2 = apduSendReponse + 4; int buffer2size = 40; u8 apduSendResponseResponse[256]; + u8 buffer3[16+16+8]; + int buffer3size = 40; sc_apdu_t apdu; const EVP_CIPHER *cipher; @@ -1963,6 +1965,47 @@ static int gids_authenticate_admin(sc_card_t *card, u8* key) { r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_check_sw(card, apdu.sw1, apdu.sw2), "invalid return"); + + if (apdu.resplen != 44) + { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Expecting a response len of 44 - found %d",(int) apdu.resplen); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); + } + // init crypto + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); + } + if (!EVP_DecryptInit(ctx, cipher, key, NULL)) { + EVP_CIPHER_CTX_free(ctx); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); + } + EVP_CIPHER_CTX_set_padding(ctx,0); + if (!EVP_DecryptUpdate(ctx, buffer3, &buffer3size, apdu.resp + 4, apdu.resplen - 4)) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "unable to decrypt data"); + EVP_CIPHER_CTX_free(ctx); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_PIN_CODE_INCORRECT); + } + if(!EVP_DecryptFinal(ctx, buffer3+buffer3size, &buffer3size)) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "unable to decrypt final data"); + EVP_CIPHER_CTX_free(ctx); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_PIN_CODE_INCORRECT); + } + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "data has been decrypted using the key"); + if (memcmp(buffer3, randomR1, 16) != 0) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "R1 doesn't match"); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_PIN_CODE_INCORRECT); + } + if (memcmp(buffer3 + 16, randomR2, 16) != 0) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "R2 doesn't match"); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_PIN_CODE_INCORRECT); + } + if (buffer[39] != 0x80) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Padding not found"); + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_PIN_CODE_INCORRECT); + } + EVP_CIPHER_CTX_free(ctx); + ctx = NULL; SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); #endif From bdb1961dee1aa0e67eb23f474f9a5dcf7d4e316d Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 21 Sep 2017 11:19:22 +0200 Subject: [PATCH 29/36] Enable RSA-PSS signatures in pkcs11-tool (#1146) * Add missing SHA224 RSA algorithms * Fix wrong replacement in pkcs11-tool manual page * Add MGF and PSS_PARAMS definitions in PKCS#11 header file * Inspect PSS signature parameters in pkcs11-spy * Enable RSA-PSS signatures in pkcs11-tool * Added short names to RSA-PSS methods * Reintroduce portable NORETURN indication for functions and use it to avoid compilers complaining --- doc/tools/pkcs11-tool.1.xml | 32 ++++++- src/pkcs11/pkcs11-display.c | 9 ++ src/pkcs11/pkcs11-display.h | 1 + src/pkcs11/pkcs11-spy.c | 18 ++++ src/pkcs11/pkcs11.h | 24 +++++ src/tools/pkcs11-tool.c | 183 +++++++++++++++++++++++++++++++++++- src/tools/util.c | 5 +- src/tools/util.h | 17 +++- 8 files changed, 280 insertions(+), 9 deletions(-) diff --git a/doc/tools/pkcs11-tool.1.xml b/doc/tools/pkcs11-tool.1.xml index 471b9b4d..037c9551 100644 --- a/doc/tools/pkcs11-tool.1.xml +++ b/doc/tools/pkcs11-tool.1.xml @@ -71,6 +71,14 @@ Hash some data. + + + mechanism + + Specify hash algorithm used with + RSA-PKCS-PSS signature. Default is SHA-1. + + id, @@ -116,7 +124,7 @@ - specification + specification Specify the type and length of the key to create, for example rsa:1024 or EC:prime256v1. @@ -212,6 +220,17 @@ of mechanisms supported by your token. + + + function + + Use the specified Message Generation + Function (MGF) function + for RSA-PSS signatures. Supported arguments are MGF1-SHA1 + to MGF1-SHA512 if supported by the driver. + The default is based on the hash selection. + + mod @@ -309,6 +328,17 @@ Derive a secret key using another key and some data. + + + bytes + + Specify how many bytes of salt should + be used in RSA-PSS signatures. Accepts two special values: + "-1" means salt length equals to digest length, + "-2" means use maximum permissible length. + Default is digest length (-1). + + id diff --git a/src/pkcs11/pkcs11-display.c b/src/pkcs11/pkcs11-display.c index a05a7f93..753c05fa 100644 --- a/src/pkcs11/pkcs11-display.c +++ b/src/pkcs11/pkcs11-display.c @@ -521,6 +521,14 @@ static enum_specs ck_mec_s[] = { { CKM_VENDOR_DEFINED , "CKM_VENDOR_DEFINED " } }; +static enum_specs ck_mgf_s[] = { + { CKG_MGF1_SHA1 , "CKG_MGF1_SHA1 " }, + { CKG_MGF1_SHA224, "CKG_MGF1_SHA224" }, + { CKG_MGF1_SHA256, "CKG_MGF1_SHA256" }, + { CKG_MGF1_SHA384, "CKG_MGF1_SHA384" }, + { CKG_MGF1_SHA512, "CKG_MGF1_SHA512" }, +}; + static enum_specs ck_err_s[] = { { CKR_OK, "CKR_OK" }, { CKR_CANCEL, "CKR_CANCEL" }, @@ -630,6 +638,7 @@ enum_spec ck_types[] = { { KEY_T, ck_key_s, sizeof(ck_key_s) / SZ_SPECS, "CK_KEY_TYPE" }, { CRT_T, ck_crt_s, sizeof(ck_crt_s) / SZ_SPECS, "CK_CERTIFICATE_TYPE" }, { MEC_T, ck_mec_s, sizeof(ck_mec_s) / SZ_SPECS, "CK_MECHANISM_TYPE" }, + { MGF_T, ck_mgf_s, sizeof(ck_mgf_s) / SZ_SPECS, "CK_RSA_PKCS_MGF_TYPE"}, { USR_T, ck_usr_s, sizeof(ck_usr_s) / SZ_SPECS, "CK_USER_TYPE" }, { STA_T, ck_sta_s, sizeof(ck_sta_s) / SZ_SPECS, "CK_STATE" }, { RV_T, ck_err_s, sizeof(ck_err_s) / SZ_SPECS, "CK_RV" }, diff --git a/src/pkcs11/pkcs11-display.h b/src/pkcs11/pkcs11-display.h index 0f7bc5fb..9473ce9c 100644 --- a/src/pkcs11/pkcs11-display.h +++ b/src/pkcs11/pkcs11-display.h @@ -56,6 +56,7 @@ enum ck_type{ KEY_T, CRT_T, MEC_T, + MGF_T, USR_T, STA_T, RV_T diff --git a/src/pkcs11/pkcs11-spy.c b/src/pkcs11/pkcs11-spy.c index d0201772..8011f047 100644 --- a/src/pkcs11/pkcs11-spy.c +++ b/src/pkcs11/pkcs11-spy.c @@ -969,6 +969,24 @@ C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HA enter("C_SignInit"); spy_dump_ulong_in("hSession", hSession); fprintf(spy_output, "pMechanism->type=%s\n", lookup_enum(MEC_T, pMechanism->mechanism)); + switch (pMechanism->mechanism) { + case CKM_RSA_PKCS_PSS: + case CKM_SHA1_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: + if (pMechanism->pParameter != NULL) { + CK_RSA_PKCS_PSS_PARAMS *param = + (CK_RSA_PKCS_PSS_PARAMS *) pMechanism->pParameter; + fprintf(spy_output, "pMechanism->pParameter->hashAlg=%s\n", + lookup_enum(MEC_T, param->hashAlg)); + fprintf(spy_output, "pMechanism->pParameter->mgf=%s\n", + lookup_enum(MGF_T, param->mgf)); + fprintf(spy_output, "pMechanism->pParameter->sLen=%lu\n", + param->sLen); + } + break; + } spy_dump_ulong_in("hKey", hKey); rv = po->C_SignInit(hSession, pMechanism, hKey); return retne(rv); diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index 74b13c68..d24597b2 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -153,6 +153,8 @@ extern "C" { #define ck_mechanism_type_t CK_MECHANISM_TYPE +#define ck_rsa_pkcs_mgf_type_t CK_RSA_PKCS_MGF_TYPE + #define ck_mechanism _CK_MECHANISM #define parameter pParameter #define parameter_len ulParameterLen @@ -478,6 +480,8 @@ struct ck_date typedef unsigned long ck_mechanism_type_t; +typedef unsigned long int ck_rsa_pkcs_mgf_type_t; + #define CKM_RSA_PKCS_KEY_PAIR_GEN (0UL) #define CKM_RSA_PKCS (1UL) #define CKM_RSA_9796 (2UL) @@ -508,6 +512,8 @@ typedef unsigned long ck_mechanism_type_t; #define CKM_SHA256_RSA_PKCS_PSS (0x43UL) #define CKM_SHA384_RSA_PKCS_PSS (0x44UL) #define CKM_SHA512_RSA_PKCS_PSS (0x45UL) +#define CKM_SHA224_RSA_PKCS (0x46UL) +#define CKM_SHA224_RSA_PKCS_PSS (0x47UL) #define CKM_RC2_KEY_GEN (0x100UL) #define CKM_RC2_ECB (0x101UL) #define CKM_RC2_CBC (0x102UL) @@ -553,6 +559,9 @@ typedef unsigned long ck_mechanism_type_t; #define CKM_SHA256 (0x250UL) #define CKM_SHA256_HMAC (0x251UL) #define CKM_SHA256_HMAC_GENERAL (0x252UL) +#define CKM_SHA224 (0x255UL) +#define CKM_SHA224_HMAC (0x256UL) +#define CKM_SHA224_HMAC_GENERAL (0x257UL) #define CKM_SHA384 (0x260UL) #define CKM_SHA384_HMAC (0x261UL) #define CKM_SHA384_HMAC_GENERAL (0x262UL) @@ -755,6 +764,17 @@ typedef struct CK_ECDH1_DERIVE_PARAMS { unsigned char * pPublicData; } CK_ECDH1_DERIVE_PARAMS; +typedef struct CK_RSA_PKCS_PSS_PARAMS { + ck_mechanism_type_t hashAlg; + unsigned long mgf; + unsigned long sLen; +} CK_RSA_PKCS_PSS_PARAMS; + +#define CKG_MGF1_SHA1 (0x00000001UL) +#define CKG_MGF1_SHA224 (0x00000005UL) +#define CKG_MGF1_SHA256 (0x00000002UL) +#define CKG_MGF1_SHA384 (0x00000003UL) +#define CKG_MGF1_SHA512 (0x00000004UL) typedef unsigned long ck_rv_t; @@ -1292,6 +1312,8 @@ typedef struct ck_date *CK_DATE_PTR; typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; +typedef ck_rsa_pkcs_mgf_type_t *CK_RSA_PKCS_MGF_TYPE_PTR; + typedef struct ck_mechanism CK_MECHANISM; typedef struct ck_mechanism *CK_MECHANISM_PTR; @@ -1362,6 +1384,8 @@ typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; #undef ck_mechanism_type_t +#undef ck_rsa_pkcs_mgf_type_t + #undef ck_mechanism #undef parameter #undef parameter_len diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index ec681a2d..dfd6913d 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -147,6 +147,9 @@ enum { OPT_TEST_FORK, OPT_GENERATE_KEY, OPT_GENERATE_RANDOM, + OPT_HASH_ALGORITHM, + OPT_MGF, + OPT_SALT, }; static const struct option options[] = { @@ -163,6 +166,9 @@ static const struct option options[] = { { "derive", 0, NULL, OPT_DERIVE }, { "derive-pass-der", 0, NULL, OPT_DERIVE_PASS_DER }, { "mechanism", 1, NULL, 'm' }, + { "hash-algorithm", 1, NULL, OPT_HASH_ALGORITHM }, + { "mgf", 1, NULL, OPT_MGF }, + { "salt-len", 1, NULL, OPT_SALT }, { "login", 0, NULL, 'l' }, { "login-type", 1, NULL, OPT_LOGIN_TYPE }, @@ -229,6 +235,9 @@ static const char *option_help[] = { "Derive a secret key using another key and some data", "Derive ECDHpass DER encoded pubkey for compatibility with some PKCS#11 implementations", "Specify mechanism (use -M for a list of supported mechanisms)", + "Specify hash algorithm used with RSA-PKCS-PSS signature", + "Specify MGF (Message Generation Function) used for RSA-PSS signatures (possible values are MGF1-SHA1 to MGF1-SHA512)", + "Specify how many bytes should be used for salt in RSA-PSS signatures (default is digest size)", "Log into the token first", "Specify login type ('so', 'user', 'context-specific'; default:'user')", @@ -320,6 +329,10 @@ static int opt_key_usage_derive = 0; static int opt_key_usage_default = 1; /* uses defaults if no opt_key_usage options */ static int opt_derive_pass_der = 0; static unsigned long opt_random_bytes = 0; +static CK_MECHANISM_TYPE opt_hash_alg = 0; +static unsigned long opt_mgf = 0; +static long salt_len = 0; +static int salt_len_given = 0; /* 0 - not given, 1 - given with input parameters */ static void *module = NULL; static CK_FUNCTION_LIST_PTR p11 = NULL; @@ -410,6 +423,8 @@ static const char * p11_utf8_to_local(CK_UTF8CHAR *, size_t); static const char * p11_flag_names(struct flag_info *, CK_FLAGS); static const char * p11_mechanism_to_name(CK_MECHANISM_TYPE); static CK_MECHANISM_TYPE p11_name_to_mechanism(const char *); +static const char * p11_mgf_to_name(CK_RSA_PKCS_MGF_TYPE); +static CK_MECHANISM_TYPE p11_name_to_mgf(const char *); static void p11_perror(const char *, CK_RV); static const char * CKR2Str(CK_ULONG res); static int p11_test(CK_SESSION_HANDLE session); @@ -677,6 +692,16 @@ int main(int argc, char * argv[]) opt_mechanism_used = 1; opt_mechanism = p11_name_to_mechanism(optarg); break; + case OPT_HASH_ALGORITHM: + opt_hash_alg = p11_name_to_mechanism(optarg); + break; + case OPT_MGF: + opt_mgf = p11_name_to_mgf(optarg); + break; + case OPT_SALT: + salt_len = (CK_ULONG) strtoul(optarg, NULL, 0); + salt_len_given = 1; + break; case 'o': opt_output = optarg; break; @@ -1609,15 +1634,45 @@ static int unlock_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess, int login_type) return 0; } +/* return digest length in bytes */ +static unsigned long figure_pss_salt_length(const int hash) { + unsigned long sLen = 0; + switch (hash) { + case CKM_SHA_1: + sLen = 20; + break; + case CKM_SHA224: + sLen = 28; + break; + case CKM_SHA256: + sLen = 32; + break; + case CKM_SHA384: + sLen = 48; + break; + case CKM_SHA512: + sLen = 64; + break; + default: + util_fatal("Unknown hash algorithm '%s' for RSA-PSS signatures", + p11_mechanism_to_name(hash)); + break; + } + return sLen; +} + static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) { unsigned char in_buffer[1025], sig_buffer[512]; CK_MECHANISM mech; + CK_RSA_PKCS_PSS_PARAMS pss_params; CK_RV rv; CK_ULONG sig_len; int fd, r; + unsigned long hashlen = 0, modlen = 0; + if (!opt_mechanism_used) if (!find_mechanism(slot, CKF_SIGN|CKF_HW, NULL, 0, &opt_mechanism)) util_fatal("Sign mechanism not supported"); @@ -1625,6 +1680,93 @@ static void sign_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, fprintf(stderr, "Using signature algorithm %s\n", p11_mechanism_to_name(opt_mechanism)); memset(&mech, 0, sizeof(mech)); mech.mechanism = opt_mechanism; + pss_params.hashAlg = 0; + + if (opt_hash_alg != 0 && opt_mechanism != CKM_RSA_PKCS_PSS) + util_fatal("The hash-algorithm is applicable only to " + "RSA-PKCS-PSS mechanism"); + + /* set "default" MGF and hash algorithms. We can overwrite MGF later */ + switch (opt_mechanism) { + case CKM_RSA_PKCS_PSS: + pss_params.hashAlg = opt_hash_alg; + + switch (opt_hash_alg) { + case CKM_SHA256: + pss_params.mgf = CKG_MGF1_SHA256; + break; + case CKM_SHA384: + pss_params.mgf = CKG_MGF1_SHA384; + break; + case CKM_SHA512: + pss_params.mgf = CKG_MGF1_SHA512; + break; + default: + /* the PSS should use SHA-1 if not specified */ + pss_params.hashAlg = CKM_SHA_1; + /* fallthrough */ + case CKM_SHA_1: + pss_params.mgf = CKG_MGF1_SHA1; + } + break; + + case CKM_SHA1_RSA_PKCS_PSS: + pss_params.hashAlg = CKM_SHA_1; + pss_params.mgf = CKG_MGF1_SHA1; + break; + + case CKM_SHA256_RSA_PKCS_PSS: + pss_params.hashAlg = CKM_SHA256; + pss_params.mgf = CKG_MGF1_SHA256; + break; + + case CKM_SHA384_RSA_PKCS_PSS: + pss_params.hashAlg = CKM_SHA384; + pss_params.mgf = CKG_MGF1_SHA384; + break; + + case CKM_SHA512_RSA_PKCS_PSS: + pss_params.hashAlg = CKM_SHA512; + pss_params.mgf = CKG_MGF1_SHA512; + break; + } + + /* One of RSA-PSS mechanisms above: They need parameters */ + if (pss_params.hashAlg) { + if (opt_mgf != 0) + pss_params.mgf = opt_mgf; + + hashlen = figure_pss_salt_length(pss_params.hashAlg); + + if (salt_len_given == 1) { /* salt size explicitly given */ + if (salt_len < 0 && salt_len != -1 && salt_len != -2) + util_fatal("Salt length must be greater or equal \ +to zero, or equal to -1 (meaning: use digest size) or to -2 \ +(meaning: use maximum permissible size"); + + modlen = (get_private_key_length(session, key) + 7) / 8; + switch(salt_len) { + case -1: /* salt size equals to digest size */ + pss_params.sLen = hashlen; + break; + case -2: /* maximum permissible salt len */ + pss_params.sLen = modlen - hashlen -2; + break; + default: /* use given size but its value must be >= 0 */ + pss_params.sLen = salt_len; + break; + } /* end switch (salt_len_given) */ + } else { /* use default: salt len of digest size */ + pss_params.sLen = hashlen; + } + + mech.pParameter = &pss_params; + mech.ulParameterLen = sizeof(pss_params); + fprintf(stderr, "PSS parameters: hashAlg=%s, mgf=%s, salt=%lu B\n", + p11_mechanism_to_name(pss_params.hashAlg), + p11_mgf_to_name(pss_params.mgf), + pss_params.sLen); + } if (opt_input == NULL) fd = 0; @@ -5649,10 +5791,10 @@ static struct mech_info p11_mechanisms[] = { { CKM_RSA_X9_31, "RSA-X9-31", NULL }, { CKM_SHA1_RSA_X9_31, "SHA1-RSA-X9-31", NULL }, { CKM_RSA_PKCS_PSS, "RSA-PKCS-PSS", NULL }, - { CKM_SHA1_RSA_PKCS_PSS, "SHA1-RSA-PKCS-PSS", NULL }, - { CKM_SHA256_RSA_PKCS_PSS,"SHA256-RSA-PKCS-PSS", NULL }, - { CKM_SHA384_RSA_PKCS_PSS,"SHA384-RSA-PKCS-PSS", NULL }, - { CKM_SHA512_RSA_PKCS_PSS,"SHA512-RSA-PKCS-PSS", NULL }, + { CKM_SHA1_RSA_PKCS_PSS, "SHA1-RSA-PKCS-PSS", "rsa-pss-sha1" }, + { CKM_SHA256_RSA_PKCS_PSS,"SHA256-RSA-PKCS-PSS", "rsa-pss-sha256" }, + { CKM_SHA384_RSA_PKCS_PSS,"SHA384-RSA-PKCS-PSS", "rsa-pss-sha384" }, + { CKM_SHA512_RSA_PKCS_PSS,"SHA512-RSA-PKCS-PSS", "rsa-pss-sha512" }, { CKM_DSA_KEY_PAIR_GEN, "DSA-KEY-PAIR-GEN", NULL }, { CKM_DSA, "DSA", NULL }, { CKM_DSA_SHA1, "DSA-SHA1", NULL }, @@ -5829,6 +5971,15 @@ static struct mech_info p11_mechanisms[] = { { 0, NULL, NULL } }; +static struct mech_info p11_mgf[] = { + { CKG_MGF1_SHA1, "MGF1-SHA1", NULL }, + { CKG_MGF1_SHA224, "MGF1-SHA224", NULL }, + { CKG_MGF1_SHA256, "MGF1-SHA256", NULL }, + { CKG_MGF1_SHA384, "MGF1-SHA384", NULL }, + { CKG_MGF1_SHA512, "MGF1-SHA512", NULL }, + { 0, NULL, NULL } +}; + static const char *p11_mechanism_to_name(CK_MECHANISM_TYPE mech) { static char temp[64]; @@ -5855,6 +6006,30 @@ static CK_MECHANISM_TYPE p11_name_to_mechanism(const char *name) return 0; /* gcc food */ } +static CK_RSA_PKCS_MGF_TYPE p11_name_to_mgf(const char *name) +{ + struct mech_info *mi; + + for (mi = p11_mgf; mi->name; mi++) { + if (!strcasecmp(mi->name, name)) + return mi->mech; + } + util_fatal("Unknown PKCS11 MGF \"%s\"", name); +} + +static const char *p11_mgf_to_name(CK_RSA_PKCS_MGF_TYPE mgf) +{ + static char temp[64]; + struct mech_info *mi; + + for (mi = p11_mgf; mi->name; mi++) { + if (mi->mech == mgf) + return mi->name; + } + snprintf(temp, sizeof(temp), "mgf-0x%lX", (unsigned long) mgf); + return temp; +} + static const char * CKR2Str(CK_ULONG res) { switch (res) { diff --git a/src/tools/util.c b/src/tools/util.c index f5a03700..9c9f37c8 100644 --- a/src/tools/util.c +++ b/src/tools/util.c @@ -232,7 +232,8 @@ void util_hex_dump_asc(FILE *f, const u8 *in, size_t count, int addr) } } -void util_print_usage_and_die(const char *app_name, const struct option options[], +NORETURN void +util_print_usage_and_die(const char *app_name, const struct option options[], const char *option_help[], const char *args) { int i; @@ -343,7 +344,7 @@ const char * util_acl_to_str(const sc_acl_entry_t *e) return line; } -void +NORETURN void util_fatal(const char *fmt, ...) { va_list ap; diff --git a/src/tools/util.h b/src/tools/util.h index b9078087..d3a15570 100644 --- a/src/tools/util.h +++ b/src/tools/util.h @@ -23,15 +23,28 @@ extern "C" { #endif +#if _MSC_VER >= 1310 +/* MS Visual Studio 2003/.NET Framework 1.1 or newer */ +# define NORETURN _declspec( noreturn) +#elif __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ >= 5)) || (defined __clang__) +# define NORETURN __attribute__ ((noreturn)) +#elif __cplusplus >= 201103L +# define NORETURN [[noreturn]] +#elif __STDC_VERSION__ >= 201112L +# define NORETURN _Noreturn +#else +# define NORETURN +#endif + void util_print_binary(FILE *f, const u8 *buf, int count); void util_hex_dump(FILE *f, const u8 *in, int len, const char *sep); void util_hex_dump_asc(FILE *f, const u8 *in, size_t count, int addr); -void util_print_usage_and_die(const char *app_name, const struct option options[], +NORETURN void util_print_usage_and_die(const char *app_name, const struct option options[], const char *option_help[], const char *args); const char * util_acl_to_str(const struct sc_acl_entry *e); void util_warn(const char *fmt, ...); void util_error(const char *fmt, ...); -void util_fatal(const char *fmt, ...); +NORETURN void util_fatal(const char *fmt, ...); /* All singing all dancing card connect routine */ int util_connect_card_ex(struct sc_context *, struct sc_card **, const char *reader_id, int do_wait, int do_lock, int verbose); int util_connect_card(struct sc_context *, struct sc_card **, const char *reader_id, int do_wait, int verbose); From dfd18389346296f8e4617832e0d5f4171835620d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sun, 24 Sep 2017 22:14:19 +0200 Subject: [PATCH 30/36] fixed building without SM fixes https://github.com/OpenSC/OpenSC/issues/1155 --- src/libopensc/card-sc-hsm.c | 6 ++++++ src/libopensc/sm.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index ff9810c4..84f767b2 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -324,7 +324,9 @@ static int sc_hsm_soc_change(sc_card_t *card, struct sc_pin_cmd_data *data, r = sc_check_sw(card, apdu.sw1, apdu.sw2); LOG_TEST_GOTO_ERR(card->ctx, r, "Could not change PIN"); } else { +#ifdef ENABLE_SM unsigned sm_mode = card->sm_ctx.sm_mode; +#endif /* verify PIN */ sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 0x85); @@ -332,15 +334,19 @@ static int sc_hsm_soc_change(sc_card_t *card, struct sc_pin_cmd_data *data, r = sc_transmit_apdu(card, &apdu); LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); +#ifdef ENABLE_SM /* temporary disable SM, change reference data does not reach the applet */ card->sm_ctx.sm_mode = SM_MODE_NONE; +#endif /* change PIN */ sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x24, 0x01, 0x85); apdu.cla = 0x80; r = sc_transmit_apdu(card, &apdu); +#ifdef ENABLE_SM /* restore SM if possible */ card->sm_ctx.sm_mode = sm_mode; +#endif LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); r = sc_check_sw(card, apdu.sw1, apdu.sw2); LOG_TEST_GOTO_ERR(card->ctx, r, "Could not change PIN"); diff --git a/src/libopensc/sm.c b/src/libopensc/sm.c index a5f53de1..94f7ce7c 100644 --- a/src/libopensc/sm.c +++ b/src/libopensc/sm.c @@ -31,6 +31,7 @@ #include "asn1.h" #include "sm.h" +#ifdef ENABLE_SM static const struct sc_asn1_entry c_asn1_sm_response[4] = { { "encryptedData", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 7, SC_ASN1_OPTIONAL, NULL, NULL }, { "statusWord", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 0x19, 0, NULL, NULL }, @@ -38,7 +39,6 @@ static const struct sc_asn1_entry c_asn1_sm_response[4] = { { NULL, 0, 0, 0, NULL, NULL } }; -#ifdef ENABLE_SM int sc_sm_parse_answer(struct sc_card *card, unsigned char *resp_data, size_t resp_len, struct sm_card_response *out) From 4923947b0aa0ff744377486cebfb04829f7485f7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 16 Oct 2017 09:25:34 +0200 Subject: [PATCH 31/36] md: added CNS ATR (#1166) fixes https://github.com/OpenSC/OpenSC/issues/1153 --- win32/customactions.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/win32/customactions.cpp b/win32/customactions.cpp index f417d74b..3a3291c7 100644 --- a/win32/customactions.cpp +++ b/win32/customactions.cpp @@ -117,12 +117,14 @@ MD_REGISTRATION minidriver_registration[] = { /* from card-cardos.c */ {TEXT("CardOS 4.0"), {0x3b,0xe2,0x00,0xff,0xc1,0x10,0x31,0xfe,0x55,0xc8,0x02,0x9c}, 12, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("Italian eID card, postecert"), {0x3b,0xe9,0x00,0xff,0xc1,0x10,0x31,0xfe,0x55,0x00,0x64,0x05,0x00,0xc8,0x02,0x31,0x80,0x00,0x47}, + {TEXT("Italian CNS (a)"), {0x3b,0xe9,0x00,0xff,0xc1,0x10,0x31,0xfe,0x55,0x00,0x64,0x05,0x00,0xc8,0x02,0x31,0x80,0x00,0x47}, 19, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("Italian eID card, infocamere"), {0x3b,0xfb,0x98,0x00,0xff,0xc1,0x10,0x31,0xfe,0x55,0x00,0x64,0x05,0x20,0x47,0x03,0x31,0x80,0x00,0x90,0x00,0xf3}, + {TEXT("Italian CNS (b)"), {0x3b,0xfb,0x98,0x00,0xff,0xc1,0x10,0x31,0xfe,0x55,0x00,0x64,0x05,0x20,0x47,0x03,0x31,0x80,0x00,0x90,0x00,0xf3}, 22, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("Italian InfocamereCard"), {0x3b,0xfc,0x98,0x00,0xff,0xc1,0x10,0x31,0xfe,0x55,0xc8,0x03,0x49,0x6e,0x66,0x6f,0x63,0x61,0x6d,0x65,0x72,0x65,0x28}, + {TEXT("Italian CNS (c)"), {0x3b,0xfc,0x98,0x00,0xff,0xc1,0x10,0x31,0xfe,0x55,0xc8,0x03,0x49,0x6e,0x66,0x6f,0x63,0x61,0x6d,0x65,0x72,0x65,0x28}, 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("Italian CNS (d)"), {0x3b,0xff,0x18,0x00,0xff,0x81,0x31,0xfe,0x55,0x00,0x6b,0x02,0x09,0x03,0x03,0x01,0x01,0x01,0x43,0x4e,0x53,0x10,0x31,0x80,0x9d}, + 25, {0xff,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("CardOS 4.0 a"), {0x3b,0xf4,0x98,0x00,0xff,0xc1,0x10,0x31,0xfe,0x55,0x4d,0x34,0x63,0x76,0xb4}, 15, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, {TEXT("Cardos M4"), {0x3b,0xf2,0x18,0x00,0x02,0xc1,0x0a,0x31,0xfe,0x58,0xc8,0x08,0x74}, From a8126ad696d50d83cabf5771f73022ee9f783503 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 22 Sep 2017 13:52:19 -0500 Subject: [PATCH 32/36] Make OpenSC PKCS#11 Vendor Defined attributes, mechanisms etc unique This will help when p11-kit is usead and wil allow for additional CK*_* things to be defined that have a much better chance of being unique. OR in "OSC" to any CK*_VENDOR_DEFINED thing. with #define SC_VENDOR_DEFINED 0x4F534300 /* OSC */ This follows Netscapes convention of doing the same but using: #define NSSCK_VENDOR_NSS 0x4E534350 /* NSCP */ The current 2 defines CKA_* are for internal attributes. On branch OSC_VENDOR_DEFINED Changes to be committed: modified: pkcs11-opensc.h --- src/pkcs11/pkcs11-opensc.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/pkcs11/pkcs11-opensc.h b/src/pkcs11/pkcs11-opensc.h index 33beb6a3..6f0954dd 100644 --- a/src/pkcs11/pkcs11-opensc.h +++ b/src/pkcs11/pkcs11-opensc.h @@ -2,13 +2,22 @@ #define PKCS11_OPENSC_H /* OpenSC specific extensions */ +/* + * define OpenSC specific Vendor Defined extensions + * to make unique OpenSC flags, attribures, mechanisms, etc. + * + * Netscape used NSSCK_VENDOR_NSS 0x4E534350 "NSCP" + */ + +#define SC_VENDOR_DEFINED 0x4F534300 /* OSC */ + /* * In PKCS#11 there is no CKA_ attribute dedicated to the NON-REPUDIATION flag. * We need this flag in PKCS#15/libopensc to make dinstinction between * 'signature' and 'qualified signature' key slots. */ -#define CKA_OPENSC_NON_REPUDIATION (CKA_VENDOR_DEFINED | 1UL) +#define CKA_OPENSC_NON_REPUDIATION (CKA_VENDOR_DEFINED | SC_VENDOR_DEFINED | 1UL) -#define CKA_SPKI (CKA_VENDOR_DEFINED | 2UL) +#define CKA_SPKI (CKA_VENDOR_DEFINED | SC_VENDOR_DEFINED | 2UL) #endif From bd9cdd243d1c35da2e83be6792565c27c685f17d Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Fri, 16 Jun 2017 14:51:41 +0200 Subject: [PATCH 33/36] Add multiple PINs support to minidriver Many cards need multiple PINs to work correctly since different on-card keys are secured by different PINs (this is true for for example OpenPGP card). Smart Card Minidriver API has supported such cards since version 6.02 (Vista+). Use the same method as PKCS#11 driver does to discover user and sign PINs, for consistency. However, if there is a default container on card we'll make sure that its PIN is an user PIN and if there is no default container we'll mark the one with the user PIN as default. All other PINs securing containers on card are added as next PINs, up to MD_MAX_PINS. Use this opportunity to also fix two cases where a pointer-to-DWORD variable was passed as pointer-to-size_t parameter to md_dialog_perform_pin_operation() - they are of different size on Win64. Signed-off-by: Maciej S. Szmigiero --- src/minidriver/minidriver.c | 647 +++++++++++++++++++++++++--------- src/pkcs11/framework-pkcs15.c | 1 + 2 files changed, 482 insertions(+), 166 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 0e6ab786..ecec13e7 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -71,6 +71,13 @@ HINSTANCE g_inst; #define MD_MAX_KEY_CONTAINERS 12 #define MD_CARDID_SIZE 16 +#define MD_ROLE_USER_SIGN (ROLE_ADMIN + 1) +/* + * must be higher than MD_ROLE_USER_SIGN and + * less than or equal MAX_PINS + */ +#define MD_MAX_PINS MAX_PINS + #define MD_UTC_TIME_LENGTH_MAX 16 #define MD_CARDCF_LENGTH (sizeof(CARD_CACHE_FILE_FORMAT)) @@ -172,7 +179,7 @@ struct md_guid_conversion md_static_conversions[MD_MAX_CONVERSIONS] = {0}; typedef struct _VENDOR_SPECIFIC { - struct sc_pkcs15_object *obj_user_pin, *obj_sopin; + struct sc_pkcs15_object *pin_objs[MD_MAX_PINS]; struct sc_context *ctx; struct sc_reader *reader; @@ -335,6 +342,9 @@ static void loghex(PCARD_DATA pCardData, int level, PBYTE data, size_t len) * caller has changed the handles. * if so, then free up all previous card info * and reestablish + * + * FIXME: if this fails the context can be left + * in inconsistent state. */ static int check_reader_status(PCARD_DATA pCardData) @@ -385,7 +395,7 @@ static DWORD md_get_pin_by_role(PCARD_DATA pCardData, PIN_ID role, struct sc_pkcs15_object **ret_obj) { VENDOR_SPECIFIC *vs; - int rv = SC_SUCCESS; + int rv; if (!pCardData) return SCARD_E_INVALID_PARAMETER; @@ -394,43 +404,65 @@ md_get_pin_by_role(PCARD_DATA pCardData, PIN_ID role, struct sc_pkcs15_object ** if (!ret_obj) return SCARD_E_INVALID_PARAMETER; - *ret_obj = NULL; - - if (role == ROLE_USER) { - if (!vs->obj_user_pin) { - /* Get 'global' User PIN; if no, get the 'local' one */ - rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL, - SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, &vs->obj_user_pin); - if (rv) - rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL, - SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, &vs->obj_user_pin); - } - - *ret_obj = vs->obj_user_pin; + /* please keep me in sync with _get_auth_object_by_name() in pkcs11/framework-pkcs15.c */ + if (role == ROLE_USER) { + /* Get 'global' User PIN; if no, get the 'local' one */ + rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL, + SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj); + if (rv) + rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL, + SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj); } - else if (role == ROLE_ADMIN) { - /* Get SO PIN; if no, get the 'global' PUK; if no get the 'local' one */ - if (!vs->obj_sopin) { - rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_SOPIN, - SC_PKCS15_PIN_TYPE_FLAGS_SOPIN, NULL, &vs->obj_sopin); - if (rv) - rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PUK_GLOBAL, - SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, &vs->obj_sopin); - if (rv) - rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PUK_LOCAL, - SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, &vs->obj_sopin); - } + else if (role == MD_ROLE_USER_SIGN) { + int idx = 0; - *ret_obj = vs->obj_sopin; + /* Get the 'global' user PIN */ + rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL, + SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj); + if (!rv) { + /* Global (user) PIN exists, get the local one -- sign PIN */ + rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL, + SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj); + } + else { + /* No global PIN, try to get first local one -- user PIN */ + rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL, + SC_PKCS15_PIN_TYPE_FLAGS_MASK, &idx, ret_obj); + if (!rv) { + /* User PIN is local, try to get the second local -- sign PIN */ + idx++; + rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_LOCAL, + SC_PKCS15_PIN_TYPE_FLAGS_MASK, &idx, ret_obj); + } + } + } + else if (role == ROLE_ADMIN) { + /* Get SO PIN; if no, get the 'global' PUK; if no get the 'local' one */ + rv = sc_pkcs15_find_so_pin(vs->p15card, ret_obj); + if (rv) + rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PUK_GLOBAL, + SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj); + if (rv) + rv = sc_pkcs15_find_pin_by_flags(vs->p15card, SC_PKCS15_PIN_TYPE_FLAGS_PUK_LOCAL, + SC_PKCS15_PIN_TYPE_FLAGS_MASK, NULL, ret_obj); } else { - logprintf(pCardData, 2, "cannot get PIN object: unsupported role\n"); + logprintf(pCardData, 2, + "cannot get PIN object: unsupported role %u\n", + (unsigned int)role); return SCARD_E_UNSUPPORTED_FEATURE; } - return (rv == SC_SUCCESS) ? SCARD_S_SUCCESS : SCARD_E_UNSUPPORTED_FEATURE; -} + if (rv) + return SCARD_E_UNSUPPORTED_FEATURE; + if (*ret_obj) + logprintf(pCardData, 7, "Returning PIN '%.*s' for role %u\n", + (int) sizeof (*ret_obj)->label, (*ret_obj)->label, + (unsigned int)role); + + return SCARD_S_SUCCESS; +} static BOOL md_get_config_bool(PCARD_DATA pCardData, char *flag_name, unsigned flag, BOOL ret_default) @@ -1376,6 +1408,14 @@ md_fs_add_msroots(PCARD_DATA pCardData, struct md_file **head) static DWORD md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) { + typedef enum { SCF_NONE, + SCF_NONDEFAULT_SIGN_PIN, + SCF_NONDEFAULT_OTHER_PIN, + SCF_NONDEFAULT_USER_PIN, + SCF_DEFAULT_SIGN_PIN, + SCF_DEFAULT_OTHER_PIN, + SCF_DEFAULT_USER_PIN + } pin_mode_t; VENDOR_SPECIFIC *vs; PCONTAINER_MAP_RECORD p; unsigned char *cmap_buf = NULL; @@ -1384,12 +1424,33 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) int ii, rv, conts_num, found_default = 0; /* struct sc_pkcs15_data *data_object; */ struct sc_pkcs15_object *prkey_objs[MD_MAX_KEY_CONTAINERS]; + pin_mode_t pin_mode = SCF_NONE; + int pin_cont_idx = -1; if (!pCardData || !file) return SCARD_E_INVALID_PARAMETER; logprintf(pCardData, 2, "set 'cmapfile'\n"); vs = pCardData->pvVendorSpecific; + + dwret = md_get_pin_by_role(pCardData, ROLE_USER, &vs->pin_objs[ROLE_USER]); + if (dwret != SCARD_S_SUCCESS) { + logprintf(pCardData, 2, "Cannot get User PIN object"); + return dwret; + } + + dwret = md_get_pin_by_role(pCardData, MD_ROLE_USER_SIGN, &vs->pin_objs[MD_ROLE_USER_SIGN]); + if (dwret != SCARD_S_SUCCESS) { + logprintf(pCardData, 2, "Cannot get Sign PIN object -- ignored"); + vs->pin_objs[MD_ROLE_USER_SIGN] = NULL; + } + + dwret = md_get_pin_by_role(pCardData, ROLE_ADMIN, &vs->pin_objs[ROLE_ADMIN]); + if (dwret != SCARD_S_SUCCESS) { + logprintf(pCardData, 2, "Cannot get Admin PIN object -- ignored"); + vs->pin_objs[ROLE_ADMIN] = NULL; + } + cmap_len = MD_MAX_KEY_CONTAINERS*sizeof(CONTAINER_MAP_RECORD); cmap_buf = pCardData->pfnCspAlloc(cmap_len); if(!cmap_buf) @@ -1431,7 +1492,116 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) dwret = md_cont_flags_from_key(pCardData, key_obj, &cont->flags); if (dwret != SCARD_S_SUCCESS) return dwret; - if (cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER) + + logprintf(pCardData, 7, "Container[%i] is '%.*s' guid=%.*s\n", ii, + (int) sizeof key_obj->label, key_obj->label, + (int) sizeof cont->guid, cont->guid); + + if (cont->flags & CONTAINER_MAP_VALID_CONTAINER && + key_obj->auth_id.len > 0) { + struct sc_pkcs15_object *keypin_obj; + struct sc_pkcs15_auth_info *userpin_info = + (struct sc_pkcs15_auth_info *)vs->pin_objs[ROLE_USER]->data; + struct sc_pkcs15_auth_info *signpin_info = + vs->pin_objs[MD_ROLE_USER_SIGN] ? + (struct sc_pkcs15_auth_info *)vs->pin_objs[MD_ROLE_USER_SIGN]->data : + NULL; + struct sc_pkcs15_auth_info *adminpin_info = + vs->pin_objs[ROLE_ADMIN] ? + (struct sc_pkcs15_auth_info *)vs->pin_objs[ROLE_ADMIN]->data : + NULL; + + if (sc_pkcs15_find_pin_by_auth_id(vs->p15card, &key_obj->auth_id, &keypin_obj)) + logprintf(pCardData, 2, + "Container[%i] has an unknown auth id, might not work properly\n", + ii); + else { + size_t pinidx; + size_t pinidxempty = MD_MAX_PINS; + for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) { + struct sc_pkcs15_auth_info *pin_info; + + if (!vs->pin_objs[pinidx]) { + if (pinidxempty >= MD_MAX_PINS) + pinidxempty = pinidx; + + continue; + } + + pin_info = + (struct sc_pkcs15_auth_info *)vs->pin_objs[pinidx]->data; + + if (sc_pkcs15_compare_id(&key_obj->auth_id, + &pin_info->auth_id)) + break; + } + + if (pinidx >= MD_MAX_PINS) { + if (pinidxempty >= MD_MAX_PINS) + logprintf(pCardData, 2, + "no free slot for container[%i] auth id, might not work properly\n", + ii); + else + vs->pin_objs[pinidxempty] = keypin_obj; + } + + if (sc_pkcs15_compare_id(&key_obj->auth_id, &userpin_info->auth_id)) { + pin_mode_t pin_mode_n = + cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ? + SCF_DEFAULT_USER_PIN : SCF_NONDEFAULT_USER_PIN; + + logprintf(pCardData, 7, + "Container[%i]%s is secured by User PIN\n", + ii, + cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ? + " (default)" : ""); + + if (pin_mode < pin_mode_n) { + pin_mode = pin_mode_n; + pin_cont_idx = ii; + } + } else if (signpin_info != NULL && + sc_pkcs15_compare_id(&key_obj->auth_id, &signpin_info->auth_id)) { + pin_mode_t pin_mode_n = + cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ? + SCF_DEFAULT_SIGN_PIN : SCF_NONDEFAULT_SIGN_PIN; + + logprintf(pCardData, 7, + "Container[%i]%s is secured by Sign PIN\n", + ii, + cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ? + " (default)" : ""); + + if (pin_mode < pin_mode_n) { + pin_mode = pin_mode_n; + pin_cont_idx = ii; + } + } else if (adminpin_info != NULL && + sc_pkcs15_compare_id(&key_obj->auth_id, &adminpin_info->auth_id)) { + logprintf(pCardData, 2, + "Container[%i] is secured by Admin PIN, might not work properly\n", + ii); + } else { + pin_mode_t pin_mode_n = + cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ? + SCF_DEFAULT_OTHER_PIN : SCF_NONDEFAULT_OTHER_PIN; + + logprintf(pCardData, 7, + "Container[%i]%s is secured by other PIN\n", + ii, + cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER ? + " (default)" : ""); + + if (pin_mode < pin_mode_n) { + pin_mode = pin_mode_n; + pin_cont_idx = ii; + } + } + } + } + + if (cont->flags & CONTAINER_MAP_VALID_CONTAINER && + cont->flags & CONTAINER_MAP_DEFAULT_CONTAINER) found_default = 1; /* AT_KEYEXCHANGE is more general key usage, @@ -1455,7 +1625,6 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) cont->size_key_exchange = prkey_info->field_length; } - logprintf(pCardData, 7, "Container[%i]'s guid=%.*s\n", ii, (int) sizeof cont->guid, cont->guid); logprintf(pCardData, 7, "Container[%i]'s key-exchange:%"SC_FORMAT_LEN_SIZE_T"u, sign:%"SC_FORMAT_LEN_SIZE_T"u\n", ii, cont->size_key_exchange, cont->size_sign); @@ -1513,6 +1682,108 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) } } #endif + + /* if no default container was found promote the best one (PIN-wise) to default */ + if (!found_default && (pin_mode == SCF_NONDEFAULT_SIGN_PIN || + pin_mode == SCF_NONDEFAULT_OTHER_PIN || + pin_mode == SCF_NONDEFAULT_USER_PIN)) { + struct md_pkcs15_container *cont = + &vs->p15_containers[pin_cont_idx]; + cont->flags |= CONTAINER_MAP_DEFAULT_CONTAINER; + + found_default = 1; + + logprintf(pCardData, 7, + "Container[%i] promoted to default\n", + pin_cont_idx); + + if (pin_mode == SCF_NONDEFAULT_SIGN_PIN) + pin_mode = SCF_DEFAULT_SIGN_PIN; + else if (pin_mode == SCF_NONDEFAULT_OTHER_PIN) + pin_mode = SCF_DEFAULT_OTHER_PIN; + else + pin_mode = SCF_DEFAULT_USER_PIN; + } + + /* if all containers use non-user PINs we need to make the best container PIN the user (primary) one */ + if (pin_mode == SCF_NONDEFAULT_SIGN_PIN || + pin_mode == SCF_DEFAULT_SIGN_PIN || + pin_mode == SCF_NONDEFAULT_OTHER_PIN || + pin_mode == SCF_DEFAULT_OTHER_PIN) { + struct sc_pkcs15_object *user_pin_old = + vs->pin_objs[ROLE_USER]; + struct sc_pkcs15_object *user_pin_new = + NULL; + + if (pin_mode == SCF_NONDEFAULT_SIGN_PIN || + pin_mode == SCF_DEFAULT_SIGN_PIN) { + user_pin_new = vs->pin_objs[MD_ROLE_USER_SIGN]; + vs->pin_objs[MD_ROLE_USER_SIGN] = NULL; + + logprintf(pCardData, 7, + "Sign PIN%s promoted to user one\n", + pin_mode == SCF_DEFAULT_SIGN_PIN ? + " (from default container)" : ""); + } else { + struct sc_pkcs15_object *key_obj = + vs->p15_containers[pin_cont_idx].prkey_obj; + struct sc_pkcs15_object *keypin_obj; + + if (sc_pkcs15_find_pin_by_auth_id(vs->p15card, &key_obj->auth_id, &keypin_obj)) + logprintf(pCardData, 2, + "Cannot find container[%i] auth id again, might not work properly\n", + pin_cont_idx); + else { + size_t pinidx; + + logprintf(pCardData, 7, + "Container[%i]%s PIN will be made the user one\n", + pin_cont_idx, + pin_mode == SCF_DEFAULT_OTHER_PIN ? + " (default)" : ""); + + for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) { + struct sc_pkcs15_auth_info *pin_info; + + if (!vs->pin_objs[pinidx]) + continue; + + pin_info = + (struct sc_pkcs15_auth_info *)vs->pin_objs[pinidx]->data; + + if (sc_pkcs15_compare_id(&key_obj->auth_id, + &pin_info->auth_id)) { + vs->pin_objs[pinidx] = NULL; + break; + } + } + + user_pin_new = keypin_obj; + } + } + + if (user_pin_new) { + size_t pinidx; + + vs->pin_objs[ROLE_USER] = user_pin_new; + + for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) { + if (vs->pin_objs[pinidx]) + continue; + + vs->pin_objs[pinidx] = user_pin_old; + break; + } + + if (pinidx >= MD_MAX_PINS) { + logprintf(pCardData, 2, + "no free slot for previous User PIN, replacing last one\n"); + + vs->pin_objs[MD_MAX_PINS - 1] = user_pin_old; + } + } + } + /* Initialize 'CMAPFILE' content from the P15 containers */ p = (PCONTAINER_MAP_RECORD)cmap_buf; for (ii=0; iipvVendorSpecific); + + if (PinId >= MD_MAX_PINS || !vs->pin_objs[PinId]) + return SCARD_E_INVALID_PARAMETER; + card = vs->p15card->card; memset(&pub_args, 0, sizeof(pub_args)); @@ -1904,12 +2179,7 @@ md_pkcs15_generate_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, DWORD ke keygen_args.prkey_args.access_flags = MD_KEY_ACCESS; - dw = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj); - if (dw != SCARD_S_SUCCESS) { - logprintf(pCardData, 2, "MdGenerateKey(): cannot get User PIN object"); - return dw; - } - + pin_obj = vs->pin_objs[PinId]; auth_info = (struct sc_pkcs15_auth_info *) pin_obj->data; keygen_args.prkey_args.auth_id = pub_args.auth_id = auth_info->auth_id; @@ -1970,9 +2240,8 @@ done: return dwret; } - static DWORD -md_pkcs15_store_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, BYTE *blob, DWORD blob_size) +md_pkcs15_store_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, BYTE *blob, DWORD blob_size, PIN_ID PinId) { #if OPENSSL_VERSION_NUMBER >= 0x10000000L VENDOR_SPECIFIC *vs; @@ -1986,13 +2255,17 @@ md_pkcs15_store_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, BYTE *blob, BYTE *ptr = blob; EVP_PKEY *pkey=NULL; int rv; - DWORD dw, dwret = SCARD_F_INTERNAL_ERROR; + DWORD dwret = SCARD_F_INTERNAL_ERROR; CHAR szGuid[MAX_CONTAINER_NAME_LEN +1] = "Default key label"; if (!pCardData) return SCARD_E_INVALID_PARAMETER; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + + if (PinId >= MD_MAX_PINS || !vs->pin_objs[PinId]) + return SCARD_E_INVALID_PARAMETER; + card = vs->p15card->card; pkey = b2i_PrivateKey((const unsigned char **)&ptr, blob_size); @@ -2032,12 +2305,7 @@ md_pkcs15_store_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, BYTE *blob, prkey_args.access_flags = MD_KEY_ACCESS; - dw = md_get_pin_by_role(pCardData, ROLE_USER, &pin_obj); - if (dw != SCARD_S_SUCCESS) { - logprintf(pCardData, 2, "MdStoreKey(): cannot get User PIN object"); - return dw; - } - + pin_obj = vs->pin_objs[PinId]; prkey_args.auth_id = ((struct sc_pkcs15_auth_info *) pin_obj->data)->auth_id; rv = sc_lock(card); @@ -2628,26 +2896,40 @@ DWORD WINAPI CardDeleteContainer(__in PCARD_DATA pCardData, return SCARD_S_SUCCESS; } - -DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData, - __in BYTE bContainerIndex, - __in DWORD dwFlags, - __in DWORD dwKeySpec, - __in DWORD dwKeySize, - __in PBYTE pbKeyData) +/** 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) { DWORD dwret; if (!pCardData) return SCARD_E_INVALID_PARAMETER; + if (PinId == ROLE_ADMIN) + return SCARD_W_SECURITY_VIOLATION; + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, - "CardCreateContainerEx(idx:%u,flags:%lX,type:%lX,size:%lu,data:%p)\n", + "CardCreateContainerEx(idx:%u,flags:%lX,type:%lX,size:%lu,data:%p,pin:%u)\n", (unsigned int)bContainerIndex, (unsigned long)dwFlags, - (unsigned long)dwKeySpec, (unsigned long)dwKeySize, pbKeyData); + (unsigned long)dwKeySpec, (unsigned long)dwKeySize, pbKeyData, + (unsigned int)PinId); if (pbKeyData) { logprintf(pCardData, 7, "Key data\n"); @@ -2676,7 +2958,7 @@ DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData, } if (dwFlags & CARD_CREATE_CONTAINER_KEY_GEN) { - dwret = md_pkcs15_generate_key(pCardData, bContainerIndex, dwKeySpec, dwKeySize); + dwret = md_pkcs15_generate_key(pCardData, bContainerIndex, dwKeySpec, dwKeySize, PinId); if (dwret != SCARD_S_SUCCESS) { logprintf(pCardData, 1, "key generation failed\n"); return dwret; @@ -2684,7 +2966,7 @@ DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData, logprintf(pCardData, 1, "key generated\n"); } else if ((dwFlags & CARD_CREATE_CONTAINER_KEY_IMPORT) && (pbKeyData != NULL)) { - dwret = md_pkcs15_store_key(pCardData, bContainerIndex, dwKeySpec, pbKeyData, dwKeySize); + dwret = md_pkcs15_store_key(pCardData, bContainerIndex, dwKeySpec, pbKeyData, dwKeySize, PinId); if (dwret != SCARD_S_SUCCESS) { logprintf(pCardData, 1, "key store failed\n"); return dwret; @@ -2700,6 +2982,17 @@ DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData, return SCARD_S_SUCCESS; } +DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData, + __in BYTE bContainerIndex, + __in DWORD dwFlags, + __in DWORD dwKeySpec, + __in DWORD dwKeySize, + __in PBYTE pbKeyData) +{ + return CardCreateContainerEx(pCardData, bContainerIndex, dwFlags, + dwKeySpec, dwKeySize, pbKeyData, + ROLE_USER); +} typedef struct { PUBLICKEYSTRUC publickeystruc; @@ -4777,6 +5070,13 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if ((vs->p15card) == NULL) return SCARD_F_INTERNAL_ERROR; + if (PinId >= MD_MAX_PINS) + return SCARD_E_INVALID_PARAMETER; + + pin_obj = vs->pin_objs[PinId]; + if (!pin_obj) + return SCARD_E_INVALID_PARAMETER; + #if 0 /* TODO do we need to return SCARD_E_UNSUPPORTED_FEATURE if the card * doesn't support it or if the minidriver doesn't support it in general? @@ -4791,6 +5091,10 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if (dwFlags & ~(CARD_AUTHENTICATE_GENERATE_SESSION_PIN | CARD_AUTHENTICATE_SESSION_PIN | CARD_PIN_SILENT_CONTEXT)) return SCARD_E_INVALID_PARAMETER; + if (dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN && + (ppbSessionPin == NULL || pcbSessionPin == NULL)) + return SCARD_E_INVALID_PARAMETER; + /* using a pin pad */ if (NULL == pbPinData) { if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD @@ -4802,20 +5106,9 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, } } - if (PinId != ROLE_USER) - return SCARD_E_INVALID_PARAMETER; - if(pcAttemptsRemaining) (*pcAttemptsRemaining) = (DWORD) -1; - r = md_get_pin_by_role(pCardData, PinId, &pin_obj); - if (r != SCARD_S_SUCCESS) { - logprintf(pCardData, 2, "Cannot get User PIN object"); - return r; - } - - if (!pin_obj) - return SCARD_F_INTERNAL_ERROR; auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; /* save the pin type */ auth_method = auth_info->auth_method; @@ -4834,34 +5127,49 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, cbPinData = 0; } else { /* seems we have a real session pin, set the pin type accordingly */ - logprintf(pCardData, 2, "use real session pin with %d bytes", cbPinData); + logprintf(pCardData, 2, + "use real session pin with %lu bytes", + (unsigned long)cbPinData); auth_info->auth_method = SC_AC_SESSION; } } /* set the session pin according to the minidriver specification */ if (dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN) { + size_t session_pin_len = SC_MAX_PIN_SIZE; + logprintf(pCardData, 2, "generating session pin"); - if (ppbSessionPin) *ppbSessionPin = pCardData->pfnCspAlloc(SC_MAX_PIN_SIZE); - if (ppbSessionPin) *pcbSessionPin = SC_MAX_PIN_SIZE; - r = md_dialog_perform_pin_operation(pCardData, SC_PIN_CMD_GET_SESSION_PIN, vs->p15card, pin_obj, (const u8 *) pbPinData, cbPinData, - ppbSessionPin && *ppbSessionPin ? *ppbSessionPin : NULL, pcbSessionPin, DisplayPinpadUI); + *ppbSessionPin = pCardData->pfnCspAlloc(SC_MAX_PIN_SIZE); + r = md_dialog_perform_pin_operation(pCardData, + SC_PIN_CMD_GET_SESSION_PIN, + vs->p15card, pin_obj, + (const u8 *) pbPinData, + cbPinData, + *ppbSessionPin, + *ppbSessionPin != NULL ? + &session_pin_len : NULL, + DisplayPinpadUI); if (r) { - if (ppbSessionPin) { + if (*ppbSessionPin != NULL) { pCardData->pfnCspFree(*ppbSessionPin); *ppbSessionPin = NULL; } - if (pcbSessionPin) *pcbSessionPin = 0; + *pcbSessionPin = 0; logprintf(pCardData, 2, "generating session pin failed"); } else { - if (pcbSessionPin && *pcbSessionPin) { - logprintf(pCardData, 2, "generated session pin with %d bytes", *pcbSessionPin); + if (*ppbSessionPin != NULL && session_pin_len > 0) { + logprintf(pCardData, 2, + "generated session pin with %"SC_FORMAT_LEN_SIZE_T"u bytes", + session_pin_len); + + *pcbSessionPin = session_pin_len; } else { logprintf(pCardData, 2, "session pin not supported"); - if (ppbSessionPin) { + if (*ppbSessionPin != NULL) { pCardData->pfnCspFree(*ppbSessionPin); *ppbSessionPin = NULL; } + *pcbSessionPin = 0; } } } else { @@ -4891,16 +5199,16 @@ 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 - && pcbSessionPin && *pcbSessionPin == 0 + if (dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN + && *pcbSessionPin == 0 && (vs->reader->capabilities & SC_READER_CAP_PIN_PAD || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { /* If we could not generate a real session PIN, set it to a special * value for pinpad authentication to force a new pinpad authentication */ - *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)); + *ppbSessionPin = pCardData->pfnCspAlloc(sizeof(MAGIC_SESSION_PIN)); + if (*ppbSessionPin != NULL) { + memcpy(*ppbSessionPin, MAGIC_SESSION_PIN, sizeof(MAGIC_SESSION_PIN)); + *pcbSessionPin = sizeof(MAGIC_SESSION_PIN); } } @@ -4920,11 +5228,11 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, __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 = FALSE; + size_t target_len = cbTargetData; logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), @@ -4933,6 +5241,9 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, if (!pCardData) return SCARD_E_INVALID_PARAMETER; + + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!(dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && !(dwFlags & PIN_CHANGE_FLAG_CHANGEPIN)){ logprintf(pCardData, 1, "Unknown flag\n"); return SCARD_E_INVALID_PARAMETER; @@ -4941,12 +5252,11 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, 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) + if (dwAuthenticatingPinId >= MD_MAX_PINS || dwTargetPinId >= MD_MAX_PINS) return SCARD_E_INVALID_PARAMETER; - if (dwTargetPinId != ROLE_USER && dwTargetPinId != ROLE_ADMIN) { - logprintf(pCardData, 1, "Only ROLE_USER or ROLE_ADMIN is supported\n"); + if (!vs->pin_objs[dwAuthenticatingPinId] || !vs->pin_objs[dwTargetPinId]) return SCARD_E_INVALID_PARAMETER; - } + /* according to the spec: cRetryCount MUST be zero */ if (cRetryCount) return SCARD_E_INVALID_PARAMETER; @@ -4961,8 +5271,6 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, check_reader_status(pCardData); - vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { if (pbAuthenticatingPinData == NULL || cbAuthenticatingPinData == 0) { @@ -4983,20 +5291,22 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, } } - 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; + pin_obj = vs->pin_objs[dwTargetPinId]; if(pcAttemptsRemaining) (*pcAttemptsRemaining) = (DWORD) -1; - 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); - + /* FIXME: this does not enforce dwAuthenticatingPinId */ + 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, &target_len, + DisplayPinpadUI); + if (rv) { logprintf(pCardData, 2, "Failed to %s %s PIN: '%s' (%i)\n", (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN?"change":"unblock"), @@ -5091,7 +5401,34 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) return ERROR_INSUFFICIENT_BUFFER; - *p = ROLE_USER; + + if (cont->prkey_obj->auth_id.len == 0) + *p = ROLE_EVERYONE; + else { + size_t pinidx; + for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) { + struct sc_pkcs15_auth_info *pin_info; + + if (!vs->pin_objs[pinidx]) + continue; + + pin_info = + (struct sc_pkcs15_auth_info *)vs->pin_objs[pinidx]->data; + + if (sc_pkcs15_compare_id(&cont->prkey_obj->auth_id, + &pin_info->auth_id)) + break; + } + + if (pinidx >= MD_MAX_PINS) { + logprintf(pCardData, 2, + "Could not find container %i PIN, returning no PIN needed, might not work properly\n", + bContainerIndex); + *p = ROLE_EVERYONE; + } else + *p = (PIN_ID)pinidx; + } + logprintf(pCardData, 2, "Return Pin id %u\n", (unsigned int)*p); return SCARD_S_SUCCESS; @@ -5249,22 +5586,17 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (p->dwVersion != PIN_INFO_CURRENT_VERSION) return ERROR_REVISION_MISMATCH; + if (dwFlags >= MD_MAX_PINS) + return SCARD_E_INVALID_PARAMETER; + + if (!vs->pin_objs[dwFlags]) + return SCARD_E_INVALID_PARAMETER; + p->PinType = vs->reader->capabilities & SC_READER_CAP_PIN_PAD || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH ? ExternalPinType : AlphaNumericPinType; p->dwFlags = 0; switch (dwFlags) { - case ROLE_USER: - logprintf(pCardData, 2, - "returning info on PIN ROLE_USER ( Auth ) [%lu]\n", - (unsigned long)dwFlags); - p->PinPurpose = DigitalSignaturePin; - p->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION; - p->PinCachePolicy.dwPinCachePolicyInfo = 0; - p->PinCachePolicy.PinCachePolicyType = PinCacheNormal; - p->dwChangePermission = CREATE_PIN_SET(ROLE_USER); - p->dwUnblockPermission = CREATE_PIN_SET(ROLE_ADMIN); - break; case ROLE_ADMIN: logprintf(pCardData, 2, "returning info on PIN ROLE_ADMIN ( Unblock ) [%lu]\n", @@ -5277,19 +5609,40 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, p->dwUnblockPermission = 0; break; default: - logprintf(pCardData, 0, - "Invalid Pin number %lu requested\n", + logprintf(pCardData, 2, + "returning info on normal PIN [%lu]\n", (unsigned long)dwFlags); - return SCARD_E_INVALID_PARAMETER; + + if (dwFlags == ROLE_USER) + p->PinPurpose = PrimaryCardPin; + else if (dwFlags == MD_ROLE_USER_SIGN) + p->PinPurpose = DigitalSignaturePin; + else + p->PinPurpose = AuthenticationPin; + + p->PinCachePolicy.dwVersion = PIN_CACHE_POLICY_CURRENT_VERSION; + p->PinCachePolicy.dwPinCachePolicyInfo = 0; + p->PinCachePolicy.PinCachePolicyType = PinCacheNormal; + p->dwChangePermission = CREATE_PIN_SET(dwFlags); + p->dwUnblockPermission = CREATE_PIN_SET(ROLE_ADMIN); + break; } } else if (wcscmp(CP_CARD_LIST_PINS,wszProperty) == 0) { PPIN_SET p = (PPIN_SET) pbData; + size_t pinidx; if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) return ERROR_INSUFFICIENT_BUFFER; - SET_PIN(*p, ROLE_USER); + + memset(p, 0, sizeof(*p)); + for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) { + if (!vs->pin_objs[pinidx]) + continue; + + SET_PIN(*p, (PIN_ID)pinidx); + } } else if (wcscmp(CP_CARD_AUTHENTICATED_STATE,wszProperty) == 0) { PPIN_SET p = (PPIN_SET) pbData; @@ -5304,8 +5657,12 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, else if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY,wszProperty) == 0) { DWORD *p = (DWORD *)pbData; - if (dwFlags != ROLE_USER) + if (dwFlags >= MD_MAX_PINS) return SCARD_E_INVALID_PARAMETER; + + if (!vs->pin_objs[dwFlags]) + return SCARD_E_INVALID_PARAMETER; + if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) @@ -5678,35 +6035,6 @@ DWORD WINAPI CardProcessEncryptedData( 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(__inout PCARD_DATA pCardData, __in DWORD dwFlags) { VENDOR_SPECIFIC *vs; @@ -5870,7 +6198,6 @@ DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags static int associate_card(PCARD_DATA pCardData) { VENDOR_SPECIFIC *vs; - DWORD dw; int r; logprintf(pCardData, 1, "associate_card\n"); @@ -5929,18 +6256,7 @@ static int associate_card(PCARD_DATA pCardData) return SCARD_E_UNKNOWN_CARD; } - dw = md_get_pin_by_role(pCardData, ROLE_USER, &vs->obj_user_pin); - if (dw != SCARD_S_SUCCESS) { - logprintf(pCardData, 2, "Cannot get User PIN object"); - return dw; - } - - dw = md_get_pin_by_role(pCardData, ROLE_USER, &vs->obj_sopin); - if (dw != SCARD_S_SUCCESS) - logprintf(pCardData, 2, "Cannot get ADMIN PIN object -- ignored"); - return SCARD_S_SUCCESS; - } static int disassociate_card(PCARD_DATA pCardData) @@ -5953,8 +6269,8 @@ static int disassociate_card(PCARD_DATA pCardData) vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - vs->obj_user_pin = NULL; - vs->obj_sopin = NULL; + memset(vs->pin_objs, 0, sizeof(vs->pin_objs)); + memset(vs->p15_containers, 0, sizeof(vs->p15_containers)); if(vs->p15card) { logprintf(pCardData, 6, "sc_pkcs15_unbind\n"); @@ -6024,4 +6340,3 @@ BOOL APIENTRY DllMain( HINSTANCE hinstDLL, #pragma managed(pop) #endif #endif - diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 8ded1125..37b2da7c 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1213,6 +1213,7 @@ _get_auth_object_by_name(struct sc_pkcs15_card *p15card, char *name) struct sc_pkcs15_object *out = NULL; int rv = SC_ERROR_OBJECT_NOT_FOUND; + /* please keep me in sync with md_get_pin_by_role() in minidriver */ if (!strcmp(name, "UserPIN")) { /* Try to get 'global' PIN; if no, get the 'local' one */ rv = sc_pkcs15_find_pin_by_flags(p15card, SC_PKCS15_PIN_TYPE_FLAGS_PIN_GLOBAL, From 294c232ca963c439a9fbdd15a5f75ef12b8d0ecd Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sat, 17 Jun 2017 19:33:37 +0200 Subject: [PATCH 34/36] Minidriver card reinitialization cleanup In minidriver before performing a card operation we currently check whether the supplied card handles have changed. If they did the card in reader might have been changed so we reinitialize it. However, in few places in reinitialization call path an error returned by some operation would leave the context in an inconsistent state. So let's walk through this path to make sure that functions there will exit cleanly if an error happens. Also, make sure that all card operations that actually do something have the necessary check call in the first place and also that they all consistently check whether VENDOR_SPECIFIC pointer is not NULL before dereferencing it. This is a cleanup part of "Keep track of card resets by other contexts in minidriver" (that is, it does not include the actual reset handling code introduced by that commit), simplified. Signed-off-by: Maciej S. Szmigiero --- src/minidriver/minidriver.c | 484 ++++++++++++++++++++++++++---------- 1 file changed, 358 insertions(+), 126 deletions(-) diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index ecec13e7..99b99408 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -179,6 +180,8 @@ struct md_guid_conversion md_static_conversions[MD_MAX_CONVERSIONS] = {0}; typedef struct _VENDOR_SPECIFIC { + BOOL initialized; + struct sc_pkcs15_object *pin_objs[MD_MAX_PINS]; struct sc_context *ctx; @@ -247,10 +250,11 @@ static const struct sc_asn1_entry c_asn1_md_container[C_ASN1_MD_CONTAINER_SIZE] static DWORD md_translate_OpenSC_to_Windows_error(int OpenSCerror, DWORD dwDefaulCode); -static int associate_card(PCARD_DATA pCardData); -static int disassociate_card(PCARD_DATA pCardData); +static DWORD associate_card(PCARD_DATA pCardData); +static void disassociate_card(PCARD_DATA pCardData); static DWORD md_pkcs15_delete_object(PCARD_DATA pCardData, struct sc_pkcs15_object *obj); static DWORD md_fs_init(PCARD_DATA pCardData); +static void md_fs_finalize(PCARD_DATA pCardData); #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf @@ -337,25 +341,91 @@ static void loghex(PCARD_DATA pCardData, int level, PBYTE data, size_t len) logprintf(pCardData, level, " %04X %s\n", a, line); } -/* - * check if the card has been removed, or the - * caller has changed the handles. - * if so, then free up all previous card info - * and reestablish - * - * FIXME: if this fails the context can be left - * in inconsistent state. - */ -static int -check_reader_status(PCARD_DATA pCardData) +static DWORD reinit_card(PCARD_DATA pCardData) +{ + VENDOR_SPECIFIC *vs; + DWORD r; + + if (!pCardData) + return SCARD_E_INVALID_PARAMETER; + + vs = (VENDOR_SPECIFIC *)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; + + logprintf(pCardData, 2, "trying to reinit card\n"); + + if (vs->initialized) { + disassociate_card(pCardData); + md_fs_finalize(pCardData); + } + + r = associate_card(pCardData); + if (r != SCARD_S_SUCCESS) + return r; + + r = md_fs_init(pCardData); + if (r != SCARD_S_SUCCESS) { + logprintf(pCardData, 1, + "reinit_card md_fs_init failed, r = 0x%lX\n", + (unsigned long)r); + disassociate_card(pCardData); + return r; + } + + return SCARD_S_SUCCESS; +} + +static DWORD reinit_card_for(PCARD_DATA pCardData, const char *name) +{ + DWORD r; + + r = reinit_card(pCardData); + if (r != SCARD_S_SUCCESS) + logprintf(pCardData, 1, + "%s was called, but unable to initialize card, r = %u\n", + name, (unsigned int)r); + + return r; +} + +static DWORD check_card_status(PCARD_DATA pCardData, const char *name) +{ + VENDOR_SPECIFIC *vs; + + if (!pCardData) + return SCARD_E_INVALID_PARAMETER; + + vs = (VENDOR_SPECIFIC *)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; + + if (vs->initialized) + return SCARD_S_SUCCESS; + + return reinit_card_for(pCardData, name); +} + +/* + * check if the card is OK, has been removed, or the + * caller has changed the handles. + * if so, then try to reinit card + */ +static DWORD +check_card_reader_status(PCARD_DATA pCardData, const char *name) { - int r = SCARD_S_SUCCESS; VENDOR_SPECIFIC *vs = NULL; + DWORD dwRet; + int r; logprintf(pCardData, 4, "check_reader_status\n"); if(!pCardData) return SCARD_E_INVALID_PARAMETER; + dwRet = check_card_status(pCardData, name); + if (dwRet != SCARD_S_SUCCESS) + return dwRet; + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if(!vs) return SCARD_E_INVALID_PARAMETER; @@ -368,27 +438,29 @@ check_reader_status(PCARD_DATA pCardData) logprintf(pCardData, 1, "HANDLES CHANGED from 0x%08X 0x%08X\n", (unsigned int)vs->hSCardCtx, (unsigned int)vs->hScard); - - /* 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 */ - 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); - logprintf(pCardData, 1, "md_fs_init r = 0x%08X\n", r); - } - else if (vs->reader) { - /* This should always work, as BaseCSP should be checking for removal too */ - r = sc_detect_card_presence(vs->reader); - logprintf(pCardData, 2, - "check_reader_status r=%d flags 0x%08X\n", r, - (unsigned int)vs->reader->flags); + return reinit_card_for(pCardData, name); } - return r; + /* This should always work, as BaseCSP should be checking for removal too */ + r = sc_detect_card_presence(vs->reader); + logprintf(pCardData, 2, + "check_reader_status r=%d flags 0x%08X\n", r, + (unsigned int)vs->reader->flags); + if (r < 0) + return md_translate_OpenSC_to_Windows_error(r, + SCARD_F_INTERNAL_ERROR); + + if (!(r & SC_READER_CARD_PRESENT)) { + /* + * if there is really no card present it may not make sense to + * try initializing the card but since it won't hurt let's try + * it anyway for completeness + */ + logprintf(pCardData, 1, "no card present? trying to reinit\n"); + return reinit_card_for(pCardData, name); + } + + return SCARD_S_SUCCESS; } static DWORD @@ -481,6 +553,9 @@ md_get_config_bool(PCARD_DATA pCardData, char *flag_name, unsigned flag, BOOL re } vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific; + if (!vs) + return ret; + if (vs->ctx && vs->reader) { struct sc_atr atr; scconf_block *atrblock; @@ -581,6 +656,9 @@ md_contguid_get_guid_from_card(PCARD_DATA pCardData, struct sc_pkcs15_object *pr size_t guid_len = MAX_CONTAINER_NAME_LEN+1; vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; + rv = sc_pkcs15_get_object_guid(vs->p15card, prkey, 1, (unsigned char*) szGuid, &guid_len); if (rv) { logprintf(pCardData, 2, "md_contguid_get_guid_from_card(): error %d\n", rv); @@ -683,6 +761,9 @@ md_cont_flags_from_key(PCARD_DATA pCardData, struct sc_pkcs15_object *key_obj, u int rv; vs = (VENDOR_SPECIFIC*) pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; + prkey_info = (struct sc_pkcs15_prkey_info *)key_obj->data; *cont_flags = CONTAINER_MAP_VALID_CONTAINER; @@ -710,6 +791,9 @@ md_fs_find_directory(PCARD_DATA pCardData, struct md_directory *parent, char *na return SCARD_E_INVALID_PARAMETER; vs = pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; + if (!parent) parent = &vs->root; @@ -889,6 +973,8 @@ md_fs_delete_file(PCARD_DATA pCardData, char *parent, char *name) return SCARD_E_INVALID_PARAMETER; vs = pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; dwret = md_fs_find_directory(pCardData, NULL, parent, &dir); if (dwret != SCARD_S_SUCCESS) { @@ -949,7 +1035,7 @@ md_fs_delete_file(PCARD_DATA pCardData, char *parent, char *name) return dwret; } -static DWORD +static void md_fs_finalize(PCARD_DATA pCardData) { VENDOR_SPECIFIC *vs; @@ -957,9 +1043,11 @@ md_fs_finalize(PCARD_DATA pCardData) struct md_directory *dir = NULL, *dir_to_rm; if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + return; vs = pCardData->pvVendorSpecific; + if (!vs) + return; file = vs->root.files; while (file != NULL) { @@ -967,6 +1055,7 @@ md_fs_finalize(PCARD_DATA pCardData) file = file->next; md_fs_free_file(pCardData, file_to_rm); } + vs->root.files = NULL; dir = vs->root.subdirs; while(dir) { @@ -980,7 +1069,7 @@ md_fs_finalize(PCARD_DATA pCardData) dir = dir->next; pCardData->pfnCspFree(dir_to_rm); } - return 0; + vs->root.subdirs = NULL; } /* @@ -998,6 +1087,8 @@ md_pkcs15_update_containers(PCARD_DATA pCardData, unsigned char *blob, size_t si return SCARD_E_INVALID_PARAMETER; vs = pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; nn_records = (int) size/sizeof(CONTAINER_MAP_RECORD); if (nn_records > MD_MAX_KEY_CONTAINERS) @@ -1044,6 +1135,9 @@ md_pkcs15_delete_object(PCARD_DATA pCardData, struct sc_pkcs15_object *obj) if (!pCardData) return SCARD_E_INVALID_PARAMETER; vs = pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; + card = vs->p15card->card; if (!obj) @@ -1124,6 +1218,9 @@ md_set_cardid(PCARD_DATA pCardData, struct md_file *file) return SCARD_E_INVALID_PARAMETER; vs = pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; + if (vs->p15card->tokeninfo && vs->p15card->tokeninfo->serial_number) { unsigned char sn_bin[SC_MAX_SERIALNR]; unsigned char cardid_bin[MD_CARDID_SIZE]; @@ -1375,6 +1472,8 @@ md_fs_add_msroots(PCARD_DATA pCardData, struct md_file **head) return SCARD_E_INVALID_PARAMETER; vs = (VENDOR_SPECIFIC *) pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; rv = sc_pkcs15_get_objects(vs->p15card, SC_PKCS15_TYPE_CERT_X509, prkey_objs, MD_MAX_KEY_CONTAINERS); if (rv < 0) { @@ -1432,6 +1531,8 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) logprintf(pCardData, 2, "set 'cmapfile'\n"); vs = pCardData->pvVendorSpecific; + if (!vs) + return SCARD_E_INVALID_PARAMETER; dwret = md_get_pin_by_role(pCardData, ROLE_USER, &vs->pin_objs[ROLE_USER]); if (dwret != SCARD_S_SUCCESS) { @@ -1860,32 +1961,32 @@ md_fs_init(PCARD_DATA pCardData) return dwret; dwret = md_set_cardid(pCardData, cardid); if (dwret != SCARD_S_SUCCESS) - return dwret; + goto ret_cleanup; dwret = md_fs_add_file(pCardData, &(vs->root.files), "cardcf", EveryoneReadUserWriteAc, NULL, 0, &cardcf); if (dwret != SCARD_S_SUCCESS) - return dwret; + goto ret_cleanup; dwret = md_set_cardcf(pCardData, cardcf); if (dwret != SCARD_S_SUCCESS) - return dwret; + goto ret_cleanup; dwret = md_fs_add_file(pCardData, &(vs->root.files), "cardapps", EveryoneReadAdminWriteAc, NULL, 0, &cardapps); if (dwret != SCARD_S_SUCCESS) - return dwret; + goto ret_cleanup; dwret = md_set_cardapps(pCardData, cardapps); if (dwret != SCARD_S_SUCCESS) - return dwret; + goto ret_cleanup; dwret = md_fs_add_directory(pCardData, &(vs->root.subdirs), "mscp", UserCreateDeleteDirAc, &mscp); if (dwret != SCARD_S_SUCCESS) - return dwret; + goto ret_cleanup; dwret = md_fs_add_file(pCardData, &(mscp->files), "cmapfile", EveryoneReadUserWriteAc, NULL, 0, &cmapfile); if (dwret != SCARD_S_SUCCESS) - return dwret; + goto ret_cleanup; dwret = md_set_cmapfile(pCardData, cmapfile); if (dwret != SCARD_S_SUCCESS) - return dwret; + goto ret_cleanup; #ifdef OPENSSL_VERSION_NUMBER logprintf(pCardData, 3, @@ -1896,6 +1997,10 @@ md_fs_init(PCARD_DATA pCardData) "MD virtual file system initialized; Without OPENSSL\n"); #endif return SCARD_S_SUCCESS; + +ret_cleanup: + md_fs_finalize(pCardData); + return dwret; } /* Create SC context */ @@ -1955,6 +2060,8 @@ md_free_space(PCARD_DATA pCardData, PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo) return ERROR_REVISION_MISMATCH; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; /* Count free containers */ for (idx=0, count=0; idxpvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; if (flags & CARD_CREATE_CONTAINER_KEY_IMPORT) { if (key_algo == SC_ALGORITHM_RSA) { @@ -2123,6 +2232,8 @@ md_pkcs15_generate_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, DWORD ke return SCARD_E_INVALID_PARAMETER; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; if (PinId >= MD_MAX_PINS || !vs->pin_objs[PinId]) return SCARD_E_INVALID_PARAMETER; @@ -2262,6 +2373,8 @@ md_pkcs15_store_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, BYTE *blob, return SCARD_E_INVALID_PARAMETER; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; if (PinId >= MD_MAX_PINS || !vs->pin_objs[PinId]) return SCARD_E_INVALID_PARAMETER; @@ -2398,6 +2511,9 @@ md_pkcs15_store_certificate(PCARD_DATA pCardData, char *file_name, unsigned char logprintf(pCardData, 1, "MdStoreCert(): store certificate '%s'\n", file_name); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; + card = vs->p15card->card; memset(&args, 0, sizeof(args)); @@ -2467,6 +2583,9 @@ md_query_key_sizes(PCARD_DATA pCardData, DWORD dwKeySpec, CARD_KEY_SIZES *pKeySi logprintf(pCardData, 1, "md_query_key_sizes: store dwKeySpec '%lu'\n", (unsigned long)dwKeySpec); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; + count = vs->p15card->card->algorithm_count; pKeySizes->dwVersion = CARD_KEY_SIZES_CURRENT_VERSION; @@ -2808,7 +2927,10 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) if(!vs) return SCARD_E_INVALID_PARAMETER; - disassociate_card(pCardData); + if (vs->initialized) { + disassociate_card(pCardData); + md_fs_finalize(pCardData); + } if(vs->ctx) { logprintf(pCardData, 6, "release context\n"); @@ -2819,7 +2941,6 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) logprintf(pCardData, 1, "**********************************************************************\n"); - md_fs_finalize(pCardData); pCardData->pfnCspFree(pCardData->pvVendorSpecific); pCardData->pvVendorSpecific = NULL; @@ -2839,11 +2960,13 @@ DWORD WINAPI CardQueryCapabilities(__in PCARD_DATA pCardData, if (!pCardData || !pCardCapabilities) return SCARD_E_INVALID_PARAMETER; - dwret = md_card_capabilities(pCardData, pCardCapabilities); + dwret = check_card_status(pCardData, "CardQueryCapabilities"); if (dwret != SCARD_S_SUCCESS) return dwret; - check_reader_status(pCardData); + dwret = md_card_capabilities(pCardData, pCardCapabilities); + if (dwret != SCARD_S_SUCCESS) + return dwret; return SCARD_S_SUCCESS; } @@ -2864,6 +2987,10 @@ DWORD WINAPI CardDeleteContainer(__in PCARD_DATA pCardData, if (!pCardData) return SCARD_E_INVALID_PARAMETER; + dwret = check_card_reader_status(pCardData, "CardDeleteContainer"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + if (bContainerIndex >= MD_MAX_KEY_CONTAINERS) return SCARD_E_INVALID_PARAMETER; @@ -2922,6 +3049,10 @@ DWORD WINAPI CardCreateContainerEx(__in PCARD_DATA pCardData, if (PinId == ROLE_ADMIN) return SCARD_W_SECURITY_VIOLATION; + dwret = check_card_reader_status(pCardData, "CardCreateContainerEx"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -3004,7 +3135,7 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine { VENDOR_SPECIFIC *vs = NULL; DWORD sz = 0; - DWORD ret = SCARD_F_UNKNOWN_ERROR; + DWORD ret; struct md_pkcs15_container *cont = NULL; struct sc_pkcs15_der pubkey_der; struct sc_pkcs15_prkey_info *prkey_info = NULL; @@ -3015,6 +3146,10 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine if (!pContainerInfo) return SCARD_E_INVALID_PARAMETER; + ret = check_card_reader_status(pCardData, "CardGetContainerInfo"); + if (ret != SCARD_S_SUCCESS) + return ret; + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -3035,6 +3170,9 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine pContainerInfo->dwVersion = CONTAINER_INFO_CURRENT_VERSION; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; + cont = &vs->p15_containers[bContainerIndex]; if (!cont->prkey_obj) { @@ -3043,13 +3181,9 @@ 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; - } - + ret = SCARD_F_UNKNOWN_ERROR; prkey_info = (struct sc_pkcs15_prkey_info *)cont->prkey_obj->data; - check_reader_status(pCardData); pubkey_der.value = NULL; pubkey_der.len = 0; @@ -3284,6 +3418,7 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, __out PDWORD pcbChallengeData) { VENDOR_SPECIFIC *vs; + DWORD dwret; int rv; logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", @@ -3296,9 +3431,13 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, if (!ppbChallengeData || !pcbChallengeData) return SCARD_E_INVALID_PARAMETER; - vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + dwret = check_card_reader_status(pCardData, "CardGetChallenge"); + if (dwret != SCARD_S_SUCCESS) + return dwret; - check_reader_status(pCardData); + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; *pcbChallengeData = 8; @@ -3446,14 +3585,12 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, cRetryCount, pcAttemptsRemaining); } -/* 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*/ +/* Note: the PIN freshness will be managed by the Base CSP */ DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData, __in LPWSTR pwszUserId, __in DWORD dwFlags) { + DWORD dwret; VENDOR_SPECIFIC* vs = NULL; int rv; logprintf(pCardData, 1, "\nP:%ld T:%ld pCardData:%p ", @@ -3465,7 +3602,13 @@ DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData, if(!pCardData) return SCARD_E_INVALID_PARAMETER; + dwret = check_card_reader_status(pCardData, "CardDeauthenticate"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; sc_pkcs15_pincache_clear(vs->p15card); @@ -3515,6 +3658,10 @@ DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData, NULLSTR(pszDirectoryName), NULLSTR(pszFileName), (unsigned long)cbInitialCreationSize, AccessCondition); + dwret = check_card_status(pCardData, "CardCreateFile"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + dwret = md_fs_find_directory(pCardData, NULL, pszDirectoryName, &dir); if (dwret != SCARD_S_SUCCESS) { logprintf(pCardData, 1, "CardCreateFile() cannot find parent directory '%s'", NULLSTR(pszDirectoryName)); @@ -3537,6 +3684,7 @@ DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData, __out PDWORD pcbData) { struct md_file *file = NULL; + DWORD dwret; logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), @@ -3556,7 +3704,9 @@ DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData, if (dwFlags) return SCARD_E_INVALID_PARAMETER; - check_reader_status(pCardData); + dwret = check_card_reader_status(pCardData, "CardReadFile"); + if (dwret != SCARD_S_SUCCESS) + return dwret; md_fs_find_file(pCardData, pszDirectoryName, pszFileName, &file); if (!file) { @@ -3607,7 +3757,9 @@ DWORD WINAPI CardWriteFile(__in PCARD_DATA pCardData, (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardWriteFile() dirName:'%s', fileName:'%s' \n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName)); - check_reader_status(pCardData); + dwret = check_card_reader_status(pCardData, "CardWriteFile"); + if (dwret != SCARD_S_SUCCESS) + return dwret; if (pbData && cbData) { logprintf(pCardData, 1, "CardWriteFile try to write (%lu):\n", @@ -3659,7 +3811,9 @@ DWORD WINAPI CardDeleteFile(__in PCARD_DATA pCardData, if(!pCardData) return SCARD_E_INVALID_PARAMETER; - check_reader_status(pCardData); + dwret = check_card_reader_status(pCardData, "CardDeleteFile"); + if (dwret != SCARD_S_SUCCESS) + return dwret; dwret = md_fs_delete_file(pCardData, pszDirectoryName, pszFileName); if (dwret != SCARD_S_SUCCESS) { @@ -3680,6 +3834,7 @@ DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData, __in DWORD dwFlags) { VENDOR_SPECIFIC *vs = NULL; + DWORD dwret; char mstr[0x100]; struct md_directory *dir = NULL; struct md_file *file = NULL; @@ -3701,7 +3856,13 @@ DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData, return SCARD_E_INVALID_PARAMETER; } + dwret = check_card_status(pCardData, "CardEnumFiles"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; memset(mstr, 0, sizeof(mstr)); @@ -3739,6 +3900,7 @@ DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData, __in LPSTR pszFileName, __inout PCARD_FILE_INFO pCardFileInfo) { + DWORD dwret; struct md_file *file = NULL; logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", @@ -3746,6 +3908,10 @@ DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData, (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetFileInfo(dirName:'%s',fileName:'%s', out %p)\n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName), pCardFileInfo); + dwret = check_card_status(pCardData, "CardGetFileInfo"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + md_fs_find_file(pCardData, pszDirectoryName, pszFileName, &file); if (!file) { logprintf(pCardData, 2, "CardWriteFile(): file '%s' not found in '%s'\n", NULLSTR(pszFileName), NULLSTR(pszDirectoryName)); @@ -3776,7 +3942,9 @@ DWORD WINAPI CardQueryFreeSpace(__in PCARD_DATA pCardData, __in DWORD dwFlags, if (!pCardData) return SCARD_E_INVALID_PARAMETER; - check_reader_status(pCardData); + dwret = check_card_status(pCardData, "CardQueryFreeSpace"); + if (dwret != SCARD_S_SUCCESS) + return dwret; dwret = md_free_space(pCardData, pCardFreeSpaceInfo); if (dwret != SCARD_S_SUCCESS) { @@ -3812,6 +3980,10 @@ DWORD WINAPI CardQueryKeySizes(__in PCARD_DATA pCardData, if ( dwKeySpec == 0 ) return SCARD_E_INVALID_PARAMETER; + dwret = check_card_status(pCardData, "CardQueryKeySizes"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + dwret = md_query_key_sizes(pCardData, dwKeySpec, pKeySizes); if (dwret != SCARD_S_SUCCESS) return dwret; @@ -3826,6 +3998,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, __inout PCARD_RSA_DECRYPT_INFO pInfo) { + DWORD dwret; int r, opt_crypt_flags = 0; unsigned ui; VENDOR_SPECIFIC *vs; @@ -3852,14 +4025,18 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, if (pInfo->dwKeySpec != AT_KEYEXCHANGE) return SCARD_E_INVALID_PARAMETER; + dwret = check_card_reader_status(pCardData, "CardRSADecrypt"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; /* 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=%lu, bContainerIndex=%u, dwKeySpec=%lu pbData=%p, cbData=%lu\n", (unsigned long)pInfo->dwVersion, @@ -4007,6 +4184,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO pInfo) { + DWORD dwret; VENDOR_SPECIFIC *vs; ALG_ID hashAlg; sc_pkcs15_prkey_info_t *prkey_info; @@ -4044,6 +4222,10 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO 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; + dwret = check_card_reader_status(pCardData, "CardSignData"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + logprintf(pCardData, 2, "CardSignData dwVersion=%lu, bContainerIndex=%u, dwKeySpec=%lu, dwSigningFlags=0x%08X, aiHashAlg=0x%08X\n", (unsigned long)pInfo->dwVersion, @@ -4059,6 +4241,9 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO hashAlg = pInfo->aiHashAlg; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; + if (pInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS) return SCARD_E_NO_KEY_CONTAINER; @@ -4067,8 +4252,6 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO return SCARD_E_NO_KEY_CONTAINER; prkey_info = (struct sc_pkcs15_prkey_info *)(pkey->data); - check_reader_status(pCardData); - logprintf(pCardData, 2, "pInfo->dwVersion = %lu\n", (unsigned long)pInfo->dwVersion); @@ -4264,6 +4447,7 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData, __inout PCARD_DH_AGREEMENT_INFO pAgreementInfo) { + DWORD dwret; VENDOR_SPECIFIC *vs; struct sc_pkcs15_object *pkey = NULL; int r, opt_derive_flags = 0; @@ -4292,14 +4476,18 @@ DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData, && pCardData->dwVersion == CARD_DATA_CURRENT_VERSION) return ERROR_REVISION_MISMATCH; + dwret = check_card_reader_status(pCardData, "CardConstructDHAgreement"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; /* check if the container exists */ if (pAgreementInfo->bContainerIndex >= MD_MAX_KEY_CONTAINERS) return SCARD_E_NO_KEY_CONTAINER; - check_reader_status(pCardData); - logprintf(pCardData, 2, "CardConstructDHAgreement dwVersion=%lu, dwKeySpec=%u pbData=%p, cbData=%lu\n", (unsigned long)pAgreementInfo->dwVersion, (unsigned int)pAgreementInfo->bContainerIndex, @@ -4835,6 +5023,8 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, return ERROR_REVISION_MISMATCH;*/ vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; /* check if the agreement index is ok */ if (pAgreementInfo->bSecretAgreementIndex >= vs->allocatedAgreements) { @@ -5005,6 +5195,8 @@ DWORD WINAPI CardDestroyDHAgreement( if (dwFlags) return SCARD_E_INVALID_PARAMETER; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; if (bSecretAgreementIndex >= vs->allocatedAgreements) { return SCARD_E_INVALID_PARAMETER; @@ -5043,6 +5235,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, __out_opt PDWORD pcbSessionPin, __out_opt PDWORD pcAttemptsRemaining) { + DWORD dwret; VENDOR_SPECIFIC *vs; struct sc_pkcs15_object *pin_obj = NULL; struct sc_pkcs15_auth_info *auth_info = NULL; @@ -5058,17 +5251,18 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if (!pCardData) return SCARD_E_INVALID_PARAMETER; + dwret = check_card_reader_status(pCardData, "CardAuthenticateEx"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + logprintf(pCardData, 2, "CardAuthenticateEx: PinId=%u, dwFlags=0x%08X, cbPinData=%lu, Attempts %s\n", (unsigned int)PinId, (unsigned int)dwFlags, (unsigned long)cbPinData, pcAttemptsRemaining ? "YES" : "NO"); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - - r = check_reader_status(pCardData); - - if ((vs->p15card) == NULL) - return SCARD_F_INTERNAL_ERROR; + if (!vs) + return SCARD_E_INVALID_PARAMETER; if (PinId >= MD_MAX_PINS) return SCARD_E_INVALID_PARAMETER; @@ -5227,6 +5421,7 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, __in DWORD cRetryCount, __out_opt PDWORD pcAttemptsRemaining) { + DWORD dwret; VENDOR_SPECIFIC *vs = NULL; struct sc_pkcs15_object *pin_obj = NULL; int rv; @@ -5242,7 +5437,13 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, if (!pCardData) return SCARD_E_INVALID_PARAMETER; + dwret = check_card_reader_status(pCardData, "CardChangeAuthenticatorEx"); + if (dwret != SCARD_S_SUCCESS) + return dwret; + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; if (!(dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && !(dwFlags & PIN_CHANGE_FLAG_CHANGEPIN)){ logprintf(pCardData, 1, "Unknown flag\n"); @@ -5268,9 +5469,6 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, (unsigned int)dwTargetPinId, (unsigned long)cbTargetData, pcAttemptsRemaining ? "YES" : "NO"); - - check_reader_status(pCardData); - if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { if (pbAuthenticatingPinData == NULL || cbAuthenticatingPinData == 0) { @@ -5350,6 +5548,7 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, __out PDWORD pdwDataLen, __in DWORD dwFlags) { + DWORD dwret; VENDOR_SPECIFIC *vs = NULL; struct md_pkcs15_container *cont = NULL; @@ -5358,9 +5557,13 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetContainerProperty\n"); - check_reader_status(pCardData); + if (!pCardData) + return SCARD_E_INVALID_PARAMETER; + + dwret = check_card_status(pCardData, "CardGetContainerProperty"); + if (dwret != SCARD_S_SUCCESS) + return dwret; - if (!pCardData) return SCARD_E_INVALID_PARAMETER; logprintf(pCardData, 2, "CardGetContainerProperty bContainerIndex=%u, wszProperty=%S, cbData=%lu, dwFlags=0x%08X\n", (unsigned int)bContainerIndex, NULLWSTR(wszProperty), @@ -5376,6 +5579,9 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, /* 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); + if (!vs) + return SCARD_E_INVALID_PARAMETER; + cont = &vs->p15_containers[bContainerIndex]; if (!cont->prkey_obj) { @@ -5475,9 +5681,13 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (!pbData || !pdwDataLen) return SCARD_E_INVALID_PARAMETER; - vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + dwret = check_card_reader_status(pCardData, "CardGetProperty"); + if (dwret != SCARD_S_SUCCESS) + return dwret; - check_reader_status(pCardData); + vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; if (wcscmp(CP_CARD_FREE_SPACE,wszProperty) == 0) { PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo = (PCARD_FREE_SPACE_INFO )pbData; @@ -5728,6 +5938,8 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, (unsigned long)dwFlags); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; if (!wszProperty) return SCARD_E_INVALID_PARAMETER; @@ -6042,7 +6254,7 @@ DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags if (!pCardData) return SCARD_E_INVALID_PARAMETER; - if (dwFlags) + if (dwFlags & ~CARD_SECURE_KEY_INJECTION_NO_CARD_MODE) return SCARD_E_INVALID_PARAMETER; if (!(dwFlags & CARD_SECURE_KEY_INJECTION_NO_CARD_MODE)) { if( pCardData->hSCardCtx == 0) { @@ -6109,11 +6321,8 @@ DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags (unsigned long)pCardData->dwVersion); dwret = md_create_context(pCardData, vs); - if (dwret != SCARD_S_SUCCESS) { - pCardData->pfnCspFree(pCardData->pvVendorSpecific); - pCardData->pvVendorSpecific = NULL; - return dwret; - } + if (dwret != SCARD_S_SUCCESS) + goto ret_free; md_static_data.flags &= ~MD_STATIC_FLAG_CONTEXT_DELETED; pCardData->pfnCardDeleteContext = CardDeleteContext; @@ -6144,18 +6353,12 @@ DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags pCardData->pfnCardConstructDHAgreement = CardConstructDHAgreement; dwret = associate_card(pCardData); - if (dwret != SCARD_S_SUCCESS) { - pCardData->pfnCspFree(pCardData->pvVendorSpecific); - pCardData->pvVendorSpecific = NULL; - return dwret; - } + if (dwret != SCARD_S_SUCCESS) + goto ret_release; dwret = md_fs_init(pCardData); - if (dwret != SCARD_S_SUCCESS) { - pCardData->pfnCspFree(pCardData->pvVendorSpecific); - pCardData->pvVendorSpecific = NULL; - return dwret; - } + if (dwret != SCARD_S_SUCCESS) + goto ret_disassoc; logprintf(pCardData, 1, "OpenSC init done.\n"); logprintf(pCardData, 1, "Supplied version %lu - version used %lu.\n", @@ -6193,18 +6396,35 @@ DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags } return SCARD_S_SUCCESS; + +ret_disassoc: + disassociate_card(pCardData); + +ret_release: + sc_release_context(vs->ctx); + md_static_data.flags |= MD_STATIC_FLAG_CONTEXT_DELETED; + +ret_free: + pCardData->pfnCspFree(pCardData->pvVendorSpecific); + pCardData->pvVendorSpecific = NULL; + return dwret; } -static int associate_card(PCARD_DATA pCardData) +static DWORD associate_card(PCARD_DATA pCardData) { VENDOR_SPECIFIC *vs; int r; + struct sc_app_info *app_generic; + struct sc_aid *aid; logprintf(pCardData, 1, "associate_card\n"); if (!pCardData) return SCARD_E_INVALID_PARAMETER; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) + return SCARD_E_INVALID_PARAMETER; + /* * set the addresses of the reader and card handles * Our pcsc code will use these when we call sc_ctx_use_reader @@ -6225,49 +6445,62 @@ static int associate_card(PCARD_DATA pCardData) } /* set the provided reader and card handles into ctx */ - logprintf(pCardData, 5, "sc_ctx_use_reader %d\n", sc_ctx_use_reader(vs->ctx, &vs->hSCardCtx, &vs->hScard)); + r = sc_ctx_use_reader(vs->ctx, &vs->hSCardCtx, &vs->hScard); + if (r != SC_SUCCESS) { + logprintf(pCardData, 0, "sc_ctx_use_reader() failed with %d\n", r); + return SCARD_E_COMM_DATA_LOST; + } /* should be only one reader */ logprintf(pCardData, 5, "sc_ctx_get_reader_count(ctx): %d\n", sc_ctx_get_reader_count(vs->ctx)); vs->reader = sc_ctx_get_reader(vs->ctx, 0); - if(vs->reader) { - struct sc_app_info *app_generic = NULL; - struct sc_aid *aid = NULL; + if (!vs->reader) + return SCARD_E_COMM_DATA_LOST; - r = sc_connect_card(vs->reader, &(vs->card)); - if(r) { - logprintf(pCardData, 0, "Cannot connect card in reader '%s'\n", NULLSTR(vs->reader->name)); - return SCARD_E_UNKNOWN_CARD; - } - logprintf(pCardData, 3, "Connected card in '%s'\n", NULLSTR(vs->reader->name)); - - app_generic = sc_pkcs15_get_application_by_type(vs->card, "generic"); - if (app_generic) - logprintf(pCardData, 3, "Use generic application '%s'\n", app_generic->label); - aid = app_generic ? &app_generic->aid : NULL; - - r = sc_pkcs15_bind(vs->card, aid, &(vs->p15card)); - logprintf(pCardData, 2, "PKCS#15 initialization result: %d, %s\n", r, sc_strerror(r)); - } - - if(vs->card == NULL || vs->p15card == NULL) { - logprintf(pCardData, 0, "Card unknown.\n"); + r = sc_connect_card(vs->reader, &(vs->card)); + if (r != SC_SUCCESS) { + logprintf(pCardData, 0, "Cannot connect card in reader '%s'\n", NULLSTR(vs->reader->name)); return SCARD_E_UNKNOWN_CARD; } + logprintf(pCardData, 3, "Connected card in '%s'\n", NULLSTR(vs->reader->name)); + + app_generic = sc_pkcs15_get_application_by_type(vs->card, "generic"); + if (app_generic) + logprintf(pCardData, 3, "Use generic application '%s'\n", app_generic->label); + aid = app_generic ? &app_generic->aid : NULL; + + r = sc_pkcs15_bind(vs->card, aid, &(vs->p15card)); + logprintf(pCardData, 2, "PKCS#15 initialization result: %d, %s\n", r, sc_strerror(r)); + if (r != SC_SUCCESS) { + logprintf(pCardData, 0, "PKCS#15 init failed.\n"); + sc_disconnect_card(vs->card); + return SCARD_E_UNKNOWN_CARD; + } + + vs->initialized = TRUE; return SCARD_S_SUCCESS; } -static int disassociate_card(PCARD_DATA pCardData) +static void disassociate_card(PCARD_DATA pCardData) { VENDOR_SPECIFIC *vs; + if (!pCardData) { + logprintf(pCardData, 1, + "disassociate_card called without card data\n"); + return; + } + logprintf(pCardData, 1, "disassociate_card\n"); - if (!pCardData) - return SCARD_E_INVALID_PARAMETER; vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); + if (!vs) { + logprintf(pCardData, 1, + "disassociate_card called without vendor specific data\n"); + return; + } memset(vs->pin_objs, 0, sizeof(vs->pin_objs)); memset(vs->p15_containers, 0, sizeof(vs->p15_containers)); @@ -6288,8 +6521,7 @@ static int disassociate_card(PCARD_DATA pCardData) vs->hSCardCtx = -1; vs->hScard = -1; - - return SCARD_S_SUCCESS; + vs->initialized = FALSE; } From 0cb654ca78d0a007489e3a1f59e4726152d310d7 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Sat, 17 Jun 2017 19:41:06 +0200 Subject: [PATCH 35/36] sc-hsm: fix unused variable warnings in sc_hsm_init() When building without OpenPACE there are two unused variables in sc_hsm_init() that cause compiler to emit warnings about them. Signed-off-by: Maciej S. Szmigiero --- src/libopensc/card-sc-hsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index 84f767b2..fc741924 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -1543,7 +1543,7 @@ static int sc_hsm_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) static int sc_hsm_init(struct sc_card *card) { -#ifdef _WIN32 +#if defined(ENABLE_OPENPACE) && defined(_WIN32) char expanded_val[PATH_MAX]; size_t expanded_len = PATH_MAX; #endif From 8d7346406d166a9db4afd239e6669df3e3b99f79 Mon Sep 17 00:00:00 2001 From: Feitian Technologies Date: Mon, 4 Sep 2017 19:29:24 +0800 Subject: [PATCH 36/36] Add ECC support and solve wrong Length status codes with SM card Fix #1073 Fix #1115 --- src/libopensc/card-epass2003.c | 171 ++++++++++++++++++++++++++---- src/libopensc/cardctl.h | 4 +- src/libopensc/sm.c | 2 +- src/pkcs15init/pkcs15-epass2003.c | 49 +++++++-- 4 files changed, 197 insertions(+), 29 deletions(-) diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c index 84ab6456..7feab598 100644 --- a/src/libopensc/card-epass2003.c +++ b/src/libopensc/card-epass2003.c @@ -98,6 +98,8 @@ typedef struct epass2003_exdata_st { unsigned char sk_enc[16]; /* encrypt session key */ unsigned char sk_mac[16]; /* mac session key */ unsigned char icv_mac[16]; /* instruction counter vector(for sm) */ + unsigned char currAlg; /* current Alg */ + unsigned int ecAlgFlags; /* Ec Alg mechanism type*/ } epass2003_exdata; #define REVERSE_ORDER4(x) ( \ @@ -170,6 +172,7 @@ static const struct sc_card_error epass2003_errors[] = { static int epass2003_transmit_apdu(struct sc_card *card, struct sc_apdu *apdu); static int epass2003_select_file(struct sc_card *card, const sc_path_t * in_path, sc_file_t ** file_out); int epass2003_refresh(struct sc_card *card); +static int hash_data(const unsigned char *data, size_t datalen, unsigned char *hash, unsigned int mechanismType); static int epass2003_check_sw(struct sc_card *card, unsigned int sw1, unsigned int sw2) @@ -403,6 +406,12 @@ sha1_digest(const unsigned char *input, size_t length, unsigned char *output) return openssl_dig(EVP_sha1(), input, length, output); } +static int +sha256_digest(const unsigned char *input, size_t length, unsigned char *output) +{ + return openssl_dig(EVP_sha256(), input, length, output); +} + static int gen_init_key(struct sc_card *card, unsigned char *key_enc, unsigned char *key_mac, @@ -1140,6 +1149,7 @@ static int epass2003_init(struct sc_card *card) { unsigned int flags; + unsigned int ext_flags; unsigned char data[SC_MAX_APDU_BUFFER_SIZE] = { 0 }; size_t datalen = SC_MAX_APDU_BUFFER_SIZE; epass2003_exdata *exdata = NULL; @@ -1192,6 +1202,11 @@ epass2003_init(struct sc_card *card) _sc_card_add_rsa_alg(card, 1024, flags, 0); _sc_card_add_rsa_alg(card, 2048, flags, 0); + //set EC Alg Flags + flags = SC_ALGORITHM_ONBOARD_KEY_GEN|SC_ALGORITHM_ECDSA_HASH_SHA1|SC_ALGORITHM_ECDSA_HASH_SHA256|SC_ALGORITHM_ECDSA_HASH_NONE|SC_ALGORITHM_ECDSA_RAW; + ext_flags = 0; + _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); + card->caps = SC_CARD_CAP_RNG | SC_CARD_CAP_APDU_EXT; LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); @@ -1561,6 +1576,13 @@ epass2003_set_security_env(struct sc_card *card, const sc_security_env_t * env, u8 *p; unsigned short fid = 0; int r, locked = 0; + epass2003_exdata *exdata = NULL; + + if (!card->drv_data) + return SC_ERROR_INVALID_ARGUMENTS; + + exdata = (epass2003_exdata *)card->drv_data; + exdata->currAlg = SC_ALGORITHM_RSA; //default algorithm sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0); switch (env->operation) { @@ -1590,6 +1612,28 @@ epass2003_set_security_env(struct sc_card *card, const sc_security_env_t * env, apdu.lc = r; apdu.datalen = r; apdu.data = sbuf; + + if (env->algorithm == SC_ALGORITHM_EC) + { + apdu.p2 = 0xB6; + exdata->currAlg = SC_ALGORITHM_EC; + if(env->algorithm_flags | SC_ALGORITHM_ECDSA_HASH_SHA1) + { + sbuf[2] = 0x91; + exdata->ecAlgFlags = SC_ALGORITHM_ECDSA_HASH_SHA1; + } + else if (env->algorithm_flags | SC_ALGORITHM_ECDSA_HASH_SHA256) + { + sbuf[2] = 0x92; + exdata->ecAlgFlags = SC_ALGORITHM_ECDSA_HASH_SHA256; + } + else + { + sc_log(card->ctx, "%0x Alg Not Support! ", env->algorithm_flags); + goto err; + } + } + if (se_num > 0) { r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); @@ -1640,7 +1684,55 @@ static int epass2003_decipher(struct sc_card *card, const u8 * data, size_t data struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE] = { 0 }; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE] = { 0 }; + epass2003_exdata *exdata = NULL; + + LOG_FUNC_CALLED(card->ctx); + + if (!card->drv_data) + return SC_ERROR_INVALID_ARGUMENTS; + + exdata = (epass2003_exdata *)card->drv_data; + if(exdata->currAlg == SC_ALGORITHM_EC) + { + unsigned char hash[HASH_LEN] = { 0 }; + if(exdata->ecAlgFlags | SC_ALGORITHM_ECDSA_HASH_SHA1) + { + hash_data(data, datalen, hash, SC_ALGORITHM_ECDSA_HASH_SHA1); + sc_format_apdu(card, &apdu, SC_APDU_CASE_3,0x2A, 0x9E, 0x9A); + memset(sbuf, 0, sizeof(sbuf)); + memcpy(sbuf, hash, 0x14); + apdu.data = sbuf; + apdu.lc = 0x14; + apdu.datalen = 0x14; + } + else if (exdata->ecAlgFlags | SC_ALGORITHM_ECDSA_HASH_SHA256) + { + hash_data(data, datalen, hash, SC_ALGORITHM_ECDSA_HASH_SHA256); + sc_format_apdu(card, &apdu, SC_APDU_CASE_3,0x2A, 0x9E, 0x9A); + memset(sbuf, 0, sizeof(sbuf)); + memcpy(sbuf, hash, 0x20); + apdu.data = sbuf; + apdu.lc = 0x20; + apdu.datalen = 0x20; + } + else + { + return SC_ERROR_NOT_SUPPORTED; + } + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + apdu.le = 0; + + r = sc_transmit_apdu_t(card, &apdu); + LOG_TEST_RET(card->ctx, 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); + LOG_FUNC_RETURN(card->ctx, len); + } + LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); + } sc_format_apdu(card, &apdu, SC_APDU_CASE_4_EXT, 0x2A, 0x80, 0x86); apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); @@ -1862,11 +1954,13 @@ epass2003_construct_fci(struct sc_card *card, const sc_file_t * file, } else if (file->type == SC_FILE_TYPE_INTERNAL_EF) { - if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT) { + if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT || + file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_CRT) { buf[0] = 0x11; buf[1] = 0x00; } - else if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC) { + else if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC || + file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC) { buf[0] = 0x12; buf[1] = 0x00; } @@ -1903,7 +1997,9 @@ epass2003_construct_fci(struct sc_card *card, const sc_file_t * file, } else if (file->type == SC_FILE_TYPE_INTERNAL_EF) { if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT || - file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC) { + file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC|| + file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_CRT|| + file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC) { buf[0] = (file->size >> 8) & 0xFF; buf[1] = file->size & 0xFF; sc_asn1_put_tag(0x85, buf, 2, p, *outlen - (p - out), &p); @@ -1942,13 +2038,14 @@ epass2003_construct_fci(struct sc_card *card, const sc_file_t * file, ops[3] = SC_AC_OP_DELETE; } else if (file->type == SC_FILE_TYPE_INTERNAL_EF) { - if (file->ef_structure == - SC_CARDCTL_OBERTHUR_KEY_RSA_CRT) { + if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_CRT || + file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_CRT) { ops[1] = SC_AC_OP_UPDATE; ops[2] = SC_AC_OP_CRYPTO; ops[3] = SC_AC_OP_DELETE; } - else if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC) { + else if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC|| + file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC) { ops[0] = SC_AC_OP_READ; ops[1] = SC_AC_OP_UPDATE; ops[2] = SC_AC_OP_CRYPTO; @@ -1973,13 +2070,22 @@ epass2003_construct_fci(struct sc_card *card, const sc_file_t * file, buf[ii] = rv; } sc_asn1_put_tag(0x86, buf, sizeof(ops), p, *outlen - (p - out), &p); + if(file->size == 256) + { + out[4]= 0x13; + } } /* VT ??? */ - if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC) { + if (file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_RSA_PUBLIC|| + file->ef_structure == SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC) { unsigned char data[2] = {0x00, 0x66}; sc_asn1_put_tag(0x87, data, sizeof(data), p, *outlen - (p - out), &p); + if(file->size == 256) + { + out[4]= 0x14; + } } out[1] = p - out - 2; @@ -2129,19 +2235,36 @@ internal_write_rsa_key(struct sc_card *card, unsigned short fid, struct sc_pkcs1 static int -hash_data(unsigned char *data, size_t datalen, unsigned char *hash) +hash_data(const unsigned char *data, size_t datalen, unsigned char *hash, unsigned int mechanismType) { - unsigned char data_hash[24] = { 0 }; - size_t len = 0; if ((NULL == data) || (NULL == hash)) return SC_ERROR_INVALID_ARGUMENTS; - sha1_digest(data, datalen, data_hash); + if(mechanismType | SC_ALGORITHM_ECDSA_HASH_SHA1) + { + unsigned char data_hash[24] = { 0 }; + size_t len = 0; - len = REVERSE_ORDER4(datalen); - memcpy(&data_hash[20], &len, 4); - memcpy(hash, data_hash, 24); + sha1_digest(data, datalen, data_hash); + len = REVERSE_ORDER4(datalen); + memcpy(&data_hash[20], &len, 4); + memcpy(hash, data_hash, 24); + } + else if(mechanismType | SC_ALGORITHM_ECDSA_HASH_SHA256) + { + unsigned char data_hash[36] = { 0 }; + size_t len = 0; + + sha256_digest(data, datalen, data_hash); + len = REVERSE_ORDER4(datalen); + memcpy(&data_hash[32], &len, 4); + memcpy(hash, data_hash, 36); + } + else + { + return SC_ERROR_NOT_SUPPORTED; + } return SC_SUCCESS; } @@ -2214,7 +2337,7 @@ internal_install_pin(struct sc_card *card, sc_epass2003_wkey_data * pin) int r; unsigned char hash[HASH_LEN] = { 0 }; - r = hash_data(pin->key_data.es_secret.key_val, pin->key_data.es_secret.key_len, hash); + r = hash_data(pin->key_data.es_secret.key_val, pin->key_data.es_secret.key_len, hash, SC_ALGORITHM_ECDSA_HASH_SHA1); LOG_TEST_RET(card->ctx, r, "hash data failed"); r = install_secret_key(card, 0x04, pin->key_data.es_secret.kid, @@ -2265,7 +2388,14 @@ epass2003_gen_key(struct sc_card *card, sc_epass2003_gen_key_data * data) LOG_FUNC_CALLED(card->ctx); - sbuf[0] = 0x01; + if(len == 256) + { + sbuf[0] = 0x02; + } + else + { + sbuf[0] = 0x01; + } sbuf[1] = (u8) ((len >> 8) & 0xff); sbuf[2] = (u8) (len & 0xff); sbuf[3] = (u8) ((data->prkey_id >> 8) & 0xFF); @@ -2285,6 +2415,10 @@ epass2003_gen_key(struct sc_card *card, sc_epass2003_gen_key_data * data) /* read public key */ sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xb4, 0x02, 0x00); + if(len == 256) + { + apdu.p1 = 0x00; + } apdu.cla = 0x80; apdu.lc = apdu.datalen = 2; apdu.data = &sbuf[5]; @@ -2349,6 +2483,7 @@ epass2003_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr) { LOG_FUNC_CALLED(card->ctx); + sc_log(card->ctx, "cmd is %0lx", cmd); switch (cmd) { case SC_CARDCTL_ENTERSAFE_WRITE_KEY: return epass2003_write_key(card, (sc_epass2003_wkey_data *) ptr); @@ -2474,7 +2609,7 @@ external_key_auth(struct sc_card *card, unsigned char kid, r = sc_get_challenge(card, random, 8); LOG_TEST_RET(card->ctx, r, "get challenge external_key_auth failed"); - r = hash_data(data, datalen, hash); + r = hash_data(data, datalen, hash, SC_ALGORITHM_ECDSA_HASH_SHA1); LOG_TEST_RET(card->ctx, r, "hash data failed"); des3_encrypt_cbc(hash, HASH_LEN, iv, random, 8, tmp_data); @@ -2501,7 +2636,7 @@ update_secret_key(struct sc_card *card, unsigned char ktype, unsigned char kid, unsigned char tmp_data[256] = { 0 }; unsigned char maxtries = 0; - r = hash_data(data, datalen, hash); + r = hash_data(data, datalen, hash, SC_ALGORITHM_ECDSA_HASH_SHA1); LOG_TEST_RET(card->ctx, r, "hash data failed"); r = get_external_key_maxtries(card, &maxtries); diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index 9a58427b..b647b053 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -490,7 +490,9 @@ enum SC_CARDCTL_OBERTHUR_KEY_TYPE { SC_CARDCTL_OBERTHUR_KEY_RSA_SFM, SC_CARDCTL_OBERTHUR_KEY_RSA_CRT, SC_CARDCTL_OBERTHUR_KEY_DSA_PUBLIC, - SC_CARDCTL_OBERTHUR_KEY_DSA_PRIVATE + SC_CARDCTL_OBERTHUR_KEY_DSA_PRIVATE, + SC_CARDCTL_OBERTHUR_KEY_EC_CRT, + SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC }; struct sc_cardctl_oberthur_genkey_info { diff --git a/src/libopensc/sm.c b/src/libopensc/sm.c index 94f7ce7c..877a5ef1 100644 --- a/src/libopensc/sm.c +++ b/src/libopensc/sm.c @@ -157,7 +157,7 @@ sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu) } /* send APDU flagged as NO_SM */ - sm_apdu->flags |= SC_APDU_FLAGS_NO_SM; + sm_apdu->flags |= SC_APDU_FLAGS_NO_SM | SC_APDU_FLAGS_NO_RETRY_WL; rv = sc_transmit_apdu(card, sm_apdu); if (rv < 0) { card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu); diff --git a/src/pkcs15init/pkcs15-epass2003.c b/src/pkcs15init/pkcs15-epass2003.c index 3be5ab85..786a7125 100644 --- a/src/pkcs15init/pkcs15-epass2003.c +++ b/src/pkcs15init/pkcs15-epass2003.c @@ -312,6 +312,16 @@ cosm_new_file(struct sc_profile *profile, struct sc_card *card, num); while (1) { switch (type) { + case SC_PKCS15_TYPE_PRKEY_EC: + desc = "RSA private key"; + _template = "private-key"; + structure = SC_CARDCTL_OBERTHUR_KEY_EC_CRT; + break; + case SC_PKCS15_TYPE_PUBKEY_EC: + desc = "RSA public key"; + _template = "public-key"; + structure = SC_CARDCTL_OBERTHUR_KEY_EC_PUBLIC; + break; case SC_PKCS15_TYPE_PRKEY_RSA: desc = "RSA private key"; _template = "private-key"; @@ -497,11 +507,14 @@ static int epass2003_pkcs15_generate_key(struct sc_profile *profile, SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); - if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) + if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA && obj->type != SC_PKCS15_TYPE_PRKEY_EC) return SC_ERROR_NOT_SUPPORTED; + if(obj->type == SC_PKCS15_TYPE_PRKEY_EC && keybits == 0) + keybits = 256; //EC key length is 256 ... + /* allocate key object */ - r = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx, &file); + r = cosm_new_file(profile, card, obj->type, idx, &file); //replace SC_PKCS15_TYPE_PRKEY_RSA with obj->type SC_TEST_GOTO_ERR(card->ctx, SC_LOG_DEBUG_NORMAL, r, "create key: failed to allocate new key object"); file->size = keybits; @@ -525,11 +538,18 @@ static int epass2003_pkcs15_generate_key(struct sc_profile *profile, "index %"SC_FORMAT_LEN_SIZE_T"u; keybits %"SC_FORMAT_LEN_SIZE_T"u\n", idx, keybits); if (keybits < 1024 || keybits > 2048 || (keybits % 0x20)) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL, - "Unsupported key size %"SC_FORMAT_LEN_SIZE_T"u\n", - keybits); - r = SC_ERROR_INVALID_ARGUMENTS; - goto err; + if(obj->type == SC_PKCS15_TYPE_PRKEY_EC && keybits == 256) + { + sc_log(card->ctx, "current Alg is EC,Only support 256 ..\n"); + } + else + { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL, + "Unsupported key size %"SC_FORMAT_LEN_SIZE_T"u\n", + keybits); + r = SC_ERROR_INVALID_ARGUMENTS; + goto err; + } } path = key_info->path; @@ -549,12 +569,23 @@ static int epass2003_pkcs15_generate_key(struct sc_profile *profile, SC_TEST_GOTO_ERR(card->ctx, SC_LOG_DEBUG_NORMAL, r, "generate key: pkcs15init_authenticate(SC_AC_OP_CREATE) failed"); - if ((r = cosm_new_file(profile, card, SC_PKCS15_TYPE_PUBKEY_RSA, idx, - &pukf)) < 0) { + if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA ) + { + + r = cosm_new_file(profile, card, SC_PKCS15_TYPE_PUBKEY_EC, idx, &pukf); + } + else + { + + r = cosm_new_file(profile, card, SC_PKCS15_TYPE_PUBKEY_RSA, idx, &pukf); + } + + if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "generate key: create temporary pukf failed\n"); goto err; } + pukf->size = keybits; pukf->id = pukf->path.value[pukf->path.len - 2] * 0x100 + pukf->path.value[pukf->path.len - 1];