Initial stab at private key import.
This commit is contained in:
+164
-3
@@ -942,11 +942,12 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n,
|
|||||||
has_value = CK_TRUE;
|
has_value = CK_TRUE;
|
||||||
*value = (CK_BYTE_PTR)templ[i].pValue;
|
*value = (CK_BYTE_PTR)templ[i].pValue;
|
||||||
|
|
||||||
*cert_len = 0;
|
/**cert_len = 0;
|
||||||
*cert_len += get_length(value + 1, cert_len) + 1;
|
*cert_len += get_length(value + 1, cert_len) + 1;*/
|
||||||
|
*cert_len = templ[i].ulValueLen;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default: // TODO: don't error on valid parameters
|
||||||
// Ignore other attributes for now
|
// Ignore other attributes for now
|
||||||
DBG(("Invalid %lx", templ[i].type));
|
DBG(("Invalid %lx", templ[i].type));
|
||||||
return CKR_ATTRIBUTE_TYPE_INVALID;
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
||||||
@@ -959,3 +960,163 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n,
|
|||||||
|
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
|
||||||
|
CK_BYTE_PTR *value, CK_ULONG_PTR cert_len,
|
||||||
|
CK_BYTE_PTR *ec_params, CK_ULONG_PTR ec_params_len) {
|
||||||
|
|
||||||
|
CK_ULONG i;
|
||||||
|
CK_BBOOL has_id = CK_FALSE;
|
||||||
|
CK_BBOOL has_value = CK_FALSE;
|
||||||
|
CK_BBOOL has_params = CK_FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
switch (templ[i].type) {
|
||||||
|
case CKA_CLASS:
|
||||||
|
if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_PRIVATE_KEY)
|
||||||
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_KEY_TYPE:
|
||||||
|
if (*((CK_ULONG_PTR)templ[i].pValue) != CKK_ECDSA)
|
||||||
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_ID:
|
||||||
|
has_id = CK_TRUE;
|
||||||
|
if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE)
|
||||||
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||||
|
|
||||||
|
*id = *((CK_BYTE_PTR)templ[i].pValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_VALUE:
|
||||||
|
has_value = CK_TRUE;
|
||||||
|
*value = (CK_BYTE_PTR)templ[i].pValue;
|
||||||
|
*cert_len = templ[i].ulValueLen;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_EC_PARAMS:
|
||||||
|
has_params = CK_TRUE;
|
||||||
|
*ec_params = (CK_BYTE_PTR)templ[i].pValue;
|
||||||
|
*ec_params_len = templ[i].ulValueLen;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // TODO: don't error on valid parameters
|
||||||
|
// Ignore other attributes for now
|
||||||
|
DBG(("Invalid %lx", templ[i].type));
|
||||||
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_id == CK_FALSE ||
|
||||||
|
has_value == CK_FALSE ||
|
||||||
|
has_params == CK_FALSE)
|
||||||
|
return CKR_TEMPLATE_INCOMPLETE;
|
||||||
|
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
|
||||||
|
CK_BYTE_PTR *e, CK_ULONG_PTR e_len,
|
||||||
|
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 i;
|
||||||
|
CK_BBOOL has_id = CK_FALSE;
|
||||||
|
CK_BBOOL has_e = CK_FALSE;
|
||||||
|
CK_BBOOL has_p = CK_FALSE;
|
||||||
|
CK_BBOOL has_q = CK_FALSE;
|
||||||
|
CK_BBOOL has_dp = CK_FALSE;
|
||||||
|
CK_BBOOL has_dq = CK_FALSE;
|
||||||
|
CK_BBOOL has_qinv = CK_FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
switch (templ[i].type) {
|
||||||
|
case CKA_CLASS:
|
||||||
|
if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_PRIVATE_KEY)
|
||||||
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_ID:
|
||||||
|
has_id = CK_TRUE;
|
||||||
|
if (is_valid_key_id(*((CK_BYTE_PTR)templ[i].pValue)) == CK_FALSE)
|
||||||
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||||
|
|
||||||
|
*id = *((CK_BYTE_PTR)templ[i].pValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_KEY_TYPE:
|
||||||
|
if (*((CK_ULONG_PTR)templ[i].pValue) != CKK_RSA)
|
||||||
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_PUBLIC_EXPONENT: // TODO: check that it is F4
|
||||||
|
has_e = CK_TRUE;
|
||||||
|
*e = (CK_BYTE_PTR)templ[i].pValue;
|
||||||
|
*e_len = templ[i].ulValueLen;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_PRIME_1:
|
||||||
|
has_p = CK_TRUE;
|
||||||
|
*p = (CK_BYTE_PTR)templ[i].pValue;
|
||||||
|
*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;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_EXPONENT_1:
|
||||||
|
has_dp = CK_TRUE;
|
||||||
|
*dp = (CK_BYTE_PTR)templ[i].pValue;
|
||||||
|
*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;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CKA_COEFFICIENT:
|
||||||
|
has_qinv = CK_TRUE;
|
||||||
|
*qinv = (CK_BYTE_PTR)templ[i].pValue;
|
||||||
|
*qinv_len = templ[i].ulValueLen;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // TODO: don't error on valid parameters
|
||||||
|
// Ignore other attributes for now
|
||||||
|
DBG(("Invalid %lx", templ[i].type));
|
||||||
|
return CKR_ATTRIBUTE_TYPE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_id == CK_FALSE ||
|
||||||
|
has_e == CK_FALSE ||
|
||||||
|
has_p == CK_FALSE ||
|
||||||
|
has_q == CK_FALSE ||
|
||||||
|
has_dp == CK_FALSE ||
|
||||||
|
has_dq == CK_FALSE ||
|
||||||
|
has_qinv == CK_FALSE)
|
||||||
|
return CKR_TEMPLATE_INCOMPLETE;
|
||||||
|
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,5 +14,15 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len);
|
|||||||
|
|
||||||
CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
|
CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
|
||||||
CK_BYTE_PTR *value, CK_ULONG_PTR cert_len);
|
CK_BYTE_PTR *value, CK_ULONG_PTR cert_len);
|
||||||
|
CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
|
||||||
|
CK_BYTE_PTR *value, CK_ULONG_PTR cert_len,
|
||||||
|
CK_BYTE_PTR *ec_params, CK_ULONG_PTR ec_params_len);
|
||||||
|
CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
|
||||||
|
CK_BYTE_PTR *e, CK_ULONG_PTR e_len,
|
||||||
|
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);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -122,6 +122,15 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B
|
|||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CK_RV COMMON_token_import_private_key(ykpiv_state *state , CK_BYTE_PTR 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) {
|
||||||
|
|
||||||
|
return CKR_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
token_vendor_t get_token_vendor(vendor_id_t vid) {
|
token_vendor_t get_token_vendor(vendor_id_t vid) {
|
||||||
token_vendor_t v;
|
token_vendor_t v;
|
||||||
|
|
||||||
@@ -141,6 +150,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
|
|||||||
v.get_token_raw_certificate = YUBICO_get_token_raw_certificate;
|
v.get_token_raw_certificate = YUBICO_get_token_raw_certificate;
|
||||||
v.token_generate_key = COMMON_token_generate_key;
|
v.token_generate_key = COMMON_token_generate_key;
|
||||||
v.token_import_cert = COMMON_token_import_cert;
|
v.token_import_cert = COMMON_token_import_cert;
|
||||||
|
v.token_import_private_key = COMMON_token_import_private_key;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
@@ -159,6 +169,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
|
|||||||
v.get_token_raw_certificate = NULL;
|
v.get_token_raw_certificate = NULL;
|
||||||
v.token_generate_key = NULL;
|
v.token_generate_key = NULL;
|
||||||
v.token_import_cert = NULL;
|
v.token_import_cert = NULL;
|
||||||
|
v.token_import_private_key = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
|||||||
@@ -22,8 +22,11 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT
|
|||||||
// Common token functions below
|
// Common token functions below
|
||||||
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);
|
||||||
typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR);
|
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_PTR ,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);
|
||||||
|
|
||||||
// TODO: replace all the common call with functions defined in .c that use libykpiv
|
// TODO: replace all the common calls with functions defined in .c that use libykpiv
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
get_t_label_f get_token_label;
|
get_t_label_f get_token_label;
|
||||||
@@ -40,6 +43,7 @@ typedef struct {
|
|||||||
get_t_raw_certificate_f get_token_raw_certificate;
|
get_t_raw_certificate_f get_token_raw_certificate;
|
||||||
t_generate_key_f token_generate_key;
|
t_generate_key_f token_generate_key;
|
||||||
t_import_cert_f token_import_cert;
|
t_import_cert_f token_import_cert;
|
||||||
|
t_import_private_key_f token_import_private_key;
|
||||||
} token_vendor_t;
|
} token_vendor_t;
|
||||||
|
|
||||||
token_vendor_t get_token_vendor(vendor_id_t vid);
|
token_vendor_t get_token_vendor(vendor_id_t vid);
|
||||||
|
|||||||
+55
-5
@@ -827,15 +827,31 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
|
|||||||
CK_OBJECT_CLASS class;
|
CK_OBJECT_CLASS class;
|
||||||
CK_BYTE id;
|
CK_BYTE id;
|
||||||
CK_BYTE_PTR value;
|
CK_BYTE_PTR value;
|
||||||
CK_ULONG len;
|
CK_ULONG value_len;
|
||||||
|
CK_BYTE_PTR ec_params;
|
||||||
|
CK_ULONG ec_params_len;
|
||||||
|
CK_BYTE_PTR e;
|
||||||
|
CK_ULONG e_len;
|
||||||
|
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;
|
||||||
token_vendor_t token;
|
token_vendor_t token;
|
||||||
CK_BBOOL is_new;
|
CK_BBOOL is_new;
|
||||||
|
CK_BBOOL is_rsa;
|
||||||
CK_OBJECT_HANDLE object;
|
CK_OBJECT_HANDLE object;
|
||||||
CK_ULONG cert_id;
|
CK_ULONG cert_id;
|
||||||
CK_ULONG pvtk_id;
|
CK_ULONG pvtk_id;
|
||||||
CK_ULONG pubk_id;
|
CK_ULONG pubk_id;
|
||||||
piv_obj_id_t *obj_ptr;
|
piv_obj_id_t *obj_ptr;
|
||||||
|
|
||||||
|
|
||||||
if (piv_state == NULL) {
|
if (piv_state == NULL) {
|
||||||
DBG(("libykpiv is not initialized or already finalized"));
|
DBG(("libykpiv is not initialized or already finalized"));
|
||||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||||
@@ -869,7 +885,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
|
|||||||
|
|
||||||
// Can only import certificates and private keys
|
// Can only import certificates and private keys
|
||||||
if (*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_CERTIFICATE &&
|
if (*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_CERTIFICATE &&
|
||||||
*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_PUBLIC_KEY) {
|
*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_PRIVATE_KEY) {
|
||||||
DBG(("Unsupported class %lu", class));
|
DBG(("Unsupported class %lu", class));
|
||||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||||
}
|
}
|
||||||
@@ -887,7 +903,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
|
|||||||
case CKO_CERTIFICATE:
|
case CKO_CERTIFICATE:
|
||||||
DBG(("Importing certificate"));
|
DBG(("Importing certificate"));
|
||||||
|
|
||||||
rv = check_create_cert(pTemplate, ulCount, &id, &value, &len);
|
rv = check_create_cert(pTemplate, ulCount, &id, &value, &value_len);
|
||||||
if (rv != CKR_OK) {
|
if (rv != CKR_OK) {
|
||||||
DBG(("Certificate template not valid"));
|
DBG(("Certificate template not valid"));
|
||||||
return rv;
|
return rv;
|
||||||
@@ -933,7 +949,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
|
|||||||
*obj_ptr++ = pubk_id;
|
*obj_ptr++ = pubk_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = store_cert(cert_id, value, len);
|
rv = store_cert(cert_id, value, value_len);
|
||||||
if (rv != CKR_OK) {
|
if (rv != CKR_OK) {
|
||||||
DBG(("Unable to store certificate data"));
|
DBG(("Unable to store certificate data"));
|
||||||
return CKR_FUNCTION_FAILED;
|
return CKR_FUNCTION_FAILED;
|
||||||
@@ -942,7 +958,41 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CKO_PRIVATE_KEY:
|
case CKO_PRIVATE_KEY:
|
||||||
//rv = create_pvt_key();
|
DBG(("Importing private key"));
|
||||||
|
|
||||||
|
// Try to parse the key as EC
|
||||||
|
is_rsa = CK_FALSE;
|
||||||
|
rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &ec_params, &ec_params_len);
|
||||||
|
if (rv != CKR_OK) {
|
||||||
|
// Try to parse the key as RSA
|
||||||
|
is_rsa = CK_TRUE;
|
||||||
|
rv = check_create_rsa_key(pTemplate, ulCount, &id, &e, &e_len, &p, &p_len,
|
||||||
|
&q, &q_len, &dp, &dp_len, &dq, &dq_len, &qinv, &qinv_len);
|
||||||
|
if (rv != CKR_OK) {
|
||||||
|
DBG(("Private key template not valid"));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG(("Key id is %u", id));
|
||||||
|
|
||||||
|
if (is_rsa == CK_TRUE) {
|
||||||
|
DBG(("Key is RSA"));
|
||||||
|
rv = token.token_import_private_key(piv_state, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0);
|
||||||
|
if (rv != CKR_OK) {
|
||||||
|
DBG(("Unable to import RSA private key"));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBG(("Key is ECDSA"));
|
||||||
|
rv = token.token_import_private_key(piv_state, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0);
|
||||||
|
if (rv != CKR_OK) {
|
||||||
|
DBG(("Unable to import ECDSA private key"));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CKR_FUNCTION_FAILED;
|
return CKR_FUNCTION_FAILED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user