diff --git a/ykcs11/objects.c b/ykcs11/objects.c index fa3ed8c..aaf3fa7 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -1161,8 +1161,12 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, } CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, - CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, - CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) { + CK_BYTE_PTR *p, CK_ULONG_PTR p_len, + CK_BYTE_PTR *q, CK_ULONG_PTR q_len, + CK_BYTE_PTR *dp, CK_ULONG_PTR dp_len, + CK_BYTE_PTR *dq, CK_ULONG_PTR dq_len, + CK_BYTE_PTR *qinv, CK_ULONG_PTR qinv_len, + CK_ULONG_PTR vendor_defined) { CK_ULONG i; CK_BBOOL has_id = CK_FALSE; @@ -1172,11 +1176,6 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BBOOL has_dp = CK_FALSE; CK_BBOOL has_dq = CK_FALSE; CK_BBOOL has_qinv = CK_FALSE; - CK_ULONG p_len = 0; - CK_ULONG q_len = 0; - CK_ULONG dp_len = 0; - CK_ULONG dq_len = 0; - CK_ULONG qinv_len = 0; *vendor_defined = 0; @@ -1211,35 +1210,35 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, case CKA_PRIME_1: has_p = CK_TRUE; *p = (CK_BYTE_PTR)templ[i].pValue; - p_len = templ[i].ulValueLen; + *p_len = templ[i].ulValueLen; break; case CKA_PRIME_2: has_q = CK_TRUE; *q = (CK_BYTE_PTR)templ[i].pValue; - q_len = templ[i].ulValueLen; + *q_len = templ[i].ulValueLen; break; case CKA_EXPONENT_1: has_dp = CK_TRUE; *dp = (CK_BYTE_PTR)templ[i].pValue; - dp_len = templ[i].ulValueLen; + *dp_len = templ[i].ulValueLen; break; case CKA_EXPONENT_2: has_dq = CK_TRUE; *dq = (CK_BYTE_PTR)templ[i].pValue; - dq_len = templ[i].ulValueLen; + *dq_len = templ[i].ulValueLen; break; case CKA_COEFFICIENT: has_qinv = CK_TRUE; *qinv = (CK_BYTE_PTR)templ[i].pValue; - qinv_len = templ[i].ulValueLen; + *qinv_len = templ[i].ulValueLen; break; @@ -1270,13 +1269,12 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, has_qinv == CK_FALSE) return CKR_TEMPLATE_INCOMPLETE; - if (p_len != 64 && p_len != 128) + if (*p_len != 64 && *p_len != 128) return CKR_ATTRIBUTE_VALUE_INVALID; - *value_len = p_len; - if (q_len != p_len || dp_len != p_len || - dq_len != p_len || qinv_len != p_len) + if (*q_len != *p_len || *dp_len > *p_len || + *dq_len > *p_len || *qinv_len > *p_len) return CKR_ATTRIBUTE_VALUE_INVALID; return CKR_OK; diff --git a/ykcs11/objects.h b/ykcs11/objects.h index be9db19..0780503 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -18,8 +18,12 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, - CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, - CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); + CK_BYTE_PTR *p, CK_ULONG_PTR p_len, + CK_BYTE_PTR *q, CK_ULONG_PTR q_len, + CK_BYTE_PTR *dp, CK_ULONG_PTR dp_len, + CK_BYTE_PTR *dq, CK_ULONG_PTR dq_len, + CK_BYTE_PTR *qinv, CK_ULONG_PTR qinv_len, + CK_ULONG_PTR vendor_defined); CK_RV check_delete_cert(CK_OBJECT_HANDLE hObject, CK_BYTE_PTR id); #endif diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index d357092..4e0569c 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -1190,6 +1190,7 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; #define CKA_TOUCH_ALWAYS 0x00000001U #define CKA_PIN_ONCE 0x00000002U #define CKA_PIN_ALWAYS 0x00000004U - +#define CKA_PIN_NEVER 0x00000008U +#define CKA_TOUCH_NEVER 0x00000016U #endif diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 25db6d7..b5bbfd8 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -176,85 +176,73 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B return CKR_OK; } -CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYTE_PTR p, CK_BYTE_PTR q, - CK_BYTE_PTR dp, CK_BYTE_PTR dq, CK_BYTE_PTR qinv, - CK_BYTE_PTR ec_data, CK_ULONG elem_len, CK_ULONG vendor_defined) { +CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, + CK_BYTE_PTR p, CK_ULONG p_len, + CK_BYTE_PTR q, CK_ULONG q_len, + CK_BYTE_PTR dp, CK_ULONG dp_len, + CK_BYTE_PTR dq, CK_ULONG dq_len, + CK_BYTE_PTR qinv, CK_ULONG qinv_len, + CK_BYTE_PTR ec_data, CK_ULONG ec_data_len, + CK_ULONG vendor_defined) { - unsigned char key_data[1024]; - unsigned char *in_ptr = key_data; - unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, 0, key_id}; - unsigned char data[0xff]; - unsigned long recv_len = sizeof(data); - int sw; + CK_BYTE pin_policy; + CK_BYTE touch_policy; + CK_BYTE algo; + ykpiv_rc rc; - if (elem_len == 128) // TODO: add a flag to check algo type ? - templ[2] = YKPIV_ALGO_RSA2048; - else if (elem_len == 64) - templ[2] = YKPIV_ALGO_RSA1024; - else if(elem_len == 32) - templ[2] = YKPIV_ALGO_ECCP256; - - if (templ[2] == YKPIV_ALGO_RSA1024 ||templ[2] == YKPIV_ALGO_RSA2048) { - *in_ptr++ = 0x01; - in_ptr += set_length(in_ptr, elem_len); - memcpy(in_ptr, p, (size_t)(elem_len)); - in_ptr += elem_len; - - *in_ptr++ = 0x02; - in_ptr += set_length(in_ptr, elem_len); - memcpy(in_ptr, q, (size_t)(elem_len)); - in_ptr += elem_len; - - *in_ptr++ = 0x03; - in_ptr += set_length(in_ptr, elem_len); - memcpy(in_ptr, dp, (size_t)(elem_len)); - in_ptr += elem_len; - - *in_ptr++ = 0x04; - in_ptr += set_length(in_ptr, elem_len); - memcpy(in_ptr, dq, (size_t)(elem_len)); - in_ptr += elem_len; - - *in_ptr++ = 0x05; - in_ptr += set_length(in_ptr, elem_len); - memcpy(in_ptr, qinv, (size_t)(elem_len)); - in_ptr += elem_len; + if (p == NULL) { + if (ec_data_len == 32 || ec_data_len == 31) + algo = YKPIV_ALGO_ECCP256; + else + algo = YKPIV_ALGO_ECCP384; } - else if (templ[2] == YKPIV_ALGO_ECCP256) { - *in_ptr++ = 0x06; - in_ptr += set_length(in_ptr, elem_len); - memcpy(in_ptr, ec_data, (size_t)(elem_len)); - in_ptr += elem_len; + else if (ec_data == NULL) { + if (p_len == 64) + algo = YKPIV_ALGO_RSA1024; + else + algo = YKPIV_ALGO_RSA2048; } - - // PIN policy and touch - if (vendor_defined != 0) { - if (vendor_defined & CKA_PIN_ONCE) { - *in_ptr++ = YKPIV_PINPOLICY_TAG; - *in_ptr++ = 0x01; - *in_ptr++ = YKPIV_PINPOLICY_ONCE; - } - else if (vendor_defined & CKA_PIN_ALWAYS) { - *in_ptr++ = YKPIV_PINPOLICY_TAG; - *in_ptr++ = 0x01; - *in_ptr++ = YKPIV_PINPOLICY_ALWAYS; - } - - if (vendor_defined & CKA_TOUCH_ALWAYS) { - *in_ptr++ = YKPIV_TOUCHPOLICY_TAG; - *in_ptr++ = 0x01; - *in_ptr++ = YKPIV_TOUCHPOLICY_ALWAYS; - } - } - - if (ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK) + else return CKR_FUNCTION_FAILED; - if (sw != 0x9000) - return CKR_DEVICE_ERROR; + pin_policy = YKPIV_PINPOLICY_DEFAULT; + touch_policy = YKPIV_TOUCHPOLICY_DEFAULT; + if (vendor_defined != 0) { + if (vendor_defined & CKA_PIN_ONCE) { + pin_policy = YKPIV_PINPOLICY_ONCE; + } + else if (vendor_defined & CKA_PIN_ALWAYS) { + pin_policy = YKPIV_PINPOLICY_ALWAYS; + } + else if (vendor_defined & CKA_PIN_NEVER) { + pin_policy = YKPIV_PINPOLICY_NEVER; + } + else + return CKR_ATTRIBUTE_VALUE_INVALID; - return CKR_OK; + if (vendor_defined & CKA_TOUCH_ALWAYS) { + touch_policy = YKPIV_TOUCHPOLICY_ALWAYS; + } + else if (vendor_defined & CKA_TOUCH_NEVER) { + touch_policy = YKPIV_TOUCHPOLICY_NEVER; + } + else + return CKR_ATTRIBUTE_VALUE_INVALID; + } + rc = ykpiv_import_private_key(state, key_id, algo, + p, p_len, + q, q_len, + dp, dp_len, + dq, dq_len, + qinv, qinv_len, + ec_data, ec_data_len, + pin_policy, touch_policy); + + if (rc != YKPIV_OK) + return CKR_FUNCTION_FAILED; + + return CKR_OK; } CK_RV COMMON_token_delete_cert(ykpiv_state *state, CK_ULONG cert_id) { diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index 3b57209..e091124 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -23,8 +23,14 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT 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, 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); +typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, + CK_BYTE_PTR, CK_ULONG, + CK_BYTE_PTR, CK_ULONG, + CK_BYTE_PTR, CK_ULONG, + CK_BYTE_PTR, CK_ULONG, + CK_BYTE_PTR, CK_ULONG, + CK_BYTE_PTR, CK_ULONG, + CK_ULONG); typedef CK_RV (*t_delete_cert_f)(ykpiv_state *, CK_ULONG); // TODO: replace all the common calls with functions defined in .c that use libykpiv diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 739df2b..37c7fbd 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -858,6 +858,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_BYTE_PTR dp; CK_BYTE_PTR dq; CK_BYTE_PTR qinv; + CK_ULONG p_len; + CK_ULONG q_len; + CK_ULONG dp_len; + CK_ULONG dq_len; + CK_ULONG qinv_len; + CK_BYTE_PTR ec_data; + CK_ULONG ec_data_len; CK_ULONG vendor_defined; token_vendor_t token; CK_BBOOL is_new; @@ -980,11 +987,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( // Try to parse the key as EC is_rsa = CK_FALSE; - rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &vendor_defined); + rv = check_create_ec_key(pTemplate, ulCount, &id, &ec_data, &ec_data_len, &vendor_defined); if (rv != CKR_OK) { // Try to parse the key as RSA is_rsa = CK_TRUE; - rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len, &vendor_defined); + rv = check_create_rsa_key(pTemplate, ulCount, &id, + &p, &p_len, + &q, &q_len, + &dp, &dp_len, + &dq, &dq_len, + &qinv, &qinv_len, + &vendor_defined); if (rv != CKR_OK) { DBG("Private key template not valid"); return rv; @@ -997,9 +1010,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( if (is_rsa == CK_TRUE) { DBG("Key is RSA"); - rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv, - NULL, - value_len, vendor_defined); + rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), + p, p_len, + q, q_len, + dp, dp_len, + dq, dq_len, + qinv, qinv_len, + NULL, 0, + vendor_defined); if (rv != CKR_OK) { DBG("Unable to import RSA private key"); return rv; @@ -1007,9 +1025,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( } else { DBG("Key is ECDSA"); - rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL, - value, - value_len, vendor_defined); + rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), + NULL, 0, + NULL, 0, + NULL, 0, + NULL, 0, + NULL, 0, + ec_data, ec_data_len, + vendor_defined); if (rv != CKR_OK) { DBG("Unable to import ECDSA private key"); return rv;