Added key import.

This commit is contained in:
Alessio Di Mauro
2015-09-01 14:08:19 +02:00
parent d2cefc66b7
commit f646ec9dde
6 changed files with 154 additions and 74 deletions
+65 -28
View File
@@ -9,6 +9,9 @@
#define IS_CERT(x) (((x) >= PIV_CERT_OBJ_X509_PIV_AUTH && (x) < PIV_CERT_OBJ_LAST) ? CK_TRUE : CK_FALSE) #define IS_CERT(x) (((x) >= PIV_CERT_OBJ_X509_PIV_AUTH && (x) < PIV_CERT_OBJ_LAST) ? CK_TRUE : CK_FALSE)
#define F4 "\x01\x00\x01" // TODO: already define in mechanisms.c. Move
#define PRIME256V1 "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07" // TODO: already define in mechanisms.c. Move
CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); // TODO: static? CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); // TODO: static?
CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template);
CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template);
@@ -942,13 +945,16 @@ 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 += get_length(value + 1, cert_len) + 1;*/
*cert_len = templ[i].ulValueLen; *cert_len = templ[i].ulValueLen;
break; break;
default: // TODO: don't error on valid parameters case CKA_TOKEN:
// Ignore other attributes for now case CKA_LABEL:
case CKA_SUBJECT:
// Ignore other attributes
break;
default:
DBG(("Invalid %lx", templ[i].type)); DBG(("Invalid %lx", templ[i].type));
return CKR_ATTRIBUTE_TYPE_INVALID; return CKR_ATTRIBUTE_TYPE_INVALID;
} }
@@ -962,14 +968,16 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n,
} }
CK_RV check_create_ec_key(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 cert_len, CK_BYTE_PTR *value, CK_ULONG_PTR value_len) {
CK_BYTE_PTR *ec_params, CK_ULONG_PTR ec_params_len) {
CK_ULONG i; CK_ULONG i;
CK_BBOOL has_id = CK_FALSE; CK_BBOOL has_id = CK_FALSE;
CK_BBOOL has_value = CK_FALSE; CK_BBOOL has_value = CK_FALSE;
CK_BBOOL has_params = CK_FALSE; CK_BBOOL has_params = CK_FALSE;
CK_BYTE_PTR ec_params;
CK_ULONG ec_params_len;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
switch (templ[i].type) { switch (templ[i].type) {
case CKA_CLASS: case CKA_CLASS:
@@ -995,19 +1003,25 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
case CKA_VALUE: case CKA_VALUE:
has_value = CK_TRUE; has_value = CK_TRUE;
*value = (CK_BYTE_PTR)templ[i].pValue; *value = (CK_BYTE_PTR)templ[i].pValue;
*cert_len = templ[i].ulValueLen; *value_len = templ[i].ulValueLen;
break; break;
case CKA_EC_PARAMS: case CKA_EC_PARAMS:
has_params = CK_TRUE; has_params = CK_TRUE;
*ec_params = (CK_BYTE_PTR)templ[i].pValue; ec_params = (CK_BYTE_PTR)templ[i].pValue;
*ec_params_len = templ[i].ulValueLen; ec_params_len = templ[i].ulValueLen;
break; break;
default: // TODO: don't error on valid parameters case CKA_TOKEN:
// Ignore other attributes for now case CKA_LABEL:
case CKA_SUBJECT:
case CKA_SENSITIVE:
case CKA_DERIVE:
// Ignore other attributes
break;
default:
DBG(("Invalid %lx", templ[i].type)); DBG(("Invalid %lx", templ[i].type));
return CKR_ATTRIBUTE_TYPE_INVALID; return CKR_ATTRIBUTE_TYPE_INVALID;
} }
@@ -1018,16 +1032,18 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
has_params == CK_FALSE) has_params == CK_FALSE)
return CKR_TEMPLATE_INCOMPLETE; return CKR_TEMPLATE_INCOMPLETE;
if (*value_len != 32)
return CKR_ATTRIBUTE_VALUE_INVALID;
if (*value_len == 32 && (ec_params_len != 10 || memcmp(ec_params, PRIME256V1, ec_params_len)) != 0)
return CKR_TEMPLATE_INCONSISTENT;
return CKR_OK; return CKR_OK;
} }
CK_RV check_create_rsa_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 *e, CK_ULONG_PTR e_len, CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp,
CK_BYTE_PTR *p, CK_ULONG_PTR p_len, CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_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_ULONG i;
CK_BBOOL has_id = CK_FALSE; CK_BBOOL has_id = CK_FALSE;
@@ -1037,6 +1053,11 @@ 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_dp = CK_FALSE;
CK_BBOOL has_dq = CK_FALSE; CK_BBOOL has_dq = CK_FALSE;
CK_BBOOL has_qinv = CK_FALSE; CK_BBOOL has_qinv = CK_FALSE;
CK_ULONG p_len;
CK_ULONG q_len;
CK_ULONG dp_len;
CK_ULONG dq_len;
CK_ULONG qinv_len;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
switch (templ[i].type) { switch (templ[i].type) {
@@ -1060,50 +1081,57 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
break; break;
case CKA_PUBLIC_EXPONENT: // TODO: check that it is F4 case CKA_PUBLIC_EXPONENT:
has_e = CK_TRUE; has_e = CK_TRUE;
*e = (CK_BYTE_PTR)templ[i].pValue;
*e_len = templ[i].ulValueLen;
if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, F4, 3) != 0)
return CKR_ATTRIBUTE_VALUE_INVALID;
break; break;
case CKA_PRIME_1: case CKA_PRIME_1:
has_p = CK_TRUE; has_p = CK_TRUE;
*p = (CK_BYTE_PTR)templ[i].pValue; *p = (CK_BYTE_PTR)templ[i].pValue;
*p_len = templ[i].ulValueLen; p_len = templ[i].ulValueLen;
break; break;
case CKA_PRIME_2: case CKA_PRIME_2:
has_q = CK_TRUE; has_q = CK_TRUE;
*q = (CK_BYTE_PTR)templ[i].pValue; *q = (CK_BYTE_PTR)templ[i].pValue;
*q_len = templ[i].ulValueLen; q_len = templ[i].ulValueLen;
break; break;
case CKA_EXPONENT_1: case CKA_EXPONENT_1:
has_dp = CK_TRUE; has_dp = CK_TRUE;
*dp = (CK_BYTE_PTR)templ[i].pValue; *dp = (CK_BYTE_PTR)templ[i].pValue;
*dp_len = templ[i].ulValueLen; dp_len = templ[i].ulValueLen;
break; break;
case CKA_EXPONENT_2: case CKA_EXPONENT_2:
has_dq = CK_TRUE; has_dq = CK_TRUE;
*dq = (CK_BYTE_PTR)templ[i].pValue; *dq = (CK_BYTE_PTR)templ[i].pValue;
*dq_len = templ[i].ulValueLen; dq_len = templ[i].ulValueLen;
break; break;
case CKA_COEFFICIENT: case CKA_COEFFICIENT:
has_qinv = CK_TRUE; has_qinv = CK_TRUE;
*qinv = (CK_BYTE_PTR)templ[i].pValue; *qinv = (CK_BYTE_PTR)templ[i].pValue;
*qinv_len = templ[i].ulValueLen; qinv_len = templ[i].ulValueLen;
break; break;
default: // TODO: don't error on valid parameters case CKA_TOKEN:
// Ignore other attributes for now case CKA_LABEL:
case CKA_SUBJECT:
case CKA_SENSITIVE:
case CKA_DERIVE:
// Ignore other attributes
break;
default:
DBG(("Invalid %lx", templ[i].type)); DBG(("Invalid %lx", templ[i].type));
return CKR_ATTRIBUTE_TYPE_INVALID; return CKR_ATTRIBUTE_TYPE_INVALID;
} }
@@ -1118,5 +1146,14 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
has_qinv == CK_FALSE) has_qinv == CK_FALSE)
return CKR_TEMPLATE_INCOMPLETE; return CKR_TEMPLATE_INCOMPLETE;
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)
return CKR_ATTRIBUTE_VALUE_INVALID;
return CKR_OK; return CKR_OK;
} }
+4 -8
View File
@@ -15,14 +15,10 @@ 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_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 *value, CK_ULONG_PTR value_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_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_BYTE_PTR *q, CK_BYTE_PTR *dp,
CK_BYTE_PTR *p, CK_ULONG_PTR p_len, CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_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
+56 -4
View File
@@ -122,10 +122,62 @@ 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_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYTE_PTR p, CK_BYTE_PTR q,
CK_BYTE_PTR q, CK_ULONG q_len, CK_BYTE_PTR dp, CK_ULONG dp_len, CK_BYTE_PTR dp, CK_BYTE_PTR dq, CK_BYTE_PTR qinv,
CK_BYTE_PTR dq, CK_ULONG dq_len, CK_BYTE_PTR qinv, CK_ULONG qinv_len, CK_BYTE_PTR ec_data, CK_ULONG elem_len) {
CK_BYTE_PTR ec_data, CK_ULONG ec_data_len) {
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;
if (elem_len == 128)
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;
}
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;
}
if(ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK)
return CKR_FUNCTION_FAILED;
if(sw != 0x9000)
return CKR_DEVICE_ERROR;
return CKR_OK; return CKR_OK;
+2 -3
View File
@@ -22,9 +22,8 @@ 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, 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_ULONG, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG);
CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG);
// TODO: replace all the common calls with functions defined in .c that use libykpiv // TODO: replace all the common calls with functions defined in .c that use libykpiv
+11 -15
View File
@@ -830,18 +830,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
CK_ULONG value_len; CK_ULONG value_len;
CK_BYTE_PTR ec_params; CK_BYTE_PTR ec_params;
CK_ULONG ec_params_len; CK_ULONG ec_params_len;
CK_BYTE_PTR e;
CK_ULONG e_len;
CK_BYTE_PTR p; CK_BYTE_PTR p;
CK_ULONG p_len;
CK_BYTE_PTR q; CK_BYTE_PTR q;
CK_ULONG q_len;
CK_BYTE_PTR dp; CK_BYTE_PTR dp;
CK_ULONG dp_len;
CK_BYTE_PTR dq; CK_BYTE_PTR dq;
CK_ULONG dq_len;
CK_BYTE_PTR qinv; 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_BBOOL is_rsa;
@@ -910,7 +903,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
} }
DBG(("Certificate id is %u", id)); DBG(("Certificate id is %u", id));
object = PIV_CERT_OBJ_X509_PIV_AUTH + id ; object = PIV_CERT_OBJ_X509_PIV_AUTH + id;
rv = token.token_import_cert(piv_state, piv_2_ykpiv(object), value); // TODO: make function to get cert id rv = token.token_import_cert(piv_state, piv_2_ykpiv(object), value); // TODO: make function to get cert id
if (rv != CKR_OK) { if (rv != CKR_OK) {
@@ -962,12 +955,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
// Try to parse the key as EC // Try to parse the key as EC
is_rsa = CK_FALSE; is_rsa = CK_FALSE;
rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &ec_params, &ec_params_len); rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len);
if (rv != CKR_OK) { if (rv != CKR_OK) {
// Try to parse the key as RSA // Try to parse the key as RSA
is_rsa = CK_TRUE; is_rsa = CK_TRUE;
rv = check_create_rsa_key(pTemplate, ulCount, &id, &e, &e_len, &p, &p_len, rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len);
&q, &q_len, &dp, &dp_len, &dq, &dq_len, &qinv, &qinv_len);
if (rv != CKR_OK) { if (rv != CKR_OK) {
DBG(("Private key template not valid")); DBG(("Private key template not valid"));
return rv; return rv;
@@ -975,10 +967,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
} }
DBG(("Key id is %u", id)); DBG(("Key id is %u", id));
DBG(("ITEM LENGTH IS %lu", value_len));
object = PIV_PVTK_OBJ_PIV_AUTH + id;
if (is_rsa == CK_TRUE) { if (is_rsa == CK_TRUE) {
DBG(("Key is RSA")); 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); rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv,
NULL,
value_len);
if (rv != CKR_OK) { if (rv != CKR_OK) {
DBG(("Unable to import RSA private key")); DBG(("Unable to import RSA private key"));
return rv; return rv;
@@ -986,14 +982,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
} }
else { else {
DBG(("Key is ECDSA")); 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); rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL,
value,
value_len);
if (rv != CKR_OK) { if (rv != CKR_OK) {
DBG(("Unable to import ECDSA private key")); DBG(("Unable to import ECDSA private key"));
return rv; return rv;
} }
} }
return CKR_FUNCTION_FAILED;
break; break;
default: default: