From 8eb56730582f9f8d0d6f26fab1f17968035b7a94 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Tue, 8 Oct 2019 15:43:40 +0200 Subject: [PATCH 001/189] Check keyformat for RSA only inside if RSA key is to be imported --- src/libopensc/card-openpgp.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index b8cdd452..16c557d5 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -3160,23 +3160,23 @@ pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info) LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid key ID; must be 1, 2, or 3"); - /* we just support standard key format */ - switch (key_info->u.rsa.keyformat) { - case SC_OPENPGP_KEYFORMAT_RSA_STD: - case SC_OPENPGP_KEYFORMAT_RSA_STDN: - break; - - case SC_OPENPGP_KEYFORMAT_RSA_CRT: - case SC_OPENPGP_KEYFORMAT_RSA_CRTN: - LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); - - default: - LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); - } - /* set algorithm attributes */ /* RSA */ if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA){ + /* we just support standard key format */ + switch (key_info->u.rsa.keyformat) { + case SC_OPENPGP_KEYFORMAT_RSA_STD: + case SC_OPENPGP_KEYFORMAT_RSA_STDN: + break; + + case SC_OPENPGP_KEYFORMAT_RSA_CRT: + case SC_OPENPGP_KEYFORMAT_RSA_CRTN: + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); + + default: + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + } + /* we only support exponent of maximum 32 bits */ if (key_info->u.rsa.e_len > SC_OPENPGP_MAX_EXP_BITS) { sc_log(card->ctx, From ca5b3977d8a7bae2b8a964e3871c5c0f468646c0 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Tue, 8 Oct 2019 17:11:00 +0200 Subject: [PATCH 002/189] Fix ecc oid handling while storing existing keys --- src/libopensc/card-openpgp.c | 2 ++ src/libopensc/cardctl.h | 2 ++ src/pkcs15init/pkcs15-openpgp.c | 11 +++++++++++ 3 files changed, 15 insertions(+) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 16c557d5..54a62135 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -3207,6 +3207,8 @@ pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info) if (key_info->u.ec.ecpoint && key_info->u.ec.ecpoint_len){ pubkey.u.ec.ecpoint = key_info->u.ec.ecpoint; pubkey.u.ec.ecpoint_len = key_info->u.ec.ecpoint_len; + pubkey.u.ec.oid = key_info->u.ec.oid; + pubkey.u.ec.oid_len = key_info->u.ec.oid_len; } else LOG_FUNC_RETURN(card->ctx,SC_ERROR_INVALID_ARGUMENTS); diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index ac196925..dedbc2df 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -995,6 +995,8 @@ typedef struct sc_cardctl_openpgp_keystore_info { size_t privateD_len; u8 *ecpoint; size_t ecpoint_len; + struct sc_object_id oid; + u8 oid_len; } ec; } u; time_t creationtime; diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index dfd4b8b8..5f301602 100644 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -119,6 +119,7 @@ static int openpgp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data; sc_cardctl_openpgp_keystore_info_t key_info; int r; + unsigned int i; LOG_FUNC_CALLED(card->ctx); @@ -152,6 +153,16 @@ static int openpgp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, key_info.u.ec.privateD_len = key->u.ec.privateD.len; key_info.u.ec.ecpoint = key->u.ec.ecpointQ.value; key_info.u.ec.ecpoint_len = key->u.ec.ecpointQ.len; + /* extract oid the way we need to import it to OpenPGP Card */ + if (key->u.ec.params.der.len > 2) + key_info.u.ec.oid_len = key->u.ec.params.der.value[1]; + else + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + + for (i=0; (i < key_info.u.ec.oid_len) && (i+2 < key->u.ec.params.der.len); i++){ + key_info.u.ec.oid.value[i] = key->u.ec.params.der.value[i+2]; + } + key_info.u.ec.oid.value[key_info.u.ec.oid_len] = -1; r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_STORE_KEY, &key_info); break; default: From 606fae5a8ec45679ea87e07346cd7bee20ee5058 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Wed, 9 Oct 2019 15:02:36 +0200 Subject: [PATCH 003/189] Use ecpointQ for better code readability --- src/libopensc/card-openpgp.c | 10 +++++----- src/libopensc/cardctl.h | 4 ++-- src/pkcs15init/pkcs15-openpgp.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 54a62135..8b68e8b2 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -3056,8 +3056,8 @@ pgp_build_extended_header_list(sc_card_t *card, sc_cardctl_openpgp_keystore_info /* TODO ECC import with public key, if necessary as denoted in algorithm caps*/ /* validate */ - if ((key_info->u.ec.ecpoint == NULL || key_info->u.ec.ecpoint_len == 0)){ - sc_log(ctx, "Error: ecpoint required!"); + if ((key_info->u.ec.ecpointQ == NULL || key_info->u.ec.ecpointQ_len == 0)){ + sc_log(ctx, "Error: ecpointQ required!"); LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); } @@ -3204,9 +3204,9 @@ pgp_store_key(sc_card_t *card, sc_cardctl_openpgp_keystore_info_t *key_info) memset(&pubkey, 0, sizeof(pubkey)); pubkey.key_id = key_info->key_id; pubkey.algorithm = key_info->algorithm; - if (key_info->u.ec.ecpoint && key_info->u.ec.ecpoint_len){ - pubkey.u.ec.ecpoint = key_info->u.ec.ecpoint; - pubkey.u.ec.ecpoint_len = key_info->u.ec.ecpoint_len; + if (key_info->u.ec.ecpointQ && key_info->u.ec.ecpointQ_len){ + pubkey.u.ec.ecpoint = key_info->u.ec.ecpointQ; + pubkey.u.ec.ecpoint_len = key_info->u.ec.ecpointQ_len; pubkey.u.ec.oid = key_info->u.ec.oid; pubkey.u.ec.oid_len = key_info->u.ec.oid_len; } diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index dedbc2df..9bce594b 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -993,8 +993,8 @@ typedef struct sc_cardctl_openpgp_keystore_info { struct { u8 *privateD; size_t privateD_len; - u8 *ecpoint; - size_t ecpoint_len; + u8 *ecpointQ; + size_t ecpointQ_len; struct sc_object_id oid; u8 oid_len; } ec; diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c index 5f301602..3740e2bb 100644 --- a/src/pkcs15init/pkcs15-openpgp.c +++ b/src/pkcs15init/pkcs15-openpgp.c @@ -151,8 +151,8 @@ static int openpgp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, key_info.key_id = kinfo->id.value[0]; key_info.u.ec.privateD = key->u.ec.privateD.data; key_info.u.ec.privateD_len = key->u.ec.privateD.len; - key_info.u.ec.ecpoint = key->u.ec.ecpointQ.value; - key_info.u.ec.ecpoint_len = key->u.ec.ecpointQ.len; + key_info.u.ec.ecpointQ = key->u.ec.ecpointQ.value; + key_info.u.ec.ecpointQ_len = key->u.ec.ecpointQ.len; /* extract oid the way we need to import it to OpenPGP Card */ if (key->u.ec.params.der.len > 2) key_info.u.ec.oid_len = key->u.ec.params.der.value[1]; From c695a4e35f0c50f491a12e2627cfb124a9876c80 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Wed, 9 Oct 2019 17:18:21 +0200 Subject: [PATCH 004/189] Add support for pubkey import if announced in algorithm attributes --- src/libopensc/card-openpgp.c | 24 +++++++++++++++++++++--- src/libopensc/cardctl.h | 7 ++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 8b68e8b2..c6b5b7a6 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -719,10 +719,20 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_ /* SC_OPENPGP_KEYALGO_ECDH || SC_OPENPGP_KEYALGO_ECDSA */ key_info->algorithm = blob->data[0]; + /* last byte is only set if pubkey import is supported, empty otherwise*/ + if (blob->data[blob->len] == SC_OPENPGP_KEYFORMAT_EC_STDPUB){ + key_info->u.ec.oid_len = blob->len - 2; + key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STDPUB; + } + else { + key_info->u.ec.oid_len = blob->len - 1; + key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STD; + } + sc_init_oid(&oid); /* Create copy of oid from blob */ - for (j=0; j < (blob->len-1); j++) { - oid.value[j] = blob->data[j+1]; /* ignore first byte of blob (algo ID) */ + for (j=0; j < key_info->u.ec.oid_len; j++) { + oid.value[j] = blob->data[j+1]; /* ignore first byte (algo ID) */ } /* compare with list of supported ec_curves */ @@ -733,6 +743,7 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_ break; } } + break; default: return SC_ERROR_NOT_IMPLEMENTED; @@ -3053,7 +3064,14 @@ pgp_build_extended_header_list(sc_card_t *card, sc_cardctl_openpgp_keystore_info componentnames[0] = "private key"; comp_to_add = 1; - /* TODO ECC import with public key, if necessary as denoted in algorithm caps*/ + /* import public key as well */ + if (key_info->u.ec.keyformat == SC_OPENPGP_KEYFORMAT_EC_STDPUB){ + components[1] = key_info->u.ec.ecpointQ; + componentlens[1] = key_info->u.ec.ecpointQ_len; + componenttags[1] = 0x99; + componentnames[1] = "public key"; + comp_to_add = 2; + } /* validate */ if ((key_info->u.ec.ecpointQ == NULL || key_info->u.ec.ecpointQ_len == 0)){ diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index 9bce594b..4b76391f 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -952,6 +952,9 @@ typedef struct sc_cardctl_piv_genkey_info_st { #define SC_OPENPGP_KEYFORMAT_RSA_CRT 2 #define SC_OPENPGP_KEYFORMAT_RSA_CRTN 3 +#define SC_OPENPGP_KEYFORMAT_EC_STD 0 +#define SC_OPENPGP_KEYFORMAT_EC_STDPUB 0xFF + #define SC_OPENPGP_MAX_EXP_BITS 0x20 /* maximum exponent length supported in bits */ typedef struct sc_cardctl_openpgp_keygen_info { @@ -959,13 +962,14 @@ typedef struct sc_cardctl_openpgp_keygen_info { u8 algorithm; /* SC_OPENPGP_KEYALGO_... */ union { struct { + u8 keyformat; /* SC_OPENPGP_KEYFORMAT_RSA_... */ u8 *modulus; /* New-generated pubkey info responded from the card */ size_t modulus_len; /* Length of modulus in bit */ u8 *exponent; size_t exponent_len; /* Length of exponent in bit */ - u8 keyformat; /* SC_OPENPGP_KEYFORMAT_RSA_... */ } rsa; struct { + u8 keyformat; /* SC_OPENPGP_KEYFORMAT_EC_... */ u8 *ecpoint; size_t ecpoint_len; struct sc_object_id oid; @@ -991,6 +995,7 @@ typedef struct sc_cardctl_openpgp_keystore_info { size_t n_len; } rsa; struct { + u8 keyformat; /* SC_OPENPGP_KEYFORMAT_EC_... */ u8 *privateD; size_t privateD_len; u8 *ecpointQ; From 5e1bfe0accc3c21ede26dc639c52009ac6165536 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 12 Aug 2019 09:23:30 +0200 Subject: [PATCH 005/189] Drop the pkcs15.h from simpletlv.h --- src/libopensc/card-cac.c | 1 + src/libopensc/card-cac1.c | 1 + src/libopensc/simpletlv.h | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c index d59b4337..2c9361df 100644 --- a/src/libopensc/card-cac.c +++ b/src/libopensc/card-cac.c @@ -54,6 +54,7 @@ #endif #include "iso7816.h" #include "card-cac-common.h" +#include "pkcs15.h" /* * CAC hardware and APDU constants diff --git a/src/libopensc/card-cac1.c b/src/libopensc/card-cac1.c index 08d62b62..67035d64 100644 --- a/src/libopensc/card-cac1.c +++ b/src/libopensc/card-cac1.c @@ -54,6 +54,7 @@ #endif #include "iso7816.h" #include "card-cac-common.h" +#include "pkcs15.h" /* * CAC hardware and APDU constants diff --git a/src/libopensc/simpletlv.h b/src/libopensc/simpletlv.h index a9527797..6bcd4f08 100644 --- a/src/libopensc/simpletlv.h +++ b/src/libopensc/simpletlv.h @@ -29,7 +29,6 @@ extern "C" { #endif #include "libopensc/opensc.h" -#include "libopensc/pkcs15.h" /* * Create a tag/length file in Simple TLV based on the val_len content length From 2882c93ec1910ce6c7dac27be8c969ab1feb8c39 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 12 Aug 2019 14:02:24 +0200 Subject: [PATCH 006/189] pkcs15: Expose the map_usage() function from CAC to other pkcs15 emulators --- src/libopensc/pkcs15-cac.c | 85 +----------------------------------- src/libopensc/pkcs15-cert.c | 86 +++++++++++++++++++++++++++++++++++++ src/libopensc/pkcs15.h | 3 ++ 3 files changed, 90 insertions(+), 84 deletions(-) diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c index d637dedf..9616b0ac 100644 --- a/src/libopensc/pkcs15-cac.c +++ b/src/libopensc/pkcs15-cac.c @@ -84,89 +84,6 @@ static const char * cac_get_name(int type) return ("CAC"); } -/* - * These could move to a helper file for other cards that wish to use usage as a way of getting flags - */ - -/* Only certain usages are valid for a given algorithm, return all the usages that the algorithm supports so we - * can use it as a filter for all the public and private key usages */ -static unsigned int -cac_alg_flags_from_algorithm(int algorithm) -{ - switch (algorithm) { - case SC_ALGORITHM_RSA: - return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP | - SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | - SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP | - SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | - SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; - case SC_ALGORITHM_DSA: - return SC_PKCS15_PRKEY_USAGE_VERIFY| SC_PKCS15_PRKEY_USAGE_SIGN | - SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; -#ifdef SC_ALGORITHM_DH - case SC_ALGORITHM_DH: - return SC_PKCS15_PRKEY_USAGE_DERIVE ; -#endif - case SC_ALGORITHM_EC: - return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY| - SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; - case SC_ALGORITHM_GOSTR3410: - return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY| - SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; - } - return 0; -} - -/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */ -#define CAC_X509_USAGE_SIGNATURE \ - (SC_X509_DIGITAL_SIGNATURE | \ - SC_X509_NON_REPUDIATION | \ - SC_X509_KEY_CERT_SIGN | \ - SC_X509_CRL_SIGN) -#define CAC_X509_USAGE_DERIVE \ - SC_X509_KEY_AGREEMENT -#define CAC_X509_USAGE_UNWRAP \ - (SC_X509_KEY_ENCIPHERMENT | \ - SC_X509_KEY_AGREEMENT) -#define CAC_X509_USAGE_DECRYPT \ - (SC_X509_DATA_ENCIPHERMENT | \ - SC_X509_ENCIPHER_ONLY) -#define CAC_X509_USAGE_NONREPUDIATION \ - SC_X509_NON_REPUDIATION - -/* map a cert usage and algorithm to public and private key usages */ -static int -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); - - if (cert_usage & CAC_X509_USAGE_SIGNATURE) { - pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER; - pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER; - } - if (cert_usage & CAC_X509_USAGE_DERIVE) { - pub_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; - pr_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; - } - if (cert_usage & (CAC_X509_USAGE_DECRYPT|CAC_X509_USAGE_UNWRAP)) { - pub_usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT; - pr_usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT; - } - if (allow_nonrepudiation && (cert_usage & CAC_X509_USAGE_NONREPUDIATION)) { - pub_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; - pr_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; - } - /* filter usages algorithm */ - if (pub_usage_ptr) { - *pub_usage_ptr = pub_usage & alg_flags; - } - if (pr_usage_ptr) { - *pr_usage_ptr = pr_usage & alg_flags; - } - return SC_SUCCESS; -} - static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) { static const pindata pins[] = { @@ -409,7 +326,7 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) if (r < 0) { usage = 0xd9ULL; /* basic default usage */ } - cac_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); + sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); sc_log(card->ctx, "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); diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index 8606d14a..7850fad8 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -257,6 +257,8 @@ sc_pkcs15_get_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert, { NULL, 0, 0, 0, NULL, NULL } }; + LOG_FUNC_CALLED(ctx); + for (next_ext = cert->extensions, next_ext_len = cert->extensions_len; next_ext_len; ) { /* unwrap the set and point to the next ava */ ext = sc_asn1_skip_tag(ctx, &next_ext, &next_ext_len, @@ -324,6 +326,8 @@ sc_pkcs15_get_bitstring_extension(struct sc_context *ctx, { NULL, 0, 0, 0, NULL, NULL } }; + LOG_FUNC_CALLED(ctx); + r = sc_pkcs15_get_extension(ctx, cert, type, &bit_string, &bit_string_len, is_critical); LOG_TEST_RET(ctx, r, "Get extension error"); @@ -550,6 +554,88 @@ sc_pkcs15_encode_cdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj return r; } +/* Only certain usages are valid for a given algorithm, return all the usages + * that the algorithm supports so we can use it as a filter for all + * the public and private key usages + */ +static unsigned int +sc_pkcs15_alg_flags_from_algorithm(int algorithm) +{ + switch (algorithm) { + case SC_ALGORITHM_RSA: + return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP | + SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | + SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP | + SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | + SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; + case SC_ALGORITHM_DSA: + return SC_PKCS15_PRKEY_USAGE_VERIFY| SC_PKCS15_PRKEY_USAGE_SIGN | + SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; +#ifdef SC_ALGORITHM_DH + case SC_ALGORITHM_DH: + return SC_PKCS15_PRKEY_USAGE_DERIVE ; +#endif + case SC_ALGORITHM_EC: + return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY| + SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; + case SC_ALGORITHM_GOSTR3410: + return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY| + SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; + } + return 0; +} + +/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */ +#define SC_PKCS15_X509_USAGE_SIGNATURE \ + (SC_X509_DIGITAL_SIGNATURE | \ + SC_X509_NON_REPUDIATION | \ + SC_X509_KEY_CERT_SIGN | \ + SC_X509_CRL_SIGN) +#define SC_PKCS15_X509_USAGE_DERIVE \ + SC_X509_KEY_AGREEMENT +#define SC_PKCS15_X509_USAGE_UNWRAP \ + (SC_X509_KEY_ENCIPHERMENT | \ + SC_X509_KEY_AGREEMENT) +#define SC_PKCS15_X509_USAGE_DECRYPT \ + (SC_X509_DATA_ENCIPHERMENT | \ + SC_X509_ENCIPHER_ONLY) +#define SC_PKCS15_X509_USAGE_NONREPUDIATION \ + SC_X509_NON_REPUDIATION + +/* map a cert usage and algorithm to public and private key usages */ +int +sc_pkcs15_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 = sc_pkcs15_alg_flags_from_algorithm(algorithm); + + if (cert_usage & SC_PKCS15_X509_USAGE_SIGNATURE) { + pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER; + pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER; + } + if (cert_usage & SC_PKCS15_X509_USAGE_DERIVE) { + pub_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; + pr_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE; + } + if (cert_usage & (SC_PKCS15_X509_USAGE_DECRYPT|SC_PKCS15_X509_USAGE_UNWRAP)) { + pub_usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT; + pr_usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT; + } + if (allow_nonrepudiation && (cert_usage & SC_PKCS15_X509_USAGE_NONREPUDIATION)) { + pub_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; + pr_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; + } + /* filter usages algorithm */ + if (pub_usage_ptr) { + *pub_usage_ptr = pub_usage & alg_flags; + } + if (pr_usage_ptr) { + *pr_usage_ptr = pr_usage & alg_flags; + } + return SC_SUCCESS; +} void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert) diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index f2ccc42a..df1435ce 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -754,6 +754,9 @@ int sc_pkcs15_get_name_from_dn(struct sc_context *ctx, const u8 *dn, size_t dn_len, const struct sc_object_id *type, u8 **name, size_t *name_len); +int sc_pkcs15_map_usage(unsigned int cert_usage, int algorithm, + unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr, + int allow_nonrepudiation); int sc_pkcs15_get_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert, const struct sc_object_id *type, From 40c41cee0c71b9361bdea91c58bbda04a15a875a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 13 Aug 2019 15:31:40 +0200 Subject: [PATCH 007/189] pkcs11-tool: Make the SHA256 default for OAEP decryption It is already default in all the other functions and it really makes sense since the SHA1 is being obsoleted --- src/tools/pkcs11-tool.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 92c8d8a5..6a8e27ee 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -2127,9 +2127,15 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, case CKM_RSA_PKCS_OAEP: oaep_params.hashAlg = opt_hash_alg; switch (opt_hash_alg) { + case CKM_SHA_1: + oaep_params.mgf = CKG_MGF1_SHA1; + break; case CKM_SHA224: oaep_params.mgf = CKG_MGF1_SHA224; break; + default: + oaep_params.hashAlg = CKM_SHA256; + /* fall through */ case CKM_SHA256: oaep_params.mgf = CKG_MGF1_SHA256; break; @@ -2139,12 +2145,6 @@ static void decrypt_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session, case CKM_SHA512: oaep_params.mgf = CKG_MGF1_SHA512; break; - default: - oaep_params.hashAlg = CKM_SHA_1; - /* fall through */ - case CKM_SHA_1: - oaep_params.mgf = CKG_MGF1_SHA1; - break; } break; case CKM_RSA_X_509: From 3a3a465e6bdeb5c62d28553f9ceb31ad95d9ec27 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 13 Aug 2019 18:05:55 +0200 Subject: [PATCH 008/189] Add basic support for OEAP decryption in OpenSC internals --- src/libopensc/opensc.h | 3 +- src/libopensc/padding.c | 1 + src/pkcs11/framework-pkcs15.c | 70 ++++++++++++++++++++++++++++++++++- src/pkcs11/mechanism.c | 9 +++++ src/tools/opensc-tool.c | 1 + 5 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index d8ec4217..ebadb4c2 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -107,12 +107,13 @@ extern "C" { * must support at least one of them, and exactly one of them must be selected * for a given operation. */ #define SC_ALGORITHM_RSA_RAW 0x00000001 -#define SC_ALGORITHM_RSA_PADS 0x0000001F +#define SC_ALGORITHM_RSA_PADS 0x0000002F #define SC_ALGORITHM_RSA_PAD_NONE 0x00000001 #define SC_ALGORITHM_RSA_PAD_PKCS1 0x00000002 /* PKCS#1 v1.5 padding */ #define SC_ALGORITHM_RSA_PAD_ANSI 0x00000004 #define SC_ALGORITHM_RSA_PAD_ISO9796 0x00000008 #define SC_ALGORITHM_RSA_PAD_PSS 0x00000010 /* PKCS#1 v2.0 PSS */ +#define SC_ALGORITHM_RSA_PAD_OAEP 0x00000020 /* PKCS#1 v2.0 OAEP */ /* If the card is willing to produce a cryptogram with the following * hash values, set these flags accordingly. The interpretation of the hash diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c index 4a8fc17b..5bcb2bb8 100644 --- a/src/libopensc/padding.c +++ b/src/libopensc/padding.c @@ -499,6 +499,7 @@ int sc_get_encoding_flags(sc_context_t *ctx, /* Use the card's raw RSA capability on the padded input */ *sflags = SC_ALGORITHM_RSA_PAD_NONE; *pflags = iflags; + /* TODO emulate the OAEP decryption */ } else if ((caps & (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) && (iflags & SC_ALGORITHM_RSA_PAD_PKCS1)) { diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 22081ffe..e94eeeff 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -3976,7 +3976,7 @@ pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj, /* Check the data length matches the selected hash */ rv = pkcs15_prkey_check_pss_param(pMechanism, (int)ulDataLen); if (rv != CKR_OK) { - sc_log(context, "Invalid data lenght for the selected " + sc_log(context, "Invalid data length for the selected " "PSS parameters"); return rv; } @@ -4179,6 +4179,39 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj, case CKM_RSA_X_509: flags |= SC_ALGORITHM_RSA_RAW; break; + case CKM_RSA_PKCS_OAEP: + flags |= SC_ALGORITHM_RSA_PAD_OAEP; + + /* Omited parameter can use MGF1-SHA1 and SHA1 hash ? */ + if (pMechanism->pParameter == NULL) { + flags |= SC_ALGORITHM_RSA_HASH_SHA1; + flags |= SC_ALGORITHM_MGF1_SHA1; + break; + } + + switch (((CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter)->hashAlg) { + case CKM_SHA_1: + flags |= SC_ALGORITHM_RSA_HASH_SHA1; + break; + case CKM_SHA224: + flags |= SC_ALGORITHM_RSA_HASH_SHA224; + break; + case CKM_SHA256: + flags |= SC_ALGORITHM_RSA_HASH_SHA256; + break; + case CKM_SHA384: + flags |= SC_ALGORITHM_RSA_HASH_SHA384; + break; + case CKM_SHA512: + flags |= SC_ALGORITHM_RSA_HASH_SHA512; + break; + default: + return CKR_MECHANISM_PARAM_INVALID; + } + + /* The MGF parameter was already verified in SignInit() */ + flags |= mgf2flags(((CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter)->mgf); + break; default: return CKR_MECHANISM_INVALID; } @@ -4352,6 +4385,7 @@ pkcs15_prkey_init_params(struct sc_pkcs11_session *session, const unsigned int salt_lens[5] = { 160, 256, 384, 512, 224 }; const unsigned int hashes[5] = { CKM_SHA_1, CKM_SHA256, CKM_SHA384, CKM_SHA512, CKM_SHA224 }; + const CK_RSA_PKCS_OAEP_PARAMS *oaep_params; switch (pMechanism->mechanism) { case CKM_RSA_PKCS_PSS: @@ -4407,6 +4441,26 @@ pkcs15_prkey_init_params(struct sc_pkcs11_session *session, /* TODO support different salt lengths */ break; + case CKM_RSA_PKCS_OAEP: + if (!pMechanism->pParameter || + pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) + return CKR_MECHANISM_PARAM_INVALID; + + oaep_params = (CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter; + switch (oaep_params->mgf) { + case CKG_MGF1_SHA1: + case CKG_MGF1_SHA224: + case CKG_MGF1_SHA256: + case CKG_MGF1_SHA384: + case CKG_MGF1_SHA512: + /* OK */ + break; + default: + return CKR_MECHANISM_PARAM_INVALID; + } + /* TODO support different salt lengths */ + /* TODO is there something more to check */ + break; } return CKR_OK; } @@ -5619,6 +5673,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) rsa_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; #ifdef ENABLE_OPENSSL rsa_flags |= SC_ALGORITHM_RSA_PAD_PSS; + /* TODO support OAEP decryption & encryption using OpenSSL */ #endif } @@ -5699,6 +5754,7 @@ register_mechanisms(struct sc_pkcs11_card *p11card) } if (rsa_flags & SC_ALGORITHM_RSA_PAD_PSS) { + CK_FLAGS old_flags = mech_info.flags; mech_info.flags &= ~(CKF_DECRYPT|CKF_ENCRYPT); mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_PSS, &mech_info, CKK_RSA, NULL, NULL); rc = sc_pkcs11_register_mechanism(p11card, mt); @@ -5735,6 +5791,18 @@ register_mechanisms(struct sc_pkcs11_card *p11card) if (rc != CKR_OK) return rc; } + mech_info.flags = old_flags; + } + + if (rsa_flags & SC_ALGORITHM_RSA_PAD_OAEP) { + CK_FLAGS old_flags = mech_info.flags; + mech_info.flags &= ~(CKF_SIGN|CKF_VERIFY|CKF_SIGN_RECOVER|CKF_VERIFY_RECOVER); + mt = sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS_OAEP, &mech_info, CKK_RSA, NULL, NULL); + rc = sc_pkcs11_register_mechanism(p11card, mt); + if (rc != CKR_OK) { + return rc; + } + mech_info.flags = old_flags; } if (rsa_flags & SC_ALGORITHM_ONBOARD_KEY_GEN) { diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c index 358cad40..983d8dcb 100644 --- a/src/pkcs11/mechanism.c +++ b/src/pkcs11/mechanism.c @@ -811,6 +811,15 @@ sc_pkcs11_decr_init(struct sc_pkcs11_session *session, } rv = mt->decrypt_init(operation, key); + /* Validate the mechanism parameters */ + if (key->ops->init_params) { + rv = key->ops->init_params(operation->session, &operation->mechanism); + if (rv != CKR_OK) { + /* Probably bad arguments */ + LOG_FUNC_RETURN(context, (int) rv); + } + } + if (rv != CKR_OK) session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT); diff --git a/src/tools/opensc-tool.c b/src/tools/opensc-tool.c index f829332f..52b570d9 100644 --- a/src/tools/opensc-tool.c +++ b/src/tools/opensc-tool.c @@ -594,6 +594,7 @@ static int list_algorithms(void) { SC_ALGORITHM_RSA_PAD_PKCS1, "pkcs1" }, { SC_ALGORITHM_RSA_PAD_ANSI, "ansi" }, { SC_ALGORITHM_RSA_PAD_PSS, "pss" }, + { SC_ALGORITHM_RSA_PAD_OAEP, "oaep" }, { SC_ALGORITHM_RSA_PAD_ISO9796, "iso9796" }, { SC_ALGORITHM_RSA_HASH_SHA1, "sha1" }, { SC_ALGORITHM_RSA_HASH_MD5, "MD5" }, From f61d9b3b53aa97c3dad6f8d065c989786662878a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 12 Aug 2019 15:26:18 +0200 Subject: [PATCH 009/189] Implement new Gemalto IDPrime driver The card is largely ISO 7816 compliant, but does not provide any simple way of listing the content which is supported by current PKCS#15 implementation therefore the PKCS#15 emulator had to be used. The certificates are compressed in a similar way as in DNIE cards which complicates reading from the card and which I think could be moved to the shared ISO (or some other file since I saw that code already many times). The card supports wide range of algorithms including RSA-PSS and RSA-OAEP padding schemes in-card. On the other hand, it does not allow raw RSA and SHA1 hashes on card anymore. The card is manufactured by Gemalto so it has strict ATR which can be used for detection. --- src/libopensc/Makefile.am | 8 +- src/libopensc/Makefile.mak | 4 +- src/libopensc/card-idprime.c | 687 +++++++++++++++++++++++++++++++++ src/libopensc/cardctl.h | 9 + src/libopensc/cards.h | 6 + src/libopensc/ctx.c | 1 + src/libopensc/pkcs15-idprime.c | 274 +++++++++++++ src/libopensc/pkcs15-syn.c | 15 +- src/libopensc/pkcs15-syn.h | 1 + 9 files changed, 992 insertions(+), 13 deletions(-) create mode 100644 src/libopensc/card-idprime.c create mode 100644 src/libopensc/pkcs15-idprime.c diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 49d12268..a9f200c9 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -48,14 +48,14 @@ libopensc_la_SOURCES_BASE = \ card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ card-dnie.c cwa14890.c cwa-dnie.c \ card-isoApplet.c card-masktech.c card-gids.c card-jpki.c \ - card-npa.c card-esteid2018.c \ + card-npa.c card-esteid2018.c card-idprime.c \ \ pkcs15-openpgp.c pkcs15-starcert.c \ pkcs15-tcos.c pkcs15-esteid.c pkcs15-gemsafeGPK.c \ pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \ pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ pkcs15-oberthur.c pkcs15-itacns.c pkcs15-gemsafeV1.c pkcs15-sc-hsm.c \ - pkcs15-coolkey.c pkcs15-din-66291.c \ + pkcs15-coolkey.c pkcs15-din-66291.c pkcs15-idprime.c \ pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c pkcs15-esteid2018.c \ compression.c p15card-helper.c sm.c \ aux-data.c @@ -131,14 +131,14 @@ TIDY_FILES = \ card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \ cwa14890.c cwa-dnie.c \ card-isoApplet.c card-masktech.c card-jpki.c \ - card-npa.c card-esteid2018.c \ + card-npa.c card-esteid2018.c card-idprime.c \ \ pkcs15-openpgp.c \ pkcs15-tcos.c pkcs15-esteid.c \ pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c \ pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ pkcs15-oberthur.c pkcs15-itacns.c pkcs15-sc-hsm.c \ - pkcs15-coolkey.c pkcs15-din-66291.c \ + pkcs15-coolkey.c pkcs15-din-66291.c pkcs15-idprime.c \ pkcs15-dnie.c pkcs15-gids.c pkcs15-iasecc.c pkcs15-jpki.c pkcs15-esteid2018.c \ compression.c p15card-helper.c sm.c \ aux-data.c \ diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak index 487fbeb4..2e3c30c2 100644 --- a/src/libopensc/Makefile.mak +++ b/src/libopensc/Makefile.mak @@ -27,7 +27,7 @@ OBJECTS = \ card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \ card-sc-hsm.obj card-dnie.obj card-isoApplet.obj pkcs15-coolkey.obj \ card-masktech.obj card-gids.obj card-jpki.obj \ - card-npa.obj card-esteid2018.obj \ + card-npa.obj card-esteid2018.obj card-idprime.obj \ \ pkcs15-openpgp.obj pkcs15-starcert.obj \ pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-gemsafeGPK.obj \ @@ -35,7 +35,7 @@ OBJECTS = \ pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \ pkcs15-oberthur.obj pkcs15-itacns.obj pkcs15-gemsafeV1.obj pkcs15-sc-hsm.obj \ pkcs15-dnie.obj pkcs15-gids.obj pkcs15-iasecc.obj pkcs15-jpki.obj \ - pkcs15-esteid2018.obj \ + pkcs15-esteid2018.obj pkcs15-idprime.obj \ compression.obj p15card-helper.obj sm.obj \ aux-data.obj \ $(TOPDIR)\win32\versioninfo.res diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c new file mode 100644 index 00000000..e2c7c616 --- /dev/null +++ b/src/libopensc/card-idprime.c @@ -0,0 +1,687 @@ +/* + * card-idprime.c: Support for Gemalto IDPrime smart cards + * + * Copyright (c) 2019 Red Hat, Inc. + * + * Author: Jakub Jelen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "internal.h" +#include +#include +#include +#ifdef ENABLE_ZLIB +#include "compression.h" +#endif + +#include "cardctl.h" +#include "pkcs15.h" + +static const struct sc_card_operations *iso_ops = NULL; + +static struct sc_card_operations idprime_ops; +static struct sc_card_driver idprime_drv = { + "Gemalto IDPrime", + "idprime", + &idprime_ops, + NULL, 0, NULL +}; + +/* This ATR says, there is no EF.DIR nor EF.ATR so ISO discovery mechanisms + * are not useful here */ +static const struct sc_atr_table idprime_atrs[] = { + { "3b:7f:96:00:00:80:31:80:65:b0:84:41:3d:f6:12:0f:fe:82:90:00", + "ff:ff:00:ff:ff:ff:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff", + "Gemalto IDPrime MD 8840, 3840, 3810, 840 and 830 Cards", + SC_CARD_TYPE_IDPRIME_GENERIC, 0, NULL }, +}; + +static const sc_path_t idprime_path = { + "", 0, + 0, 0, SC_PATH_TYPE_DF_NAME, + { "\xA0\x00\x00\x00\x18\x80\x00\x00\x00\x06\x62", 11 } +}; + +/* data structures to store meta data about IDPrime objects */ +typedef struct idprime_object { + int fd; + unsigned char key_reference; + u8 df[2]; +} idprime_object_t; + +/* + * IDPrime private data per card state + */ +typedef struct idprime_private_data { + u8 *cache_buf; /* cached version of the currently selected file */ + size_t cache_buf_len; /* length of the cached selected file */ + int cached; /* is the cached selected file valid */ + size_t file_size; /* this is real file size since IDPrime is quite strict about lengths */ + list_t pki_list; /* list of pki containers */ + idprime_object_t *pki_current; /* current pki object _ctl function */ +} idprime_private_data_t; + +/* For SimCList autocopy, we need to know the size of the data elements */ +static size_t idprime_list_meter(const void *el) { + return sizeof(idprime_object_t); +} + +void idprime_free_private_data(idprime_private_data_t *priv) +{ + free(priv->cache_buf); + list_destroy(&priv->pki_list); + free(priv); + return; +} + +idprime_private_data_t *idprime_new_private_data(void) +{ + idprime_private_data_t *priv; + + priv = calloc(1, sizeof(idprime_private_data_t)); + if (priv == NULL) + return NULL; + + /* Initialize PKI Applets list */ + if (list_init(&priv->pki_list) != 0 || + list_attributes_copy(&priv->pki_list, idprime_list_meter, 1) != 0) { + idprime_free_private_data(priv); + return NULL; + } + + return priv; +} + +int idprime_add_object_to_list(list_t *list, const idprime_object_t *object) +{ + if (list_append(list, object) < 0) + return SC_ERROR_INTERNAL; + return SC_SUCCESS; +} + +/* This selects main IDPrime AID which is used for communication with + * the card */ +static int idprime_select_idprime(sc_card_t *card) +{ + return iso_ops->select_file(card, &idprime_path, NULL); +} + +/* This select some index file, which is useful for enumerating other files + * on the card */ +static int idprime_select_index(sc_card_t *card) +{ + int r; + sc_file_t *file = NULL; + sc_path_t index_path; + + /* First, we need to make sure the IDPrime AID is selected */ + r = idprime_select_idprime(card); + if (r != SC_SUCCESS) { + LOG_FUNC_RETURN(card->ctx, r); + } + + /* Returns FCI with expected length of data */ + sc_format_path("0101", &index_path); + r = iso_ops->select_file(card, &index_path, &file); + if (r != SC_SUCCESS) { + sc_file_free(file); + LOG_FUNC_RETURN(card->ctx, r); + } + r = file->size; + sc_file_free(file); + return r; +} + +static int idprime_process_index(sc_card_t *card, idprime_private_data_t *priv, int length) +{ + u8 *buf = NULL; + int r = SC_ERROR_OUT_OF_MEMORY; + int i, num_entries; + idprime_object_t new_object; + + buf = malloc(length); + if (buf == NULL) { + goto done; + } + + r = iso_ops->read_binary(card, 0, buf, length, 0); + if (r < 1) { + r = SC_ERROR_WRONG_LENGTH; + goto done; + } + + /* First byte shows the number of entries, each of them 21 bytes long */ + num_entries = buf[0]; + if (r < num_entries*21 + 1) { + r = SC_ERROR_INVALID_DATA; + goto done; + } + new_object.fd = 0; + for (i = 0; i < num_entries; i++) { + u8 *start = &buf[i*21+1]; + + /* First two bytes specify the object DF */ + new_object.df[0] = start[0]; + new_object.df[1] = start[1]; + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "df=%s", + sc_dump_hex(new_object.df, sizeof(new_object.df))); + /* I assume this is some identification of certificate */ + if (start[4] == 0x6B && start[5] == 0x78 && start[6] == 0x63 + && start[7] == 0x30) { + new_object.fd++; + /* The key reference is one bigger than the value found here for some reason */ + new_object.key_reference = start[8] + 1; + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d", + new_object.fd); + idprime_add_object_to_list(&priv->pki_list, &new_object); + } + } + r = SC_SUCCESS; +done: + free(buf); + LOG_FUNC_RETURN(card->ctx, r); +} + +static int idprime_init(sc_card_t *card) +{ + int r; + unsigned long flags; + idprime_private_data_t *priv = NULL; + + r = idprime_select_index(card); + if (r <= 0) { + LOG_FUNC_RETURN(card->ctx, r); + } + + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Index file found"); + + priv = idprime_new_private_data(); + if (!priv) { + return SC_ERROR_OUT_OF_MEMORY; + } + r = idprime_process_index(card, priv, r); + if (r != SC_SUCCESS) { + idprime_free_private_data(priv); + LOG_FUNC_RETURN(card->ctx, r); + } + card->type = SC_CARD_TYPE_IDPRIME_GENERIC; + card->drv_data = priv; + + card->name = "Gemalto IDPrime"; + card->cla = 0x00; + + /* Set up algorithm info. */ + flags = SC_ALGORITHM_RSA_PAD_PKCS1 + | SC_ALGORITHM_RSA_PAD_PSS + | SC_ALGORITHM_RSA_PAD_OAEP + /* SHA-1 mechanisms are not allowed in the card I have */ + | (SC_ALGORITHM_RSA_HASH_SHA256 | SC_ALGORITHM_RSA_HASH_SHA384 | SC_ALGORITHM_RSA_HASH_SHA512) + | (SC_ALGORITHM_MGF1_SHA256 | SC_ALGORITHM_MGF1_SHA384 | SC_ALGORITHM_MGF1_SHA512) + ; + + _sc_card_add_rsa_alg(card, 1024, flags, 0); + _sc_card_add_rsa_alg(card, 2048, flags, 0); + + card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; + + LOG_FUNC_RETURN(card->ctx, 0); +} + +static int idprime_finish(sc_card_t *card) +{ + idprime_private_data_t * priv = card->drv_data; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + if (priv) { + idprime_free_private_data(priv); + } + return SC_SUCCESS; +} + +static int idprime_match_card(sc_card_t *card) +{ + int i, r; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + i = _sc_match_atr(card, idprime_atrs, &card->type); + if (i < 0) + return 0; + + r = idprime_select_index(card); + return (r > 0); +} + +/* initialize getting a list and return the number of elements in the list */ +static int idprime_get_init_and_get_count(list_t *list, idprime_object_t **entry, int *countp) +{ + if (countp == NULL || entry == NULL) { + return SC_ERROR_INVALID_ARGUMENTS; + } + *countp = list_size(list); + list_iterator_start(list); + *entry = list_iterator_next(list); + return SC_SUCCESS; +} + +/* finalize the list iterator */ +static int idprime_final_iterator(list_t *list) +{ + list_iterator_stop(list); + return SC_SUCCESS; +} + +/* fill in the prkey_info for the current object on the list and advance to the next object */ +static int idprime_fill_prkey_info(list_t *list, idprime_object_t **entry, sc_pkcs15_prkey_info_t *prkey_info) +{ + memset(prkey_info, 0, sizeof(sc_pkcs15_prkey_info_t)); + if (*entry == NULL) { + return SC_ERROR_FILE_END_REACHED; + } + + prkey_info->path.len = sizeof((*entry)->df); + memcpy(prkey_info->path.value, (*entry)->df, sizeof((*entry)->df)); + prkey_info->path.type = SC_PATH_TYPE_FILE_ID; + /* Do not specify the length -- it will be read from the FCI */ + prkey_info->path.count = -1; + + /* TODO figure out the IDs as the original driver? */ + prkey_info->id.value[0] = ((*entry)->fd >> 8) & 0xff; + prkey_info->id.value[1] = (*entry)->fd & 0xff; + prkey_info->id.len = 2; + prkey_info->key_reference = (*entry)->key_reference; + *entry = list_iterator_next(list); + return SC_SUCCESS; +} + +#define IDPRIME_CARDID_LEN 16 + +static int idprime_get_serial(sc_card_t* card, sc_serial_number_t* serial) +{ + sc_path_t cardid_path; + sc_file_t *file = NULL; + u8 buf[IDPRIME_CARDID_LEN]; + int r; + + LOG_FUNC_CALLED(card->ctx); + + /* XXX this is assumed to be cardid for windows. It can be read from the index file */ + sc_format_path("0201", &cardid_path); + r = iso_ops->select_file(card, &cardid_path, &file); + if (r != SC_SUCCESS || file->size != IDPRIME_CARDID_LEN) { /* The cardid is always 16 B */ + sc_file_free(file); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH); + } + + r = iso_ops->read_binary(card, 0, buf, file->size, 0); + sc_file_free(file); + if (r < 1) { + LOG_FUNC_RETURN(card->ctx, r); + } else if (r != IDPRIME_CARDID_LEN) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); + } + + serial->len = MIN(IDPRIME_CARDID_LEN, SC_MAX_SERIALNR); + memcpy(serial->value, buf, serial->len); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +static int idprime_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) +{ + idprime_private_data_t * priv = card->drv_data; + + LOG_FUNC_CALLED(card->ctx); + sc_log(card->ctx, "cmd=%ld ptr=%p", cmd, ptr); + + if (priv == NULL) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } + switch (cmd) { + case SC_CARDCTL_GET_SERIALNR: + return idprime_get_serial(card, (sc_serial_number_t *) ptr); + case SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS: + return idprime_get_init_and_get_count(&priv->pki_list, &priv->pki_current, + (int *)ptr); + case SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT: + return idprime_fill_prkey_info(&priv->pki_list, &priv->pki_current, + (sc_pkcs15_prkey_info_t *)ptr); + case SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS: + return idprime_final_iterator(&priv->pki_list); + } + + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); +} + +#define HEADER_LEN 4 + +static int idprime_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out) +{ + int r, len; + idprime_private_data_t * priv = card->drv_data; + u8 data[HEADER_LEN]; + size_t data_len = HEADER_LEN; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + /* forget any old cached values */ + if (priv->cache_buf) { + free(priv->cache_buf); + priv->cache_buf = NULL; + } + priv->cache_buf_len = 0; + priv->cached = 0; + + r = iso_ops->select_file(card, in_path, file_out); + if (r == SC_SUCCESS && priv && file_out != NULL) { + /* Try to read first bytes of the file to fix FCI in case of + * compressed certififcate */ + len = iso_ops->read_binary(card, 0, data, data_len, 0); + if (len == HEADER_LEN && data[0] == 0x01 && data[1] == 0x00) { + /* Cache the real file size for the caching read_binary() */ + priv->file_size = (*file_out)->size; + /* Fix the information in the file structure to not confuse upper layers */ + (*file_out)->size = (data[3]<<8) | data[2]; + } + } + /* Return the exit code of the select command */ + return r; +} + +// used to read existing certificates +static int idprime_read_binary(sc_card_t *card, unsigned int offset, + unsigned char *buf, size_t count, unsigned long flags) +{ + struct idprime_private_data *priv = card->drv_data; + int r; + int size; + + sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at offset %d", + count, offset); + + if (!priv->cached && offset == 0) { + // this function is called to read and uncompress the certificate + u8 buffer[SC_MAX_EXT_APDU_BUFFER_SIZE]; + if (sizeof(buffer) < count) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } + /* Read what was reported by FCI from select command */ + r = iso_ops->read_binary(card, 0, buffer, priv->file_size, flags); + if (r < 0) { + LOG_FUNC_RETURN(card->ctx, r); + } + if (r < 4) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); + } + if (buffer[0] == 1 && buffer[1] == 0) { +#ifdef ENABLE_ZLIB + size_t expectedsize = buffer[2] + buffer[3] * 0x100; + r = sc_decompress_alloc(&priv->cache_buf, &(priv->cache_buf_len), + buffer+4, priv->file_size-4, COMPRESSION_AUTO); + if (r != SC_SUCCESS) { + sc_log(card->ctx, "Zlib error: %d", r); + LOG_FUNC_RETURN(card->ctx, r); + } + if (priv->cache_buf_len != expectedsize) { + sc_log(card->ctx, + "expected size: %"SC_FORMAT_LEN_SIZE_T"u real size: %"SC_FORMAT_LEN_SIZE_T"u", + expectedsize, priv->cache_buf_len); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); + } +#else + sc_log(card->ctx, "compression not supported, no zlib"); + return SC_ERROR_NOT_SUPPORTED; +#endif /* ENABLE_ZLIB */ + } else { + /* assuming uncompressed certificate */ + priv->cache_buf = malloc(r); + if (priv->cache_buf == NULL) { + return SC_ERROR_OUT_OF_MEMORY; + } + memcpy(priv->cache_buf, buffer, r); + priv->cache_buf_len = r; + } + priv->cached = 1; + } + if (offset >= priv->cache_buf_len) { + return 0; + } + size = (int) MIN((priv->cache_buf_len - offset), count); + memcpy(buf, priv->cache_buf + offset, size); + return size; +} + +static int +idprime_set_security_env(struct sc_card *card, + const struct sc_security_env *env, int se_num) +{ + int r; + struct sc_security_env new_env; + + if (card == NULL || env == NULL) { + return SC_ERROR_INVALID_ARGUMENTS; + } + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + /* The card requires algorithm reference here */ + new_env = *env; + new_env.flags |= SC_SEC_ENV_ALG_REF_PRESENT; + /* SHA-1 mechanisms are not allowed in the card I have available */ + switch (env->operation) { + case SC_SEC_OPERATION_DECIPHER: + if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_OAEP) { + if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) { + new_env.algorithm_ref = 0x1D; + } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) { + new_env.algorithm_ref = 0x4D; + } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) { + new_env.algorithm_ref = 0x5D; + } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) { + new_env.algorithm_ref = 0x6D; + } + } else { /* RSA-PKCS without hashing */ + new_env.algorithm_ref = 0x1A; + } + break; + case SC_SEC_OPERATION_SIGN: + if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PSS) { + if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) { + new_env.algorithm_ref = 0x45; + } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) { + new_env.algorithm_ref = 0x55; + } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) { + new_env.algorithm_ref = 0x65; + } + } else { /* RSA-PKCS */ + if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256) { + new_env.algorithm_ref = 0x42; + } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA384) { + new_env.algorithm_ref = 0x52; + } else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA512) { + new_env.algorithm_ref = 0x62; + } else { /* RSA-PKCS without hashing */ + new_env.algorithm_ref = 0x02; + } + } + break; + default: + return SC_ERROR_INVALID_ARGUMENTS; + } + r = iso_ops->set_security_env(card, + (const struct sc_security_env *) &new_env, se_num); + + LOG_FUNC_RETURN(card->ctx, r); +} + +/* These are mostly ISO versions updated to IDPrime specifics */ +static int +idprime_compute_signature(struct sc_card *card, + const u8 * data, size_t datalen, u8 * out, size_t outlen) +{ + int r; + struct sc_apdu apdu; + u8 *p; + u8 sbuf[128]; /* For SHA-512 we need 64 + 2 bytes */ + u8 rbuf[4096]; /* needs work. for 3072 keys, needs 384+2 or so */ + size_t rbuflen = sizeof(rbuf); + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + /* We should be signing hashes only so we should not reach this limit */ + if (datalen + 2 > sizeof(sbuf)) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } + + p = sbuf; + *(p++) = 0x90; + *(p++) = datalen; + memcpy(p, data, datalen); + p += datalen; + + /* INS: 0x2A PERFORM SECURITY OPERATION + * P1: 0x90 Hash code + * P2: 0xA0 Input template for the computation of a hash-code (the template is hashed) */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x90, 0xA0); + apdu.resp = rbuf; + apdu.resplen = rbuflen; + apdu.le = datalen; + + apdu.data = sbuf; + apdu.lc = p - sbuf; + apdu.datalen = p - sbuf; + + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + /* This just returns the passed data (hash code) (for verification?) */ + if (apdu.resplen != datalen || memcmp(rbuf, data, datalen) != 0) { + sc_log(card->ctx, "The initial APDU did not return the same data"); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } + /* INS: 0x2A PERFORM SECURITY OPERATION + * P1: 0x9E Resp: Digital Signature + * P2: 0x9A Cmd: Input for Digital Signature */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x2A, 0x9E, 0x9A); + apdu.resp = out; + apdu.resplen = outlen; + apdu.le = outlen; + if (apdu.le > sc_get_max_recv_size(card)) { + /* The lower layers will automatically do a GET RESPONSE, if possible. + * All other workarounds must be carried out by the upper layers. */ + apdu.le = sc_get_max_recv_size(card); + } + + apdu.data = NULL; + apdu.datalen = 0; + apdu.lc = 0; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) + LOG_FUNC_RETURN(card->ctx, apdu.resplen); + + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + LOG_FUNC_RETURN(card->ctx, r); +} + +/* These are mostly ISO versions updated to IDPrime specifics */ +static int +idprime_decipher(struct sc_card *card, + const u8 * crgram, size_t crgram_len, + u8 * out, size_t outlen) +{ + int r; + struct sc_apdu apdu; + u8 *sbuf = NULL; + + if (card == NULL || crgram == NULL || out == NULL) { + return SC_ERROR_INVALID_ARGUMENTS; + } + LOG_FUNC_CALLED(card->ctx); + sc_log(card->ctx, + "IDPrime decipher: in-len %"SC_FORMAT_LEN_SIZE_T"u, out-len %"SC_FORMAT_LEN_SIZE_T"u", + crgram_len, outlen); + + sbuf = malloc(crgram_len + 1); + if (sbuf == NULL) + return SC_ERROR_OUT_OF_MEMORY; + + /* INS: 0x2A PERFORM SECURITY OPERATION + * P1: 0x80 Resp: Plain value + * P2: 0x86 Cmd: Padding indicator byte followed by cryptogram */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86); + apdu.resp = out; + apdu.resplen = outlen; + apdu.le = outlen; + + sbuf[0] = 0x81; /* padding indicator byte, 0x81 = Proprietary */ + memcpy(sbuf + 1, crgram, crgram_len); + apdu.data = sbuf; + apdu.lc = crgram_len + 1; + if (apdu.lc > sc_get_max_send_size(card)) { + /* The lower layers will automatically do chaining */ + apdu.flags |= SC_APDU_FLAGS_CHAINING; + } + if (apdu.le > sc_get_max_recv_size(card)) { + /* The lower layers will automatically do a GET RESPONSE, if possible. + * All other workarounds must be carried out by the upper layers. */ + apdu.le = sc_get_max_recv_size(card); + } + apdu.datalen = crgram_len + 1; + + r = sc_transmit_apdu(card, &apdu); + sc_mem_clear(sbuf, crgram_len + 1); + free(sbuf); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) + LOG_FUNC_RETURN(card->ctx, apdu.resplen); + else + LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); +} + + +static struct sc_card_driver * sc_get_driver(void) +{ + if (iso_ops == NULL) { + iso_ops = sc_get_iso7816_driver()->ops; + } + + idprime_ops = *iso_ops; + idprime_ops.match_card = idprime_match_card; + idprime_ops.init = idprime_init; + idprime_ops.finish = idprime_finish; + + idprime_ops.read_binary = idprime_read_binary; + idprime_ops.select_file = idprime_select_file; + idprime_ops.card_ctl = idprime_card_ctl; + idprime_ops.set_security_env = idprime_set_security_env; + idprime_ops.compute_signature = idprime_compute_signature; + idprime_ops.decipher = idprime_decipher; + + return &idprime_drv; +} + +struct sc_card_driver * sc_get_idprime_driver(void) +{ + return sc_get_driver(); +} diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index ac196925..bd9833e5 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -303,6 +303,15 @@ enum { SC_CARDCTL_GIDS_INITIALIZE, SC_CARDCTL_GIDS_SET_ADMIN_KEY, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, + + /* + * IDPrime specific calls + */ + SC_CARDCTL_IDPRIME_BASE = _CTL_PREFIX('I', 'D', 'P'), + SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, + SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, + SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, + }; enum { diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index 24d73c09..f13f57ef 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -234,6 +234,7 @@ enum { /* JPKI cards */ SC_CARD_TYPE_JPKI_BASE = 31000, + /* Coolkey cards */ SC_CARD_TYPE_COOLKEY_BASE = 32000, SC_CARD_TYPE_COOLKEY_GENERIC, @@ -258,6 +259,10 @@ enum { SC_CARD_TYPE_RUTOKEN_ECP_SC, SC_CARD_TYPE_RUTOKEN_LITE, SC_CARD_TYPE_RUTOKEN_LITE_SC, + + /* IDPrime cards */ + SC_CARD_TYPE_IDPRIME_BASE = 37000, + SC_CARD_TYPE_IDPRIME_GENERIC, }; extern sc_card_driver_t *sc_get_default_driver(void); @@ -301,6 +306,7 @@ extern sc_card_driver_t *sc_get_cac_driver(void); extern sc_card_driver_t *sc_get_cac1_driver(void); extern sc_card_driver_t *sc_get_npa_driver(void); extern sc_card_driver_t *sc_get_esteid2018_driver(void); +extern sc_card_driver_t *sc_get_idprime_driver(void); #ifdef __cplusplus } diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 40f573ed..4c5adc6e 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -128,6 +128,7 @@ static const struct _sc_driver_entry internal_card_drivers[] = { { "atrust-acos",(void *(*)(void)) sc_get_atrust_acos_driver }, { "westcos", (void *(*)(void)) sc_get_westcos_driver }, { "esteid2018", (void *(*)(void)) sc_get_esteid2018_driver }, + { "idprime", (void *(*)(void)) sc_get_idprime_driver }, /* Here should be placed drivers that need some APDU transactions in the * driver's `match_card()` function. */ diff --git a/src/libopensc/pkcs15-idprime.c b/src/libopensc/pkcs15-idprime.c new file mode 100644 index 00000000..c28b3de8 --- /dev/null +++ b/src/libopensc/pkcs15-idprime.c @@ -0,0 +1,274 @@ +/* + * partial PKCS15 emulation for IDPrime cards. + * + * We can not use the ISO code, since the EF.DIR and EF.ATR for + * object discovery are missing + * + * Copyright (C) 2019, Red Hat, Inc. + * + * Author: Jakub Jelen + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "internal.h" +#include "cardctl.h" +#include "pkcs15.h" + +#define CERT_LABEL_TEMPLATE "Certificate %d" +#define PUBKEY_LABEL_TEMPLATE "Public key %d" +#define PRIVKEY_LABEL_TEMPLATE "Private key %d" + +static int idprime_detect_card(sc_pkcs15_card_t *p15card) +{ + sc_card_t *card = p15card->card; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + if (card->type < SC_CARD_TYPE_IDPRIME_BASE + || card->type >= SC_CARD_TYPE_IDPRIME_BASE+1000) + return SC_ERROR_INVALID_CARD; + return SC_SUCCESS; +} + +static int sc_pkcs15emu_idprime_init(sc_pkcs15_card_t *p15card) +{ + int r, i; + sc_card_t *card = p15card->card; + sc_serial_number_t serial; + char buf[SC_MAX_SERIALNR * 2 + 1]; + int count; + char *token_name = NULL; + struct sc_pkcs15_auth_info pin_info; + struct sc_pkcs15_object pin_obj; + const char pin_label[] = "PIN"; + const char *pin_id = "11"; + + /* oid for key usage */ + static const struct sc_object_id usage_type = {{ 2, 5, 29, 15, -1 }}; + unsigned int usage; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + /* could read this off card if needed */ + p15card->tokeninfo->label = strdup("IDPrime"); + p15card->tokeninfo->manufacturer_id = strdup("Gemalto"); + + /* + * get serial number + */ + memset(&serial, 0, sizeof(serial)); + r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); + if (r < 0) { + sc_log(card->ctx, "sc_card_ctl rc=%d", r); + p15card->tokeninfo->serial_number = strdup("00000000"); + } else { + sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); + p15card->tokeninfo->serial_number = strdup(buf); + } + /* set pin */ + sc_log(card->ctx, "IDPrime adding pin..."); + memset(&pin_info, 0, sizeof(pin_info)); + memset(&pin_obj, 0, sizeof(pin_obj)); + + pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; + sc_pkcs15_format_id(pin_id, &pin_info.auth_id); + pin_info.attrs.pin.reference = 0x11; + pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_INITIALIZED; + pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; + pin_info.attrs.pin.min_length = 4; + pin_info.attrs.pin.stored_length = 8; + pin_info.attrs.pin.max_length = 8; + pin_info.tries_left = -1; + + sc_log(card->ctx, "IDPrime Adding pin with label=%s", pin_label); + strncpy(pin_obj.label, pin_label, SC_PKCS15_MAX_LABEL_SIZE - 1); + pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; + + r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); + if (r < 0) + LOG_FUNC_RETURN(card->ctx, r); + + /* + * certs, pubkeys and priv keys are related and we assume + * they are in order + * We need to read the cert, get modulus and keylen + * We use those for the pubkey, and priv key objects. + */ + sc_log(card->ctx, "IDPrime adding certs, pub and priv keys..."); + r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, &count); + LOG_TEST_RET(card->ctx, r, "Can not initiate cert objects."); + + for (i = 0; i < count; i++) { + struct sc_pkcs15_prkey_info prkey_info; + struct sc_pkcs15_cert_info cert_info; + struct sc_pkcs15_pubkey_info pubkey_info; + struct sc_pkcs15_object cert_obj; + struct sc_pkcs15_object pubkey_obj; + struct sc_pkcs15_object prkey_obj; + sc_pkcs15_der_t cert_der; + sc_pkcs15_cert_t *cert_out = NULL; + + r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, &prkey_info); + LOG_TEST_RET(card->ctx, r, "Can not get next object"); + + memset(&cert_info, 0, sizeof(cert_info)); + memset(&pubkey_info, 0, sizeof(pubkey_info)); + /* prkey_info cleaned by the card_ctl call */ + memset(&cert_obj, 0, sizeof(cert_obj)); + memset(&pubkey_obj, 0, sizeof(pubkey_obj)); + memset(&prkey_obj, 0, sizeof(prkey_obj)); + + cert_info.id = prkey_info.id; + pubkey_info.id = prkey_info.id; + cert_info.path = prkey_info.path; + /* For private keys, we no longer care for the path, just + * the key reference later used in the security environment */ + prkey_info.path.len = 0; + prkey_info.path.aid.len = 0; + pubkey_info.key_reference = prkey_info.key_reference; + sc_log(card->ctx, "Key ref r=%x", prkey_info.key_reference); + + pubkey_info.native = 1; + prkey_info.native = 1; + + snprintf(cert_obj.label, SC_PKCS15_MAX_LABEL_SIZE, CERT_LABEL_TEMPLATE, i+1); + snprintf(pubkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, PUBKEY_LABEL_TEMPLATE, i+1); + snprintf(prkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, PRIVKEY_LABEL_TEMPLATE, i+1); + prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; + sc_pkcs15_format_id(pin_id, &prkey_obj.auth_id); + + r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len); + + if (r) { + sc_log(card->ctx, "No cert found,i=%d", i); + continue; + } + cert_info.path.count = cert_der.len; + + sc_log(card->ctx, + "cert len=%"SC_FORMAT_LEN_SIZE_T"u, cert_info.path.count=%d r=%d\n", + cert_der.len, cert_info.path.count, r); + sc_log_hex(card->ctx, "cert", cert_der.value, cert_der.len); + + /* cache it using the PKCS15 emulation objects */ + /* as it does not change */ + if (cert_der.value) { + cert_info.value.value = cert_der.value; + cert_info.value.len = cert_der.len; + cert_info.path.len = 0; /* use in mem cert from now on */ + } + + /* following will find the cached cert in cert_info */ + r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); + if (r < 0 || cert_out->key == NULL) { + sc_log(card->ctx, "Failed to read/parse the certificate r=%d",r); + if (cert_out != NULL) + sc_pkcs15_free_certificate(cert_out); + free(cert_der.value); + continue; + } + + r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); + if (r < 0) { + sc_log(card->ctx, " Failed to add cert obj r=%d",r); + sc_pkcs15_free_certificate(cert_out); + free(cert_der.value); + 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) { + free(cn_name); + r = SC_ERROR_OUT_OF_MEMORY; + goto fail; + } + memcpy(token_name, cn_name, cn_len); + free(cn_name); + token_name[cn_len] = '\0'; + free(p15card->tokeninfo->label); + p15card->tokeninfo->label = token_name; + } + } + + + r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, cert_out->key, + &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len); + if (r < 0) + goto fail; + pubkey_obj.emulated = cert_out->key; + + r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL); + if (r < 0) { + usage = SC_X509_DATA_ENCIPHERMENT|SC_X509_DIGITAL_SIGNATURE; /* basic default usage */ + } + sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); + sc_log(card->ctx, "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) { + sc_log(card->ctx, "unsupported key.algorithm %d", cert_out->key->algorithm); + sc_pkcs15_free_certificate(cert_out); + continue; + } else { + pubkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; + prkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; + sc_log(card->ctx, "adding rsa public key r=%d usage=%x",r, pubkey_info.usage); + r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); + if (r < 0) + goto fail; + sc_log(card->ctx, "adding rsa private key r=%d usage=%x",r, prkey_info.usage); + r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); + if (r < 0) + goto fail; + } + + cert_out->key = NULL; +fail: + sc_pkcs15_free_certificate(cert_out); + if (r < 0) + LOG_FUNC_RETURN(card->ctx, r); /* should not fail */ + + } + r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, &count); + LOG_TEST_RET(card->ctx, r, "Can not finalize cert objects."); + + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + +int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, + struct sc_aid *aid) +{ + sc_card_t *card = p15card->card; + sc_context_t *ctx = card->ctx; + + LOG_FUNC_CALLED(ctx); + + if (idprime_detect_card(p15card)) + return SC_ERROR_WRONG_CARD; + return sc_pkcs15emu_idprime_init(p15card); +} diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index facb0a60..279a001e 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -43,22 +43,23 @@ struct sc_pkcs15_emulator_handler builtin_emulators[] = { { "itacns", sc_pkcs15emu_itacns_init_ex }, { "PIV-II", sc_pkcs15emu_piv_init_ex }, { "cac", sc_pkcs15emu_cac_init_ex }, + { "idprime", sc_pkcs15emu_idprime_init_ex }, { "gemsafeGPK", sc_pkcs15emu_gemsafeGPK_init_ex }, { "gemsafeV1", sc_pkcs15emu_gemsafeV1_init_ex }, { "actalis", sc_pkcs15emu_actalis_init_ex }, { "atrust-acos",sc_pkcs15emu_atrust_acos_init_ex}, { "tccardos", sc_pkcs15emu_tccardos_init_ex }, - { "entersafe", sc_pkcs15emu_entersafe_init_ex }, + { "entersafe", sc_pkcs15emu_entersafe_init_ex }, { "pteid", sc_pkcs15emu_pteid_init_ex }, { "oberthur", sc_pkcs15emu_oberthur_init_ex }, { "sc-hsm", sc_pkcs15emu_sc_hsm_init_ex }, - { "dnie", sc_pkcs15emu_dnie_init_ex }, - { "gids", sc_pkcs15emu_gids_init_ex }, - { "iasecc", sc_pkcs15emu_iasecc_init_ex }, - { "jpki", sc_pkcs15emu_jpki_init_ex }, + { "dnie", sc_pkcs15emu_dnie_init_ex }, + { "gids", sc_pkcs15emu_gids_init_ex }, + { "iasecc", sc_pkcs15emu_iasecc_init_ex }, + { "jpki", sc_pkcs15emu_jpki_init_ex }, { "coolkey", sc_pkcs15emu_coolkey_init_ex }, - { "din66291", sc_pkcs15emu_din_66291_init_ex }, - { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, + { "din66291", sc_pkcs15emu_din_66291_init_ex }, + { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, { NULL, NULL } }; diff --git a/src/libopensc/pkcs15-syn.h b/src/libopensc/pkcs15-syn.h index 6811b3da..ccaf693c 100644 --- a/src/libopensc/pkcs15-syn.h +++ b/src/libopensc/pkcs15-syn.h @@ -53,6 +53,7 @@ int sc_pkcs15emu_iasecc_init_ex(sc_pkcs15_card_t *, struct sc_aid *); int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *, struct sc_aid *); int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); +int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); struct sc_pkcs15_emulator_handler { const char *name; From 9db15089b80f0690b464bf0b413e979f84ec3804 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 20 Aug 2019 16:26:16 +0200 Subject: [PATCH 010/189] p11test: Avoid memory leaks --- src/tests/p11test/p11test_case_common.c | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/tests/p11test/p11test_case_common.c b/src/tests/p11test/p11test_case_common.c index bd4b39af..22e639cf 100644 --- a/src/tests/p11test/p11test_case_common.c +++ b/src/tests/p11test/p11test_case_common.c @@ -422,7 +422,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, CK_OBJECT_HANDLE object_handle = CK_INVALID_HANDLE; CK_OBJECT_HANDLE_PTR object_handles = NULL; unsigned long i = 0, objects_length = 0; - int j; + int j, ret = -1; /* FindObjects first * https://wiki.oasis-open.org/pkcs11/CommonBugs @@ -439,16 +439,18 @@ int search_objects(test_certs_t *objects, token_info_t *info, break; if (rv != CKR_OK) { fprintf(stderr, "C_FindObjects: rv = 0x%.8lX\n", rv); - return -1; + goto out; } /* store handle */ if (i >= objects_length) { + CK_OBJECT_HANDLE_PTR new_object_handles = NULL; objects_length += 4; // do not realloc after each row - object_handles = realloc(object_handles, objects_length * sizeof(CK_OBJECT_HANDLE)); - if (object_handles == NULL) { + new_object_handles = realloc(object_handles, objects_length * sizeof(CK_OBJECT_HANDLE)); + if (new_object_handles == NULL) { fail_msg("Realloc failed. Need to store object handles.\n"); - return -1; + goto out; } + object_handles = new_object_handles; } object_handles[i++] = object_handle; } @@ -458,8 +460,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, if (rv != CKR_OK) { fprintf(stderr, "C_FindObjectsFinal: rv = 0x%.8lX\n", rv); fail_msg("Could not find certificate.\n"); - free(object_handles); - return -1; + goto out; } for (i = 0; i < objects_length; i++) { @@ -476,8 +477,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, continue; } else if (rv != CKR_OK) { fail_msg("C_GetAttributeValue: rv = 0x%.8lX\n", rv); - free(object_handles); - return -1; + goto out; } /* Allocate memory to hold the data we want */ @@ -487,8 +487,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, template[j].pValue = malloc(template[j].ulValueLen); if (template[j].pValue == NULL) { fail_msg("malloc failed"); - free(object_handles); - return -1; + goto out; } } /* Call again to get actual attribute */ @@ -496,8 +495,7 @@ int search_objects(test_certs_t *objects, token_info_t *info, &(template[j]), 1); if (rv != CKR_OK) { fail_msg("C_GetAttributeValue: rv = 0x%.8lX\n", rv); - free(object_handles); - return -1; + goto out; } } @@ -506,8 +504,10 @@ int search_objects(test_certs_t *objects, token_info_t *info, for (j = 0; j < template_size; j++) free(template[j].pValue); } + ret = 0; +out: free(object_handles); - return 0; + return ret; } void search_for_all_objects(test_certs_t *objects, token_info_t *info) From 48e323985727a95ed17dce26c4c58d85558c26e3 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 27 Aug 2019 10:27:42 +0200 Subject: [PATCH 011/189] pkcs15-cac: Use constants rather than magic numbers --- src/libopensc/pkcs15-cac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-cac.c b/src/libopensc/pkcs15-cac.c index 9616b0ac..e8c13d5f 100644 --- a/src/libopensc/pkcs15-cac.c +++ b/src/libopensc/pkcs15-cac.c @@ -324,7 +324,7 @@ static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL); if (r < 0) { - usage = 0xd9ULL; /* basic default usage */ + usage = SC_X509_DATA_ENCIPHERMENT|SC_X509_DIGITAL_SIGNATURE; /* basic default usage */ } sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); sc_log(card->ctx, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", From fdcc843e786a0a19e8bccfe769e5e94641e1c15e Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 30 Sep 2019 15:01:55 +0200 Subject: [PATCH 012/189] idprime: Implement a way of getting token label from special card structure --- src/libopensc/card-idprime.c | 60 ++++++++++++++++++++++++++++++++++ src/libopensc/cardctl.h | 1 + src/libopensc/pkcs15-idprime.c | 12 +++++++ 3 files changed, 73 insertions(+) diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c index e2c7c616..8608ef50 100644 --- a/src/libopensc/card-idprime.c +++ b/src/libopensc/card-idprime.c @@ -77,6 +77,8 @@ typedef struct idprime_private_data { size_t file_size; /* this is real file size since IDPrime is quite strict about lengths */ list_t pki_list; /* list of pki containers */ idprime_object_t *pki_current; /* current pki object _ctl function */ + int tinfo_present; /* Token Info Label object is present*/ + u8 tinfo_df[2]; /* DF of object with Token Info Label */ } idprime_private_data_t; /* For SimCList autocopy, we need to know the size of the data elements */ @@ -192,6 +194,12 @@ static int idprime_process_index(sc_card_t *card, idprime_private_data_t *priv, sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d", new_object.fd); idprime_add_object_to_list(&priv->pki_list, &new_object); + + /* This looks like non-standard extension listing pkcs11 token info label in my card */ + } else if ((memcmp(&start[4], "tinfo", 6) == 0) && (memcmp(&start[12], "p11", 4) == 0)) { + memcpy(priv->tinfo_df, new_object.df, sizeof(priv->tinfo_df)); + priv->tinfo_present = 1; + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found p11/tinfo object"); } } r = SC_SUCCESS; @@ -343,6 +351,56 @@ static int idprime_get_serial(sc_card_t* card, sc_serial_number_t* serial) LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } +static int idprime_get_token_name(sc_card_t* card, char** tname) +{ + idprime_private_data_t * priv = card->drv_data; + sc_path_t tinfo_path = {"\x00\x00", 2, 0, 0, SC_PATH_TYPE_PATH, {"", 0}}; + sc_file_t *file = NULL; + u8 buf[2]; + int r; + + LOG_FUNC_CALLED(card->ctx); + + if (tname == NULL) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); + } + + if (!priv->tinfo_present) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); + } + + memcpy(tinfo_path.value, priv->tinfo_df, 2); + r = iso_ops->select_file(card, &tinfo_path, &file); + if (r != SC_SUCCESS || file->size == 0) { + sc_file_free(file); + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); + } + + /* First two bytes lists 0x01, the second indicates length */ + r = iso_ops->read_binary(card, 0, buf, 2, 0); + if (r < 2 || buf[1] > file->size) { /* make sure we do not overrun */ + sc_file_free(file); + LOG_FUNC_RETURN(card->ctx, r); + } + sc_file_free(file); + + *tname = malloc(buf[1]); + if (*tname == NULL) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + } + + r = iso_ops->read_binary(card, 2, (unsigned char *)*tname, buf[1], 0); + if (r < 1) { + free(*tname); + LOG_FUNC_RETURN(card->ctx, r); + } + + if ((*tname)[r-1] != '\0') { + (*tname)[r-1] = '\0'; + } + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); +} + static int idprime_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) { idprime_private_data_t * priv = card->drv_data; @@ -356,6 +414,8 @@ static int idprime_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) switch (cmd) { case SC_CARDCTL_GET_SERIALNR: return idprime_get_serial(card, (sc_serial_number_t *) ptr); + case SC_CARDCTL_IDPRIME_GET_TOKEN_NAME: + return idprime_get_token_name(card, (char **) ptr); case SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS: return idprime_get_init_and_get_count(&priv->pki_list, &priv->pki_current, (int *)ptr); diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index bd9833e5..7bba7e66 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -311,6 +311,7 @@ enum { SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, + SC_CARDCTL_IDPRIME_GET_TOKEN_NAME, }; diff --git a/src/libopensc/pkcs15-idprime.c b/src/libopensc/pkcs15-idprime.c index c28b3de8..785cf16a 100644 --- a/src/libopensc/pkcs15-idprime.c +++ b/src/libopensc/pkcs15-idprime.c @@ -106,6 +106,18 @@ static int sc_pkcs15emu_idprime_init(sc_pkcs15_card_t *p15card) if (r < 0) LOG_FUNC_RETURN(card->ctx, r); + /* + * get token name if provided + */ + r = sc_card_ctl(card, SC_CARDCTL_IDPRIME_GET_TOKEN_NAME, &token_name); + if (r < 0) { + /* On failure we will get the token name from certificates later */ + sc_log(card->ctx, "sc_card_ctl rc=%d", r); + } else { + free(p15card->tokeninfo->label); + p15card->tokeninfo->label = token_name; + sc_log(card->ctx, "IDPrime setting token label = %s", token_name); + } /* * certs, pubkeys and priv keys are related and we assume * they are in order From 2c9510af1e116cb1c53e36278736dc7a1f64deae Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 30 Sep 2019 15:09:36 +0200 Subject: [PATCH 013/189] Improve parsing of the root file and store also the object length --- src/libopensc/card-idprime.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c index 8608ef50..24934e43 100644 --- a/src/libopensc/card-idprime.c +++ b/src/libopensc/card-idprime.c @@ -65,6 +65,7 @@ typedef struct idprime_object { int fd; unsigned char key_reference; u8 df[2]; + unsigned short length; } idprime_object_t; /* @@ -183,11 +184,13 @@ static int idprime_process_index(sc_card_t *card, idprime_private_data_t *priv, /* First two bytes specify the object DF */ new_object.df[0] = start[0]; new_object.df[1] = start[1]; - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "df=%s", - sc_dump_hex(new_object.df, sizeof(new_object.df))); - /* I assume this is some identification of certificate */ - if (start[4] == 0x6B && start[5] == 0x78 && start[6] == 0x63 - && start[7] == 0x30) { + /* Second two bytes refer to the object size */ + new_object.length = bebytes2ushort(&start[2]); + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "df=%s, len=%u", + sc_dump_hex(new_object.df, sizeof(new_object.df)), new_object.length); + /* in minidriver, mscp/kxcNN or kscNN lists certificates */ + if (((memcmp(&start[4], "ksc", 3) == 0) || memcmp(&start[4], "kxc", 3) == 0) + && (memcmp(&start[12], "mscp", 5) == 0)) { new_object.fd++; /* The key reference is one bigger than the value found here for some reason */ new_object.key_reference = start[8] + 1; From 5017768e5b08ab0904ad15f1b92e86318c35d1f8 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 30 Sep 2019 18:06:45 +0200 Subject: [PATCH 014/189] idprime: Detect the newer version of OS using CPLC data --- src/libopensc/card-idprime.c | 50 ++++++++++++++++++++++++++++++++---- src/libopensc/cards.h | 2 ++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c index 24934e43..bf158e64 100644 --- a/src/libopensc/card-idprime.c +++ b/src/libopensc/card-idprime.c @@ -192,10 +192,15 @@ static int idprime_process_index(sc_card_t *card, idprime_private_data_t *priv, if (((memcmp(&start[4], "ksc", 3) == 0) || memcmp(&start[4], "kxc", 3) == 0) && (memcmp(&start[12], "mscp", 5) == 0)) { new_object.fd++; - /* The key reference is one bigger than the value found here for some reason */ - new_object.key_reference = start[8] + 1; - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d", - new_object.fd); + if (card->type == SC_CARD_TYPE_IDPRIME_V2) { + /* The key reference starts from 0x11 */ + new_object.key_reference = 0x10 + new_object.fd; + } else { + /* The key reference is one bigger than the value found here for some reason */ + new_object.key_reference = start[8] + 1; + } + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Found certificate with fd=%d, key_ref=%d", + new_object.fd, new_object.key_reference); idprime_add_object_to_list(&priv->pki_list, &new_object); /* This looks like non-standard extension listing pkcs11 token info label in my card */ @@ -211,12 +216,46 @@ done: LOG_FUNC_RETURN(card->ctx, r); } +/* CPLC has 42 bytes, but we get it with 3B header */ +#define CPLC_LENGTH 45 static int idprime_init(sc_card_t *card) { int r; unsigned long flags; idprime_private_data_t *priv = NULL; + struct sc_apdu apdu; + u8 rbuf[CPLC_LENGTH]; + size_t rbuflen = sizeof(rbuf); + /* We need to differentiate the OS version since they behave slightly differently */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xCA, 0x9F, 0x7F); + apdu.resp = rbuf; + apdu.resplen = rbuflen; + apdu.le = rbuflen; + r = sc_transmit_apdu(card, &apdu); + card->type = SC_CARD_TYPE_IDPRIME_GENERIC; + if (r == SC_SUCCESS && apdu.resplen == CPLC_LENGTH) { + /* We are interested in the OS release level here */ + switch (rbuf[11]) { + case 0x01: + card->type = SC_CARD_TYPE_IDPRIME_V1; + sc_log(card->ctx, "Detected IDPrime applet version 1"); + break; + case 0x02: + card->type = SC_CARD_TYPE_IDPRIME_V2; + sc_log(card->ctx, "Detected IDPrime applet version 2"); + break; + default: + sc_log(card->ctx, "Unknown OS version received: %d", rbuf[11]); + break; + } + } else { + sc_log(card->ctx, "Failed to get CPLC data or invalid length returned, " + "err=%d, len=%"SC_FORMAT_LEN_SIZE_T"u", + r, apdu.resplen); + } + + /* Now, select and process the index file */ r = idprime_select_index(card); if (r <= 0) { LOG_FUNC_RETURN(card->ctx, r); @@ -228,12 +267,13 @@ static int idprime_init(sc_card_t *card) if (!priv) { return SC_ERROR_OUT_OF_MEMORY; } + r = idprime_process_index(card, priv, r); if (r != SC_SUCCESS) { idprime_free_private_data(priv); LOG_FUNC_RETURN(card->ctx, r); } - card->type = SC_CARD_TYPE_IDPRIME_GENERIC; + card->drv_data = priv; card->name = "Gemalto IDPrime"; diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index f13f57ef..cb0501c3 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -262,6 +262,8 @@ enum { /* IDPrime cards */ SC_CARD_TYPE_IDPRIME_BASE = 37000, + SC_CARD_TYPE_IDPRIME_V1, + SC_CARD_TYPE_IDPRIME_V2, SC_CARD_TYPE_IDPRIME_GENERIC, }; From fe8f6297f08d55bedea22d0c54161dd1cb5b8a70 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 14 Nov 2019 09:36:16 +0100 Subject: [PATCH 015/189] idprime: Add support for longer PINs --- src/libopensc/pkcs15-idprime.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/pkcs15-idprime.c b/src/libopensc/pkcs15-idprime.c index 785cf16a..d8826969 100644 --- a/src/libopensc/pkcs15-idprime.c +++ b/src/libopensc/pkcs15-idprime.c @@ -94,8 +94,8 @@ static int sc_pkcs15emu_idprime_init(sc_pkcs15_card_t *p15card) pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_INITIALIZED; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = 4; - pin_info.attrs.pin.stored_length = 8; - pin_info.attrs.pin.max_length = 8; + pin_info.attrs.pin.stored_length = 0; + pin_info.attrs.pin.max_length = 16; pin_info.tries_left = -1; sc_log(card->ctx, "IDPrime Adding pin with label=%s", pin_label); From 3537cbbc78fd780cc39f59cddb77cc99ee2d726f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 22 Nov 2019 17:59:09 +0100 Subject: [PATCH 016/189] Unbreak RSA-PSS padding --- src/libopensc/opensc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index ebadb4c2..10bea0a0 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -107,7 +107,7 @@ extern "C" { * must support at least one of them, and exactly one of them must be selected * for a given operation. */ #define SC_ALGORITHM_RSA_RAW 0x00000001 -#define SC_ALGORITHM_RSA_PADS 0x0000002F +#define SC_ALGORITHM_RSA_PADS 0x0000003F #define SC_ALGORITHM_RSA_PAD_NONE 0x00000001 #define SC_ALGORITHM_RSA_PAD_PKCS1 0x00000002 /* PKCS#1 v1.5 padding */ #define SC_ALGORITHM_RSA_PAD_ANSI 0x00000004 From bebb5be6e028eb43af2e328a784916b1661a0e3b Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 7 Jan 2020 11:04:09 +0100 Subject: [PATCH 017/189] idprime: Simplify applet selection and limit file size to sensible values --- src/libopensc/card-idprime.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c index bf158e64..c2822cc6 100644 --- a/src/libopensc/card-idprime.c +++ b/src/libopensc/card-idprime.c @@ -144,12 +144,14 @@ static int idprime_select_index(sc_card_t *card) /* Returns FCI with expected length of data */ sc_format_path("0101", &index_path); r = iso_ops->select_file(card, &index_path, &file); - if (r != SC_SUCCESS) { - sc_file_free(file); - LOG_FUNC_RETURN(card->ctx, r); + if (r == SC_SUCCESS) { + r = file->size; } - r = file->size; sc_file_free(file); + /* Ignore too large files */ + if (r > MAX_FILE_SIZE) { + r = SC_ERROR_INVALID_DATA; + } return r; } From 8e8c3735bcc2cd10554fa8b89492423d093bcae0 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 7 Jan 2020 12:48:21 +0100 Subject: [PATCH 018/189] idprime: Reflect the OS version in the card name --- src/libopensc/card-idprime.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c index c2822cc6..7399830a 100644 --- a/src/libopensc/card-idprime.c +++ b/src/libopensc/card-idprime.c @@ -278,7 +278,18 @@ static int idprime_init(sc_card_t *card) card->drv_data = priv; - card->name = "Gemalto IDPrime"; + switch (card->type) { + case SC_CARD_TYPE_IDPRIME_V1: + card->name = "Gemalto IDPrime (OSv1)"; + break; + case SC_CARD_TYPE_IDPRIME_V2: + card->name = "Gemalto IDPrime (OSv2)"; + break; + case SC_CARD_TYPE_IDPRIME_GENERIC: + default: + card->name = "Gemalto IDPrime (generic)"; + break; + } card->cla = 0x00; /* Set up algorithm info. */ From a9873b87ddb19056119ba3abb3de515b97e669fc Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 26 Jan 2020 09:27:16 +0100 Subject: [PATCH 019/189] openpgp-tool: force use of 'openpgp' driver Follow the example of other card-specific tools and explicitly force the use of the correct driver, and fail if it cannot be set. --- src/tools/openpgp-tool.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index 63db8b49..6aad107c 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -878,6 +878,14 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + /* force OpenPGP card driver */ + r = sc_set_card_driver(ctx, "openpgp"); + if (r) { + sc_release_context(ctx); + util_fatal("OpenPGP card driver not found!\n"); + return EXIT_FAILURE; + } + r = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose); if (r) { sc_release_context(ctx); From 7ef40cdc1758e7b7282d83f495d8810c6f178a51 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 26 Jan 2020 09:30:35 +0100 Subject: [PATCH 020/189] openpgp-tool: update copyright --- src/tools/openpgp-tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index 6aad107c..f5665949 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -1,7 +1,7 @@ /* * openpgp-tool.c: OpenPGP card utility * - * Copyright (C) 2012 Peter Marschall + * Copyright (C) 2012-2020 Peter Marschall * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -194,7 +194,7 @@ static void show_version(void) fprintf(stderr, "openpgp-tool - OpenPGP card utility version " PACKAGE_VERSION "\n" "\n" - "Copyright (c) 2012-18 Peter Marschall \n" + "Copyright (c) 2012-2020 Peter Marschall \n" "Licensed under LGPL v2\n"); } From cd4dc5a9e7de69c1bdcaeca0ebd2924caf239ef5 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 26 Jan 2020 10:56:03 +0100 Subject: [PATCH 021/189] OpenPGP: refactor definitions into header file Factor out constants and structure definitions into a header file so that they can be also used consistently in openpgp-tool. --- src/libopensc/Makefile.am | 3 +- src/libopensc/card-openpgp.c | 216 ++++++----------------------------- src/libopensc/card-openpgp.h | 192 +++++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+), 184 deletions(-) create mode 100644 src/libopensc/card-openpgp.h diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 49d12268..2d7b4c95 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -12,7 +12,8 @@ noinst_HEADERS = cards.h ctbcs.h internal.h muscle.h muscle-filesystem.h \ errors.h types.h compression.h itacns.h iso7816.h \ authentic.h iasecc.h iasecc-sdo.h sm.h card-sc-hsm.h \ pace.h cwa14890.h cwa-dnie.h card-gids.h aux-data.h \ - jpki.h sc-ossl-compat.h card-npa.h ccid-types.h reader-tr03119.h \ + jpki.h sc-ossl-compat.h card-npa.h card-openpgp.h \ + ccid-types.h reader-tr03119.h \ card-cac-common.h AM_CPPFLAGS = -D'OPENSC_CONF_PATH="$(sysconfdir)/opensc.conf"' \ diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 35230ac5..2ca29a9f 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -52,11 +52,15 @@ #include #endif /* ENABLE_OPENSSL */ +#include "card-openpgp.h" + + static const char default_cardname[] = "OpenPGP card"; static const char default_cardname_v1[] = "OpenPGP card v1.x"; static const char default_cardname_v2[] = "OpenPGP card v2.x"; static const char default_cardname_v3[] = "OpenPGP card v3.x"; + static const struct sc_atr_table pgp_atrs[] = { { "3b:fa:13:00:ff:81:31:80:45:00:31:c1:73:c0:01:00:00:90:00:b1", NULL, default_cardname_v1, SC_CARD_TYPE_OPENPGP_V1, 0, NULL }, { "3b:da:18:ff:81:b1:fe:75:1f:03:00:31:c5:73:c0:01:40:00:90:00:0c", NULL, default_cardname_v2, SC_CARD_TYPE_OPENPGP_V2, 0, NULL }, @@ -72,6 +76,7 @@ static const struct sc_atr_table pgp_atrs[] = { { NULL, NULL, NULL, 0, 0, NULL } }; + static struct sc_card_operations *iso_ops; static struct sc_card_operations pgp_ops; static struct sc_card_driver pgp_drv = { @@ -81,84 +86,8 @@ static struct sc_card_driver pgp_drv = { NULL, 0, NULL }; -/* - * The OpenPGP card doesn't have a file system, instead everything - * is stored in data objects that are accessed through GET/PUT. - * - * However, much inside OpenSC's pkcs15 implementation is based on - * the assumption that we have a file system. So we fake one here. - * - * Selecting the MF causes us to select the OpenPGP AID. - * - * Everything else is mapped to "file" IDs. - */ -enum _type { /* DO type */ - SIMPLE = SC_FILE_TYPE_WORKING_EF, - CONSTRUCTED = SC_FILE_TYPE_DF -}; - -enum _version { /* 2-byte BCD-alike encoded version number */ - OPENPGP_CARD_1_0 = 0x0100, - OPENPGP_CARD_1_1 = 0x0101, - OPENPGP_CARD_2_0 = 0x0200, - OPENPGP_CARD_2_1 = 0x0201, - OPENPGP_CARD_2_2 = 0x0202, - OPENPGP_CARD_3_0 = 0x0300, - OPENPGP_CARD_3_1 = 0x0301, - OPENPGP_CARD_3_2 = 0x0302, - OPENPGP_CARD_3_3 = 0x0303, - OPENPGP_CARD_3_4 = 0x0304, -}; - -enum _access { /* access flags for the respective DO/file */ - READ_NEVER = 0x0010, - READ_PIN1 = 0x0011, - READ_PIN2 = 0x0012, - READ_PIN3 = 0x0014, - READ_ALWAYS = 0x0018, - READ_MASK = 0x00FF, - WRITE_NEVER = 0x1000, - WRITE_PIN1 = 0x1100, - WRITE_PIN2 = 0x1200, - WRITE_PIN3 = 0x1400, - WRITE_ALWAYS = 0x1800, - WRITE_MASK = 0x1F00 -}; - -enum _ext_caps { /* extended capabilities/features: bit flags */ - EXT_CAP_ALG_ATTR_CHANGEABLE = 0x0004, - EXT_CAP_PRIVATE_DO = 0x0008, - EXT_CAP_C4_CHANGEABLE = 0x0010, - EXT_CAP_KEY_IMPORT = 0x0020, - EXT_CAP_GET_CHALLENGE = 0x0040, - EXT_CAP_SM = 0x0080, - EXT_CAP_LCS = 0x0100, - EXT_CAP_CHAINING = 0x1000, - EXT_CAP_APDU_EXT = 0x2000, - EXT_CAP_MSE = 0x4000 -}; - -enum _card_state { - CARD_STATE_UNKNOWN = 0x00, - CARD_STATE_INITIALIZATION = 0x03, - CARD_STATE_ACTIVATED = 0x05 -}; - -enum _sm_algo { - SM_ALGO_NONE = 0, /* SM not supported */ - SM_ALGO_AES128 = 1, - SM_ALGO_AES256 = 2, - SM_ALGO_SCP11b = 3, - SM_ALGO_3DES = 256, /* 2.x: coded as 0 in DO C0 */ - SM_ALGO_UNKNOWN = 257 /* 3.x: coded as 0 in DO C0 */ -}; - -static struct pgp_supported_ec_curves { - struct sc_object_id oid; - size_t size; - struct sc_object_id oid_binary; -} ec_curves[] = { +static pgp_ec_curves_t ec_curves[] = { {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, {{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, -1}}}, /* ansiX9p256r1 */ {{{1, 3, 132, 0, 34, -1}}, 384, @@ -174,11 +103,7 @@ static struct pgp_supported_ec_curves { {{{-1}}, 0, {{0x0}}} /* This entry must not be touched. */ }; -static struct pgp_supported_ec_curves_gnuk { - struct sc_object_id oid; - size_t size; - struct sc_object_id oid_binary; -} ec_curves_gnuk[] = { +static pgp_ec_curves_t ec_curves_gnuk[] = { {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, {{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, -1}}}, /* ansiX9p256r1 */ {{{1, 3, 132, 0, 10, -1}}, 256, @@ -190,33 +115,18 @@ static struct pgp_supported_ec_curves_gnuk { {{{-1}}, 0, {{0x0}}} /* This entry must not be touched. */ }; -typedef struct pgp_blob { - struct pgp_blob * next; /* pointer to next sibling */ - struct pgp_blob * parent; /* pointer to parent */ - struct do_info *info; - sc_file_t * file; - unsigned int id; - int status; - - unsigned char * data; - unsigned int len; - struct pgp_blob * files; /* pointer to 1st child */ -} pgp_blob_t; - -struct do_info { - unsigned int id; /* ID of the DO in question */ - - enum _type type; /* constructed DO or not */ - enum _access access; /* R/W access levels for the DO */ - - /* function to get the DO from the card: - * only != NULL is DO if readable and not only a part of a constructed DO */ - int (*get_fn)(sc_card_t *, unsigned int, u8 *, size_t); - /* function to write the DO to the card: - * only != NULL if DO is writeable under some conditions */ - int (*put_fn)(sc_card_t *, unsigned int, const u8 *, size_t); -}; +/* + * The OpenPGP card doesn't have a file system, instead everything + * is stored in data objects that are accessed through GET/PUT. + * + * However, much inside OpenSC's pkcs15 implementation is based on + * the assumption that we have a file system. So we fake one here. + * + * Selecting the MF causes us to select the OpenPGP AID. + * + * Everything else is mapped to "file" IDs. + */ static int pgp_get_card_features(sc_card_t *card); static int pgp_finish(sc_card_t *card); @@ -224,50 +134,13 @@ static void pgp_iterate_blobs(pgp_blob_t *, int, void (*func)()); static int pgp_get_blob(sc_card_t *card, pgp_blob_t *blob, unsigned int id, pgp_blob_t **ret); -static pgp_blob_t * pgp_new_blob(sc_card_t *, pgp_blob_t *, unsigned int, sc_file_t *); +static pgp_blob_t *pgp_new_blob(sc_card_t *, pgp_blob_t *, unsigned int, sc_file_t *); static void pgp_free_blob(pgp_blob_t *); -static int pgp_get_pubkey(sc_card_t *, unsigned int, - u8 *, size_t); -static int pgp_get_pubkey_pem(sc_card_t *, unsigned int, - u8 *, size_t); - -/* The DO holding X.509 certificate is constructed but does not contain a child DO. - * We should notice this when building fake file system later. */ -#define DO_CERT 0x7f21 -/* Control Reference Template of private keys. Ref: Section 4.3.3.7 of OpenPGP card v2 spec. - * Here we treat them as DOs just for convenience */ -#define DO_SIGN 0xb600 -#define DO_ENCR 0xb800 -#define DO_AUTH 0xa400 -/* These DOs do not exist. They are defined and used just for ease of implementation */ -#define DO_SIGN_SYM 0xb601 -#define DO_ENCR_SYM 0xb801 -#define DO_AUTH_SYM 0xa401 -/* Private DOs */ -#define DO_PRIV1 0x0101 -#define DO_PRIV2 0x0102 -#define DO_PRIV3 0x0103 -#define DO_PRIV4 0x0104 -/* Cardholder information DOs */ -#define DO_CARDHOLDER 0x65 -#define DO_NAME 0x5b -#define DO_LANG_PREF 0x5f2d -#define DO_SEX 0x5f35 +static int pgp_get_pubkey(sc_card_t *, unsigned int, u8 *, size_t); +static int pgp_get_pubkey_pem(sc_card_t *, unsigned int, u8 *, size_t); -/* Maximum length for response buffer when reading pubkey. - * This value is calculated with 4096-bit key length */ -#define MAXLEN_RESP_PUBKEY 527 -/* Gnuk only supports 1 key length (2048 bit) */ -#define MAXLEN_RESP_PUBKEY_GNUK 271 - -/* Maximal size of a DO: - * v2.0+: max. certificate size it at bytes 5-6 of Extended Capabilities DO 00C0 - * v3.0+: max. special DO size is at bytes 7-8 of Extended Capabilities DO 00C0 - * Theoretically we should have the 64k, but we currently limit to 8k. */ -#define MAX_OPENPGP_DO_SIZE 8192 - -static struct do_info pgp1x_objects[] = { /* OpenPGP card spec 1.1 */ +static pgp_do_info_t pgp1x_objects[] = { /* OpenPGP card spec 1.1 */ { 0x004f, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL }, { 0x005b, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data }, { 0x005e, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data }, @@ -316,7 +189,7 @@ static struct do_info pgp1x_objects[] = { /* OpenPGP card spec 1.1 */ { 0, 0, 0, NULL, NULL }, }; -static struct do_info pgp34_objects[] = { /**** OpenPGP card spec 3.4 ****/ +static pgp_do_info_t pgp34_objects[] = { /**** OpenPGP card spec 3.4 ****/ { 0x00d9, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data }, { 0x00da, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data }, { 0x00db, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data }, @@ -400,31 +273,10 @@ static struct do_info pgp34_objects[] = { /**** OpenPGP card spec 3.4 ****/ { 0, 0, 0, NULL, NULL }, }; -static struct do_info *pgp33_objects = pgp34_objects + 9; -static struct do_info *pgp30_objects = pgp34_objects + 10; -static struct do_info *pgp21_objects = pgp34_objects + 15; -static struct do_info *pgp20_objects = pgp34_objects + 16; - - -#define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data)) - -struct pgp_priv_data { - pgp_blob_t *mf; - pgp_blob_t *current; /* currently selected file */ - - enum _version bcd_version; - struct do_info *pgp_objects; - - enum _card_state state; /* card state */ - enum _ext_caps ext_caps; /* extended capabilities */ - - enum _sm_algo sm_algo; /* Secure Messaging algorithm */ - - size_t max_challenge_size; - size_t max_cert_size; - - sc_security_env_t sec_env; -}; +static pgp_do_info_t *pgp33_objects = pgp34_objects + 9; +static pgp_do_info_t *pgp30_objects = pgp34_objects + 10; +static pgp_do_info_t *pgp21_objects = pgp34_objects + 15; +static pgp_do_info_t *pgp20_objects = pgp34_objects + 16; /** @@ -445,8 +297,6 @@ get_full_pgp_aid(sc_card_t *card, sc_file_t *file) } -#define BCD2UCHAR(x) (((((x) & 0xF0) >> 4) * 10) + ((x) & 0x0F)) - /** * ABI: check if card's ATR matches one of driver's * or if the OpenPGP application is present on the card. @@ -515,7 +365,7 @@ pgp_init(sc_card_t *card) struct pgp_priv_data *priv; sc_path_t path; sc_file_t *file = NULL; - struct do_info *info; + pgp_do_info_t *info; int r, i; LOG_FUNC_CALLED(card->ctx); @@ -1019,7 +869,7 @@ pgp_set_blob(pgp_blob_t *blob, const u8 *data, size_t len) * The Access Control is derived from the DO access permission. **/ static void -pgp_attach_acl(sc_card_t *card, sc_file_t *file, struct do_info *info) +pgp_attach_acl(sc_card_t *card, sc_file_t *file, pgp_do_info_t *info) { unsigned int method = SC_AC_NONE; unsigned long key_ref = SC_AC_KEY_REF_NONE; @@ -1096,7 +946,7 @@ pgp_new_blob(sc_card_t *card, pgp_blob_t *parent, unsigned int file_id, if ((blob = calloc(1, sizeof(pgp_blob_t))) != NULL) { struct pgp_priv_data *priv = DRVDATA(card); - struct do_info *info; + pgp_do_info_t *info; blob->file = file; @@ -1406,11 +1256,11 @@ pgp_find_blob(sc_card_t *card, unsigned int tag) /** * Internal: get info for a specific tag. */ -static struct do_info * +static pgp_do_info_t * pgp_get_info_by_tag(sc_card_t *card, unsigned int tag) { struct pgp_priv_data *priv = DRVDATA(card); - struct do_info *info; + pgp_do_info_t *info; for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++) if (tag == info->id) @@ -1876,7 +1726,7 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len) { struct pgp_priv_data *priv = DRVDATA(card); pgp_blob_t *affected_blob = NULL; - struct do_info *dinfo = NULL; + pgp_do_info_t *dinfo = NULL; int r; LOG_FUNC_CALLED(card->ctx); diff --git a/src/libopensc/card-openpgp.h b/src/libopensc/card-openpgp.h new file mode 100644 index 00000000..f13e3be6 --- /dev/null +++ b/src/libopensc/card-openpgp.h @@ -0,0 +1,192 @@ +/* + * card-openpgp.h: Support for OpenPGP card + * + * Copyright (C) 2020 Peter Marschall + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CARD_OPENPGP_H +#define _CARD_OPENPGP_H + +/* + * The OpenPGP card doesn't have a file system, instead everything + * is stored in data objects that are accessed through GET/PUT. + * + * However, much inside OpenSC's pkcs15 implementation is based on + * the assumption that we have a file system. So we fake one here. + * + * Selecting the MF causes us to select the OpenPGP AID. + * + * Everything else is mapped to "file" IDs. + */ + +typedef enum _pgp_do_type { /* DO type */ + SIMPLE = SC_FILE_TYPE_WORKING_EF, + CONSTRUCTED = SC_FILE_TYPE_DF +} pgp_do_type_t; + +typedef enum _pgp_version { /* 2-byte BCD-alike encoded version number */ + OPENPGP_CARD_1_0 = 0x0100, + OPENPGP_CARD_1_1 = 0x0101, + OPENPGP_CARD_2_0 = 0x0200, + OPENPGP_CARD_2_1 = 0x0201, + OPENPGP_CARD_2_2 = 0x0202, + OPENPGP_CARD_3_0 = 0x0300, + OPENPGP_CARD_3_1 = 0x0301, + OPENPGP_CARD_3_2 = 0x0302, + OPENPGP_CARD_3_3 = 0x0303, + OPENPGP_CARD_3_4 = 0x0304, +} pgp_version_t; + +typedef enum _pgp_access { /* access flags for the respective DO/file */ + READ_NEVER = 0x0010, + READ_PIN1 = 0x0011, + READ_PIN2 = 0x0012, + READ_PIN3 = 0x0014, + READ_ALWAYS = 0x0018, + READ_MASK = 0x00FF, + WRITE_NEVER = 0x1000, + WRITE_PIN1 = 0x1100, + WRITE_PIN2 = 0x1200, + WRITE_PIN3 = 0x1400, + WRITE_ALWAYS = 0x1800, + WRITE_MASK = 0x1F00 +} pgp_access_t; + +typedef enum _pgp_ext_caps { /* extended capabilities/features: bit flags */ + EXT_CAP_ALG_ATTR_CHANGEABLE = 0x0004, + EXT_CAP_PRIVATE_DO = 0x0008, + EXT_CAP_C4_CHANGEABLE = 0x0010, + EXT_CAP_KEY_IMPORT = 0x0020, + EXT_CAP_GET_CHALLENGE = 0x0040, + EXT_CAP_SM = 0x0080, + EXT_CAP_LCS = 0x0100, + EXT_CAP_CHAINING = 0x1000, + EXT_CAP_APDU_EXT = 0x2000, + EXT_CAP_MSE = 0x4000 +} pgp_ext_caps_t; + +typedef enum _pgp_card_state { + CARD_STATE_UNKNOWN = 0x00, + CARD_STATE_INITIALIZATION = 0x03, + CARD_STATE_ACTIVATED = 0x05 +} pgp_card_state_t; + +typedef enum _pgp_sm_algo { + SM_ALGO_NONE = 0, /* SM not supported */ + SM_ALGO_AES128 = 1, + SM_ALGO_AES256 = 2, + SM_ALGO_SCP11b = 3, + SM_ALGO_3DES = 256, /* 2.x: coded as 0 in DO C0 */ + SM_ALGO_UNKNOWN = 257 /* 3.x: coded as 0 in DO C0 */ +} pgp_sm_algo_t; + +typedef struct _pgp_do_info { + unsigned int id; /* ID of the DO in question */ + + pgp_do_type_t type; /* constructed DO or not */ + pgp_access_t access; /* R/W access levels for the DO */ + + /* function to get the DO from the card: + * only != NULL is DO if readable and not only a part of a constructed DO */ + int (*get_fn)(sc_card_t *, unsigned int, u8 *, size_t); + /* function to write the DO to the card: + * only != NULL if DO is writeable under some conditions */ + int (*put_fn)(sc_card_t *, unsigned int, const u8 *, size_t); +} pgp_do_info_t; + +typedef struct pgp_blob { + struct pgp_blob *next; /* pointer to next sibling */ + struct pgp_blob *parent; /* pointer to parent */ + pgp_do_info_t *info; + + sc_file_t *file; + unsigned int id; + int status; + + unsigned char *data; + unsigned int len; + struct pgp_blob *files; /* pointer to 1st child */ +} pgp_blob_t; + + +/* The DO holding X.509 certificate is constructed but does not contain a child DO. + * We should notice this when building fake file system later. */ +#define DO_CERT 0x7f21 +/* Control Reference Template of private keys. Ref: Section 4.3.3.7 of OpenPGP card v2 spec. + * Here we treat them as DOs just for convenience */ +#define DO_SIGN 0xb600 +#define DO_ENCR 0xb800 +#define DO_AUTH 0xa400 +/* These DOs do not exist. They are defined and used just for ease of implementation */ +#define DO_SIGN_SYM 0xb601 +#define DO_ENCR_SYM 0xb801 +#define DO_AUTH_SYM 0xa401 +/* Private DOs */ +#define DO_PRIV1 0x0101 +#define DO_PRIV2 0x0102 +#define DO_PRIV3 0x0103 +#define DO_PRIV4 0x0104 +/* Cardholder information DOs */ +#define DO_CARDHOLDER 0x65 +#define DO_NAME 0x5b +#define DO_LANG_PREF 0x5f2d +#define DO_SEX 0x5f35 + + +/* Maximum length for response buffer when reading pubkey. + * This value is calculated with 4096-bit key length */ +#define MAXLEN_RESP_PUBKEY 527 +/* Gnuk only supports 1 key length (2048 bit) */ +#define MAXLEN_RESP_PUBKEY_GNUK 271 + +/* Maximal size of a DO: + * v2.0+: max. certificate size it at bytes 5-6 of Extended Capabilities DO 00C0 + * v3.0+: max. special DO size is at bytes 7-8 of Extended Capabilities DO 00C0 + * Theoretically we should have the 64k, but we currently limit to 8k. */ +#define MAX_OPENPGP_DO_SIZE 8192 + + +typedef struct _pgp_ec_curves { + struct sc_object_id oid; + size_t size; + struct sc_object_id oid_binary; +} pgp_ec_curves_t; + + +#define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data)) + +struct pgp_priv_data { + pgp_blob_t *mf; + pgp_blob_t *current; /* currently selected file */ + + pgp_version_t bcd_version; + pgp_do_info_t *pgp_objects; + + pgp_card_state_t state; /* card state */ + pgp_ext_caps_t ext_caps; /* extended capabilities */ + + pgp_sm_algo_t sm_algo; /* Secure Messaging algorithm */ + + size_t max_challenge_size; + size_t max_cert_size; + + sc_security_env_t sec_env; +}; + +#define BCD2UCHAR(x) (((((x) & 0xF0) >> 4) * 10) + ((x) & 0x0F)) + +#endif From 7d3e4b0878f4e3a9b58fd38b7e040e8181278d9f Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 26 Jan 2020 09:44:43 +0100 Subject: [PATCH 022/189] openpgp-tool: increase buffer for private DOs * OpenPGP v3 increased the size for private DOs. Adapt to it. * Use the symbolic constant from the refactored OpenPGP driver instead of relying on magic numbers. --- src/tools/openpgp-tool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index f5665949..b643b0c5 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -47,6 +47,7 @@ #include "libopensc/errors.h" #include "util.h" #include "libopensc/log.h" +#include "libopensc/card-openpgp.h" #define OPT_RAW 256 #define OPT_PRETTY 257 @@ -613,7 +614,7 @@ static int do_dump_do(sc_card_t *card, unsigned int tag) { int r; size_t length; - unsigned char buffer[254]; // Private DO are specified up to 254 bytes + unsigned char buffer[MAX_OPENPGP_DO_SIZE]; memset(buffer, '\0', sizeof(buffer)); From 471df32faab8748abbc4972f9e595ed50198a12f Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 26 Jan 2020 12:42:00 +0100 Subject: [PATCH 023/189] OpenPGP: correctly determine max. special DO size In pre-v3 cards, it is hard-coded to 254 bytes. In v3+ cards, it is stored in the "extended capabilities" DO 00C0. Make the determined size available as a variable in the driver data. --- src/libopensc/card-openpgp.c | 6 ++++++ src/libopensc/card-openpgp.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 2ca29a9f..b03d7202 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -688,6 +688,9 @@ pgp_get_card_features(sc_card_t *card) card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; } + /* v1.1 & v2.x: special DOs are limited to 254 bytes */ + priv->max_specialDO_size = 254; + if ((pgp_get_blob(card, priv->mf, 0x006e, &blob6e) >= 0) && (pgp_get_blob(card, blob6e, 0x0073, &blob73) >= 0)) { @@ -738,6 +741,9 @@ pgp_get_card_features(sc_card_t *card) priv->sm_algo = blob->data[1]; if ((priv->sm_algo == SM_ALGO_NONE) && (priv->ext_caps & EXT_CAP_SM)) priv->sm_algo = SM_ALGO_UNKNOWN; + + /* v3.0+: max. size of special DOs is at bytes 7-8 */ + priv->max_specialDO_size = bebytes2ushort(blob->data + 6); } if (priv->bcd_version >= OPENPGP_CARD_3_3 && (blob->len >= 10)) { /* v3.3+: MSE for key numbers 2(DEC) and 3(AUT) supported */ diff --git a/src/libopensc/card-openpgp.h b/src/libopensc/card-openpgp.h index f13e3be6..9f3dea11 100644 --- a/src/libopensc/card-openpgp.h +++ b/src/libopensc/card-openpgp.h @@ -183,6 +183,7 @@ struct pgp_priv_data { size_t max_challenge_size; size_t max_cert_size; + size_t max_specialDO_size; sc_security_env_t sec_env; }; From 5d576f4b310f5f89ed3239bf03c81c271b44470d Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 26 Jan 2020 12:42:34 +0100 Subject: [PATCH 024/189] openpgp-tool: use specialDO_size from driver in do_dump_do() --- src/tools/openpgp-tool.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index b643b0c5..3d686b87 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -612,19 +612,25 @@ static int do_info(sc_card_t *card, const struct ef_name_map *map) static int do_dump_do(sc_card_t *card, unsigned int tag) { + struct pgp_priv_data *priv = DRVDATA(card); int r; size_t length; - unsigned char buffer[MAX_OPENPGP_DO_SIZE]; - - memset(buffer, '\0', sizeof(buffer)); + unsigned char *buffer; if (tag < 0x101 || tag > 0x104) { util_error("illegal DO identifier %04X", tag); return SC_ERROR_INVALID_ARGUMENTS; } - r = sc_get_data(card, tag, buffer, sizeof(buffer)); + buffer = calloc(priv->max_specialDO_size, sizeof(unsigned char)); + if (buffer == NULL) { + util_error("error allocating memory for DO %04X", tag); + return SC_ERROR_OUT_OF_MEMORY; + } + + r = sc_get_data(card, tag, buffer, priv->max_specialDO_size); if (r < 0) { + free(buffer); util_error("failed to get data object DO %04X: %s", tag, sc_strerror(r)); if (SC_ERROR_SECURITY_STATUS_NOT_SATISFIED == r) { util_error("make sure the 'verify' and 'pin' parameters are correct"); @@ -656,12 +662,15 @@ static int do_dump_do(sc_card_t *card, unsigned int tag) clearerr(stdout); close(tmp); - if (length != (size_t) r) /* fail on write errors */ + if (length != (size_t) r) { /* fail on write errors */ + free(buffer); return EXIT_FAILURE; + } } else { util_hex_dump_asc(stdout, buffer, length, -1); } + free(buffer); return EXIT_SUCCESS; } From 723129bc123699ef72332ed106628236b96bd20d Mon Sep 17 00:00:00 2001 From: Lewis Porter Date: Tue, 7 Jan 2020 20:44:09 +0200 Subject: [PATCH 025/189] Check if card name is null in acos atrust driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit opensc-tool segfaults when trying to read a card that doen’t populate the name field. This commit adds a null check before calling strcmp(). --- src/libopensc/card-atrust-acos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-atrust-acos.c b/src/libopensc/card-atrust-acos.c index 83da3923..86bbf7ab 100644 --- a/src/libopensc/card-atrust-acos.c +++ b/src/libopensc/card-atrust-acos.c @@ -123,7 +123,7 @@ static int atrust_acos_init(struct sc_card *card) | SC_ALGORITHM_RSA_HASH_RIPEMD160 | SC_ALGORITHM_RSA_HASH_MD5_SHA1; - if (!strcmp(card->name, ACOS_EMV_A05)) + if (card->name != NULL && !strcmp(card->name, ACOS_EMV_A05)) flags |= SC_ALGORITHM_RSA_HASH_SHA256; _sc_card_add_rsa_alg(card, 1536, flags, 0x10001); From 8d4af9eb0b799f22b25783e8e1b7af329b5a917b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 12:15:53 +0100 Subject: [PATCH 026/189] pkcs11: fixed right padding of token label with ' ' fixes https://github.com/OpenSC/OpenSC/issues/1922 --- src/pkcs11/framework-pkcs15.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index e94eeeff..a1951c2e 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1122,9 +1122,10 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot, max_tokeninfo_len); slot->token_info.label[max_tokeninfo_len] = ' '; slot->token_info.label[max_tokeninfo_len+1] = '('; - slot->token_info.label[max_tokeninfo_len+2+pin_len] = ')'; strcpy_bp(slot->token_info.label+max_tokeninfo_len+2, auth->label, pin_len); + strcpy_bp(slot->token_info.label+max_tokeninfo_len+2+pin_len, + ")", 32 - max_tokeninfo_len-2-pin_len); } } else { /* PIN label is empty or just says non-useful "PIN", From 0cd19b59e19a7129f4064fcb94e0e39615ec0cdc Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 27 Jan 2020 10:54:50 +0100 Subject: [PATCH 027/189] pkcs11-tool: add --usage-wrap (disabled by default) fixes https://github.com/OpenSC/OpenSC/issues/1913 --- doc/tools/pkcs11-tool.1.xml | 7 +++++++ src/tools/pkcs11-tool.c | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/doc/tools/pkcs11-tool.1.xml b/doc/tools/pkcs11-tool.1.xml index 32b04114..a433c66d 100644 --- a/doc/tools/pkcs11-tool.1.xml +++ b/doc/tools/pkcs11-tool.1.xml @@ -170,6 +170,13 @@ Specify 'derive' key usage flag (EC only). + + + + + Specify 'wrap' key usage flag. + + name, diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index b026195b..9f5cda81 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -137,6 +137,7 @@ enum { OPT_KEY_USAGE_SIGN, OPT_KEY_USAGE_DECRYPT, OPT_KEY_USAGE_DERIVE, + OPT_KEY_USAGE_WRAP, OPT_PRIVATE, OPT_SENSITIVE, OPT_EXTRACTABLE, @@ -197,6 +198,7 @@ static const struct option options[] = { { "usage-sign", 0, NULL, OPT_KEY_USAGE_SIGN }, { "usage-decrypt", 0, NULL, OPT_KEY_USAGE_DECRYPT }, { "usage-derive", 0, NULL, OPT_KEY_USAGE_DERIVE }, + { "usage-wrap", 0, NULL, OPT_KEY_USAGE_WRAP }, { "write-object", 1, NULL, 'w' }, { "read-object", 0, NULL, 'r' }, { "delete-object", 0, NULL, 'b' }, @@ -355,6 +357,7 @@ static int opt_login_type = -1; static int opt_key_usage_sign = 0; static int opt_key_usage_decrypt = 0; static int opt_key_usage_derive = 0; +static int opt_key_usage_wrap = 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; @@ -879,6 +882,10 @@ int main(int argc, char * argv[]) opt_key_usage_derive = 1; opt_key_usage_default = 0; break; + case OPT_KEY_USAGE_WRAP: + opt_key_usage_wrap = 1; + opt_key_usage_default = 0; + break; case OPT_PRIVATE: opt_is_private = 1; break; @@ -2326,10 +2333,12 @@ static int gen_keypair(CK_SLOT_ID slot, CK_SESSION_HANDLE session, n_privkey_attr++; } - FILL_ATTR(publicKeyTemplate[n_pubkey_attr], CKA_WRAP, &_true, sizeof(_true)); - n_pubkey_attr++; - FILL_ATTR(privateKeyTemplate[n_privkey_attr], CKA_UNWRAP, &_true, sizeof(_true)); - n_privkey_attr++; + if (opt_key_usage_wrap) { + FILL_ATTR(publicKeyTemplate[n_pubkey_attr], CKA_WRAP, &_true, sizeof(_true)); + n_pubkey_attr++; + FILL_ATTR(privateKeyTemplate[n_privkey_attr], CKA_UNWRAP, &_true, sizeof(_true)); + n_privkey_attr++; + } } else if (!strncmp(type, "EC:", 3)) { CK_MECHANISM_TYPE mtypes[] = {CKM_EC_KEY_PAIR_GEN}; From 348551c920a94b103e0440877b71759ca3dff001 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Tue, 21 Jan 2020 09:43:56 -0600 Subject: [PATCH 028/189] Add EC parameters to PKCS15 public key in OpenPGP driver - Fixes #1906 The EC Parameters are the way the EC curve is presented to the outside world, and in most cases is present in a matching certificate in the SPKI. card-openpgp.c is modified to add the EC named_curve to the PKCS15 public key. OpenPGP specs only provide this via the "Algorithm Attributes" for the 3 keys via tags C1, C2 and C3 These contain the OID (not DER encoded) for the EC curve. PKCS15 has two ways to encode a "pubkey" as it was originally written for RSA. But other algorithms have parameters. X509 certificates encode the public key in the SPKI and PKIX requires the parameters to be in the SPKI. PKCS15 allows for using a SPKI as source for a public key. pgp_get_pubkey_pem will return the DER encoded RSA pubkey as before by calling sc_pkcs15_encode_pubkey pgp_get_pubkey_pem will return the DER encoded EC pubkey with parameters by calling sc_pkcs15_encode_pubkey_as_spki which calls sc_pkcs15_fix_ec_parameters internally to map DER encoded OID to named_curve. For readability, "sc_pkcs15_pubkey_t pubkey;" definitions are changed to "sc_pkcs15_pubkey_t p15pubkey;" sc_pkcs15_erase_pubkey is used to avoid memory leaks. On branch openpgp-ec-pub-curve Date: Tue Jan 21 09:43:56 2020 -0600 Changes to be committed: modified: src/libopensc/card-openpgp.c --- src/libopensc/card-openpgp.c | 92 +++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 28 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index b03d7202..54da1ac4 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -1523,13 +1523,16 @@ static int pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len) { struct pgp_priv_data *priv = DRVDATA(card); - pgp_blob_t *blob, *mod_blob, *exp_blob, *pubkey_blob; - sc_pkcs15_pubkey_t pubkey; - u8 *data; - size_t len; + pgp_blob_t *blob, *mod_blob, *exp_blob, *pubkey_blob, *blob6e, *blob73, *aa_blob; + sc_pkcs15_pubkey_t p15pubkey; + sc_cardctl_openpgp_keygen_info_t key_info; + unsigned int aa_tag = 0; + u8 *data = NULL; + size_t len = 0; int r; sc_log(card->ctx, "called, tag=%04x\n", tag); + memset(&p15pubkey, 0, sizeof(p15pubkey)); if ((r = pgp_get_blob(card, priv->mf, tag & 0xFFFE, &blob)) < 0 || (r = pgp_get_blob(card, blob, 0x7F49, &blob)) < 0) @@ -1541,28 +1544,61 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len) && (r = pgp_read_blob(card, mod_blob)) >= 0 && (r = pgp_read_blob(card, exp_blob)) >= 0) { - memset(&pubkey, 0, sizeof(pubkey)); - - pubkey.algorithm = SC_ALGORITHM_RSA; - pubkey.u.rsa.modulus.data = mod_blob->data; - pubkey.u.rsa.modulus.len = mod_blob->len; - pubkey.u.rsa.exponent.data = exp_blob->data; - pubkey.u.rsa.exponent.len = exp_blob->len; + p15pubkey.algorithm = SC_ALGORITHM_RSA; + p15pubkey.u.rsa.modulus.data = mod_blob->data; + p15pubkey.u.rsa.modulus.len = mod_blob->len; + p15pubkey.u.rsa.exponent.data = exp_blob->data; + p15pubkey.u.rsa.exponent.len = exp_blob->len; + r = sc_pkcs15_encode_pubkey(card->ctx, &p15pubkey, &data, &len); } /* ECC */ else if ((r = pgp_get_blob(card, blob, 0x0086, &pubkey_blob)) >= 0 && (r = pgp_read_blob(card, pubkey_blob)) >= 0) { - memset(&pubkey, 0, sizeof(pubkey)); + p15pubkey.algorithm = SC_ALGORITHM_EC; + p15pubkey.u.ec.ecpointQ.value = pubkey_blob->data; + p15pubkey.u.ec.ecpointQ.len = pubkey_blob->len; - pubkey.algorithm = SC_ALGORITHM_EC; - pubkey.u.ec.ecpointQ.value = pubkey_blob->data; - pubkey.u.ec.ecpointQ.len = pubkey_blob->len; + switch(tag & 0xFFFE) { + case DO_SIGN: aa_tag = 0x00C1; break; + case DO_ENCR: aa_tag = 0x00C2; break; + case DO_AUTH: aa_tag = 0x00C3; break; + default: r = SC_ERROR_INCORRECT_PARAMETERS; + } + + /* Get EC parameters from Algorithm Attribute if present */ + + if (aa_tag && ((r = pgp_get_blob(card, priv->mf, 0x006e, &blob6e)) >= 0) && + ((r = pgp_get_blob(card, blob6e, 0x0073, &blob73)) >= 0) && + ((r = pgp_get_blob(card, blob73, aa_tag, &aa_blob)) >= 0) && + ((r = pgp_parse_algo_attr_blob(aa_blob, &key_info)) >= 0)) { + + if ((r = sc_encode_oid(card->ctx, &key_info.u.ec.oid, + &p15pubkey.u.ec.params.der.value, + &p15pubkey.u.ec.params.der.len)) == 0) { + p15pubkey.u.ec.params.type = 1; + r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, &p15pubkey, &data, &len); + } + } else + sc_log(card->ctx, "Unable to find Algorithm Attribute for EC curve OID"); } else LOG_TEST_RET(card->ctx, r, "error getting elements"); - r = sc_pkcs15_encode_pubkey(card->ctx, &pubkey, &data, &len); + /* clean up anything we may have set in p15pubkey that can not be freed */ + if (p15pubkey.algorithm == SC_ALGORITHM_RSA) { + p15pubkey.u.rsa.modulus.data = NULL; + p15pubkey.u.rsa.modulus.len = 0; + p15pubkey.u.rsa.exponent.data = NULL; + p15pubkey.u.rsa.exponent.len = 0; + } else + if (p15pubkey.algorithm == SC_ALGORITHM_EC) { + p15pubkey.u.ec.ecpointQ.value = NULL; + p15pubkey.u.ec.ecpointQ.len = 0; + /* p15pubkey.u.ec.params.der and named_curve will be freed by sc_pkcs15_erase_pubkey */ + } + sc_pkcs15_erase_pubkey(&p15pubkey); + LOG_TEST_RET(card->ctx, r, "public key encoding failed"); if (len > buf_len) @@ -2478,7 +2514,7 @@ pgp_update_pubkey_blob(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in struct pgp_priv_data *priv = DRVDATA(card); pgp_blob_t *pk_blob; unsigned int blob_id = 0; - sc_pkcs15_pubkey_t pubkey; + sc_pkcs15_pubkey_t p15pubkey; u8 *data = NULL; size_t len; int r; @@ -2503,25 +2539,25 @@ pgp_update_pubkey_blob(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in /* encode pubkey */ /* RSA */ if (key_info->algorithm == SC_OPENPGP_KEYALGO_RSA){ - memset(&pubkey, 0, sizeof(pubkey)); - pubkey.algorithm = SC_ALGORITHM_RSA; - pubkey.u.rsa.modulus.data = key_info->u.rsa.modulus; - pubkey.u.rsa.modulus.len = BYTES4BITS(key_info->u.rsa.modulus_len); - pubkey.u.rsa.exponent.data = key_info->u.rsa.exponent; - pubkey.u.rsa.exponent.len = BYTES4BITS(key_info->u.rsa.exponent_len); + memset(&p15pubkey, 0, sizeof(p15pubkey)); + p15pubkey.algorithm = SC_ALGORITHM_RSA; + p15pubkey.u.rsa.modulus.data = key_info->u.rsa.modulus; + p15pubkey.u.rsa.modulus.len = BYTES4BITS(key_info->u.rsa.modulus_len); + p15pubkey.u.rsa.exponent.data = key_info->u.rsa.exponent; + p15pubkey.u.rsa.exponent.len = BYTES4BITS(key_info->u.rsa.exponent_len); } /* ECC */ else if (key_info->algorithm == SC_OPENPGP_KEYALGO_ECDH || key_info->algorithm == SC_OPENPGP_KEYALGO_ECDSA){ - memset(&pubkey, 0, sizeof(pubkey)); - pubkey.algorithm = SC_ALGORITHM_EC; - pubkey.u.ec.ecpointQ.value = key_info->u.ec.ecpoint; - pubkey.u.ec.ecpointQ.len = key_info->u.ec.ecpoint_len; + memset(&p15pubkey, 0, sizeof(p15pubkey)); + p15pubkey.algorithm = SC_ALGORITHM_EC; + p15pubkey.u.ec.ecpointQ.value = key_info->u.ec.ecpoint; + p15pubkey.u.ec.ecpointQ.len = key_info->u.ec.ecpoint_len; } else LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); - r = sc_pkcs15_encode_pubkey(card->ctx, &pubkey, &data, &len); + r = sc_pkcs15_encode_pubkey(card->ctx, &p15pubkey, &data, &len); LOG_TEST_RET(card->ctx, r, "Cannot encode pubkey"); sc_log(card->ctx, "Updating blob %04X's content.", blob_id); From 111246f1d23f6705368d1e615b2a7b3b930a189a Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 1 Nov 2019 14:31:03 -0500 Subject: [PATCH 029/189] Better error debug messages for Minidriver Add MD_FUNC_CALLED(pCardData, level) and MD_FUNC_RETURN(pCardData, level, ...) macros. Handles are type __int3264 in VS2015 are casted as size_t when printing so all bytes are printed. size_t on Windows are also treated as 32 or 64 bits. SC_FORMAT_LEN_SIZE is used in the format. (Works with VS2105 needs to be tested on other platforms.) On branch minidriver-4 Changes to be committed: modified: minidriver.c Minidriver.c and reader-pcsc.c - reuse OpenSC reader structure Windows CNG is managing the insertion and removal of the reader and the card and will call CardAcquireContext and CardDeleteContext as needed if the card or reader change. But different processes or threads may establish different PCSC connects to the same reader and card but with different handles. Reuse the OpenSC reader when windows uses the same reader but with different handles. Tests show the certutil -v -scinfo works the same. Associate_card is only need when called from CardAcquireContext and disassociate_card is only need when called from CardDeleteContext. No need to call reinit_card_for(pCardData, name) just because the handles changed. This may be the fix for #1763 because calls like CardCreateContainerEx remain in card state rather then being lost when the handles changed. Changes to be committed: modified: src/libopensc/reader-pcsc.c modified: src/minidriver/minidriver.c --- src/libopensc/reader-pcsc.c | 19 +- src/minidriver/minidriver.c | 643 ++++++++++++++++++++++-------------- 2 files changed, 412 insertions(+), 250 deletions(-) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index bcba4964..7cfa4bdc 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -2411,11 +2411,22 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c goto out; } - /* if we already had a reader, delete it */ + /* Only minidriver calls this and only uses one reader */ + /* if we already have a reader, use it*/ if (sc_ctx_get_reader_count(ctx) > 0) { - sc_reader_t *oldrdr = list_extract_at(&ctx->readers, 0); - if (oldrdr) - _sc_delete_reader(ctx, oldrdr); + sc_log(ctx, "Reusing the reader"); + sc_reader_t *reader = list_get_at(&ctx->readers, 0); + + if (reader) { + struct pcsc_private_data *priv = reader->drv_data; + priv->pcsc_card =*(SCARDHANDLE *)pcsc_card_handle; + gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle; + ret = SC_SUCCESS; + goto out; + } else { + ret = SC_ERROR_INTERNAL; + goto out; + } } sc_log(ctx, "Probing PC/SC reader"); diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 8aa38707..f14cb893 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -69,6 +69,25 @@ #include "cardmod.h" +#define MD_FUNC_CALLED(pCardData, level) do { \ + logprintf(pCardData, level, "MD_Function:%s:%d called\n",__func__, __LINE__); \ + } while(0) + + +#define MD_FUNC_CALLED_EXT(pCardData, level) do { \ + logprintf(pCardData, level, "\nP:%lu T:%lu MD_Function:%s:%d called\n", \ + (unsigned long)GetCurrentProcessId(),\ + (unsigned long)GetCurrentThreadId(), \ + __func__, __LINE__); \ + } while(0) + +#define MD_FUNC_RETURN(pCardData, level, ...) do { \ + DWORD _ret = __VA_ARGS__; \ + logprintf(pCardData, level,\ + "MD_Function:%s:%d returning with: 0x%08X\n", __func__, __LINE__, _ret); \ + return _ret; \ + } while(0) + /* store the instance given at DllMain when attached to access internal resources */ HINSTANCE g_inst; @@ -307,13 +326,11 @@ static DWORD reinit_card(PCARD_DATA pCardData) DWORD r; if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); vs = (VENDOR_SPECIFIC *)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; - - logprintf(pCardData, 2, "trying to reinit card\n"); + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (vs->initialized) { disassociate_card(pCardData); @@ -322,7 +339,7 @@ static DWORD reinit_card(PCARD_DATA pCardData) r = associate_card(pCardData); if (r != SCARD_S_SUCCESS) - return r; + MD_FUNC_RETURN(pCardData, 1, r); r = md_fs_init(pCardData); if (r != SCARD_S_SUCCESS) { @@ -330,10 +347,10 @@ static DWORD reinit_card(PCARD_DATA pCardData) "reinit_card md_fs_init failed, r = 0x%lX\n", (unsigned long)r); disassociate_card(pCardData); - return r; + MD_FUNC_RETURN(pCardData, 1, r); } - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } static BOOL lock(PCARD_DATA pCardData) @@ -369,24 +386,26 @@ static DWORD reinit_card_for(PCARD_DATA pCardData, const char *name) "%s was called, but unable to initialize card, r = %u\n", name, (unsigned int)r); - return r; + MD_FUNC_RETURN(pCardData, 1, r); } static DWORD check_card_status(PCARD_DATA pCardData, const char *name) { VENDOR_SPECIFIC *vs; + MD_FUNC_CALLED(pCardData, 3); + if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 3, SCARD_E_INVALID_PARAMETER); vs = (VENDOR_SPECIFIC *)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 3, SCARD_E_INVALID_PARAMETER); if (vs->initialized) - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 3, SCARD_S_SUCCESS); - return reinit_card_for(pCardData, name); + MD_FUNC_RETURN(pCardData, 3, reinit_card_for(pCardData, name)); } /* @@ -401,27 +420,37 @@ check_card_reader_status(PCARD_DATA pCardData, const char *name) DWORD dwRet; int r; - logprintf(pCardData, 4, "check_reader_status\n"); + logprintf(pCardData, 1, "check_reader_status for %s\n", name); if(!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwRet = check_card_status(pCardData, name); if (dwRet != SCARD_S_SUCCESS) - return dwRet; + MD_FUNC_RETURN(pCardData, 3, dwRet); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if(!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 3, SCARD_E_INVALID_PARAMETER); - logprintf(pCardData, 7, "pCardData->hSCardCtx:0x%08X hScard:0x%08X\n", - (unsigned int)pCardData->hSCardCtx, - (unsigned int)pCardData->hScard); + logprintf(pCardData, 7, "sizeof(size_t):%d sizeof(ULONG_PTR):%d sizeof(__int3264):%d sizeof pCardData->hSCardCtx:%d\n", + sizeof(size_t), sizeof(ULONG_PTR), sizeof(__int3264), sizeof pCardData->hSCardCtx); + + logprintf(pCardData, 1, "pCardData->hSCardCtx:0x%08"SC_FORMAT_LEN_SIZE_T"X hScard:0x%08"SC_FORMAT_LEN_SIZE_T"X\n", + (size_t)pCardData->hSCardCtx, + (size_t)pCardData->hScard); if (pCardData->hSCardCtx != vs->hSCardCtx || pCardData->hScard != vs->hScard) { - logprintf(pCardData, 1, "HANDLES CHANGED from 0x%08X 0x%08X\n", - (unsigned int)vs->hSCardCtx, - (unsigned int)vs->hScard); - return reinit_card_for(pCardData, name); + logprintf(pCardData, 1, "HANDLES CHANGED from vs->hSCardCtx:0x%08"SC_FORMAT_LEN_SIZE_T"X vs->hScard:0x%08"SC_FORMAT_LEN_SIZE_T"X\n", + (size_t)vs->hSCardCtx, + (size_t)vs->hScard); + if (vs->ctx) { + vs->hScard = pCardData->hScard; + vs->hSCardCtx = pCardData->hSCardCtx; + r = sc_ctx_use_reader(vs->ctx, &vs->hSCardCtx, &vs->hScard); + logprintf(pCardData, 1, "sc_ctx_use_reader returned %d\n", r); + if (r) + MD_FUNC_RETURN(pCardData, 1, SCARD_F_INTERNAL_ERROR); + } } /* This should always work, as BaseCSP should be checking for removal too */ @@ -430,8 +459,8 @@ check_card_reader_status(PCARD_DATA pCardData, const char *name) "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); + MD_FUNC_RETURN(pCardData, 1, + md_translate_OpenSC_to_Windows_error(r, SCARD_F_INTERNAL_ERROR)); if (!(r & SC_READER_CARD_PRESENT)) { /* @@ -440,10 +469,10 @@ check_card_reader_status(PCARD_DATA pCardData, const char *name) * it anyway for completeness */ logprintf(pCardData, 1, "no card present? trying to reinit\n"); - return reinit_card_for(pCardData, name); + MD_FUNC_RETURN(pCardData, 1, reinit_card_for(pCardData, name)); } - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } static DWORD @@ -452,12 +481,14 @@ md_get_pin_by_role(PCARD_DATA pCardData, PIN_ID role, struct sc_pkcs15_object ** VENDOR_SPECIFIC *vs; int rv; + MD_FUNC_CALLED(pCardData, 1); + if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if (!ret_obj) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* please keep me in sync with _get_auth_object_by_name() in pkcs11/framework-pkcs15.c */ if (role == ROLE_USER) { @@ -505,18 +536,18 @@ md_get_pin_by_role(PCARD_DATA pCardData, PIN_ID role, struct sc_pkcs15_object ** logprintf(pCardData, 2, "cannot get PIN object: unsupported role %u\n", (unsigned int)role); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } if (rv) - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, 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; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } static const char * @@ -651,6 +682,7 @@ md_get_config_bool(PCARD_DATA pCardData, char *flag_name, BOOL ret_default) ret = scconf_get_bool(atrblock, flag_name, ret_default) ? TRUE : FALSE; } + logprintf(pCardData, 2, "flag_name:%s:%s\n", flag_name, ret ? "TRUE": "FALSE"); return ret; } @@ -1655,19 +1687,19 @@ md_set_cmapfile(PCARD_DATA pCardData, struct md_file *file) 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"); + logprintf(pCardData, 2, "Cannot get User PIN object\n"); 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"); + logprintf(pCardData, 2, "Cannot get Sign PIN object -- ignored\n"); 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"); + logprintf(pCardData, 2, "Cannot get Admin PIN object -- ignored\n"); vs->pin_objs[ROLE_ADMIN] = NULL; } @@ -3167,8 +3199,10 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) VENDOR_SPECIFIC *vs = NULL; CRITICAL_SECTION hScard_lock; + MD_FUNC_CALLED(pCardData, 1); + if(!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p hScard=0x%08X hSCardCtx=0x%08X CardDeleteContext\n", @@ -3179,7 +3213,7 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if(!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); hScard_lock = vs->hScard_lock; EnterCriticalSection(&hScard_lock); @@ -3201,7 +3235,7 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) LeaveCriticalSection(&hScard_lock); DeleteCriticalSection(&hScard_lock); - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } DWORD WINAPI CardQueryCapabilities(__in PCARD_DATA pCardData, @@ -3209,13 +3243,15 @@ DWORD WINAPI CardQueryCapabilities(__in PCARD_DATA pCardData, { DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "pCardCapabilities=%p\n", pCardCapabilities); if (!pCardData || !pCardCapabilities || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_status(pCardData, "CardQueryCapabilities"); if (dwret != SCARD_S_SUCCESS) { @@ -3230,7 +3266,7 @@ DWORD WINAPI CardQueryCapabilities(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } DWORD WINAPI CardDeleteContainer(__in PCARD_DATA pCardData, @@ -3240,6 +3276,9 @@ DWORD WINAPI CardDeleteContainer(__in PCARD_DATA pCardData, VENDOR_SPECIFIC *vs = NULL; DWORD dwret; struct md_pkcs15_container* cont; + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -3247,7 +3286,7 @@ DWORD WINAPI CardDeleteContainer(__in PCARD_DATA pCardData, (unsigned int)bContainerIndex); if (!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardDeleteContainer"); if (dwret != SCARD_S_SUCCESS) { @@ -3292,7 +3331,7 @@ DWORD WINAPI CardDeleteContainer(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } /** The CardCreateContainerEx function creates a new key container that the @@ -3315,8 +3354,10 @@ DWORD WINAPI CardCreateContainerEx(__in PCARD_DATA pCardData, { DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + if (!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (PinId == ROLE_ADMIN) { dwret = SCARD_W_SECURITY_VIOLATION; @@ -3389,7 +3430,7 @@ DWORD WINAPI CardCreateContainerEx(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData, @@ -3399,9 +3440,15 @@ DWORD WINAPI CardCreateContainer(__in PCARD_DATA pCardData, __in DWORD dwKeySize, __in PBYTE pbKeyData) { - return CardCreateContainerEx(pCardData, bContainerIndex, dwFlags, + DWORD dwret; + + MD_FUNC_CALLED(pCardData, 1); + + dwret = CardCreateContainerEx(pCardData, bContainerIndex, dwFlags, dwKeySpec, dwKeySize, pbKeyData, ROLE_USER); + + MD_FUNC_RETURN(pCardData, 1, dwret); } typedef struct { @@ -3422,10 +3469,12 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine pubkey_der.value = NULL; pubkey_der.len = 0; + MD_FUNC_CALLED(pCardData, 1); + if(!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!pContainerInfo || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); ret = check_card_reader_status(pCardData, "CardGetContainerInfo"); if (ret != SCARD_S_SUCCESS) @@ -3676,14 +3725,14 @@ DWORD WINAPI CardGetContainerInfo(__in PCARD_DATA pCardData, __in BYTE bContaine } } } - logprintf(pCardData, 7, "returns container(idx:%u) info", + logprintf(pCardData, 7, "returns container(idx:%u) info\n", (unsigned int)bContainerIndex); err: free(pubkey_der.value); unlock(pCardData); - return ret; + MD_FUNC_RETURN(pCardData, 1, ret); } DWORD WINAPI CardAuthenticatePin(__in PCARD_DATA pCardData, @@ -3693,6 +3742,9 @@ DWORD WINAPI CardAuthenticatePin(__in PCARD_DATA pCardData, __out_opt PDWORD pcAttemptsRemaining) { PIN_ID PinId = 0; + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -3706,12 +3758,12 @@ DWORD WINAPI CardAuthenticatePin(__in PCARD_DATA pCardData, PinId = ROLE_ADMIN; } else { - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } if (pbPin == NULL) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); - return CardAuthenticateEx(pCardData, PinId, CARD_PIN_SILENT_CONTEXT, pbPin, cbPin, NULL, NULL, pcAttemptsRemaining); + MD_FUNC_RETURN(pCardData, 1, CardAuthenticateEx(pCardData, PinId, CARD_PIN_SILENT_CONTEXT, pbPin, cbPin, NULL, NULL, pcAttemptsRemaining)); } @@ -3723,15 +3775,17 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, DWORD dwret; int rv; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetChallenge\n"); if(!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!ppbChallengeData || !pcbChallengeData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardGetChallenge"); if (dwret != SCARD_S_SUCCESS) { @@ -3768,7 +3822,7 @@ DWORD WINAPI CardGetChallenge(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -3777,11 +3831,14 @@ DWORD WINAPI CardAuthenticateChallenge(__in PCARD_DATA pCardData, __in DWORD cbResponseData, __out_opt PDWORD pcAttemptsRemaining) { + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardAuthenticateChallenge - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } @@ -3796,8 +3853,10 @@ DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData, { DWORD r = SCARD_S_SUCCESS; + MD_FUNC_CALLED(pCardData, 1); + if(!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), @@ -3851,7 +3910,7 @@ DWORD WINAPI CardUnblockPin(__in PCARD_DATA pCardData, err: unlock(pCardData); - return r; + MD_FUNC_RETURN(pCardData, 1, r); } @@ -3868,8 +3927,10 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, DWORD r = SCARD_S_SUCCESS; PIN_ID pinid; + MD_FUNC_CALLED(pCardData, 1); + if(!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), @@ -3917,7 +3978,7 @@ DWORD WINAPI CardChangeAuthenticator(__in PCARD_DATA pCardData, err: unlock(pCardData); - return r; + MD_FUNC_RETURN(pCardData, 1, r); } /* Note: the PIN freshness will be managed by the Base CSP */ @@ -3929,6 +3990,8 @@ DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData, VENDOR_SPECIFIC* vs = NULL; int rv; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%ld T:%ld pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -3936,7 +3999,7 @@ DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData, NULLWSTR(pwszUserId), (unsigned long)dwFlags); if(!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardDeauthenticate"); if (dwret != SCARD_S_SUCCESS) @@ -3964,28 +4027,34 @@ DWORD WINAPI CardDeauthenticate(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } DWORD WINAPI CardCreateDirectory(__in PCARD_DATA pCardData, __in LPSTR pszDirectoryName, __in CARD_DIRECTORY_ACCESS_CONDITION AccessCondition) { + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardCreateDirectory - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } DWORD WINAPI CardDeleteDirectory(__in PCARD_DATA pCardData, __in LPSTR pszDirectoryName) { + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardDeleteDirectory(%s) - unsupported\n", NULLSTR(pszDirectoryName)); - return SCARD_E_UNSUPPORTED_FEATURE; + + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData, @@ -3997,6 +4066,8 @@ DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData, struct md_directory *dir = NULL; DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -4006,7 +4077,7 @@ DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData, (unsigned long)cbInitialCreationSize, AccessCondition); if (!lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_status(pCardData, "CardCreateFile"); if (dwret != SCARD_S_SUCCESS) @@ -4025,7 +4096,7 @@ DWORD WINAPI CardCreateFile(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -4039,13 +4110,15 @@ DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData, struct md_file *file = NULL; DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardReadFile\n"); if(!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 2, "pszDirectoryName = %s, pszFileName = %s, dwFlags = %lX, pcbData=%p, ppbData=%p\n", @@ -4093,7 +4166,7 @@ DWORD WINAPI CardReadFile(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -4107,8 +4180,10 @@ DWORD WINAPI CardWriteFile(__in PCARD_DATA pCardData, struct md_file *file = NULL; DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + if(!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), @@ -4155,7 +4230,7 @@ DWORD WINAPI CardWriteFile(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } DWORD WINAPI CardDeleteFile(__in PCARD_DATA pCardData, @@ -4165,13 +4240,15 @@ DWORD WINAPI CardDeleteFile(__in PCARD_DATA pCardData, { DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardDeleteFile(%s, %s) called\n", NULLSTR(pszDirectoryName), NULLSTR(pszFileName)); if(!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardDeleteFile"); if (dwret != SCARD_S_SUCCESS) @@ -4187,7 +4264,7 @@ DWORD WINAPI CardDeleteFile(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -4204,13 +4281,15 @@ DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData, struct md_file *file = NULL; size_t offs; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardEnumFiles() directory '%s'\n", NULLSTR(pszDirectoryName)); if (!pCardData || !pmszFileNames || !pdwcbFileName || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (dwFlags) { logprintf(pCardData, 1, "CardEnumFiles() dwFlags not 'zero' -- %lX\n", @@ -4262,7 +4341,7 @@ DWORD WINAPI CardEnumFiles(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -4274,8 +4353,10 @@ DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData, DWORD dwret; struct md_file *file = NULL; + MD_FUNC_CALLED(pCardData, 1); + if(!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), @@ -4299,7 +4380,7 @@ DWORD WINAPI CardGetFileInfo(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -4308,6 +4389,8 @@ DWORD WINAPI CardQueryFreeSpace(__in PCARD_DATA pCardData, __in DWORD dwFlags, { DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -4317,7 +4400,7 @@ DWORD WINAPI CardQueryFreeSpace(__in PCARD_DATA pCardData, __in DWORD dwFlags, (unsigned long)pCardFreeSpaceInfo->dwVersion); if (!pCardData || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_status(pCardData, "CardQueryFreeSpace"); if (dwret != SCARD_S_SUCCESS) @@ -4334,7 +4417,7 @@ DWORD WINAPI CardQueryFreeSpace(__in PCARD_DATA pCardData, __in DWORD dwFlags, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -4345,6 +4428,8 @@ DWORD WINAPI CardQueryKeySizes(__in PCARD_DATA pCardData, { DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -4354,7 +4439,7 @@ DWORD WINAPI CardQueryKeySizes(__in PCARD_DATA pCardData, pKeySizes ? (unsigned long)pKeySizes->dwVersion : 0); if (!pCardData || dwFlags != 0 || dwKeySpec == 0 || !lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_status(pCardData, "CardQueryKeySizes"); if (dwret != SCARD_S_SUCCESS) @@ -4369,7 +4454,7 @@ DWORD WINAPI CardQueryKeySizes(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -4386,22 +4471,25 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, struct sc_pkcs15_object *pkey = NULL; struct sc_algorithm_info *alg_info = NULL; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardRSADecrypt\n"); + if (!pCardData || !pInfo || pInfo->pbData == NULL) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (pInfo->dwVersion > CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if ( pInfo->dwVersion < CARD_RSA_KEY_DECRYPT_INFO_CURRENT_VERSION && pCardData->dwVersion == CARD_DATA_CURRENT_VERSION) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if (pInfo->dwKeySpec != AT_KEYEXCHANGE) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardRSADecrypt"); if (dwret != SCARD_S_SUCCESS) @@ -4573,7 +4661,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -4588,18 +4676,20 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO size_t dataToSignLen = sizeof(dataToSign); sc_pkcs15_object_t *pkey; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardSignData\n"); if (!pCardData || !pInfo) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if ( ( pInfo->dwVersion != CARD_SIGNING_INFO_BASIC_VERSION ) && ( pInfo->dwVersion != CARD_SIGNING_INFO_CURRENT_VERSION ) ) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if ( pInfo->pbData == NULL ) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); switch(pInfo->dwKeySpec) { case AT_SIGNATURE: @@ -4612,7 +4702,7 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO case AT_ECDHE_P521: break; default: - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } 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; @@ -4866,7 +4956,7 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData, @@ -4884,25 +4974,27 @@ DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData, struct md_dh_agreement* temp = NULL; BYTE i; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardConstructDHAgreement\n"); if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!pAgreementInfo) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if ( pAgreementInfo->pbPublicKey == NULL ) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (pAgreementInfo->dwVersion > CARD_DH_AGREEMENT_INFO_VERSION) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if ( pAgreementInfo->dwVersion < CARD_DH_AGREEMENT_INFO_VERSION && pCardData->dwVersion == CARD_DATA_CURRENT_VERSION) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if (!lock(pCardData)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardConstructDHAgreement"); if (dwret != SCARD_S_SUCCESS) @@ -5007,7 +5099,7 @@ DWORD WINAPI CardConstructDHAgreement(__in PCARD_DATA pCardData, err: unlock(pCardData); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } @@ -5028,6 +5120,8 @@ DWORD WINAPI CardDeriveHashOrHMAC(__in PCARD_DATA pCardData, ULONG i; NCryptBufferDesc* parameters = NULL; + MD_FUNC_CALLED(pCardData, 1); + dwReturn = BCryptOpenAlgorithmProvider(&hAlgorithm, szAlgorithm, NULL, (pbHmacKey?BCRYPT_ALG_HANDLE_HMAC_FLAG:0)); if (dwReturn) { logprintf(pCardData, 0, @@ -5134,7 +5228,7 @@ cleanup: LocalFree(pbBuffer); if (hAlgorithm) BCryptCloseAlgorithmProvider(hAlgorithm, 0); - return dwReturn; + MD_FUNC_RETURN(pCardData, 1, dwReturn); } /* Generic function to perform hash. Could have been OpenSSL but used BCrypt* functions. @@ -5444,18 +5538,21 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardDeriveKey\n"); + + MD_FUNC_CALLED(pCardData, 1); + if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!pAgreementInfo) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!pAgreementInfo->dwVersion) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if (pAgreementInfo->dwVersion > CARD_DERIVE_KEY_CURRENT_VERSION) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if (pAgreementInfo->pwszKDF == NULL) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (pAgreementInfo->dwFlags & ~(KDF_USE_SECRET_AS_HMAC_KEY_FLAG | CARD_RETURN_KEY_HANDLE | CARD_BUFFER_SIZE_ONLY)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* according to the documentation, CARD_DERIVE_KEY_CURRENT_VERSION should be equal to 2. In practice it is not 2 but 1 @@ -5466,20 +5563,20 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* check if the agreement index is ok */ if (pAgreementInfo->bSecretAgreementIndex >= vs->allocatedAgreements) { - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } agreement = vs->dh_agreements + pAgreementInfo->bSecretAgreementIndex; if (agreement->pbAgreement == NULL) { - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } if (pAgreementInfo->dwFlags & CARD_RETURN_KEY_HANDLE ) { - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } /* find the algorithm, checks parameters */ @@ -5509,7 +5606,7 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, logprintf(pCardData, 0, "CardDeriveKey: unsupported algorithm %S\n", (PWSTR)buffer->pvBuffer); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } break; case KDF_HMAC_KEY: @@ -5527,7 +5624,7 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, case KDF_TLS_PRF_LABEL: if (pbLabel != NULL) { logprintf(pCardData, 0, "CardDeriveKey: got more than one Label\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } pbLabel = (PBYTE)buffer->pvBuffer; dwLabelSize = buffer->cbBuffer; @@ -5535,14 +5632,14 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, case KDF_TLS_PRF_SEED: if (pbSeed != NULL) { logprintf(pCardData, 0, "CardDeriveKey: got more than one Seed\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } if (buffer->cbBuffer != 64) { logprintf(pCardData, 0, "CardDeriveKey: invalid seed size %lu\n", buffer->cbBuffer); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } pbSeed = (PBYTE)buffer->pvBuffer; break; @@ -5559,7 +5656,7 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, logprintf(pCardData, 0, "CardDeriveKey: unknown buffer type %lu\n", (parameters->pBuffers + i)->BufferType); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } } } @@ -5574,21 +5671,21 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_HMAC) == 0) { if (pbHmacKey == NULL) { logprintf(pCardData, 0, "CardDeriveKey: no hhmac key for hmac KDF\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } } else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_TLS_PRF) == 0) { if (!pbSeed) { logprintf(pCardData, 0, "CardDeriveKey: No seed was provided\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } if (!pbLabel) { logprintf(pCardData, 0, "CardDeriveKey: No label was provided\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } } else { logprintf(pCardData, 0, "CardDeriveKey: unsupported KDF %S\n", pAgreementInfo->pwszKDF); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } /* do the job for the KDF Hash & Hmac */ @@ -5600,7 +5697,7 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, logprintf(pCardData, 0, "CardDeriveKey: got an error while deriving the Key (hash or HMAC) 0x%08X\n", (unsigned int)dwReturn); - return dwReturn; + MD_FUNC_RETURN(pCardData, 1, dwReturn); } } else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_TLS_PRF) == 0) { @@ -5609,14 +5706,14 @@ DWORD WINAPI CardDeriveKey(__in PCARD_DATA pCardData, logprintf(pCardData, 0, "CardDeriveKey: got an error while deriving the Key (TlsPrf) 0x%08X\n", (unsigned int)dwReturn); - return dwReturn; + MD_FUNC_RETURN(pCardData, 1, dwReturn); } } /*else if (wcscmp(pAgreementInfo->pwszKDF, BCRYPT_KDF_SP80056A_CONCAT ) == 0) { }*/ - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } @@ -5628,31 +5725,34 @@ DWORD WINAPI CardDestroyDHAgreement( VENDOR_SPECIFIC *vs; struct md_dh_agreement* agreement = NULL; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardDestroyDHAgreement\n"); + if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (dwFlags) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (bSecretAgreementIndex >= vs->allocatedAgreements) { - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } agreement = vs->dh_agreements + bSecretAgreementIndex; if (agreement->pbAgreement == NULL) { - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } SecureZeroMemory(agreement->pbAgreement, agreement->dwSize); pCardData->pfnCspFree(agreement->pbAgreement); agreement->pbAgreement = 0; agreement->dwSize = 0; - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } DWORD WINAPI CardGetChallengeEx(__in PCARD_DATA pCardData, @@ -5661,11 +5761,14 @@ DWORD WINAPI CardGetChallengeEx(__in PCARD_DATA pCardData, __out PDWORD pcbChallengeData, __in DWORD dwFlags) { + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetChallengeEx - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, @@ -5685,17 +5788,19 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, int r; BOOL DisplayPinpadUI = FALSE; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardAuthenticateEx\n"); if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardAuthenticateEx"); if (dwret != SCARD_S_SUCCESS) - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); logprintf(pCardData, 2, "CardAuthenticateEx: PinId=%u, dwFlags=0x%08X, cbPinData=%lu, Attempts %s\n", @@ -5704,14 +5809,14 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (PinId >= MD_MAX_PINS) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); pin_obj = vs->pin_objs[PinId]; if (!pin_obj) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); #if 0 /* TODO do we need to return SCARD_E_UNSUPPORTED_FEATURE if the card @@ -5720,22 +5825,22 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN || dwFlags == CARD_AUTHENTICATE_SESSION_PIN) { if (! (vs->reader->capabilities & SC_READER_CAP_PIN_PAD || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } #endif if (dwFlags & ~(CARD_AUTHENTICATE_GENERATE_SESSION_PIN | CARD_AUTHENTICATE_SESSION_PIN | CARD_PIN_SILENT_CONTEXT)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (dwFlags & CARD_AUTHENTICATE_GENERATE_SESSION_PIN && (ppbSessionPin == NULL || pcbSessionPin == NULL)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* using a pin pad */ if (NULL == pbPinData) { if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!(dwFlags & CARD_PIN_SILENT_CONTEXT) && !(vs->ctx->flags & SC_CTX_FLAG_DISABLE_POPUPS)) { DisplayPinpadUI = TRUE; @@ -5824,12 +5929,12 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { if(pcAttemptsRemaining) (*pcAttemptsRemaining) = 0; - return SCARD_W_CHV_BLOCKED; + MD_FUNC_RETURN(pCardData, 1, SCARD_W_CHV_BLOCKED); } if(pcAttemptsRemaining) (*pcAttemptsRemaining) = auth_info->tries_left; - return md_translate_OpenSC_to_Windows_error(r, SCARD_W_WRONG_CHV); + MD_FUNC_RETURN(pCardData, 1, md_translate_OpenSC_to_Windows_error(r, SCARD_W_WRONG_CHV)); } logprintf(pCardData, 2, "Pin code correct.\n"); @@ -5848,7 +5953,7 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, } } - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } @@ -5871,38 +5976,40 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, BOOL DisplayPinpadUI = FALSE; size_t target_len = cbTargetData; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardChangeAuthenticatorEx\n"); if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardChangeAuthenticatorEx"); if (dwret != SCARD_S_SUCCESS) - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, 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; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } if ((dwFlags & PIN_CHANGE_FLAG_UNBLOCK) && (dwFlags & PIN_CHANGE_FLAG_CHANGEPIN)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (dwFlags & PIN_CHANGE_FLAG_UNBLOCK && dwAuthenticatingPinId == dwTargetPinId) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (dwAuthenticatingPinId >= MD_MAX_PINS || dwTargetPinId >= MD_MAX_PINS) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!vs->pin_objs[dwAuthenticatingPinId] || !vs->pin_objs[dwTargetPinId]) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* according to the spec: cRetryCount MUST be zero */ if (cRetryCount) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 2, "CardChangeAuthenticatorEx: AuthenticatingPinId=%u, dwFlags=0x%08X, cbAuthenticatingPinData=%lu, TargetPinId=%u, cbTargetData=%lu, Attempts %s\n", @@ -5915,12 +6022,12 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { if (pbAuthenticatingPinData == NULL || cbAuthenticatingPinData == 0) { logprintf(pCardData, 1, "Invalid current PIN data\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } if (pbTargetData == NULL || cbTargetData == 0) { logprintf(pCardData, 1, "Invalid new PIN data\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } } /* using a pin pad */ @@ -5955,22 +6062,23 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, if (rv == SC_ERROR_AUTH_METHOD_BLOCKED) { if(pcAttemptsRemaining) (*pcAttemptsRemaining) = 0; - return SCARD_W_CHV_BLOCKED; + MD_FUNC_RETURN(pCardData, 1, SCARD_W_CHV_BLOCKED); } if(pcAttemptsRemaining) (*pcAttemptsRemaining) = auth_info->tries_left; - return md_translate_OpenSC_to_Windows_error(rv, SCARD_W_WRONG_CHV); + MD_FUNC_RETURN(pCardData, 1, md_translate_OpenSC_to_Windows_error(rv, SCARD_W_WRONG_CHV)); } logprintf(pCardData, 7, "returns success\n"); - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } DWORD WINAPI CardDeauthenticateEx(__in PCARD_DATA pCardData, __in PIN_SET PinId, __in DWORD dwFlags) { + MD_FUNC_CALLED(pCardData, 1); logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), @@ -5979,7 +6087,7 @@ DWORD WINAPI CardDeauthenticateEx(__in PCARD_DATA pCardData, "CardDeauthenticateEx PinId=%u dwFlags=0x%08X\n", (unsigned int)PinId, (unsigned int)dwFlags); - return CardDeauthenticate(pCardData, wszCARD_USER_USER, 0); + MD_FUNC_RETURN(pCardData, 1, CardDeauthenticate(pCardData, wszCARD_USER_USER, 0)); } DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, @@ -5994,42 +6102,44 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, VENDOR_SPECIFIC *vs = NULL; struct md_pkcs15_container *cont = NULL; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetContainerProperty\n"); if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_status(pCardData, "CardGetContainerProperty"); if (dwret != SCARD_S_SUCCESS) - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); logprintf(pCardData, 2, "CardGetContainerProperty bContainerIndex=%u, wszProperty=%S, cbData=%lu, dwFlags=0x%08X\n", (unsigned int)bContainerIndex, NULLWSTR(wszProperty), (unsigned long)cbData, (unsigned int)dwFlags); if (!wszProperty) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (dwFlags) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!pbData || !pdwDataLen) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (bContainerIndex >= MD_MAX_KEY_CONTAINERS) - return SCARD_E_NO_KEY_CONTAINER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_NO_KEY_CONTAINER); /* the test for the existence of containers is redundant 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; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); cont = &vs->p15_containers[bContainerIndex]; if (!cont->prkey_obj) { logprintf(pCardData, 7, "Container %u is empty\n", (unsigned int)bContainerIndex); - return SCARD_E_NO_KEY_CONTAINER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_NO_KEY_CONTAINER); } if (wcscmp(CCP_CONTAINER_INFO,wszProperty) == 0) { @@ -6037,10 +6147,10 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData >= sizeof(DWORD)) if (p->dwVersion != CONTAINER_INFO_CURRENT_VERSION && p->dwVersion != 0 ) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; - return CardGetContainerInfo(pCardData,bContainerIndex,0,p); + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); + MD_FUNC_RETURN(pCardData, 1, CardGetContainerInfo(pCardData,bContainerIndex,0,p)); } if (wcscmp(CCP_PIN_IDENTIFIER,wszProperty) == 0) { @@ -6048,7 +6158,7 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); if (cont->prkey_obj->auth_id.len == 0) *p = ROLE_EVERYONE; @@ -6079,10 +6189,10 @@ DWORD WINAPI CardGetContainerProperty(__in PCARD_DATA pCardData, logprintf(pCardData, 2, "Return Pin id %u\n", (unsigned int)*p); - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } DWORD WINAPI CardSetContainerProperty(__in PCARD_DATA pCardData, @@ -6092,11 +6202,14 @@ DWORD WINAPI CardSetContainerProperty(__in PCARD_DATA pCardData, __in DWORD cbDataLen, __in DWORD dwFlags) { + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardSetContainerProperty - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } @@ -6110,6 +6223,8 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, VENDOR_SPECIFIC *vs; DWORD dwret; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); @@ -6119,29 +6234,29 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, (unsigned long)dwFlags); if (!pCardData || !wszProperty) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!pbData || !pdwDataLen) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); dwret = check_card_reader_status(pCardData, "CardGetProperty"); if (dwret != SCARD_S_SUCCESS) - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (wcscmp(CP_CARD_FREE_SPACE,wszProperty) == 0) { PCARD_FREE_SPACE_INFO pCardFreeSpaceInfo = (PCARD_FREE_SPACE_INFO )pbData; if (pdwDataLen) *pdwDataLen = sizeof(*pCardFreeSpaceInfo); if (cbData < sizeof(*pCardFreeSpaceInfo)) - return SCARD_E_NO_MEMORY; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_NO_MEMORY); dwret = md_free_space(pCardData, pCardFreeSpaceInfo); if (dwret != SCARD_S_SUCCESS) { logprintf(pCardData, 1, "Get free space error"); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } } else if (wcscmp(CP_CARD_CAPABILITIES, wszProperty) == 0) { @@ -6150,28 +6265,28 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = sizeof(*pCardCapabilities); if (cbData < sizeof(*pCardCapabilities)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); dwret = md_card_capabilities(pCardData, pCardCapabilities); if (dwret != SCARD_S_SUCCESS) - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } else if (wcscmp(CP_CARD_KEYSIZES,wszProperty) == 0) { PCARD_KEY_SIZES pKeySizes = (PCARD_KEY_SIZES )pbData; if (pdwDataLen) *pdwDataLen = sizeof(*pKeySizes); if (cbData < sizeof(*pKeySizes)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); dwret = md_query_key_sizes(pCardData, 0, pKeySizes); if (dwret != SCARD_S_SUCCESS) - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } else if (wcscmp(CP_CARD_READ_ONLY, wszProperty) == 0) { BOOL *p = (BOOL *)pbData; if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); *p = md_is_read_only(pCardData); } @@ -6180,7 +6295,7 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); *p = CP_CACHE_MODE_NO_CACHE; } else if (wcscmp(CP_SUPPORTS_WIN_X509_ENROLLMENT, wszProperty) == 0) { @@ -6188,7 +6303,7 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); *p = md_is_supports_X509_enrollment(pCardData); } else if (wcscmp(CP_CARD_GUID, wszProperty) == 0) { @@ -6197,13 +6312,13 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, md_fs_find_file(pCardData, NULL, "cardid", &cardid); if (!cardid) { logprintf(pCardData, 2, "file 'cardid' not found\n"); - return SCARD_E_FILE_NOT_FOUND; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_FILE_NOT_FOUND); } if (pdwDataLen) *pdwDataLen = (DWORD) cardid->size; if (cbData < cardid->size) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); CopyMemory(pbData, cardid->blob, cardid->size); } @@ -6222,7 +6337,7 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = (DWORD) buf_len; if (cbData < buf_len) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); CopyMemory(pbData, buf, buf_len); } @@ -6233,16 +6348,16 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); if (p->dwVersion != PIN_INFO_CURRENT_VERSION) - return ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, ERROR_REVISION_MISMATCH); if (dwFlags >= MD_MAX_PINS) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!vs->pin_objs[dwFlags]) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); p->PinType = vs->reader->capabilities & SC_READER_CAP_PIN_PAD || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH @@ -6286,7 +6401,7 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); memset(p, 0, sizeof(*p)); for (pinidx = 0; pinidx < MD_MAX_PINS; pinidx++) { @@ -6301,24 +6416,24 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); logprintf(pCardData, 7, "CARD_AUTHENTICATED_STATE invalid\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } else if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY,wszProperty) == 0) { DWORD *p = (DWORD *)pbData; if (dwFlags >= MD_MAX_PINS) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!vs->pin_objs[dwFlags]) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); *p = CARD_PIN_STRENGTH_PLAINTEXT; if (vs->p15card->card->caps & SC_CARD_CAP_SESSION_PIN) { *p |= CARD_PIN_STRENGTH_SESSION_PIN; @@ -6329,33 +6444,33 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (pdwDataLen) *pdwDataLen = sizeof(*p); if (cbData < sizeof(*p)) - return ERROR_INSUFFICIENT_BUFFER; + MD_FUNC_RETURN(pCardData, 1, ERROR_INSUFFICIENT_BUFFER); *p = 0; } else if (wcscmp(CP_ENUM_ALGORITHMS, wszProperty) == 0) { logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty); //TODO - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } else if (wcscmp(CP_PADDING_SCHEMES, wszProperty) == 0) { logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty); //TODO - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } else if (wcscmp(CP_CHAINING_MODES, wszProperty) == 0) { logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty); //TODO - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } else { logprintf(pCardData, 3, "Unsupported property '%S'\n", wszProperty); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } logprintf(pCardData, 7, "returns '%S' ", wszProperty); loghex(pCardData, 7, pbData, *pdwDataLen); - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, @@ -6366,13 +6481,15 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, { VENDOR_SPECIFIC *vs; + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardSetProperty\n"); if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 2, "CardSetProperty wszProperty=%S, pbData=%p, cbDataLen=%lu, dwFlags=%lu", @@ -6381,16 +6498,16 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!wszProperty) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (dwFlags) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if (!cbDataLen) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* the following properties cannot be set according to the minidriver specifications */ if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0 || @@ -6406,14 +6523,14 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, wcscmp(wszProperty,CP_CARD_CACHE_MODE) == 0 || wcscmp(wszProperty,CP_CARD_SERIAL_NO) == 0 ) { - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } /* the following properties can be set, but are not implemented by the minidriver */ if (wcscmp(CP_CARD_PIN_STRENGTH_VERIFY, wszProperty) == 0 || wcscmp(CP_CARD_PIN_INFO, wszProperty) == 0 || wcscmp(CP_CARD_GUID, wszProperty) == 0 ) { - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } /* This property and CP_PIN_CONTEXT_STRING are set just prior to a call to @@ -6421,25 +6538,25 @@ DWORD WINAPI CardSetProperty(__in PCARD_DATA pCardData, */ if (wcscmp(CP_PARENT_WINDOW, wszProperty) == 0) { if (cbDataLen != sizeof(HWND) || !pbData) { - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } else { HWND cp = *((HWND *) pbData); if (cp!=0 && !IsWindow(cp)) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); vs->hwndParent = cp; } logprintf(pCardData, 3, "Saved parent window (%p)\n", vs->hwndParent); - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } if (wcscmp(CP_PIN_CONTEXT_STRING, wszProperty) == 0) { vs->wszPinContext = (PWSTR) pbData; logprintf(pCardData, 3, "Saved PIN context string: %S\n", (PWSTR) pbData); - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } logprintf(pCardData, 3, "INVALID PARAMETER\n"); - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); } @@ -6472,11 +6589,14 @@ DWORD WINAPI CardImportSessionKey( UNREFERENCED_PARAMETER(pbInput); UNREFERENCED_PARAMETER(cbInput); UNREFERENCED_PARAMETER(dwFlags); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardImportSessionKey - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } /** The MDImportSessionKey function imports a temporary session key to the card minidriver @@ -6497,11 +6617,14 @@ DWORD WINAPI MDImportSessionKey( UNREFERENCED_PARAMETER(phKey); UNREFERENCED_PARAMETER(pbInput); UNREFERENCED_PARAMETER(cbInput); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "MDImportSessionKey - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } /** The MDEncryptData function uses a key handle to encrypt data with a symmetric key. @@ -6527,11 +6650,14 @@ DWORD WINAPI MDEncryptData( UNREFERENCED_PARAMETER(dwFlags); UNREFERENCED_PARAMETER(ppEncryptedData); UNREFERENCED_PARAMETER(pcEncryptedData); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "MDEncryptData - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } @@ -6557,11 +6683,15 @@ DWORD WINAPI CardGetSharedKeyHandle( UNREFERENCED_PARAMETER(ppbOutput); UNREFERENCED_PARAMETER(pcbOutput); UNREFERENCED_PARAMETER(phKey); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetSharedKeyHandle - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); + } /** The CardDestroyKey function releases a temporary key on the card. The card @@ -6574,11 +6704,14 @@ DWORD WINAPI CardDestroyKey( { UNREFERENCED_PARAMETER(pCardData); UNREFERENCED_PARAMETER(hKey); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardDestroyKey - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } /** This function can be used to get properties for a cryptographic algorithm.*/ @@ -6600,11 +6733,14 @@ DWORD WINAPI CardGetAlgorithmProperty ( UNREFERENCED_PARAMETER(cbData); UNREFERENCED_PARAMETER(pdwDataLen); UNREFERENCED_PARAMETER(dwFlags); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetAlgorithmProperty - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } /** This function is used to get the properties of a key.*/ @@ -6625,11 +6761,14 @@ DWORD WINAPI CardGetKeyProperty( UNREFERENCED_PARAMETER(cbData); UNREFERENCED_PARAMETER(pdwDataLen); UNREFERENCED_PARAMETER(dwFlags); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardGetKeyProperty - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } /** This function is used to set the properties of a key.*/ @@ -6649,11 +6788,15 @@ DWORD WINAPI CardSetKeyProperty( UNREFERENCED_PARAMETER(pbInput); UNREFERENCED_PARAMETER(cbInput); UNREFERENCED_PARAMETER(dwFlags); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardSetKeyProperty - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); + } /** CardProcessEncryptedData processes a set of encrypted data BLOBs by @@ -6682,11 +6825,15 @@ DWORD WINAPI CardProcessEncryptedData( UNREFERENCED_PARAMETER(cbOutput); UNREFERENCED_PARAMETER(pdwOutputLen); UNREFERENCED_PARAMETER(dwFlags); + + MD_FUNC_CALLED(pCardData, 1); + logprintf(pCardData, 1, "\nP:%lu T:%lu pCardData:%p ", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, "CardProcessEncryptedData - unsupported\n"); - return SCARD_E_UNSUPPORTED_FEATURE; + + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags) @@ -6696,51 +6843,55 @@ DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags CRITICAL_SECTION hScard_lock; if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); + + MD_FUNC_CALLED(pCardData, 1); + if (dwFlags & ~CARD_SECURE_KEY_INJECTION_NO_CARD_MODE) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); + if (!(dwFlags & CARD_SECURE_KEY_INJECTION_NO_CARD_MODE)) { if( pCardData->hSCardCtx == 0) { logprintf(pCardData, 0, "Invalid handle.\n"); - return SCARD_E_INVALID_HANDLE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_HANDLE); } if( pCardData->hScard == 0) { logprintf(pCardData, 0, "Invalid handle.\n"); - return SCARD_E_INVALID_HANDLE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_HANDLE); } } else { /* secure key injection not supported */ - return SCARD_E_UNSUPPORTED_FEATURE; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNSUPPORTED_FEATURE); } if (pCardData->pbAtr == NULL) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); if ( pCardData->pwszCardName == NULL ) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* <2 length or >=0x22 are not ISO compliant */ if (pCardData->cbAtr >= 0x22 || pCardData->cbAtr <= 0x2) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* ATR beginning by 0x00 or 0xFF are not ISO compliant */ if (pCardData->pbAtr[0] == 0xFF || pCardData->pbAtr[0] == 0x00) - return SCARD_E_UNKNOWN_CARD; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNKNOWN_CARD); /* Memory management functions */ if ( ( pCardData->pfnCspAlloc == NULL ) || ( pCardData->pfnCspReAlloc == NULL ) || ( pCardData->pfnCspFree == NULL ) ) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* The lowest supported version is 4 - maximum is 7. */ if (pCardData->dwVersion < MD_MINIMUM_VERSION_SUPPORTED) - return (DWORD) ERROR_REVISION_MISMATCH; + MD_FUNC_RETURN(pCardData, 1, (DWORD) ERROR_REVISION_MISMATCH); suppliedVersion = pCardData->dwVersion; /* VENDOR SPECIFIC */ vs = pCardData->pvVendorSpecific = pCardData->pfnCspAlloc(sizeof(VENDOR_SPECIFIC)); if (!vs) - return SCARD_E_NO_MEMORY; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_NO_MEMORY); memset(vs, 0, sizeof(VENDOR_SPECIFIC)); InitializeCriticalSection(&vs->hScard_lock); @@ -6842,7 +6993,7 @@ DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags unlock(pCardData); - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); ret_disassoc: disassociate_card(pCardData); @@ -6856,7 +7007,7 @@ ret_free: pCardData->pvVendorSpecific = NULL; LeaveCriticalSection(&hScard_lock); DeleteCriticalSection(&hScard_lock); - return dwret; + MD_FUNC_RETURN(pCardData, 1, dwret); } static DWORD associate_card(PCARD_DATA pCardData) @@ -6866,13 +7017,13 @@ static DWORD associate_card(PCARD_DATA pCardData) struct sc_app_info *app_generic; struct sc_aid *aid; - logprintf(pCardData, 1, "associate_card\n"); + MD_FUNC_CALLED(pCardData, 1); if (!pCardData) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if (!vs) - return SCARD_E_INVALID_PARAMETER; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); /* * set the addresses of the reader and card handles @@ -6885,8 +7036,8 @@ static DWORD associate_card(PCARD_DATA pCardData) /* set the provided reader and card handles into ctx */ 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; + logprintf(pCardData, 1, "sc_ctx_use_reader() failed with %d\n", r); + MD_FUNC_RETURN(pCardData, 1, SCARD_E_COMM_DATA_LOST); } /* should be only one reader */ @@ -6894,12 +7045,12 @@ static DWORD associate_card(PCARD_DATA pCardData) vs->reader = sc_ctx_get_reader(vs->ctx, 0); if (!vs->reader) - return SCARD_E_COMM_DATA_LOST; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_COMM_DATA_LOST); 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; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNKNOWN_CARD); } logprintf(pCardData, 3, "Connected card in '%s'\n", NULLSTR(vs->reader->name)); @@ -6913,12 +7064,12 @@ static DWORD associate_card(PCARD_DATA pCardData) if (r != SC_SUCCESS) { logprintf(pCardData, 0, "PKCS#15 init failed.\n"); sc_disconnect_card(vs->card); - return SCARD_E_UNKNOWN_CARD; + MD_FUNC_RETURN(pCardData, 1, SCARD_E_UNKNOWN_CARD); } vs->initialized = TRUE; - return SCARD_S_SUCCESS; + MD_FUNC_RETURN(pCardData, 1, SCARD_S_SUCCESS); } static void disassociate_card(PCARD_DATA pCardData) From 0fd77d642c1e7f3cff6f9cf4b60da0d5e516bbe4 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 9 Nov 2019 18:50:15 -0600 Subject: [PATCH 030/189] Minidriver additionl fixes Use __FUNCTION__ as defind in log.h so will compile with any compiler. logprint additional handles as size_t Add check in reader-pcsc.c pcsc_user_reader for minidriver only. On branch minidriver-5 Changes to be committed: modified: src/libopensc/reader-pcsc.c modified: src/minidriver/minidriver.c --- src/libopensc/reader-pcsc.c | 7 ++++++- src/minidriver/minidriver.c | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 7cfa4bdc..66b426e4 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -2411,8 +2411,13 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c goto out; } + if (!gpriv->cardmod) { + ret = SC_ERROR_INTERNAL; + goto out; + } + /* Only minidriver calls this and only uses one reader */ - /* if we already have a reader, use it*/ + /* if we already have a reader, update it */ if (sc_ctx_get_reader_count(ctx) > 0) { sc_log(ctx, "Reusing the reader"); sc_reader_t *reader = list_get_at(&ctx->readers, 0); diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index f14cb893..639f88bb 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -70,7 +70,7 @@ #include "cardmod.h" #define MD_FUNC_CALLED(pCardData, level) do { \ - logprintf(pCardData, level, "MD_Function:%s:%d called\n",__func__, __LINE__); \ + logprintf(pCardData, level, "MD_Function:%s:%d called\n",__FUNCTION__, __LINE__); \ } while(0) @@ -78,13 +78,13 @@ logprintf(pCardData, level, "\nP:%lu T:%lu MD_Function:%s:%d called\n", \ (unsigned long)GetCurrentProcessId(),\ (unsigned long)GetCurrentThreadId(), \ - __func__, __LINE__); \ + __FUNCTION__, __LINE__); \ } while(0) #define MD_FUNC_RETURN(pCardData, level, ...) do { \ DWORD _ret = __VA_ARGS__; \ logprintf(pCardData, level,\ - "MD_Function:%s:%d returning with: 0x%08X\n", __func__, __LINE__, _ret); \ + "MD_Function:%s:%d returning with: 0x%08X\n", __FUNCTION__, __LINE__, _ret); \ return _ret; \ } while(0) @@ -3205,11 +3205,11 @@ DWORD WINAPI CardDeleteContext(__inout PCARD_DATA pCardData) MD_FUNC_RETURN(pCardData, 1, SCARD_E_INVALID_PARAMETER); logprintf(pCardData, 1, - "\nP:%lu T:%lu pCardData:%p hScard=0x%08X hSCardCtx=0x%08X CardDeleteContext\n", + "\nP:%lu T:%lu pCardData:%p hScard=0x%08"SC_FORMAT_LEN_SIZE_T"X hSCardCtx=0x%08"SC_FORMAT_LEN_SIZE_T"X CardDeleteContext\n", (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData, - (unsigned int)pCardData->hScard, - (unsigned int)pCardData->hSCardCtx); + (size_t)pCardData->hScard, + (size_t)pCardData->hSCardCtx); vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); if(!vs) @@ -4948,11 +4948,11 @@ DWORD WINAPI CardSignData(__in PCARD_DATA pCardData, __inout PCARD_SIGNING_INFO } logprintf(pCardData, 3, - "CardSignData, dwVersion=%lu, name=%S, hScard=0x%08X, hSCardCtx=0x%08X\n", + "CardSignData, dwVersion=%lu, name=%S, hScard=0x%08"SC_FORMAT_LEN_SIZE_T"X, hSCardCtx=0x%08"SC_FORMAT_LEN_SIZE_T"X\n", (unsigned long)pCardData->dwVersion, NULLWSTR(pCardData->pwszCardName), - (unsigned int)pCardData->hScard, - (unsigned int)pCardData->hSCardCtx); + (size_t)pCardData->hScard, + (size_t)pCardData->hSCardCtx); err: unlock(pCardData); @@ -6902,11 +6902,11 @@ DWORD WINAPI CardAcquireContext(__inout PCARD_DATA pCardData, __in DWORD dwFlags (unsigned long)GetCurrentProcessId(), (unsigned long)GetCurrentThreadId(), pCardData); logprintf(pCardData, 1, - "CardAcquireContext, dwVersion=%lu, name=%S,hScard=0x%08X, hSCardCtx=0x%08X\n", + "CardAcquireContext, dwVersion=%lu, name=%S,hScard=0x%08"SC_FORMAT_LEN_SIZE_T"X, hSCardCtx=0x%08"SC_FORMAT_LEN_SIZE_T"X\n", (unsigned long)pCardData->dwVersion, NULLWSTR(pCardData->pwszCardName), - (unsigned int)pCardData->hScard, - (unsigned int)pCardData->hSCardCtx); + (size_t)pCardData->hScard, + (size_t)pCardData->hSCardCtx); vs->hScard = pCardData->hScard; vs->hSCardCtx = pCardData->hSCardCtx; From 72836fa3cb82705ab545c44282d546f91d54892b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 16:27:06 +0100 Subject: [PATCH 031/189] Fixed Dereference before null check As reported by coverity scan --- src/libopensc/card-idprime.c | 2 +- src/pkcs15init/pkcs15-lib.c | 2 +- src/tools/pkcs15-crypt.c | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c index 7399830a..744d5189 100644 --- a/src/libopensc/card-idprime.c +++ b/src/libopensc/card-idprime.c @@ -505,7 +505,7 @@ static int idprime_select_file(sc_card_t *card, const sc_path_t *in_path, sc_fil priv->cached = 0; r = iso_ops->select_file(card, in_path, file_out); - if (r == SC_SUCCESS && priv && file_out != NULL) { + if (r == SC_SUCCESS && file_out != NULL) { /* Try to read first bytes of the file to fix FCI in case of * compressed certififcate */ len = iso_ops->read_binary(card, 0, data, data_len, 0); diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 830c2007..2b28bce0 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -1871,7 +1871,7 @@ sc_pkcs15init_store_public_key(struct sc_pkcs15_card *p15card, struct sc_profile profile->dirty = 1; err: - if (object && r < 0) + if (r < 0) sc_pkcs15init_free_object(object); LOG_FUNC_RETURN(ctx, r); diff --git a/src/tools/pkcs15-crypt.c b/src/tools/pkcs15-crypt.c index 763510ed..d7ce7b95 100644 --- a/src/tools/pkcs15-crypt.c +++ b/src/tools/pkcs15-crypt.c @@ -132,8 +132,12 @@ static char * get_pin(struct sc_pkcs15_object *obj) { char buf[(sizeof obj->label) + 20]; char *pincode; - struct sc_pkcs15_auth_info *pinfo = (struct sc_pkcs15_auth_info *) obj->data; + struct sc_pkcs15_auth_info *pinfo; + if (!obj) + return NULL; + + pinfo = (struct sc_pkcs15_auth_info *) obj->data; if (pinfo->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return NULL; From 094aa6863211209f888c6a83e15a88dd0c99113c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 17:14:14 +0100 Subject: [PATCH 032/189] fixed Explicit null dereferenced Thanks to Coverity Scan --- src/libopensc/compression.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/libopensc/compression.c b/src/libopensc/compression.c index 00c7f707..3c8352d2 100644 --- a/src/libopensc/compression.c +++ b/src/libopensc/compression.c @@ -51,17 +51,21 @@ static int zerr_to_opensc(int err) { } } static int detect_method(const u8* in, size_t inLen) { - if(inLen > 2 && in[0] == 0x1f && in[1] == 0x8b) { /* GZIP */ - return COMPRESSION_GZIP; - } else if(inLen > 1 /*&& (in[0] & 0x10) == Z_DEFLATED*/) { - /* REALLY SIMPLE ZLIB TEST -- - * Check for the compression method to be set to 8... - * many things can spoof this, but this is ok for now - * */ + if (in != NULL && inLen > 1) { + if (inLen > 2 && in[0] == 0x1f && in[1] == 0x8b) + return COMPRESSION_GZIP; +#if 0 + if ((in[0] & 0x10) == Z_DEFLATED) + /* REALLY SIMPLE ZLIB TEST -- + * Check for the compression method to be set to 8... + * many things can spoof this, but this is ok for now + * */ + return COMPRESSION_ZLIB; +#else return COMPRESSION_ZLIB; - } else { - return COMPRESSION_UNKNOWN; +#endif } + return COMPRESSION_UNKNOWN; } static int sc_compress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLen) { From d138522e33f1e84b52ddbca35bc3ef895dc528ea Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 17:24:30 +0100 Subject: [PATCH 033/189] added detection of zlib compression ... and always set outLen to 0 in case of an error in sc_decompress --- src/libopensc/compression.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/libopensc/compression.c b/src/libopensc/compression.c index 3c8352d2..3dfd0ead 100644 --- a/src/libopensc/compression.c +++ b/src/libopensc/compression.c @@ -52,18 +52,28 @@ static int zerr_to_opensc(int err) { } static int detect_method(const u8* in, size_t inLen) { if (in != NULL && inLen > 1) { - if (inLen > 2 && in[0] == 0x1f && in[1] == 0x8b) + if (in[0] == 0x1f && in[1] == 0x8b) return COMPRESSION_GZIP; -#if 0 - if ((in[0] & 0x10) == Z_DEFLATED) - /* REALLY SIMPLE ZLIB TEST -- - * Check for the compression method to be set to 8... - * many things can spoof this, but this is ok for now - * */ + /* + * A zlib stream has the following structure: + * 0 1 + * +---+---+ + * |CMF|FLG| (more-->) + * +---+---+ + * + * FLG (FLaGs) + * This flag byte is divided as follows: + * + * bits 0 to 4 FCHECK (check bits for CMF and FLG) + * bit 5 FDICT (preset dictionary) + * bits 6 to 7 FLEVEL (compression level) + * + * The FCHECK value must be such that CMF and FLG, when viewed as + * a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), + * is a multiple of 31. + */ + if ((((uint16_t) in[0])*256 + in[1]) % 31 == 0) return COMPRESSION_ZLIB; -#else - return COMPRESSION_ZLIB; -#endif } return COMPRESSION_UNKNOWN; } @@ -105,8 +115,10 @@ static int sc_decompress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLe gz.next_out = out; gz.avail_out = *outLen; + *outLen = 0; + err = inflateInit2(&gz, window_size); - if(err != Z_OK) return zerr_to_opensc(err); + if (err != Z_OK) return zerr_to_opensc(err); err = inflate(&gz, Z_FINISH); if(err != Z_STREAM_END) { inflateEnd(&gz); @@ -144,7 +156,8 @@ int sc_decompress(u8* out, size_t* outLen, const u8* in, size_t inLen, int metho if(method == COMPRESSION_AUTO) { method = detect_method(in, inLen); - if(method == COMPRESSION_UNKNOWN) { + if (method == COMPRESSION_UNKNOWN) { + *outLen = 0; return SC_ERROR_UNKNOWN_DATA_RECEIVED; } } From 40b3aeb6266af5bb7d4c94798ed54a71ced6f083 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 21:03:20 +0100 Subject: [PATCH 034/189] travis: output results of unittests on errors --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c565a8e2..3892168e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -283,7 +283,7 @@ script: fi - if [ "${DO_SIMULATION}" = "cac" ]; then cd $TRAVIS_BUILD_DIR; - make check && sudo make install || (cat tests/*log && exit); + make check && sudo make install || (cat tests/*log src/tests/unittests/*log && exit); export LD_LIBRARY_PATH=/usr/local/lib; cd src/tests/p11test/; ./p11test -s 0 -p 12345678 -i & From 8db1cbe35f5d05cb8aaed1fbd9b8f235e483507a Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 21:48:46 +0100 Subject: [PATCH 035/189] use a more explicit assignment --- src/libopensc/card-gpk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-gpk.c b/src/libopensc/card-gpk.c index 4144057c..2bfcdde1 100644 --- a/src/libopensc/card-gpk.c +++ b/src/libopensc/card-gpk.c @@ -749,8 +749,10 @@ gpk_compute_crycks(sc_card_t *card, sc_apdu_t *apdu, block[len++] = apdu->p1; block[len++] = apdu->p2; block[len++] = apdu->lc + 3; - if ((i = apdu->datalen) + len > sizeof(block)) + if (apdu->datalen + len > sizeof(block)) i = sizeof(block) - len; + else + i = apdu->datalen; memcpy(block+len, apdu->data, i); len += i; From 3dede423e640e50032d877573f8047e60e5da48b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 21:56:11 +0100 Subject: [PATCH 036/189] fixed Out-of-bounds access Thanks to Coverity scan --- src/libopensc/card-setcos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-setcos.c b/src/libopensc/card-setcos.c index 2d3692cc..859f72fd 100644 --- a/src/libopensc/card-setcos.c +++ b/src/libopensc/card-setcos.c @@ -476,7 +476,7 @@ static int setcos_create_file_44(sc_card_t *card, sc_file_t *file) sc_log(card->ctx, "SetCOS 4.4 PIN refs can only be 1..7\n"); return SC_ERROR_INVALID_ARGUMENTS; } - bCommands_pin[setcos_pin_index_44(pins, sizeof(pins), (int) bNumber)] |= 1 << i; + bCommands_pin[setcos_pin_index_44(pins, sizeof(pins)/sizeof(pins[0]), (int) bNumber)] |= 1 << i; break; case SC_AC_TERM: /* key */ bKeyNumber = bNumber; /* There should be only 1 key */ From 5475dbcb3ca705e1a29256cdd1b452d89936af74 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 22:03:12 +0100 Subject: [PATCH 037/189] fixed Uninitialized scalar variable Thanks to Coverity Scan --- src/tools/opensc-explorer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index fb116546..1ac9a89f 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -653,6 +653,8 @@ static int do_find_tags(int argc, char **argv) r = sc_lock(card); if (r == SC_SUCCESS) r = sc_get_data(card, tag, rbuf, sizeof rbuf); + else + r = SC_ERROR_READER_LOCKED; sc_unlock(card); if (r >= 0) { printf(" %04X ", tag); @@ -792,6 +794,8 @@ static int read_and_print_record_file(sc_file_t *file, unsigned char sfi) if (r == SC_SUCCESS) r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR | sfi); + else + r = SC_ERROR_READER_LOCKED; sc_unlock(card); if (r == SC_ERROR_RECORD_NOT_FOUND) return 0; From 3687f71bf7fc239ac726f8303b21f4c9b51a5a08 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 22:08:10 +0100 Subject: [PATCH 038/189] fixed 123497 Dereference after null check Thanks to Coverity Scan --- src/libopensc/card-gids.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card-gids.c b/src/libopensc/card-gids.c index d775175d..e434d347 100644 --- a/src/libopensc/card-gids.c +++ b/src/libopensc/card-gids.c @@ -255,11 +255,13 @@ static int gids_get_DO(sc_card_t* card, int fileIdentifier, int dataObjectIdenti if (!p) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_NOT_FOUND); } - if (datasize > *responselen) { - LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); + if (response && responselen) { + if (datasize > *responselen) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL); + } + memcpy(response, p, datasize); + *responselen = datasize; } - memcpy(response, p, datasize); - *responselen = datasize; return SC_SUCCESS; } From 723176d62f90a3d8d300d292f3fc7404c8200607 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 22:23:37 +0100 Subject: [PATCH 039/189] avoid calling memcpy with length 0 --- src/libopensc/asn1.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 61da5601..bf951782 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -2154,8 +2154,10 @@ sc_asn1_sig_value_sequence_to_rs(struct sc_context *ctx, const unsigned char *in } memset(buf, 0, buflen); - memcpy(buf + (halflen - r_len), r, r_len); - memcpy(buf + (buflen - s_len), s, s_len); + if (r_len > 0) + memcpy(buf + (halflen - r_len), r, r_len); + if (s_len > 0) + memcpy(buf + (buflen - s_len), s, s_len); sc_log(ctx, "r(%"SC_FORMAT_LEN_SIZE_T"u): %s", halflen, sc_dump_hex(buf, halflen)); From c339136c737b991ce6e1b50bdb8ec18dd85c7eb5 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 22:34:51 +0100 Subject: [PATCH 040/189] tccardos: fixed freeing file object --- src/libopensc/pkcs15-tccardos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-tccardos.c b/src/libopensc/pkcs15-tccardos.c index c9a643ae..3c245a67 100644 --- a/src/libopensc/pkcs15-tccardos.c +++ b/src/libopensc/pkcs15-tccardos.c @@ -55,7 +55,7 @@ static int read_file(struct sc_card *card, const char *file, u8 *buf, if (fid->size < *len) *len = fid->size; r = sc_read_binary(card, 0, buf, *len, 0); - free(fid); + sc_file_free(fid); if ((size_t)r < *len) return SC_ERROR_INTERNAL; From f1044f3645ff3c182166fc43cc7a9b35c4f6b76c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Jan 2020 22:38:29 +0100 Subject: [PATCH 041/189] tccardos: fixed error checking --- src/libopensc/pkcs15-tccardos.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-tccardos.c b/src/libopensc/pkcs15-tccardos.c index 3c245a67..f78c9d7c 100644 --- a/src/libopensc/pkcs15-tccardos.c +++ b/src/libopensc/pkcs15-tccardos.c @@ -50,8 +50,10 @@ static int read_file(struct sc_card *card, const char *file, u8 *buf, sc_format_path(file, &path); r = sc_select_file(card, &path, &fid); - if (r != SC_SUCCESS || !fid) + if (r != SC_SUCCESS) return r; + if (!fid) + return SC_ERROR_INTERNAL; if (fid->size < *len) *len = fid->size; r = sc_read_binary(card, 0, buf, *len, 0); From e9308a2011358e004772da9924d290b7abb01e11 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 1 Feb 2020 00:54:58 +0100 Subject: [PATCH 042/189] addeed zlib test data --- src/tests/unittests/compression.c | 64 ++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/src/tests/unittests/compression.c b/src/tests/unittests/compression.c index d1b7a4d7..f0c114d9 100644 --- a/src/tests/unittests/compression.c +++ b/src/tests/unittests/compression.c @@ -63,6 +63,22 @@ u8 invalid_suffix_data[] = { 0xb9, 0x3b, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}; +/* https://github.com/madler/zlib/blob/master/test/infcover.c + */ +u8 zlib_good[] = {0x78, 0x9c, 0x63, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1}; + +/* Generated using + * $ echo "test" > /tmp/test + * $ pigz --zlib /tmp/test > /tmp/test.zz + * $ hexdump -C /tmp/test.zz + */ +u8 valid_zlib_data[] = {0x78, 0x5e, 0x2b, 0x49, 0x2d, 0x2e, 0xe1, 0x02, 0x00, 0x06, 0x28, 0x01, 0xcb}; + +/* Generated as in the previous test case with some added mess on the end + */ +u8 invalid_zlib_suffix_data[] = {0x78, 0x5e, 0x2b, 0x49, 0x2d, 0x2e, 0xe1, 0x02, 0x00, 0x06, 0x28, 0x01, 0xcb, + 0xff, 0xff, 0xff, 0xff}; + static void torture_compression_decompress_alloc_empty(void **state) { u8 *buf = NULL; @@ -150,10 +166,14 @@ static void torture_compression_decompress_alloc_valid(void **state) { u8 *buf = NULL; size_t buflen = 0; - size_t datalen = sizeof(valid_data); int rv; - rv = sc_decompress_alloc(&buf, &buflen, valid_data, datalen, COMPRESSION_AUTO); + rv = sc_decompress_alloc(&buf, &buflen, valid_data, sizeof(valid_data), COMPRESSION_AUTO); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(buflen, 5); + assert_memory_equal(buf, "test\x0a", 5); + + rv = sc_decompress_alloc(&buf, &buflen, valid_zlib_data, sizeof(valid_zlib_data), COMPRESSION_AUTO); assert_int_equal(rv, SC_SUCCESS); assert_int_equal(buflen, 5); assert_memory_equal(buf, "test\x0a", 5); @@ -163,10 +183,14 @@ static void torture_compression_decompress_alloc_invalid_suffix(void **state) { u8 *buf = NULL; size_t buflen = 0; - size_t datalen = sizeof(invalid_suffix_data); int rv; - rv = sc_decompress_alloc(&buf, &buflen, invalid_suffix_data, datalen, COMPRESSION_AUTO); + rv = sc_decompress_alloc(&buf, &buflen, invalid_suffix_data, sizeof(invalid_suffix_data), COMPRESSION_AUTO); + assert_int_equal(rv, SC_SUCCESS); /* TODO Is this fine? */ + assert_int_equal(buflen, 5); + assert_memory_equal(buf, "test\x0a", 5); + + rv = sc_decompress_alloc(&buf, &buflen, invalid_zlib_suffix_data, sizeof(invalid_zlib_suffix_data), COMPRESSION_AUTO); assert_int_equal(rv, SC_SUCCESS); /* TODO Is this fine? */ assert_int_equal(buflen, 5); assert_memory_equal(buf, "test\x0a", 5); @@ -185,7 +209,7 @@ static void torture_compression_decompress_empty(void **state) rv = sc_decompress(buf, &buflen, data, datalen, COMPRESSION_AUTO); assert_int_equal(rv, SC_ERROR_UNKNOWN_DATA_RECEIVED); - assert_int_equal(buflen, sizeof(buf)); /* Was not touched */ + assert_int_equal(buflen, 0); } static void torture_compression_decompress_gzip_empty(void **state) @@ -198,7 +222,7 @@ static void torture_compression_decompress_gzip_empty(void **state) rv = sc_decompress(buf, &buflen, data, datalen, COMPRESSION_GZIP); assert_int_equal(rv, SC_ERROR_UNKNOWN_DATA_RECEIVED); - assert_int_equal(buflen, sizeof(buf)); + assert_int_equal(buflen, 0); } static void torture_compression_decompress_zlib_empty(void **state) @@ -256,10 +280,14 @@ static void torture_compression_decompress_valid(void **state) { u8 buf[1024]; size_t buflen = sizeof(buf); - size_t datalen = sizeof(valid_data); int rv; - rv = sc_decompress(buf, &buflen, valid_data, datalen, COMPRESSION_AUTO); + rv = sc_decompress(buf, &buflen, valid_data, sizeof(valid_data), COMPRESSION_AUTO); + assert_int_equal(rv, SC_SUCCESS); + assert_int_equal(buflen, 5); + assert_memory_equal(buf, "test\x0a", 5); + + rv = sc_decompress(buf, &buflen, valid_zlib_data, sizeof(valid_zlib_data), COMPRESSION_AUTO); assert_int_equal(rv, SC_SUCCESS); assert_int_equal(buflen, 5); assert_memory_equal(buf, "test\x0a", 5); @@ -269,13 +297,28 @@ static void torture_compression_decompress_invalid_suffix(void **state) { u8 buf[1024]; size_t buflen = sizeof(buf); - size_t datalen = sizeof(invalid_suffix_data); int rv; - rv = sc_decompress(buf, &buflen, invalid_suffix_data, datalen, COMPRESSION_AUTO); + rv = sc_decompress(buf, &buflen, invalid_suffix_data, sizeof(invalid_suffix_data), COMPRESSION_AUTO); assert_int_equal(rv, SC_SUCCESS); /* TODO Is this fine? */ assert_int_equal(buflen, 5); assert_memory_equal(buf, "test\x0a", 5); + + rv = sc_decompress(buf, &buflen, invalid_zlib_suffix_data, sizeof(invalid_zlib_suffix_data), COMPRESSION_AUTO); + assert_int_equal(rv, SC_SUCCESS); /* TODO Is this fine? */ + assert_int_equal(buflen, 5); + assert_memory_equal(buf, "test\x0a", 5); +} + +static void torture_compression_decompress_zlib_good(void **state) +{ + u8 buf[1024]; + size_t buflen; + int rv; + + buflen = sizeof(buf); + rv = sc_decompress(buf, &buflen, zlib_good, sizeof zlib_good, COMPRESSION_AUTO); + assert_int_equal(rv, SC_SUCCESS); } @@ -302,6 +345,7 @@ int main(void) cmocka_unit_test(torture_compression_decompress_invalid), cmocka_unit_test(torture_compression_decompress_invalid_suffix), cmocka_unit_test(torture_compression_decompress_valid), + cmocka_unit_test(torture_compression_decompress_zlib_good), }; rc = cmocka_run_group_tests(tests, NULL, NULL); From 09531d720a5e955d6c9307a33d0240ead892768f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 29 Jan 2020 15:07:24 +0100 Subject: [PATCH 043/189] cac: Avoid stack overflow on infinite recursion in CCC chaining Thanks oss-fuzz Fixes: #1920 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19725 --- src/libopensc/card-cac.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c index 2c9361df..6970d0f4 100644 --- a/src/libopensc/card-cac.c +++ b/src/libopensc/card-cac.c @@ -106,6 +106,8 @@ #define CAC_ACR_AMP 0x20 #define CAC_ACR_SERVICE 0x21 +#define CAC_MAX_CCC_DEPTH 16 + /* hardware data structures (returned in the CCC) */ /* part of the card_url */ typedef struct cac_access_profile { @@ -1420,10 +1422,10 @@ static int cac_parse_cuid(sc_card_t *card, cac_private_data_t *priv, cac_cuid_t priv->cac_id_len = card_id_len; return SC_SUCCESS; } -static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv); +static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv, int depth); static int cac_parse_CCC(sc_card_t *card, cac_private_data_t *priv, const u8 *tl, - size_t tl_len, u8 *val, size_t val_len) + size_t tl_len, u8 *val, size_t val_len, int depth) { size_t len = 0; const u8 *tl_end = tl + tl_len; @@ -1520,7 +1522,8 @@ static int cac_parse_CCC(sc_card_t *card, cac_private_data_t *priv, const u8 *tl if (r < 0) return r; - r = cac_process_CCC(card, priv); + /* Increase depth to avoid infinite recursion */ + r = cac_process_CCC(card, priv, depth + 1); if (r < 0) return r; break; @@ -1533,12 +1536,16 @@ static int cac_parse_CCC(sc_card_t *card, cac_private_data_t *priv, const u8 *tl return SC_SUCCESS; } -static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv) +static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv, int depth) { u8 *tl = NULL, *val = NULL; size_t tl_len, val_len; int r; + if (depth < 0) { + sc_log(card->ctx, "Too much recursive CCC found. Exiting"); + return SC_ERROR_INVALID_CARD; + } r = cac_read_file(card, CAC_FILE_TAG, &tl, &tl_len); if (r < 0) @@ -1548,7 +1555,7 @@ static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv) if (r < 0) goto done; - r = cac_parse_CCC(card, priv, tl, tl_len, val, val_len); + r = cac_parse_CCC(card, priv, tl, tl_len, val, val_len, depth); done: if (tl) free(tl); @@ -1775,7 +1782,7 @@ static int cac_find_and_initialize(sc_card_t *card, int initialize) priv = cac_new_private_data(); if (!priv) return SC_ERROR_OUT_OF_MEMORY; - r = cac_process_CCC(card, priv); + r = cac_process_CCC(card, priv, CAC_MAX_CCC_DEPTH); if (r == SC_SUCCESS) { card->type = SC_CARD_TYPE_CAC_II; card->drv_data = priv; From 2a0f53dd4f7d8db2b1b320223655f7041205438a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 29 Jan 2020 16:38:58 +0100 Subject: [PATCH 044/189] coolkey: Avoid heap buffer overflow for malformend combinded objects, the ID and header were parsed before making sure we have at least that lenght available. Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20131 --- src/libopensc/card-coolkey.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c index 19c17f68..24c5a114 100644 --- a/src/libopensc/card-coolkey.c +++ b/src/libopensc/card-coolkey.c @@ -2063,13 +2063,24 @@ coolkey_process_combined_object(sc_card_t *card, coolkey_private_data_t *priv, u priv->token_name_length = decompressed_header->token_name_length; - for (i=0; i < object_count && object_offset < decompressed_object_len; i++ ) { - u8 *current_object = &decompressed_object[object_offset]; - coolkey_combined_object_header_t *object_header = - (coolkey_combined_object_header_t *)current_object; - unsigned long object_id = bebytes2ulong(object_header->object_id); + for (i=0; i < object_count; i++) { + u8 *current_object = NULL; + coolkey_combined_object_header_t *object_header = NULL; + unsigned long object_id; int current_object_len; + /* Can we read the object header at all? */ + if ((object_offset + sizeof(coolkey_combined_object_header_t)) > decompressed_object_len) { + r = SC_ERROR_CORRUPTED_DATA; + goto done; + } + + current_object = &decompressed_object[object_offset]; + object_header = (coolkey_combined_object_header_t *)current_object; + + /* Parse object ID */ + object_id = bebytes2ulong(object_header->object_id); + /* figure out how big it is */ r = coolkey_v1_get_object_length(current_object, decompressed_object_len-object_offset); if (r < 0) { From 63435adc68ae3f0a83f89351f70a329a5d9c2953 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 29 Jan 2020 16:57:37 +0100 Subject: [PATCH 045/189] coolkey: Do not return bogus error if read already failed --- src/libopensc/card-coolkey.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c index 24c5a114..ce22b3f2 100644 --- a/src/libopensc/card-coolkey.c +++ b/src/libopensc/card-coolkey.c @@ -1382,6 +1382,9 @@ coolkey_fill_object(sc_card_t *card, sc_cardctl_coolkey_object_t *obj) priv->nonce, sizeof(priv->nonce)); if (r != (int)buf_len) { free(new_obj_data); + if (r < 0) { + LOG_FUNC_RETURN(card->ctx, r); + } LOG_FUNC_RETURN(card->ctx, SC_ERROR_CORRUPTED_DATA); } obj_entry = coolkey_find_object_by_id(&priv->objects_list, obj->id); From 34dad7f543f006ad269ce1f935a9e8d3e3a83db7 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 3 Feb 2020 16:40:51 +0100 Subject: [PATCH 046/189] idprime: Add missing terminator in ATR list Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20510 --- src/libopensc/card-idprime.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c index 744d5189..9f5adde9 100644 --- a/src/libopensc/card-idprime.c +++ b/src/libopensc/card-idprime.c @@ -52,6 +52,7 @@ static const struct sc_atr_table idprime_atrs[] = { "ff:ff:00:ff:ff:ff:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:ff:ff", "Gemalto IDPrime MD 8840, 3840, 3810, 840 and 830 Cards", SC_CARD_TYPE_IDPRIME_GENERIC, 0, NULL }, + { NULL, NULL, NULL, 0, 0, NULL } }; static const sc_path_t idprime_path = { From 2f7d0cf20f7dc844cf20dd4d540d737d6801f1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charl=C3=A8ne?= Date: Wed, 5 Feb 2020 11:08:00 +0100 Subject: [PATCH 047/189] Put user supplied CFLAGS on top priority --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e73dc9bd..45e169bf 100644 --- a/configure.ac +++ b/configure.ac @@ -1072,10 +1072,10 @@ AS_IF([test "${enable_shared}" = "yes"], [AC_DEFINE([ENABLE_SHARED], [1], [Enabl if test "${enable_pedantic}" = "yes"; then enable_strict="yes"; - CFLAGS="${CFLAGS} -pedantic" + CFLAGS="-pedantic ${CFLAGS}" fi if test "${enable_strict}" = "yes"; then - CFLAGS="${CFLAGS} -Wall -Wextra -Wno-unused-parameter -Werror" + CFLAGS="-Wall -Wextra -Wno-unused-parameter -Werror ${CFLAGS}" fi AC_CONFIG_FILES([ From 8e466ad56830e534ac164fae6ffbbee21ab615c4 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 08:58:26 +0100 Subject: [PATCH 048/189] OpenPGP: add 3 more OpenPGP card vendors * taken from GnuPG's git --- src/libopensc/pkcs15-openpgp.c | 41 ++++++++++++++++++---------------- src/tools/openpgp-tool.c | 3 +++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c index 28b2b70f..78366e01 100644 --- a/src/libopensc/pkcs15-openpgp.c +++ b/src/libopensc/pkcs15-openpgp.c @@ -105,25 +105,28 @@ typedef struct _pgp_manuf_map { } pgp_manuf_map_t; static const pgp_manuf_map_t manuf_map[] = { - { 0x0001, "PPC Card Systems" }, - { 0x0002, "Prism" }, - { 0x0003, "OpenFortress" }, - { 0x0004, "Wewid AB" }, - { 0x0005, "ZeitControl" }, - { 0x0006, "Yubico" }, - { 0x0007, "OpenKMS" }, - { 0x0008, "LogoEmail" }, - { 0x0009, "Fidesmo" }, - { 0x000A, "Dangerous Things" }, - { 0x002A, "Magrathea" }, - { 0x0042, "GnuPG e.V." }, - { 0x1337, "Warsaw Hackerspace" }, - { 0x2342, "warpzone" }, - { 0x63AF, "Trustica" }, - { 0xBD0E, "Paranoidlabs" }, - { 0xF517, "FSIJ" }, - { 0x0000, "test card" }, - { 0xffff, "test card" }, + { 0x0001, "PPC Card Systems" }, + { 0x0002, "Prism" }, + { 0x0003, "OpenFortress" }, + { 0x0004, "Wewid AB" }, + { 0x0005, "ZeitControl" }, + { 0x0006, "Yubico" }, + { 0x0007, "OpenKMS" }, + { 0x0008, "LogoEmail" }, + { 0x0009, "Fidesmo" }, + { 0x000A, "Dangerous Things" }, + { 0x000B, "Feitian Technologies" }, + { 0x002A, "Magrathea" }, + { 0x0042, "GnuPG e.V." }, + { 0x1337, "Warsaw Hackerspace" }, + { 0x2342, "warpzone" }, + { 0x4354, "Confidential Technologies" }, + { 0x5443, "TIF-IT e.V." }, + { 0x63AF, "Trustica" }, + { 0xBD0E, "Paranoidlabs" }, + { 0xF517, "FSIJ" }, + { 0x0000, "test card" }, + { 0xffff, "test card" }, { 0, NULL } }; diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index 3d686b87..1d13d0a0 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -293,12 +293,15 @@ static char *prettify_manufacturer(u8 *data, size_t length) case 0x0008: return "LogoEmail"; case 0x0009: return "Fidesmo"; case 0x000A: return "Dangerous Things"; + case 0x000B: return "Feitian Technologies"; case 0x002A: return "Magrathea"; case 0x0042: return "GnuPG e.V."; case 0x1337: return "Warsaw Hackerspace"; case 0x2342: return "warpzone"; /* hackerspace Muenster. */ + case 0x4354: return "Confidential Technologies"; /* cotech.de */ + case 0x5443: return "TIF-IT e.V."; case 0x63AF: return "Trustica"; case 0xBD0E: return "Paranoidlabs"; case 0xF517: return "FSIJ"; From d7e02d3bf5cfdfb5d8a954c4a42b831598a32677 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 4 Feb 2020 14:05:07 +0100 Subject: [PATCH 049/189] fixed memory leak Fixes https://oss-fuzz.com/testcase-detail/5151975710916608 --- src/libopensc/card-epass2003.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c index 26b9d79f..5d5eb520 100644 --- a/src/libopensc/card-epass2003.c +++ b/src/libopensc/card-epass2003.c @@ -1157,6 +1157,7 @@ epass2003_init(struct sc_card *card) unsigned char data[SC_MAX_APDU_BUFFER_SIZE] = { 0 }; size_t datalen = SC_MAX_APDU_BUFFER_SIZE; epass2003_exdata *exdata = NULL; + void *old_drv_data = card->drv_data; LOG_FUNC_CALLED(card->ctx); @@ -1171,8 +1172,11 @@ epass2003_init(struct sc_card *card) exdata->sm = SM_SCP01; /* decide FIPS/Non-FIPS mode */ - if (SC_SUCCESS != get_data(card, 0x86, data, datalen)) + if (SC_SUCCESS != get_data(card, 0x86, data, datalen)) { + free(exdata); + card->drv_data = old_drv_data; return SC_ERROR_INVALID_CARD; + } if (0x01 == data[2]) exdata->smtype = KEY_TYPE_AES; From 2493c5de07f6df1b0c20b4882a8d35fe8f7bb2cc Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 4 Feb 2020 14:10:43 +0100 Subject: [PATCH 050/189] fixed memory leak fixes https://oss-fuzz.com/testcase-detail/6237284133502976 --- src/libopensc/card-dnie.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index ce0bc33a..adc5a871 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -1161,8 +1161,6 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa int res = 0; sc_apdu_t apdu; u8 rbuf[MAX_RESP_BUFFER_SIZE]; - sc_file_t *file = NULL; - sc_context_t *ctx = NULL; if (!card || !card->ctx) @@ -1199,14 +1197,15 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); } - /* finally process FCI response */ - file = sc_file_new(); - if (file == NULL) { - LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + if (file_out) { + /* finally process FCI response */ + sc_file_free(*file_out); + *file_out = sc_file_new(); + if (*file_out == NULL) { + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + } + res = card->ops->process_fci(card, *file_out, apdu.resp + 2, apdu.resp[1]); } - res = card->ops->process_fci(card, file, apdu.resp + 2, apdu.resp[1]); - sc_file_free(*file_out); - *file_out = file; LOG_FUNC_RETURN(ctx, res); } From ea2991ea69ca77a60dbfc5a3dcd5a8e6cd074c5e Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 4 Feb 2020 14:20:15 +0100 Subject: [PATCH 051/189] fixed memory leak also, use sc_file_free instead of free fixes https://oss-fuzz.com/testcase-detail/4905082200260608 --- src/libopensc/pkcs15-atrust-acos.c | 3 +-- src/libopensc/pkcs15-dnie.c | 3 +++ src/libopensc/pkcs15-gemsafeV1.c | 3 +-- src/libopensc/pkcs15-pteid.c | 3 +-- src/libopensc/pkcs15-starcert.c | 3 +-- src/libopensc/pkcs15-tccardos.c | 3 +-- src/libopensc/pkcs15.c | 1 + 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/libopensc/pkcs15-atrust-acos.c b/src/libopensc/pkcs15-atrust-acos.c index c4b19e80..09a80fa0 100644 --- a/src/libopensc/pkcs15-atrust-acos.c +++ b/src/libopensc/pkcs15-atrust-acos.c @@ -253,8 +253,7 @@ static int sc_pkcs15emu_atrust_acos_init(sc_pkcs15_card_t *p15card) if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ - if (p15card->file_app) - free(p15card->file_app); + sc_file_free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; diff --git a/src/libopensc/pkcs15-dnie.c b/src/libopensc/pkcs15-dnie.c index f4b144e4..92a602c5 100644 --- a/src/libopensc/pkcs15-dnie.c +++ b/src/libopensc/pkcs15-dnie.c @@ -169,7 +169,10 @@ static int sc_pkcs15emu_dnie_init(sc_pkcs15_card_t * p15card) } /* Set root path of this application */ + sc_file_free(p15card->file_app); p15card->file_app = sc_file_new(); + if (NULL == p15card->file_app) + LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY); sc_format_path("3F00", &p15card->file_app->path); /* Load TokenInfo */ diff --git a/src/libopensc/pkcs15-gemsafeV1.c b/src/libopensc/pkcs15-gemsafeV1.c index 074fedd3..4e945157 100644 --- a/src/libopensc/pkcs15-gemsafeV1.c +++ b/src/libopensc/pkcs15-gemsafeV1.c @@ -425,8 +425,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ - if (p15card->file_app) - free(p15card->file_app); + sc_file_free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; diff --git a/src/libopensc/pkcs15-pteid.c b/src/libopensc/pkcs15-pteid.c index 483fc402..e1ca787f 100644 --- a/src/libopensc/pkcs15-pteid.c +++ b/src/libopensc/pkcs15-pteid.c @@ -163,8 +163,7 @@ static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card) if (rv != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ - if (p15card->file_app) - free(p15card->file_app); + sc_file_free(p15card->file_app); p15card->file_app = file; /* Load TokenInfo */ diff --git a/src/libopensc/pkcs15-starcert.c b/src/libopensc/pkcs15-starcert.c index f6394faa..e8c670ca 100644 --- a/src/libopensc/pkcs15-starcert.c +++ b/src/libopensc/pkcs15-starcert.c @@ -261,8 +261,7 @@ static int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card) if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ - if (p15card->file_app) - free(p15card->file_app); + sc_file_free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; diff --git a/src/libopensc/pkcs15-tccardos.c b/src/libopensc/pkcs15-tccardos.c index f78c9d7c..f1039fd3 100644 --- a/src/libopensc/pkcs15-tccardos.c +++ b/src/libopensc/pkcs15-tccardos.c @@ -345,8 +345,7 @@ static int sc_pkcs15_tccardos_init_func(sc_pkcs15_card_t *p15card) if (r != SC_SUCCESS || file == NULL) return SC_ERROR_INTERNAL; /* set the application DF */ - if (p15card->file_app) - free(p15card->file_app); + sc_file_free(p15card->file_app; p15card->file_app = file; return SC_SUCCESS; diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index aa541264..e474803d 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -966,6 +966,7 @@ sc_pkcs15_bind_internal(struct sc_pkcs15_card *p15card, struct sc_aid *aid) if (err != SC_SUCCESS) sc_log(ctx, "unable to enumerate apps: %s", sc_strerror(err)); } + sc_file_free(p15card->file_app); p15card->file_app = sc_file_new(); if (p15card->file_app == NULL) { err = SC_ERROR_OUT_OF_MEMORY; From a0e1bf7ae5c23a8ceccc851353162d111810f332 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 4 Feb 2020 15:25:39 +0100 Subject: [PATCH 052/189] fixed compiler error --- src/libopensc/pkcs15-tccardos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-tccardos.c b/src/libopensc/pkcs15-tccardos.c index f1039fd3..67692230 100644 --- a/src/libopensc/pkcs15-tccardos.c +++ b/src/libopensc/pkcs15-tccardos.c @@ -345,7 +345,7 @@ static int sc_pkcs15_tccardos_init_func(sc_pkcs15_card_t *p15card) if (r != SC_SUCCESS || file == NULL) return SC_ERROR_INTERNAL; /* set the application DF */ - sc_file_free(p15card->file_app; + sc_file_free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; From 1fb134138960a65ef0bd2d5bdd45af3ac472dbe7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 11 Feb 2020 04:11:13 +0100 Subject: [PATCH 053/189] ignore OpenPACE man page generation fixes https://github.com/frankmorgner/OpenSCToken/issues/26 --- MacOSX/build-package.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index ad31336e..5d9db917 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -49,7 +49,7 @@ if ! test -e $BUILDPATH/openpace_bin/$PREFIX/lib/pkgconfig; then fi cd openpace autoreconf -vis - ./configure --disable-shared --prefix=$PREFIX CRYPTO_CFLAGS="$OPENSSL_CFLAGS" CRYPTO_LIBS="$OPENSSL_LIBS" + ./configure --disable-shared --prefix=$PREFIX CRYPTO_CFLAGS="$OPENSSL_CFLAGS" CRYPTO_LIBS="$OPENSSL_LIBS" HELP2MAN=true make DESTDIR=$BUILDPATH/openpace_bin install cd .. fi From 5450f61681d0c46c587dbe789bf19f1cb573e794 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 10 Feb 2020 15:09:17 +0100 Subject: [PATCH 054/189] Unbreak build with -fno-common (default in gcc10) --- src/tests/p11test/p11test.c | 3 +++ src/tests/p11test/p11test_common.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tests/p11test/p11test.c b/src/tests/p11test/p11test.c index feecf6fb..a16282cb 100644 --- a/src/tests/p11test/p11test.c +++ b/src/tests/p11test/p11test.c @@ -34,6 +34,9 @@ #define DEFAULT_P11LIB "../../pkcs11/.libs/opensc-pkcs11.so" +/* Global variable keeping information about token we are using */ +token_info_t token; + void display_usage() { fprintf(stdout, " Usage:\n" diff --git a/src/tests/p11test/p11test_common.h b/src/tests/p11test/p11test_common.h index 2f3b238d..9eb5cede 100644 --- a/src/tests/p11test/p11test_common.h +++ b/src/tests/p11test/p11test_common.h @@ -84,7 +84,7 @@ typedef struct { size_t num_keygen_mechs; } token_info_t; -token_info_t token; +extern token_info_t token; #endif /* P11TEST_COMMON_H */ From 0d82c95a027c7680f88ad1b50d37b19dd3b100a8 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 5 Feb 2020 21:39:09 +0100 Subject: [PATCH 055/189] removed unused call to sc_detect_card_presence() --- src/pkcs11/slot.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index d72fa3fb..423457b4 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -160,12 +160,7 @@ CK_RV initialize_reader(sc_reader_t *reader) if (rv != CKR_OK) return rv; } - - sc_log(context, "Initialize reader '%s': detect SC card presence", reader->name); - if (sc_detect_card_presence(reader)) { - sc_log(context, "Initialize reader '%s': detect PKCS11 card presence", reader->name); - card_detect(reader); - } + card_detect(reader); sc_log(context, "Reader '%s' initialized", reader->name); return CKR_OK; From 6c855c561cec37a1826196a94e5a370cbfd2acb2 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 12 Feb 2020 04:48:40 +0100 Subject: [PATCH 056/189] fixed memory leak fixes https://oss-fuzz.com/testcase-detail/5739164513599488 --- src/libopensc/card-iasecc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index e3a1f55b..8054b277 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -580,6 +580,7 @@ iasecc_init(struct sc_card *card) struct sc_context *ctx = card->ctx; struct iasecc_private_data *private_data = NULL; int rv = SC_ERROR_NO_CARD_SUPPORT; + void *old_drv_data = card->drv_data; LOG_FUNC_CALLED(ctx); private_data = (struct iasecc_private_data *) calloc(1, sizeof(struct iasecc_private_data)); @@ -599,8 +600,9 @@ iasecc_init(struct sc_card *card) rv = iasecc_init_amos_or_sagem(card); else if (card->type == SC_CARD_TYPE_IASECC_MI) rv = iasecc_init_amos_or_sagem(card); - else - LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_CARD); + else { + LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_CARD, ""); + } if (!rv) { @@ -614,7 +616,7 @@ iasecc_init(struct sc_card *card) rv = iasecc_select_file(card, &path, NULL); sc_log(ctx, "Select ECC ROOT with the AID from EF.ATR: rv %i", rv); - LOG_TEST_RET(ctx, rv, "Select EF.ATR AID failed"); + LOG_TEST_GOTO_ERR(ctx, rv, "Select EF.ATR AID failed"); } iasecc_get_serialnr(card, NULL); @@ -628,6 +630,13 @@ iasecc_init(struct sc_card *card) if (!rv && card->ef_atr && card->ef_atr->aid.len) { sc_log(ctx, "EF.ATR(aid:'%s')", sc_dump_hex(card->ef_atr->aid.value, card->ef_atr->aid.len)); } + +err: + if (rv < 0) { + free(private_data); + card->drv_data = old_drv_data; + } + LOG_FUNC_RETURN(ctx, rv); } From e0b27af205f2e8e733f93237df426bd65a45526d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 13 Feb 2020 10:39:41 +0100 Subject: [PATCH 057/189] fixed Undefined-shift fixes https://oss-fuzz.com/testcase-detail/5644419049193472 --- src/libopensc/card-dnie.c | 24 ++++-------------------- src/libopensc/internal.h | 6 ++++++ src/libopensc/sc.c | 10 ++++++++++ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index adc5a871..110b3a83 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -903,22 +903,6 @@ static int dnie_finish(struct sc_card *card) /* ISO 7816-4 functions */ -/** - * Convert little-endian data into unsigned long. - * - * @param pt pointer to little-endian data - * @return equivalent long - */ -static unsigned long le2ulong(u8 * pt) -{ - unsigned long res = 0L; - if (pt==NULL) return res; - res = (0xff & *(pt + 0)) + - ((0xff & *(pt + 1)) << 8) + - ((0xff & *(pt + 2)) << 16) + ((0xff & *(pt + 3)) << 24); - return res; -} - /** * Uncompress data if in compressed format. * @@ -944,8 +928,8 @@ static u8 *dnie_uncompress(sc_card_t * card, u8 * from, size_t *len) if (*len < 8) goto compress_exit; /* evaluate compressed an uncompressed sizes (little endian format) */ - uncompressed = le2ulong(from); - compressed = le2ulong(from + 4); + uncompressed = lebytes2ulong(from); + compressed = lebytes2ulong(from + 4); /* if compressed size doesn't match data length assume not compressed */ if (compressed != (*len) - 8) goto compress_exit; @@ -1906,8 +1890,8 @@ static int dnie_read_header(struct sc_card *card) /* check response */ if (apdu.resplen != 8) goto header_notcompressed; - uncompressed = le2ulong(apdu.resp); - compressed = le2ulong(apdu.resp + 4); + uncompressed = lebytes2ulong(apdu.resp); + compressed = lebytes2ulong(apdu.resp + 4); if (uncompressed < compressed) goto header_notcompressed; if (uncompressed > 32767) diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h index 5fd9c185..3aa86a00 100644 --- a/src/libopensc/internal.h +++ b/src/libopensc/internal.h @@ -117,6 +117,12 @@ unsigned short bebytes2ushort(const u8 *buf); * @return the converted value */ unsigned short lebytes2ushort(const u8 *buf); +/** + * Convert 4 bytes in little endian order into an unsigned long + * @param buf the byte array of 4 bytes + * @return the converted value + */ +unsigned long lebytes2ulong(const u8 *buf); #define BYTES4BITS(num) (((num) + 7) / 8) /* number of bytes necessary to hold 'num' bits */ diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 7d014a34..49bf5c97 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -227,6 +227,16 @@ unsigned short lebytes2ushort(const u8 *buf) | (unsigned short)buf[0]; } +unsigned long lebytes2ulong(const u8 *buf) +{ + if (buf == NULL) + return 0UL; + return (unsigned long)buf[3] << 24 + | (unsigned long)buf[2] << 16 + | (unsigned long)buf[1] << 8 + | (unsigned long)buf[0]; +} + void sc_init_oid(struct sc_object_id *oid) { int ii; From cd5c91b8efba5741a6046e4b82a6ecedfefd837f Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 2 Feb 2020 11:14:24 +0100 Subject: [PATCH 058/189] iso7816: extend iso7816_process_fci() * define file type SC_FILE_TYPE_UNKNOWN * explicitly set file->type to SC_FILE_TYPE_UNKNOWN for unkown files * store full-length file type attributes via sc_file_set_type_attr() * parse # of records for record-oriented EFs * parse record length for for EFs with fixed-size records Note: I am not sure, parsing the record length only for EFs with fixed- size records is the correct approach. My interpretation of the norm is slightly different, but it seems to be in-line what's currently in opensc: - there's a comment hinting at that interpretation - otherwise variable size records fail to be read in opensc-explorer So I leave it this way for now. --- src/libopensc/iso7816.c | 25 ++++++++++++++++++++++++- src/libopensc/types.h | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index e1fc6d86..a8aad766 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -387,13 +387,36 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file, file->type = SC_FILE_TYPE_DF; break; default: + file->type = SC_FILE_TYPE_UNKNOWN; type = "unknown"; break; } sc_log(ctx, " type: %s", type); sc_log(ctx, " EF structure: %d", byte & 0x07); sc_log(ctx, " tag 0x82: 0x%02x", byte); - if (SC_SUCCESS != sc_file_set_type_attr(file, &byte, 1)) + + /* if possible, get additional information for non-DFs */ + if (file->type != SC_FILE_TYPE_DF) { + /* record length for fixed size records */ + if (length > 2 && byte & 0x02) { + file->record_length = (length > 3) + ? bebytes2ushort(p+2) + : p[2]; + sc_log(ctx, " record length: %"SC_FORMAT_LEN_SIZE_T"u", + file->record_length); + } + + /* number of records */ + if (length > 4) { + file->record_count = (length > 5) + ? bebytes2ushort(p+4) + : p[4]; + sc_log(ctx, " records: %"SC_FORMAT_LEN_SIZE_T"u", + file->record_count); + } + } + + if (SC_SUCCESS != sc_file_set_type_attr(file, p, length)) sc_log(ctx, "Warning: Could not set file attributes"); } break; diff --git a/src/libopensc/types.h b/src/libopensc/types.h index ab5cbded..76cf4c1a 100644 --- a/src/libopensc/types.h +++ b/src/libopensc/types.h @@ -209,6 +209,7 @@ typedef struct sc_acl_entry { } sc_acl_entry_t; /* File types */ +#define SC_FILE_TYPE_UNKNOWN 0x00 #define SC_FILE_TYPE_DF 0x04 #define SC_FILE_TYPE_INTERNAL_EF 0x03 #define SC_FILE_TYPE_WORKING_EF 0x01 From 31d8c2dfd14ed01b430def2f46cc718ef4b595fc Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 19 Feb 2020 16:09:20 +0100 Subject: [PATCH 059/189] Revert "pkcs11: fixed slotIDs when a new slot list is requested" This reverts commit 7fb72ccf7bf3ca2ff3979b7ffbb690eed41ddb5f. --- src/pkcs11/pkcs11-global.c | 22 +--------------------- src/pkcs11/slot.c | 2 +- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 71e13831..c51f2fb9 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -451,13 +451,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese pSlotList==NULL_PTR? "plug-n-play":"refresh"); /* Slot list can only change in v2.20 */ - if (pSlotList == NULL_PTR) { + if (pSlotList == NULL_PTR) sc_ctx_detect_readers(context); - for (i=0; iflags &= ~SC_PKCS11_SLOT_FLAG_SEEN; - } - } card_detect_all(); @@ -488,21 +483,6 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese prev_reader = slot->reader; } - /* Slot list can only change in v2.20 */ - if (pSlotList == NULL_PTR) { - /* slot->id is derived from its location in the list virtual_slots. - * When the slot list changes, so does slot->id, so we reindex the - * slots here the same way it is done in `create_slot()` - * - * TODO use a persistent CK_SLOT_ID, e.g. by using something like - * `slot->id = sc_crc32(slot, sizeof *slot);` (this example, however, - * is currently not thread safe). */ - for (i=0; iid = (CK_SLOT_ID) list_locate(&virtual_slots, slot); - } - } - if (pSlotList == NULL_PTR) { sc_log(context, "was only a size inquiry (%lu)\n", numMatches); *pulCount = numMatches; diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 423457b4..12dea459 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -115,6 +115,7 @@ CK_RV create_slot(sc_reader_t *reader) } slot->login_user = -1; + slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot); init_slot_info(&slot->slot_info, reader); sc_log(context, "Initializing slot with id 0x%lx", slot->id); @@ -125,7 +126,6 @@ CK_RV create_slot(sc_reader_t *reader) slot->slot_info.hardwareVersion.major = reader->version_major; slot->slot_info.hardwareVersion.minor = reader->version_minor; } - slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot); return CKR_OK; } From 8f4a6c703b5ae7d4f44cf33c85330171afa917bf Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 20 Feb 2020 01:42:18 +0100 Subject: [PATCH 060/189] align comment with implementation order --- src/pkcs11/pkcs11-global.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index c51f2fb9..b1e0ab57 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -469,8 +469,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); /* the list of available slots contains: * - if present, virtual hotplug slot; - * - any slot with token; * - without token(s), one empty slot per reader; + * - any slot with token; * - any slot that has already been seen; */ if ((!tokenPresent && !slot->reader) @@ -504,10 +504,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese sc_log(context, "returned %lu slots\n", numMatches); out: - if (found != NULL) { - free (found); - found = NULL; - } + free (found); sc_pkcs11_unlock(); return rv; } From 6a9241b5322070923d199bfd9bf05b329cd1bfff Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 11 Feb 2020 03:47:15 +0100 Subject: [PATCH 061/189] macOS: unregister CTK driver on uninstallation fixes https://github.com/frankmorgner/OpenSCToken/issues/24 --- MacOSX/opensc-uninstall | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MacOSX/opensc-uninstall b/MacOSX/opensc-uninstall index 6a14cecd..ab1d7f99 100755 --- a/MacOSX/opensc-uninstall +++ b/MacOSX/opensc-uninstall @@ -6,6 +6,8 @@ if [ "$(id -u)" != "0" ]; then exit 1 fi +pluginkit -r -i org.opensc-project.mac.opensctoken.OpenSCTokenApp.OpenSCToken + for f in \ /Library/OpenSC/bin/* \ /Library/OpenSC/etc/bash_completion.d/* \ From 70716be8150c1c3ec246b8a733f7f6b34c89e66d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 11 Feb 2020 03:56:54 +0100 Subject: [PATCH 062/189] macOS: register CTK driver on installation --- MacOSX/scripts/postinstall | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MacOSX/scripts/postinstall b/MacOSX/scripts/postinstall index ff11f831..52337d4d 100755 --- a/MacOSX/scripts/postinstall +++ b/MacOSX/scripts/postinstall @@ -40,4 +40,8 @@ do fi done +if [ -e /Applications/OpenSCTokenApp.app/Contents/PlugIns/OpenSCToken.appex ] + sudo -u _securityagent pluginkit -a /Applications/OpenSCTokenApp.app/Contents/PlugIns/OpenSCToken.appex +fi + exit 0 From 95cae64f834e532ea6fd877abc361087e8ae18ba Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 22 Feb 2020 17:50:12 +0100 Subject: [PATCH 063/189] opensc-explorer: replace magic numbers by SC_MAX_PIN_SIZE Replace magic numbers, used as size of PIN-type buffers, with the symbolic constant SC_MAX_PIN_SIZE, fixing - readability / understandability - too small sizes (e.g. for GnuPG cards) --- src/tools/opensc-explorer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 1ac9a89f..c145db6b 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1178,7 +1178,7 @@ static int do_verify(int argc, char **argv) { SC_AC_NONE, NULL, } }; int r, tries_left = -1; - u8 buf[64]; + u8 buf[SC_MAX_PIN_SIZE]; size_t buflen = sizeof(buf), i; struct sc_pin_cmd_data data; int prefix_len = 0; @@ -1263,8 +1263,8 @@ static int do_verify(int argc, char **argv) static int do_change(int argc, char **argv) { int ref, r, tries_left = -1; - u8 oldpin[64]; - u8 newpin[64]; + u8 oldpin[SC_MAX_PIN_SIZE]; + u8 newpin[SC_MAX_PIN_SIZE]; size_t oldpinlen = 0; size_t newpinlen = 0; struct sc_pin_cmd_data data; @@ -1328,8 +1328,8 @@ static int do_change(int argc, char **argv) static int do_unblock(int argc, char **argv) { int ref, r; - u8 puk[64]; - u8 newpin[64]; + u8 puk[SC_MAX_PIN_SIZE]; + u8 newpin[SC_MAX_PIN_SIZE]; size_t puklen = 0; size_t newpinlen = 0; struct sc_pin_cmd_data data; From 81ace3689d610d7d8a269f90743d7ec3b48013cc Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 2 Feb 2020 14:42:22 +0100 Subject: [PATCH 064/189] opensc-explorer: extend do_info() * distinguish between Internal and Working EFs * add information optionally available in sc_file_t - record_count - record_length - type_attr * align all labelled values --- src/tools/opensc-explorer.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index c145db6b..9a4dc65f 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -904,13 +904,15 @@ static int do_info(int argc, char **argv) } else return usage(do_info); - if(!file->type_attr_len) + if (!file->type_attr_len) st = "Unknown File"; switch (file->type) { case SC_FILE_TYPE_WORKING_EF: + st = "Working Elementary File"; + break; case SC_FILE_TYPE_INTERNAL_EF: - st = "Elementary File"; + st = "Internal Elementary File"; break; case SC_FILE_TYPE_DF: st = "Dedicated File"; @@ -922,8 +924,8 @@ static int do_info(int argc, char **argv) printf("\n%s ID %04X", st, file->id); if (file->sid) printf(", SFI %02X", file->sid); - printf("\n\n%-15s%s\n", "File path:", path_to_filename(&path, '/')); - printf("%-15s%lu bytes\n", "File size:", (unsigned long) file->size); + printf("\n\n%-25s%s\n", "File path:", path_to_filename(&path, '/')); + printf("%-25s%"SC_FORMAT_LEN_SIZE_T"u bytes\n", "File size:", file->size); if (file->type == SC_FILE_TYPE_DF) { static const id2str_t ac_ops_df[] = { @@ -940,7 +942,7 @@ static int do_info(int argc, char **argv) }; if (file->namelen) { - printf("%-15s", "DF name:"); + printf("%-25s", "DF name:"); util_print_binary(stdout, file->name, file->namelen); printf("\n"); } @@ -973,7 +975,15 @@ static int do_info(int argc, char **argv) for (i = 0; ef_type_name[i].str != NULL; i++) if (file->ef_structure == ef_type_name[i].id) ef_type = ef_type_name[i].str; - printf("%-15s%s\n", "EF structure:", ef_type); + printf("%-25s%s\n", "EF structure:", ef_type); + + if (file->record_count > 0) + printf("%-25s%"SC_FORMAT_LEN_SIZE_T"u\n", + "Number of records:", file->record_count); + + if (file->record_length > 0) + printf("%-25s%"SC_FORMAT_LEN_SIZE_T"u bytes\n", + "Max. record size:", file->record_length); ac_ops = ac_ops_ef; } @@ -983,16 +993,21 @@ static int do_info(int argc, char **argv) printf("ACL for %s:%*s %s\n", ac_ops[i].str, - (12 > len) ? (12 - len) : 0, "", + (15 > len) ? (15 - len) : 0, "", util_acl_to_str(sc_file_get_acl_entry(file, ac_ops[i].id))); } - if (file->prop_attr_len) { + if (file->type_attr_len > 0) { + printf("%-25s", "Type attributes:"); + util_hex_dump(stdout, file->type_attr, file->type_attr_len, " "); + printf("\n"); + } + if (file->prop_attr_len > 0) { printf("%-25s", "Proprietary attributes:"); util_hex_dump(stdout, file->prop_attr, file->prop_attr_len, " "); printf("\n"); } - if (file->sec_attr_len) { + if (file->sec_attr_len > 0) { printf("%-25s", "Security attributes:"); util_hex_dump(stdout, file->sec_attr, file->sec_attr_len, " "); printf("\n"); From 21ee26b0704ec2ae1040010d2d5266a499ec4e2d Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 23 Feb 2020 01:12:39 +0100 Subject: [PATCH 065/189] openpgp-tool: fix key generation with non-standard exponent length Address issue #1949 by reading non-default algorithm attributes for key generation from the key's algorithm attributes DO, if that exists. --- src/tools/openpgp-tool.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index 1d13d0a0..7e848b2d 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -699,8 +699,11 @@ int do_genkey(sc_card_t *card, u8 in_key_id, const char *keytype) /* generate key depending on keytype passed */ if (strncasecmp("RSA", keytype, strlen("RSA")) == 0) { - size_t keylen = 2048; /* default length for RSA keys */ const char *keylen_ptr = keytype + strlen("RSA"); + size_t keylen = 2048; /* default key length for RSA keys */ + size_t expolen = 32; /* default exponent length for RSA keys */ + u8 keyformat = SC_OPENPGP_KEYFORMAT_RSA_STD; /* default keyformat */ + char pathstr[SC_MAX_PATH_STRING_SIZE]; /* try to get key length from keytype, e.g. "rsa3072" -> 3072 */ if (strlen(keylen_ptr) > 0) { @@ -714,14 +717,29 @@ int do_genkey(sc_card_t *card, u8 in_key_id, const char *keytype) } } + /* get some algorithm attributes from respective DO - ignore errors */ + snprintf(pathstr, sizeof(pathstr), "006E007300C%d", in_key_id); + sc_format_path(pathstr, &path); + if (sc_select_file(card, &path, &file) >= 0) { + u8 attrs[6]; /* algorithm attrs DO for RSA is <= 6 bytes */ + + r = sc_read_binary(card, 0, attrs, sizeof(attrs), 0); + if (r >= 5 && attrs[0] == SC_OPENPGP_KEYALGO_RSA) { + expolen = (unsigned short) attrs[3] << 8 + | (unsigned short) attrs[4]; + if (r > 5) + keyformat = attrs[5]; + } + } + /* set key_info */ key_info.key_id = in_key_id; key_info.algorithm = SC_OPENPGP_KEYALGO_RSA; key_info.u.rsa.modulus_len = keylen; key_info.u.rsa.modulus = calloc(BYTES4BITS(keylen), 1); - /* The OpenPGP supports only 32-bit exponent. */ - key_info.u.rsa.exponent_len = 32; - key_info.u.rsa.exponent = calloc(BYTES4BITS(key_info.u.rsa.exponent_len), 1); + key_info.u.rsa.exponent_len = expolen; + key_info.u.rsa.exponent = calloc(BYTES4BITS(expolen), 1); + key_info.u.rsa.keyformat = keyformat; r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info); free(key_info.u.rsa.modulus); From dca02dd9a09cc06dd60b88a86ad69f8bc95a441f Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 18 Feb 2020 22:30:12 +0100 Subject: [PATCH 066/189] fixed 323588 Uninitialized scalar variable accessing uninitialized data with mlock is undefined behavior --- src/libopensc/card-coolkey.c | 2 +- src/libopensc/sc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c index ce22b3f2..0b37acf7 100644 --- a/src/libopensc/card-coolkey.c +++ b/src/libopensc/card-coolkey.c @@ -2062,7 +2062,7 @@ coolkey_process_combined_object(sc_card_t *card, coolkey_private_data_t *priv, u } memcpy(priv->token_name, &decompressed_header->token_name[0], decompressed_header->token_name_length); - priv->token_name[decompressed_header->token_name_length] = 0; + priv->token_name[decompressed_header->token_name_length] = '\0'; priv->token_name_length = decompressed_header->token_name_length; diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 49bf5c97..85ab0b76 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -902,7 +902,7 @@ void *sc_mem_secure_alloc(size_t len) len = pages * page_size; } - p = malloc(len); + p = calloc(1, len); if (p == NULL) { return NULL; } From 6b1770e7addfebc83c549fdf1cee3246c381e46f Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 18 Feb 2020 22:49:29 +0100 Subject: [PATCH 067/189] pkcs15-init: removed --options-file use an environment variable to pass a hidden PIN code instead of the options file fixes 13814 Resource leak as reported by Coverity Scan --- doc/tools/pkcs15-init.1.xml | 28 ++---------------- src/tools/pkcs15-init.c | 58 +------------------------------------ 2 files changed, 4 insertions(+), 82 deletions(-) diff --git a/doc/tools/pkcs15-init.1.xml b/doc/tools/pkcs15-init.1.xml index bed58f43..212358bd 100644 --- a/doc/tools/pkcs15-init.1.xml +++ b/doc/tools/pkcs15-init.1.xml @@ -346,27 +346,6 @@ - - - filename - - - - Tells pkcs15-init to read additional options - from filename. The file is supposed to - contain one long option per line, without the leading dashes, - for instance: - -pin 1234 -puk 87654321 - - - - You can specify several times. - - - - , @@ -384,10 +363,9 @@ puk 87654321 that on most operation systems, any user can display the command line of any process on the system using utilities such as - ps(1). Therefore, you should use - these options only on a secured system, or in an - options file specified with - . + ps(1). Therefore, you should prefer + passing the values via a hidden environment variable + on an unsecured system. diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index 899f5306..5339402e 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -115,13 +115,11 @@ static int do_read_public_key(const char *, const char *, EVP_PKEY **); static int do_read_certificate(const char *, const char *, X509 **); static char * cert_common_name(X509 *x509); static void parse_commandline(int argc, char **argv); -static void read_options_file(const char *); static void ossl_print_errors(void); static int verify_pin(struct sc_pkcs15_card *, char *); enum { - OPT_OPTIONS = 0x100, - OPT_PASSPHRASE, + OPT_PASSPHRASE = 0x100, OPT_PUBKEY, OPT_SECRKEY, OPT_EXTRACTABLE, @@ -213,7 +211,6 @@ const struct option options[] = { { "profile", required_argument, NULL, 'p' }, { "card-profile", required_argument, NULL, 'c' }, - { "options-file", required_argument, NULL, OPT_OPTIONS }, { "md-container-guid", required_argument, NULL, OPT_MD_CONTAINER_GUID}, { "wait", no_argument, NULL, 'w' }, { "help", no_argument, NULL, 'h' }, @@ -279,7 +276,6 @@ static const char * option_help[] = { "Specify the general profile to use", "Specify the card profile to use", - "Read additional command line options from file", "For a new key specify GUID for a MD container", "Wait for card insertion", "Display this message", @@ -2774,9 +2770,6 @@ handle_option(const struct option *opt) case 'w': opt_wait = 1; break; - case OPT_OPTIONS: - read_options_file(optarg); - break; case OPT_PIN1: case OPT_PUK1: case OPT_PIN2: case OPT_PUK2: util_get_pin(optarg, &(opt_pins[opt->val & 3])); @@ -2954,55 +2947,6 @@ next: ; } } -/* - * Read a file containing more command line options. - * This allows you to specify PINs to pkcs15-init without - * exposing them through ps. - */ -static void -read_options_file(const char *filename) -{ - const struct option *o; - char buffer[1024], *name; - FILE *fp; - - if ((fp = fopen(filename, "r")) == NULL) - util_fatal("Unable to open %s: %m", filename); - while (fgets(buffer, sizeof(buffer), fp) != NULL) { - buffer[strcspn(buffer, "\n")] = '\0'; - - name = strtok(buffer, " \t"); - while (name) { - if (*name == '#') - break; - for (o = options; o->name; o++) - if (!strcmp(o->name, name)) - break; - if (!o->name) { - util_error("Unknown option \"%s\"\n", name); - util_print_usage_and_die(app_name, options, option_help, NULL); - } - if (o->has_arg != no_argument) { - optarg = strtok(NULL, ""); - if (optarg) { - while (isspace((int) *optarg)) - optarg++; - optarg = strdup(optarg); - } - } - if (o->has_arg == required_argument - && (!optarg || !*optarg)) { - util_error("Option %s: missing argument\n", name); - util_print_usage_and_die(app_name, options, option_help, NULL); - } - handle_option(o); - name = strtok(NULL, " \t"); - } - } - fclose(fp); -} - - /* * OpenSSL helpers */ From 261e0b6b0d57075f7c802f17901ae03b55b8f27c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 18 Feb 2020 23:33:30 +0100 Subject: [PATCH 068/189] unified documentation of handling PIN/PUK on CLI --- doc/tools/dnie-tool.1.xml | 24 ++++++++++++++++------ doc/tools/gids-tool.1.xml | 20 ++++++++++++++++-- doc/tools/openpgp-tool.1.xml | 25 ++++++++++++++++------- doc/tools/pkcs15-init.1.xml | 24 ++++++++++++---------- doc/tools/pkcs15-tool.1.xml | 29 ++++++++++++++++++--------- doc/tools/sc-hsm-tool.1.xml | 35 ++++++++++++++++---------------- doc/tools/westcos-tool.1.xml | 39 +++++++++++++++++++----------------- 7 files changed, 125 insertions(+), 71 deletions(-) diff --git a/doc/tools/dnie-tool.1.xml b/doc/tools/dnie-tool.1.xml index 0daac27d..4120bc73 100644 --- a/doc/tools/dnie-tool.1.xml +++ b/doc/tools/dnie-tool.1.xml @@ -73,13 +73,25 @@ pin, - pin + pin - Specify the user pin pin to use. - If set to env:VARIABLE, the - value of the environment variable - VARIABLE is used. - The default is do not enter pin + + + These options can be used to specify the PIN value + on the command line. If the value is set to + env:VARIABLE, the value + of the specified environment variable is used. By default, + the code is prompted on the command line if needed. + + + Note that on most operation systems, any user can + display the command line of any process on the + system using utilities such as + ps(1). Therefore, you should prefer + passing the codes via an environment variable + on an unsecured system. + + diff --git a/doc/tools/gids-tool.1.xml b/doc/tools/gids-tool.1.xml index a7d4f8be..9bad4d5c 100644 --- a/doc/tools/gids-tool.1.xml +++ b/doc/tools/gids-tool.1.xml @@ -46,9 +46,25 @@ - argument + pin - Define user PIN. + + + This option can be used to specify the PIN value + on the command line. If the value is set to + env:VARIABLE, the value + of the specified environment variable is used. By default, + the code is prompted on the command line if needed. + + + Note that on most operation systems, any user can + display the command line of any process on the + system using utilities such as + ps(1). Therefore, you should prefer + passing the codes via an environment variable + on an unsecured system. + + diff --git a/doc/tools/openpgp-tool.1.xml b/doc/tools/openpgp-tool.1.xml index 5f46be29..cc513131 100644 --- a/doc/tools/openpgp-tool.1.xml +++ b/doc/tools/openpgp-tool.1.xml @@ -149,14 +149,25 @@ - string + pin - - The PIN text to verify. If set to - env:VARIABLE, the value of - the environment variable - VARIABLE is used. - + + + This option can be used to specify the PIN value + on the command line. If the value is set to + env:VARIABLE, the value + of the specified environment variable is used. By default, + the code is prompted on the command line if needed. + + + Note that on most operation systems, any user can + display the command line of any process on the + system using utilities such as + ps(1). Therefore, you should prefer + passing the codes via an environment variable + on an unsecured system. + + diff --git a/doc/tools/pkcs15-init.1.xml b/doc/tools/pkcs15-init.1.xml index 212358bd..e7c87383 100644 --- a/doc/tools/pkcs15-init.1.xml +++ b/doc/tools/pkcs15-init.1.xml @@ -348,23 +348,25 @@ - , - - , - , + pin, + puk, + sopin, + sopuk - These options can be used to specify PIN/PUK values - on the command line. If set to - env:VARIABLE, the value - of the environment variable - VARIABLE is used. Note - that on most operation systems, any user can + These options can be used to specify the PIN/PUK values + on the command line. If the value is set to + env:VARIABLE, the value + of the specified environment variable is used. By default, + the code is prompted on the command line if needed. + + + Note that on most operation systems, any user can display the command line of any process on the system using utilities such as ps(1). Therefore, you should prefer - passing the values via a hidden environment variable + passing the codes via an environment variable on an unsecured system. diff --git a/doc/tools/pkcs15-tool.1.xml b/doc/tools/pkcs15-tool.1.xml index 02b3b03b..45bbb077 100644 --- a/doc/tools/pkcs15-tool.1.xml +++ b/doc/tools/pkcs15-tool.1.xml @@ -310,16 +310,27 @@ - PIN + pin, + newpin + puk - Specify PIN - - - - - PUK - - Specify Unblock PIN + + + These options can be used to specify the PIN/PUK values + on the command line. If the value is set to + env:VARIABLE, the value + of the specified environment variable is used. By default, + the code is prompted on the command line if needed. + + + Note that on most operation systems, any user can + display the command line of any process on the + system using utilities such as + ps(1). Therefore, you should prefer + passing the codes via an environment variable + on an unsecured system. + + diff --git a/doc/tools/sc-hsm-tool.1.xml b/doc/tools/sc-hsm-tool.1.xml index ced876ae..3f63eda6 100644 --- a/doc/tools/sc-hsm-tool.1.xml +++ b/doc/tools/sc-hsm-tool.1.xml @@ -120,26 +120,25 @@ - value + pin, + sopin, - Define SO-PIN for initialization. If set to - env:VARIABLE, the value of - the environment variable - VARIABLE is used. - - - - - - value - - - Define user PIN for initialization, wrap or - unwrap operation. If set to - env:VARIABLE, the value of - the environment variable - VARIABLE is used. + + These options can be used to specify the PIN values + on the command line. If the value is set to + env:VARIABLE, the value + of the specified environment variable is used. By default, + the code is prompted on the command line if needed. + + + Note that on most operation systems, any user can + display the command line of any process on the + system using utilities such as + ps(1). Therefore, you should prefer + passing the codes via an environment variable + on an unsecured system. + diff --git a/doc/tools/westcos-tool.1.xml b/doc/tools/westcos-tool.1.xml index 3034f2e8..9950ecf2 100644 --- a/doc/tools/westcos-tool.1.xml +++ b/doc/tools/westcos-tool.1.xml @@ -115,25 +115,28 @@ - value, - value + pin, + pin + puk, + puk - Set value of PIN. If set to - env:VARIABLE, the value of - the environment variable - VARIABLE is used. - - - - - value, - value - - set value of PUK (or value of new PIN for change PIN - command see ). If set to - env:VARIABLE, the value of - the environment variable - VARIABLE is used. + + + These options can be used to specify the PIN/PUK values + on the command line. If the value is set to + env:VARIABLE, the value + of the specified environment variable is used. By default, + the code is prompted on the command line if needed. + + + Note that on most operation systems, any user can + display the command line of any process on the + system using utilities such as + ps(1). Therefore, you should prefer + passing the codes via an environment variable + on an unsecured system. + + From 906108bb691a35828cc4e09fcba904d08c24d458 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 20 Feb 2020 10:46:23 +0100 Subject: [PATCH 069/189] dnie: fixed length checking of uncompressed data fixes https://oss-fuzz.com/testcase-detail/5632848910614528 --- src/libopensc/card-dnie.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 110b3a83..164ae15c 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -944,16 +944,15 @@ static u8 *dnie_uncompress(sc_card_t * card, u8 * from, size_t *len) sc_log(card->ctx, "alloc() for uncompressed buffer failed"); return NULL; } + *len = uncompressed; res = sc_decompress(upt, /* try to uncompress by calling sc_xx routine */ - (size_t *) & uncompressed, + len, from + 8, (size_t) compressed, COMPRESSION_ZLIB); - /* TODO: check that returned uncompressed size matches expected */ if (res != SC_SUCCESS) { sc_log(card->ctx, "Uncompress() failed or data not compressed"); goto compress_exit; /* assume not need uncompression */ } /* Done; update buffer len and return pt to uncompressed data */ - *len = uncompressed; sc_log_hex(card->ctx, "Compressed data", from + 8, compressed); sc_log_hex(card->ctx, "Uncompressed data", upt, uncompressed); compress_exit: From c212776f45ba4190f378aac017e69e1125cb83e7 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 27 Feb 2020 22:53:10 +0100 Subject: [PATCH 070/189] fixed dashes --- doc/tools/dnie-tool.1.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tools/dnie-tool.1.xml b/doc/tools/dnie-tool.1.xml index 4120bc73..6467a68f 100644 --- a/doc/tools/dnie-tool.1.xml +++ b/doc/tools/dnie-tool.1.xml @@ -73,7 +73,7 @@ pin, - pin + pin From ad7eb834cf20e1e8f5889b1f095162763abcd053 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 20 Feb 2020 14:07:58 +0100 Subject: [PATCH 071/189] fixed indenting --- src/libopensc/pkcs15-gemsafeGPK.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libopensc/pkcs15-gemsafeGPK.c b/src/libopensc/pkcs15-gemsafeGPK.c index c8d35dad..a6bf7b18 100644 --- a/src/libopensc/pkcs15-gemsafeGPK.c +++ b/src/libopensc/pkcs15-gemsafeGPK.c @@ -360,14 +360,14 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card) } if ( gsdata[idx1] == 0x30 && - is_seq(gsdata + idx1, &seq_size1, &seq_len1) && - is_seq(gsdata + idx1 + seq_size1, &seq_size2, &seq_len2) && - gsdata[idx1 + seq_size1 + seq_size2 + 0] == 0xa0 && - gsdata[idx1 + seq_size1 + seq_size2 + 1] == 0x03 && - gsdata[idx1 + seq_size1 + seq_size2 + 2] == 0x02 && - gsdata[idx1 + seq_size1 + seq_size2 + 3] == 0x01 && - gsdata[idx1 + seq_size1 + seq_size2 + 4] == 0x02 && - idx1 + 4 + seq_len1 < file->size) { + is_seq(gsdata + idx1, &seq_size1, &seq_len1) && + is_seq(gsdata + idx1 + seq_size1, &seq_size2, &seq_len2) && + gsdata[idx1 + seq_size1 + seq_size2 + 0] == 0xa0 && + gsdata[idx1 + seq_size1 + seq_size2 + 1] == 0x03 && + gsdata[idx1 + seq_size1 + seq_size2 + 2] == 0x02 && + gsdata[idx1 + seq_size1 + seq_size2 + 3] == 0x01 && + gsdata[idx1 + seq_size1 + seq_size2 + 4] == 0x02 && + idx1 + 4 + seq_len1 < file->size) { /* we have a cert (I hope) */ /* read in rest if needed */ idxlen = idx1 + seq_len1 + 4 - idx2; @@ -386,7 +386,7 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card) return SC_ERROR_OUT_OF_MEMORY; memcpy(cert_info.value.value, gsdata + idx1, cert_info.value.len); - idx1 = idx1 + cert_info.value.len; + idx1 = idx1 + cert_info.value.len; break; } idx1++; From af40303fe8e94c7cd103f1eb980cdd872dc9b6d2 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Tue, 25 Feb 2020 20:24:00 -0600 Subject: [PATCH 072/189] Improved Handling of PKCS11 Slots OpenSC PKCS11 now retains slots even when the reader is removed. It can do this because existing OpenSC reader handling in ctx.c, reader-pcsc.c and PC/SC allow OpenSC to do this. This simplifies the code, and allow a reader to be reinserted and use the existing slot. This matching is actually done in reader-pcsc.c because PC/SC returns the unique ids based on the OS reader names. This is then used as the manufacturerID By not deleting slots the slot list can only increase which is a restriction of Firefox. It does not fix all the Firefox issues, but it does not go into a loop, when all the readers are removed. The defaults in opensc.conf for max-virtual-readers and slots-per-card allow for 4 different readers used during one session. On branch PKCS11-SLOTS-3 Changes to be committed: modified: sc-pkcs11.h modified: slot.c --- src/pkcs11/sc-pkcs11.h | 5 +++++ src/pkcs11/slot.c | 43 ++++++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 4309b631..55236d21 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -206,6 +206,11 @@ struct sc_pkcs11_card { * the application calls `C_GetSlotList` with `NULL`. This flag tracks the * visibility to the application */ #define SC_PKCS11_SLOT_FLAG_SEEN 1 +/* reader-pcsc.c can reuse a removed reader, as the ctx->reader list contains + * readers which have been removed retain removed readers. + * Take advantage of this feature to allow for reinsertion of a reader*/ +#define SC_PKCS11_SLOT_FLAG_READER_REMOVED 2 + struct sc_pkcs11_slot { CK_SLOT_ID id; /* ID of the slot */ diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 12dea459..daaac6bb 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -133,18 +133,8 @@ CK_RV create_slot(sc_reader_t *reader) void empty_slot(struct sc_pkcs11_slot *slot) { if (slot) { - if (slot->flags & SC_PKCS11_SLOT_FLAG_SEEN) { - /* Keep the slot visible to the application. The slot's state has - * already been reset by `slot_token_removed()`, lists have been - * emptied. We replace the reader with a virtual hotplug slot. */ - slot->reader = NULL; - init_slot_info(&slot->slot_info, NULL); - } else { - list_destroy(&slot->objects); - list_destroy(&slot->logins); - list_delete(&virtual_slots, slot); - free(slot); - } + list_clear(&slot->objects); + list_clear(&slot->logins); } } @@ -383,21 +373,38 @@ fail: CK_RV card_detect_all(void) { - unsigned int i; + unsigned int i, j; sc_log(context, "Detect all cards"); /* Detect cards in all initialized readers */ for (i=0; i< sc_ctx_get_reader_count(context); i++) { sc_reader_t *reader = sc_ctx_get_reader(context, i); + int removed = 0; /* have we called card_removed for this reader */ + if (reader->flags & SC_READER_REMOVED) { struct sc_pkcs11_slot *slot; - card_removed(reader); - while ((slot = reader_get_slot(reader))) { - empty_slot(slot); + /* look at all slots to call card_removed amd empty_slot */ + for (j = 0; jreader == reader) { + if (!removed) { + card_removed(reader); + removed = 1; /* only need to call once for this reader */ + } + if (slot->flags & SC_PKCS11_SLOT_FLAG_READER_REMOVED) { + empty_slot(slot); + slot->flags |= SC_PKCS11_SLOT_FLAG_READER_REMOVED; + } + } } - _sc_delete_reader(context, reader); - i--; } else { + struct sc_pkcs11_slot *slot; + for (j = 0; jreader == reader) + slot->flags &= ~SC_PKCS11_SLOT_FLAG_READER_REMOVED; + } + if (!reader_get_slot(reader)) initialize_reader(reader); else From d54f346937e478e81d36a942e3a5df7834db11d1 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 2 Mar 2020 22:24:54 +0100 Subject: [PATCH 073/189] pkcs11: simpify reader removal - reader (slot) description is already initialized init_slot_info() - objects and logins are already released in slot_token_removed --- src/pkcs11/pkcs11-global.c | 4 +--- src/pkcs11/sc-pkcs11.h | 11 ---------- src/pkcs11/slot.c | 43 ++++++-------------------------------- 3 files changed, 7 insertions(+), 51 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index b1e0ab57..25c4cd36 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -475,10 +475,8 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese */ if ((!tokenPresent && !slot->reader) || (!tokenPresent && slot->reader != prev_reader) - || (slot->slot_info.flags & CKF_TOKEN_PRESENT) - || (slot->flags & SC_PKCS11_SLOT_FLAG_SEEN)) { + || (slot->slot_info.flags & CKF_TOKEN_PRESENT)) { found[numMatches++] = slot->id; - slot->flags |= SC_PKCS11_SLOT_FLAG_SEEN; } prev_reader = slot->reader; } diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 55236d21..16e8fdf7 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -201,16 +201,6 @@ struct sc_pkcs11_card { unsigned int nmechanisms; }; -/* If the slot did already show with `C_GetSlotList`, then we need to keep this - * slot alive. PKCS#11 2.30 allows allows adding but not removing slots until - * the application calls `C_GetSlotList` with `NULL`. This flag tracks the - * visibility to the application */ -#define SC_PKCS11_SLOT_FLAG_SEEN 1 -/* reader-pcsc.c can reuse a removed reader, as the ctx->reader list contains - * readers which have been removed retain removed readers. - * Take advantage of this feature to allow for reinsertion of a reader*/ -#define SC_PKCS11_SLOT_FLAG_READER_REMOVED 2 - struct sc_pkcs11_slot { CK_SLOT_ID id; /* ID of the slot */ @@ -232,7 +222,6 @@ struct sc_pkcs11_slot { }; typedef struct sc_pkcs11_slot sc_pkcs11_slot_t; - /* Forward decl */ typedef struct sc_pkcs11_operation sc_pkcs11_operation_t; diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index daaac6bb..2fb495d2 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -121,24 +121,11 @@ CK_RV create_slot(sc_reader_t *reader) if (reader != NULL) { slot->reader = reader; - strcpy_bp(slot->slot_info.manufacturerID, reader->vendor, 32); - strcpy_bp(slot->slot_info.slotDescription, reader->name, 64); - slot->slot_info.hardwareVersion.major = reader->version_major; - slot->slot_info.hardwareVersion.minor = reader->version_minor; } return CKR_OK; } -void empty_slot(struct sc_pkcs11_slot *slot) -{ - if (slot) { - list_clear(&slot->objects); - list_clear(&slot->logins); - } -} - - /* create slots associated with a reader, called whenever a reader is seen. */ CK_RV initialize_reader(sc_reader_t *reader) { @@ -373,38 +360,20 @@ fail: CK_RV card_detect_all(void) { - unsigned int i, j; + unsigned int i; sc_log(context, "Detect all cards"); /* Detect cards in all initialized readers */ for (i=0; i< sc_ctx_get_reader_count(context); i++) { sc_reader_t *reader = sc_ctx_get_reader(context, i); - int removed = 0; /* have we called card_removed for this reader */ if (reader->flags & SC_READER_REMOVED) { - struct sc_pkcs11_slot *slot; - /* look at all slots to call card_removed amd empty_slot */ - for (j = 0; jreader == reader) { - if (!removed) { - card_removed(reader); - removed = 1; /* only need to call once for this reader */ - } - if (slot->flags & SC_PKCS11_SLOT_FLAG_READER_REMOVED) { - empty_slot(slot); - slot->flags |= SC_PKCS11_SLOT_FLAG_READER_REMOVED; - } - } - } + card_removed(reader); + /* do not remove slots related to this reader which would be + * possible according to PKCS#11 2.20 and later, because NSS can't + * handle a shrinking slot list + * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */ } else { - struct sc_pkcs11_slot *slot; - for (j = 0; jreader == reader) - slot->flags &= ~SC_PKCS11_SLOT_FLAG_READER_REMOVED; - } - if (!reader_get_slot(reader)) initialize_reader(reader); else From ce704f5eb15d103ab6db1ba974548f8bb3e5882b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Mar 2020 12:38:37 +0100 Subject: [PATCH 074/189] removed unused plug_and_play parameter see 1fb741338a010515b35f28cd9c769561f3e574a2 --- src/pkcs11/sc-pkcs11.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 16e8fdf7..c3a13934 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -65,7 +65,6 @@ struct sc_pkcs11_slot; struct sc_pkcs11_card; struct sc_pkcs11_config { - unsigned int plug_and_play; unsigned int max_virtual_slots; unsigned int slots_per_card; unsigned char lock_login; From 5b9af968518344ba92b7023428280873fab1d34e Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Mar 2020 15:09:17 +0100 Subject: [PATCH 075/189] pkcs11: reclaim unused slots based on reader description When a reader is removed and reattached, this re-uses the old slot without relying on the fact that the sc_reader_t is unchanged. --- src/pkcs11/pkcs11-global.c | 5 ++--- src/pkcs11/slot.c | 46 ++++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 25c4cd36..95c37f3c 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -468,8 +468,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese for (i=0; iname, 64); + strcpy_bp(manufacturerID, reader->vendor, 32); /* Locate a slot related to the reader */ for (i = 0; ireader == reader) return slot; + if (slot->reader == NULL && reader != NULL + && 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64) + && 0 == memcmp(slot->slot_info.manufacturerID, manufacturerID, 32) + && slot->slot_info.hardwareVersion.major == reader->version_major + && slot->slot_info.hardwareVersion.minor == reader->version_minor) + return slot; } return NULL; } @@ -82,8 +93,8 @@ static int object_list_seeker(const void *el, const void *key) CK_RV create_slot(sc_reader_t *reader) { - /* find unused virtual hotplug slots */ - struct sc_pkcs11_slot *slot = reader_get_slot(NULL); + /* find unused slots previously allocated for the same reader */ + struct sc_pkcs11_slot *slot = reader_reclaim_slot(reader); /* create a new slot if no empty slot is available */ if (!slot) { @@ -373,11 +384,32 @@ card_detect_all(void) * possible according to PKCS#11 2.20 and later, because NSS can't * handle a shrinking slot list * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */ + + /* Instead, remove the releation between reader and slot */ + for (i = 0; ireader == reader) { + slot->reader = NULL; + } + } } else { - if (!reader_get_slot(reader)) - initialize_reader(reader); - else - card_detect(sc_ctx_get_reader(context, i)); + /* Locate a slot related to the reader */ + int found = 0; + for (i = 0; ireader == reader) { + found = 1; + break; + } + } + if (!found) { + for (i = 0; i < sc_pkcs11_conf.slots_per_card; i++) { + CK_RV rv = create_slot(reader); + if (rv != CKR_OK) + return rv; + } + } + card_detect(reader); } } sc_log(context, "All cards detected"); From 14e396273ca06e6bbed7e3484166f64373501972 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 13 Jan 2020 17:21:18 +0100 Subject: [PATCH 076/189] reader-pcsc: fixed handling of detatching events - allows re-attatching a reader to an existing reader object by resetting the SC_READER_REMOVED flag - readers that are flagged with SC_READER_REMOVED are not used for SCardGetStatusChange to avoid SCARD_E_UNKNOWN_READER fixes https://github.com/OpenSC/OpenSC/issues/1903 --- src/libopensc/reader-pcsc.c | 50 ++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 66b426e4..14e3b4e0 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -181,6 +181,9 @@ static int pcsc_to_opensc_error(LONG rv) return SC_ERROR_READER_LOCKED; case SCARD_E_NO_READERS_AVAILABLE: return SC_ERROR_NO_READERS_FOUND; + case SCARD_E_UNKNOWN_READER: + return SC_ERROR_READER_DETACHED; + case SCARD_E_NO_SERVICE: /* If the service is (auto)started, there could be readers later */ return SC_ERROR_NO_READERS_FOUND; @@ -1467,8 +1470,13 @@ static int pcsc_detect_readers(sc_context_t *ctx) for (reader_name = reader_buf; *reader_name != '\x0'; reader_name += strlen(reader_name) + 1) { - if (!strcmp(reader->name, reader_name)) + if (!strcmp(reader->name, reader_name)) { + if (reader->flags & SC_READER_REMOVED) { + reader->flags &= ~SC_READER_REMOVED; + refresh_attributes(reader); + } break; + } } if (*reader_name != '\x0') { @@ -1546,7 +1554,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re LONG rv; SCARD_READERSTATE *rgReaderStates; size_t i; - unsigned int num_watch; + unsigned int num_watch, count; int r = SC_ERROR_INTERNAL; DWORD dwtimeout; @@ -1565,22 +1573,30 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); /* Find out the current status */ - num_watch = sc_ctx_get_reader_count(ctx); - sc_log(ctx, "Trying to watch %d readers", num_watch); - for (i = 0; i < num_watch; i++) { - rgReaderStates[i].szReader = sc_ctx_get_reader(ctx, i)->name; - rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE; - rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE; - } -#ifndef __APPLE__ - /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ - if (event_mask & SC_EVENT_READER_ATTACHED) { - rgReaderStates[i].szReader = "\\\\?PnP?\\Notification"; - rgReaderStates[i].dwCurrentState = SCARD_STATE_UNAWARE; - rgReaderStates[i].dwEventState = SCARD_STATE_UNAWARE; + num_watch = 0; + count = sc_ctx_get_reader_count(ctx); + for (i = 0; i < count; i++) { + sc_reader_t *reader = sc_ctx_get_reader(ctx, i); + if (reader->flags & SC_READER_REMOVED) + continue; + rgReaderStates[num_watch].szReader = reader->name; + rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; + rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; num_watch++; } + sc_log(ctx, "Trying to watch %d reader%s", num_watch, num_watch == 1 ? "" : "s"); + if (event_mask & SC_EVENT_READER_ATTACHED) { +#ifdef __APPLE__ + /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ + sc_log(ctx, "PnP notification not supported"); +#else + rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification"; + rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; + rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; + num_watch++; + sc_log(ctx, "Trying to detect new readers"); #endif + } } else { rgReaderStates = (SCARD_READERSTATE *)(*reader_states); @@ -1606,14 +1622,12 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re goto out; } -#ifdef __APPLE__ if (num_watch == 0) { - sc_log(ctx, "No readers available, PnP notification not supported"); + sc_log(ctx, "No readers available to be watched"); *event_reader = NULL; r = SC_ERROR_NO_READERS_FOUND; goto out; } -#endif rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, 0, rgReaderStates, num_watch); if (rv != SCARD_S_SUCCESS) { From 649ee272eca4d5ca659e70059b32cd3375e5404e Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 3 Mar 2020 22:25:24 +0100 Subject: [PATCH 077/189] reader-cryptotokenkit: fixed handling of reattached reader --- src/libopensc/reader-cryptotokenkit.m | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libopensc/reader-cryptotokenkit.m b/src/libopensc/reader-cryptotokenkit.m index 7bee8278..3a2b579d 100644 --- a/src/libopensc/reader-cryptotokenkit.m +++ b/src/libopensc/reader-cryptotokenkit.m @@ -577,6 +577,7 @@ static int cryptotokenkit_detect_readers(sc_context_t *ctx) if (j < [slotNames count]) { /* existing reader found; remove it from the list */ [slotNames removeObjectAtIndex:j]; + reader->flags &= ~SC_READER_REMOVED; } else { /* existing reader not found */ reader->flags |= SC_READER_REMOVED; From 2e89f1634fee658ccda0a38b65975e96a3c64c7c Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 21 Feb 2020 08:19:37 -0600 Subject: [PATCH 078/189] Debug PKCS11 virtual slots Macro DEBUG_VSS and routine _debug_virtual_slots were added. DEBUG_VSS(slot, "printf like format string" [,args...]) will print the virtual_slots to the opensc-debug.log showing were it was called from. If slot is not NULL and found in the table it will be highlighted with an "*". In gdb: call _debug_virtual_slots(slot) can be used along with another window to tail opensc-debug.log On branch PKCS11-SLOTS-2 Date: Fri Feb 21 08:19:37 2020 -0600 Changes to be committed: modified: src/pkcs11/sc-pkcs11.h modified: src/pkcs11/slot.c --- src/pkcs11/sc-pkcs11.h | 9 +++++++++ src/pkcs11/slot.c | 28 +++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index c3a13934..5be8903d 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -221,6 +221,14 @@ struct sc_pkcs11_slot { }; typedef struct sc_pkcs11_slot sc_pkcs11_slot_t; +/* Debug virtual slots. S is slot to be highlighted or NULL + * C is a comment format string and args It will be preceeded by "VSS " */ + +#define DEBUG_VSS(S, C...) sc_log(context,"VSS " C); _debug_virtual_slots(S) + +/* called by DEBUG_VSS to print table of virtual slots */ +void _debug_virtual_slots(sc_pkcs11_slot_t *p); + /* Forward decl */ typedef struct sc_pkcs11_operation sc_pkcs11_operation_t; @@ -354,6 +362,7 @@ void sc_pkcs11_print_attrs(int level, const char *file, unsigned int line, const CK_RV card_removed(sc_reader_t *reader); CK_RV card_detect_all(void); CK_RV create_slot(sc_reader_t *reader); +void init_slot_info(CK_SLOT_INFO_PTR pInfo, sc_reader_t *reader); CK_RV initialize_reader(sc_reader_t *reader); CK_RV card_detect(sc_reader_t *reader); CK_RV slot_get_slot(CK_SLOT_ID id, struct sc_pkcs11_slot **); diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index bf91b6bc..d43d81b7 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -27,6 +27,32 @@ #include "sc-pkcs11.h" +/* Print virtual_slots list. Called by DEBUG_VSS(S, C) */ +void _debug_virtual_slots(sc_pkcs11_slot_t *p) +{ + int i, vs_size; + sc_pkcs11_slot_t * slot; + + vs_size = list_size(&virtual_slots); + _sc_debug(context, SC_LOG_DEBUG_NORMAL, + "VSS size:%d", vs_size); + _sc_debug(context, SC_LOG_DEBUG_NORMAL, + "VSS [i] id flags LU events nsessions slot_info.flags reader p11card description"); + for (i = 0; i < vs_size; i++) { + slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); + if (slot) { + _sc_debug(context, SC_LOG_DEBUG_NORMAL, + "VSS %s[%d] 0x%2.2lx 0x%4.4x %d %d %d %4.4lx %p %p %.64s", + ((slot == p) ? "*" : " "), + i, slot->id, slot->flags, slot->login_user, slot->events, slot->nsessions, + slot->slot_info.flags, + slot->reader, slot->p11card, + slot->slot_info.slotDescription); + } + } + _sc_debug(context, SC_LOG_DEBUG_NORMAL, "VSS END"); +} + static struct sc_pkcs11_framework_ops *frameworks[] = { &framework_pkcs15, #ifdef USE_PKCS15_INIT @@ -61,7 +87,7 @@ static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader) return NULL; } -static void init_slot_info(CK_SLOT_INFO_PTR pInfo, sc_reader_t *reader) +void init_slot_info(CK_SLOT_INFO_PTR pInfo, sc_reader_t *reader) { if (reader) { strcpy_bp(pInfo->slotDescription, reader->name, 64); From 8d519ed3c4a8c4cedd9ea7e9c11a6348d447d452 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 21 Feb 2020 20:21:10 -0600 Subject: [PATCH 079/189] Add calls to DEBUG_VSS On branch PKCS11-SLOTS-2 Changes to be committed: modified: pkcs11-global.c modified: slot.c --- src/pkcs11/pkcs11-global.c | 11 ++++++++++- src/pkcs11/slot.c | 7 ++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 95c37f3c..cfd847ef 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -449,13 +449,18 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese sc_log(context, "C_GetSlotList(token=%d, %s)", tokenPresent, pSlotList==NULL_PTR? "plug-n-play":"refresh"); + DEBUG_VSS(NULL, "C_GetSlotList before ctx_detect_detect"); /* Slot list can only change in v2.20 */ if (pSlotList == NULL_PTR) sc_ctx_detect_readers(context); + DEBUG_VSS(NULL, "C_GetSlotList after ctx_detect_readers"); + card_detect_all(); + DEBUG_VSS(NULL, "C_GetSlotList after card_detect_all"); + found = calloc(list_size(&virtual_slots), sizeof(CK_SLOT_ID)); if (found == NULL) { @@ -479,6 +484,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese } prev_reader = slot->reader; } + DEBUG_VSS(NULL, "C_GetSlotList after card_detect_all"); if (pSlotList == NULL_PTR) { sc_log(context, "was only a size inquiry (%lu)\n", numMatches); @@ -486,6 +492,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese rv = CKR_OK; goto out; } + DEBUG_VSS(NULL, "C_GetSlotList after slot->id reassigned"); if (*pulCount < numMatches) { sc_log(context, "buffer was too small (needed %lu)\n", numMatches); @@ -499,6 +506,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese rv = CKR_OK; sc_log(context, "returned %lu slots\n", numMatches); + DEBUG_VSS(NULL, "Returning a new slot list"); out: free (found); @@ -535,7 +543,7 @@ static sc_timestamp_t get_current_time(void) CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { - struct sc_pkcs11_slot *slot; + struct sc_pkcs11_slot *slot = NULL; sc_timestamp_t now; CK_RV rv; @@ -558,6 +566,7 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) } rv = slot_get_slot(slotID, &slot); + DEBUG_VSS(slot, "C_GetSlotInfo found"); sc_log(context, "C_GetSlotInfo() get slot rv %s", lookup_enum( RV_T, rv)); if (rv == CKR_OK) { if (slot->reader == NULL) { diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index d43d81b7..ceff97f5 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -75,7 +75,8 @@ static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader) /* Locate a slot related to the reader */ for (i = 0; ireader == reader) + if (slot->reader == reader) { + DEBUG_VSS(slot, "reader_get_slot found slot"); return slot; if (slot->reader == NULL && reader != NULL && 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64) @@ -83,6 +84,7 @@ static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader) && slot->slot_info.hardwareVersion.major == reader->version_major && slot->slot_info.hardwareVersion.minor == reader->version_minor) return slot; + } } return NULL; } @@ -140,6 +142,7 @@ CK_RV create_slot(sc_reader_t *reader) if (0 != list_init(&slot->logins)) { return CKR_HOST_MEMORY; } + DEBUG_VSS(slot, "Creating new slot"); } else { /* reuse the old list of logins/objects since they should be empty */ list_t logins = slot->logins; @@ -149,6 +152,7 @@ CK_RV create_slot(sc_reader_t *reader) slot->logins = logins; slot->objects = objects; + DEBUG_VSS(slot, "Reusing old slot"); } slot->login_user = -1; @@ -159,6 +163,7 @@ CK_RV create_slot(sc_reader_t *reader) if (reader != NULL) { slot->reader = reader; } + DEBUG_VSS(slot, "Created this slot"); return CKR_OK; } From 7e7458edce303ac3e8f421e52dacc350c908274c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Mar 2020 14:25:08 +0100 Subject: [PATCH 080/189] pkcs11: restore creating 4 virtual slots for each reader fixes old token slot ids (https://github.com/OpenSC/OpenSC/pull/1970#issuecomment-594400562) --- src/pkcs11/pkcs11-global.c | 5 +---- src/pkcs11/sc-pkcs11.h | 1 - src/pkcs11/slot.c | 35 ++++++----------------------------- 3 files changed, 7 insertions(+), 34 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index cfd847ef..178c7264 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -269,7 +269,6 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs) pid_t current_pid = getpid(); #endif int rc; - unsigned int i; sc_context_param_t ctx_opts; #if !defined(_WIN32) @@ -321,9 +320,7 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs) } list_attributes_seeker(&virtual_slots, slot_list_seeker); - /* Create slots for readers found on initialization, only if in 2.11 mode */ - for (i=0; ireader == reader) { - DEBUG_VSS(slot, "reader_get_slot found slot"); - return slot; if (slot->reader == NULL && reader != NULL && 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64) && 0 == memcmp(slot->slot_info.manufacturerID, manufacturerID, 32) && slot->slot_info.hardwareVersion.major == reader->version_major - && slot->slot_info.hardwareVersion.minor == reader->version_minor) + && slot->slot_info.hardwareVersion.minor == reader->version_minor) { return slot; } } @@ -126,6 +123,7 @@ CK_RV create_slot(sc_reader_t *reader) /* create a new slot if no empty slot is available */ if (!slot) { + sc_log(context, "Creating new slot"); if (list_size(&virtual_slots) >= sc_pkcs11_conf.max_virtual_slots) return CKR_FUNCTION_FAILED; @@ -142,8 +140,9 @@ CK_RV create_slot(sc_reader_t *reader) if (0 != list_init(&slot->logins)) { return CKR_HOST_MEMORY; } - DEBUG_VSS(slot, "Creating new slot"); } else { + DEBUG_VSS(slot, "Reusing this old slot"); + /* reuse the old list of logins/objects since they should be empty */ list_t logins = slot->logins; list_t objects = slot->objects; @@ -152,40 +151,18 @@ CK_RV create_slot(sc_reader_t *reader) slot->logins = logins; slot->objects = objects; - DEBUG_VSS(slot, "Reusing old slot"); } slot->login_user = -1; slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot); init_slot_info(&slot->slot_info, reader); - sc_log(context, "Initializing slot with id 0x%lx", slot->id); + slot->reader = reader; - if (reader != NULL) { - slot->reader = reader; - } - DEBUG_VSS(slot, "Created this slot"); + DEBUG_VSS(slot, "Finished initializing this slot"); return CKR_OK; } -/* create slots associated with a reader, called whenever a reader is seen. */ -CK_RV initialize_reader(sc_reader_t *reader) -{ - unsigned int i; - CK_RV rv; - - for (i = 0; i < sc_pkcs11_conf.slots_per_card; i++) { - rv = create_slot(reader); - if (rv != CKR_OK) - return rv; - } - card_detect(reader); - - sc_log(context, "Reader '%s' initialized", reader->name); - return CKR_OK; -} - - CK_RV card_removed(sc_reader_t * reader) { unsigned int i; From 2a6bf1e5771800f87691fd6f8532c3d057a0e090 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Mar 2020 14:29:34 +0100 Subject: [PATCH 081/189] pkcs11: lower debug level of virtual slots --- src/pkcs11/slot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index c9a47976..26af2bac 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -34,14 +34,14 @@ void _debug_virtual_slots(sc_pkcs11_slot_t *p) sc_pkcs11_slot_t * slot; vs_size = list_size(&virtual_slots); - _sc_debug(context, SC_LOG_DEBUG_NORMAL, + _sc_debug(context, 10, "VSS size:%d", vs_size); - _sc_debug(context, SC_LOG_DEBUG_NORMAL, + _sc_debug(context, 10, "VSS [i] id flags LU events nsessions slot_info.flags reader p11card description"); for (i = 0; i < vs_size; i++) { slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); if (slot) { - _sc_debug(context, SC_LOG_DEBUG_NORMAL, + _sc_debug(context, 10, "VSS %s[%d] 0x%2.2lx 0x%4.4x %d %d %d %4.4lx %p %p %.64s", ((slot == p) ? "*" : " "), i, slot->id, slot->flags, slot->login_user, slot->events, slot->nsessions, @@ -50,7 +50,7 @@ void _debug_virtual_slots(sc_pkcs11_slot_t *p) slot->slot_info.slotDescription); } } - _sc_debug(context, SC_LOG_DEBUG_NORMAL, "VSS END"); + _sc_debug(context, 10, "VSS END"); } static struct sc_pkcs11_framework_ops *frameworks[] = { From dba0f567225bfde36b3097413f84ecf1d7fca27a Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Mar 2020 16:43:51 +0100 Subject: [PATCH 082/189] pkcs11: fixed state tracking - when listing the slots, we don't have a hotplug slot anymore with slot->reader == NULL. Instead, we're now using this state for any left over slots when a reader is removed. So we don't need to include this in the slot list - when listing the slots, we need to remember which slots the application has seen already, to not shrink the list of slots (which is allowed in PKCS#11 v2.2, but NSS can't handle this) --- src/pkcs11/pkcs11-global.c | 7 ++++--- src/pkcs11/sc-pkcs11.h | 5 +++++ src/pkcs11/slot.c | 12 ++++++------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index 178c7264..a3260314 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -474,10 +474,11 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese * - any slot with token; * - any slot that has already been seen; */ - if ((!tokenPresent && !slot->reader) - || (!tokenPresent && slot->reader != prev_reader) - || (slot->slot_info.flags & CKF_TOKEN_PRESENT)) { + if ((!tokenPresent && slot->reader != prev_reader) + || (slot->slot_info.flags & CKF_TOKEN_PRESENT) + || (slot->flags & SC_PKCS11_SLOT_FLAG_SEEN)) { found[numMatches++] = slot->id; + slot->flags |= SC_PKCS11_SLOT_FLAG_SEEN; } prev_reader = slot->reader; } diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index f661faf6..e2c82fba 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -200,6 +200,11 @@ struct sc_pkcs11_card { unsigned int nmechanisms; }; +/* If the slot did already show with `C_GetSlotList`, then we need to keep this + * slot alive. PKCS#11 2.30 allows allows adding but not removing slots until + * the application calls `C_GetSlotList` with `NULL`. This flag tracks the + * visibility to the application */ +#define SC_PKCS11_SLOT_FLAG_SEEN 1 struct sc_pkcs11_slot { CK_SLOT_ID id; /* ID of the slot */ diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c index 26af2bac..148b59ec 100644 --- a/src/pkcs11/slot.c +++ b/src/pkcs11/slot.c @@ -379,7 +379,7 @@ fail: CK_RV card_detect_all(void) { - unsigned int i; + unsigned int i, j; sc_log(context, "Detect all cards"); /* Detect cards in all initialized readers */ @@ -394,8 +394,8 @@ card_detect_all(void) * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */ /* Instead, remove the releation between reader and slot */ - for (i = 0; ireader == reader) { slot->reader = NULL; } @@ -403,15 +403,15 @@ card_detect_all(void) } else { /* Locate a slot related to the reader */ int found = 0; - for (i = 0; ireader == reader) { found = 1; break; } } if (!found) { - for (i = 0; i < sc_pkcs11_conf.slots_per_card; i++) { + for (j = 0; j < sc_pkcs11_conf.slots_per_card; j++) { CK_RV rv = create_slot(reader); if (rv != CKR_OK) return rv; From c69add3b640830e17d7bf7e7707880514d9a013f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 15:34:37 +0100 Subject: [PATCH 083/189] cac: Correctly avoid recursion (amends 09531d72) Closes: #1920 Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19725 --- src/libopensc/card-cac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c index 6970d0f4..b93d0fab 100644 --- a/src/libopensc/card-cac.c +++ b/src/libopensc/card-cac.c @@ -1542,7 +1542,7 @@ static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv, int depth) size_t tl_len, val_len; int r; - if (depth < 0) { + if (depth > CAC_MAX_CCC_DEPTH) { sc_log(card->ctx, "Too much recursive CCC found. Exiting"); return SC_ERROR_INVALID_CARD; } @@ -1782,7 +1782,7 @@ static int cac_find_and_initialize(sc_card_t *card, int initialize) priv = cac_new_private_data(); if (!priv) return SC_ERROR_OUT_OF_MEMORY; - r = cac_process_CCC(card, priv, CAC_MAX_CCC_DEPTH); + r = cac_process_CCC(card, priv, 0); if (r == SC_SUCCESS) { card->type = SC_CARD_TYPE_CAC_II; card->drv_data = priv; From d31ebe2fec7b601a9a2bb01d4df950736f2fd121 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 16:23:51 +0100 Subject: [PATCH 084/189] gemsafeGPK: Fix typo in comment --- src/libopensc/pkcs15-gemsafeGPK.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-gemsafeGPK.c b/src/libopensc/pkcs15-gemsafeGPK.c index a6bf7b18..e13f3b87 100644 --- a/src/libopensc/pkcs15-gemsafeGPK.c +++ b/src/libopensc/pkcs15-gemsafeGPK.c @@ -205,7 +205,7 @@ static int sc_pkcs15emu_gemsafeGPK_init(sc_pkcs15_card_t *p15card) u8 sysrec[7]; int num_keyinfo = 0; - keyinfo kinfo[8]; /* will loook for 8 keys */ + keyinfo kinfo[8]; /* will look for 8 keys */ u8 modulus_buf[ 1 + 1024 / 8]; /* tag+modulus */ u8 *cp; char buf[256]; From 9c0a7adbfc63550da7796fad0a55f351e5ef469a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 16:32:53 +0100 Subject: [PATCH 085/189] iasecc: Avoid memory leaks on error Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20700 --- src/libopensc/card-iasecc.c | 60 +++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 8054b277..e443c034 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -868,12 +868,14 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, df_from_cache = 1; rv = iasecc_select_file(card, &ppath, &file); - LOG_TEST_RET(ctx, rv, "select AID path failed"); + LOG_TEST_GOTO_ERR(ctx, rv, "select AID path failed"); - if (file_out) + if (file_out) { + sc_file_free(*file_out); *file_out = file; - else - sc_file_free(file); + } else { + sc_file_free(file); + } if (lpath.type == SC_PATH_TYPE_DF_NAME) lpath.type = SC_PATH_TYPE_FROM_CURRENT; @@ -882,8 +884,13 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, if (lpath.type == SC_PATH_TYPE_PATH) lpath.type = SC_PATH_TYPE_FROM_CURRENT; - if (!lpath.len) + if (!lpath.len) { + if (file_out) { + sc_file_free(*file_out); + *file_out = NULL; + } LOG_FUNC_RETURN(ctx, SC_SUCCESS); + } sc_print_cache(card); @@ -891,7 +898,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, && card->cache.current_df->path.len == lpath.len && !memcmp(card->cache.current_df->path.value, lpath.value, lpath.len)) { sc_log(ctx, "returns current DF path %s", sc_print_path(&card->cache.current_df->path)); - if (file_out) { + if (file_out) { sc_file_free(*file_out); sc_file_dup(file_out, card->cache.current_df); } @@ -913,8 +920,10 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, && 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_MI2) - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported card"); + && card->type != SC_CARD_TYPE_IASECC_MI2) { + rv = SC_ERROR_NOT_SUPPORTED; + LOG_TEST_GOTO_ERR(ctx, rv, "Unsupported card"); + } if (lpath.type == SC_PATH_TYPE_FILE_ID) { apdu.p1 = 0x02; @@ -954,7 +963,8 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, } else { sc_log(ctx, "Invalid PATH type: 0x%X", lpath.type); - LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "iasecc_select_file() invalid PATH type"); + rv = SC_ERROR_NOT_SUPPORTED; + LOG_TEST_GOTO_ERR(ctx, rv, "iasecc_select_file() invalid PATH type"); } for (ii=0; ii<2; ii++) { @@ -967,7 +977,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, apdu.le = 256; rv = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(ctx, rv, "APDU transmit failed"); + LOG_TEST_GOTO_ERR(ctx, rv, "APDU transmit failed"); rv = sc_check_sw(card, apdu.sw1, apdu.sw2); if (rv == SC_ERROR_INCORRECT_PARAMETERS && lpath.type == SC_PATH_TYPE_DF_NAME && apdu.p2 == 0x00) { @@ -979,7 +989,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, /* 'SELECT AID' do not returned FCP. Try to emulate. */ apdu.resplen = sizeof(rbuf); rv = iasecc_emulate_fcp(ctx, &apdu); - LOG_TEST_RET(ctx, rv, "Failed to emulate DF FCP"); + LOG_TEST_GOTO_ERR(ctx, rv, "Failed to emulate DF FCP"); } break; @@ -993,7 +1003,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, if (rv == SC_ERROR_FILE_NOT_FOUND && cache_valid && df_from_cache) { sc_invalidate_cache(card); sc_log(ctx, "iasecc_select_file() file not found, retry without cached DF"); - if (file_out) { + if (file_out) { sc_file_free(*file_out); *file_out = NULL; } @@ -1001,7 +1011,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, LOG_FUNC_RETURN(ctx, rv); } - LOG_TEST_RET(ctx, rv, "iasecc_select_file() check SW failed"); + LOG_TEST_GOTO_ERR(ctx, rv, "iasecc_select_file() check SW failed"); sc_log(ctx, "iasecc_select_file() apdu.resp %"SC_FORMAT_LEN_SIZE_T"u", @@ -1013,15 +1023,29 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, case 0x62: case 0x6F: file = sc_file_new(); - if (file == NULL) + if (file == NULL) { + if (file_out) { + sc_file_free(*file_out); + *file_out = NULL; + } LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + } file->path = lpath; rv = iasecc_process_fci(card, file, apdu.resp, apdu.resplen); - if (rv) + if (rv) { + if (file_out) { + sc_file_free(*file_out); + *file_out = NULL; + } LOG_FUNC_RETURN(ctx, rv); + } break; default: + if (file_out) { + sc_file_free(*file_out); + *file_out = NULL; + } LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); } @@ -1069,6 +1093,12 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, sc_print_cache(card); LOG_FUNC_RETURN(ctx, SC_SUCCESS); +err: + if (file_out) { + sc_file_free(*file_out); + *file_out = NULL; + } + return rv; } From a623226a878ead2b9d44996a7be28d636d82ba3c Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 16:43:34 +0100 Subject: [PATCH 086/189] Avoid memory leaks from sc_parse_ef_attr() Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20710 --- src/libopensc/ef-atr.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libopensc/ef-atr.c b/src/libopensc/ef-atr.c index c03473d3..edbf4410 100644 --- a/src/libopensc/ef-atr.c +++ b/src/libopensc/ef-atr.c @@ -139,7 +139,7 @@ int sc_parse_ef_atr(struct sc_card *card) { struct sc_context *ctx = card->ctx; struct sc_path path; - struct sc_file *file; + struct sc_file *file = NULL; int rv; unsigned char *buf = NULL; size_t size; @@ -157,17 +157,19 @@ int sc_parse_ef_atr(struct sc_card *card) } buf = malloc(size); if (!buf) - LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Memory allocation error"); + LOG_TEST_GOTO_ERR(ctx, SC_ERROR_OUT_OF_MEMORY, "Memory allocation error"); rv = sc_read_binary(card, 0, buf, size, 0); - LOG_TEST_RET(ctx, rv, "Cannot read EF(ATR) file"); + LOG_TEST_GOTO_ERR(ctx, rv, "Cannot read EF(ATR) file"); rv = sc_parse_ef_atr_content(card, buf, rv); - LOG_TEST_RET(ctx, rv, "EF(ATR) parse error"); + LOG_TEST_GOTO_ERR(ctx, rv, "EF(ATR) parse error"); - free(buf); + rv = SC_SUCCESS; + +err: sc_file_free(file); - - LOG_FUNC_RETURN(ctx, SC_SUCCESS); + free(buf); + LOG_FUNC_RETURN(ctx, rv); } void sc_free_ef_atr(sc_card_t *card) From 7d3b82c204271bf9c1085de8402cc0cc1fe8cc0f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 16:57:11 +0100 Subject: [PATCH 087/189] epass2003: Avoid memory leaks if no file_out is passed Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20898 --- src/libopensc/card-epass2003.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c index 5d5eb520..9621f647 100644 --- a/src/libopensc/card-epass2003.c +++ b/src/libopensc/card-epass2003.c @@ -1369,7 +1369,7 @@ epass2003_select_fid(struct sc_card *card, unsigned int id_hi, unsigned int id_l sc_file_t ** file_out) { int r; - sc_file_t *file = 0; + sc_file_t *file = NULL; sc_path_t path; memset(&path, 0, sizeof(path)); @@ -1396,8 +1396,11 @@ epass2003_select_fid(struct sc_card *card, unsigned int id_hi, unsigned int id_l } } - if (file_out) + if (file_out) { *file_out = file; + } else { + sc_file_free(file); + } LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } From 677710c72b14249deeecc5396e04f3aedfe03763 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 17:02:38 +0100 Subject: [PATCH 088/189] dnie: Avoid insane memory allocations Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20916 --- src/libopensc/card-dnie.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 164ae15c..4788f59e 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -936,6 +936,9 @@ static u8 *dnie_uncompress(sc_card_t * card, u8 * from, size_t *len) /* if compressed size greater than uncompressed, assume uncompressed data */ if (uncompressed < compressed) goto compress_exit; + /* Do not try to allocate insane size if we receive bogus data */ + if (uncompressed > MAX_FILE_SIZE) + goto compress_exit; sc_log(card->ctx, "Data seems to be compressed. calling uncompress"); /* ok: data seems to be compressed */ From 7bfca52bab96c5b283ed993b77d8f8711c8fcc07 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 17:08:57 +0100 Subject: [PATCH 089/189] iasecc: Free old driver data if the driver was initialized correctly CID: 354007 --- src/libopensc/card-iasecc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index e443c034..835572be 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -635,6 +635,8 @@ err: if (rv < 0) { free(private_data); card->drv_data = old_drv_data; + } else { + free(old_drv_data); } LOG_FUNC_RETURN(ctx, rv); From 2a88d82cad47d87ecd63178df0a84335c41d7f7e Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 17:34:04 +0100 Subject: [PATCH 090/189] compression: Validate inputs to decompression functions CID 353531 CID 353530 --- src/libopensc/compression.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/libopensc/compression.c b/src/libopensc/compression.c index 3dfd0ead..19d1a984 100644 --- a/src/libopensc/compression.c +++ b/src/libopensc/compression.c @@ -150,18 +150,23 @@ int sc_compress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method) } } -int sc_decompress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method) { +int sc_decompress(u8* out, size_t* outLen, const u8* in, size_t inLen, int method) +{ unsigned long zlib_outlen; int rc; - if(method == COMPRESSION_AUTO) { + if (in == NULL || out == NULL) { + return SC_ERROR_UNKNOWN_DATA_RECEIVED; + } + + if (method == COMPRESSION_AUTO) { method = detect_method(in, inLen); if (method == COMPRESSION_UNKNOWN) { *outLen = 0; return SC_ERROR_UNKNOWN_DATA_RECEIVED; } } - switch(method) { + switch (method) { case COMPRESSION_ZLIB: zlib_outlen = *outLen; rc = zerr_to_opensc(uncompress(out, &zlib_outlen, in, inLen)); @@ -241,14 +246,20 @@ static int sc_decompress_zlib_alloc(u8** out, size_t* outLen, const u8* in, size return zerr_to_opensc(err); } -int sc_decompress_alloc(u8** out, size_t* outLen, const u8* in, size_t inLen, int method) { - if(method == COMPRESSION_AUTO) { +int sc_decompress_alloc(u8** out, size_t* outLen, const u8* in, size_t inLen, int method) +{ + if (in == NULL || out == NULL) { + return SC_ERROR_UNKNOWN_DATA_RECEIVED; + } + + if (method == COMPRESSION_AUTO) { method = detect_method(in, inLen); - if(method == COMPRESSION_UNKNOWN) { + if (method == COMPRESSION_UNKNOWN) { return SC_ERROR_UNKNOWN_DATA_RECEIVED; } } - switch(method) { + + switch (method) { case COMPRESSION_ZLIB: return sc_decompress_zlib_alloc(out, outLen, in, inLen, 0); case COMPRESSION_GZIP: From e3e461aad9fe197324a7c876c6e6ad4a7bba3125 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 17:47:41 +0100 Subject: [PATCH 091/189] coolkey: Avoid insane allocations and use correct variable type CID 341847 --- src/libopensc/card-coolkey.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c index 0b37acf7..ff79e840 100644 --- a/src/libopensc/card-coolkey.c +++ b/src/libopensc/card-coolkey.c @@ -2166,7 +2166,7 @@ static int coolkey_initialize(sc_card_t *card) r = coolkey_list_object(card, COOLKEY_LIST_RESET, &object_info); while (r >= 0) { unsigned long object_id; - unsigned short object_len; + unsigned long object_len; /* The card did not return what we expected: Lets try other objects */ if ((size_t)r < (sizeof(object_info))) @@ -2176,6 +2176,10 @@ static int coolkey_initialize(sc_card_t *card) object_id = bebytes2ulong(object_info.object_id); object_len = bebytes2ulong(object_info.object_length); + /* Avoid insanely large data */ + if (object_len > MAX_FILE_SIZE) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_CORRUPTED_DATA); + } /* the combined object is a single object that can store the other objects. @@ -2203,7 +2207,7 @@ static int coolkey_initialize(sc_card_t *card) } combined_processed = 1; } else { - sc_log(card->ctx, "Add new object id=%ld, len=%u", object_id, object_len); + sc_log(card->ctx, "Add new object id=%ld, len=%lu", object_id, object_len); r = coolkey_add_object(priv, object_id, NULL, object_len, 0); if (r != SC_SUCCESS) sc_log(card->ctx, "coolkey_add_object() returned %d", r); From 44bc324864f608025a3c6f85d19e829d391028ae Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 18:13:32 +0100 Subject: [PATCH 092/189] actalis: Check return codes CID 127776 --- src/libopensc/pkcs15-actalis.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-actalis.c b/src/libopensc/pkcs15-actalis.c index 9ded751e..201d40f8 100644 --- a/src/libopensc/pkcs15-actalis.c +++ b/src/libopensc/pkcs15-actalis.c @@ -252,7 +252,13 @@ static int sc_pkcs15emu_actalis_init(sc_pkcs15_card_t * p15card) j++; cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; - sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); + r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); + if (r < 0) { + sc_log(card->ctx, "Failed to add cert obj r=%d", r); + free(cert); + free(compCert); + continue; + } free(cert); free(compCert); From c3924859a91da0619a35653f08a4819d9df4f9c3 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 18:22:36 +0100 Subject: [PATCH 093/189] Update gengetopt generated code with a new version to remove hardcoded paths --- src/tools/egk-tool-cmdline.c | 40 ++++++++++++++-------- src/tools/egk-tool-cmdline.h | 4 +-- src/tools/goid-tool-cmdline.c | 37 +++++++++++++------- src/tools/goid-tool-cmdline.h | 4 +-- src/tools/npa-tool-cmdline.c | 52 ++++++++++++++++++----------- src/tools/npa-tool-cmdline.h | 8 ++--- src/tools/opensc-asn1-cmdline.c | 38 ++++++++++++++------- src/tools/opensc-asn1-cmdline.h | 8 ++--- src/tools/opensc-notify-cmdline.c | 41 +++++++++++++++-------- src/tools/opensc-notify-cmdline.h | 4 +-- src/tools/pkcs11-register-cmdline.c | 41 +++++++++++++++-------- src/tools/pkcs11-register-cmdline.h | 4 +-- 12 files changed, 183 insertions(+), 98 deletions(-) diff --git a/src/tools/egk-tool-cmdline.c b/src/tools/egk-tool-cmdline.c index 22851b0e..706c91fb 100644 --- a/src/tools/egk-tool-cmdline.c +++ b/src/tools/egk-tool-cmdline.c @@ -1,5 +1,5 @@ /* - File autogenerated by gengetopt version 2.22.6 + File autogenerated by gengetopt version 2.23 generated with the following command: /usr/bin/gengetopt --file-name=egk-tool-cmdline --output-dir=. @@ -27,7 +27,7 @@ const char *gengetopt_args_info_purpose = ""; -const char *gengetopt_args_info_usage = "Usage: egk-tool [OPTIONS]..."; +const char *gengetopt_args_info_usage = "Usage: egk-tool [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; @@ -122,19 +122,25 @@ cmdline_parser_print_version (void) printf("\n%s\n", gengetopt_args_info_versiontext); } -static void print_help_common(void) { - cmdline_parser_print_version (); +static void print_help_common(void) +{ + size_t len_purpose = strlen(gengetopt_args_info_purpose); + size_t len_usage = strlen(gengetopt_args_info_usage); - if (strlen(gengetopt_args_info_purpose) > 0) - printf("\n%s\n", gengetopt_args_info_purpose); + if (len_usage > 0) { + printf("%s\n", gengetopt_args_info_usage); + } + if (len_purpose > 0) { + printf("%s\n", gengetopt_args_info_purpose); + } - if (strlen(gengetopt_args_info_usage) > 0) - printf("\n%s\n", gengetopt_args_info_usage); + if (len_usage || len_purpose) { + printf("\n"); + } - printf("\n"); - - if (strlen(gengetopt_args_info_description) > 0) - printf("%s\n\n", gengetopt_args_info_description); + if (strlen(gengetopt_args_info_description) > 0) { + printf("%s\n\n", gengetopt_args_info_description); + } } void @@ -507,7 +513,8 @@ int update_arg(void *field, char **orig_field, break; }; - + FIX_UNUSED(stop_char); + /* store the original value */ switch(arg_type) { case ARG_NO: @@ -546,10 +553,16 @@ cmdline_parser_internal ( package_name = argv[0]; + /* TODO: Why is this here? It is not used anywhere. */ override = params->override; + FIX_UNUSED(override); + initialize = params->initialize; check_required = params->check_required; + + /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; + FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); @@ -694,3 +707,4 @@ failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } +/* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ diff --git a/src/tools/egk-tool-cmdline.h b/src/tools/egk-tool-cmdline.h index 3fb36efa..51967686 100644 --- a/src/tools/egk-tool-cmdline.h +++ b/src/tools/egk-tool-cmdline.h @@ -1,9 +1,9 @@ /** @file egk-tool-cmdline.h * @brief The header file for the command line option parser - * generated by GNU Gengetopt version 2.22.6 + * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten - * @author GNU Gengetopt by Lorenzo Bettini */ + * @author GNU Gengetopt */ #ifndef EGK_TOOL_CMDLINE_H #define EGK_TOOL_CMDLINE_H diff --git a/src/tools/goid-tool-cmdline.c b/src/tools/goid-tool-cmdline.c index 6e020347..d81b0b97 100644 --- a/src/tools/goid-tool-cmdline.c +++ b/src/tools/goid-tool-cmdline.c @@ -1,5 +1,5 @@ /* - File autogenerated by gengetopt version 2.22.6 + File autogenerated by gengetopt version 2.23 generated with the following command: /usr/bin/gengetopt --file-name=goid-tool-cmdline --output-dir=. @@ -27,7 +27,7 @@ const char *gengetopt_args_info_purpose = ""; -const char *gengetopt_args_info_usage = "Usage: goid-tool [OPTIONS]..."; +const char *gengetopt_args_info_usage = "Usage: goid-tool [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; @@ -231,19 +231,25 @@ cmdline_parser_print_version (void) printf("\n%s\n", gengetopt_args_info_versiontext); } -static void print_help_common(void) { - cmdline_parser_print_version (); +static void print_help_common(void) +{ + size_t len_purpose = strlen(gengetopt_args_info_purpose); + size_t len_usage = strlen(gengetopt_args_info_usage); - if (strlen(gengetopt_args_info_purpose) > 0) - printf("\n%s\n", gengetopt_args_info_purpose); + if (len_usage > 0) { + printf("%s\n", gengetopt_args_info_usage); + } + if (len_purpose > 0) { + printf("%s\n", gengetopt_args_info_purpose); + } - if (strlen(gengetopt_args_info_usage) > 0) - printf("\n%s\n", gengetopt_args_info_usage); + if (len_usage || len_purpose) { + printf("\n"); + } - printf("\n"); - - if (strlen(gengetopt_args_info_description) > 0) - printf("%s\n\n", gengetopt_args_info_description); + if (strlen(gengetopt_args_info_description) > 0) { + printf("%s\n\n", gengetopt_args_info_description); + } } void @@ -1142,10 +1148,16 @@ cmdline_parser_internal ( package_name = argv[0]; + /* TODO: Why is this here? It is not used anywhere. */ override = params->override; + FIX_UNUSED(override); + initialize = params->initialize; check_required = params->check_required; + + /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; + FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); @@ -1634,3 +1646,4 @@ failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } +/* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ diff --git a/src/tools/goid-tool-cmdline.h b/src/tools/goid-tool-cmdline.h index f684b6df..5ae8eeda 100644 --- a/src/tools/goid-tool-cmdline.h +++ b/src/tools/goid-tool-cmdline.h @@ -1,9 +1,9 @@ /** @file goid-tool-cmdline.h * @brief The header file for the command line option parser - * generated by GNU Gengetopt version 2.22.6 + * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten - * @author GNU Gengetopt by Lorenzo Bettini */ + * @author GNU Gengetopt */ #ifndef GOID_TOOL_CMDLINE_H #define GOID_TOOL_CMDLINE_H diff --git a/src/tools/npa-tool-cmdline.c b/src/tools/npa-tool-cmdline.c index 2918888a..5ab97819 100644 --- a/src/tools/npa-tool-cmdline.c +++ b/src/tools/npa-tool-cmdline.c @@ -1,5 +1,5 @@ /* - File autogenerated by gengetopt version 2.22.6 + File autogenerated by gengetopt version 2.23 generated with the following command: /usr/bin/gengetopt --file-name=npa-tool-cmdline --output-dir=. @@ -27,7 +27,7 @@ const char *gengetopt_args_info_purpose = ""; -const char *gengetopt_args_info_usage = "Usage: npa-tool [OPTIONS]..."; +const char *gengetopt_args_info_usage = "Usage: npa-tool [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; @@ -54,8 +54,8 @@ const char *gengetopt_args_info_help[] = { " --chat=HEX_STRING Card holder authorization template to use\n (default is terminal's CHAT). Use\n 7F4C0E060904007F000703010203530103 to trigger\n EAC on the CAT-C (Komfortleser).", " -A, --auxiliary-data=HEX_STRING\n Terminal's auxiliary data (default is\n determined by verification of validity, age\n and community ID).", " -P, --private-key=FILENAME Terminal's private key", - " --cvc-dir=DIRECTORY Where to look for the CVCA's certificate\n (default=`/home/fm/.local/etc/eac/cvc')", - " --x509-dir=DIRECTORY Where to look for the CSCA's certificate\n (default=`/home/fm/.local/etc/eac/x509')", + " --cvc-dir=DIRECTORY Where to look for the CVCA's certificate\n (default=`')", + " --x509-dir=DIRECTORY Where to look for the CSCA's certificate\n (default=`')", " --disable-ta-checks Disable checking the validity period of CV\n certificates (default=off)", " --disable-ca-checks Disable passive authentication (default=off)", "\nRead and write data groups:", @@ -206,9 +206,9 @@ void clear_args (struct gengetopt_args_info *args_info) args_info->auxiliary_data_orig = NULL; args_info->private_key_arg = NULL; args_info->private_key_orig = NULL; - args_info->cvc_dir_arg = gengetopt_strdup ("/home/fm/.local/etc/eac/cvc"); + args_info->cvc_dir_arg = gengetopt_strdup (""); args_info->cvc_dir_orig = NULL; - args_info->x509_dir_arg = gengetopt_strdup ("/home/fm/.local/etc/eac/x509"); + args_info->x509_dir_arg = gengetopt_strdup (""); args_info->x509_dir_orig = NULL; args_info->disable_ta_checks_flag = 0; args_info->disable_ca_checks_flag = 0; @@ -334,19 +334,25 @@ cmdline_parser_print_version (void) printf("\n%s\n", gengetopt_args_info_versiontext); } -static void print_help_common(void) { - cmdline_parser_print_version (); +static void print_help_common(void) +{ + size_t len_purpose = strlen(gengetopt_args_info_purpose); + size_t len_usage = strlen(gengetopt_args_info_usage); - if (strlen(gengetopt_args_info_purpose) > 0) - printf("\n%s\n", gengetopt_args_info_purpose); + if (len_usage > 0) { + printf("%s\n", gengetopt_args_info_usage); + } + if (len_purpose > 0) { + printf("%s\n", gengetopt_args_info_purpose); + } - if (strlen(gengetopt_args_info_usage) > 0) - printf("\n%s\n", gengetopt_args_info_usage); + if (len_usage || len_purpose) { + printf("\n"); + } - printf("\n"); - - if (strlen(gengetopt_args_info_description) > 0) - printf("%s\n\n", gengetopt_args_info_description); + if (strlen(gengetopt_args_info_description) > 0) { + printf("%s\n\n", gengetopt_args_info_description); + } } void @@ -978,7 +984,8 @@ int update_arg(void *field, char **orig_field, break; }; - + FIX_UNUSED(stop_char); + /* store the original value */ switch(arg_type) { case ARG_NO: @@ -1139,10 +1146,16 @@ cmdline_parser_internal ( package_name = argv[0]; + /* TODO: Why is this here? It is not used anywhere. */ override = params->override; + FIX_UNUSED(override); + initialize = params->initialize; check_required = params->check_required; + + /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; + FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); @@ -1433,7 +1446,7 @@ cmdline_parser_internal ( if (update_arg( (void *)&(args_info->cvc_dir_arg), &(args_info->cvc_dir_orig), &(args_info->cvc_dir_given), - &(local_args_info.cvc_dir_given), optarg, 0, "/home/fm/.local/etc/eac/cvc", ARG_STRING, + &(local_args_info.cvc_dir_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "cvc-dir", '-', additional_error)) @@ -1447,7 +1460,7 @@ cmdline_parser_internal ( if (update_arg( (void *)&(args_info->x509_dir_arg), &(args_info->x509_dir_orig), &(args_info->x509_dir_given), - &(local_args_info.x509_dir_given), optarg, 0, "/home/fm/.local/etc/eac/x509", ARG_STRING, + &(local_args_info.x509_dir_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "x509-dir", '-', additional_error)) @@ -1907,3 +1920,4 @@ failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } +/* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ diff --git a/src/tools/npa-tool-cmdline.h b/src/tools/npa-tool-cmdline.h index ad42cc0b..190dc5d6 100644 --- a/src/tools/npa-tool-cmdline.h +++ b/src/tools/npa-tool-cmdline.h @@ -1,9 +1,9 @@ /** @file npa-tool-cmdline.h * @brief The header file for the command line option parser - * generated by GNU Gengetopt version 2.22.6 + * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten - * @author GNU Gengetopt by Lorenzo Bettini */ + * @author GNU Gengetopt */ #ifndef NPA_TOOL_CMDLINE_H #define NPA_TOOL_CMDLINE_H @@ -83,10 +83,10 @@ struct gengetopt_args_info char * private_key_arg; /**< @brief Terminal's private key. */ char * private_key_orig; /**< @brief Terminal's private key original value given at command line. */ const char *private_key_help; /**< @brief Terminal's private key help description. */ - char * cvc_dir_arg; /**< @brief Where to look for the CVCA's certificate (default='/home/fm/.local/etc/eac/cvc'). */ + char * cvc_dir_arg; /**< @brief Where to look for the CVCA's certificate (default=''). */ char * cvc_dir_orig; /**< @brief Where to look for the CVCA's certificate original value given at command line. */ const char *cvc_dir_help; /**< @brief Where to look for the CVCA's certificate help description. */ - char * x509_dir_arg; /**< @brief Where to look for the CSCA's certificate (default='/home/fm/.local/etc/eac/x509'). */ + char * x509_dir_arg; /**< @brief Where to look for the CSCA's certificate (default=''). */ char * x509_dir_orig; /**< @brief Where to look for the CSCA's certificate original value given at command line. */ const char *x509_dir_help; /**< @brief Where to look for the CSCA's certificate help description. */ int disable_ta_checks_flag; /**< @brief Disable checking the validity period of CV certificates (default=off). */ diff --git a/src/tools/opensc-asn1-cmdline.c b/src/tools/opensc-asn1-cmdline.c index f8b20b94..13e5412a 100644 --- a/src/tools/opensc-asn1-cmdline.c +++ b/src/tools/opensc-asn1-cmdline.c @@ -1,5 +1,5 @@ /* - File autogenerated by gengetopt version 2.22.6 + File autogenerated by gengetopt version 2.23 generated with the following command: /usr/bin/gengetopt --file-name=opensc-asn1-cmdline --output-dir=. --unamed-opts @@ -27,7 +27,7 @@ const char *gengetopt_args_info_purpose = ""; -const char *gengetopt_args_info_usage = "Usage: opensc-asn1 [OPTIONS]... [FILES]..."; +const char *gengetopt_args_info_usage = "Usage: opensc-asn1 [OPTION]... [FILE]..."; const char *gengetopt_args_info_versiontext = ""; @@ -91,19 +91,25 @@ cmdline_parser_print_version (void) printf("\n%s\n", gengetopt_args_info_versiontext); } -static void print_help_common(void) { - cmdline_parser_print_version (); +static void print_help_common(void) +{ + size_t len_purpose = strlen(gengetopt_args_info_purpose); + size_t len_usage = strlen(gengetopt_args_info_usage); - if (strlen(gengetopt_args_info_purpose) > 0) - printf("\n%s\n", gengetopt_args_info_purpose); + if (len_usage > 0) { + printf("%s\n", gengetopt_args_info_usage); + } + if (len_purpose > 0) { + printf("%s\n", gengetopt_args_info_purpose); + } - if (strlen(gengetopt_args_info_usage) > 0) - printf("\n%s\n", gengetopt_args_info_usage); + if (len_usage || len_purpose) { + printf("\n"); + } - printf("\n"); - - if (strlen(gengetopt_args_info_description) > 0) - printf("%s\n\n", gengetopt_args_info_description); + if (strlen(gengetopt_args_info_description) > 0) { + printf("%s\n\n", gengetopt_args_info_description); + } } void @@ -315,10 +321,16 @@ cmdline_parser_internal ( package_name = argv[0]; + /* TODO: Why is this here? It is not used anywhere. */ override = params->override; + FIX_UNUSED(override); + initialize = params->initialize; check_required = params->check_required; + + /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; + FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); @@ -370,6 +382,7 @@ cmdline_parser_internal ( + FIX_UNUSED(check_required); cmdline_parser_release (&local_args_info); @@ -407,3 +420,4 @@ failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } +/* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ diff --git a/src/tools/opensc-asn1-cmdline.h b/src/tools/opensc-asn1-cmdline.h index 43baee5b..93073da9 100644 --- a/src/tools/opensc-asn1-cmdline.h +++ b/src/tools/opensc-asn1-cmdline.h @@ -1,9 +1,9 @@ /** @file opensc-asn1-cmdline.h * @brief The header file for the command line option parser - * generated by GNU Gengetopt version 2.22.6 + * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten - * @author GNU Gengetopt by Lorenzo Bettini */ + * @author GNU Gengetopt */ #ifndef OPENSC_ASN1_CMDLINE_H #define OPENSC_ASN1_CMDLINE_H @@ -43,8 +43,8 @@ struct gengetopt_args_info unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ - char **inputs ; /**< @brief unamed options (options without names) */ - unsigned inputs_num ; /**< @brief unamed options number */ + char **inputs ; /**< @brief unnamed options (options without names) */ + unsigned inputs_num ; /**< @brief unnamed options number */ } ; /** @brief The additional parameters to pass to parser functions */ diff --git a/src/tools/opensc-notify-cmdline.c b/src/tools/opensc-notify-cmdline.c index 3fe2fcd2..9bae830a 100644 --- a/src/tools/opensc-notify-cmdline.c +++ b/src/tools/opensc-notify-cmdline.c @@ -1,5 +1,5 @@ /* - File autogenerated by gengetopt version 2.22.6 + File autogenerated by gengetopt version 2.23 generated with the following command: /usr/bin/gengetopt --file-name=opensc-notify-cmdline --output-dir=. @@ -27,7 +27,7 @@ const char *gengetopt_args_info_purpose = ""; -const char *gengetopt_args_info_usage = "Usage: opensc-notify [OPTIONS]..."; +const char *gengetopt_args_info_usage = "Usage: opensc-notify [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; @@ -124,19 +124,25 @@ cmdline_parser_print_version (void) printf("\n%s\n", gengetopt_args_info_versiontext); } -static void print_help_common(void) { - cmdline_parser_print_version (); +static void print_help_common(void) +{ + size_t len_purpose = strlen(gengetopt_args_info_purpose); + size_t len_usage = strlen(gengetopt_args_info_usage); - if (strlen(gengetopt_args_info_purpose) > 0) - printf("\n%s\n", gengetopt_args_info_purpose); + if (len_usage > 0) { + printf("%s\n", gengetopt_args_info_usage); + } + if (len_purpose > 0) { + printf("%s\n", gengetopt_args_info_purpose); + } - if (strlen(gengetopt_args_info_usage) > 0) - printf("\n%s\n", gengetopt_args_info_usage); + if (len_usage || len_purpose) { + printf("\n"); + } - printf("\n"); - - if (strlen(gengetopt_args_info_description) > 0) - printf("%s\n\n", gengetopt_args_info_description); + if (strlen(gengetopt_args_info_description) > 0) { + printf("%s\n\n", gengetopt_args_info_description); + } } void @@ -424,7 +430,8 @@ int update_arg(void *field, char **orig_field, break; }; - + FIX_UNUSED(stop_char); + /* store the original value */ switch(arg_type) { case ARG_NO: @@ -486,10 +493,16 @@ cmdline_parser_internal ( package_name = argv[0]; + /* TODO: Why is this here? It is not used anywhere. */ override = params->override; + FIX_UNUSED(override); + initialize = params->initialize; check_required = params->check_required; + + /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; + FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); @@ -625,6 +638,7 @@ cmdline_parser_internal ( error_occurred += check_modes(customized_given, customized_desc, standard_given, standard_desc); } + FIX_UNUSED(check_required); cmdline_parser_release (&local_args_info); @@ -638,3 +652,4 @@ failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } +/* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ diff --git a/src/tools/opensc-notify-cmdline.h b/src/tools/opensc-notify-cmdline.h index 9bd77963..e36be178 100644 --- a/src/tools/opensc-notify-cmdline.h +++ b/src/tools/opensc-notify-cmdline.h @@ -1,9 +1,9 @@ /** @file opensc-notify-cmdline.h * @brief The header file for the command line option parser - * generated by GNU Gengetopt version 2.22.6 + * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten - * @author GNU Gengetopt by Lorenzo Bettini */ + * @author GNU Gengetopt */ #ifndef OPENSC_NOTIFY_CMDLINE_H #define OPENSC_NOTIFY_CMDLINE_H diff --git a/src/tools/pkcs11-register-cmdline.c b/src/tools/pkcs11-register-cmdline.c index f7f0b001..4cdc7890 100644 --- a/src/tools/pkcs11-register-cmdline.c +++ b/src/tools/pkcs11-register-cmdline.c @@ -1,5 +1,5 @@ /* - File autogenerated by gengetopt version 2.22.6 + File autogenerated by gengetopt version 2.23 generated with the following command: /usr/bin/gengetopt --file-name=pkcs11-register-cmdline --output-dir=. @@ -27,7 +27,7 @@ const char *gengetopt_args_info_purpose = ""; -const char *gengetopt_args_info_usage = "Usage: pkcs11-register [OPTIONS]..."; +const char *gengetopt_args_info_usage = "Usage: pkcs11-register [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; @@ -114,19 +114,25 @@ cmdline_parser_print_version (void) printf("\n%s\n", gengetopt_args_info_versiontext); } -static void print_help_common(void) { - cmdline_parser_print_version (); +static void print_help_common(void) +{ + size_t len_purpose = strlen(gengetopt_args_info_purpose); + size_t len_usage = strlen(gengetopt_args_info_usage); - if (strlen(gengetopt_args_info_purpose) > 0) - printf("\n%s\n", gengetopt_args_info_purpose); + if (len_usage > 0) { + printf("%s\n", gengetopt_args_info_usage); + } + if (len_purpose > 0) { + printf("%s\n", gengetopt_args_info_purpose); + } - if (strlen(gengetopt_args_info_usage) > 0) - printf("\n%s\n", gengetopt_args_info_usage); + if (len_usage || len_purpose) { + printf("\n"); + } - printf("\n"); - - if (strlen(gengetopt_args_info_description) > 0) - printf("%s\n\n", gengetopt_args_info_description); + if (strlen(gengetopt_args_info_description) > 0) { + printf("%s\n\n", gengetopt_args_info_description); + } } void @@ -410,7 +416,8 @@ int update_arg(void *field, char **orig_field, break; }; - + FIX_UNUSED(stop_char); + /* store the original value */ switch(arg_type) { case ARG_NO: @@ -449,10 +456,16 @@ cmdline_parser_internal ( package_name = argv[0]; + /* TODO: Why is this here? It is not used anywhere. */ override = params->override; + FIX_UNUSED(override); + initialize = params->initialize; check_required = params->check_required; + + /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; + FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); @@ -571,6 +584,7 @@ cmdline_parser_internal ( + FIX_UNUSED(check_required); cmdline_parser_release (&local_args_info); @@ -584,3 +598,4 @@ failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } +/* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ diff --git a/src/tools/pkcs11-register-cmdline.h b/src/tools/pkcs11-register-cmdline.h index 8b38526a..67188023 100644 --- a/src/tools/pkcs11-register-cmdline.h +++ b/src/tools/pkcs11-register-cmdline.h @@ -1,9 +1,9 @@ /** @file pkcs11-register-cmdline.h * @brief The header file for the command line option parser - * generated by GNU Gengetopt version 2.22.6 + * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten - * @author GNU Gengetopt by Lorenzo Bettini */ + * @author GNU Gengetopt */ #ifndef PKCS11_REGISTER_CMDLINE_H #define PKCS11_REGISTER_CMDLINE_H From aeef29238e661b142008704b33b37f4969143cfe Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Mar 2020 18:29:56 +0100 Subject: [PATCH 094/189] tests: Update tests to reflect current behavior of decompress --- src/tests/unittests/compression.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/unittests/compression.c b/src/tests/unittests/compression.c index f0c114d9..07fea8e6 100644 --- a/src/tests/unittests/compression.c +++ b/src/tests/unittests/compression.c @@ -209,7 +209,7 @@ static void torture_compression_decompress_empty(void **state) rv = sc_decompress(buf, &buflen, data, datalen, COMPRESSION_AUTO); assert_int_equal(rv, SC_ERROR_UNKNOWN_DATA_RECEIVED); - assert_int_equal(buflen, 0); + assert_int_equal(buflen, sizeof(buf)); /* not touched */ } static void torture_compression_decompress_gzip_empty(void **state) @@ -222,7 +222,7 @@ static void torture_compression_decompress_gzip_empty(void **state) rv = sc_decompress(buf, &buflen, data, datalen, COMPRESSION_GZIP); assert_int_equal(rv, SC_ERROR_UNKNOWN_DATA_RECEIVED); - assert_int_equal(buflen, 0); + assert_int_equal(buflen, sizeof(buf)); /* not touched */ } static void torture_compression_decompress_zlib_empty(void **state) @@ -235,7 +235,7 @@ static void torture_compression_decompress_zlib_empty(void **state) rv = sc_decompress(buf, &buflen, data, datalen, COMPRESSION_ZLIB); assert_int_equal(rv, SC_ERROR_UNKNOWN_DATA_RECEIVED); - assert_int_equal(buflen, 0); + assert_int_equal(buflen, sizeof(buf)); /* not touched */ } static void torture_compression_decompress_header(void **state) From b8d9b840eec5cbc005693f66ffe285274e442348 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 3 Mar 2020 10:06:11 +0100 Subject: [PATCH 095/189] travis-ci: Remove deprecated sudo option The warning was jobs.include: deprecated key sudo (The key `sudo` has no effect anymore.) --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3892168e..5aeb1474 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,13 +11,11 @@ matrix: env: - DO_SIMULATION=javacard - ENABLE_DOC=--enable-doc - sudo: true - compiler: gcc os: linux dist: bionic env: - DO_SIMULATION=oseid - sudo: true - env: - HOST=x86_64-w64-mingw32 - DO_PUSH_ARTIFACT=yes @@ -30,7 +28,6 @@ matrix: dist: bionic env: - DO_SIMULATION=cac - sudo: true env: global: From f301ec98b6b9666ee5b2837a5b40e913f56fd335 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 3 Mar 2020 10:09:38 +0100 Subject: [PATCH 096/189] travis-ci: There is no files option in cache The error was cache: unknown key files (isetup-5.5.6.exe) --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5aeb1474..23d5c7e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -99,8 +99,11 @@ before_script: if [ ! -f "$(winepath 'C:/Program Files (x86)/Inno Setup 5/ISCC.exe')" ]; then /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16; export DISPLAY=:99.0; + [ -d isetup ] || mkdir isetup; + pushd isetup; [ -f isetup-5.5.6.exe ] || wget http://files.jrsoftware.org/is/5/isetup-5.5.6.exe; wine isetup-5.5.6.exe /SILENT /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART; + popd; fi; unset CC; unset CXX; @@ -318,5 +321,4 @@ cache: - $HOME/Library/Caches/Homebrew - openssl_bin - openpace_bin - files: - - isetup-5.5.6.exe + - isetup From 0a610319bde92125633e0cd4f0d8b59bd029831a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 3 Mar 2020 10:57:33 +0100 Subject: [PATCH 097/189] pkcs11-tool: Fix wrong printf arguments This argument should be of type 'unsigned int' but is of type 'unsigned long' Thanks lgtm --- src/tools/pkcs11-tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 9f5cda81..bf8e7bc9 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -3328,7 +3328,7 @@ static int write_object(CK_SESSION_HANDLE session) else if (strncasecmp(opt_key_type, "DES3:", strlen("DES3:")) == 0) type = CKK_DES3; else - util_fatal("Unknown key type: 0x%X", type); + util_fatal("Unknown key type: 0x%lX", type); } FILL_ATTR(seckey_templ[0], CKA_CLASS, &clazz, sizeof(clazz)); @@ -4489,7 +4489,7 @@ static int read_object(CK_SESSION_HANDLE session) #endif } else - util_fatal("Reading public keys of type 0x%X not (yet) supported", type); + util_fatal("Reading public keys of type 0x%lX not (yet) supported", type); value = BIO_copy_data(pout, &derlen); BIO_free(pout); len = derlen; From 663894951300d99166be49d1fe3f7a100252d4da Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 3 Mar 2020 10:58:38 +0100 Subject: [PATCH 098/189] goid-tool: Fix wrong printf arguments This argument should be of type 'wchar_t *' but is of type 'unsigned short *' Thanks lgtm --- src/tools/gids-tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/gids-tool.c b/src/tools/gids-tool.c index 5902ae16..8574af1f 100644 --- a/src/tools/gids-tool.c +++ b/src/tools/gids-tool.c @@ -417,7 +417,7 @@ static int print_info(sc_card_t *card) { } for (i = 0; i < cmaprecordnum; i++) { printf(" container: %d\n", i); - wprintf(L" guid: %ls\n", cmaprecords[i].wszGuid); + wprintf(L" guid: %s\n", cmaprecords[i].wszGuid); printf(" bFlags: "); if (cmaprecords[i].bFlags & CONTAINER_MAP_VALID_CONTAINER) { printf("Valid container"); From 5721961be2520cd25283d742ef80c59400f423af Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 3 Mar 2020 11:01:21 +0100 Subject: [PATCH 099/189] pkcs11-tool: Properly report invalid signatures Comparison is always false because rv <= 0. Thanks lgtm --- src/tools/pkcs11-tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index bf8e7bc9..b8e02cac 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -2065,7 +2065,7 @@ static void verify_signature(CK_SLOT_ID slot, CK_SESSION_HANDLE session, rv = p11->C_Verify(session, in_buffer, r, sig_buffer, sig_len); } - if (rv != CKR_OK) { + if (rv != CKR_OK && rv != CKR_SIGNATURE_INVALID) { rv = p11->C_VerifyInit(session, &mech, key); if (rv != CKR_OK) p11_fatal("C_VerifyInit", rv); @@ -2080,7 +2080,7 @@ static void verify_signature(CK_SLOT_ID slot, CK_SESSION_HANDLE session, sig_len = r2; rv = p11->C_VerifyFinal(session, sig_buffer, sig_len); - if (rv != CKR_OK) + if (rv != CKR_OK && rv != CKR_SIGNATURE_INVALID) p11_fatal("C_VerifyFinal", rv); } From 15b1e93b513d68838a4953e46b19ed40e0293b15 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 3 Mar 2020 11:03:03 +0100 Subject: [PATCH 100/189] cac: Avoid always-true condition Comparison is always true because pathlen >= 3. Thanks lgtm --- src/libopensc/card-cac.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libopensc/card-cac.c b/src/libopensc/card-cac.c index b93d0fab..801fb20a 100644 --- a/src/libopensc/card-cac.c +++ b/src/libopensc/card-cac.c @@ -1093,10 +1093,8 @@ static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc * We only need to do this for private keys. */ if ((pathlen > 2) && (pathlen <= 4) && memcmp(path, "\x3F\x00", 2) == 0) { - if (pathlen > 2) { - path += 2; - pathlen -= 2; - } + path += 2; + pathlen -= 2; } From e429fe03c555d7abe62de4e0a878d8e910de160a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 3 Mar 2020 11:04:56 +0100 Subject: [PATCH 101/189] cardos: Avoid always-true condition Comparison is always true because offset >= 1. Thanks lgtm --- src/libopensc/card-cardos.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index f55cadcb..306822b9 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -381,8 +381,7 @@ get_next_part: q = sc_asn1_find_tag(card->ctx, p, tlen, 0x8a, &ilen); if (q != NULL && ilen == 1) { offset = (u8)ilen; - if (offset != 0) - goto get_next_part; + goto get_next_part; } len -= tlen + 2; p += tlen; From 88dce1218176c81aef74dc86a26df536b93cec26 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 3 Mar 2020 11:14:25 +0100 Subject: [PATCH 102/189] gids-tool: Remove empty condition Empty block without comment Thanks lgtm --- src/tools/gids-tool.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/gids-tool.c b/src/tools/gids-tool.c index 8574af1f..b9b0a4a0 100644 --- a/src/tools/gids-tool.c +++ b/src/tools/gids-tool.c @@ -115,8 +115,7 @@ static int initialize(sc_card_t *card, const char *so_pin, const char *user_pin, return -1; } - if (len == 0) { - } else if (len != 24) { + if (len != 24) { fprintf(stderr, "The admin key must be a hexadecimal string of 48 characters\n"); return -1; } From 78c79c0efbffe98716130a12c5b29bb091d53bfe Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 16:59:30 +0100 Subject: [PATCH 103/189] opensc-explorer: refactor arg_to_path() * fix indentation * fix spaces before opening curly braces --- src/tools/opensc-explorer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 9a4dc65f..8a38d1fd 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -371,7 +371,8 @@ arg_to_path(const char *arg, sc_path_t *path, int is_id) } else { /* file id */ u8 cbuf[2]; - if (arg_to_fid(arg, cbuf) < 0) + + if (arg_to_fid(arg, cbuf) < 0) return -1; if ((cbuf[0] == 0x3F && cbuf[1] == 0x00) || is_id) { @@ -380,8 +381,8 @@ arg_to_path(const char *arg, sc_path_t *path, int is_id) path->type = (is_id) ? SC_PATH_TYPE_FILE_ID : SC_PATH_TYPE_PATH; } else { *path = current_path; - if (path->type == SC_PATH_TYPE_DF_NAME) { - if (path->len > sizeof(path->aid.value)) { + if (path->type == SC_PATH_TYPE_DF_NAME) { + if (path->len > sizeof(path->aid.value)) { fprintf(stderr, "Invalid length of DF_NAME path\n"); return -1; } From f20b646a97f1f791b73c7a23f5e6a68be44d0605 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 2 Feb 2020 11:22:49 +0100 Subject: [PATCH 104/189] opensc-explorer: re-factor do_cd() * do not fail on SC_FILE_TYPE_UNKNOWN: be more flexible w.r.t accepting unknown file types when the preceding card operations succeeded * fix spaces before opening curly braces --- src/tools/opensc-explorer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 8a38d1fd..052d7ac8 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -707,10 +707,10 @@ static int do_cd(int argc, char **argv) return -1; } - if (path.type == SC_PATH_TYPE_DF_NAME) { + if (path.type == SC_PATH_TYPE_DF_NAME) { sc_format_path("3F00", &path); } - else { + else { path.len -= 2; } @@ -738,7 +738,8 @@ static int do_cd(int argc, char **argv) check_ret(r, SC_AC_OP_SELECT, "unable to select DF", current_file); return -1; } - if ((file->type != SC_FILE_TYPE_DF) && (card->type != SC_CARD_TYPE_BELPIC_EID)) { + if ((file->type != SC_FILE_TYPE_DF) && (file->type != SC_FILE_TYPE_UNKNOWN) && + (card->type != SC_CARD_TYPE_BELPIC_EID)) { fprintf(stderr, "Error: file is not a DF.\n"); sc_file_free(file); select_current_path_or_die(); From 4abacbf5c1648aa69296679042fa7a1b057a910c Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sun, 2 Feb 2020 13:57:27 +0100 Subject: [PATCH 105/189] opensc-explorer: re-factor read_and_print_binary_file() * rename from read_and_util_print_binary_file(); adapt callers * use large enough buffer size SC_MAX_EXT_APDU_RESP_SIZE instead of potentially too small magic number * fix spaces before opening curly braces * avoid special casing SC_CARD_TYPE_BELPIC_EID: a successful read of an empty file is still a success, even if nothing can get printed --- src/tools/opensc-explorer.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 052d7ac8..61338f1d 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -752,35 +752,29 @@ static int do_cd(int argc, char **argv) return 0; } -static int read_and_util_print_binary_file(sc_file_t *file) +static int read_and_print_binary_file(sc_file_t *file) { - unsigned char *buf = NULL; + u8 *buf; + size_t size = (file->size > 0) ? file->size : SC_MAX_EXT_APDU_RESP_SIZE; int r, ret = -1; - size_t size; - if (file->size) { - size = file->size; - } else { - size = 1024; - } - buf = malloc(size); - if (!buf) + buf = calloc(size, 1); + if (buf == NULL) return -1; r = sc_lock(card); if (r == SC_SUCCESS) r = sc_read_binary(card, 0, buf, size, 0); sc_unlock(card); - if (r < 0) { - check_ret(r, SC_AC_OP_READ, "read failed", file); + if (r < 0) { + check_ret(r, SC_AC_OP_READ, "Read failed", file); goto err; } - if ((r == 0) && (card->type == SC_CARD_TYPE_BELPIC_EID)) - goto err; util_hex_dump_asc(stdout, buf, r, 0); ret = 0; + err: free(buf); return ret; @@ -864,7 +858,7 @@ static int do_cat(int argc, char **argv) goto err; } if (file->ef_structure == SC_FILE_EF_TRANSPARENT && !sfi) - read_and_util_print_binary_file(file); + read_and_print_binary_file(file); else read_and_print_record_file(file, sfi); From b6febc0c7a84e23dcc5c26dea20846446a5e4249 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 14:20:31 +0100 Subject: [PATCH 106/189] opensc-explorer: re-factor do_find() * set default values for variables at declaration time * use sizeof(fid) instead of magic number * use braces after sizeof, i.e. sizeof(X) instead of sizeof X * start error message with upper-case letter --- src/tools/opensc-explorer.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 61338f1d..86b28d72 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -553,14 +553,11 @@ static int do_ls(int argc, char **argv) static int do_find(int argc, char **argv) { - u8 fid[2], end[2]; + u8 fid[2] = { 0x00, 0x00 }; + u8 end[2] = { 0xFF, 0xFF }; sc_path_t path; int r; - fid[0] = 0; - fid[1] = 0; - end[0] = 0xFF; - end[1] = 0xFF; switch (argc) { case 2: if (arg_to_fid(argv[1], end) != 0) @@ -585,10 +582,10 @@ static int do_find(int argc, char **argv) if (current_path.type != SC_PATH_TYPE_DF_NAME) { path = current_path; - sc_append_path_id(&path, fid, sizeof fid); + sc_append_path_id(&path, fid, sizeof(fid)); } else { - if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0) != SC_SUCCESS) { - fprintf(stderr, "unable to set path.\n"); + if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, sizeof(fid), 0, 0) != SC_SUCCESS) { + fprintf(stderr, "Unable to set path.\n"); die(1); } } From f556c275f7fb5ab44a95f46f1909dfa5244925ab Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 14:28:23 +0100 Subject: [PATCH 107/189] opensc-explorer: re-factor do_find_tags() * set default values for variables at declaration time * replace magic number used as potentially too small buffer size by SC_MAX_EXT_APDU_RESP_SIZE * use braces after sizeof, i.e. sizeof(X) instead of sizeof X --- src/tools/opensc-explorer.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 86b28d72..f1433ad2 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -618,14 +618,12 @@ static int do_find(int argc, char **argv) static int do_find_tags(int argc, char **argv) { - u8 start[2], end[2], rbuf[256]; + u8 start[2] = { 0x00, 0x00 }; + u8 end[2] = { 0xFF, 0xFF }; + u8 rbuf[SC_MAX_EXT_APDU_RESP_SIZE]; int r; unsigned int tag, tag_end; - start[0] = 0x00; - start[1] = 0x00; - end[0] = 0xFF; - end[1] = 0xFF; switch (argc) { case 2: if (arg_to_fid(argv[1], end) != 0) @@ -650,7 +648,7 @@ static int do_find_tags(int argc, char **argv) r = sc_lock(card); if (r == SC_SUCCESS) - r = sc_get_data(card, tag, rbuf, sizeof rbuf); + r = sc_get_data(card, tag, rbuf, sizeof(rbuf)); else r = SC_ERROR_READER_LOCKED; sc_unlock(card); From 968815e6ef91ba3ed4175eee6ea8adb6cebcedb4 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 14:34:46 +0100 Subject: [PATCH 108/189] opensc-explorer: re-factor do_get_data() * determine DO ID/tag the same way as do_find_tags() * replace magic magic number used as potentially too small buffer size by SC_MAX_EXT_APDU_RESP_SIZE * change buffer type from unsigned char to u8 for consistency with do_put_data() & do_find_tags() * give ID/tag of DO in error message * open target file in binary mode --- src/tools/opensc-explorer.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index f1433ad2..3bfdc2a0 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1764,35 +1764,38 @@ static int do_random(int argc, char **argv) static int do_get_data(int argc, char **argv) { - unsigned char buffer[256]; + u8 id[2] = { 0x00, 0x00 }; unsigned int tag; + u8 buffer[SC_MAX_EXT_APDU_RESP_SIZE]; FILE *fp; int r; if (argc != 1 && argc != 2) return usage(do_get_data); + if (arg_to_fid(argv[0], id) != 0) + return usage(do_get_data); + tag = id[0] << 8 | id[1]; - tag = strtoul(argv[0], NULL, 16); r = sc_lock(card); if (r == SC_SUCCESS) r = sc_get_data(card, tag, buffer, sizeof(buffer)); sc_unlock(card); if (r < 0) { - fprintf(stderr, "Failed to get data object: %s\n", sc_strerror(r)); + fprintf(stderr, "Failed to get DO %04X: %s\n", tag, sc_strerror(r)); return -1; } if (argc == 2) { - const char *filename = argv[1]; + const char *filename = argv[1]; - if (!(fp = fopen(filename, "w"))) { + if (!(fp = fopen(filename, "wb"))) { perror(filename); return -1; } fwrite(buffer, r, 1, fp); fclose(fp); } else { - printf("Object %04x:\n", tag & 0xFFFF); + printf("Data Object %04X:\n", tag & 0xFFFF); util_hex_dump_asc(stdout, buffer, r, 0); } From f1d46401cb93ab7c3581218b327af55ea87e2e2d Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 15:14:01 +0100 Subject: [PATCH 109/189] opensc-explorer: re-factor do_put_data() * determine DO ID/tag the same way as do_find_tags() * start error message with upper-case letter * use sc_strerror(r) instead of plain numeric r in error message * adapt size of buffer to SC_MAX_EXT_APDU_DATA_SIZE --- src/tools/opensc-explorer.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 3bfdc2a0..adf01af7 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1807,22 +1807,24 @@ static int do_get_data(int argc, char **argv) **/ static int do_put_data(int argc, char **argv) { + u8 id[2] = { 0x00, 0x00 }; unsigned int tag; - u8 buf[SC_MAX_EXT_APDU_BUFFER_SIZE]; + u8 buf[SC_MAX_EXT_APDU_DATA_SIZE]; size_t buflen = sizeof(buf); int r; if (argc != 2) return usage(do_put_data); - /* Extract DO's tag */ - tag = strtoul(argv[0], NULL, 16); + if (arg_to_fid(argv[0], id) != 0) + return usage(do_get_data); + tag = id[0] << 8 | id[1]; /* Extract the new content */ /* buflen is the max length of reception buffer */ r = parse_string_or_hexdata(argv[1], buf, &buflen); if (r < 0) { - fprintf(stderr, "error parsing %s: %s\n", argv[1], sc_strerror(r)); + fprintf(stderr, "Error parsing %s: %s\n", argv[1], sc_strerror(r)); return r; } @@ -1832,7 +1834,7 @@ static int do_put_data(int argc, char **argv) r = sc_put_data(card, tag, buf, buflen); sc_unlock(card); if (r < 0) { - fprintf(stderr, "Cannot put data to %04X; return %i\n", tag, r); + fprintf(stderr, "Failed to put data to DO %04X: %s\n", tag, sc_strerror(r)); return -1; } From b77e0faadb5f6edb8272d2856f5fff49884664fa Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 15:56:36 +0100 Subject: [PATCH 110/189] opensc-explorer: re-factor do_ls() * replace magic magic number used as potentially too small buffer size by SC_MAX_EXT_APDU_RESP_SIZE * replace magic number for filename by SC_MAX_PATH_STRING_SIZE * start error messages with upper-case letters * use braces after sizeof, i.e. sizeof(X) instead of sizeof X * fix indentation --- src/tools/opensc-explorer.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index adf01af7..2f2bd6ab 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -488,24 +488,22 @@ static int pattern_match(const char *pattern, const char *string) static int do_ls(int argc, char **argv) { - u8 buf[256], *cur = buf; + u8 buf[SC_MAX_EXT_APDU_RESP_SIZE], *cur = buf; int r, count; - memset(buf, 0, sizeof buf); + memset(buf, 0, sizeof(buf)); r = sc_lock(card); if (r == SC_SUCCESS) r = sc_list_files(card, buf, sizeof(buf)); sc_unlock(card); if (r < 0) { - check_ret(r, SC_AC_OP_LIST_FILES, "unable to receive file listing", current_file); + check_ret(r, SC_AC_OP_LIST_FILES, "Unable to receive file listing", current_file); return -1; } count = r; printf("FileID\tType Size\n"); while (count >= 2) { - sc_path_t path; - sc_file_t *file = NULL; - char filename[10]; + char filename[SC_MAX_PATH_STRING_SIZE]; int i = 0; int matches = 0; @@ -522,12 +520,15 @@ static int do_ls(int argc, char **argv) /* if any filename pattern were given, filter only matching file names */ if (argc == 0 || matches) { + sc_path_t path; + sc_file_t *file = NULL; + if (current_path.type != SC_PATH_TYPE_DF_NAME) { path = current_path; sc_append_path_id(&path, cur, 2); } else { if (sc_path_set(&path, SC_PATH_TYPE_FILE_ID, cur, 2, 0, 0) != SC_SUCCESS) { - fprintf(stderr, "unable to set path.\n"); + fprintf(stderr, "Unable to set path.\n"); die(1); } } @@ -537,10 +538,11 @@ static int do_ls(int argc, char **argv) r = sc_select_file(card, &path, &file); sc_unlock(card); if (r) { - fprintf(stderr, " %02X%02X unable to select file, %s\n", cur[0], cur[1], sc_strerror(r)); + fprintf(stderr, "Unable to select file %02X%02X: %s\n", + cur[0], cur[1], sc_strerror(r)); } else { file->id = (cur[0] << 8) | cur[1]; - print_file(file); + print_file(file); sc_file_free(file); } } From c2a8102615c9bfc7dd004df61e4d6a46ad6e5586 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 18:05:14 +0100 Subject: [PATCH 111/189] opensc-explorer: re-factor do_get() * replace magic number used as potentially too small buffer size by SC_MAX_EXT_APDU_RESP_SIZE * start error messages with upper-case letters --- src/tools/opensc-explorer.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 2f2bd6ab..ad0b4526 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef ENABLE_READLINE #include #include @@ -1395,7 +1396,7 @@ static int do_unblock(int argc, char **argv) static int do_get(int argc, char **argv) { - u8 buf[256]; + u8 buf[SC_MAX_EXT_APDU_RESP_SIZE]; int r, err = 1; size_t count = 0; unsigned int idx = 0; @@ -1422,11 +1423,11 @@ static int do_get(int argc, char **argv) r = sc_select_file(card, &path, &file); sc_unlock(card); if (r || file == NULL) { - check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); + check_ret(r, SC_AC_OP_SELECT, "Unable to select file", current_file); goto err; } if (file->type != SC_FILE_TYPE_WORKING_EF || file->ef_structure != SC_FILE_EF_TRANSPARENT) { - fprintf(stderr, "only transparent working EFs may be read\n"); + fprintf(stderr, "Only transparent working EFs may be read\n"); goto err; } count = file->size; @@ -1436,11 +1437,11 @@ static int do_get(int argc, char **argv) r = sc_read_binary(card, idx, buf, c, 0); if (r < 0) { - check_ret(r, SC_AC_OP_READ, "read failed", file); + check_ret(r, SC_AC_OP_READ, "Read failed", file); goto err; } if ((r != c) && (card->type != SC_CARD_TYPE_BELPIC_EID)) { - fprintf(stderr, "expecting %d, got only %d bytes.\n", c, r); + fprintf(stderr, "Expecting %d, got only %d bytes.\n", c, r); goto err; } if ((r == 0) && (card->type == SC_CARD_TYPE_BELPIC_EID)) From be152f78b41cf3c5bcc66aa2b96136284c984064 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 16:15:27 +0100 Subject: [PATCH 112/189] opensc-explorer: re-factor do_update_binary() * replace magic magic number used as potentially too small buffer size by SC_MAX_EXT_APDU_DATA_SIZE * remove print() statement that looks suspiciously like a leftover from debugging * start error messages with upper-case letters * use sc_strerror(r) instead of plain numeric r in error message * fix spaces before opening curly braces --- src/tools/opensc-explorer.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index ad0b4526..d8fc3cdf 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1469,7 +1469,7 @@ err: static int do_update_binary(int argc, char **argv) { - u8 buf[240]; + u8 buf[SC_MAX_EXT_APDU_DATA_SIZE]; size_t buflen = sizeof(buf); int r, err = 1; int offs; @@ -1480,13 +1480,11 @@ static int do_update_binary(int argc, char **argv) return usage(do_update_binary); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_binary); - offs = strtol(argv[1],NULL,10); - - printf("in: %i; %s\n", offs, argv[2]); + offs = strtol(argv[1], NULL, 10); r = parse_string_or_hexdata(argv[2], buf, &buflen); if (r < 0) { - fprintf(stderr, "unable to parse data\n"); + fprintf(stderr, "Unable to parse input data: %s\n", strerror(r)); return -1; } @@ -1495,11 +1493,11 @@ static int do_update_binary(int argc, char **argv) r = sc_select_file(card, &path, &file); sc_unlock(card); if (r) { - check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); + check_ret(r, SC_AC_OP_SELECT, "Unable to select file", current_file); return -1; } - if (file->ef_structure != SC_FILE_EF_TRANSPARENT) { + if (file->ef_structure != SC_FILE_EF_TRANSPARENT) { fprintf(stderr, "EF structure should be SC_FILE_EF_TRANSPARENT\n"); goto err; } @@ -1509,11 +1507,11 @@ static int do_update_binary(int argc, char **argv) r = sc_update_binary(card, offs, buf, buflen, 0); sc_unlock(card); if (r < 0) { - fprintf(stderr, "Cannot update %04X; return %i\n", file->id, r); + fprintf(stderr, "Cannot update %04X: %s\n", file->id, strerror(r)); goto err; } - printf("Total of %d bytes written to %04X at %i offset.\n", + printf("Total of %d bytes written to %04X at offset %d.\n", r, file->id, offs); err = 0; From b9d4f0c7d8bf2320b73b44bb55c28b23010a3e1c Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 16:35:08 +0100 Subject: [PATCH 113/189] opensc-explorer: re-factor & fix do_update_record() * bug fix: pass correct buffer length to sc_update_record() * bug fix: report correct number of bytes written * bug fix: check for offs to be small enough * replace magic magic number used as potentially too small buffer size by SC_MAX_EXT_APDU_DATA_SIZE * remove print() statement that looks suspiciously like a leftover from debugging * start error messages with upper-case letters * use sc_strerror(r) instead of plain numeric r in error messages * fix spaces before opening curly braces --- src/tools/opensc-explorer.c | 49 ++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index d8fc3cdf..ca2482f7 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1523,9 +1523,9 @@ err: static int do_update_record(int argc, char **argv) { - u8 buf[240]; + u8 buf[SC_MAX_EXT_APDU_DATA_SIZE]; size_t buflen; - int r, i, err = 1; + int r, err = 1; size_t rec, offs; sc_path_t path; sc_file_t *file; @@ -1534,52 +1534,61 @@ static int do_update_record(int argc, char **argv) return usage(do_update_record); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_record); - rec = strtol(argv[1],NULL,10); - offs = strtol(argv[2],NULL,10); - - printf("in: %"SC_FORMAT_LEN_SIZE_T"u; %"SC_FORMAT_LEN_SIZE_T"u; %s\n", rec, offs, argv[3]); + rec = strtol(argv[1], NULL, 10); + offs = strtol(argv[2], NULL, 10); r = sc_lock(card); if (r == SC_SUCCESS) r = sc_select_file(card, &path, &file); sc_unlock(card); if (r) { - check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); + check_ret(r, SC_AC_OP_SELECT, "Unable to select file", current_file); return -1; } - if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE) { + if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE) { fprintf(stderr, "EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n"); goto err; - } else if (rec < 1 || rec > file->record_count) { + } + + if (rec < 1 || rec > file->record_count) { fprintf(stderr, "Invalid record number %"SC_FORMAT_LEN_SIZE_T"u\n", rec); goto err; } r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); - if (r<0) { - fprintf(stderr, "Cannot read record %"SC_FORMAT_LEN_SIZE_T"u; return %i\n", rec, r); - goto err;; + if (r < 0) { + fprintf(stderr, "Cannot read record %"SC_FORMAT_LEN_SIZE_T"u of %04X: %s\n", + rec, file->id, strerror(r)); + goto err; + } + + /* do not allow gaps between data read and added */ + if (offs >= (size_t) r) { + fprintf(stderr, "Offset too large.\n"); + goto err; } buflen = sizeof(buf) - offs; - i = parse_string_or_hexdata(argv[3], buf + offs, &buflen); - if (!i) { - fprintf(stderr, "unable to parse data\n"); + r = parse_string_or_hexdata(argv[3], buf + offs, &buflen); + if (r < 0) { + fprintf(stderr, "Unable to parse input data: %s.\n", strerror(r)); goto err; } r = sc_lock(card); if (r == SC_SUCCESS) - r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR); + r = sc_update_record(card, rec, buf, buflen, SC_RECORD_BY_REC_NR); sc_unlock(card); - if (r<0) { - fprintf(stderr, "Cannot update record %"SC_FORMAT_LEN_SIZE_T"u; return %i\n", rec, r); + if (r < 0) { + fprintf(stderr, "Cannot update record %"SC_FORMAT_LEN_SIZE_T"u of %04X: %s\n.", + rec, file->id, strerror(r)); goto err; } - printf("Total of %d bytes written to record %"SC_FORMAT_LEN_SIZE_T"u at %"SC_FORMAT_LEN_SIZE_T"u offset.\n", - i, rec, offs); + printf("Total of %d bytes written to %04X's record %"SC_FORMAT_LEN_SIZE_T"u " + "at offset %"SC_FORMAT_LEN_SIZE_T"u.\n", + r, file->id, rec, offs); err = 0; err: From 9b0983e96d9a5b53117257437e972cbcb49bb4a5 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 19:12:21 +0100 Subject: [PATCH 114/189] opensc-explorer: re-factor do_random() * use braces after sizeof, i.e. sizeof(X) instead of sizeof X --- src/tools/opensc-explorer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index ca2482f7..465e9c63 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1711,11 +1711,11 @@ static int do_random(int argc, char **argv) if (argc < 1 || argc > 2) return usage(do_random); - count = atoi(argv[0]); - if (count < 0 || (size_t) count > sizeof buffer) { + + if (count < 0 || (size_t) count > sizeof(buffer)) { fprintf(stderr, "Number must be in range 0..%"SC_FORMAT_LEN_SIZE_T"u\n", - sizeof buffer); + sizeof(buffer)); return -1; } From b2f86b3997f2da5fa9f172270a7bfa7f4bdf988f Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 19:21:59 +0100 Subject: [PATCH 115/189] opensc-explorer: re-factor read_and_print_record_file() * replace magic magic number used as potentially too small buffer size by SC_MAX_EXT_APDU_RESP_SIZE * start error message with upper-case letter * return 0 on success --- src/tools/opensc-explorer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 465e9c63..66c4be65 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -780,7 +780,7 @@ err: static int read_and_print_record_file(sc_file_t *file, unsigned char sfi) { - u8 buf[256]; + u8 buf[SC_MAX_EXT_APDU_RESP_SIZE]; int rec, r; for (rec = 1; ; rec++) { @@ -794,12 +794,14 @@ static int read_and_print_record_file(sc_file_t *file, unsigned char sfi) if (r == SC_ERROR_RECORD_NOT_FOUND) return 0; if (r < 0) { - check_ret(r, SC_AC_OP_READ, "read failed", file); + check_ret(r, SC_AC_OP_READ, "Read failed", file); return -1; } printf("Record %d:\n", rec); util_hex_dump_asc(stdout, buf, r, 0); } + + return 0; } static int do_cat(int argc, char **argv) From 44c22b7820b34cb6c4ef56024ee9d04f693e03e1 Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 8 Feb 2020 19:39:18 +0100 Subject: [PATCH 116/189] opensc-explorer: re-factor do_put() * replace magic magic number used as potentially too small buffer size by SC_MAX_EXT_APDU_DATA_SIZE * start error message with upper-case letter --- src/tools/opensc-explorer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 66c4be65..715cc906 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1602,7 +1602,7 @@ err: static int do_put(int argc, char **argv) { - u8 buf[256]; + u8 buf[SC_MAX_EXT_APDU_DATA_SIZE]; int r, err = 1; size_t count = 0; unsigned int idx = 0; @@ -1627,7 +1627,7 @@ static int do_put(int argc, char **argv) r = sc_select_file(card, &path, &file); sc_unlock(card); if (r || file == NULL) { - check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); + check_ret(r, SC_AC_OP_SELECT, "Unable to select file", current_file); goto err; } count = file->size; @@ -1646,17 +1646,17 @@ static int do_put(int argc, char **argv) r = sc_update_binary(card, idx, buf, c, 0); sc_unlock(card); if (r < 0) { - check_ret(r, SC_AC_OP_READ, "update failed", file); + check_ret(r, SC_AC_OP_READ, "Update failed", file); goto err; } if (r != c) { - fprintf(stderr, "expecting %d, wrote only %d bytes.\n", c, r); + fprintf(stderr, "Expecting %d, wrote only %d bytes.\n", c, r); goto err; } idx += c; count -= c; } - printf("Total of %d bytes written.\n", idx); + printf("Total of %d bytes written to %04X.\n", idx, file->id); err = 0; err: From 8551e84d74af24638581a473775b71e6aad10dcf Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 4 Mar 2020 23:09:57 +0100 Subject: [PATCH 117/189] fixed https://github.com/OpenSC/OpenSC/issues/1948 closes https://github.com/OpenSC/OpenSC/pull/1958 --- src/tests/p11test/p11test_case_pss_oaep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/p11test/p11test_case_pss_oaep.c b/src/tests/p11test/p11test_case_pss_oaep.c index 01947119..b114b736 100644 --- a/src/tests/p11test/p11test_case_pss_oaep.c +++ b/src/tests/p11test/p11test_case_pss_oaep.c @@ -376,7 +376,7 @@ int oaep_encrypt_decrypt_test(test_cert_t *o, token_info_t *info, test_mech_t *m CK_BYTE *dec_message = NULL; int dec_message_length = 0; int message_length = 16; - unsigned char *enc_message; + unsigned char *enc_message = NULL; int enc_message_length, rv; if (o->private_handle == CK_INVALID_HANDLE) { From 7fb0696a29912aad8ff951d71a702cb31962eb37 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Thu, 13 Feb 2020 15:12:22 +0200 Subject: [PATCH 118/189] Upgrade OpenSSL to 1.1.1 Version 1.0.2 is deprecated Signed-off-by: Raul Metsma --- MacOSX/build-package.in | 6 ++---- appveyor.yml | 4 ++-- win32/Make.rules.mak | 16 ++++++++-------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index 5d9db917..5cb223e8 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -28,15 +28,13 @@ if ! pkg-config libcrypto --atleast-version=1.0.1; then if ! test -e $BUILDPATH/openssl_bin/$PREFIX/lib/pkgconfig; then # Build OpenSSL manually, because Apple's binaries are deprecated if ! test -e openssl; then - git clone --depth=1 https://github.com/openssl/openssl.git -b OpenSSL_1_0_2-stable + git clone --depth=1 https://github.com/openssl/openssl.git -b OpenSSL_1_1_1-stable fi cd openssl KERNEL_BITS=64 ./config --prefix=$PREFIX make clean - make update - make depend make -j 4 - make INSTALL_PREFIX=$BUILDPATH/openssl_bin install_sw + make DESTDIR=$BUILDPATH/openssl_bin install_sw cd .. fi export OPENSSL_CFLAGS="`env PKG_CONFIG_PATH=$BUILDPATH/openssl_bin/$PREFIX/lib/pkgconfig PKG_CONFIG_SYSROOT_DIR=$BUILDPATH/openssl_bin pkg-config --static --cflags libcrypto`" diff --git a/appveyor.yml b/appveyor.yml index ec15bb3b..f3af565b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -79,9 +79,9 @@ build_script: xcopy C:\openpace C:\openpace-${env:OPENSSL_PF} /e /i /y /s cd C:\openpace-${env:OPENSSL_PF}\src # 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 + #cl /IC:\OpenSSL-v111-${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 + cl /IC:\OpenSSL-v111-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c ssl_compat.c lib /out:libeac.lib ca_lib.obj cv_cert.obj cvc_lookup.obj x509_lookup.obj eac_asn1.obj eac.obj eac_ca.obj eac_dh.obj eac_ecdh.obj eac_kdf.obj eac_lib.obj eac_print.obj eac_util.obj misc.obj pace.obj pace_lib.obj pace_mappings.obj ri.obj ri_lib.obj ta.obj ta_lib.obj objects.obj ssl_compat.obj cd C:\projects\OpenSC } diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index b6759e57..0fcd80b6 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -49,26 +49,26 @@ OPENSSL_STATIC_DIR = static !IF "$(DEBUG_DEF)" == "/DDEBUG" !IF "$(PLATFORM)" == "x86" # 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_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 +OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto32MTd.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib !ELSE # 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_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 +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 1.0.2 -OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libeay32MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib +#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 +OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto32MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib !ELSE # 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_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 +OPENSSL_LIB = $(OPENSSL_DIR)\lib\VC\$(OPENSSL_STATIC_DIR)\libcrypto64MT.lib user32.lib advapi32.lib crypt32.lib ws2_32.lib !ENDIF !ENDIF From b89fbce9f2e24c6ca80b8e5fafef1ab1a188cf5f Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 29 Feb 2020 02:50:40 +0100 Subject: [PATCH 119/189] make OPENSSL_DIR configurable --- appveyor.yml | 2 +- win32/Make.rules.mak | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f3af565b..84e6eb0b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -40,7 +40,7 @@ install: If ($env:Configuration -Like "*Light*") { $env:ARTIFACT="${env:ARTIFACT}-Light" } Else { - $env:NMAKE_EXTRA="OPENSSL_DEF=/DENABLE_OPENSSL ${env:NMAKE_EXTRA}" + $env:NMAKE_EXTRA="OPENSSL_DEF=/DENABLE_OPENSSL OPENSSL_DIR=C:\OpenSSL-v111-${env:OPENSSL_PF} ${env:NMAKE_EXTRA}" $env:NMAKE_EXTRA="OPENSSL_EXTRA_CFLAGS=/DOPENSSL_SECURE_MALLOC_SIZE=65536 ${env:NMAKE_EXTRA}" If (!(Test-Path C:\zlib )) { appveyor DownloadFile "https://github.com/madler/zlib/archive/v${env:ZLIB_VER_DOT}.zip" -FileName zlib.zip diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index 0fcd80b6..9a422c5a 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -36,11 +36,13 @@ SM_DEF = /DENABLE_SM # - set the OPENSSL_LIB below to your openssl lib file #OPENSSL_DEF= /DENABLE_OPENSSL !IF "$(OPENSSL_DEF)" == "/DENABLE_OPENSSL" +!IF "$(OPENSSL_DIR)" == "" !IF "$(PLATFORM)" == "x86" OPENSSL_DIR = C:\OpenSSL-Win32 !ELSE OPENSSL_DIR = C:\OpenSSL-Win64 !ENDIF +!ENDIF OPENSSL_INCL_DIR = /I$(OPENSSL_DIR)\include #define OPENSSL_STATIC if you have visual studio compatible with OpenSSL's static binaries From 1e05e9aff0b2372639b2352d08c8de8df7da53ff Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 29 Feb 2020 02:31:19 +0100 Subject: [PATCH 120/189] fixed OpenPACE flags for OpenSSL 1.1.1 --- appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 84e6eb0b..408c4201 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -80,8 +80,10 @@ build_script: cd C:\openpace-${env:OPENSSL_PF}\src # OpenSSL 1.1.0 #cl /IC:\OpenSSL-v111-${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.1 + cl /IC:\OpenSSL-v111-${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 /DHAVE_EC_POINT_GET_AFFINE_COORDINATES=1 /DHAVE_EC_POINT_SET_AFFINE_COORDINATES=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-v111-${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 + #cl /IC:\OpenSSL-v111-${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 } From 2f5514a2d1ed079b3d25b46de0e93bd1ad598815 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 29 Feb 2020 22:42:04 +0100 Subject: [PATCH 121/189] appveyor: build for VS 2017, too --- appveyor.yml | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 408c4201..1f55ff81 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,13 @@ version: 0.20.0.{build} +image: + # not compatible with OpenSSL 1.1.1: + # - Visual Studio 2013 + # not compatible with WiX 3.11.2: + # - Visual Studio 2019 + - Visual Studio 2015 + - Visual Studio 2017 + platform: - x86 - x64 @@ -11,10 +19,6 @@ configuration: environment: GH_TOKEN: secure: aLu3tFc7lRJbotnmnHLx/QruIHc5rLaGm1RttoEdy4QILlPXzVkCZ6loYMz0sfrY - matrix: - - VSVER: 14 - - VSVER: 12 - DO_PUSH_ARTIFACT: yes install: - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` @@ -56,9 +60,19 @@ install: If (!(Test-Path cngsdk.msi )) { appveyor DownloadFile "http://download.microsoft.com/download/2/C/9/2C93059C-0532-42DF-8C24-9AEAFF00768E/cngsdk.msi" } - - ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) - - echo "Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS%" - - call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% + - ps: >- + If ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") { + $env:VCVARSALL="${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" + } ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") { + $env:VCVARSALL="${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" + } ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { + $env:VCVARSALL="${env:VS140COMNTOOLS}\..\..\VC\vcvarsall.bat" + $env:DO_PUSH_ARTIFACT="yes" + } ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2013") { + $env:VCVARSALL="${env:VS120COMNTOOLS}\..\..\VC\vcvarsall.bat" + } + - echo "Using %APPVEYOR_BUILD_WORKER_IMAGE% with %VCVARSALL%" + - call "%VCVARSALL%" %VCVARS_PLATFORM% - cngsdk.msi /quiet - uname -a - set @@ -97,7 +111,7 @@ build_script: - bash -c "exec 0 Date: Wed, 4 Mar 2020 22:08:04 +0100 Subject: [PATCH 122/189] win32: recognize WiX libs for VS2017/2019 --- win32/Make.rules.mak | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index 9a422c5a..4f4971a7 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -17,6 +17,12 @@ WIXVSVER = VS2013 !IF "$(VISUALSTUDIOVERSION)" == "14.0" WIXVSVER = VS2015 !ENDIF +!IF "$(VISUALSTUDIOVERSION)" == "15.0" +WIXVSVER = VS2017 +!ENDIF +!IF "$(VISUALSTUDIOVERSION)" == "16.0" +WIXVSVER = VS2019 +!ENDIF WIX_INCL_DIR = "/I$(WIX)\SDK\$(WIXVSVER)\inc" WIX_LIBS = "$(WIX)\SDK\$(WIXVSVER)\lib\$(PLATFORM)\dutil.lib" "$(WIX)\SDK\$(WIXVSVER)\lib\$(PLATFORM)\wcautil.lib" From 9681193ad58731de19a5d7c452a706a8a716577d Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 5 Mar 2020 09:32:15 +0100 Subject: [PATCH 123/189] fixed macro definition --- src/pkcs11/sc-pkcs11.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index e2c82fba..f87a56f8 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -228,8 +228,7 @@ typedef struct sc_pkcs11_slot sc_pkcs11_slot_t; /* Debug virtual slots. S is slot to be highlighted or NULL * C is a comment format string and args It will be preceeded by "VSS " */ - -#define DEBUG_VSS(S, C...) sc_log(context,"VSS " C); _debug_virtual_slots(S) +#define DEBUG_VSS(S, ...) do { sc_log(context,"VSS " __VA_ARGS__); _debug_virtual_slots(S); } while (0) /* called by DEBUG_VSS to print table of virtual slots */ void _debug_virtual_slots(sc_pkcs11_slot_t *p); From d06f23e89bdfeee0003812e3cd7b7f37d37a6da8 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 5 Mar 2020 22:15:27 +0100 Subject: [PATCH 124/189] avoid debugging PIN commands use a higher debug level to see it anyway --- src/libopensc/log.h | 1 + src/libopensc/sec.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libopensc/log.h b/src/libopensc/log.h index 527281f2..4648643d 100644 --- a/src/libopensc/log.h +++ b/src/libopensc/log.h @@ -37,6 +37,7 @@ enum { SC_LOG_DEBUG_SM, /* secure messaging */ SC_LOG_DEBUG_ASN1, /* asn1.c */ SC_LOG_DEBUG_MATCH, /* card matching */ + SC_LOG_DEBUG_PIN, /* PIN commands */ }; #define SC_COLOR_FG_RED 0x0001 diff --git a/src/libopensc/sec.c b/src/libopensc/sec.c index bc498678..abe31061 100644 --- a/src/libopensc/sec.c +++ b/src/libopensc/sec.c @@ -192,12 +192,19 @@ int sc_reset_retry_counter(sc_card_t *card, unsigned int type, int ref, int sc_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) { - int r; + int r, debug; if (card == NULL) { return SC_ERROR_INVALID_ARGUMENTS; } LOG_FUNC_CALLED(card->ctx); + + debug = card->ctx->debug; + if (data->cmd != SC_PIN_CMD_GET_INFO + && card->ctx->debug < SC_LOG_DEBUG_PIN) { + card->ctx->debug = 0; + } + if (card->ops->pin_cmd) { r = card->ops->pin_cmd(card, data, tries_left); } else if (!(data->flags & SC_PIN_CMD_USE_PINPAD)) { @@ -244,6 +251,8 @@ int sc_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, sc_log(card->ctx, "Use of pin pad not supported by card driver"); r = SC_ERROR_NOT_SUPPORTED; } + card->ctx->debug = debug; + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); } From 267aea759c03405d368b06824df61ec82f25877f Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 6 Mar 2020 12:23:16 +0100 Subject: [PATCH 125/189] use platform dependant implementation of erasing memory fixes potentially insecure use of memset in CWA SM implementation fixes https://github.com/OpenSC/OpenSC/issues/1957 --- configure.ac | 2 +- src/common/libpkcs11.c | 1 - src/libopensc/cwa14890.c | 14 ++++++-------- src/libopensc/sc.c | 8 +++++++- src/pkcs15init/profile.c | 1 - 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/configure.ac b/configure.ac index 45e169bf..8d06eaa8 100644 --- a/configure.ac +++ b/configure.ac @@ -415,7 +415,7 @@ AC_FUNC_STAT AC_FUNC_VPRINTF AC_CHECK_FUNCS([ \ getpass gettimeofday getline memset mkdir \ - strdup strerror \ + strdup strerror memset_s explicit_bzero \ strlcpy strlcat strnlen sigaction ]) AC_CHECK_SIZEOF(void *) diff --git a/src/common/libpkcs11.c b/src/common/libpkcs11.c index 9f99b8af..337bb5b1 100644 --- a/src/common/libpkcs11.c +++ b/src/common/libpkcs11.c @@ -100,7 +100,6 @@ C_UnloadModule(void *module) if (mod->handle != NULL && sc_dlclose(mod->handle) < 0) return CKR_FUNCTION_FAILED; - memset(mod, 0, sizeof(*mod)); free(mod); return CKR_OK; } diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index a8b0664d..d28242d0 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -647,23 +647,22 @@ static int cwa_prepare_external_auth(sc_card_t * card, if (bnsub) BN_free(bnsub); if (buf1) { - memset(buf1, 0, 128); + sc_mem_clear(buf1, 128); free(buf1); } if (buf2) { - memset(buf2, 0, 128); + sc_mem_clear(buf2, 128); free(buf2); } if (buf3) { - memset(buf3, 0, 128); + sc_mem_clear(buf3, 128); free(buf3); } if (sha_buf) { - memset(sha_buf, 0, 74 + 32 + 8 + 1 + 7); + sc_mem_clear(sha_buf, 74 + 32 + 8 + 1 + 7); free(sha_buf); } if (sha_data) { - memset(sha_data, 0, SHA_DIGEST_LENGTH); free(sha_data); } @@ -770,15 +769,14 @@ static int cwa_compute_session_keys(sc_card_t * card) compute_session_keys_end: if (kseed) { - memset(kseed, 0, 32); + sc_mem_clear(kseed, 32); free(kseed); } if (data) { - memset(data, 0, 32 + 4); + sc_mem_clear(data, 32 + 4); free(data); } if (sha_data) { - memset(sha_data, 0, SHA_DIGEST_LENGTH); free(sha_data); } if (res != SC_SUCCESS) diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 85ab0b76..1b957653 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -928,7 +928,13 @@ void sc_mem_secure_free(void *ptr, size_t len) void sc_mem_clear(void *ptr, size_t len) { if (len > 0) { -#ifdef ENABLE_OPENSSL +#ifdef HAVE_MEMSET_S + memset_s(ptr, len, 0, len); +#elif _WIN32 + SecureZeroMemory(ptr, len); +#elif HAVE_EXPLICIT_BZERO + explicit_bzero(ptr, len); +#elif ENABLE_OPENSSL OPENSSL_cleanse(ptr, len); #else memset(ptr, 0, len); diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c index 107529a5..b5f08a9d 100644 --- a/src/pkcs15init/profile.c +++ b/src/pkcs15init/profile.c @@ -485,7 +485,6 @@ sc_profile_free(struct sc_profile *profile) if (profile->p15_spec) sc_pkcs15_card_free(profile->p15_spec); - memset(profile, 0, sizeof(*profile)); free(profile); } From 501311c4e38e6b2bae9525fa6d46ce9a9f41180a Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 6 Mar 2020 14:31:08 +0100 Subject: [PATCH 126/189] TravisCI: fixed OpenPACE build --- MacOSX/build-package.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index 5cb223e8..53248ac7 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -47,7 +47,8 @@ if ! test -e $BUILDPATH/openpace_bin/$PREFIX/lib/pkgconfig; then fi cd openpace autoreconf -vis - ./configure --disable-shared --prefix=$PREFIX CRYPTO_CFLAGS="$OPENSSL_CFLAGS" CRYPTO_LIBS="$OPENSSL_LIBS" HELP2MAN=true + ./configure --disable-shared --prefix=$PREFIX CRYPTO_CFLAGS="$OPENSSL_CFLAGS" CRYPTO_LIBS="$OPENSSL_LIBS" HELP2MAN=/usr/bin/true + touch src/cvc-create.1 src/cvc-print.1 make DESTDIR=$BUILDPATH/openpace_bin install cd .. fi From d6280226739904ea4c8d89b07c6926276f40580c Mon Sep 17 00:00:00 2001 From: Peter Marschall Date: Sat, 7 Mar 2020 10:25:07 +0100 Subject: [PATCH 127/189] OpenPGP: add additional vendors Taken from git.gnupg.org --- src/libopensc/pkcs15-openpgp.c | 2 ++ src/tools/openpgp-tool.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c index 78366e01..e775e3b4 100644 --- a/src/libopensc/pkcs15-openpgp.c +++ b/src/libopensc/pkcs15-openpgp.c @@ -123,8 +123,10 @@ static const pgp_manuf_map_t manuf_map[] = { { 0x4354, "Confidential Technologies" }, { 0x5443, "TIF-IT e.V." }, { 0x63AF, "Trustica" }, + { 0xBA53, "c-base e.V." }, { 0xBD0E, "Paranoidlabs" }, { 0xF517, "FSIJ" }, + { 0xF5EC, "F-Secure" }, { 0x0000, "test card" }, { 0xffff, "test card" }, { 0, NULL } diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c index 7e848b2d..25d982f4 100644 --- a/src/tools/openpgp-tool.c +++ b/src/tools/openpgp-tool.c @@ -303,8 +303,10 @@ static char *prettify_manufacturer(u8 *data, size_t length) case 0x4354: return "Confidential Technologies"; /* cotech.de */ case 0x5443: return "TIF-IT e.V."; case 0x63AF: return "Trustica"; + case 0xBA53: return "c-base e.V."; case 0xBD0E: return "Paranoidlabs"; case 0xF517: return "FSIJ"; + case 0xF5EC: return "F-Secure"; /* 0x0000 and 0xFFFF are defined as test cards per spec, 0xFF00 to 0xFFFE are assigned for use with randomly created From f1bcadfbe9d156adbe509b0860511ee41add0c67 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 10 Mar 2020 12:13:29 +0100 Subject: [PATCH 128/189] pkcs11: don't try to allocate 0 byte with calloc fixes #1978 --- src/pkcs11/pkcs11-global.c | 7 ++++++- win32/Make.rules.mak | 4 ++-- win32/winconfig.h.in | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c index a3260314..67189030 100644 --- a/src/pkcs11/pkcs11-global.c +++ b/src/pkcs11/pkcs11-global.c @@ -456,7 +456,12 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese card_detect_all(); - DEBUG_VSS(NULL, "C_GetSlotList after card_detect_all"); + if (list_empty(&virtual_slots)) { + sc_log(context, "returned 0 slots\n"); + *pulCount = 0; + rv = CKR_OK; + goto out; + } found = calloc(list_size(&virtual_slots), sizeof(CK_SLOT_ID)); diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index 4f4971a7..c6b1aac3 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -1,7 +1,7 @@ OPENSC_FEATURES = pcsc #Include support for minidriver -MINIDRIVER_DEF = /DENABLE_MINIDRIVER +#MINIDRIVER_DEF = /DENABLE_MINIDRIVER #Build MSI with the Windows Installer XML (WIX) toolkit, requires WIX >= 3.9 !IF "$(WIX)" == "" @@ -33,7 +33,7 @@ WIX_LIBS = "$(WIX)\SDK\$(WIXVSVER)\lib\$(PLATFORM)\dutil.lib" "$(WIX)\SDK\$(WIXV SM_DEF = /DENABLE_SM #Build with debugging support -#DEBUG_DEF = /DDEBUG +DEBUG_DEF = /DDEBUG # If you want support for OpenSSL (needed for pkcs15-init tool, software hashing in PKCS#11 library and verification): # - download and build OpenSSL diff --git a/win32/winconfig.h.in b/win32/winconfig.h.in index 94ed9b54..fa682c5b 100644 --- a/win32/winconfig.h.in +++ b/win32/winconfig.h.in @@ -103,6 +103,8 @@ #define DEFAULT_ONEPIN_PKCS11_PROVIDER "@DEFAULT_ONEPIN_PKCS11_PROVIDER@" #endif +#define PKCS11_THREAD_LOCKING + #ifndef DEFAULT_SM_MODULE #define DEFAULT_SM_MODULE "@DEFAULT_SM_MODULE@" #endif From b91cfa8cd7bff91245e9b1e4a7455d183f964bd0 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 10 Mar 2020 12:20:31 +0100 Subject: [PATCH 129/189] reverted accidental change of default flags --- win32/Make.rules.mak | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index c6b1aac3..4f4971a7 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -1,7 +1,7 @@ OPENSC_FEATURES = pcsc #Include support for minidriver -#MINIDRIVER_DEF = /DENABLE_MINIDRIVER +MINIDRIVER_DEF = /DENABLE_MINIDRIVER #Build MSI with the Windows Installer XML (WIX) toolkit, requires WIX >= 3.9 !IF "$(WIX)" == "" @@ -33,7 +33,7 @@ WIX_LIBS = "$(WIX)\SDK\$(WIXVSVER)\lib\$(PLATFORM)\dutil.lib" "$(WIX)\SDK\$(WIXV SM_DEF = /DENABLE_SM #Build with debugging support -DEBUG_DEF = /DDEBUG +#DEBUG_DEF = /DDEBUG # If you want support for OpenSSL (needed for pkcs15-init tool, software hashing in PKCS#11 library and verification): # - download and build OpenSSL From 6ed3939ae5a4517251eafc96b2fbdefdded1b34f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 5 Mar 2020 10:37:14 +0100 Subject: [PATCH 130/189] coolkey: Avoid memory leak Fixup previous attempt to avoid too large allocations Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21059 --- src/libopensc/card-coolkey.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c index ff79e840..c99ef429 100644 --- a/src/libopensc/card-coolkey.c +++ b/src/libopensc/card-coolkey.c @@ -2178,10 +2178,10 @@ static int coolkey_initialize(sc_card_t *card) object_len = bebytes2ulong(object_info.object_length); /* Avoid insanely large data */ if (object_len > MAX_FILE_SIZE) { - LOG_FUNC_RETURN(card->ctx, SC_ERROR_CORRUPTED_DATA); + r = SC_ERROR_CORRUPTED_DATA; + goto cleanup; } - /* the combined object is a single object that can store the other objects. * most coolkeys provisioned by TPS has a single combined object that is * compressed greatly increasing the effectiveness of compress (since lots From dc29b0fe18108f34cac5f2f7d5e5006b189f193c Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 12 Mar 2020 23:07:17 +0100 Subject: [PATCH 131/189] fixed memory leak fixes https://oss-fuzz.com/testcase-detail/6237284133502976 --- src/libopensc/dir.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libopensc/dir.c b/src/libopensc/dir.c index 5a8914d9..6e27293d 100644 --- a/src/libopensc/dir.c +++ b/src/libopensc/dir.c @@ -171,6 +171,8 @@ int sc_enum_apps(sc_card_t *card) sc_format_path("3F002F00", &path); r = sc_select_file(card, &path, &ef_dir); + if (r < 0) + sc_file_free(ef_dir); LOG_TEST_RET(ctx, r, "Cannot select EF.DIR file"); if (ef_dir->type != SC_FILE_TYPE_WORKING_EF) { From 0ba44cbec66ca2d47eac05c50aab0d3529e4ba24 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Thu, 19 Mar 2020 13:31:31 +0100 Subject: [PATCH 132/189] Add length checking --- src/libopensc/card-openpgp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index d044a225..0b0aa945 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -606,17 +606,23 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_ key_info->algorithm = blob->data[0]; /* last byte is only set if pubkey import is supported, empty otherwise*/ - if (blob->data[blob->len] == SC_OPENPGP_KEYFORMAT_EC_STDPUB){ + if (blob->data[blob->len-1] == SC_OPENPGP_KEYFORMAT_EC_STDPUB){ + if (blob->len < 3) + return SC_ERROR_INCORRECT_PARAMETERS; key_info->u.ec.oid_len = blob->len - 2; key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STDPUB; } else { + if (blob->len < 2) + return SC_ERROR_INCORRECT_PARAMETERS; key_info->u.ec.oid_len = blob->len - 1; key_info->u.ec.keyformat = SC_OPENPGP_KEYFORMAT_EC_STD; } - sc_init_oid(&oid); /* Create copy of oid from blob */ + if (blob->len < 2) + return SC_ERROR_INCORRECT_PARAMETERS; + sc_init_oid(&oid); for (j=0; j < (blob->len-1) && j < SC_MAX_OBJECT_ID_OCTETS; j++) { oid.value[j] = blob->data[j+1]; /* ignore first byte of blob (algo ID) */ } From 1e7e6e11a482f5b2c5fcbab38376e4453578f4b0 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Thu, 19 Mar 2020 13:33:12 +0100 Subject: [PATCH 133/189] Add key import of ecc key to openpgp Travis tests --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 23d5c7e3..c85c93b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -248,6 +248,8 @@ script: opensc-tool -n; openpgp-tool --verify CHV3 --pin 12345678 --gen-key 2; pkcs15-init --verify --auth-id 3 --pin 12345678 --delete-objects privkey,pubkey --id 2 --generate-key rsa/2048; + openssl ecparam -genkey -name "brainpoolP384r1" -out myec.key.pem; + pkcs15-init --delete-objects privkey,pubkey --id 3 --store-private-key myec.key.pem --auth-id 3 --verify-pin --id 3; pkcs11-tool -l -t -p 123456; killall java; From b2d082f4aac4110e6ba1a3fdd156955d5150b8d9 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Thu, 19 Mar 2020 14:51:18 +0100 Subject: [PATCH 134/189] Use curve that is supported by trusty OpenSSL package --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c85c93b8..1c55dc3a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -248,7 +248,7 @@ script: opensc-tool -n; openpgp-tool --verify CHV3 --pin 12345678 --gen-key 2; pkcs15-init --verify --auth-id 3 --pin 12345678 --delete-objects privkey,pubkey --id 2 --generate-key rsa/2048; - openssl ecparam -genkey -name "brainpoolP384r1" -out myec.key.pem; + openssl ecparam -genkey -name "secp384r1" -out myec.key.pem; pkcs15-init --delete-objects privkey,pubkey --id 3 --store-private-key myec.key.pem --auth-id 3 --verify-pin --id 3; pkcs11-tool -l -t -p 123456; killall java; From f4d28a18b96d39926e11ae75e0a2f2e47789f190 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Thu, 19 Mar 2020 15:21:55 +0100 Subject: [PATCH 135/189] Add pin to command --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1c55dc3a..b1000d99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -249,7 +249,7 @@ script: openpgp-tool --verify CHV3 --pin 12345678 --gen-key 2; pkcs15-init --verify --auth-id 3 --pin 12345678 --delete-objects privkey,pubkey --id 2 --generate-key rsa/2048; openssl ecparam -genkey -name "secp384r1" -out myec.key.pem; - pkcs15-init --delete-objects privkey,pubkey --id 3 --store-private-key myec.key.pem --auth-id 3 --verify-pin --id 3; + pkcs15-init --verify --auth-id 3 --pin 12345678 --delete-objects privkey,pubkey --id 3 --store-private-key myec.key.pem; pkcs11-tool -l -t -p 123456; killall java; From d5ecafc334aeb333a274ec19b19b92dd261ae8fb Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 20 Mar 2020 17:12:18 +0100 Subject: [PATCH 136/189] fixed memory leak fixes https://oss-fuzz.com/testcase-detail/5084702283399168 --- src/libopensc/ef-atr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libopensc/ef-atr.c b/src/libopensc/ef-atr.c index edbf4410..1a20c8d2 100644 --- a/src/libopensc/ef-atr.c +++ b/src/libopensc/ef-atr.c @@ -148,7 +148,7 @@ int sc_parse_ef_atr(struct sc_card *card) sc_format_path("3F002F01", &path); rv = sc_select_file(card, &path, &file); - LOG_TEST_RET(ctx, rv, "Cannot select EF(ATR) file"); + LOG_TEST_GOTO_ERR(ctx, rv, "Cannot select EF(ATR) file"); if (file->size) { size = file->size; @@ -156,8 +156,10 @@ int sc_parse_ef_atr(struct sc_card *card) size = 1024; } buf = malloc(size); - if (!buf) - LOG_TEST_GOTO_ERR(ctx, SC_ERROR_OUT_OF_MEMORY, "Memory allocation error"); + if (!buf) { + rv = SC_ERROR_OUT_OF_MEMORY; + LOG_TEST_GOTO_ERR(ctx, rv, "Memory allocation error"); + } rv = sc_read_binary(card, 0, buf, size, 0); LOG_TEST_GOTO_ERR(ctx, rv, "Cannot read EF(ATR) file"); From 7840804762f720d1a8886d9c76390c117ac6ef07 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 21 Mar 2020 16:47:26 +0100 Subject: [PATCH 137/189] fixed typo fixes coverity's: "Argument cannot be negative (NEGATIVE_RETURNS)" --- src/tools/opensc-explorer.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/opensc-explorer.c b/src/tools/opensc-explorer.c index 715cc906..ae86e478 100644 --- a/src/tools/opensc-explorer.c +++ b/src/tools/opensc-explorer.c @@ -1486,7 +1486,7 @@ static int do_update_binary(int argc, char **argv) r = parse_string_or_hexdata(argv[2], buf, &buflen); if (r < 0) { - fprintf(stderr, "Unable to parse input data: %s\n", strerror(r)); + fprintf(stderr, "Unable to parse input data: %s\n", sc_strerror(r)); return -1; } @@ -1509,7 +1509,7 @@ static int do_update_binary(int argc, char **argv) r = sc_update_binary(card, offs, buf, buflen, 0); sc_unlock(card); if (r < 0) { - fprintf(stderr, "Cannot update %04X: %s\n", file->id, strerror(r)); + fprintf(stderr, "Cannot update %04X: %s\n", file->id, sc_strerror(r)); goto err; } @@ -1561,7 +1561,7 @@ static int do_update_record(int argc, char **argv) r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r < 0) { fprintf(stderr, "Cannot read record %"SC_FORMAT_LEN_SIZE_T"u of %04X: %s\n", - rec, file->id, strerror(r)); + rec, file->id, sc_strerror(r)); goto err; } @@ -1574,7 +1574,7 @@ static int do_update_record(int argc, char **argv) buflen = sizeof(buf) - offs; r = parse_string_or_hexdata(argv[3], buf + offs, &buflen); if (r < 0) { - fprintf(stderr, "Unable to parse input data: %s.\n", strerror(r)); + fprintf(stderr, "Unable to parse input data: %s.\n", sc_strerror(r)); goto err; } @@ -1584,7 +1584,7 @@ static int do_update_record(int argc, char **argv) sc_unlock(card); if (r < 0) { fprintf(stderr, "Cannot update record %"SC_FORMAT_LEN_SIZE_T"u of %04X: %s\n.", - rec, file->id, strerror(r)); + rec, file->id, sc_strerror(r)); goto err; } @@ -1698,7 +1698,7 @@ static int do_erase(int argc, char **argv) r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL); sc_unlock(card); if (r) { - fprintf(stderr, "Failed to erase card: %s\n", sc_strerror (r)); + fprintf(stderr, "Failed to erase card: %s\n", sc_strerror(r)); return -1; } return 0; From 396aabcb7b578b6b7fcacd21f8f22af1c012fac6 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Tue, 24 Mar 2020 12:07:29 +0100 Subject: [PATCH 138/189] ykneo-openpgp does not support ecc keys yet --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b1000d99..23d5c7e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -248,8 +248,6 @@ script: opensc-tool -n; openpgp-tool --verify CHV3 --pin 12345678 --gen-key 2; pkcs15-init --verify --auth-id 3 --pin 12345678 --delete-objects privkey,pubkey --id 2 --generate-key rsa/2048; - openssl ecparam -genkey -name "secp384r1" -out myec.key.pem; - pkcs15-init --verify --auth-id 3 --pin 12345678 --delete-objects privkey,pubkey --id 3 --store-private-key myec.key.pem; pkcs11-tool -l -t -p 123456; killall java; From 7ba89620bf8c4757b5f6bec2921e7eac7991ccf1 Mon Sep 17 00:00:00 2001 From: alex-nitrokey Date: Tue, 24 Mar 2020 12:09:06 +0100 Subject: [PATCH 139/189] refactoring: get rid of oid_binary in ec_tables --- src/libopensc/card-openpgp.c | 48 ++++++++++++++---------------------- src/libopensc/card-openpgp.h | 1 - 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c index 0b0aa945..e830677c 100644 --- a/src/libopensc/card-openpgp.c +++ b/src/libopensc/card-openpgp.c @@ -88,31 +88,21 @@ static struct sc_card_driver pgp_drv = { static pgp_ec_curves_t ec_curves[] = { - {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, - {{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, -1}}}, /* ansiX9p256r1 */ - {{{1, 3, 132, 0, 34, -1}}, 384, - {{0x2b, 0x81, 0x04, 0x00, 0x22, -1}}}, /* ansiX9p384r1 */ - {{{1, 3, 132, 0, 35, -1}}, 521, - {{0x2b, 0x81, 0x04, 0x00, 0x23, -1}}}, /* ansiX9p521r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256, - {{0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07, -1}}}, /* brainpoolP256r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 11, -1}}, 384, - {{0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0b, -1}}}, /* brainpoolP384r1 */ - {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 13, -1}}, 512, - {{0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0d, -1}}}, /* brainpoolP512r1 */ - {{{-1}}, 0, {{0x0}}} /* This entry must not be touched. */ + {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ + {{{1, 3, 132, 0, 34, -1}}, 384}, /* ansiX9p384r1 */ + {{{1, 3, 132, 0, 35, -1}}, 521}, /* ansiX9p521r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256}, /* brainpoolP256r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 11, -1}}, 384}, /* brainpoolP384r1 */ + {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 13, -1}}, 512}, /* brainpoolP512r1 */ + {{{-1}}, 0} /* This entry must not be touched. */ }; static pgp_ec_curves_t ec_curves_gnuk[] = { - {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256, - {{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, -1}}}, /* ansiX9p256r1 */ - {{{1, 3, 132, 0, 10, -1}}, 256, - {{0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A, -1}}}, /* secp256k1 */ - /*{{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256, - {{0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01, -1}}}, //cv25519 - {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256, - {{0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01, -1}}}, // ed25519 */ - {{{-1}}, 0, {{0x0}}} /* This entry must not be touched. */ + {{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256}, /* ansiX9p256r1 */ + {{{1, 3, 132, 0, 10, -1}}, 256}, /* secp256k1 */ + /*{{{1, 3, 6, 1, 4, 1, 3029, 1, 5, 1, -1}}, 256}, //cv25519 + {{{1, 3, 6, 1, 4, 1, 11591, 15, 1, -1}}, 256}, // ed25519 */ + {{{-1}}, 0} /* This entry must not be touched. */ }; @@ -578,7 +568,7 @@ static int pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_t *key_info) { struct sc_object_id oid; - unsigned int j; + unsigned int j, r; if (blob == NULL || blob->data == NULL || blob->len == 0 || blob->id < 0x00c1 || blob->id > 0x00c3 || key_info == NULL) @@ -620,16 +610,16 @@ pgp_parse_algo_attr_blob(const pgp_blob_t *blob, sc_cardctl_openpgp_keygen_info_ } /* Create copy of oid from blob */ - if (blob->len < 2) - return SC_ERROR_INCORRECT_PARAMETERS; sc_init_oid(&oid); - for (j=0; j < (blob->len-1) && j < SC_MAX_OBJECT_ID_OCTETS; j++) { - oid.value[j] = blob->data[j+1]; /* ignore first byte of blob (algo ID) */ - } + r = sc_asn1_decode_object_id(&blob->data[1], key_info->u.ec.oid_len, &oid); + /* decoding failed, return sc_asn1_decode_object_id error code */ + if (r > 0){ + return r; + } /* compare with list of supported ec_curves */ for (j=0; ec_curves[j].oid.value[0] >= 0; j++){ - if (sc_compare_oid(&ec_curves[j].oid_binary, &oid)){ + if (sc_compare_oid(&ec_curves[j].oid, &oid)){ key_info->u.ec.oid = ec_curves[j].oid; key_info->u.ec.key_length = ec_curves[j].size; break; diff --git a/src/libopensc/card-openpgp.h b/src/libopensc/card-openpgp.h index 9f3dea11..00c2f90a 100644 --- a/src/libopensc/card-openpgp.h +++ b/src/libopensc/card-openpgp.h @@ -163,7 +163,6 @@ typedef struct pgp_blob { typedef struct _pgp_ec_curves { struct sc_object_id oid; size_t size; - struct sc_object_id oid_binary; } pgp_ec_curves_t; From 768bd1dde7d3815325edb3f1f920a51862f61feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Cie=C5=9Blak?= Date: Fri, 3 Apr 2020 01:23:57 +0200 Subject: [PATCH 140/189] Check if we HAVE_ENDIAN_H BSDs will have , Linux just --- configure.ac | 3 ++- src/libopensc/reader-tr03119.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 8d06eaa8..6219f36b 100644 --- a/configure.ac +++ b/configure.ac @@ -400,7 +400,8 @@ AC_HEADER_ASSERT AC_CHECK_HEADERS([ \ errno.h fcntl.h stdlib.h \ inttypes.h string.h strings.h \ - sys/time.h unistd.h sys/mman.h + sys/time.h unistd.h sys/mman.h \ + sys/endian.h endian.h ]) dnl Checks for typedefs, structures, and compiler characteristics. diff --git a/src/libopensc/reader-tr03119.c b/src/libopensc/reader-tr03119.c index 009e62a7..0a425a50 100644 --- a/src/libopensc/reader-tr03119.c +++ b/src/libopensc/reader-tr03119.c @@ -40,8 +40,13 @@ #ifndef _BSD_SOURCE #define _BSD_SOURCE /* See feature_test_macros(7) */ #endif +#ifdef HAVE_SYS_ENDIAN_H +#include +#endif +#ifdef HAVE_ENDIAN_H #include #endif +#endif int get_pace_capabilities(u8 *bitmap) { From 591ffad5dc9ee8e19d95c6ecd7dd827dca36553c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Cie=C5=9Blak?= Date: Fri, 3 Apr 2020 00:31:20 +0200 Subject: [PATCH 141/189] Ignore test-driver and aminclude_static.am Those files are generate by autotools --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 76f431d3..5dc35ee1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ core archive acinclude.m4 aclocal.m4 +aminclude_static.am autom4te.cache compile confdefs.h @@ -22,6 +23,7 @@ mkinstalldirs so_locations stamp-h* tags +test-driver .deps .libs .#*# From 5eff42e39e14f8122c5a8296d28282dd7fa74a9d Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Mon, 2 Mar 2020 14:47:00 +0200 Subject: [PATCH 142/189] Use nologo parameter to avoid warnings in appveyor log Signed-off-by: Raul Metsma --- appveyor.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 1f55ff81..8a53d03a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,6 +19,9 @@ configuration: environment: GH_TOKEN: secure: aLu3tFc7lRJbotnmnHLx/QruIHc5rLaGm1RttoEdy4QILlPXzVkCZ6loYMz0sfrY + PATH: C:\cygwin\bin;%PATH% + OPENPACE_VER: 1.1.0 + ZLIB_VER_DOT: 1.2.11 install: - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` @@ -26,9 +29,6 @@ install: Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` throw "There are newer queued builds for this pull request, failing early." } - date /T & time /T - - set PATH=C:\cygwin\bin;%PATH% - - set OPENPACE_VER=1.1.0 - - set ZLIB_VER_DOT=1.2.11 - ps: $env:PACKAGE_NAME=(git describe --tags --abbrev=0) - ps: >- If ($env:Platform -Match "x86") { @@ -42,10 +42,10 @@ install: } - ps: >- If ($env:Configuration -Like "*Light*") { - $env:ARTIFACT="${env:ARTIFACT}-Light" + $env:ARTIFACT+="-Light" } Else { - $env:NMAKE_EXTRA="OPENSSL_DEF=/DENABLE_OPENSSL OPENSSL_DIR=C:\OpenSSL-v111-${env:OPENSSL_PF} ${env:NMAKE_EXTRA}" - $env:NMAKE_EXTRA="OPENSSL_EXTRA_CFLAGS=/DOPENSSL_SECURE_MALLOC_SIZE=65536 ${env:NMAKE_EXTRA}" + $env:NMAKE_EXTRA+=" OPENSSL_DEF=/DENABLE_OPENSSL OPENSSL_DIR=C:\OpenSSL-v111-${env:OPENSSL_PF}" + $env:NMAKE_EXTRA+=" OPENSSL_EXTRA_CFLAGS=/DOPENSSL_SECURE_MALLOC_SIZE=65536" If (!(Test-Path C:\zlib )) { appveyor DownloadFile "https://github.com/madler/zlib/archive/v${env:ZLIB_VER_DOT}.zip" -FileName zlib.zip 7z x zlib.zip -oC:\ @@ -85,23 +85,23 @@ build_script: xcopy C:\zlib C:\zlib-${env:OPENSSL_PF} /e /i /y /s cd C:\zlib-${env:OPENSSL_PF} (Get-Content win32/Makefile.msc).replace('-MD', '-MT') | Set-Content win32/Makefile.msc - nmake -f win32/Makefile.msc zlib.lib + nmake /nologo -f win32/Makefile.msc zlib.lib } - $env:NMAKE_EXTRA="ZLIBSTATIC_DEF=/DENABLE_ZLIB_STATIC ZLIB_INCL_DIR=/IC:\zlib-${env:OPENSSL_PF} ZLIB_LIB=C:\zlib-${env:OPENSSL_PF}\zlib.lib ${env:NMAKE_EXTRA}" + $env:NMAKE_EXTRA+=" ZLIBSTATIC_DEF=/DENABLE_ZLIB_STATIC ZLIB_INCL_DIR=/IC:\zlib-${env:OPENSSL_PF} ZLIB_LIB=C:\zlib-${env:OPENSSL_PF}\zlib.lib" If (!(Test-Path -Path "C:\openpace-${env:OPENSSL_PF}" )) { # 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 # OpenSSL 1.1.0 - #cl /IC:\OpenSSL-v111-${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 + #cl /nologo /IC:\OpenSSL-v110-${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.1 - cl /IC:\OpenSSL-v111-${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 /DHAVE_EC_POINT_GET_AFFINE_COORDINATES=1 /DHAVE_EC_POINT_SET_AFFINE_COORDINATES=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 + cl /nologo /IC:\OpenSSL-v111-${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 /DHAVE_EC_POINT_GET_AFFINE_COORDINATES=1 /DHAVE_EC_POINT_SET_AFFINE_COORDINATES=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-v111-${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 + #cl /nologo /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 /nologo /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 } - $env:NMAKE_EXTRA="OPENPACE_DEF=/DENABLE_OPENPACE OPENPACE_DIR=C:\openpace-${env:OPENSSL_PF} ${env:NMAKE_EXTRA}" + $env:NMAKE_EXTRA+=" OPENPACE_DEF=/DENABLE_OPENPACE OPENPACE_DIR=C:\openpace-${env:OPENSSL_PF}" } - bash -c "exec 0 Date: Mon, 6 Apr 2020 09:54:29 +0200 Subject: [PATCH 143/189] iasecc: Avoid memory leak on error Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21297 --- src/libopensc/card-iasecc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c index 835572be..45b3f348 100644 --- a/src/libopensc/card-iasecc.c +++ b/src/libopensc/card-iasecc.c @@ -1036,6 +1036,7 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path, rv = iasecc_process_fci(card, file, apdu.resp, apdu.resplen); if (rv) { + sc_file_free(file); if (file_out) { sc_file_free(*file_out); *file_out = NULL; From 7893d2860c1472ade6b2d45c3bd4f97199ced096 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 6 Apr 2020 12:28:13 +0200 Subject: [PATCH 144/189] idprime: Fix null-dereference Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21586 --- src/libopensc/card-idprime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c index 9f5adde9..e805da15 100644 --- a/src/libopensc/card-idprime.c +++ b/src/libopensc/card-idprime.c @@ -150,7 +150,7 @@ static int idprime_select_index(sc_card_t *card) } sc_file_free(file); /* Ignore too large files */ - if (r > MAX_FILE_SIZE) { + if (r <= 0 || r > MAX_FILE_SIZE) { r = SC_ERROR_INVALID_DATA; } return r; From 2c26b7392d8d0d7e1db2b6143583376758074dda Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 13 Jan 2020 17:25:38 +0100 Subject: [PATCH 145/189] opensc-notify: handle reader insertion/removal events - If readers are attatched, the new reader is probed for a card to check if a notification needs to be sent - removal of readers are not notified to the user, we assume that PC/SC sends the correct card removal event - The list of readers to be monitored is adjusted once a reader (dis)appears - On macOS, without PnP notification, we always check for new/removed readers with SCardListReaders - fixes interrupt handling in opensc-notify on Unix fixes https://github.com/OpenSC/OpenSC/issues/1874 --- src/libopensc/errors.c | 4 +- src/libopensc/internal-winscard.h | 1 + src/libopensc/opensc.h | 33 +++-- src/libopensc/reader-pcsc.c | 205 +++++++++++++++++++++--------- src/tools/opensc-notify.c | 125 ++++++++++-------- src/ui/strings.c | 10 +- 6 files changed, 248 insertions(+), 130 deletions(-) diff --git a/src/libopensc/errors.c b/src/libopensc/errors.c index 5b58b7ea..03cb79dd 100644 --- a/src/libopensc/errors.c +++ b/src/libopensc/errors.c @@ -45,8 +45,8 @@ const char *sc_strerror(int error) "Message too long (keypad)", "Timeout while waiting for event from card reader", "Unresponsive card (correctly inserted?)", - "Reader detached (hotplug device?)", - "Reader reattached (hotplug device?)", + "Reader detached", + "Reader reattached", "Reader in use by another application" }; const int rdr_base = -SC_ERROR_READER; diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h index edc315ca..6b2a21c5 100644 --- a/src/libopensc/internal-winscard.h +++ b/src/libopensc/internal-winscard.h @@ -100,6 +100,7 @@ typedef unsigned __int8 uint8_t; #define SCARD_E_NOT_TRANSACTED 0x80100016 /**< An attempt was made to end a non-existent transaction. */ #define SCARD_E_READER_UNAVAILABLE 0x80100017 /**< The specified reader is not currently available for use. */ #define SCARD_E_NO_SERVICE 0x8010001D /**< The Smart card resource manager is not running. */ +#define SCARD_E_SERVICE_STOPPED 0x8010001E /**< The smart card resource manager has shut down. */ #define SCARD_E_NO_READERS_AVAILABLE 0x8010002E /**< Cannot find a smart card reader. */ #define SCARD_W_UNRESPONSIVE_CARD 0x80100066 /**< The smart card is not responding to a reset. */ #define SCARD_W_UNPOWERED_CARD 0x80100067 /**< Power has been removed from the smart card, so that further communication is not possible. */ diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 10bea0a0..9e764665 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -213,10 +213,10 @@ extern "C" { /* Event masks for sc_wait_for_event() */ #define SC_EVENT_CARD_INSERTED 0x0001 #define SC_EVENT_CARD_REMOVED 0x0002 -#define SC_EVENT_CARD_EVENTS SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED +#define SC_EVENT_CARD_EVENTS (SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED) #define SC_EVENT_READER_ATTACHED 0x0004 #define SC_EVENT_READER_DETACHED 0x0008 -#define SC_EVENT_READER_EVENTS SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED +#define SC_EVENT_READER_EVENTS (SC_EVENT_READER_ATTACHED|SC_EVENT_READER_DETACHED) #define MAX_FILE_SIZE 65535 @@ -1024,18 +1024,25 @@ int sc_disconnect_card(struct sc_card *card); int sc_detect_card_presence(sc_reader_t *reader); /** - * Waits for an event on readers. Note: only the event is detected, - * there is no update of any card or other info. - * NOTE: Only PC/SC backend implements this. - * @param ctx pointer to a Context structure - * @param event_mask The types of events to wait for; this should - * be ORed from one of the following - * SC_EVENT_CARD_REMOVED - * SC_EVENT_CARD_INSERTED - * SC_EVENT_READER_ATTACHED - * @param event_reader (OUT) the reader on which the event was detected, or NULL if new reader + * Waits for an event on readers. + * + * In case of a reader event (attached/detached), the list of reader is + * adjusted accordingly. This means that a subsequent call to + * `sc_ctx_detect_readers()` is not needed. + * + * @note Only PC/SC backend implements this. An infinite timeout on macOS does + * not detect reader events (use a limited timeout instead if needed). + * + * @param ctx (IN) pointer to a Context structure + * @param event_mask (IN) The types of events to wait for; this should + * be ORed from one of the following: + * - SC_EVENT_CARD_REMOVED + * - SC_EVENT_CARD_INSERTED + * - SC_EVENT_READER_ATTACHED + * - SC_EVENT_READER_DETACHED + * @param event_reader (OUT) the reader on which the event was detected * @param event (OUT) the events that occurred. This is also ORed - * from the SC_EVENT_CARD_* constants listed above. + * from the constants listed above. * @param timeout Amount of millisecs to wait; -1 means forever * @retval < 0 if an error occurred * @retval = 0 if a an event happened diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 14e3b4e0..34dc821b 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -127,6 +127,9 @@ struct pcsc_global_private_data { SCardTransmit_t SCardTransmit; SCardListReaders_t SCardListReaders; SCardGetAttrib_t SCardGetAttrib; + + sc_reader_t *attached_reader; + sc_reader_t *removed_reader; }; struct pcsc_private_data { @@ -185,6 +188,7 @@ static int pcsc_to_opensc_error(LONG rv) return SC_ERROR_READER_DETACHED; case SCARD_E_NO_SERVICE: + case SCARD_E_SERVICE_STOPPED: /* If the service is (auto)started, there could be readers later */ return SC_ERROR_NO_READERS_FOUND; case SCARD_E_NO_SMARTCARD: @@ -358,7 +362,7 @@ static int refresh_attributes(sc_reader_t *reader) if (reader->ctx->flags & SC_CTX_FLAG_TERMINATE) return SC_ERROR_NOT_ALLOWED; - if (priv->reader_state.szReader == NULL) { + if (priv->reader_state.szReader == NULL || reader->ctx->flags & SC_READER_REMOVED) { priv->reader_state.szReader = reader->name; priv->reader_state.dwCurrentState = SCARD_STATE_UNAWARE; priv->reader_state.dwEventState = SCARD_STATE_UNAWARE; @@ -382,12 +386,11 @@ static int refresh_attributes(sc_reader_t *reader) } /* the system could not detect the reader. It means, the prevoiusly attached reader is disconnected. */ - if ( + if (rv == (LONG)SCARD_E_UNKNOWN_READER #ifdef SCARD_E_NO_READERS_AVAILABLE - (rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) || + || rv == (LONG)SCARD_E_NO_READERS_AVAILABLE #endif - (rv == (LONG)SCARD_E_UNKNOWN_READER) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) { - + || rv == (LONG)SCARD_E_SERVICE_STOPPED) { if (old_flags & SC_READER_CARD_PRESENT) { reader->flags |= SC_READER_CARD_CHANGED; } @@ -1143,7 +1146,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) return; rv = gpriv->SCardControl(card_handle, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len); - if (rv != (LONG)SCARD_S_SUCCESS) { + if (rv != SCARD_S_SUCCESS) { PCSC_TRACE(reader, "SCardControl failed", rv); return; } @@ -1382,6 +1385,8 @@ static int pcsc_detect_readers(sc_context_t *ctx) } sc_log(ctx, "Probing PC/SC readers"); + gpriv->attached_reader = NULL; + gpriv->removed_reader = NULL; do { if (gpriv->pcsc_ctx == (SCARDCONTEXT)-1) { @@ -1399,12 +1404,11 @@ static int pcsc_detect_readers(sc_context_t *ctx) * All readers have disappeared, so mark them as * such so we don't keep polling them over and over. */ - if ( + if (rv == (LONG)SCARD_E_NO_SERVICE #ifdef SCARD_E_NO_READERS_AVAILABLE - (rv == (LONG)SCARD_E_NO_READERS_AVAILABLE) || + || rv == (LONG)SCARD_E_NO_READERS_AVAILABLE #endif - (rv == (LONG)SCARD_E_NO_SERVICE) || (rv == (LONG)SCARD_E_SERVICE_STOPPED)) { - + || rv == (LONG)SCARD_E_SERVICE_STOPPED) { for (i = 0; i < sc_ctx_get_reader_count(ctx); i++) { sc_reader_t *reader = sc_ctx_get_reader(ctx, i); @@ -1414,6 +1418,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) } reader->flags |= SC_READER_REMOVED; + gpriv->removed_reader = reader; } } @@ -1473,6 +1478,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) if (!strcmp(reader->name, reader_name)) { if (reader->flags & SC_READER_REMOVED) { reader->flags &= ~SC_READER_REMOVED; + gpriv->attached_reader = reader; refresh_attributes(reader); } break; @@ -1487,8 +1493,11 @@ static int pcsc_detect_readers(sc_context_t *ctx) (reader_buf + reader_buf_size) - next_reader_name); reader_buf_size -= (next_reader_name - reader_name); } else { - /* existing reader not found */ - reader->flags |= SC_READER_REMOVED; + if (!(reader->flags & SC_READER_REMOVED)) { + /* existing reader not found */ + reader->flags |= SC_READER_REMOVED; + gpriv->removed_reader = reader; + } } } @@ -1503,6 +1512,7 @@ static int pcsc_detect_readers(sc_context_t *ctx) _sc_delete_reader(ctx, reader); continue; } + gpriv->attached_reader = reader; /* check for pinpad support early, to allow opensc-tool -l display accurate information */ priv = reader->drv_data; @@ -1555,7 +1565,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re SCARD_READERSTATE *rgReaderStates; size_t i; unsigned int num_watch, count; - int r = SC_ERROR_INTERNAL; + int r = SC_ERROR_INTERNAL, detect_readers = 0, detected_hotplug = 0; DWORD dwtimeout; LOG_FUNC_CALLED(ctx); @@ -1579,8 +1589,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re sc_reader_t *reader = sc_ctx_get_reader(ctx, i); if (reader->flags & SC_READER_REMOVED) continue; + struct pcsc_private_data *priv = reader->drv_data; rgReaderStates[num_watch].szReader = reader->name; - rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; + if (priv->reader_state.szReader == NULL) { + rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; + } else { + rgReaderStates[num_watch].dwCurrentState = priv->reader_state.dwEventState; + } rgReaderStates[num_watch].dwEventState = SCARD_STATE_UNAWARE; num_watch++; } @@ -1589,6 +1604,12 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re #ifdef __APPLE__ /* OS X 10.6.2 - 10.12.6 do not support PnP notification */ sc_log(ctx, "PnP notification not supported"); + /* Always check on new readers as if a hotplug + * event was detected. This overwrites a + * SC_ERROR_EVENT_TIMEOUT if a new reader is + * detected with SC_SUCCESS. */ + detect_readers = 1; + detected_hotplug = 1; #else rgReaderStates[num_watch].szReader = "\\\\?PnP?\\Notification"; rgReaderStates[num_watch].dwCurrentState = SCARD_STATE_UNAWARE; @@ -1622,9 +1643,11 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re goto out; } + *event_reader = NULL; + *event = 0; + if (num_watch == 0) { sc_log(ctx, "No readers available to be watched"); - *event_reader = NULL; r = SC_ERROR_NO_READERS_FOUND; goto out; } @@ -1646,7 +1669,6 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re /* Scan the current state of all readers to see if they * match any of the events we're polling for */ - *event = 0; for (i = 0, rsp = rgReaderStates; i < num_watch; i++, rsp++) { DWORD state, prev_state; sc_log(ctx, "'%s' before=0x%08X now=0x%08X", @@ -1657,51 +1679,72 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re state = rsp->dwEventState; rsp->dwCurrentState = rsp->dwEventState; if (state & SCARD_STATE_CHANGED) { - /* check for hotplug events */ - if (!strcmp(rgReaderStates[i].szReader, "\\\\?PnP?\\Notification")) { + if (!strcmp(rsp->szReader, "\\\\?PnP?\\Notification")) { sc_log(ctx, "detected hotplug event"); - *event |= SC_EVENT_READER_ATTACHED; - *event_reader = NULL; - } + /* Windows sends hotplug event on both, attaching and + * detaching a reader. pcscd only sends it in case of + * attaching a reader. We'll detect later in which case we + * are. */ + detect_readers = 1; + detected_hotplug = 1; - if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) { - sc_log(ctx, "card inserted event"); - *event |= SC_EVENT_CARD_INSERTED; - } + /* Windows wants us to manually reset the changed state */ + rsp->dwEventState &= ~SCARD_STATE_CHANGED; - if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) { - sc_log(ctx, "card removed event"); - *event |= SC_EVENT_CARD_REMOVED; - } + /* By default, ignore a hotplug event as if a timout + * occurred, since it may be an unrequested removal or + * false alarm. Just continue to loop and check at the end + * of this function whether we need to return the attached + * reader or not. */ + r = SC_ERROR_EVENT_TIMEOUT; + } else { + sc_reader_t *reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader); + if (reader) { + /* copy the state so we know what to watch out for */ + struct pcsc_private_data *priv = reader->drv_data; + priv->reader_state.dwEventState = state; + priv->reader_state.dwCurrentState = prev_state; + } - if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) { - sc_log(ctx, "reader detached event"); - *event |= SC_EVENT_READER_DETACHED; - } + if ((state & SCARD_STATE_PRESENT) && !(prev_state & SCARD_STATE_PRESENT)) { + sc_log(ctx, "card inserted event"); + *event |= SC_EVENT_CARD_INSERTED; + } - if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) { - sc_log(ctx, "reader re-attached event"); - *event |= SC_EVENT_READER_ATTACHED; - } + if ((prev_state & SCARD_STATE_PRESENT) && !(state & SCARD_STATE_PRESENT)) { + sc_log(ctx, "card removed event"); + *event |= SC_EVENT_CARD_REMOVED; + } - if (*event & event_mask) { - sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader); - *event_reader = sc_ctx_get_reader_by_name(ctx, rsp->szReader); - r = SC_SUCCESS; - goto out; - } + if ((state & SCARD_STATE_UNKNOWN) && !(prev_state & SCARD_STATE_UNKNOWN)) { + sc_log(ctx, "reader detached event"); + *event |= SC_EVENT_READER_DETACHED; + detect_readers = 1; + } + if ((state & SCARD_STATE_IGNORE) && !(prev_state & SCARD_STATE_IGNORE)) { + sc_log(ctx, "reader detached event"); + *event |= SC_EVENT_READER_DETACHED; + detect_readers = 1; + } + + if ((prev_state & SCARD_STATE_UNKNOWN) && !(state & SCARD_STATE_UNKNOWN)) { + sc_log(ctx, "reader re-attached event"); + *event |= SC_EVENT_READER_ATTACHED; + detect_readers = 1; + } + + if (*event & event_mask) { + sc_log(ctx, "Matching event 0x%02X in reader %s", *event, rsp->szReader); + *event_reader = reader; + r = SC_SUCCESS; + goto out; + } else { + *event = 0; + } + } } - - /* No match - copy the state so pcscd knows - * what to watch out for */ - /* rsp->dwCurrentState = rsp->dwEventState; */ - } - - if (timeout == 0) { - r = SC_ERROR_EVENT_TIMEOUT; - goto out; } /* Set the timeout if caller wants to time out */ @@ -1713,13 +1756,13 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re rv = gpriv->SCardGetStatusChange(gpriv->pcsc_wait_ctx, dwtimeout, rgReaderStates, num_watch); - if (rv == (LONG) SCARD_E_CANCELLED) { + if (rv == (LONG)SCARD_E_CANCELLED) { /* C_Finalize was called, events don't matter */ r = SC_ERROR_EVENT_TIMEOUT; goto out; } - if (rv == (LONG) SCARD_E_TIMEOUT) { + if (rv == (LONG)SCARD_E_TIMEOUT) { r = SC_ERROR_EVENT_TIMEOUT; goto out; } @@ -1731,12 +1774,54 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re } } out: - if (!reader_states) { - free(rgReaderStates); + /* in case of an error re-detect all readers */ + if (r < 0 && r != SC_ERROR_EVENT_TIMEOUT) + detect_readers = 1; + + if (detect_readers) { + pcsc_detect_readers(ctx); } - else if (*reader_states == NULL) { - sc_log(ctx, "return allocated 'reader states'"); - *reader_states = rgReaderStates; + + if (detected_hotplug) { + if (gpriv->attached_reader) { + if (event_reader && event && !*event) { + /* no other event has been detected, yet */ + *event_reader = gpriv->attached_reader; + *event = SC_EVENT_READER_ATTACHED; + r = SC_SUCCESS; + } + gpriv->attached_reader = NULL; + } else if (gpriv->removed_reader) { + /* Normally, we only check the hotplug event for attached readers. + * However, Windows also notifies on removal. Check, if the latter + * was requested by the caller. */ + if (event_mask & SC_EVENT_READER_DETACHED + && event_reader && event && !*event) { + /* no other event has been detected, yet */ + *event_reader = gpriv->removed_reader; + *event = SC_EVENT_READER_DETACHED; + r = SC_SUCCESS; + } + gpriv->removed_reader = NULL; + } else { + /* false alarm, there was no reader attached or removed, + * avoid re-initialize the reader states by resetting detect_readers */ + detect_readers = 0; + } + } + + if (detect_readers) { + free(rgReaderStates); + if (reader_states && *reader_states) + *reader_states = NULL; + } else { + if (!reader_states) { + free(rgReaderStates); + } + else if (*reader_states == NULL) { + sc_log(ctx, "return allocated reader states"); + *reader_states = rgReaderStates; + } } LOG_FUNC_RETURN(ctx, r); @@ -2449,6 +2534,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c } sc_log(ctx, "Probing PC/SC reader"); + gpriv->attached_reader = NULL; gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle; card_handle = *(SCARDHANDLE *)pcsc_card_handle; @@ -2467,6 +2553,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c } else { _sc_delete_reader(ctx, reader); } + gpriv->attached_reader = reader; } out: diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c index afc24353..87d66c67 100644 --- a/src/tools/opensc-notify.c +++ b/src/tools/opensc-notify.c @@ -49,26 +49,21 @@ void Sleep(unsigned int Milliseconds) } #endif -void stop_daemon() -{ -#ifdef PCSCLITE_GOOD - sc_cancel(ctx); -#endif - run_daemon = 0; -} - void notify_daemon() { int r; - const unsigned int event_mask = SC_EVENT_CARD_EVENTS; + const unsigned int event_mask = SC_EVENT_CARD_EVENTS|SC_EVENT_READER_EVENTS; unsigned int event; struct sc_reader *event_reader = NULL; - size_t error_count = 0; + void *reader_states = NULL; +#ifndef __APPLE__ /* timeout adjusted to the maximum response time for WM_CLOSE in case * canceling doesn't work */ const int timeout = 20000; - struct sc_atr old_atr; - void *reader_states = NULL; +#else + /* lower timeout, because Apple doesn't support hotplug events */ + const int timeout = 2000; +#endif r = sc_establish_context(&ctx, "opensc-notify"); if (r < 0 || !ctx) { @@ -76,50 +71,51 @@ void notify_daemon() return; } - while (run_daemon && error_count < 1000) { + while (run_daemon) { + r = sc_wait_for_event(ctx, event_mask, &event_reader, &event, timeout, &reader_states); if (r < 0) { if (r == SC_ERROR_NO_READERS_FOUND) { - /* No readers available, PnP notification not supported */ - Sleep(200); - } else { - error_count++; + Sleep(timeout); + continue; } - continue; } - error_count = 0; - - if (event & SC_EVENT_CARD_REMOVED) { - sc_notify_id(ctx, &old_atr, NULL, NOTIFY_CARD_REMOVED); - } - if (event & SC_EVENT_CARD_INSERTED) { - if (event_reader) { - /* FIXME `pcsc_wait_for_event` has all the information that's - * requested again with `pcsc_detect_card_presence`, but it - * doesn't use the ATR, for example, to refresh the reader's - * attributes. To get the ATR we need to call - * sc_detect_card_presence. Eventually this should be fixed. */ - sc_detect_card_presence(event_reader); - memcpy(old_atr.value, event_reader->atr.value, - event_reader->atr.len); - old_atr.len = event_reader->atr.len; - } else { - old_atr.len = 0; + if (event_reader) { + if (event & SC_EVENT_CARD_REMOVED + || (event & SC_EVENT_READER_DETACHED + && event_reader->flags & SC_READER_CARD_PRESENT)) { + /* sc_notify_id uses only the reader's name for displaying on + * removal, so use a dummy card here to get that information + * into the notification */ + struct sc_pkcs15_card p15card; + sc_card_t card; + memset(&card, 0, sizeof card); + card.reader = event_reader; + memset(&p15card, 0, sizeof p15card); + p15card.card = &card; + sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_REMOVED); + } else if (event & SC_EVENT_CARD_INSERTED + || (event & SC_EVENT_READER_ATTACHED + && event_reader->flags & SC_READER_CARD_PRESENT)) { + /* sc_notify_id prevers the reader's name for displaying on + * insertion, so use a dummy card here to get that information + * into the notification */ + struct sc_pkcs15_card p15card; + sc_card_t card; + memset(&card, 0, sizeof card); + card.reader = event_reader; + memset(&p15card, 0, sizeof p15card); + p15card.card = &card; + sc_notify_id(ctx, &event_reader->atr, &p15card, NOTIFY_CARD_INSERTED); } - sc_notify_id(ctx, old_atr.len ? &old_atr : NULL, NULL, - NOTIFY_CARD_INSERTED); } } if (ctx) { - if (error_count >= 1000) { - sc_log(ctx, "Too many errors; aborting."); - } /* free `reader_states` */ sc_wait_for_event(ctx, 0, NULL, NULL, 0, &reader_states); - reader_states = NULL; sc_release_context(ctx); ctx = NULL; } @@ -132,7 +128,8 @@ void notify_daemon() LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_CLOSE || message == WM_QUIT) { - stop_daemon(); + run_daemon = 0; + sc_cancel(ctx); return TRUE; } @@ -182,32 +179,54 @@ WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowC #else -#ifdef HAVE_SIGACTION +#if defined(HAVE_SIGACTION) && defined(HAVE_PTHREAD) +#include +#include #include +#include + +static int cancellation_fd[] = {-1, -1}; void sig_handler(int sig) { - stop_daemon(); + run_daemon = 0; + write(cancellation_fd[1], &sig, sizeof sig); } -void set_sa_handler(void) +static void *cancellation_proc(void *arg) { - struct sigaction new_sig, old_sig; + (void)arg; + while (run_daemon) { + int sig; + if (sizeof sig == read(cancellation_fd[0], &sig, sizeof sig)) { + break; + } + } + sc_cancel(ctx); + return NULL; +} - /* Register signal handlers */ +void setup_cancellation(void) +{ + pthread_t cancellation_thread; + struct sigaction new_sig, old_sig; new_sig.sa_handler = sig_handler; sigemptyset(&new_sig.sa_mask); new_sig.sa_flags = SA_RESTART; - if ((sigaction(SIGINT, &new_sig, &old_sig) < 0) - || (sigaction(SIGTERM, &new_sig, &old_sig) < 0)) { - fprintf(stderr, "Failed to create signal handler: %s", strerror(errno)); + + if (pipe(cancellation_fd) != 0 + || (errno = pthread_create(&cancellation_thread, NULL, cancellation_proc, NULL)) != 0 + || sigaction(SIGINT, &new_sig, &old_sig) != 0 + || sigaction(SIGTERM, &new_sig, &old_sig) != 0) { + fprintf(stderr, "Failed to setup cancellation: %s", strerror(errno)); } } #else -void set_sa_handler(void) +void setup_cancellation(void) { } + #endif #include "opensc-notify-cmdline.h" @@ -244,8 +263,8 @@ main (int argc, char **argv) if ((!cmdline.customized_mode_counter && !cmdline.standard_mode_counter) || cmdline.daemon_mode_counter) { - set_sa_handler(); run_daemon = 1; + setup_cancellation(); notify_daemon(); } else { /* give the notification process some time to spawn */ diff --git a/src/ui/strings.c b/src/ui/strings.c index ea1d3ba6..90dbc0f9 100644 --- a/src/ui/strings.c +++ b/src/ui/strings.c @@ -34,8 +34,12 @@ static const char *get_inserted_text(struct sc_pkcs15_card *p15card, struct sc_a static char text[3*SC_MAX_ATR_SIZE] = {0}; const char prefix[] = "ATR: "; - if (p15card && p15card->card && p15card->card->name) { + if (p15card && p15card->card + && p15card->card->name) { return p15card->card->name; + } else if (p15card && p15card->card + && p15card->card->reader && p15card->card->reader->name) { + return p15card->card->reader->name; } if (!atr) @@ -192,7 +196,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr, str = "Dieses Fenster wird automatisch geschlossen, wenn die PIN am PIN-Pad eingegeben wurde (Timeout typischerweise nach 30 Sekunden)."; break; case NOTIFY_CARD_INSERTED: - if (p15card) { + if (p15card && p15card->card && p15card->card->name) { str = "Smartcard kann jetzt verwendet werden"; } else { str = "Smartcard erkannt"; @@ -260,7 +264,7 @@ const char *ui_get_str(struct sc_context *ctx, struct sc_atr *atr, str = "This window will be closed automatically after the PIN has been submitted on the PIN pad (timeout typically after 30 seconds)."; break; case NOTIFY_CARD_INSERTED: - if (p15card) { + if (p15card && p15card->card && p15card->card->name) { str = "Smart card is ready to use"; } else { str = "Smart card detected"; From f9b31e50dd427d4974f7928d4f4c0900435d27a8 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 8 Apr 2020 02:13:24 +0200 Subject: [PATCH 146/189] iso-sm: fixed too short response APDU data length one byte off error in calculation of ASN.1 length --- src/sm/sm-iso.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/sm/sm-iso.c b/src/sm/sm-iso.c index 9dbda86e..5baded77 100644 --- a/src/sm/sm-iso.c +++ b/src/sm/sm-iso.c @@ -469,16 +469,17 @@ static int sm_encrypt(const struct iso_sm_ctx *ctx, sc_card_t *card, sm_apdu->datalen = sm_data_len; sm_apdu->lc = sm_data_len; sm_apdu->le = 0; + /* for encrypted APDUs we usually get authenticated status bytes (4B), a + * MAC (2B without data) and a cryptogram with padding indicator (2B tag + * and indicator, max. 2B/3B ASN.1 length, without data). The cryptogram is + * always padded to the block size. */ if (apdu->cse & SC_APDU_EXT) { sm_apdu->cse = SC_APDU_CASE_4_EXT; + sm_apdu->resplen = 4 + 2 + mac_len + 2 + 3 + ((apdu->resplen+1)/ctx->block_length+1)*ctx->block_length; } else { sm_apdu->cse = SC_APDU_CASE_4_SHORT; + sm_apdu->resplen = 4 + 2 + mac_len + 2 + 2 + ((apdu->resplen+1)/ctx->block_length+1)*ctx->block_length; } - /* for encrypted APDUs we usually get authenticated status bytes - * (4B), a MAC (2B without data) and a cryptogram with padding - * indicator (3B without data). The cryptogram is always padded to - * the block size. */ - sm_apdu->resplen = 4 + 2 + mac_len + 3 + ((apdu->resplen+1)/ctx->block_length+1)*ctx->block_length; resp_data = calloc(sm_apdu->resplen, 1); if (!resp_data) { r = SC_ERROR_OUT_OF_MEMORY; From a771450ab20318d7d85801b42852b709e2d459c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Silv=C3=A9n?= Date: Fri, 27 Mar 2020 17:11:32 +0100 Subject: [PATCH 147/189] From the PKCS#11 specification chapter C_SetPIN: C_SetPIN modifies the PIN of the user that is currently logged in, or the CKU_USER PIN if the session is not logged in. .... This was not true for "if the session is not logged in" before this fix. --- src/pkcs11/framework-pkcs15.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index a1951c2e..924bc32f 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1858,11 +1858,7 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot, return CKR_PIN_LEN_RANGE; } - if (login_user < 0) { - if (sc_pkcs11_conf.pin_unblock_style != SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN) { - sc_log(context, "PIN unlock is not allowed in unlogged session"); - return CKR_FUNCTION_NOT_SUPPORTED; - } + if (login_user < 0 && sc_pkcs11_conf.pin_unblock_style == SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN) { rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen); } else if (login_user == CKU_CONTEXT_SPECIFIC) { @@ -1872,7 +1868,7 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot, } rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen); } - else if ((login_user == CKU_USER) || (login_user == CKU_SO)) { + else if (login_user < 0 || login_user == CKU_USER || login_user == CKU_SO) { rc = sc_pkcs15_change_pin(fw_data->p15_card, pin_obj, pOldPin, ulOldLen, pNewPin, ulNewLen); } else { From 8257e0186dfa3a501f680d33015c6f26f52533d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Silv=C3=A9n?= Date: Mon, 30 Mar 2020 14:38:25 +0200 Subject: [PATCH 148/189] The PKCS#11 specifies that the PIN parameter(s) in C_Login and C_SetPIN always should be used, even if a PIN pad reader is used. PIN must only be fetched from the PIN pad reader if the corresponding parameter is null. Before this commit PIN was always fetch from the reader if the PIN could be fetched from the reader. The 'pkcs11-tool has also been updated. Before parameters was never taken from the command line if a PID pad reader was used. Now PINs from the command line is always used but if not existing the PIN is fetched from the reader if a reader with a PIN pad is used, otherwise the user is prompted for PIN(s) from the CLI. --- src/pkcs11/framework-pkcs15.c | 29 +-------------- src/tools/pkcs11-tool.c | 67 +++++++++++++++-------------------- 2 files changed, 29 insertions(+), 67 deletions(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 924bc32f..dae65c55 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1668,22 +1668,6 @@ pkcs15_login(struct sc_pkcs11_slot *slot, CK_USER_TYPE userType, if (!p11card) return CKR_TOKEN_NOT_RECOGNIZED; - if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD - || (p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { - /* pPin should be NULL in case of a pin pad reader, but - * some apps (e.g. older Netscapes) don't know about it. - * So we don't require that pPin == NULL, but set it to - * NULL ourselves. This way, you can supply an empty (if - * possible) or fake PIN if an application asks a PIN). - */ - /* But we want to be able to specify a PIN on the command - * line (e.g. for the test scripts). So we don't do anything - * here - this gives the user the choice of entering - * an empty pin (which makes us use the pin pad) or - * a valid pin (which is processed normally). --okir */ - if (ulPinLen == 0) - pPin = NULL; - } /* By default, we make the reader resource manager keep other * processes from accessing the card while we're logged in. @@ -1843,18 +1827,7 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot, return CKR_USER_PIN_NOT_INITIALIZED; sc_log(context, "Change '%.*s' (ref:%i,type:%i)", (int) sizeof pin_obj->label, pin_obj->label, auth_info->attrs.pin.reference, login_user); - if ((p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) - || (p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { - /* pPin should be NULL in case of a pin pad reader, but - * some apps (e.g. older Netscapes) don't know about it. - * So we don't require that pPin == NULL, but set it to - * NULL ourselves. This way, you can supply an empty (if - * possible) or fake PIN if an application asks a PIN). - */ - pOldPin = pNewPin = NULL; - ulOldLen = ulNewLen = 0; - } - else if (ulNewLen < auth_info->attrs.pin.min_length || ulNewLen > auth_info->attrs.pin.max_length) { + if (pNewPin && (ulNewLen < auth_info->attrs.pin.min_length || ulNewLen > auth_info->attrs.pin.max_length)) { return CKR_PIN_LEN_RANGE; } diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index b8e02cac..b33e78ff 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -1597,53 +1597,42 @@ static void init_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess) static int change_pin(CK_SLOT_ID slot, CK_SESSION_HANDLE sess) { - char old_buf[21], *old_pin = NULL; - char new_buf[21], *new_pin = NULL; + char old_buf[21], *old_pin = opt_so_pin ? (char*)opt_so_pin : (char*)opt_pin; + char new_buf[21], *new_pin = (char *)opt_new_pin; CK_TOKEN_INFO info; CK_RV rv; int r; size_t len = 0; get_token_info(slot, &info); + const CK_FLAGS hasReaderPinPad = info.flags & CKF_PROTECTED_AUTHENTICATION_PATH; - if (!(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) { - if (!opt_pin && !opt_so_pin) { - printf("Please enter the current PIN: "); - r = util_getpass(&old_pin, &len, stdin); - if (r < 0) - return 1; - if (!old_pin || !*old_pin || strlen(old_pin) > 20) - return 1; - strcpy(old_buf, old_pin); - old_pin = old_buf; - } - else { - if (opt_so_pin) - old_pin = (char *) opt_so_pin; - else - old_pin = (char *) opt_pin; - } + if (!hasReaderPinPad && !old_pin) { + printf("Please enter the current PIN: "); + r = util_getpass(&old_pin, &len, stdin); + if (r < 0) + return 1; + if (!old_pin || !*old_pin || strlen(old_pin) > 20) + return 1; + strcpy(old_buf, old_pin); + old_pin = old_buf; + } + if (!hasReaderPinPad && !new_pin) { + printf("Please enter the new PIN: "); + r = util_getpass(&new_pin, &len, stdin); + if (r < 0) + return 1; + if (!new_pin || !*new_pin || strlen(new_pin) > 20) + return 1; + strcpy(new_buf, new_pin); - if (!opt_new_pin) { - printf("Please enter the new PIN: "); - r = util_getpass(&new_pin, &len, stdin); - if (r < 0) - return 1; - if (!new_pin || !*new_pin || strlen(new_pin) > 20) - return 1; - strcpy(new_buf, new_pin); - - printf("Please enter the new PIN again: "); - r = util_getpass(&new_pin, &len, stdin); - if (r < 0) - return 1; - if (!new_pin || !*new_pin || strcmp(new_buf, new_pin) != 0) { - free(new_pin); - return 1; - } - } - else { - new_pin = (char *) opt_new_pin; + printf("Please enter the new PIN again: "); + r = util_getpass(&new_pin, &len, stdin); + if (r < 0) + return 1; + if (!new_pin || !*new_pin || strcmp(new_buf, new_pin) != 0) { + free(new_pin); + return 1; } } From 78a7c11d0ddfe88bc582dd481de43868f8454a06 Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Wed, 8 Apr 2020 10:29:02 +0300 Subject: [PATCH 149/189] Simplify build matrix Signed-off-by: Raul Metsma --- appveyor.yml | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8a53d03a..08f22abe 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,13 +1,5 @@ version: 0.20.0.{build} -image: - # not compatible with OpenSSL 1.1.1: - # - Visual Studio 2013 - # not compatible with WiX 3.11.2: - # - Visual Studio 2019 - - Visual Studio 2015 - - Visual Studio 2017 - platform: - x86 - x64 @@ -22,6 +14,18 @@ environment: PATH: C:\cygwin\bin;%PATH% OPENPACE_VER: 1.1.0 ZLIB_VER_DOT: 1.2.11 + matrix: + # not compatible with OpenSSL 1.1.1: + # - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + # VCVARSALL: "%VS120COMNTOOLS%/../../VC/vcvarsall.bat" + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + VCVARSALL: "%VS140COMNTOOLS%/../../VC/vcvarsall.bat" + DO_PUSH_ARTIFACT: yes + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + VCVARSALL: "%ProgramFiles(x86)%/Microsoft Visual Studio/2017/Community/VC/Auxiliary/Build/vcvarsall.bat" + # not compatible with WiX 3.11.2: + # - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + # VCVARSALL: "%ProgramFiles(x86)%/Microsoft Visual Studio/2019/Community/VC/Auxiliary/Build/vcvarsall.bat" install: - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` @@ -32,11 +36,9 @@ install: - ps: $env:PACKAGE_NAME=(git describe --tags --abbrev=0) - ps: >- If ($env:Platform -Match "x86") { - $env:VCVARS_PLATFORM="x86" $env:OPENSSL_PF="Win32" $env:ARTIFACT="OpenSC-${env:PACKAGE_NAME}_win32" } Else { - $env:VCVARS_PLATFORM="amd64" $env:OPENSSL_PF="Win64" $env:ARTIFACT="OpenSC-${env:PACKAGE_NAME}_win64" } @@ -60,19 +62,8 @@ install: If (!(Test-Path cngsdk.msi )) { appveyor DownloadFile "http://download.microsoft.com/download/2/C/9/2C93059C-0532-42DF-8C24-9AEAFF00768E/cngsdk.msi" } - - ps: >- - If ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2019") { - $env:VCVARSALL="${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" - } ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2017") { - $env:VCVARSALL="${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" - } ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2015") { - $env:VCVARSALL="${env:VS140COMNTOOLS}\..\..\VC\vcvarsall.bat" - $env:DO_PUSH_ARTIFACT="yes" - } ElseIf ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq "Visual Studio 2013") { - $env:VCVARSALL="${env:VS120COMNTOOLS}\..\..\VC\vcvarsall.bat" - } - echo "Using %APPVEYOR_BUILD_WORKER_IMAGE% with %VCVARSALL%" - - call "%VCVARSALL%" %VCVARS_PLATFORM% + - call "%VCVARSALL%" %Platform% - cngsdk.msi /quiet - uname -a - set From 5e79a2a4abdd523cfff19824718bbb0d8ced7320 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 9 Apr 2020 16:29:44 +0200 Subject: [PATCH 150/189] fixed compiler warning --- src/tools/opensc-notify.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c index 87d66c67..b1afc62d 100644 --- a/src/tools/opensc-notify.c +++ b/src/tools/opensc-notify.c @@ -189,7 +189,9 @@ static int cancellation_fd[] = {-1, -1}; void sig_handler(int sig) { run_daemon = 0; - write(cancellation_fd[1], &sig, sizeof sig); + if (-1 == write(cancellation_fd[1], &sig, sizeof sig)) { + fprintf(stderr, "Failed immediate cancellation: %s", strerror(errno)); + } } static void *cancellation_proc(void *arg) From 843779fe6e0f345f483f9ce9c9739913502391eb Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 23 Apr 2020 08:45:24 +0200 Subject: [PATCH 151/189] opensc-notify: respect signal safety Thanks, Marcin. https://github.com/OpenSC/OpenSC/commit/5e79a2a4abdd523cfff19824718bbb0d8ced7320#r38486829 --- src/tools/opensc-notify.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c index b1afc62d..75767aba 100644 --- a/src/tools/opensc-notify.c +++ b/src/tools/opensc-notify.c @@ -189,9 +189,7 @@ static int cancellation_fd[] = {-1, -1}; void sig_handler(int sig) { run_daemon = 0; - if (-1 == write(cancellation_fd[1], &sig, sizeof sig)) { - fprintf(stderr, "Failed immediate cancellation: %s", strerror(errno)); - } + (void)write(cancellation_fd[1], &sig, sizeof sig); } static void *cancellation_proc(void *arg) From 0234e1bc1499514518d1c8e8589232514769b47b Mon Sep 17 00:00:00 2001 From: James Bromwell <943160+thw0rted@users.noreply.github.com> Date: Tue, 21 Apr 2020 11:23:19 +0200 Subject: [PATCH 152/189] Update ISSUE_TEMPLATE.md Note that I took out the Markdown formatting for links, because Markdown inside of HTML comments never renders. --- .github/ISSUE_TEMPLATE.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 49ba8602..183fb662 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,7 +1,9 @@ ### Problem Description ### Proposed Resolution @@ -21,7 +23,7 @@ Debug output is essential to identify the problem. You can enable debugging by e #debug_file = opensc-debug.log ``` -Please use [Gist](https://gist.github.com/) or a similar code paster for longer logs. Before pasting here, remove your sensitive data from your log (e.g. PIN code or certificates). +Please use a Gist (https://gist.github.com/) or a similar code paster for longer logs. Before pasting here, remove your sensitive data from your log (e.g. PIN code or certificates). ``` Paste Log output with less than 10 lines here (between the backticks) From bb47c1a5d08c241b98ffaf92ead43ce421c63507 Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Tue, 21 Apr 2020 10:26:56 +0000 Subject: [PATCH 153/189] pkcs11-tool: Fix mismatched --help text The addition of --usage-wrap did not add a corresponding help string, which caused all help text for the options below it to be shifted by one. --- src/tools/pkcs11-tool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index b33e78ff..3ad92890 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -274,6 +274,7 @@ static const char *option_help[] = { "Specify 'sign' key usage flag (sets SIGN in privkey, sets VERIFY in pubkey)", "Specify 'decrypt' key usage flag (RSA only, set DECRYPT privkey, ENCRYPT in pubkey)", "Specify 'derive' key usage flag (EC only)", + "Specify 'wrap' key usage flag", "Write an object (key, cert, data) to the card", "Get object's CKA_VALUE attribute (use with --type)", "Delete an object (use with --type cert/data/privkey/pubkey/secrkey)", From 7936bdef15c71139a6a6159cabaf9e6101565add Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2020 01:25:33 +0200 Subject: [PATCH 154/189] resolve unused variable warning on newer gcc --- src/tools/opensc-notify.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c index 75767aba..3b61c498 100644 --- a/src/tools/opensc-notify.c +++ b/src/tools/opensc-notify.c @@ -189,7 +189,10 @@ static int cancellation_fd[] = {-1, -1}; void sig_handler(int sig) { run_daemon = 0; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" (void)write(cancellation_fd[1], &sig, sizeof sig); +#pragma GCC diagnostic pop } static void *cancellation_proc(void *arg) From 1202eceeefd5ffab45648d41ed0a3076cac10920 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Wed, 29 Apr 2020 15:16:31 +0200 Subject: [PATCH 155/189] fixed wrong error --- src/tools/opensc-notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/opensc-notify.c b/src/tools/opensc-notify.c index 3b61c498..c67212b3 100644 --- a/src/tools/opensc-notify.c +++ b/src/tools/opensc-notify.c @@ -190,7 +190,7 @@ static int cancellation_fd[] = {-1, -1}; void sig_handler(int sig) { run_daemon = 0; #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-result" (void)write(cancellation_fd[1], &sig, sizeof sig); #pragma GCC diagnostic pop } From be57a4bf0f40c488c6a60ccd87cbb1767221048d Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 20 Apr 2020 21:04:09 +0200 Subject: [PATCH 156/189] configure: Do not overwrite passed CFLAGS --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6219f36b..705bc027 100644 --- a/configure.ac +++ b/configure.ac @@ -79,7 +79,7 @@ AC_ARG_WITH( ) if test "${enable_optimization}" = "no"; then - CFLAGS="-O0 -g" + CFLAGS="${CFLAGS} -O0 -g" fi dnl Check for some target-specific stuff From ed06787b5e155fc683ee816b6a67a406a6bb1970 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 21 Apr 2020 14:45:21 +0200 Subject: [PATCH 157/189] oberthur: Avoid memory leak when the auth_init is called multiple times Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21678 --- src/libopensc/card-oberthur.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libopensc/card-oberthur.c b/src/libopensc/card-oberthur.c index 0d4103de..b692e724 100644 --- a/src/libopensc/card-oberthur.c +++ b/src/libopensc/card-oberthur.c @@ -182,10 +182,12 @@ auth_select_aid(struct sc_card *card) LOG_TEST_RET(card->ctx, rv, "select parent failed"); sc_format_path("3F00", &tmp_path); + sc_file_free(auth_current_df); rv = iso_ops->select_file(card, &tmp_path, &auth_current_df); LOG_TEST_RET(card->ctx, rv, "select parent failed"); sc_format_path("3F00", &card->cache.current_path); + sc_file_free(auth_current_ef); sc_file_dup(&auth_current_ef, auth_current_df); memcpy(data->aid, aidAuthentIC_V5, lenAidAuthentIC_V5); From b76e08504afed39b6a4b963ca76f332c9a98fd44 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 21 Apr 2020 14:46:34 +0200 Subject: [PATCH 158/189] piv: Fix indentation --- src/libopensc/pkcs15-piv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/pkcs15-piv.c b/src/libopensc/pkcs15-piv.c index 5a031f12..c0b873c7 100644 --- a/src/libopensc/pkcs15-piv.c +++ b/src/libopensc/pkcs15-piv.c @@ -1104,7 +1104,7 @@ sc_log(card->ctx, "DEE Adding pin %d label=%s",i, label); if (ckis[i].cert_keyUsage_present) { pubkey_info.usage = ckis[i].pub_usage; } else { - pubkey_info.usage = pubkeys[i].usage_ec; + pubkey_info.usage = pubkeys[i].usage_ec; } pubkey_info.field_length = ckis[i].pubkey_len; From 127c8d911f860430171436931fa9349d547af009 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 21 Apr 2020 14:47:20 +0200 Subject: [PATCH 159/189] pkcs15-pubkey: Avoid memory leaks when ec_params are already initialized from pkcs15-algo --- src/libopensc/pkcs15-pubkey.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index 01efb02b..f3f01692 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -851,6 +851,8 @@ sc_pkcs15_encode_pubkey_as_spki(sc_context_t *ctx, struct sc_pkcs15_pubkey *pubk } memcpy(ec_params->der.value, pubkey->u.ec.params.der.value, pubkey->u.ec.params.der.len); ec_params->der.len = pubkey->u.ec.params.der.len; + /* This could have been already allocated: avoid memory leak */ + sc_asn1_clear_algorithm_id(pubkey->alg_id); pubkey->alg_id->params = ec_params; } break; From 75be610ea006f63f8190b1fb62c6ce8f7ea87bba Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 21 Apr 2020 14:48:41 +0200 Subject: [PATCH 160/189] pkcs15: Clean memory if it was not transfered to framework-pkcs15 --- src/libopensc/pkcs15.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index e474803d..ba04f531 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -1895,6 +1895,11 @@ sc_pkcs15_free_object(struct sc_pkcs15_object *obj) sc_pkcs15_free_prkey_info((sc_pkcs15_prkey_info_t *)obj->data); break; case SC_PKCS15_TYPE_PUBKEY: + /* This is normally passed to framework-pkcs15, + * but if something fails on the way, it would not get freed */ + if (obj->emulated) { + sc_pkcs15_free_pubkey(obj->emulated); + } sc_pkcs15_free_pubkey_info((sc_pkcs15_pubkey_info_t *)obj->data); break; case SC_PKCS15_TYPE_CERT: From 84ee2be122e0ff746b2500890f4f1211419e740f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 09:28:31 +0200 Subject: [PATCH 161/189] framework-pkcs15: Copy pubkey to avoid double free --- src/pkcs11/framework-pkcs15.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index dae65c55..b9ee80d8 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -732,7 +732,7 @@ __pkcs15_create_pubkey_object(struct pkcs15_fw_data *fw_data, /* if emulation already created pubkey use it */ if (pubkey->emulated && (fw_data->p15_card->flags & SC_PKCS15_CARD_FLAG_EMULATED)) { sc_log(context, "Use emulated pubkey"); - p15_key = (struct sc_pkcs15_pubkey *) pubkey->emulated; + sc_pkcs15_dup_pubkey(context, (struct sc_pkcs15_pubkey *) pubkey->emulated, &p15_key); } else { sc_log(context, "Get pubkey from PKCS#15 object"); From 508f8a9fced369f60e6f0c0f62176ea9427fbf42 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 10:03:32 +0200 Subject: [PATCH 162/189] iso7816: Do not recurse if no data was returned Thanks oss-fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20399 --- src/libopensc/iso7816.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index a8aad766..10311250 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -161,7 +161,7 @@ iso7816_read_binary(struct sc_card *card, unsigned int idx, u8 *buf, size_t coun LOG_FUNC_RETURN(ctx, apdu.resplen); LOG_TEST_RET(ctx, r, "Check SW error"); - if (apdu.resplen < count) { + if (apdu.resplen > 0 && apdu.resplen < count) { r = iso7816_read_binary(card, idx + apdu.resplen, buf + apdu.resplen, count - apdu.resplen, flags); /* Ignore all but 'corrupted data' errors */ if (r == SC_ERROR_CORRUPTED_DATA) From 4c4237f8a33de61627ee27a7fa445e145e595f84 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 12:59:34 +0200 Subject: [PATCH 163/189] tests: Cover asn1_put_tag() --- src/libopensc/asn1.c | 3 + src/tests/unittests/asn1.c | 123 +++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index bf951782..75bc1c9e 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -961,6 +961,9 @@ static int sc_asn1_decode_utf8string(const u8 *inbuf, size_t inlen, return 0; } +/* + * This assumes the tag is already encoded + */ int sc_asn1_put_tag(unsigned int tag, const u8 * data, size_t datalen, u8 * out, size_t outlen, u8 **ptr) { size_t c = 0; diff --git a/src/tests/unittests/asn1.c b/src/tests/unittests/asn1.c index cef1128c..c5fad085 100644 --- a/src/tests/unittests/asn1.c +++ b/src/tests/unittests/asn1.c @@ -439,6 +439,124 @@ static void torture_asn1_decode_entry_bit_string_ni(void **state) assert_memory_equal(bit_string + 1, result, resultlen/8); } +static void torture_asn1_put_tag_short(void **state) +{ + unsigned int tag = 0xAC; + const u8 expected[] = {0xAC, 0x01, 0x02}; + const u8 data[] = {0x02}; + size_t data_len = 1; + u8 out[10]; + size_t out_len = sizeof(out); + u8 *p = out; + int rv; + + /* Without the out and out_len we are getting expected length */ + rv = sc_asn1_put_tag(tag, data, data_len, NULL, 0, &p); + assert_int_equal(rv, sizeof(expected)); + assert_ptr_equal(p, out); + + /* Now we do the actual encoding */ + rv = sc_asn1_put_tag(tag, data, data_len, out, out_len, &p); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, expected, sizeof(expected)); + assert_ptr_equal(p, out + sizeof(expected)); + + /* Short buffer */ + rv = sc_asn1_put_tag(tag, data, data_len, out, 2, &p); + assert_int_equal(rv, SC_ERROR_BUFFER_TOO_SMALL); +} + +static void torture_asn1_put_tag_long_tag(void **state) +{ + /* Max supported value already encoded as ASN1 tag */ + unsigned int tag = 0xFFFFFF7F; + const u8 expected[] = {0xFF, 0xFF, 0xFF, 0x7F, 0x01, 0x02}; + const u8 data[] = {0x02}; + size_t data_len = 1; + u8 out[10]; + size_t out_len = sizeof(out); + u8 *p = out; + int rv; + + /* Without the out and out_len we are getting expected length */ + rv = sc_asn1_put_tag(tag, data, data_len, NULL, 0, &p); + assert_int_equal(rv, sizeof(expected)); + assert_ptr_equal(p, out); + + /* Now we do the actual encoding */ + rv = sc_asn1_put_tag(tag, data, data_len, out, out_len, &p); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, expected, sizeof(expected)); + assert_ptr_equal(p, out + sizeof(expected)); + + /* The buffer is too small */ + rv = sc_asn1_put_tag(tag, data, data_len, out, 5, &p); + assert_int_equal(rv, SC_ERROR_BUFFER_TOO_SMALL); + + /* the MSB of last byte needs to be 0 */ + tag = 0xFFFFFF8F; + rv = sc_asn1_put_tag(tag, data, data_len, NULL, 0, NULL); + assert_int_equal(rv, SC_ERROR_INVALID_DATA); + + /* the MSB of all byts needs to be 1 */ + tag = 0xFFFF7F7F; + rv = sc_asn1_put_tag(tag, data, data_len, NULL, 0, NULL); + assert_int_equal(rv, SC_ERROR_INVALID_DATA); + + /* Fisrt byte has bits 5-1 set to 1 */ + tag = 0xE0FFFF7F; + rv = sc_asn1_put_tag(tag, data, data_len, NULL, 0, NULL); + assert_int_equal(rv, SC_ERROR_INVALID_DATA); +} + +static void torture_asn1_put_tag_long_data(void **state) +{ + unsigned int tag = 0xAC; + const u8 expected[131] = {0xAC, 0x81, 0x80, 0x00, /* the rest is zero */}; + const u8 data[128] = {0}; + size_t data_len = sizeof(data); + u8 out[200]; + size_t out_len = sizeof(out); + u8 *p = out; + int rv; + + /* Without the out and out_len we are getting expected length */ + rv = sc_asn1_put_tag(tag, data, data_len, NULL, 0, &p); + assert_int_equal(rv, sizeof(expected)); + assert_ptr_equal(p, out); + + /* Now we do the actual encoding */ + rv = sc_asn1_put_tag(tag, data, data_len, out, out_len, &p); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, expected, sizeof(expected)); + assert_ptr_equal(p, out + sizeof(expected)); + + /* The buffer is too small */ + rv = sc_asn1_put_tag(tag, data, data_len, out, 130, &p); + assert_int_equal(rv, SC_ERROR_BUFFER_TOO_SMALL); +} + +static void torture_asn1_put_tag_without_data(void **state) +{ + unsigned int tag = 0xAC; + const u8 expected[] = {0xAC, 0x01}; + size_t data_len = 1; + u8 out[10]; + size_t out_len = sizeof(out); + u8 *p = out; + int rv; + + /* Without the out and out_len we are getting expected length */ + rv = sc_asn1_put_tag(tag, NULL, data_len, NULL, 0, &p); + assert_int_equal(rv, sizeof(expected) + data_len); + assert_ptr_equal(p, out); + + /* Now we do the actual encoding, but data field is not filled */ + rv = sc_asn1_put_tag(tag, NULL, data_len, out, out_len, &p); + assert_int_equal(rv, SC_SUCCESS); + assert_memory_equal(out, expected, sizeof(expected)); + assert_ptr_equal(p, out + sizeof(expected)); +} int main(void) { @@ -502,6 +620,11 @@ int main(void) setup_sc_context, teardown_sc_context), cmocka_unit_test_setup_teardown(torture_asn1_decode_entry_bit_string_ni, setup_sc_context, teardown_sc_context), + /* put_tag() */ + cmocka_unit_test(torture_asn1_put_tag_short), + cmocka_unit_test(torture_asn1_put_tag_without_data), + cmocka_unit_test(torture_asn1_put_tag_long_tag), + cmocka_unit_test(torture_asn1_put_tag_long_data), }; rc = cmocka_run_group_tests(tests, NULL, NULL); From 71998501f29adbfacf47dea038329fd81712fc9a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 13:24:24 +0200 Subject: [PATCH 164/189] piv: Replace internal implementation of put_tag with asn1 The asn1 implementation is simpler and has more throughout error and buffer overflow checking. Fixes #1394 --- src/libopensc/card-piv.c | 244 +++++++++++++++++++++------------------ 1 file changed, 132 insertions(+), 112 deletions(-) diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index 6e5e1166..4c885a78 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -465,49 +465,6 @@ piv_find_obj_by_containerid(sc_card_t *card, const u8 * str) LOG_FUNC_RETURN(card->ctx, -1); } -/* - * If ptr == NULL, just return the size of the tag and length and data - * otherwise, store tag and length at **ptr, and increment - */ - -static size_t -put_tag_and_len(unsigned int tag, size_t len, u8 **ptr) -{ - int i; - u8 *p; - - if (len < 128) { - i = 2; - } else if (len < 256) { - i = 3; - } else { - i = 4; - } - - if (ptr) { - p = *ptr; - *p++ = (u8)tag; - switch (i) { - case 2: - *p++ = len; - break; - case 3: - *p++ = 0x81; - *p++ = len; - break; - case 4: - *p++ = 0x82; - *p++ = (u8) (len >> 8); - *p++ = (u8) (len & 0xff); - break; - } - *ptr = p; - } else { - i += len; - } - return i; -} - /* * Send a command and receive data. There is always something to send. * Used by GET DATA, PUT DATA, GENERAL AUTHENTICATE @@ -618,10 +575,11 @@ static int piv_generate_key(sc_card_t *card, p = tagbuf; - put_tag_and_len(0xAC, out_len, &p); - - memcpy(p, outdata, out_len); - p+=out_len; + r = sc_asn1_put_tag(0xAC, outdata, out_len, tagbuf, sizeof(tagbuf), &p); + if (r != SC_SUCCESS) { + sc_log(card->ctx, "Failed to encode ASN1 tag"); + goto err; + } r = piv_general_io(card, 0x47, 0x00, keydata->key_num, tagbuf, p - tagbuf, rbuf, sizeof rbuf); @@ -889,9 +847,11 @@ piv_get_data(sc_card_t * card, int enumtag, u8 **buf, size_t *buf_len) tag_len = piv_objects[enumtag].tag_len; p = tagbuf; - put_tag_and_len(0x5c, tag_len, &p); - memcpy(p, piv_objects[enumtag].tag_value, tag_len); - p += tag_len; + r = sc_asn1_put_tag(0x5c, piv_objects[enumtag].tag_value, tag_len, tagbuf, sizeof(tagbuf), &p); + if (r != SC_SUCCESS) { + sc_log(card->ctx, "Failed to encode ASN1 tag"); + goto err; + } if (*buf_len == 1 && *buf == NULL) { /* we need to get the length */ u8 rbufinitbuf[8]; /* tag of 53 with 82 xx xx will fit in 4 */ @@ -1222,15 +1182,22 @@ piv_put_data(sc_card_t *card, int tag, const u8 *buf, size_t buf_len) SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); tag_len = piv_objects[tag].tag_len; - sbuflen = put_tag_and_len(0x5c, tag_len, NULL) + buf_len; - if (!(sbuf = malloc(sbuflen))) + sbuflen = sc_asn1_put_tag(0x5c, piv_objects[tag].tag_value, tag_len, NULL, 0, NULL); + if (sbuflen <= 0) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } + sbuflen += buf_len; + if (!(sbuf = malloc(sbuflen))) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + } p = sbuf; - put_tag_and_len(0x5c, tag_len, &p); - memcpy(p, piv_objects[tag].tag_value, tag_len); - p += tag_len; + r = sc_asn1_put_tag(0x5c, piv_objects[tag].tag_value, tag_len, sbuf, sbuflen, &p); + if (r != SC_SUCCESS) { + LOG_FUNC_RETURN(card->ctx, r); + } + /* This is safe as we calculated the size of buffer above */ memcpy(p, buf, buf_len); p += buf_len; @@ -1253,31 +1220,39 @@ piv_write_certificate(sc_card_t *card, const u8* buf, size_t count, unsigned lon size_t sbuflen; size_t taglen; - taglen = put_tag_and_len(0x70, count, NULL) - + put_tag_and_len(0x71, 1, NULL) - + put_tag_and_len(0xFE, 0, NULL); + taglen = sc_asn1_put_tag(0x70, buf, count, NULL, 0, NULL) + + sc_asn1_put_tag(0x71, NULL, 1, NULL, 0, NULL) + + sc_asn1_put_tag(0xFE, NULL, 0, NULL, 0, NULL); + if (taglen <= 0) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } - sbuflen = put_tag_and_len(0x53, taglen, NULL); + sbuflen = sc_asn1_put_tag(0x53, NULL, taglen, NULL, 0, NULL); + if (sbuflen <= 0) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } sbuf = malloc(sbuflen); if (sbuf == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); p = sbuf; - put_tag_and_len(0x53, taglen, &p); - - put_tag_and_len(0x70, count, &p); - memcpy(p, buf, count); - p += count; - put_tag_and_len(0x71, 1, &p); + if ((r = sc_asn1_put_tag(0x53, NULL, taglen, sbuf, sbuflen, &p)) != SC_SUCCESS || + (r = sc_asn1_put_tag(0x70, buf, count, p, sbuflen - (p - sbuf), &p)) != SC_SUCCESS || + (r = sc_asn1_put_tag(0x71, NULL, 1, p, sbuflen - (p - sbuf), &p)) != SC_SUCCESS) { + goto out; + } /* Use 01 as per NIST 800-73-3 */ - *p++ = (flags)? 0x01:0x00; /* certinfo, i.e. gzipped? */ - put_tag_and_len(0xFE,0,&p); /* LRC tag */ + *p++ = (flags) ? 0x01 : 0x00; /* certinfo, i.e. gzipped? */ + r = sc_asn1_put_tag(0xFE, NULL, 0, p, sbuflen - (p - sbuf), &p); + if (r != SC_SUCCESS) { + goto out; + } enumtag = piv_objects[priv->selected_obj].enumtag; r = piv_put_data(card, enumtag, sbuf, sbuflen); - if (sbuf) - free(sbuf); +out: + free(sbuf); LOG_FUNC_RETURN(card->ctx, r); } @@ -1610,7 +1585,7 @@ static int piv_general_mutual_authenticate(sc_card_t *card, /* get the encrypted nonce */ r = piv_general_io(card, 0x87, alg_id, key_ref, sbuf, p - sbuf, rbuf, sizeof rbuf); - if (r < 0) goto err; + if (r < 0) goto err; /* Remove the encompassing outer TLV of 0x7C and get the data */ body = sc_asn1_find_tag(card->ctx, rbuf, @@ -1695,14 +1670,26 @@ static int piv_general_mutual_authenticate(sc_card_t *card, } /* nonce for challenge */ - tmplen = put_tag_and_len(0x81, witness_len, NULL); + tmplen = sc_asn1_put_tag(0x81, NULL, witness_len, NULL, 0, NULL); + if (tmplen <= 0) { + r = SC_ERROR_INTERNAL; + goto err; + } /* plain text witness keep a length separate for the 0x7C tag */ - tmplen += put_tag_and_len(0x80, witness_len, NULL); - tmplen2 = tmplen; + tmplen2 = sc_asn1_put_tag(0x80, NULL, witness_len, NULL, 0, NULL); + if (tmplen2 <= 0) { + r = SC_ERROR_INTERNAL; + goto err; + } + tmplen2 += tmplen; /* outside 7C tag with 81:80 as innards */ - tmplen = put_tag_and_len(0x7C, tmplen, NULL); + tmplen = sc_asn1_put_tag(0x7C, NULL, tmplen, NULL, 0, NULL); + if (tmplen <= 0) { + r = SC_ERROR_INTERNAL; + goto err; + } built_len = tmplen; @@ -1717,20 +1704,28 @@ static int piv_general_mutual_authenticate(sc_card_t *card, p = built; /* Start with the 7C Tag */ - put_tag_and_len(0x7C, tmplen2, &p); + r = sc_asn1_put_tag(0x7C, NULL, tmplen2, p, built_len, &p); + if (r != SC_SUCCESS) { + goto err; + } /* Add the DECRYPTED witness, tag 0x80 */ - put_tag_and_len(0x80, witness_len, &p); - memcpy(p, plain_text, witness_len); - p += witness_len; + r = sc_asn1_put_tag(0x80, plain_text, witness_len, p, built_len - (p - built), &p); + if (r != SC_SUCCESS) { + goto err; + } /* Add the challenge, tag 0x81 */ - put_tag_and_len(0x81, witness_len, &p); - memcpy(p, nonce, witness_len); + r = sc_asn1_put_tag(0x81, nonce, witness_len, p, built_len - (p - built), &p); + if (r != SC_SUCCESS) { + goto err; + } /* Send constructed data */ - r = piv_general_io(card, 0x87, alg_id, key_ref, built,built_len, rbuf, sizeof rbuf); - if (r < 0) goto err; + r = piv_general_io(card, 0x87, alg_id, key_ref, built, built_len, rbuf, sizeof rbuf); + if (r < 0) { + goto err; + } /* Remove the encompassing outer TLV of 0x7C and get the data */ body = sc_asn1_find_tag(card->ctx, rbuf, @@ -1974,19 +1969,27 @@ static int piv_general_external_authenticate(sc_card_t *card, * memcopy the body past the 7C portion * Transmit */ - tmplen = put_tag_and_len(0x82, cypher_text_len, NULL); + tmplen = sc_asn1_put_tag(0x82, NULL, cypher_text_len, NULL, 0, NULL); + if (tmplen <= 0) { + r = SC_ERROR_INTERNAL; + goto err; + } - tmplen = put_tag_and_len(0x7C, tmplen, &p); + r = sc_asn1_put_tag(0x7C, NULL, tmplen, p, output_len, &p); + if (r != SC_SUCCESS) { + goto err; + } /* Build the 0x82 TLV and append to the 7C tag */ - tmplen += put_tag_and_len(0x82, cypher_text_len, &p); - - memcpy(p, cypher_text, cypher_text_len); - p += cypher_text_len; - tmplen += cypher_text_len; + r = sc_asn1_put_tag(0x82, cypher_text, cypher_text_len, p, output_len - (p - output_buf), &p); + if (r != SC_SUCCESS) { + goto err; + } /* Sanity check the lengths again */ - if(output_len != (size_t)tmplen) { + tmplen = sc_asn1_put_tag(0x7C, NULL, tmplen, NULL, 0, NULL) + + sc_asn1_put_tag(0x82, NULL, cypher_text_len, NULL, 0, NULL); + if (output_len != (size_t)tmplen) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Allocated and computed lengths do not match! " "Expected %"SC_FORMAT_LEN_SIZE_T"d, found: %d\n", output_len, tmplen); r = SC_ERROR_INTERNAL; @@ -2283,31 +2286,42 @@ static int piv_validate_general_authentication(sc_card_t *card, u8 * out, size_t outlen) { piv_private_data_t * priv = PIV_DATA(card); - int r; + int r, tmplen, tmplen2; u8 *p; const u8 *tag; size_t taglen; const u8 *body; size_t bodylen; - unsigned int real_alg_id; + unsigned int real_alg_id, op_tag; u8 sbuf[4096]; /* needs work. for 3072 keys, needs 384+10 or so */ + size_t sbuflen = sizeof(sbuf); u8 rbuf[4096]; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); /* should assume large send data */ p = sbuf; - put_tag_and_len(0x7c, (2 + put_tag_and_len(0, datalen, NULL)) , &p); - put_tag_and_len(0x82, 0, &p); + tmplen = sc_asn1_put_tag(0xff, NULL, datalen, NULL, 0, NULL); + tmplen2 = sc_asn1_put_tag(0x82, NULL, 0, NULL, 0, NULL); + if (tmplen <= 0 || tmplen2 <= 0) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); + } + tmplen += tmplen2; + if ((r = sc_asn1_put_tag(0x7c, NULL, tmplen, p, sbuflen, &p)) != SC_SUCCESS || + (r = sc_asn1_put_tag(0x82, NULL, 0, p, sbuflen - (p - sbuf), &p)) != SC_SUCCESS) { + LOG_FUNC_RETURN(card->ctx, r); + } if (priv->operation == SC_SEC_OPERATION_DERIVE - && priv->algorithm == SC_ALGORITHM_EC) - put_tag_and_len(0x85, datalen, &p); - else - put_tag_and_len(0x81, datalen, &p); - - memcpy(p, data, datalen); - p += datalen; + && priv->algorithm == SC_ALGORITHM_EC) { + op_tag = 0x85; + } else { + op_tag = 0x81; + } + r = sc_asn1_put_tag(op_tag, data, datalen, p, sbuflen - (p - sbuf), &p); + if (r != SC_SUCCESS) { + LOG_FUNC_RETURN(card->ctx, r); + } /* * alg_id=06 is a place holder for all RSA keys. @@ -2897,11 +2911,14 @@ piv_process_history(sc_card_t *card) enumtag = PIV_OBJ_RETIRED_X509_1 + *keyref - 0x82; /* now add the cert like another object */ - i2 = put_tag_and_len(0x70,certlen, NULL) - + put_tag_and_len(0x71, 1, NULL) - + put_tag_and_len(0xFE, 0, NULL); - - certobjlen = put_tag_and_len(0x53, i2, NULL); + i2 = sc_asn1_put_tag(0x70, NULL, certlen, NULL, 0, NULL) + + sc_asn1_put_tag(0x71, NULL, 1, NULL, 0, NULL) + + sc_asn1_put_tag(0xFE, NULL, 0, NULL, 0, NULL); + certobjlen = sc_asn1_put_tag(0x53, NULL, i2, NULL, 0, NULL); + if (i2 <= 0 || certobjlen <= 0) { + r = SC_ERROR_INTERNAL; + goto err; + } certobj = malloc(certobjlen); if (certobj == NULL) { @@ -2909,13 +2926,16 @@ piv_process_history(sc_card_t *card) goto err; } cp = certobj; - put_tag_and_len(0x53, i2, &cp); - put_tag_and_len(0x70,certlen, &cp); - memcpy(cp, cert, certlen); - cp += certlen; - put_tag_and_len(0x71, 1,&cp); + if ((r = sc_asn1_put_tag(0x53, NULL, i2, cp, certobjlen, &cp)) != SC_SUCCESS || + (r = sc_asn1_put_tag(0x70, cert, certlen, cp, certobjlen - (cp - certobj), &cp)) != SC_SUCCESS || + (r = sc_asn1_put_tag(0x71, NULL, 1, cp, certobjlen - (cp - certobj), &cp)) != SC_SUCCESS) { + goto err; + } *cp++ = 0x00; - put_tag_and_len(0xFE, 0, &cp); + r = sc_asn1_put_tag(0xFE, NULL, 0, cp, certobjlen - (cp - certobj), &cp); + if (r != SC_SUCCESS) { + goto err; + } priv->obj_cache[enumtag].obj_data = certobj; priv->obj_cache[enumtag].obj_len = certobjlen; From 295f399304644e6b0acde267ac410d0aae4a1aee Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 24 Apr 2020 10:18:03 +0200 Subject: [PATCH 165/189] reader-pcsc: Avoid use after free (CID 355473) --- src/libopensc/reader-pcsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 34dc821b..b3da6fc8 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -2550,10 +2550,10 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c priv->pcsc_card = card_handle; detect_protocol(reader, card_handle); detect_reader_features(reader, card_handle); + gpriv->attached_reader = reader; } else { _sc_delete_reader(ctx, reader); } - gpriv->attached_reader = reader; } out: From d1457e9fa3e9e36cab64e6355dca0ffa2176f93b Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Fri, 24 Apr 2020 10:30:25 +0200 Subject: [PATCH 166/189] coolkey: Drop dead code (CID 351911) default branch of the switch calls continue, preventing going out of the loop without obj_info set. --- src/libopensc/pkcs15-coolkey.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libopensc/pkcs15-coolkey.c b/src/libopensc/pkcs15-coolkey.c index a182eca0..414ab2f2 100644 --- a/src/libopensc/pkcs15-coolkey.c +++ b/src/libopensc/pkcs15-coolkey.c @@ -670,9 +670,6 @@ static int sc_pkcs15emu_coolkey_init(sc_pkcs15_card_t *p15card) sc_log(card->ctx, "Unknown object type %lu, skipping", obj_class); continue; } - if (obj_info == NULL) { - continue; - } r = sc_pkcs15emu_object_add(p15card, obj_type, &obj_obj, obj_info); if (r != SC_SUCCESS) From ce659b2f7af54559fc632cf018249c60e9a68e70 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 14:30:54 +0200 Subject: [PATCH 167/189] test: Fix typo in comment --- tests/test-manpage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-manpage.sh b/tests/test-manpage.sh index 89fab7d1..6567534a 100755 --- a/tests/test-manpage.sh +++ b/tests/test-manpage.sh @@ -1,7 +1,7 @@ #!/bin/bash SOURCE_PATH=../ -# find all the manual pages in src/tools +# find all the manual pages in doc/tools TOOLS=`find "${SOURCE_PATH}/doc/tools" -name "*.1.xml" | sed -E -e "s|.*/([a-z0-9-]*).*|\1|"` ALL=1 From ddc049e37bac40ec20bfd10f79c69f4dad15d949 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 15:00:05 +0200 Subject: [PATCH 168/189] Remove bogus file from tools directory --- src/tools/apdus | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 src/tools/apdus diff --git a/src/tools/apdus b/src/tools/apdus deleted file mode 100644 index 922c3cd4..00000000 --- a/src/tools/apdus +++ /dev/null @@ -1,29 +0,0 @@ -00:22:81:B6:0F:83:0D:5A:5A:43:56:43:41:41:54:41:30:30:30:31 -00:2a:00:be:e4:7f:4e:81:9d:5f:29:01:00:42:0d:5a:5a:43:56:43:41:41:54:41:30:30:30:31:7f:49:4f:06:0a:04:00:7f:00:07:02:02:02:02:03:86:41:04:52:dd:32:ea:fe:1f:bb:b4:00:0c:d9:ce:75:f6:66:36:cf:cf:1e:dd:44:f7:b1:ed:ae:25:b8:41:93:da:04:a9:1c:77:ee:87:f5:c8:f9:59:ed:27:62:00:de:33:ab:57:4c:e9:80:11:35:ff:44:97:a3:71:62:b7:c8:54:8a:0c:5f:20:0e:5a:5a:44:56:43:41:41:54:41:30:30:30:30:35:7f:4c:12:06:09:04:00:7f:00:07:03:01:02:02:53:05:70:03:01:ff:b7:5f:25:06:01:00:00:06:01:01:5f:24:06:01:00:01:00:03:01:5f:37:40:6f:13:ae:9a:6f:4e:dd:b7:83:9f:f3:f0:4d:71:e0:dc:37:7b:c4:b0:8f:ad:29:5e:ed:24:1b:52:43:28:ad:07:30:eb:55:34:97:b4:fb:66:e9:bb:7a:b9:08:15:f0:42:73:f0:9e:75:1d:7f:d4:b8:61:43:9b:4e:e6:53:81:c3 -002281B610830E5A5A445643414154413030303035 -002a00be0001417f4e81fa5f290100420e5a5a4456434141544130303030357f494f060a04007f000702020202038641049bfe7415d73c4a78d60b2cc1bca11b6d5e523969acfb5b756a3be1551b22239c79ae362b838b00669983c0caf6ed0c781d401c95d2b32857de8ce1b619dac4a75f200a5a5a5349543030304f347f4c12060904007f000703010202530500000000045f25060100000902015f2406010000090206655e732d060904007f0007030103028020b02baa51a94fac0954df204d61fe22da1d408d45db4aa1d70e600dad4faf6799732d060904007f0007030103018020c72e13582f01ba068dd1aac29a2428c0c54ab9c204fd53b3f13e8290e21e50f95f374083c5b441fec5b18efd1caa4a11b8e1cede0a8b42d442f00d7f604e429f339b4e3e6c06f9e76a2daa82c1722ee137a89038b969c634561581e6c26d9f6fa75c52 -00:22:81:A4:53:80:0A:04:00:7F:00:07:02:02:02:02:03:83:0A:5A:5A:53:49:54:30:30:30:4F:34:91:20:88:E5:F2:C6:11:18:0D:0A:C1:0E:BD:E6:FC:2A:5E:62:41:79:C0:A5:77:C3:E4:88:52:DD:81:A4:CD:F7:90:51:67:17:73:15:06:09:04:00:7F:00:07:03:01:04:02:53:08:32:30:31:30:30:39:32:34 -00:84:00:00:08 -00820000400C9E7DB72CB0FAEA15B00FECAE0257546446A9395862239AF240C3C29E857F8403345817760FE13F6597F04D2F7330B59065F68DF71EF7FDEC86743CDE2869DD -00a4000c023f00 -00:A4:02:0C:02:01:1D -00:b0:00:00:80 -00B0008080 -00b0010080 -00:B0:01:80:80 -00:b0:02:00:80 -00B0028080 -00b0030080 -00:B0:03:80:80 -00:b0:04:00:80 -00B0048080 -00b0050080 -00:B0:05:80:80 -00:b0:06:00:80 -00B0068080 -00b0070080 -00:B0:07:80:80 -00:22:41:a4:0c:80:0a:04:00:7f:00:07:02:02:03:02:02 -00860000457C43804104239E3D05EEB059117D30F86AEB5AE7D12E0EBF758889C79115F2A13DC1BB570A5CAD91A384337C09D1B74BED1C0FF195A7C3EA3A2CEDF86DDEF7B95D1FD1B35D00 -0020001006010203040506 - From 3c7823d1f0b4870f4ae310aa052821f82debee67 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 15:01:21 +0200 Subject: [PATCH 169/189] tests: Verify every tool has a manual page --- tests/test-manpage.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/test-manpage.sh b/tests/test-manpage.sh index 6567534a..67eef8bf 100755 --- a/tests/test-manpage.sh +++ b/tests/test-manpage.sh @@ -17,5 +17,17 @@ for T in $TOOLS; do done if [ "$ALL" = 0 ]; then echo "Not all the switches in help are documented in manual pages" - exit 1; + exit 1 fi + +RES=0 +# find all tools in src/tools (files without extension) +TOOLS=`find "${SOURCE_PATH}/src/tools" -maxdepth 1 -type f ! -name "*.*" | sed -E -e "s|.*/([a-z0-9-]*).*|\1|"` +for T in $TOOLS; do + if [[ ! -f "${SOURCE_PATH}/doc/tools/$T.1.xml" ]]; then + echo "Missing manual page for '$T'" + RES=1 + fi +done + +exit $RES From a1d53aa2171b65f0208274495f342dfe4b298958 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 15:40:48 +0200 Subject: [PATCH 170/189] tests: Temporarily whitelist example binaries in tools/ --- tests/test-manpage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-manpage.sh b/tests/test-manpage.sh index 67eef8bf..9a43d422 100755 --- a/tests/test-manpage.sh +++ b/tests/test-manpage.sh @@ -22,7 +22,7 @@ fi RES=0 # find all tools in src/tools (files without extension) -TOOLS=`find "${SOURCE_PATH}/src/tools" -maxdepth 1 -type f ! -name "*.*" | sed -E -e "s|.*/([a-z0-9-]*).*|\1|"` +TOOLS=`find "${SOURCE_PATH}/src/tools" -maxdepth 1 -type f ! -name "*.*" | sed -E -e "s|.*/([a-z0-9-]*).*|\1|" | grep -v -- -example` for T in $TOOLS; do if [[ ! -f "${SOURCE_PATH}/doc/tools/$T.1.xml" ]]; then echo "Missing manual page for '$T'" From 0a057a976d8d517a16045c466a88606b1cde3ac4 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 16:32:08 +0200 Subject: [PATCH 171/189] Fix typo arguement -> argument in documentation --- src/tools/egk-tool-cmdline.c | 4 ++-- src/tools/egk-tool-cmdline.h | 6 +++--- src/tools/egk-tool.ggo.in | 2 +- src/tools/goid-tool-cmdline.c | 4 ++-- src/tools/goid-tool-cmdline.h | 6 +++--- src/tools/goid-tool.ggo.in | 2 +- src/tools/npa-tool-cmdline.c | 4 ++-- src/tools/npa-tool-cmdline.h | 6 +++--- src/tools/npa-tool.ggo.in | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/tools/egk-tool-cmdline.c b/src/tools/egk-tool-cmdline.c index 706c91fb..6b64cf33 100644 --- a/src/tools/egk-tool-cmdline.c +++ b/src/tools/egk-tool-cmdline.c @@ -36,7 +36,7 @@ const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", - " -r, --reader=STRING Number of the reader to use. By default, the first\n reader with a present card is used. If the arguement\n is an ATR, the reader with a matching card will be\n chosen.", + " -r, --reader=STRING Number of the reader to use. By default, the first\n reader with a present card is used. If the argument\n is an ATR, the reader with a matching card will be\n chosen.", " -v, --verbose Use (several times) to be more verbose", "\nHealth Care Application (HCA):", " --pd Show 'Persönliche Versicherungsdaten' (XML)\n (default=off)", @@ -606,7 +606,7 @@ cmdline_parser_internal ( cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); - case 'r': /* Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen.. */ + case 'r': /* Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen.. */ if (update_arg( (void *)&(args_info->reader_arg), diff --git a/src/tools/egk-tool-cmdline.h b/src/tools/egk-tool-cmdline.h index 51967686..f231389c 100644 --- a/src/tools/egk-tool-cmdline.h +++ b/src/tools/egk-tool-cmdline.h @@ -39,9 +39,9 @@ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ - char * reader_arg; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen.. */ - char * reader_orig; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen. original value given at command line. */ - const char *reader_help; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen. help description. */ + char * reader_arg; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen.. */ + char * reader_orig; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen. original value given at command line. */ + const char *reader_help; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen. help description. */ unsigned int verbose_min; /**< @brief Use (several times) to be more verbose's minimum occurreces */ unsigned int verbose_max; /**< @brief Use (several times) to be more verbose's maximum occurreces */ const char *verbose_help; /**< @brief Use (several times) to be more verbose help description. */ diff --git a/src/tools/egk-tool.ggo.in b/src/tools/egk-tool.ggo.in index 6b709461..dc7dcf2c 100644 --- a/src/tools/egk-tool.ggo.in +++ b/src/tools/egk-tool.ggo.in @@ -2,7 +2,7 @@ package "egk-tool" purpose "@PACKAGE_SUMMARY@" option "reader" r - "Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen." + "Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen." string optional option "verbose" v diff --git a/src/tools/goid-tool-cmdline.c b/src/tools/goid-tool-cmdline.c index d81b0b97..51d27883 100644 --- a/src/tools/goid-tool-cmdline.c +++ b/src/tools/goid-tool-cmdline.c @@ -36,7 +36,7 @@ const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", - " -r, --reader=STRING Number of the reader to use. By default, the\n first reader with a present card is used. If\n the arguement is an ATR, the reader with a\n matching card will be chosen.", + " -r, --reader=STRING Number of the reader to use. By default, the\n first reader with a present card is used. If\n the argument is an ATR, the reader with a\n matching card will be chosen.", " -v, --verbose Use (several times) to be more verbose", " -p, --verify-pin Verify PIN", " -b, --verify-bio Verify finger print", @@ -1220,7 +1220,7 @@ cmdline_parser_internal ( cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); - case 'r': /* Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen.. */ + case 'r': /* Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen.. */ if (update_arg( (void *)&(args_info->reader_arg), diff --git a/src/tools/goid-tool-cmdline.h b/src/tools/goid-tool-cmdline.h index 5ae8eeda..9685d56f 100644 --- a/src/tools/goid-tool-cmdline.h +++ b/src/tools/goid-tool-cmdline.h @@ -39,9 +39,9 @@ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ - char * reader_arg; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen.. */ - char * reader_orig; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen. original value given at command line. */ - const char *reader_help; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen. help description. */ + char * reader_arg; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen.. */ + char * reader_orig; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen. original value given at command line. */ + const char *reader_help; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen. help description. */ unsigned int verbose_min; /**< @brief Use (several times) to be more verbose's minimum occurreces */ unsigned int verbose_max; /**< @brief Use (several times) to be more verbose's maximum occurreces */ const char *verbose_help; /**< @brief Use (several times) to be more verbose help description. */ diff --git a/src/tools/goid-tool.ggo.in b/src/tools/goid-tool.ggo.in index 3034e56c..e606da76 100644 --- a/src/tools/goid-tool.ggo.in +++ b/src/tools/goid-tool.ggo.in @@ -2,7 +2,7 @@ package "goid-tool" purpose "@PACKAGE_SUMMARY@" option "reader" r - "Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen." + "Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen." string optional option "verbose" v "Use (several times) to be more verbose" diff --git a/src/tools/npa-tool-cmdline.c b/src/tools/npa-tool-cmdline.c index 5ab97819..68a4b94b 100644 --- a/src/tools/npa-tool-cmdline.c +++ b/src/tools/npa-tool-cmdline.c @@ -36,7 +36,7 @@ const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", - " -r, --reader=STRING Number of the reader to use. By default, the\n first reader with a present card is used. If\n the arguement is an ATR, the reader with a\n matching card will be chosen.", + " -r, --reader=STRING Number of the reader to use. By default, the\n first reader with a present card is used. If\n the argument is an ATR, the reader with a\n matching card will be chosen.", " -v, --verbose Use (several times) to be more verbose", "\nPassword Authenticated Connection Establishment (PACE):", " -p, --pin[=STRING] Run PACE with (transport) eID-PIN", @@ -1245,7 +1245,7 @@ cmdline_parser_internal ( cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); - case 'r': /* Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen.. */ + case 'r': /* Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen.. */ if (update_arg( (void *)&(args_info->reader_arg), diff --git a/src/tools/npa-tool-cmdline.h b/src/tools/npa-tool-cmdline.h index 190dc5d6..6412362f 100644 --- a/src/tools/npa-tool-cmdline.h +++ b/src/tools/npa-tool-cmdline.h @@ -39,9 +39,9 @@ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ - char * reader_arg; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen.. */ - char * reader_orig; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen. original value given at command line. */ - const char *reader_help; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen. help description. */ + char * reader_arg; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen.. */ + char * reader_orig; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen. original value given at command line. */ + const char *reader_help; /**< @brief Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen. help description. */ unsigned int verbose_min; /**< @brief Use (several times) to be more verbose's minimum occurreces */ unsigned int verbose_max; /**< @brief Use (several times) to be more verbose's maximum occurreces */ const char *verbose_help; /**< @brief Use (several times) to be more verbose help description. */ diff --git a/src/tools/npa-tool.ggo.in b/src/tools/npa-tool.ggo.in index e27889ca..f2439a72 100644 --- a/src/tools/npa-tool.ggo.in +++ b/src/tools/npa-tool.ggo.in @@ -2,7 +2,7 @@ package "npa-tool" purpose "@PACKAGE_SUMMARY@" option "reader" r - "Number of the reader to use. By default, the first reader with a present card is used. If the arguement is an ATR, the reader with a matching card will be chosen." + "Number of the reader to use. By default, the first reader with a present card is used. If the argument is an ATR, the reader with a matching card will be chosen." string optional option "verbose" v From b091165595d309468542ca8fb7e0173b53ace080 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 16:32:30 +0200 Subject: [PATCH 172/189] doc: Drop trailing comma --- doc/tools/opensc-tool.1.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tools/opensc-tool.1.xml b/doc/tools/opensc-tool.1.xml index ea2c235a..43acf612 100644 --- a/doc/tools/opensc-tool.1.xml +++ b/doc/tools/opensc-tool.1.xml @@ -35,7 +35,7 @@ - , + Print the OpenSC package release version. From 797414be05220fa371972606d7a6c2e94dd6d8db Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 22 Apr 2020 16:48:40 +0200 Subject: [PATCH 173/189] Create missing man pages (goid needs some work) --- doc/tools/goid-tool.1.xml | 126 ++++++++++++++++++++++++++++++++ doc/tools/pkcs11-register.1.xml | 124 +++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 doc/tools/goid-tool.1.xml create mode 100644 doc/tools/pkcs11-register.1.xml diff --git a/doc/tools/goid-tool.1.xml b/doc/tools/goid-tool.1.xml new file mode 100644 index 00000000..53e23140 --- /dev/null +++ b/doc/tools/goid-tool.1.xml @@ -0,0 +1,126 @@ + + + + goid-tool + 1 + OpenSC + OpenSC Tools + opensc + + + + goid-tool + ??? + + + + + goid-tool + OPTIONS + mode + + + + + Description + + The goid-tool utility can be used from + the command line to ??? + + + + + Options + + + + + , + + + Print help message on screen. + + + + , + + + Print the OpenSC package release version. + + + + string, + string + + + Specify the number of the reader to use. By default, the + first reader with present card is used. If + the arguement is an ATR, the reader with a + matching card will be chosen. + + + + + , + + + + Cause goid-tool to be + more verbose. Use it multiple times to be even more + verbose. + + + + + , + + + + Verify PIN. + + + + + , + + + + Verify finger print. + + + + + + + + Verify PIN or finger print (user's choice). + + + + + + + + See also + + + pkcs11-tool + 1 + + + opensc.conf + 5 + + + + + + Authors + pkcs11-register was written by + Frank Morgner frankmorgner@gmail.com. + + + + + + diff --git a/doc/tools/pkcs11-register.1.xml b/doc/tools/pkcs11-register.1.xml new file mode 100644 index 00000000..a3da7546 --- /dev/null +++ b/doc/tools/pkcs11-register.1.xml @@ -0,0 +1,124 @@ + + + + pkcs11-register + 1 + OpenSC + OpenSC Tools + opensc + + + + pkcs11-register + Simple tool to install PKCS#11 modules to known applications. + + + + + pkcs11-register + OPTIONS + + + + + Description + + The pkcs11-register utility can be used from + the command line to register PKCS#11 modules to various applications + + + + + Options + + + + + , + + + Print help message on screen. + + + + , + + + Print the OpenSC package release version. + + + + filename, + filename + + + Path to the PKCS#11 module to load. The default + is OpenSC PKCS#11 module. + + + + + + + + Don't install module for Chrome browser. By default, + the tool attempts to install the module for Chrome + browser. + + + + + + + + Don't install module for Firefox browser. By default, + the tool attempts to install the module for Firefox + browser. + + + + + + + + Don't install module for Thunderbird mail client. + By default, the tool attempts to install the module + for Thunderbird mail client. + + + + + + + + Don't install module for Seamonkey. By default, + the tool attempts to install the module Seamonkey. + + + + + + + + See also + + + pkcs11-tool + 1 + + + opensc.conf + 5 + + + + + + Authors + pkcs11-register was written by + Frank Morgner frankmorgner@gmail.com. + + + + + From 52d5370c1e3bb1480d82f5f81cabdaf5767354a8 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sat, 4 Apr 2020 15:29:47 -0500 Subject: [PATCH 174/189] asn1.c don't use strict mode see: https://github.com/OpenSC/OpenSC/issues/1995#issuecomment-607490809 On branch cardos-5.3 Changes to be committed: modified: asn1.c --- src/libopensc/asn1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 75bc1c9e..e19a8d32 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -1509,7 +1509,7 @@ static int asn1_decode_entry(sc_context_t *ctx,struct sc_asn1_entry *entry, case SC_ASN1_INTEGER: case SC_ASN1_ENUMERATED: if (parm != NULL) { - r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm, 1); + r = sc_asn1_decode_integer(obj, objlen, (int *) entry->parm, 0); sc_debug(ctx, SC_LOG_DEBUG_ASN1, "%*.*sdecoding '%s' returned %d\n", depth, depth, "", entry->name, *((int *) entry->parm)); } From f5fe292ae13687e722ec3167fec28e62e5aae3ab Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sun, 29 Mar 2020 05:56:21 -0500 Subject: [PATCH 175/189] pkcs11-tool - use valid data for decription tests In tests, make sute test data is either padded, or "zero" padded so size if data <= modlen - 11. The smallest pad in 11 bytes, 00 | NN | PS | 00. PS is at least 8 bytes. "zero" padding has N = 00, PS >= 8 byte of 00. On branch cardos-5.3 Changes to be committed: modified: tools/pkcs11-tool.c --- src/tools/pkcs11-tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 3ad92890..b1674a76 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -5044,8 +5044,8 @@ static int test_signature(CK_SESSION_HANDLE sess) } if (firstMechType == CKM_RSA_X_509) { - /* make sure our data is smaller than the modulus */ - data[0] = 0x00; + /* make sure our data is smaller than the modulus - 11 */ + memset(data, 0, 11); /* in effect is zero padding */ } ck_mech.mechanism = firstMechType; From 3f21dc57b73de829a69c99583916c55b97483da0 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Sun, 5 Apr 2020 11:04:42 -0500 Subject: [PATCH 176/189] Increase SC_MAX_SUPPORTED_ALGORITHMS from 8 to 16 CardOS cards may have more then 8 supported_algo_info entries in tokenInfo. We may bemissing some. We have seen 8 in some pkcs15-tool -i -v output. Simple fix is to incrase the limit. More appropriate fix is to remove the limit, much like is done with sc_algorithm_info. and use realloc of the array. On branch cardos-5.3 Changes to be committed: modified: src/libopensc/pkcs15-prkey.c modified: src/libopensc/pkcs15-skey.c modified: src/libopensc/pkcs15.c modified: src/libopensc/types.h --- src/libopensc/pkcs15-prkey.c | 10 +++++++++- src/libopensc/pkcs15-skey.c | 10 +++++++++- src/libopensc/pkcs15.c | 10 +++++++++- src/libopensc/types.h | 6 ++++-- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index ed008ede..a6c05415 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -48,10 +48,18 @@ #include "aux-data.h" /* - * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 + * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 */ #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1) static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = { + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, diff --git a/src/libopensc/pkcs15-skey.c b/src/libopensc/pkcs15-skey.c index b22e6197..4e58355a 100644 --- a/src/libopensc/pkcs15-skey.c +++ b/src/libopensc/pkcs15-skey.c @@ -28,10 +28,18 @@ #include /* - * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 + * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 */ #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1) static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = { + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index ba04f531..d4a44969 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -64,9 +64,17 @@ static const struct sc_asn1_entry c_asn1_algorithm_info_parameters[3] = { }; /* - * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 8 + * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 */ static const struct sc_asn1_entry c_asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1] = { + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, + { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, { "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, diff --git a/src/libopensc/types.h b/src/libopensc/types.h index 76cf4c1a..17035b55 100644 --- a/src/libopensc/types.h +++ b/src/libopensc/types.h @@ -52,9 +52,11 @@ typedef unsigned char u8; /* When changing this value, pay attention to the initialization of the ASN1 * static variables that use this macro, like, for example, - * 'c_asn1_supported_algorithms' in src/libopensc/pkcs15.c + * 'c_asn1_supported_algorithms' in src/libopensc/pkcs15.c, + * src/libopensc/pkcs15-prkey.c and src/libopensc/pkcs15-skey.c + * `grep "src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as"' */ -#define SC_MAX_SUPPORTED_ALGORITHMS 8 +#define SC_MAX_SUPPORTED_ALGORITHMS 16 struct sc_lv_data { unsigned char *value; From c03efeee405efe4810b6a35aad7f54c0c689205c Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 17 Apr 2020 12:26:14 -0500 Subject: [PATCH 177/189] sc_supported_algo_info - Put ECDSA OID as inline Mismatch of ASN1 parsing of tokeninfo.supported_algos[n].paramters in one place parameter was treated as a pointer to sc_object_id and in another as inline structure. This caused segfaults in pkcs15-tool when it tried to print the OID. Changes to be committed: modified: src/libopensc/opensc.h modified: src/libopensc/pkcs15.c --- src/libopensc/opensc.h | 2 +- src/libopensc/pkcs15.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 9e764665..0c3c73e2 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -223,7 +223,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 */ + struct sc_object_id parameters; /* OID for ECC */ unsigned int operations; struct sc_object_id algo_id; unsigned int algo_ref; diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index d4a44969..c58c34fd 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -318,7 +318,7 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, 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, asn1_algo_infos_parameters[ii], NULL, 1); - if (!ti->supported_algos[ii].parameters) { + if (!sc_valid_oid(&ti->supported_algos[ii].parameters)) { sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0, NULL, NULL, 1); } From 8a5a1435f1a7d1b22e3255d2726d8020c15a6658 Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Thu, 26 Mar 2020 13:51:33 -0500 Subject: [PATCH 178/189] pkcs15-tool.c - print Supported_algorithms from tokenInfo Some cards can provide supported algorithms in tokenInfo which contain ECDSA OID, and PKCS11 mechanism Don't know how many Algo_refs were actually read, and a ref of 0 may be valid. print at least one Algo_refs. Print the mechanism from PKCS11, and print operations Use the $(top_srcdir)/src/pkcs11/pkcs11-display.c on Unix Use the $(TOPDIR)\src\pkcs11\pkcs11-display.obj on Windows pkcs15.tool.c treat ECDSA OID as inline pkcs15-tool prints PKCS11 mechanisms using pkcs11-display.c Automake now warns that the default will change, in the future so "[subdir-objects]" is added to configure.ac Changes to be committed: modified: configure.ac modified: src/tools/Makefile.am modified: src/tools/Makefile.mak modified: src/tools/pkcs15-tool.c --- configure.ac | 2 +- src/tools/Makefile.am | 2 +- src/tools/Makefile.mak | 5 ++++ src/tools/pkcs15-tool.c | 57 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 705bc027..f54093b0 100644 --- a/configure.ac +++ b/configure.ac @@ -27,7 +27,7 @@ AC_INIT([PRODUCT_NAME],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERS AC_CONFIG_AUX_DIR([.]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE(foreign 1.10) +AM_INIT_AUTOMAKE(foreign 1.10 [subdir-objects]) OPENSC_VERSION_MAJOR="PACKAGE_VERSION_MAJOR" OPENSC_VERSION_MINOR="PACKAGE_VERSION_MINOR" diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 5ee5edfb..55beb631 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -52,7 +52,7 @@ piv_tool_SOURCES = piv-tool.c util.c piv_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) opensc_explorer_SOURCES = opensc-explorer.c util.c opensc_explorer_LDADD = $(OPTIONAL_READLINE_LIBS) -pkcs15_tool_SOURCES = pkcs15-tool.c util.c +pkcs15_tool_SOURCES = pkcs15-tool.c util.c ../pkcs11/pkcs11-display.c ../pkcs11/pkcs11-display.h pkcs15_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS) pkcs11_tool_SOURCES = pkcs11-tool.c util.c pkcs11_tool_LDADD = \ diff --git a/src/tools/Makefile.mak b/src/tools/Makefile.mak index 4637a44d..38e5ba4e 100644 --- a/src/tools/Makefile.mak +++ b/src/tools/Makefile.mak @@ -52,6 +52,11 @@ pkcs11-register.exe: pkcs11-register-cmdline.obj fread_to_eof.obj $(LIBS) link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj pkcs11-register-cmdline.obj fread_to_eof.obj versioninfo-tools.res $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib mt -manifest exe.manifest -outputresource:$@;1 +pkcs15-tool.exe: pkcs15-tool.obj $(TOPDIR)\src\pkcs11\pkcs11-display.obj + cl $(COPTS) /c $*.c + link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj $(TOPDIR)\src\pkcs11\pkcs11-display.obj $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib + mt -manifest exe.manifest -outputresource:$@;1 + .c.exe: cl $(COPTS) /c $< link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index e901e17d..363bfb82 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -57,6 +57,7 @@ typedef unsigned __int32 uint32_t; #include "libopensc/pkcs15.h" #include "libopensc/asn1.h" #include "util.h" +#include "pkcs11/pkcs11-display.h" static const char *app_name = "pkcs15-tool"; @@ -607,6 +608,8 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; unsigned char guid[40]; size_t guid_len; + int i; + int last_algo_refs = 0; if (compact) { printf("\t%-3s", key_types[7 & obj->type]); @@ -635,6 +638,16 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj) printf("\tAccess Flags : [0x%02X]", prkey->access_flags); print_key_access_flags(prkey->access_flags); printf("\n"); + printf("\tAlgo_refs : "); + /* zero may be valid and don't know how many were read print at least 1*/ + for (i = 0; i< SC_MAX_SUPPORTED_ALGORITHMS; i++) { + if (prkey->algo_refs[i] != 0) + last_algo_refs = i; + } + for (i = 0; i< last_algo_refs + 1; i++) { + printf("%s%u", (i == 0) ? "" : ", ", prkey->algo_refs[i]); + } + printf("\n"); print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES); @@ -1645,6 +1658,21 @@ static int list_apps(FILE *fout) return 0; } + +static void print_supported_algo_info_operations(unsigned int operation) + +{ + size_t i; + const char *operations[] = { + "compute_checksum", "compute_signature", "verify_checksum", "verify_signature", + "encipher", "decipher", "hash", "generate/derive_key" + }; + const size_t operations_count = NELEMENTS(operations); + for (i = 0; i < operations_count; i++) + if (operation & (1 << i)) + printf(", %s", operations[i]); +} + static void list_info(void) { const char *flags[] = { @@ -1655,6 +1683,7 @@ static void list_info(void) }; char *last_update = sc_pkcs15_get_lastupdate(p15card); int i, count = 0; + int idx; printf("PKCS#15 Card [%s]:\n", p15card->tokeninfo->label); printf("\tVersion : %d\n", p15card->tokeninfo->version); @@ -1675,6 +1704,34 @@ static void list_info(void) count++; } } + printf("\n"); + for (i = 0; i < SC_MAX_SUPPORTED_ALGORITHMS; i++) { + struct sc_supported_algo_info * sa = &p15card->tokeninfo->supported_algos[i]; + + if (sa->reference == 0 && sa->reference == 0 && sa->mechanism == 0 + && sa->operations == 0 && sa->algo_ref == 0) + break; + printf("\t\t sc_supported_algo_info[%d]:\n", i); + printf("\t\t\t reference : %u (0x%02x)\n", sa->reference, sa->reference); + printf("\t\t\t mechanism : [0x%02x] %s\n", sa->mechanism, lookup_enum(MEC_T, sa->mechanism)); + if (sc_valid_oid(&sa->parameters)) { + printf("\t\t\t parameters: %i", sa->parameters.value[0]); + for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && sa->parameters.value[idx] != -1 ; idx++) + printf(".%i", sa->parameters.value[idx]); + printf("\n"); + } + printf("\t\t\t operations : [0x%2.2x]",sa->operations); + print_supported_algo_info_operations(sa->operations); + printf("\n"); + if (sc_valid_oid((const struct sc_object_id*)&sa->algo_id)) { + printf("\t\t\t algo_id : %i", sa->algo_id.value[0]); + for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && sa->algo_id.value[idx] != -1 ; idx++) + printf(".%i", sa->algo_id.value[idx]); + printf("\n"); + } + printf("\t\t\t algo_ref : [0x%02x]\n",sa->algo_ref); + } + printf((compact) ? "\n" : "\n\n"); } From db41cd9ab1033e0c63c894e2dcdd3da14edec3cf Mon Sep 17 00:00:00 2001 From: Doug Engert Date: Fri, 17 Apr 2020 11:36:48 -0500 Subject: [PATCH 179/189] Various CardOS V5_* improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Treat CardOS V5_0 and V5_3 cards differently then older versions: Use card->dvr_data as a pointer to cardos_data_t to store private driver data to pass internally, especially between set security environment and the crypto operations. Sc_get_encoding_flags sets sec_flags from algo_info->flags in pkcs15-sec.c and it passed to decipher. Some cards when doing a decipher may drop leading 00 byte when returning data from RSA_RAW decipher. Add leading byte(s) as needed. Get Cryptographic Mechanism Reference from Key Reference: Key reference byte appears to be a 4 bit Cryptographic Mechanism Reference and a 4 bit key reference. This is only done if key reference & 0xF0 != 0 i.e. default Cryptographic mechanism reference is 0. which appears to be the case for RSA RAW. PKCS1 appears to be 0x10 and ECDSA 0x30 See iso 7816-4 table 55 for DST: 84 Reference of a private key 95 Usage qualifier byte - Table 57 - 40 looks OK 80 Cryptographic mechanism reference and referes to section 9.2 The 4 bit key reference limits card to 16 keys. In future this may not work, but we can derive a Cryptographic Mechanism Reference from what OpenSC thinks the card needs to do. Only know RSA RAW, PKCS1 and ECDSA. ECDSA code has not been tested, but expected to work. Allow setting CardOS type and flags from opensc.conf using card_atr stanza This is a fallback if newer cards are added or older cards have problems giving us time to make need changes in next release. It will help in identifying what flags are needed for each card. As user can report what combination of flags work for them. They do this by adding to opensc.conf with something like this. (Change the ATR to your card's ATR): card_atr 3b:d2:18:00:81:31:fe:58:c9:03:16 { driver = "cardos"; # type is decimal from cards.h: # SC_CARD_TYPE_CARDOS_V5_0 is 1009 # SC_CARD_TYPE_CARDOS_V5_3 is 1010 type = 1010; # flags is hex from opensc.h: #define SC_ALGORITHM_ONBOARD_KEY_GEN 0x80000000 #define SC_ALGORITHM_NEED_USAGE 0x40000000 #define SC_ALGORITHM_RSA_RAW 0x00000001 /* RSA_RAW is PAD_NONE */ #define SC_ALGORITHM_RSA_PAD_NONE 0x00000001 #define SC_ALGORITHM_RSA_PAD_PKCS1 0x00000002 /* PKCS#1 v1.5 padding */ #define SC_ALGORITHM_RSA_PAD_ANSI 0x00000004 #define SC_ALGORITHM_RSA_PAD_ISO9796 0x00000008 #define SC_ALGORITHM_RSA_PAD_PSS 0x00000010 /* PKCS#1 v2.0 PSS */ #define SC_ALGORITHM_RSA_PAD_OAEP 0x00000020 /* PKCS#1 v2.0 OAEP */ #define SC_ALGORITHM_RSA_HASH_NONE 0x00000100 /* only applies to PKCS1 padding */ # example: SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_RAW flags = 80000101; #example: SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_PAD_PKCS1 flags = 80000002; } For V5_0 and v5_3 cards, use sc_get_max_send_size and sc_get_max_recv_size which takes care or reader sizes even on Windows where SCardControl can not get PART_10 sizes. (commit eddea6f3c2d3dafc2c09eba6695c745a61b5186f on Windows forces reader sizes to 255, 256 in reader-pcsc.c if not already set. It should not do this, but leave that up to card drivers.) pkcs15-cardos.c added: New file, pkcs15-cardos.c, added as emulation only for CardOS V5_0 and V5_3 cards. sc_pkcs15_bind_internal is called to get tokenInfo as CardOS cards are substantially PKCS15 cards. But some V5_* cards have errors in the tokenInfo, Which are corrected. For older CardOS cards, card-cardos.c will create all the card->algorithms. Pkcs15-cardos.c will check for card->algorithms and if there are none, it will do the following: SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS is called twice. First to get the flags as set by user via opensc.conf card_atr or default flags set by the card driver. Then after determining from the tokenInfo what algorithms the card can support, the new flags are passed to card_cardos.c to create card->algorithms. https://atos.net/wp-content/uploads/2018/11/CT_181026_LPM_CardOS_V5-3_Multifunctionality_FS_en3_web.pdf says card supports: "“Command chaining” in accordance with ISO/IEC 7816-4" To take advantage of this with older readers, max_send_size and max_recv_size is now based on minimum of reader limits and "data_field_length" from card. This should allow card to work in older readers not capable of extended APDU. So far current cards we have seen do no appear to support “Command chaining”. Changes to be committed: modified: src/libopensc/Makefile.am modified: src/libopensc/Makefile.mak modified: src/libopensc/card-cardos.c modified: src/libopensc/cardctl.h modified: src/libopensc/cards.h new file: src/libopensc/pkcs15-cardos.c modified: src/libopensc/pkcs15-syn.c modified: src/libopensc/pkcs15-syn.h --- src/libopensc/Makefile.am | 4 +- src/libopensc/Makefile.mak | 2 +- src/libopensc/card-cardos.c | 336 +++++++++++++++++++++++++++++----- src/libopensc/cardctl.h | 18 ++ src/libopensc/cards.h | 1 + src/libopensc/pkcs15-cardos.c | 177 ++++++++++++++++++ src/libopensc/pkcs15-syn.c | 3 + src/libopensc/pkcs15-syn.h | 1 + 8 files changed, 492 insertions(+), 50 deletions(-) create mode 100644 src/libopensc/pkcs15-cardos.c diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 140665c8..9f0dda5e 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -51,7 +51,7 @@ libopensc_la_SOURCES_BASE = \ card-isoApplet.c card-masktech.c card-gids.c card-jpki.c \ card-npa.c card-esteid2018.c card-idprime.c \ \ - pkcs15-openpgp.c pkcs15-starcert.c \ + pkcs15-openpgp.c pkcs15-starcert.c pkcs15-cardos.c \ pkcs15-tcos.c pkcs15-esteid.c pkcs15-gemsafeGPK.c \ pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \ pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ @@ -134,7 +134,7 @@ TIDY_FILES = \ card-isoApplet.c card-masktech.c card-jpki.c \ card-npa.c card-esteid2018.c card-idprime.c \ \ - pkcs15-openpgp.c \ + pkcs15-openpgp.c pkcs15-cardos.c \ pkcs15-tcos.c pkcs15-esteid.c \ pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c \ pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \ diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak index 2e3c30c2..1b0ff45c 100644 --- a/src/libopensc/Makefile.mak +++ b/src/libopensc/Makefile.mak @@ -29,7 +29,7 @@ OBJECTS = \ card-masktech.obj card-gids.obj card-jpki.obj \ card-npa.obj card-esteid2018.obj card-idprime.obj \ \ - pkcs15-openpgp.obj pkcs15-starcert.obj \ + pkcs15-openpgp.obj pkcs15-starcert.obj pkcs15-cardos.obj \ pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-gemsafeGPK.obj \ pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \ pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \ diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index 306822b9..4ef6ead0 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -53,13 +53,42 @@ static const 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}, + { "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL}, + { "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL}, { NULL, NULL, NULL, 0, 0, NULL } }; -static unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS]; -static unsigned int algorithm_ids_in_tokeninfo_count=0; +/* private data for cardos driver */ +typedef struct cardos_data { + /* constructed internally */ + unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS]; + unsigned int algorithm_ids_in_tokeninfo_count; + unsigned long flags; /* flags used by init to create sc_algorithms */ + unsigned long ec_flags; + unsigned long ext_flags; + int rsa_2048; + const sc_security_env_t * sec_env; +} cardos_data_t; + +/* copied from iso7816.c */ +static void fixup_transceive_length(const struct sc_card *card, + struct sc_apdu *apdu) +{ + if (card == NULL || apdu == NULL) { + return; + } + + if (apdu->lc > sc_get_max_send_size(card)) { + /* The lower layers will automatically do chaining */ + apdu->flags |= SC_APDU_FLAGS_CHAINING; + } + + if (apdu->le > sc_get_max_recv_size(card)) { + /* The lower layers will automatically do a GET RESPONSE, if possible. + * All other workarounds must be carried out by the upper layers. */ + apdu->le = sc_get_max_recv_size(card); + } +} static int cardos_match_card(sc_card_t *card) { @@ -79,6 +108,8 @@ static int cardos_match_card(sc_card_t *card) return 1; if (card->type == SC_CARD_TYPE_CARDOS_V5_0) return 1; + if (card->type == SC_CARD_TYPE_CARDOS_V5_3) + return 1; if (card->type == SC_CARD_TYPE_CARDOS_M4_2) { int rv; sc_apdu_t apdu; @@ -159,42 +190,102 @@ static int cardos_have_2048bit_package(sc_card_t *card) return 0; } + +/* Called from cardos_init for old cards, from cardos_cardctl_parsed_token_info for new cards */ +/* TODO see if works from old cards too */ +static int cardos_add_algs(sc_card_t *card, unsigned long flags, unsigned long ec_flags, unsigned long ext_flags) +{ + + cardos_data_t * priv = (cardos_data_t *)card->drv_data; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + _sc_card_add_rsa_alg(card, 512, flags, 0); + _sc_card_add_rsa_alg(card, 768, flags, 0); + _sc_card_add_rsa_alg(card, 1024, flags, 0); + if (priv->rsa_2048 == 1) { + _sc_card_add_rsa_alg(card, 1280, flags, 0); + _sc_card_add_rsa_alg(card, 1536, flags, 0); + _sc_card_add_rsa_alg(card, 1792, flags, 0); + _sc_card_add_rsa_alg(card, 2048, flags, 0); + } + + if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { + /* Starting with CardOS 5, the card supports PIN query commands */ + card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; + _sc_card_add_rsa_alg(card, 3072, flags, 0); + _sc_card_add_rsa_alg(card, 4096, flags, 0); + } + + /* TODO need to get sizes from supported_algos too */ + if (ec_flags != 0) { + _sc_card_add_ec_alg(card, 256, ec_flags, priv->ext_flags, NULL); + _sc_card_add_ec_alg(card, 384, ec_flags, priv->ext_flags, NULL); + } + + return 0; +} + static int cardos_init(sc_card_t *card) { - unsigned long flags = 0, rsa_2048 = 0; + cardos_data_t * priv = NULL; + unsigned long flags = 0; size_t data_field_length; sc_apdu_t apdu; u8 rbuf[2]; int r; + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + priv = calloc(1, sizeof(cardos_data_t)); + if (!priv) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + card->drv_data = priv; + card->name = "Atos CardOS"; card->cla = 0x00; - /* Set up algorithm info. */ - flags = 0; - if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { - flags |= SC_ALGORITHM_RSA_PAD_PKCS1; + /* let user override flags and type from opensc.conf */ + /* user can override card->type too.*/ + if (card->flags) { + flags = card->flags; } else { - flags |= SC_ALGORITHM_RSA_RAW - | SC_ALGORITHM_RSA_HASH_NONE - | SC_ALGORITHM_NEED_USAGE - | SC_ALGORITHM_ONBOARD_KEY_GEN; + + /* Set up algorithm info. */ + flags = 0; + if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { + flags |= SC_ALGORITHM_RSA_PAD_PKCS1; + } else if(card->type == SC_CARD_TYPE_CARDOS_V5_3) { + flags |= SC_ALGORITHM_RSA_RAW + | SC_ALGORITHM_RSA_HASH_NONE + | SC_ALGORITHM_ONBOARD_KEY_GEN; + } else { + flags |= SC_ALGORITHM_RSA_RAW + | SC_ALGORITHM_RSA_HASH_NONE + | SC_ALGORITHM_NEED_USAGE + | SC_ALGORITHM_ONBOARD_KEY_GEN; + } } + priv->flags = flags; + if (card->type == SC_CARD_TYPE_CARDOS_M4_2) { r = cardos_have_2048bit_package(card); if (r < 0) return SC_ERROR_INVALID_CARD; if (r == 1) - rsa_2048 = 1; + priv->rsa_2048 = 1; card->caps |= SC_CARD_CAP_APDU_EXT; - } else if (card->type == SC_CARD_TYPE_CARDOS_M4_3 + } else if (card->type == SC_CARD_TYPE_CARDOS_M4_3 || card->type == SC_CARD_TYPE_CARDOS_M4_2B || card->type == SC_CARD_TYPE_CARDOS_M4_2C || card->type == SC_CARD_TYPE_CARDOS_M4_4 - || card->type == SC_CARD_TYPE_CARDOS_V5_0) { - rsa_2048 = 1; + || card->type == SC_CARD_TYPE_CARDOS_V5_0 + || card->type == SC_CARD_TYPE_CARDOS_V5_3) { + priv->rsa_2048 = 1; card->caps |= SC_CARD_CAP_APDU_EXT; + /* TODO check this. EC only if in supported_algo */ + priv->ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; } /* probe DATA FIELD LENGTH with GET DATA */ @@ -202,6 +293,7 @@ static int cardos_init(sc_card_t *card) apdu.le = sizeof rbuf; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); + r = sc_transmit_apdu(card, &apdu); if (r < 0) LOG_TEST_RET(card->ctx, @@ -216,34 +308,99 @@ static int cardos_init(sc_card_t *card) return SC_ERROR_INVALID_CARD; data_field_length = ((rbuf[0] << 8) | rbuf[1]); - /* strip the length of possible Lc and Le bytes */ - if (card->caps & SC_CARD_CAP_APDU_EXT) - card->max_send_size = data_field_length - 6; - else - card->max_send_size = data_field_length - 3; - /* strip the length of SW bytes */ - card->max_recv_size = data_field_length - 2; + /* TODO is this really needed? strip the length of possible Lc and Le bytes */ - _sc_card_add_rsa_alg(card, 512, flags, 0); - _sc_card_add_rsa_alg(card, 768, flags, 0); - _sc_card_add_rsa_alg(card, 1024, flags, 0); - if (rsa_2048 == 1) { - _sc_card_add_rsa_alg(card, 1280, flags, 0); - _sc_card_add_rsa_alg(card, 1536, flags, 0); - _sc_card_add_rsa_alg(card, 1792, flags, 0); - _sc_card_add_rsa_alg(card, 2048, flags, 0); + /* Use Min card sizes and reader too. for V5_3 at least*/ + + if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "data_field_length:%"SC_FORMAT_LEN_SIZE_T"u " + "card->reader->max_send_size:%"SC_FORMAT_LEN_SIZE_T"u " + "card->reader->max_recv_size:%"SC_FORMAT_LEN_SIZE_T"u %s", + data_field_length, card->reader->max_send_size, card->reader->max_recv_size, + (card->caps & SC_CARD_CAP_APDU_EXT) ? "SC_CARD_CAP_APDU_EXT" : " "); + + if (card->caps & SC_CARD_CAP_APDU_EXT) { + card->max_send_size = data_field_length - 6; +#ifdef _WIN32 + /* Windows does not support PCSC PART_10 and may have forced reader to 255/256 + * https://github.com/OpenSC/OpenSC/commit/eddea6f3c2d3dafc2c09eba6695c745a61b5186f + * may have reset this. if so, will override and force extended + * Most, if not all, cardos cards do extended, but not chaining + */ + if (card->reader->max_send_size == 255 && card->reader->max_recv_size == 256) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "reseting reader to use data_field_length"); + card->reader->max_send_size = data_field_length - 6; + card->reader->max_recv_size = data_field_length - 3; + } +#endif + } else + card->max_send_size = data_field_length - 3; + + card->max_send_size = sc_get_max_send_size(card); /* include reader sizes and protocol */ + card->max_recv_size = data_field_length - 2; + card->max_recv_size = sc_get_max_recv_size(card); + } else { + /* old way, disregards reader capabilities */ + if (card->caps & SC_CARD_CAP_APDU_EXT) + card->max_send_size = data_field_length - 6; + else + card->max_send_size = data_field_length - 3; + /* strip the length of SW bytes */ + card->max_recv_size = data_field_length - 2; } - if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { - /* Starting with CardOS 5, the card supports PIN query commands */ - card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO; - _sc_card_add_rsa_alg(card, 3072, flags, 0); - _sc_card_add_rsa_alg(card, 4096, flags, 0); + /*for new cards, wait till after sc_pkcs15_bind_internal reads tokeninfo */ + if (card->type != SC_CARD_TYPE_CARDOS_V5_0 && card->type != SC_CARD_TYPE_CARDOS_V5_3) { + r = cardos_add_algs(card, flags, 0, 0); } return 0; } +static int cardos_pass_algo_flags(sc_card_t *card, struct sc_cardctl_cardos_pass_algo_flags * ptr) +{ + cardos_data_t * priv = (cardos_data_t *)card->drv_data; + int r = 0; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + switch (ptr->pass) { + case 1: + ptr->card_flags = card->flags; + ptr->used_flags = priv->flags; + ptr->ec_flags = priv->ec_flags; + ptr->ext_flags = priv->ext_flags; + break; + case 2: + r = cardos_add_algs(card,ptr->new_flags, ptr->ec_flags, ptr->ext_flags); + break; + default: + sc_log(card->ctx, "ptr->pass: %ul invalid", ptr->pass); + r = SC_ERROR_INTERNAL; + } + LOG_FUNC_RETURN(card->ctx, r); +} + + +static int cardos_finish(sc_card_t *card) +{ + int r = 0; + + if (card) + return 0; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + /* free priv data */ + if (card->drv_data) { /* priv */ + free(card->drv_data); + card->drv_data = NULL; + } + + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); +} + + + static const struct sc_card_error cardos_errors[] = { /* some error inside the card */ /* i.e. nothing you can do */ @@ -772,8 +929,9 @@ cardos_set_security_env(sc_card_t *card, const sc_security_env_t *env, int se_num) { + cardos_data_t* priv = (cardos_data_t*)card->drv_data; sc_apdu_t apdu; - u8 data[6]; + u8 data[9]; int key_id, r; assert(card != NULL && env != NULL); @@ -782,6 +940,15 @@ cardos_set_security_env(sc_card_t *card, sc_log(card->ctx, "No or invalid key reference\n"); return SC_ERROR_INVALID_ARGUMENTS; } + priv->sec_env = env; /* pass on to crypto routines */ + + /* key_ref includes card mechanism and key number + * But newer cards appear to get this some other way, + * We can use flags passed to know what OpenSC expects from the card + * and have derived what these machanisums are. + * Newer cards may change how this is done + */ + key_id = env->key_ref[0]; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); @@ -802,16 +969,39 @@ cardos_set_security_env(sc_card_t *card, return SC_ERROR_INVALID_ARGUMENTS; } - if (card->type == SC_CARD_TYPE_CARDOS_V5_0) { + if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { + /* some cards appear to have key_id be both Cryptographic mechanism reference 4 bits + * and key_ref 4 bits. But this limits card to 16 keys. + * TODO may need to be looked at at a later time + */ /* Private key reference */ data[0] = 0x84; data[1] = 0x01; - data[2] = key_id; + data[2] = key_id & 0x0F; /* Usage qualifier byte */ data[3] = 0x95; data[4] = 0x01; data[5] = 0x40; apdu.lc = apdu.datalen = 6; + if (key_id & 0xF0) { + /* Cryptographic mechanism reference */ + data[6] = 0x80; + data[7] = 0x01; + data[8] = key_id & 0xF0; + apdu.lc = apdu.datalen = 9; + } else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { + /* TODO this may only apply to c903 cards */ + /* TODO or only for cards without any supported_algos or EIDComplient only */ + data[6] = 0x80; + data[7] = 0x01; + data[8] = 0x10; + apdu.lc = apdu.datalen = 9; + } else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW) { + data[6] = 0x80; + data[7] = 0x01; + data[8] = 0x30; + apdu.lc = apdu.datalen = 9; + } } else { data[0] = 0x83; data[1] = 0x01; @@ -839,12 +1029,12 @@ cardos_set_security_env(sc_card_t *card, sc_log(card->ctx, "is signature"); sc_log(card->ctx, "Adding ID %d at index %d", algorithm_id, algorithm_id_count); - algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id; + priv->algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id; } sc_log(card->ctx, "reference=%d, mechanism=%d, operations=%d, algo_ref=%d", alg.reference, alg.mechanism, alg.operations, alg.algo_ref); } - algorithm_ids_in_tokeninfo_count = algorithm_id_count; + priv -> algorithm_ids_in_tokeninfo_count = algorithm_id_count; } while (0); LOG_FUNC_RETURN(card->ctx, r); @@ -859,6 +1049,7 @@ static int do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, u8 *out, size_t outlen) { + /* cardos_data_t* priv = (cardos_data_t*)card->drv_dataa */; int r; sc_apdu_t apdu; @@ -873,6 +1064,7 @@ do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, apdu.data = data; apdu.lc = datalen; apdu.datalen = datalen; + fixup_transceive_length(card, &apdu); r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); @@ -886,6 +1078,7 @@ static int cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, u8 *out, size_t outlen) { + cardos_data_t* priv; int r; sc_context_t *ctx; int do_rsa_pure_sig = 0; @@ -895,8 +1088,21 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, assert(card != NULL && data != NULL && out != NULL); ctx = card->ctx; + priv = (cardos_data_t*)card->drv_data; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); + /* sec_env has algorithm_flags set from sc_get_encoding_flags sec_flags + * If flags are set correctly we don't need to test anything + * TODO this assumes RSA is PSS, PKCS1 or RAW and we are passing + * the correct data. Should work for ECDSA too. + * use for V5 cards and TODO should for older cards too + */ + if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { + + r = do_compute_signature(card, data, datalen, out, outlen); + LOG_FUNC_RETURN(ctx, r); + } + /* There are two ways to create a signature, depending on the way, * the key was created: RSA_SIG and RSA_PURE_SIG. * We can use the following reasoning, to determine the correct operation: @@ -913,8 +1119,8 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, */ /* check the the algorithmIDs from the AlgorithmInfo */ - for (i = 0; i < algorithm_ids_in_tokeninfo_count; ++i) { - unsigned int id = algorithm_ids_in_tokeninfo[i]; + for (i = 0; i < priv->algorithm_ids_in_tokeninfo_count; ++i) { + unsigned int id = priv->algorithm_ids_in_tokeninfo[i]; if (id == 0x86 || id == 0x88) { do_rsa_sig = 1; } else if (id == 0x8C || id == 0x8A) { @@ -985,10 +1191,41 @@ cardos_decipher(struct sc_card *card, const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen) { + cardos_data_t* priv = (cardos_data_t*)card->drv_data; int r; size_t card_max_send_size = card->max_send_size; size_t reader_max_send_size = card->reader->max_send_size; + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + /* 5.3 supports command chaining. Others may also + * card_max_send_size for 5.3 is already based on reader max_send_size */ + + if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) { + + r = iso_ops->decipher(card, crgram, crgram_len, out, outlen); + /* + * 5.3 supports RAW as well as PKCS1 and PSS + * decription may strip padding if card supports it + * with cards that support RAW, it always appears to + * drop first 00 that is start of padding. + */ + + if (r > 0 && priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_RAW) { + size_t rsize = r; + /* RSA RAW crgram_len == modlen */ + /* removed padding is always > 1 byte */ + /* add back missing leading zero if card dropped it */ + if (rsize == crgram_len - 1 && rsize < outlen) { + memmove(out+1, out, rsize); + out[0] =0x00; + r++; + } + } + + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); + } + if (sc_get_max_send_size(card) < crgram_len + 1) { /* CardOS doesn't support chaining for PSO:DEC, so we just _hope_ * that both, the reader and the card are able to send enough data. @@ -1003,7 +1240,7 @@ cardos_decipher(struct sc_card *card, card->max_send_size = card_max_send_size; card->reader->max_send_size = reader_max_send_size; - return r; + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); } static int @@ -1188,7 +1425,7 @@ static int cardos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) return SC_ERROR_INTERNAL; - if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0)) { + if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3)) { /* cache serial number */ memcpy(card->serialnr.value, rbuf, 8); card->serialnr.len = 8; @@ -1223,6 +1460,9 @@ cardos_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) case SC_CARDCTL_CARDOS_GENERATE_KEY: return cardos_generate_key(card, (struct sc_cardctl_cardos_genkey_info *) ptr); + case SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS: + return cardos_pass_algo_flags(card, + (struct sc_cardctl_cardos_pass_algo_flags *) ptr); case SC_CARDCTL_LIFECYCLE_GET: return cardos_lifecycle_get(card, (int *) ptr); case SC_CARDCTL_LIFECYCLE_SET: @@ -1279,7 +1519,8 @@ cardos_logout(sc_card_t *card) || card->type == SC_CARD_TYPE_CARDOS_M4_2C || card->type == SC_CARD_TYPE_CARDOS_M4_3 || card->type == SC_CARD_TYPE_CARDOS_M4_4 - || card->type == SC_CARD_TYPE_CARDOS_V5_0) { + || card->type == SC_CARD_TYPE_CARDOS_V5_0 + || card->type == SC_CARD_TYPE_CARDOS_V5_3) { sc_apdu_t apdu; int r; sc_path_t path; @@ -1309,6 +1550,7 @@ static struct sc_card_driver * sc_get_driver(void) cardos_ops = *iso_ops; cardos_ops.match_card = cardos_match_card; cardos_ops.init = cardos_init; + cardos_ops.finish = cardos_finish; cardos_ops.select_file = cardos_select_file; cardos_ops.create_file = cardos_create_file; cardos_ops.set_security_env = cardos_set_security_env; diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h index 0c68c4c6..10ddfa05 100644 --- a/src/libopensc/cardctl.h +++ b/src/libopensc/cardctl.h @@ -83,6 +83,7 @@ enum { SC_CARDCTL_CARDOS_PUT_DATA_OCI, SC_CARDCTL_CARDOS_PUT_DATA_SECI, SC_CARDCTL_CARDOS_GENERATE_KEY, + SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, /* * Starcos SPK 2.3 specific calls @@ -350,6 +351,14 @@ typedef struct sc_cardctl_pkcs11_init_pin { size_t pin_len; } sc_cardctl_pkcs11_init_pin_t; +/* + * Generic cardctl - card driver can examine token info + */ +struct sc_cardctl_parsed_token_info { + unsigned int flags; + struct sc_pkcs15_tokeninfo * tokeninfo; +}; + /* * GPK lock file. * Parent DF of file must be selected. @@ -419,6 +428,15 @@ struct sc_cardctl_cardos_genkey_info { unsigned short fid; }; +struct sc_cardctl_cardos_pass_algo_flags { + unsigned int pass; + unsigned long card_flags; /* from card->flags i.e. user set */ + unsigned long used_flags; /* as set by default */ + unsigned long new_flags; /* set in pkcs15-cardos.c */ + unsigned long ec_flags; /* for EC keys */ + unsigned long ext_flags; /* for EC keys */ +}; + /* * Incrypto34 PIN info */ diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index cb0501c3..8d58fb93 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -47,6 +47,7 @@ enum { SC_CARD_TYPE_CARDOS_CIE_V1, /* Italian CIE (eID) v1 */ SC_CARD_TYPE_CARDOS_M4_4, SC_CARD_TYPE_CARDOS_V5_0, + SC_CARD_TYPE_CARDOS_V5_3, /* flex/cyberflex drivers */ SC_CARD_TYPE_FLEX_BASE = 2000, diff --git a/src/libopensc/pkcs15-cardos.c b/src/libopensc/pkcs15-cardos.c new file mode 100644 index 00000000..752631ce --- /dev/null +++ b/src/libopensc/pkcs15-cardos.c @@ -0,0 +1,177 @@ +/* + * PKCS15 emulation layer for CardOS cards + * Adapted from PKCS15 emulation layer for IAS/ECC card. + * + * Copyright (C) 2020, Douglas E. Engert + * Copyright (C) 2016, Viktor Tarasov + * Copyright (C) 2004, Bud P. Bruegger + * Copyright (C) 2004, Antonino Iacono + * Copyright (C) 2003, Olaf Kirch + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "internal.h" +#include "pkcs15.h" + + +/* + * Called after sc_pkcs15_bind_internal + * Create new flags based on supported_algos. + */ +static int cardos_fix_token_info(sc_pkcs15_card_t *p15card) +{ + sc_card_t *card; + struct sc_supported_algo_info (*saa)[SC_MAX_SUPPORTED_ALGORITHMS]; + struct sc_supported_algo_info *sa; + struct sc_cardctl_cardos_pass_algo_flags *passed = NULL; + int r = 0; + int i; + + card = p15card->card; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + + passed = calloc(1, sizeof(struct sc_cardctl_cardos_pass_algo_flags)); + if (!passed) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY); + + passed->pass = 1; /* get used_flags and card_flags from card */ + r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed); + if (r < 0) { + free(passed); + LOG_FUNC_RETURN(card->ctx, r); + } + + saa = &(p15card->tokeninfo->supported_algos); + + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Original Flags: 0x%8.8lx card->flags:0x%8.8lx", passed->used_flags, passed->card_flags); + + if (passed->card_flags) { /* user forced the flags, use them */ + passed->new_flags = passed->card_flags; /* from card_atr flags */ + } else { + + for (i = 0, sa = saa[0]; i < SC_MAX_SUPPORTED_ALGORITHMS; i++, sa++) { + + if (sa->reference == 0 && sa->reference == 0 && sa->mechanism == 0 + && sa->operations == 0 && sa->algo_ref == 0) + break; + + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "supported_algos[%d] mechamism:0x%8.8x", i, sa->mechanism); + switch(sa->mechanism) { + case 0x01 : + /* + * Card appears to use lower 4 bits of reference as key, and upper + * 4 bits as mech for card. + * Also has a bug if mechanism = 1 (CKM_RSA_PKCS1) and reference 0x10 + * bit is set mechanism should be 3 (CKM_RSA_X_509) + * correct the mechanism in tokenInfo + */ + if (sa->reference & 0x10) { + sc_log(card->ctx, "Changeing mechanism to CKM_RSA_X_509 based on reference"); + passed->new_flags |= SC_ALGORITHM_RSA_RAW + | SC_ALGORITHM_RSA_PAD_NONE; + sa->mechanism = 0x03; + } else + passed->new_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; + break; + case 0x03 : + passed->new_flags |= SC_ALGORITHM_RSA_RAW + | SC_ALGORITHM_RSA_PAD_NONE; + break; + case 0x06 : + passed->new_flags |= SC_ALGORITHM_RSA_HASH_SHA1; + break; + case 0x1041: + passed->ec_flags |= SC_ALGORITHM_ECDSA_RAW; + /* no old_ec_flags */ + /* TODO turn on sizes from ec curves OIDS */ + break; + default: + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "UNKNOWN MECH: 0x%8.8x", sa->mechanism); + } + + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", + passed->new_flags, passed->ec_flags); + } + + if (passed->new_flags == 0) { + if (p15card->tokeninfo && p15card->tokeninfo->flags & SC_PKCS15_TOKEN_EID_COMPLIANT) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EID_COMPLIANT flag found"); + passed->new_flags = (passed->used_flags & ~SC_ALGORITHM_SPECIFIC_FLAGS) | SC_ALGORITHM_RSA_PAD_PKCS1; + } else + passed->new_flags = passed->used_flags; /* from default cardos_init */ + } + } + + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Final New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", passed->new_flags, passed->ec_flags); + + passed->pass = 2; /* tell card driver to use the new flags */ + r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed); + + free(passed); + LOG_FUNC_RETURN(card->ctx, r); +} + +static int +cardos_pkcs15emu_detect_card(sc_pkcs15_card_t *p15card) +{ + if (p15card->card->type < SC_CARD_TYPE_CARDOS_BASE) + return SC_ERROR_WRONG_CARD; + + if (p15card->card->type >= SC_CARD_TYPE_CARDOS_BASE + 1000) + return SC_ERROR_WRONG_CARD; + + return SC_SUCCESS; +} + + +static int +sc_pkcs15emu_cardos_init(struct sc_pkcs15_card *p15card, struct sc_aid *aid) +{ + sc_card_t *card = p15card->card; + int r; + + LOG_FUNC_CALLED(card->ctx); + + r = sc_pkcs15_bind_internal(p15card, aid); + LOG_TEST_RET(card->ctx, r, "sc_pkcs15_bind_internal failed"); + + /* If card has created algorithms, return */ + sc_log(card->ctx, " card->algorithms:%p card->algorithm_count:%d", card->algorithms, card->algorithm_count); + if (!card->algorithms && card->algorithm_count == 0) { + r = cardos_fix_token_info(p15card); + } + + LOG_FUNC_RETURN(card->ctx, r); +} + + +int +sc_pkcs15emu_cardos_init_ex(struct sc_pkcs15_card *p15card, struct sc_aid *aid) +{ + if (cardos_pkcs15emu_detect_card(p15card)) + return SC_ERROR_WRONG_CARD; + + return sc_pkcs15emu_cardos_init(p15card, aid); +} diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index aba6f52c..ecd06b13 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -60,6 +60,7 @@ struct sc_pkcs15_emulator_handler builtin_emulators[] = { { "coolkey", sc_pkcs15emu_coolkey_init_ex }, { "din66291", sc_pkcs15emu_din_66291_init_ex }, { "esteid2018", sc_pkcs15emu_esteid2018_init_ex }, + { "cardos", sc_pkcs15emu_cardos_init_ex }, { NULL, NULL } }; @@ -95,6 +96,8 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card) case SC_CARD_TYPE_PIV_II_NEO: case SC_CARD_TYPE_PIV_II_YUBIKEY4: case SC_CARD_TYPE_ESTEID_2018: + case SC_CARD_TYPE_CARDOS_V5_0: + case SC_CARD_TYPE_CARDOS_V5_3: return 1; default: diff --git a/src/libopensc/pkcs15-syn.h b/src/libopensc/pkcs15-syn.h index ccaf693c..a15e0d95 100644 --- a/src/libopensc/pkcs15-syn.h +++ b/src/libopensc/pkcs15-syn.h @@ -54,6 +54,7 @@ int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *, struct sc_aid *); int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); +int sc_pkcs15emu_cardos_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *); struct sc_pkcs15_emulator_handler { const char *name; From a49a64ec79e8129c70b1d16f34acc8562e5ca4be Mon Sep 17 00:00:00 2001 From: Michael Weiser Date: Thu, 7 May 2020 21:52:17 +0200 Subject: [PATCH 180/189] unittests: Fix out-of-source build Commit 4fd34e28eaf1 unintentionally replaced top_builddir with top_srcdir when refactoring flags variables in Makefile.am. This causes out-of-source builds to fail. Restore top_builddir in LDADD. Also, remove a superfluous -L flag also referencing top_srcdir from AM_CFLAGS while at it. Signed-off-by: Michael Weiser Closes #2027. --- src/tests/unittests/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tests/unittests/Makefile.am b/src/tests/unittests/Makefile.am index 0795b62a..e2887d73 100644 --- a/src/tests/unittests/Makefile.am +++ b/src/tests/unittests/Makefile.am @@ -12,11 +12,10 @@ TESTS = asn1 simpletlv noinst_HEADERS = torture.h AM_CFLAGS = -I$(top_srcdir)/src/ \ - -L$(top_srcdir)/src/libopensc/ \ $(CODE_COVERAGE_CFLAGS) \ $(CMOCKA_CFLAGS) AM_CPPFLAGS =$(CODE_COVERAGE_CPPFLAGS) -LDADD = $(top_srcdir)/src/libopensc/libopensc.la \ +LDADD = $(top_builddir)/src/libopensc/libopensc.la \ $(CODE_COVERAGE_LIBS) \ $(OPTIONAL_OPENSSL_LIBS) \ $(CMOCKA_LIBS) From 7add7e9dedf41db4f8c5182d340c50ce9e9ca275 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sun, 10 May 2020 01:01:34 +0200 Subject: [PATCH 181/189] fixed memory leak fixes https://oss-fuzz.com/testcase-detail/5738653415636992 --- src/libopensc/pkcs15-gemsafeV1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libopensc/pkcs15-gemsafeV1.c b/src/libopensc/pkcs15-gemsafeV1.c index 4e945157..d4280bb0 100644 --- a/src/libopensc/pkcs15-gemsafeV1.c +++ b/src/libopensc/pkcs15-gemsafeV1.c @@ -173,6 +173,7 @@ static int gemsafe_get_cert_len(sc_card_t *card) r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; + sc_file_free(file); /* Initial read */ r = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0); From c1eda420995baa300b6d7ffdaebc872521d0864b Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sun, 10 May 2020 01:14:00 +0200 Subject: [PATCH 182/189] oberthur: fixed current file state handling fixes https://oss-fuzz.com/testcase-detail/5644083327664128 --- src/libopensc/card-oberthur.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/libopensc/card-oberthur.c b/src/libopensc/card-oberthur.c index b692e724..530421a4 100644 --- a/src/libopensc/card-oberthur.c +++ b/src/libopensc/card-oberthur.c @@ -183,11 +183,13 @@ auth_select_aid(struct sc_card *card) sc_format_path("3F00", &tmp_path); sc_file_free(auth_current_df); + auth_current_df = NULL; rv = iso_ops->select_file(card, &tmp_path, &auth_current_df); LOG_TEST_RET(card->ctx, rv, "select parent failed"); sc_format_path("3F00", &card->cache.current_path); sc_file_free(auth_current_ef); + auth_current_ef = NULL; sc_file_dup(&auth_current_ef, auth_current_df); memcpy(data->aid, aidAuthentIC_V5, lenAidAuthentIC_V5); @@ -480,6 +482,7 @@ auth_select_file(struct sc_card *card, const struct sc_path *in_path, tmp_file->path.len -= 2; sc_file_free(auth_current_df); + auth_current_df = NULL; sc_file_dup(&auth_current_df, tmp_file); } else { @@ -487,10 +490,12 @@ auth_select_file(struct sc_card *card, const struct sc_path *in_path, sc_concatenate_path(&tmp_file->path, &auth_current_df->path, &path); sc_file_free(auth_current_df); + auth_current_df = NULL; sc_file_dup(&auth_current_df, tmp_file); } else { sc_file_free(auth_current_ef); + auth_current_ef = NULL; sc_file_dup(&auth_current_ef, tmp_file); sc_concatenate_path(&auth_current_ef->path, &auth_current_df->path, &path); @@ -972,6 +977,7 @@ auth_create_file(struct sc_card *card, struct sc_file *file) } sc_file_free(auth_current_ef); + auth_current_ef = NULL; sc_file_dup(&auth_current_ef, file); LOG_FUNC_RETURN(card->ctx, rv); @@ -1845,8 +1851,15 @@ auth_pin_reset_oberthur_style(struct sc_card *card, unsigned int type, "%s: PIN CMD 'VERIFY' with pinpad failed", sc_strerror(rvv)); - if (auth_current_ef) - rv = iso_ops->select_file(card, &auth_current_ef->path, &auth_current_ef); + if (auth_current_ef) { + struct sc_file *ef = NULL; + rv = iso_ops->select_file(card, &auth_current_ef->path, &ef); + if (rv == SC_SUCCESS) { + sc_file_free(auth_current_ef); + auth_current_ef = ef; + } else + sc_file_free(ef); + } if (rv > 0) rv = 0; @@ -2053,6 +2066,10 @@ auth_update_binary(struct sc_card *card, unsigned int offset, int rv = 0; LOG_FUNC_CALLED(card->ctx); + + if (!auth_current_ef) + LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid auth_current_ef"); + sc_log(card->ctx, "offset %i; count %"SC_FORMAT_LEN_SIZE_T"u", offset, count); sc_log(card->ctx, "last selected : magic %X; ef %X", From 3af52cd1c6532edac6f378722983f422d4361033 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 7 May 2020 09:13:57 +0200 Subject: [PATCH 183/189] tests: Temporarily exclude goid-tool from manpage tests --- tests/test-manpage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-manpage.sh b/tests/test-manpage.sh index 9a43d422..a8d53d4c 100755 --- a/tests/test-manpage.sh +++ b/tests/test-manpage.sh @@ -2,7 +2,7 @@ SOURCE_PATH=../ # find all the manual pages in doc/tools -TOOLS=`find "${SOURCE_PATH}/doc/tools" -name "*.1.xml" | sed -E -e "s|.*/([a-z0-9-]*).*|\1|"` +TOOLS=`find "${SOURCE_PATH}/doc/tools" -name "*.1.xml" | sed -E -e "s|.*/([a-z0-9-]*).*|\1|" | grep -v goid-tool` ALL=1 for T in $TOOLS; do From e71b85867f7325c4c03db10a66f31ee826ddbce2 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 6 Apr 2020 15:42:30 +0200 Subject: [PATCH 184/189] macOS: added basic installer signing --- .github/add_signing_key.sh | 28 ++++++++++++++++++++++++++++ .github/remove_signing_key.sh | 8 ++++++++ .github/secrets.tar.enc | Bin 0 -> 7184 bytes .travis.yml | 11 +++++++++++ MacOSX/build-package.in | 32 ++++++++++++++++++++------------ 5 files changed, 67 insertions(+), 12 deletions(-) create mode 100755 .github/add_signing_key.sh create mode 100755 .github/remove_signing_key.sh create mode 100644 .github/secrets.tar.enc diff --git a/.github/add_signing_key.sh b/.github/add_signing_key.sh new file mode 100755 index 00000000..689e2cad --- /dev/null +++ b/.github/add_signing_key.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +set -ex -o xtrace + +pushd .github/ +tar xvf secrets.tar +KEY_CHAIN=mac-build.keychain + +# Create the keychain with a password +security create-keychain -p travis $KEY_CHAIN + +# Make the custom keychain default, so xcodebuild will use it for signing +security default-keychain -s $KEY_CHAIN + +# Unlock the keychain for one hour +security unlock-keychain -p travis $KEY_CHAIN +security set-keychain-settings -t 3600 -u $KEY_CHAIN + +# Add certificates to keychain and allow codesign to access them +curl -L https://developer.apple.com/certificationauthority/AppleWWDRCA.cer > AppleWWDRCA.cer +security import AppleWWDRCA.cer -k ~/Library/Keychains/$KEY_CHAIN -T /usr/bin/codesign +security import certificate.cer -k ~/Library/Keychains/$KEY_CHAIN -T /usr/bin/codesign +security import certificate.p12 -k ~/Library/Keychains/$KEY_CHAIN -P $KEY_PASSWORD -T /usr/bin/codesign +security unlock-keychain -p travis $KEY_CHAIN + +# https://docs.travis-ci.com/user/common-build-problems/#mac-macos-sierra-1012-code-signing-errors +security set-key-partition-list -S apple-tool:,apple: -s -k travis $KEY_CHAIN +popd diff --git a/.github/remove_signing_key.sh b/.github/remove_signing_key.sh new file mode 100755 index 00000000..218471c5 --- /dev/null +++ b/.github/remove_signing_key.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -ex -o xtrace + +pushd .github/ +security delete-keychain mac-build.keychain +rm -f certificate.cer certificate.p12 +popd diff --git a/.github/secrets.tar.enc b/.github/secrets.tar.enc new file mode 100644 index 0000000000000000000000000000000000000000..20690baa80af59f3f3abce8cda1e8356eb076e5d GIT binary patch literal 7184 zcmV+r9Pi`lsah|RSysDnstcN+J=&3tTuDP%*Y!Ee!NI8aqq_`~7v=DUJh)A>2*eGz zbq}(+^v?tq2sm`xB}M5lHCRO*~%UiU)$wIExj_l*ARU=h`8zVeib15h_(Qefae z5)`6ggve23jZPpNot>#-Zi8Llk_4L~0@K?%R%7FUoAd!=p z<78vB}q?SyS^EI;?iaeR@*V_07) zQe4x^&j>tywf%6KcA|*Y_jakps-2&7o1EjmFNhljJ3u(su%I7jZ~W}MIGRJhzdF4- z&*{sEsl+u^{fQ^oMJEDm(}}Nw2B6Ia>N+RY=?E*VV>IzI?fCl$rR%wT*LP%%En3x@ zfp5vJeH?i83-|((>o@nZ&)-w00SMPKZa^FifZr{oW)EJoaSk2tR?FI-AI~9nFnl9Z zBc*)S)#@4D%66GwecNlB##?Pn#V(T58_3bZXuR#&h>oX<>C&ce8Z?QT{;K7O!MXsw zH3X&75Tg&3zXehv#wc4w$sg2`WA8ZwKJ;^{U;{ck5<^2sX(5LSL{$LmQUqU5Z@xXw1w)`i z`AgZ1_TLw#q#o|$Ms_4y_C#l(-Tnj)3eSiDVXbA@Ll0>um9TyntopBl@iVhC|+%z+SdlTRud4`b1+# zcad|qgn0q@2@xXy-zAF)6v~UOisQ6HG)|}iY;H=ZSGGSAT;mwm#co2lXdij2Aq^d* zKcfJSq{hMHqhu1io`SY(+-RxwGZViF4ObUkpk%uoBttngZL=so?NsMP zjFmHLk+JtBz;Z55Xegt8pCjM|m%(L-Q#*n#Oc`^6tA&{w@`B;12*bSikq?F#KP2=M zmDA;%Vl|Y8i^&>!S2P0R*vY!jJ(D0GB*de)M!v;TC$&kHDaz_@`W5^#9N+1t@MNh) zior#ydzLGN#Qu2djVjOcH0zwGyoPrm!OZ;_WgC|zif(R73k69h=Fpg3xJKD57&X4T z-?pymPjNU~v9(r3J@zdC%VNXYZ2m1+>d#+Xl~Rghmiw-LS`e?YWcp_hT6%L~9c z(t3kCH4I$;`VyRk9egl8*4~X4)nucmGjNf$P@?nZ&GIWhRgB)Z#XGiDT>?XRGe-G| zf^-oqcTqi^=j56bx(8moW-8vJc?(n$2mW6FfQ?;Yup+-OL>qv}r2PgWz%w)#`B;)o z`L-uq0sTwl!$?+0eg&e#^m1EaG{_MWQY7!<-<;-{!)4>+k8lx~P@ABTk)Ujmjp%or zc$VrD@-RD&Z5Ic@S37X)IN;CF)lv2)yRXRH6La$;APBvwpsA}WcJjIp_m|~|sD{i6 z1Q`tYQ812yGHO>cRb`ocVH127RSbW7LAb{A@asT>#XNrxbc0N~kGzN%hvMX~Vle z${oeVZ_q*$R{fb{*(wzrkJT=i-`|Mj5hwJnq`3u-IM~qJXUt1NDistJoy&-2J*F`? zU{&gAAWY`)sp;RAnl}U_hHd|aK^X}$fi&t&K=3ErIA2mdcnatYZ};wqBZ@F-Z0k>9 z_Fudah&q^&Mkg0~+}y^$AI&Q4GUgQooWt0fEn885Fwc!PgWXjnJaZc|6XOE;Zv|>O;P(AJfz-{d(k{HgDMIwS z;&Q{jKf{aiAvS4eSWnKWlvotfwmwR{mK_76)pF0-i<*ATmXn)or5uiGTvnwNua3+3 znECLlDWShjjr-BysYc*$)$yYoi;fPxxgm^0vy8N4zhk%o#NRJMZW6Xqxo}n{`ko}TT%K2Xik2aTy!&;6yLmi#hY_a$qTt8 zgjt#{4C=6+7FhXD5NE|GC)z+k)!2=S%MO9P>Bts~;OGVvmYCAq0XXnd(0_2vn6pB^ojH#Q5f(qTA<(fjW#7Ilu=hVZ) z`fyjtRLtV_Qf-|9E_HSkPL8OcVG|uKwHGHzK3(IBXBy!6U9&s@5MHAb4%0yO1Rxp? z3bRQv1P1ycRUpZG07oG@d`erB>z&@aaQb)8dm`*edX-I6p_;c(tj9Wn3N8TR~BFRKd|3l2OgoDne8(30_}_aZ3M-GZH>bo5pJ z5JY4WiKj{ckECq77s1r%=+P`?62+SCzF`pBG!4(kL~6C`)n8{pifBW9T@Emlkk&O6 zk|n=?sS=jawh%h|kA=H2^9Tj>ZmZ&rzHBm1x+^0^K6o}x*QfY;ai~d$W_Se}4n_M+ zlk3CAIX?Gitm^Q5jmUrwa1e8pJpt$!Nvc$DO%%~iTy-l6|ENiot4aJW7yQC0TKZY0A! z)-hnkW7HT=WB%N7lpf{LCqL!hgg)HfVm$=>gc>Ra>u8HvdCaV_%yW;*Hl}HT0WfpI zf%%s8*+FnxJo~r6J(9DP_^w648;VFjlgdMb( zI6b@jqQ1KPB|~a33kc0b?o~kitaI9AJ2`DSb9Q7#I$!Tq!vpcF|J!r8xpYO;DSk~^ zKMp*n_ay2jmR==WS$^4xi_onY<)lT?<)YE|nvf-TG(*Y^ zE7^8M0GlMRRrSDt(@vE^mi+UN)$Q)Al5oYf87ZhsL+2vT*hfQ(HSW^8cTZkxV?uaN zWFS14#1_F|$#p9Fr_;x^h`{<#5%x^kX@$_Erx*vDX+YjlyK+F<2dCndHRYE3w!alR zw9UW`qEiEQqiR9qdNr$N zf{(u)kiR6%#NzAUBBFW-r=($d2(H!f-_f@xTa8?sEVcf_e>*gVfM!ZiILpDhOylM_WRSy-rf2G&Z_x#`}1O$7>xI~ZJDl_Y*W!fbY{r0j%K}xd6*}iP=+uiVQm^@EBT8Q+hGy>YgXwsbF7@ zize#Z>r{4O>{F8$+d}o^?$u%HIL#_`N9HaZGtKLV{e}?=f_*NUlmvCk07M}BdHj?u zqq)@klj09K++N8fq2-nO*7#X@KtY{hPyV6oiv-GV^V-ZxT8#-E3y8C~m3yc8gZcfg zFP(9Jn%KNXKN+PlYFx@XpmZ`rGn9}?TQJx9_Ms=OH6K^(L+eU$v^bJNQHkOExQ$SO zRgGduW1hj6e0Mdf*`4Ky^HGCuC(g0emZknECO=-WB!XP6jJ)@+J}YBAqF87ESkv(( zhc!lloWE$ZL`t){+9pqgw%vFK62AbI_Od3d{`6jDXRwFhsEB9XPOh(Smdz6!$e%lj zltygLpLBdWA$REWY6k6LU)-35iD{M!B)xcq-#|NswY(qyjy#|=cFtm=!O@DfHF8b& z3?`Q@@gCWe4}0xeCwGwPUG47=@87T0%y5&` z1NQKpH~^ul+N5sPsyO|^qx9dtMgq~T0&_Dhba-du4$}JUsP5RJA#X+LhX44qswQ#t zF^j)vICW>bd3Ub{7xqU}%ja%}lXCYpvu{8k65#Q%*10k{23?==GM)y1t!$VkC605(BuNb0ggZ`M3-_BedHD>UF zVcZyas-RltvZT93Gg-K?M%Da-4_Q>n6we}$`1tB))53ALX(aqdw(Uq~S$~QKxgbw}S`p7m+r^W}?VrxR& zu-?BZ=LSn-^)qn04>Kr(T%p>0q*KVhiN)}^x#X>Tl8)Azjpp7>?|^bS@ZP%u6?sQ` z-;O>6DVC?^r!)6jAVD5F@)hd2`}P2`l_#j$I({1y(PUx7@LhDqedy4Ugi|QT5mBp>Bg9NCGVV3Akm7?y#7JV|-2o1oJuoE(5==(gAvA`ExiIP2Pn(N#_ z^>|3h6AvbG(7b>CUcPj4Wxmb(%93fIkR7fhq$y&1MEvS&zll?TnhIod8FGL>)77^P z9t0{mF`PX(>P;|s3+4f&E1|P>76g2H9wb61)}AZgpzuFUev$cfX!NATB<$x}J5|&b z0g9||$Zyu!NdX;rcbu$U9j_f^1RD@*e}3%;(yRM0=Ky-Al0pP;QsM>~%S0@R<90p$ z#BLe6*VKO)vc0J=#TZ<)Rcme}yXWfW8_ltIku=zDHPQLQ3=!Y5tn#x=LkVj>tWnM7 ziuu>peS9NEnh#a){(PDWYPjI(JjQ%fLub-f!@bzK8q!bcfIMAXG9ZcnasYc`VmGlR zlOV>+vU(D@gn}_UT4`L_MYLt*+8!Uc@hyom^VZD}ygeJ9(rJ&!EX9CE6Ge!&a10{W zUZh)yS=3l-)YAPHjeOl+_KkYzBa4eXtBR}<(t3)-K=G+ghJ0fAn%xcB0#sVld31YCVhkGVfq5D4eE@T{w0$kOC2`5M4earYw)flWEzt;_h7rxj31ouNgHl@T&hb*yKD%sf; zoJC>8K|wmrBkMk!PDZ=q1{KkLVnqcFWH2$YmVv(`S3G4KY_L#XlhT8iCa%)eE$RZ; zLI8sPt)^k3v?_8`w1WY5?7;q_mU)46Jh@W2q0vC-pRoAwC2qg3amzGbD%14z5ey!m zACIR=bRa%(u0zPm|C6-WL&BU3=X}Pj^4u${$_i+0Gm!U&DONHNr=)xiT*EDFsp9sB zS^{g>~d0XhV3sC^xDmvO2Hebk$dXHAYio&%O^om`s>A-jrbBP zJnZRQdwaOl*IxDB2$_=q2?77Nbrg29BOu)A)j^5a9k09#0N|><7W+wcoH@{js_T{n ze%$;EAe7nTo&x$*;A^3jo|DDBqB)5y!^eDmOG{Mva~6p0RzvOTGB~#1W>MP4@^L(f z`Qn>wa&RwKN_Y8(AU)uxkcsP?*p!KAtIx5>2M{}%MMt9c1gGhCMDAO_Xaa9AFQ z{fKuz(+SRX?)@QC9AXnQkUNsAxU0SD@F1I2J@Iv-$=?^>t$XVyi4=Mm@s|1a9Wg_7 z!&7{wnNSNRVxL!?Nz37Z&zcIJ7A(-xzQ5JoX=~$Q>wt(y$}P)K>GU3>n9Ur&Ok$2_ zNglhWAJ(coaUxO>l=Nb_va1uKOk^Gc+%BMljgDm zKsEmS!}A!tTitR4nK!8jUD)FUs^9$|ZjdCRxH_mJL?ea7q&T63;4O)f6HqEivYZ+y z@{Kt)$sd;kcPkx=nDI1Z`k@z&vpUwDI9hw*y=g03cuO^sq{9Osg>cz)eCIUP#8ZkF zQDPtut(VwBKES(t4An70J`;VgrU~w_sSN(_cJFq(30B8>xdc#}yJjB|fEX)>4~@Kd zyu`#4QuM?l4AiN~C_4EfTs_>R;z>V#W(nHW;CW8)jb6DgSygKu!CCYd@A_3q)xgFa zLG|4}4Ri~@8bBE(fZl(jWp}@v5>|`PCAk|^VH1&F#pdcBu~}uQFyC6K6{p;WCOL#x zzp&as){L!>p5N03WPsz7C0&(iY{#nZ&oJuH2t?U)x6zrj9^!ZHo*9@Fa5x(dK=H7I zgA3x3jeu<@?lUoCldRvhfc9@J&k`;7r|#!>AD90Ph_2O=|ZP2GJ2V=VkHWX;_DqmWsV<}9yl@3r&) z{b5uBXyv{RK2O@+G^Q-zheQPu zsC%65PybHW3#4w?L9HJTrW8Z@<0z5?pw%{~BpMI8 ze?5$qJG|=&{<9@l?sY`tLp@J0HZOO) zr5WV#_nYVpqze9#$400RH6BnwMF1R92DtJ5vdp-7USTiGoBg~ZsZm?VSOMP3e0mgX zG-E-pT~XMe&Y!;uHTZ_A?)qg43^@A%Py@oKvqZ&MpAsf^1#GVf#(%J+yj>uLv58G% zdG2VXE;c1E9_@$5yG0Ru`rk+@vl#@q>Q|)#K=V@G#GDPdw^p*c8RwTct(Xznw?At4 zMK#Sjd(0k1fK84DbKv=frAlF6E(}x<-DkAbSmL(*#S}1ru3rH=-8{_+F20VmoAY!Z_Co3J_6D#hmLB0HjK$! z^7ro_QM&^kdf9Dvb2pz@mNCHZ^rw5vu+we|on4ok!;o0@tAlRt&X?x$u!X8FZkZo114*6+7O?#l1f_!0H%1V8UPZK&kZ+z^gr5 z)B`Rd6;L`Eac6830UnNZy@0{kd(vik9U?j6Z=_-F?;()CY4nIASz`c0k3r-E{a8-z zaPAc)Sb3pPV5~S+Ozvt{AcqDK9HH#&wkp%a1lRVwFXiuFwDDO^XmZF*5)lcu0Q35F zcHP^eM&Z1~e&ke+k&b}&J|7oT&UZMI1~zNp35XF#KPZqG9~b@jfs!vQKURoyDBZI* SaBxZ)51E~=H*~x>W!D!)c?@#^ literal 0 HcmV?d00001 diff --git a/.travis.yml b/.travis.yml index 23d5c7e3..873fb530 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,12 +65,17 @@ addons: before_install: # brew install gengetopt help2man cmocka ccache llvm; # export PATH="/usr/local/opt/ccache/libexec:/usr/local/opt/llvm/bin:$PATH"; + # add magic notarization flags for macOS, see https://github.com/akeru-inc/xcnotary/blob/master/README.md - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; brew uninstall libtool; brew install libtool; brew install gengetopt help2man cmocka ccache; export PATH="/usr/local/opt/ccache/libexec:$PATH"; + openssl aes-256-cbc -K $encrypted_3b9f0b9d36d1_key -iv $encrypted_3b9f0b9d36d1_iv -in .github/secrets.tar.enc -out .github/secrets.tar -d; + .github/add_signing_key.sh; + export OTHER_CODE_SIGN_FLAGS=--timestamp CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO CODE_SIGN_STYLE=Manual; + git clone https://github.com/frankmorgner/OpenSCToken.git; fi - if [ "${DO_SIMULATION}" = "cac" ]; then sudo apt-get install -y libglib2.0-dev libnss3-dev pkgconf libtool make autoconf autoconf-archive automake libsofthsm2-dev softhsm2 softhsm2-common help2man gnutls-bin libcmocka-dev libusb-dev libudev-dev flex libnss3-tools libssl-dev libpcsclite1; @@ -309,6 +314,10 @@ after_script: git config --global user.name "Travis CI"; .github/push_artifacts.sh "Travis CI build ${TRAVIS_JOB_NUMBER}"; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then + .github/remove_signing_key.sh; + rm -f .github/secrets.tar; + fi before_cache: - brew cleanup @@ -319,6 +328,8 @@ cache: directories: - $HOME/.m2/ - $HOME/Library/Caches/Homebrew + - openssl + - openpace - openssl_bin - openpace_bin - isetup diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index 53248ac7..fb9979c1 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -19,6 +19,13 @@ SDK_PATH=$(xcrun --sdk macosx --show-sdk-path) # Set SDK path export CFLAGS="$CFLAGS -isysroot $SDK_PATH -arch x86_64" +# xcodebuild doesn't read the environment variables +# transform them into parameters +P1="${CODE_SIGN_IDENTITY:+CODE_SIGN_IDENTITY=${CODE_SIGN_IDENTITY}}" +P2="${OTHER_CODE_SIGN_FLAGS:+OTHER_CODE_SIGN_FLAGS=${OTHER_CODE_SIGN_FLAGS}}" +P3="${CODE_SIGN_INJECT_BASE_ENTITLEMENTS:+CODE_SIGN_INJECT_BASE_ENTITLEMENTS=${CODE_SIGN_INJECT_BASE_ENTITLEMENTS}}" +P4="${CODE_SIGN_STYLE:+CODE_SIGN_STYLE=${CODE_SIGN_STYLE}}" + export SED=/usr/bin/sed PREFIX=/Library/OpenSC export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/lib/pkgconfig @@ -90,7 +97,7 @@ fi if ! test -e NotificationProxy; then git clone http://github.com/frankmorgner/NotificationProxy.git fi -xcodebuild -target NotificationProxy -configuration Release -project NotificationProxy/NotificationProxy.xcodeproj install DSTROOT=$BUILDPATH/target/Library/OpenSC/ +xcodebuild -target NotificationProxy -configuration Release -project NotificationProxy/NotificationProxy.xcodeproj install DSTROOT=$BUILDPATH/target/Library/OpenSC/ "$P1" "$P2" "$P3" "$P4" mkdir -p "$BUILDPATH/target/Applications" osacompile -o "$BUILDPATH/target/Applications/OpenSC Notify.app" "MacOSX/OpenSC_Notify.applescript" @@ -106,7 +113,7 @@ if (( xcodebuild -version | sed -En 's/Xcode[[:space:]]+([0-9]+)\.[0-9]*/\1/p' < test -L OpenSC.tokend/build/opensc-src || ln -sf ${BUILDPATH}/src OpenSC.tokend/build/opensc-src # Build and copy OpenSC.tokend - xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj install DSTROOT=${BUILDPATH}/target_tokend + xcodebuild -target OpenSC -configuration Deployment -project OpenSC.tokend/Tokend.xcodeproj install DSTROOT=${BUILDPATH}/target_tokend "$P1" $P2 "$P3" "$P4" else # https://github.com/OpenSC/OpenSC.tokend/issues/33 mkdir -p ${BUILDPATH}/target_tokend @@ -139,24 +146,25 @@ if test -e OpenSCToken; then cd OpenSCToken # make sure OpenSCToken builds with the same dependencies as before if ! test -e OpenSC; then - git clone --depth=1 ../../OpenSC + git clone --depth=1 file://$PWD/../../OpenSC else cd OpenSC && git pull && cd .. fi - if ! test -e openssl; then - git clone --depth=1 ../openssl - else - cd openssl && git pull && cd .. + mkdir -p build + if ! test -e build/openssl; then + # build/openssl/lib/libcrypto.a is hardcoded in OpenSCToken + ln -sf $BUILDPATH/openssl_bin/$PREFIX build/openssl + # in OpenSCToken's variant of OpenSC we still use OpenSSL flags from above fi - if ! test -e openpace; then - git clone --depth=1 ../openpace - else - cd openpace && git pull && cd .. + if ! test -e build/openpace; then + # build/openpace/lib/libeac.a is hardcoded in OpenSCToken + ln -sf $BUILDPATH/openpace_bin/$PREFIX build/openpace + # in OpenSCToken's variant of OpenSC we still use OpenPACE flags from above fi BP=${BUILDPATH} . ./bootstrap BUILDPATH=${BP} - xcodebuild -target OpenSCTokenApp -configuration Debug -project OpenSCTokenApp.xcodeproj install DSTROOT=${BUILDPATH}/target_token + xcodebuild -target OpenSCTokenApp -configuration Debug -project OpenSCTokenApp.xcodeproj install DSTROOT=${BUILDPATH}/target_token "$P1" "$P2" "$P3" "$P4" cd .. else # if no OpenSCToken is checked out, then we create a dummy package From 178c4a9eaa0be983093057cc9dfe49fa7e1d3124 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 9 Apr 2020 17:20:54 +0200 Subject: [PATCH 185/189] fixed checking for strlcat/strlcpy newer clang uses a definition rather than a function --- configure.ac | 3 ++- src/common/compat_strlcat.c | 2 +- src/common/compat_strlcat.h | 4 +++- src/common/compat_strlcpy.c | 2 +- src/common/compat_strlcpy.h | 4 +++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index f54093b0..61f24633 100644 --- a/configure.ac +++ b/configure.ac @@ -417,8 +417,9 @@ AC_FUNC_VPRINTF AC_CHECK_FUNCS([ \ getpass gettimeofday getline memset mkdir \ strdup strerror memset_s explicit_bzero \ - strlcpy strlcat strnlen sigaction + strnlen sigaction ]) +AC_CHECK_DECLS([strlcpy, strlcat], [], [], [[#include ]]) AC_CHECK_SIZEOF(void *) if test "${ac_cv_sizeof_void_p}" = 8; then LIBRARY_BITNESS="64" diff --git a/src/common/compat_strlcat.c b/src/common/compat_strlcat.c index af373f11..fa51cd29 100644 --- a/src/common/compat_strlcat.c +++ b/src/common/compat_strlcat.c @@ -31,7 +31,7 @@ #include "config.h" #endif -#ifndef HAVE_STRLCAT +#if !defined(HAVE_DECL_STRLCAT) || !HAVE_DECL_STRLCAT #include #include diff --git a/src/common/compat_strlcat.h b/src/common/compat_strlcat.h index f0284aca..9debdfad 100644 --- a/src/common/compat_strlcat.h +++ b/src/common/compat_strlcat.h @@ -10,9 +10,11 @@ #include "config.h" #endif -#ifndef HAVE_STRLCAT +#if !defined(HAVE_DECL_STRLCAT) || !HAVE_DECL_STRLCAT #include size_t strlcat(char *dst, const char *src, size_t siz); +#else +#include #endif #endif diff --git a/src/common/compat_strlcpy.c b/src/common/compat_strlcpy.c index 88f3a5fb..c8505707 100644 --- a/src/common/compat_strlcpy.c +++ b/src/common/compat_strlcpy.c @@ -20,7 +20,7 @@ #include "config.h" #endif -#ifndef HAVE_STRLCPY /* empty file if strlcpy is available */ +#if !defined(HAVE_DECL_STRLCPY) || !HAVE_DECL_STRLCPY #include #include diff --git a/src/common/compat_strlcpy.h b/src/common/compat_strlcpy.h index 5a6067fb..9da1604e 100644 --- a/src/common/compat_strlcpy.h +++ b/src/common/compat_strlcpy.h @@ -38,9 +38,11 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "config.h" #endif -#ifndef HAVE_STRLCPY +#if !defined(HAVE_DECL_STRLCPY) || !HAVE_DECL_STRLCPY #include size_t strlcpy(char *dst, const char *src, size_t siz); +#else +#include #endif #endif From 0dcb910289a83aaec5200900690bba57ec538992 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Sat, 11 Apr 2020 11:03:27 +0200 Subject: [PATCH 186/189] fixed "libtool: compile: unable to infer tagged configuration" --- src/libopensc/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 9f0dda5e..44e74db6 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -65,10 +65,9 @@ if ENABLE_CRYPTOTOKENKIT # most platforms don't support objective C the way we needed. # Only include it if needed libopensc_la_SOURCES_BASE += reader-cryptotokenkit.m -else +endif libopensc_la_LIBTOOLFLAGS = --tag CC libopensc_static_la_LIBTOOLFLAGS = --tag CC -endif libopensc_la_SOURCES = $(libopensc_la_SOURCES_BASE) \ libopensc.exports From b08d33ceb67e6607f632026417581ba443c4615a Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Tue, 14 Apr 2020 18:18:26 +0200 Subject: [PATCH 187/189] Travis: seperate installer packages not needed anymore --- .github/push_artifacts.sh | 2 +- .travis.yml | 2 - MacOSX/Makefile.am | 2 +- MacOSX/build-package-from-ci.in | 80 --------------------------------- configure.ac | 1 - 5 files changed, 2 insertions(+), 85 deletions(-) delete mode 100755 MacOSX/build-package-from-ci.in diff --git a/.github/push_artifacts.sh b/.github/push_artifacts.sh index 15d07868..4b7f5d9a 100755 --- a/.github/push_artifacts.sh +++ b/.github/push_artifacts.sh @@ -9,7 +9,7 @@ git clone --single-branch https://${GH_TOKEN}@github.com/OpenSC/Nightly.git > /d cd Nightly git checkout -b "${BRANCH}" -for file in ${BUILDPATH}/win32/Output/OpenSC*.exe ${BUILDPATH}/opensc*.tar.gz ${BUILDPATH}/OpenSC*.dmg ${BUILDPATH}/OpenSC*.msi ${BUILDPATH}/OpenSC*.zip ${BUILDPATH}/*.pkg +for file in ${BUILDPATH}/win32/Output/OpenSC*.exe ${BUILDPATH}/opensc*.tar.gz ${BUILDPATH}/OpenSC*.dmg ${BUILDPATH}/OpenSC*.msi ${BUILDPATH}/OpenSC*.zip do if [ -f ${file} ] then diff --git a/.travis.yml b/.travis.yml index 873fb530..0256e837 100644 --- a/.travis.yml +++ b/.travis.yml @@ -328,8 +328,6 @@ cache: directories: - $HOME/.m2/ - $HOME/Library/Caches/Homebrew - - openssl - - openpace - openssl_bin - openpace_bin - isetup diff --git a/MacOSX/Makefile.am b/MacOSX/Makefile.am index 4d032aee..b0fa2130 100644 --- a/MacOSX/Makefile.am +++ b/MacOSX/Makefile.am @@ -1,5 +1,5 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in -EXTRA_DIST = build build-package.in build-package-from-ci.in Distribution.xml.in libtool-bundle opensc-uninstall \ +EXTRA_DIST = build build-package.in Distribution.xml.in libtool-bundle opensc-uninstall \ resources \ resources/background.jpg \ resources/Welcome.html.in \ diff --git a/MacOSX/build-package-from-ci.in b/MacOSX/build-package-from-ci.in deleted file mode 100755 index 24e626bb..00000000 --- a/MacOSX/build-package-from-ci.in +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/bash -# temporary build script until we've fixed the CI to include CTK - -# You need to install the following packages from homebrew or macports or fink: -# autoconf automake libtool pkg-config help2man gengetopt - -export MACOSX_DEPLOYMENT_TARGET="10.10" - -set -ex -test -x ./configure || ./bootstrap -BUILDPATH=${PWD} - -# Locate the latest OSX SDK -SDK_PATH=$(xcrun --sdk macosx --show-sdk-path) - -# Set SDK path -export CFLAGS="$CFLAGS -isysroot $SDK_PATH -arch x86_64" - -# Build OpenSCToken -if ! test -e OpenSCToken; then - git clone --depth=1 https://github.com/frankmorgner/OpenSCToken.git -fi -cd OpenSCToken -# make sure OpenSCToken builds with the same dependencies as before -if ! test -e OpenSC; then - git clone --depth=1 ../../OpenSC -else - cd OpenSC && git pull && cd .. -fi -if ! test -e openssl; then - git clone --depth=1 https://github.com/openssl/openssl.git -b OpenSSL_1_0_2-stable -else - cd openssl && git pull && cd .. -fi -if ! test -e openpace; then - git clone --depth=1 https://github.com/frankmorgner/openpace.git -b 1.1.0 -else - cd openpace && git pull && cd .. -fi -BP=${BUILDPATH} -. ./bootstrap -BUILDPATH=${BP} -xcodebuild -target OpenSCTokenApp -configuration Debug -project OpenSCTokenApp.xcodeproj install DSTROOT=${BUILDPATH}/target_token -cd .. - -imagedir=$(mktemp -d) - -# Get name of branch in Nightly which corresponds to the latest commit in OpenSC -BRANCH=`git log --max-count=1 --date=short --abbrev=8 --pretty=format:"%cd_%h"` -if ! test -e Nightly-${BRANCH}; then - # Download the build - curl -L https://github.com/OpenSC/Nightly/archive/${BRANCH}.zip > ${BRANCH}.zip - # Unpack the build - unzip ${BRANCH}.zip -fi -cp Nightly-${BRANCH}/OpenSC-startup.pkg . -cp Nightly-${BRANCH}/OpenSC-tokend.pkg . -cp Nightly-${BRANCH}/OpenSC.pkg . - -# Build package -pkgbuild --root ${BUILDPATH}/target_token --identifier org.opensc-project.mac.opensctoken --version @PACKAGE_VERSION@ --install-location / OpenSCToken.pkg - -# Build product -productbuild --distribution MacOSX/Distribution.xml --package-path . --resources MacOSX/resources "${imagedir}/OpenSC @PACKAGE_VERSION@.pkg" - -# Build "Uninstaller" -osacompile -o "${imagedir}/OpenSC Uninstaller.app" "MacOSX/OpenSC_Uninstaller.applescript" - -# Create .dmg -rm -f OpenSC-@PACKAGE_VERSION@.dmg -i=0 -while ! hdiutil create -srcfolder "${imagedir}" -volname "@PACKAGE_NAME@" -fs JHFS+ OpenSC-@PACKAGE_VERSION@.dmg -do - i=$[$i+1] - if [ $i -gt 2 ] - then - exit 1 - fi -done -rm -rf ${imagedir} diff --git a/configure.ac b/configure.ac index 61f24633..b1bf2965 100644 --- a/configure.ac +++ b/configure.ac @@ -1118,7 +1118,6 @@ AC_CONFIG_FILES([ win32/OpenSC.wxs MacOSX/Makefile MacOSX/build-package - MacOSX/build-package-from-ci MacOSX/Distribution.xml MacOSX/resources/Welcome.html ]) From e864aa6d76a200200dd351100ebd378836b3bb3f Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 1 May 2020 12:48:10 +0200 Subject: [PATCH 188/189] macOS: cover minor versions of xcode uses subshell for getting xcode version --- .travis.yml | 1 + MacOSX/build-package.in | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0256e837..d1b2e4e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ matrix: include: - compiler: clang os: osx + osx_image: xcode9.4 env: DO_PUSH_ARTIFACT=yes - compiler: gcc os: linux diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index fb9979c1..a5f4e871 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -103,7 +103,7 @@ osacompile -o "$BUILDPATH/target/Applications/OpenSC Notify.app" "MacOSX/OpenSC_ # Build OpenSC.tokend when XCode version < 10 -if (( xcodebuild -version | sed -En 's/Xcode[[:space:]]+([0-9]+)\.[0-9]*/\1/p' < 10 )); then +if (( $(xcodebuild -version | sed -En 's/Xcode[[:space:]]+([0-9]+)(\.[0-9]*)*/\1/p') < 10 )); then # Check out OpenSC.tokend, if not already fetched. if ! test -e OpenSC.tokend; then git clone http://github.com/OpenSC/OpenSC.tokend.git From 2495bbecf7ff4bf4f8aaa1b4ac41f3b7ee864dd9 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 4 May 2020 22:53:34 +0200 Subject: [PATCH 189/189] macOS: pass installation if we could not start the background services --- MacOSX/scripts/postinstall | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MacOSX/scripts/postinstall b/MacOSX/scripts/postinstall index 52337d4d..45f21436 100755 --- a/MacOSX/scripts/postinstall +++ b/MacOSX/scripts/postinstall @@ -36,7 +36,7 @@ for f in \ do if [ -e "$f" ] then - /bin/launchctl asuser $(id -u "${USER}") /bin/launchctl load "$f" + /bin/launchctl asuser $(id -u "${USER}") /bin/launchctl load "$f" || true fi done