Merge remote branch 'upstream/master'

This commit is contained in:
Ludovic Rousseau 2011-06-14 14:00:18 +02:00
commit 40cb1c9e35
4 changed files with 101 additions and 4 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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 */