diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index ba9a7357..f608fdc3 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -70,26 +70,33 @@ typedef struct sc_pkcs15_id sc_pkcs15_id_t; #define SC_PKCS15_PIN_TYPE_ISO9564_1 4 #define SC_PKCS15_PIN_AUTH_TYPE_PIN 0 -#define SC_PKCS15_PIN_AUTH_TYPE_AUTH_KEY 1 -#define SC_PKCS15_PIN_AUTH_TYPE_SM_KEY 2 +#define SC_PKCS15_PIN_AUTH_TYPE_BIOMETRIC 1 +#define SC_PKCS15_PIN_AUTH_TYPE_AUTH_KEY 2 +#define SC_PKCS15_PIN_AUTH_TYPE_SM_KEY 3 +/* PinAttributes as they defined in PKCS#15 v1.1 for PIN authentication object */ struct sc_pkcs15_pin_attributes { unsigned int flags, type; size_t min_length, stored_length, max_length; int reference; u8 pad_char; }; +/* AuthKeyAttributes of the authKey authentication object */ struct sc_pkcs15_authkey_attributes { int derived; struct sc_pkcs15_id skey_id; }; +/* BiometricAttributes of the biometricTemplate authentication object */ struct sc_pkcs15_biometric_attributes { unsigned int flags; struct sc_object_id template_id; /* ... */ }; struct sc_pkcs15_auth_info { + /* CommonAuthenticationObjectAttributes */ struct sc_pkcs15_id auth_id; + + /* AuthObjectAttributes */ struct sc_path path; unsigned auth_type; union { @@ -97,7 +104,10 @@ struct sc_pkcs15_auth_info { struct sc_pkcs15_biometric_attributes bio; struct sc_pkcs15_authkey_attributes authkey; } attrs; + + /* authentication method: CHV, SEN, SYMBOLIC, ... */ unsigned int auth_method; + int tries_left, max_tries; }; typedef struct sc_pkcs15_auth_info sc_pkcs15_auth_info_t; diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index e3ed3a45..5db870a1 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1411,6 +1411,18 @@ static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card, return CKR_OK; } +static unsigned long +pkcs15_check_bool_cka(CK_ATTRIBUTE_PTR attr, unsigned long flag) +{ + if (attr->ulValueLen != sizeof(CK_BBOOL) || !attr->pValue) + return 0; + + if (*((CK_BBOOL *)attr->pValue)) + return flag; + + return 0; +} + static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card, struct sc_pkcs11_slot *slot, struct sc_profile *profile, @@ -1493,7 +1505,21 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card, if (key_type == CKK_GOSTR3410) bn = &gost->d; break; - + case CKA_SIGN: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_SIGN); + break; + case CKA_SIGN_RECOVER: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_SIGNRECOVER); + break; + case CKA_DECRYPT: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_DECRYPT); + break; + case CKA_UNWRAP: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_UNWRAP); + break; + case OPENSC_CKA_NON_REPUDIATION: + args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION); + break; default: /* ignore unknown attrs, or flag error? */ continue; diff --git a/src/pkcs11/pkcs11-opensc.h b/src/pkcs11/pkcs11-opensc.h index 6ab95303..c262a49c 100644 --- a/src/pkcs11/pkcs11-opensc.h +++ b/src/pkcs11/pkcs11-opensc.h @@ -2,5 +2,11 @@ #define PKCS11_OPENSC_H /* OpenSC specific extensions */ +/* + * In PKCS#11 there is no CKA_ attribute dedicated to the NON-REPUDIATION flag. + * We need this flag in PKCS#15/libopensc to make dinstinction between + * 'signature' and 'qualified signature' key slots. + */ +#define OPENSC_CKA_NON_REPUDIATION (CKA_VENDOR_DEFINED | 1UL) #endif diff --git a/src/pkcs15init/pkcs15-cardos.c b/src/pkcs15init/pkcs15-cardos.c index dba0d66c..90771d14 100644 --- a/src/pkcs15init/pkcs15-cardos.c +++ b/src/pkcs15init/pkcs15-cardos.c @@ -62,6 +62,7 @@ static int cardos_extract_pubkey(sc_card_t *, sc_pkcs15_pubkey_t *, sc_file_t *, int); static int do_cardos_extract_pubkey(sc_card_t *card, int nr, u8 tag, sc_pkcs15_bignum_t *bn); +static int cardos_have_verifyrc_package(sc_card_t *card); /* Object IDs for PIN objects. * SO PIN = 0x01, SO PUK = 0x02 @@ -413,7 +414,7 @@ cardos_store_pin(sc_profile_t *profile, sc_card_t *card, unsigned char pinpadded[256]; struct tlv tlv; unsigned int attempts, minlen, maxlen; - int r; + int r, hasverifyrc; if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_OBJECT_NOT_VALID; @@ -445,6 +446,10 @@ cardos_store_pin(sc_profile_t *profile, sc_card_t *card, /* parameters */ tlv_next(&tlv, 0x85); tlv_add(&tlv, 0x02); /* options byte */ + hasverifyrc = cardos_have_verifyrc_package(card); + if (hasverifyrc == 1) + /* Use 9 byte OCI parameters to be able to set VerifyRC bit */ + tlv_add(&tlv, 0x04); /* options_2 byte with bit 2 set to return CurrentErrorCounter */ tlv_add(&tlv, attempts & 0xf); /* flags byte */ tlv_add(&tlv, CARDOS_ALGO_PIN); /* algorithm = pin-test */ tlv_add(&tlv, attempts & 0xf); /* errcount = attempts */ @@ -786,6 +791,56 @@ static int cardos_extract_pubkey(sc_card_t *card, sc_pkcs15_pubkey_t *pubkey, return r; } +static int cardos_have_verifyrc_package(sc_card_t *card) +{ + sc_apdu_t apdu; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + int r; + const u8 *p = rbuf, *q; + size_t len, tlen = 0, ilen = 0; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88); + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + apdu.lc = 0; + apdu.le = 256; + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); + + if ((len = apdu.resplen) == 0) + /* looks like no package has been installed */ + return 0; + + while (len != 0) { + p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen); + if (p == NULL) + return 0; + if (card->type == SC_CARD_TYPE_CARDOS_M4_3) { + /* the verifyRC package on CardOS 4.3B use Manufacturer ID 0x01 */ + /* and Package Number 0x07 */ + q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen); + if (q == NULL || ilen != 4) + return 0; + if (q[0] == 0x07) + return 1; + } else if (card->type == SC_CARD_TYPE_CARDOS_M4_4) { + /* the verifyRC package on CardOS 4.4 use Manufacturer ID 0x03 */ + /* and Package Number 0x02 */ + q = sc_asn1_find_tag(card->ctx, p, tlen, 0x03, &ilen); + if (q == NULL || ilen != 4) + return 0; + if (q[0] == 0x02) + return 1; + } else { + return 0; + } + p += tlen; + len -= tlen + 2; + } + + return 0; +} + static struct sc_pkcs15init_operations sc_pkcs15init_cardos_operations = { cardos_erase, NULL, /* init_card */