diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index b7b4886..de642ff 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -420,7 +420,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG default: DBG(("Invalid attribute %lx in public key template", templ[i].type)); - return CKR_ATTRIBUTE_VALUE_INVALID; + return CKR_ATTRIBUTE_TYPE_INVALID; } } @@ -433,6 +433,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG CK_ULONG i; op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism); + op_info->op.gen.vendor_defined = 0; for (i = 0; i < n; i++) { switch (templ[i].type) { @@ -473,6 +474,9 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG op_info->op.gen.key_id = PIV_PVTK_OBJ_PIV_AUTH + *((CK_BYTE_PTR)templ[i].pValue); break; + case CKA_VENDOR_DEFINED: + op_info->op.gen.vendor_defined = (*((CK_ULONG_PTR)templ[i].pValue)); + case CKA_SENSITIVE: case CKA_DECRYPT: case CKA_UNWRAP: @@ -485,7 +489,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG default: DBG(("Invalid attribute %lx in private key template", templ[i].type)); - return CKR_ATTRIBUTE_VALUE_INVALID; + return CKR_ATTRIBUTE_TYPE_INVALID; } } diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 99dfd7e..0fd7198 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -31,9 +31,11 @@ static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CH return CKR_OK; } -static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE key, CK_ULONG key_len) { +static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, + CK_BYTE key, CK_ULONG key_len, CK_ULONG vendor_defined) { // TODO: make a function in ykpiv for this - unsigned char in_data[5]; + unsigned char in_data[11]; + unsigned char *in_ptr = in_data; unsigned char data[1024]; unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0}; unsigned char *certptr; @@ -45,10 +47,10 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE templ[3] = key; - in_data[0] = 0xac; - in_data[1] = 3; - in_data[2] = 0x80; - in_data[3] = 1; + *in_ptr++ = 0xac; + *in_ptr++ = 3; + *in_ptr++ = 0x80; + *in_ptr++ = 1; switch(key_len) { case 2048: @@ -61,7 +63,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE case 1024: if (rsa == CK_TRUE) - in_data[4] = YKPIV_ALGO_RSA1024; + *in_ptr++ = YKPIV_ALGO_RSA1024; else return CKR_FUNCTION_FAILED; @@ -69,7 +71,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE case 256: if (rsa == CK_FALSE) - in_data[4] = YKPIV_ALGO_ECCP256; + *in_ptr++ = YKPIV_ALGO_ECCP256; else return CKR_FUNCTION_FAILED; @@ -78,8 +80,30 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE default: return CKR_FUNCTION_FAILED; } - //DBG(("Generating key %x with algorithm %u and length %lu", templ[3], in_data[4], key_len)); - if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data, &recv_len, &sw) != YKPIV_OK || + // PIN policy and touch + if (vendor_defined != 0) { + if (vendor_defined & CKA_PIN_ONCE) { + in_data[1] += 3; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ONCE; + } + else if (vendor_defined & CKA_PIN_ALWAYS) { + in_data[1] += 3; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ALWAYS; + } + + if (vendor_defined & CKA_TOUCH_ALWAYS) { + in_data[1] += 3; + *in_ptr++ = YKPIV_TOUCHPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_TOUCHPOLICY_ALWAYS; + } + } + + if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK || sw != 0x9000) return CKR_DEVICE_ERROR; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index c59f376..9513063 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -21,7 +21,7 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT // Common token functions below typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); +typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index c026e28..4025524 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -2053,7 +2053,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( token = get_token_vendor(session.slot->token->vid); - if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len)) != CKR_OK) { + if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len, op_info.op.gen.vendor_defined)) != CKR_OK) { DBG(("Unable to generate key pair")); return rv; } diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 0793432..e29b24b 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -28,7 +28,6 @@ typedef struct { ykcs11_slot_t *slot; } ykcs11_session_t; - typedef enum { YKCS11_NOOP, YKCS11_GEN, @@ -38,9 +37,10 @@ typedef enum { } ykcs11_op_type_t; typedef struct { - CK_BBOOL rsa; // RSA or EC key - CK_BYTE key_id; // Key id - CK_ULONG key_len; // Length in bits + CK_BBOOL rsa; // RSA or EC key + CK_BYTE key_id; // Key id + CK_ULONG key_len; // Length in bits + CK_ULONG vendor_defined; // Additional parameters (touch and PIN policy) } gen_info_t; typedef struct {