Initial stab at private key import.

This commit is contained in:
Alessio Di Mauro
2015-08-28 17:15:11 +02:00
parent 5ca058bdfa
commit d2cefc66b7
5 changed files with 245 additions and 9 deletions
+164 -3
View File
@@ -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;
}
+10
View File
@@ -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
+11
View File
@@ -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;
+5 -1
View File
@@ -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
View File
@@ -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;