Added certificate import

This commit is contained in:
Alessio Di Mauro
2015-08-28 13:47:57 +02:00
parent d7f5dd35f4
commit 5ca058bdfa
8 changed files with 255 additions and 11 deletions
+2 -2
View File
@@ -13,8 +13,8 @@ CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG i
CK_RV apply_sign_mechanism_finalize(op_info_t *op_info); CK_RV apply_sign_mechanism_finalize(op_info_t *op_info);
CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m);
CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); // TODO: Move to objects.c
CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n); // TODO: Move to objects.c
CK_RV check_hash_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_RV check_hash_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m);
+47
View File
@@ -4,6 +4,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "openssl_utils.h" #include "openssl_utils.h"
#include "utils.h"
#include "debug.h" #include "debug.h"
#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)
@@ -912,3 +913,49 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) {
return CKR_OK; return CKR_OK;
} }
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_ULONG i;
CK_BBOOL has_id = CK_FALSE;
CK_BBOOL has_value = CK_FALSE;
for (i = 0; i < n; i++) {
switch (templ[i].type) {
case CKA_CLASS:
// Technically redundant check
if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_CERTIFICATE)
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 = 0;
*cert_len += get_length(value + 1, cert_len) + 1;
break;
default:
// 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)
return CKR_TEMPLATE_INCOMPLETE;
return CKR_OK;
}
+3
View File
@@ -12,4 +12,7 @@ CK_BBOOL is_private_object(ykcs11_session_t *s, CK_OBJECT_HANDLE obj);
CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs); CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs);
CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); 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_BYTE_PTR *value, CK_ULONG_PTR cert_len);
#endif #endif
+28 -4
View File
@@ -14,10 +14,16 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) {
return CKR_HOST_MEMORY;*/ return CKR_HOST_MEMORY;*/
//dump_hex(data, len, stderr, CK_TRUE); //dump_hex(data, len, stderr, CK_TRUE);
if (*p++ != 0x70) if (*p == 0x70) {
return CKR_FUNCTION_FAILED; // The certificate is in "PIV" format 0x70 len 0x30 len ...
p++;
p += get_length(p, &cert_len); p += get_length(p, &cert_len);
}
else {
// Raw certificate 0x30 len ...
cert_len = 0;
cert_len += get_length(p + 1, &cert_len) + 1;
}
*cert = d2i_X509(NULL, &p, cert_len); *cert = d2i_X509(NULL, &p, cert_len);
if (*cert == NULL) if (*cert == NULL)
@@ -223,6 +229,24 @@ create_empty_cert_cleanup:
return rv; return rv;
} }
CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len) {
X509 *cert;
const unsigned char *p = in; // Mandatory temp variable required by OpenSSL
int len;
len = 0;
len += get_length(p + 1, &len) + 1;
*cert_len = len;
cert = d2i_X509(NULL, &p, *cert_len);
if (cert == NULL)
return CKR_FUNCTION_FAILED;
return CKR_OK;
}
CK_RV free_cert(X509 *cert) { CK_RV free_cert(X509 *cert) {
X509_free((X509 *) cert); X509_free((X509 *) cert);
+1
View File
@@ -12,6 +12,7 @@
CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert);
CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ULONG key_len, CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_ULONG key_len,
CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_BYTE_PTR out, CK_ULONG_PTR out_len);
CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len);
CK_RV free_cert(X509 *cert); CK_RV free_cert(X509 *cert);
CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key);
+39
View File
@@ -1,7 +1,9 @@
#include "token_vendors.h" #include "token_vendors.h"
#include "yubico_token.h" #include "yubico_token.h"
#include "openssl_utils.h"
#include <string.h> #include <string.h>
#include "debug.h" #include "debug.h"
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) {
// TODO: make a function in ykpiv for this // TODO: make a function in ykpiv for this
unsigned char in_data[5]; unsigned char in_data[5];
@@ -85,6 +87,41 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE
return CKR_OK; return CKR_OK;
} }
static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_BYTE_PTR in) {
unsigned char certdata[2100];
unsigned char *certptr;
CK_ULONG cert_len;
CK_RV rv;
// Check whether or not we have a valid cert
if ((rv = do_check_cert(in, &cert_len)) != CKR_OK)
return rv;
if (cert_len > 2100)
return CKR_FUNCTION_FAILED;
certptr = certdata;
*certptr++ = 0x70;
certptr += set_length(certptr, cert_len);
memcpy(certptr, in, cert_len);
certptr += cert_len;
*certptr++ = 0x71;
*certptr++ = 1;
*certptr++ = 0; /* certinfo (gzip etc) */
*certptr++ = 0xfe; /* LRC */
*certptr++ = 0;
// Store the certificate into the token
if (ykpiv_save_object(state, cert_id, certdata, (size_t)(certptr - certdata)) != YKPIV_OK)
return CKR_DEVICE_ERROR;
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;
@@ -103,6 +140,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
v.get_token_object_list = YUBICO_get_token_object_list; v.get_token_object_list = YUBICO_get_token_object_list;
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;
break; break;
case UNKNOWN: case UNKNOWN:
@@ -120,6 +158,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
v.get_token_object_list = NULL; v.get_token_object_list = NULL;
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;
} }
return v; return v;
+2
View File
@@ -21,6 +21,7 @@ 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);
// TODO: replace all the common call with functions defined in .c that use libykpiv // TODO: replace all the common call with functions defined in .c that use libykpiv
@@ -38,6 +39,7 @@ typedef struct {
get_t_object_list_f get_token_object_list; get_t_object_list_f get_token_object_list;
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;
} 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);
+133 -5
View File
@@ -821,7 +821,136 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
) )
{ {
DIN; DIN;
DBG(("TODO!!!"));
CK_ULONG i;
CK_RV rv;
CK_OBJECT_CLASS class;
CK_BYTE id;
CK_BYTE_PTR value;
CK_ULONG len;
token_vendor_t token;
CK_BBOOL is_new;
CK_OBJECT_HANDLE object;
CK_ULONG cert_id;
CK_ULONG pvtk_id;
CK_ULONG pubk_id;
piv_obj_id_t *obj_ptr;
if (piv_state == NULL) {
DBG(("libykpiv is not initialized or already finalized"));
return CKR_CRYPTOKI_NOT_INITIALIZED;
}
if (session.handle != YKCS11_SESSION_ID) {
DBG(("Session is not open"));
return CKR_SESSION_CLOSED;
}
if (hSession != session.handle) {
DBG(("Unknown session %lu", hSession));
return CKR_SESSION_HANDLE_INVALID;
}
if (session.info.state != CKS_RW_SO_FUNCTIONS) { // TODO: does a regular user ever call this function?
DBG(("Authentication required to import objects"));
return CKR_SESSION_READ_ONLY;
}
if (pTemplate == NULL_PTR ||
phObject == NULL_PTR) {
DBG(("Wrong/Missing parameter"));
return CKR_ARGUMENTS_BAD;
}
class = CKO_VENDOR_DEFINED; // Use this as a known value
for (i = 0; i < ulCount; i++) {
if (pTemplate[i].type == CKA_CLASS) {
class = *((CK_ULONG_PTR)pTemplate[i].pValue);
// Can only import certificates and private keys
if (*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_CERTIFICATE &&
*((CK_ULONG_PTR)pTemplate[i].pValue) != CKO_PUBLIC_KEY) {
DBG(("Unsupported class %lu", class));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
}
if (class == CKO_VENDOR_DEFINED) {
DBG(("Object class must be specified"));
return CKR_TEMPLATE_INCOMPLETE;
}
token = get_token_vendor(session.slot->token->vid);
switch (class) {
case CKO_CERTIFICATE:
DBG(("Importing certificate"));
rv = check_create_cert(pTemplate, ulCount, &id, &value, &len);
if (rv != CKR_OK) {
DBG(("Certificate template not valid"));
return rv;
}
DBG(("Certificate id is %u", 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
if (rv != CKR_OK) {
DBG(("Unable to import certificate"));
return rv;
}
is_new = CK_TRUE;
for (i = 0; i < session.slot->token->n_objects; i++) {
if (session.slot->token->objects[i] == object)
is_new = CK_FALSE;
}
cert_id = PIV_CERT_OBJ_X509_PIV_AUTH + id; // TODO: make function for these
pvtk_id = PIV_PVTK_OBJ_PIV_AUTH + id;
pubk_id = PIV_PUBK_OBJ_PIV_AUTH + id;
// Check whether we created a new object or updated an existing one
if (is_new == CK_TRUE) {
// New object created, add it to the object list
// Each object counts as three, even if we just only added a certificate
session.slot->token->n_objects += 3;
session.slot->token->n_certs++;
obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t));
if (obj_ptr == NULL) {
DBG(("Unable to store new item in the session"));
return CKR_HOST_MEMORY;
}
session.slot->token->objects = obj_ptr;
obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 3;
*obj_ptr++ = cert_id;
*obj_ptr++ = pvtk_id;
*obj_ptr++ = pubk_id;
}
rv = store_cert(cert_id, value, len);
if (rv != CKR_OK) {
DBG(("Unable to store certificate data"));
return CKR_FUNCTION_FAILED;
}
break;
case CKO_PRIVATE_KEY:
//rv = create_pvt_key();
return CKR_FUNCTION_FAILED;
break;
default:
DBG(("Unknown object type"));
return CKR_ATTRIBUTE_TYPE_INVALID;
}
DOUT; DOUT;
return CKR_OK; return CKR_OK;
} }
@@ -1865,8 +1994,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(
if (is_new == CK_TRUE) { if (is_new == CK_TRUE) {
// New object created, add it to the object list // New object created, add it to the object list
// Each object counts as four // Each object counts as three (data object is always there)
session.slot->token->n_objects += 4; session.slot->token->n_objects += 3;
session.slot->token->n_certs++; session.slot->token->n_certs++;
obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t)); obj_ptr = realloc(session.slot->token->objects, session.slot->token->n_objects * sizeof(piv_obj_id_t));
@@ -1876,8 +2005,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(
} }
session.slot->token->objects = obj_ptr; session.slot->token->objects = obj_ptr;
obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 4; obj_ptr = session.slot->token->objects + session.slot->token->n_objects - 3;
*obj_ptr++ = dobj_id;
*obj_ptr++ = cert_id; *obj_ptr++ = cert_id;
*obj_ptr++ = pvtk_id; *obj_ptr++ = pvtk_id;
*obj_ptr++ = pubk_id; *obj_ptr++ = pubk_id;