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/configure.ac b/configure.ac index bbedd37c..3cdd4342 100644 --- a/configure.ac +++ b/configure.ac @@ -862,7 +862,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/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/etc/opensc.conf.in b/etc/opensc.conf.in index 96615160..c24d65f9 100644 --- a/etc/opensc.conf.in +++ b/etc/opensc.conf.in @@ -1160,6 +1160,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; } } 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); } diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index 41e28835..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 } }; @@ -171,7 +172,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. */ 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/card-gids.c b/src/libopensc/card-gids.c index 923cf3bd..a10de902 100644 --- a/src/libopensc/card-gids.c +++ b/src/libopensc/card-gids.c @@ -1879,13 +1879,13 @@ 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; int buffer2size = 40; u8 apduSendResponseResponse[256]; + u8 buffer3[16+16+8]; + int buffer3size = 40; sc_apdu_t apdu; const EVP_CIPHER *cipher; @@ -1923,8 +1923,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); @@ -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 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/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index 5a417913..fc741924 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,62 @@ 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 { +#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); + apdu.cla = 0x80; + 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"); + } 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 +372,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 +411,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 +605,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 @@ -1501,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 @@ -1575,7 +1617,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/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/cards.h b/src/libopensc/cards.h index f7c78dd8..0cc7650e 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -200,10 +200,12 @@ 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, 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/opensc.h b/src/libopensc/opensc.h index bd2eb500..209e4aba 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-cac.c b/src/libopensc/pkcs15-cac.c index fa76ec34..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; /* @@ -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)); @@ -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 d38d7ba7..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; @@ -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, @@ -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 @@ -773,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 */ @@ -932,7 +952,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; diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index 26eaa058..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); @@ -941,7 +939,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 +997,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); diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 2ce34b6c..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); @@ -1059,15 +1085,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 +1153,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 +2421,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/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 diff --git a/src/libopensc/sm.c b/src/libopensc/sm.c index a5f53de1..877a5ef1 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) @@ -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/minidriver/Makefile.am b/src/minidriver/Makefile.am index ac774e39..e0922e0f 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 38598b2c..00000000 Binary files a/src/minidriver/minidriver-sc-hsm.reg and /dev/null differ diff --git a/src/minidriver/minidriver-westcos.reg b/src/minidriver/minidriver-westcos.reg deleted file mode 100644 index 840daee6..00000000 --- a/src/minidriver/minidriver-westcos.reg +++ /dev/null @@ -1,7 +0,0 @@ -Windows Registry Editor Version 5.00 - -[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\CEV WESTCOS] -"80000001"="opensc-minidriver.dll" -"ATR"=hex:3f,69,00,00,00,64,01,00,00,00,80,90,00 -"ATRMask"=hex:ff,ff,ff,ff,ff,ff,ff,00,00,00,f0,ff,ff -"Crypto Provider"="Microsoft Base Smart Card Crypto Provider" diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index b9157f92..7058e23c 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -30,9 +30,9 @@ #pragma managed(push, off) #endif - #include #include +#include #include #include @@ -77,6 +77,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)) @@ -175,7 +182,9 @@ struct md_guid_conversion md_static_conversions[MD_MAX_CONVERSIONS] = {0}; typedef struct _VENDOR_SPECIFIC { - struct sc_pkcs15_object *obj_user_pin, *obj_sopin; + BOOL initialized; + + struct sc_pkcs15_object *pin_objs[MD_MAX_PINS]; struct sc_context *ctx; struct sc_reader *reader; @@ -246,10 +255,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 @@ -336,22 +346,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 - */ -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; @@ -364,34 +443,36 @@ 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 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; @@ -400,43 +481,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 const char * md_get_config_str(PCARD_DATA pCardData, enum ui_str id) @@ -565,6 +668,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; @@ -674,6 +780,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); @@ -776,6 +885,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; @@ -803,6 +915,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; @@ -982,6 +1097,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) { @@ -1042,7 +1159,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; @@ -1050,9 +1167,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) { @@ -1060,6 +1179,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) { @@ -1073,7 +1193,7 @@ md_fs_finalize(PCARD_DATA pCardData) dir = dir->next; pCardData->pfnCspFree(dir_to_rm); } - return 0; + vs->root.subdirs = NULL; } /* @@ -1091,6 +1211,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) @@ -1137,6 +1259,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) @@ -1217,6 +1342,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]; @@ -1468,6 +1596,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) { @@ -1501,6 +1631,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; @@ -1509,12 +1647,35 @@ 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; + 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) { + 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) @@ -1556,7 +1717,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, @@ -1580,7 +1850,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); @@ -1638,6 +1907,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; iiroot.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, @@ -1750,6 +2121,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 */ @@ -1809,6 +2184,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) { @@ -1958,7 +2337,7 @@ md_check_key_compatibility(PCARD_DATA pCardData, DWORD flags, DWORD key_type, static DWORD -md_pkcs15_generate_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, DWORD key_size) +md_pkcs15_generate_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, DWORD key_size, PIN_ID PinId) { VENDOR_SPECIFIC *vs; struct sc_card *card = NULL; @@ -1970,13 +2349,19 @@ md_pkcs15_generate_key(PCARD_DATA pCardData, DWORD idx, DWORD key_type, DWORD ke struct sc_pkcs15init_pubkeyargs pub_args; struct md_pkcs15_container *cont = 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 (!vs) + return SCARD_E_INVALID_PARAMETER; + + 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)); @@ -2029,12 +2414,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; @@ -2095,9 +2475,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; @@ -2111,13 +2490,19 @@ 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 (!vs) + return SCARD_E_INVALID_PARAMETER; + + 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); @@ -2157,12 +2542,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); @@ -2255,6 +2635,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)); @@ -2324,6 +2707,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; @@ -2752,7 +3138,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"); @@ -2763,7 +3152,6 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) logprintf(pCardData, 1, "**********************************************************************\n"); - md_fs_finalize(pCardData); pCardData->pfnCspFree(pCardData->pvVendorSpecific); pCardData->pvVendorSpecific = NULL; @@ -2783,11 +3171,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; } @@ -2808,6 +3198,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; @@ -2840,26 +3234,44 @@ 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; + + 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); 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"); @@ -2888,7 +3300,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; @@ -2896,7 +3308,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; @@ -2912,6 +3324,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; @@ -2923,7 +3346,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; @@ -2934,6 +3357,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); @@ -2954,6 +3381,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) { @@ -2962,13 +3392,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; @@ -3203,6 +3629,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 ", @@ -3215,9 +3642,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; @@ -3365,14 +3796,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 ", @@ -3384,7 +3813,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); @@ -3434,6 +3869,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)); @@ -3456,6 +3895,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(), @@ -3475,7 +3915,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) { @@ -3526,7 +3968,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", @@ -3578,7 +4022,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) { @@ -3599,6 +4045,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; @@ -3620,7 +4067,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)); @@ -3658,6 +4111,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 ", @@ -3665,6 +4119,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)); @@ -3695,7 +4153,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) { @@ -3731,6 +4191,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; @@ -3745,6 +4209,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; @@ -3771,14 +4236,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, @@ -3926,6 +4395,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; @@ -3963,6 +4433,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, @@ -3978,6 +4452,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; @@ -3986,8 +4463,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); @@ -4183,6 +4658,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; @@ -4211,14 +4687,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, @@ -4754,6 +5234,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) { @@ -4924,6 +5406,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; @@ -4962,6 +5446,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; @@ -4977,17 +5462,25 @@ 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); + if (!vs) + return SCARD_E_INVALID_PARAMETER; - r = check_reader_status(pCardData); + if (PinId >= MD_MAX_PINS) + return SCARD_E_INVALID_PARAMETER; - if ((vs->p15card) == NULL) - return SCARD_F_INTERNAL_ERROR; + 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 @@ -5003,6 +5496,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 @@ -5014,20 +5511,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; @@ -5046,34 +5532,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, PinId); + *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, PinId); 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 { @@ -5103,16 +5604,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); } } @@ -5131,12 +5632,13 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, __in DWORD cRetryCount, __out_opt PDWORD pcAttemptsRemaining) { + DWORD dwret; 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(), @@ -5145,6 +5647,15 @@ 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"); return SCARD_E_INVALID_PARAMETER; @@ -5153,12 +5664,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; @@ -5170,11 +5680,6 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, (unsigned int)dwTargetPinId, (unsigned long)cbTargetData, pcAttemptsRemaining ? "YES" : "NO"); - - 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) { @@ -5195,20 +5700,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, dwTargetPinId); - + /* 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, dwTargetPinId); + if (rv) { logprintf(pCardData, 2, "Failed to %s %s PIN: '%s' (%i)\n", (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN?"change":"unblock"), @@ -5252,6 +5759,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; @@ -5260,9 +5768,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), @@ -5278,6 +5790,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) { @@ -5303,7 +5818,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; @@ -5350,9 +5892,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; @@ -5461,22 +6007,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", @@ -5489,19 +6030,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; @@ -5516,8 +6078,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)) @@ -5583,6 +6149,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; @@ -5890,35 +6458,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; @@ -5926,7 +6465,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) { @@ -5993,11 +6532,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; @@ -6028,18 +6564,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", @@ -6077,19 +6607,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; - DWORD dw; 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 @@ -6110,63 +6656,65 @@ 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)); + 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)); - if(vs->card == NULL || vs->p15card == NULL) { - logprintf(pCardData, 0, "Card unknown.\n"); + 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; } - 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"); + 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; + } - 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)); EnterCriticalSection(&md_static_data.hScard_lock); @@ -6186,10 +6734,9 @@ static int disassociate_card(PCARD_DATA pCardData) vs->hSCardCtx = -1; vs->hScard = -1; + vs->initialized = FALSE; LeaveCriticalSection(&md_static_data.hScard_lock); - - return SCARD_S_SUCCESS; } @@ -6245,4 +6792,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 2f0ddc2b..34d92cb5 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1043,6 +1043,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) @@ -1067,9 +1068,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; } @@ -1230,6 +1232,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, 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-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; 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 diff --git a/src/pkcs11/pkcs11-spy.c b/src/pkcs11/pkcs11-spy.c index 1aed6389..8011f047 100644 --- a/src/pkcs11/pkcs11-spy.c +++ b/src/pkcs11/pkcs11-spy.c @@ -172,7 +172,7 @@ init_spy(void) } } - if( (rc == ERROR_SUCCESS) && (temp_len < PATH_MAX) ) + if( (rc == ERROR_SUCCESS) && (temp_len < PATH_MAX) ) output = temp_path; RegCloseKey( hKey ); } @@ -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/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 834573bf..49297596 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -36,12 +36,6 @@ extern "C" { #endif -#if defined(_WIN32) || defined(USE_CYGWIN) -#define PKCS11_DEFAULT_MODULE_NAME "opensc-pkcs11.dll" -#else -#define PKCS11_DEFAULT_MODULE_NAME "opensc-pkcs11.so" -#endif - #define SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED 0 #define SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN 1 #define SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN 2 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]; 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); 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"); } diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index f1ff0efb..dfd6913d 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -26,10 +26,11 @@ #include #ifndef _WIN32 -#include #include #include +#include #else +#include #include #endif @@ -133,6 +134,7 @@ enum { OPT_KEY_USAGE_DECRYPT, OPT_KEY_USAGE_DERIVE, OPT_PRIVATE, + OPT_SENSITIVE, OPT_TEST_HOTPLUG, OPT_UNLOCK_PIN, OPT_PUK, @@ -145,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[] = { @@ -161,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 }, @@ -203,6 +211,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 }, @@ -226,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')", @@ -268,6 +280,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 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", @@ -307,6 +320,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; @@ -315,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; @@ -405,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); @@ -537,6 +557,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) @@ -669,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; @@ -804,6 +837,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++; @@ -844,6 +880,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"); @@ -1318,7 +1361,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)); @@ -1329,7 +1372,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)); @@ -1591,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"); @@ -1607,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; @@ -1659,7 +1819,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; @@ -2028,6 +2188,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] = { @@ -2102,6 +2263,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)); @@ -4310,14 +4480,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; @@ -4836,7 +5006,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; } @@ -4847,14 +5017,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) @@ -5621,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, "SHA256-RSA-PKCS-PSS", NULL }, - { CKM_SHA384_RSA_PKCS, "SHA384-RSA-PKCS-PSS", NULL }, - { CKM_SHA512_RSA_PKCS, "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 }, @@ -5671,8 +5841,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 }, @@ -5770,7 +5943,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 }, @@ -5798,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]; @@ -5824,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); diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index 2c14ad6f..00f076d6 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 diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index 9c17ebce..cd02ab5f 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -7,7 +7,6 @@ - @@ -17,7 +16,6 @@ - @@ -59,56 +57,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -122,6 +74,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -300,6 +293,15 @@ + + + + + + + + + diff --git a/win32/customactions.cpp b/win32/customactions.cpp index f576fc6e..3a3291c7 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 */ @@ -120,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}, @@ -254,8 +253,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)