First crude signature implementation plus additional refactor.

This commit is contained in:
Alessio Di Mauro
2015-07-30 17:04:24 +02:00
parent 246cf626b2
commit 175f0ff42b
15 changed files with 383 additions and 121 deletions
+4 -2
View File
@@ -39,8 +39,9 @@ libykcs11_la_SOURCES += slot_vendors.c slot_vendor.h
libykcs11_la_SOURCES += token_vendors.c token_vendor.h libykcs11_la_SOURCES += token_vendors.c token_vendor.h
libykcs11_la_SOURCES += mechanisms.c mechanisms.h libykcs11_la_SOURCES += mechanisms.c mechanisms.h
libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h libykcs11_la_SOURCES += yubico_slot.c yubico_slot.h yubico_token.c yubico_token.h
libykcs11_la_SOURCES += utils.h utils.c libykcs11_la_SOURCES += utils.c utils.h
libykcs11_la_SOURCES += obj_types.h objects.h objects.c libykcs11_la_SOURCES += openssl_utils.c openssl_utils.h
libykcs11_la_SOURCES += objects.c objects.h obj_types.h
#internal.h #internal.h
#libykcs11_la_SOURCES += error.c #libykcs11_la_SOURCES += error.c
@@ -54,6 +55,7 @@ EXTRA_libykcs11_la_DEPENDENCIES = ykcs11.map
#libykcs11_la_LIBADD = $(OPENSSL_LIBS) $(PCSC_LIBS) #libykcs11_la_LIBADD = $(OPENSSL_LIBS) $(PCSC_LIBS)
#libykcs11_la_LIBADD += $(PCSC_WIN_LIBS) $(PCSC_MACOSX_LIBS) #libykcs11_la_LIBADD += $(PCSC_WIN_LIBS) $(PCSC_MACOSX_LIBS)
libykcs11_la_LIBADD = $(LIBNSPR) ../lib/libykpiv.la libykcs11_la_LIBADD = $(LIBNSPR) ../lib/libykpiv.la
libykcs11_la_LIBADD += ../tool/libpiv_util.la
libykcs11_la_LDFLAGS = -no-undefined libykcs11_la_LDFLAGS = -no-undefined
libykcs11_la_LDFLAGS += -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) libykcs11_la_LDFLAGS += -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+18 -1
View File
@@ -40,7 +40,7 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m)
if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK) if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK)
return CKR_MECHANISM_INVALID; return CKR_MECHANISM_INVALID;
// TODO: also check that parametes make sens if any? // TODO: also check that parametes make sense if any?
CKR_OK; CKR_OK;
@@ -84,3 +84,20 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) {
// Not reached // Not reached
return CK_FALSE; return CK_FALSE;
} }
CK_RV do_sign_padding(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len,
CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) {
switch (m->mechanism) {
case CKM_RSA_PKCS:
return do_pkcs_t1(in, in_len, out, out_len, key_len);
case CKM_RSA_PKCS_PSS:
case CKM_RSA_X_509:
case CKM_SHA1_RSA_PKCS:
case CKM_SHA256_RSA_PKCS:
case CKM_SHA384_RSA_PKCS:
case CKM_SHA512_RSA_PKCS:
return CKR_FUNCTION_FAILED;
}
}
+3
View File
@@ -7,4 +7,7 @@
CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m); CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m);
CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m); CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m);
CK_RV do_sign_padding(CK_MECHANISM_PTR m, CK_BYTE_PTR in, CK_ULONG in_len,
CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len);
#endif #endif
+2 -2
View File
@@ -103,12 +103,12 @@ typedef struct {
X509 *data; X509 *data;
} piv_cert_obj_t; } piv_cert_obj_t;
typedef struct { typedef struct { // TODO: enough to use the public key for the parameters?
CK_BBOOL todo; CK_BBOOL todo;
} piv_pvtk_obj_t; } piv_pvtk_obj_t;
typedef struct { typedef struct {
CK_BBOOL todo; EVP_PKEY *data;
} piv_pubk_obj_t; } piv_pubk_obj_t;
typedef struct { typedef struct {
+64 -1
View File
@@ -3,6 +3,9 @@
#include <ykpiv.h> #include <ykpiv.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "openssl_utils.h"
#define IS_CERT(x) (((x) >= PIV_CERT_OBJ_X509_PIV_AUTH && (x) < PIV_CERT_OBJ_LAST) ? CK_TRUE : CK_FALSE)
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);
@@ -843,6 +846,38 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
} }
CK_ULONG piv_2_ykpiv(piv_obj_id_t id) {
// TODO: add retired keys
switch(id) {
case PIV_CERT_OBJ_X509_PIV_AUTH:
return YKPIV_OBJ_AUTHENTICATION;
case PIV_CERT_OBJ_X509_CARD_AUTH:
return YKPIV_OBJ_CARD_AUTH;
case PIV_CERT_OBJ_X509_DS:
return YKPIV_OBJ_SIGNATURE;
case PIV_CERT_OBJ_X509_KM:
return YKPIV_OBJ_KEY_MANAGEMENT;
case PIV_PVTK_OBJ_PIV_AUTH:
return YKPIV_KEY_AUTHENTICATION;
case PIV_PVTK_OBJ_CARD_AUTH:
return YKPIV_KEY_CARDAUTH;
case PIV_PVTK_OBJ_DS:
return YKPIV_KEY_SIGNATURE;
case PIV_PVTK_OBJ_KM:
return YKPIV_KEY_KEYMGM;
default:
return 0ul;
}
}
CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
CK_ULONG i; CK_ULONG i;
@@ -851,6 +886,34 @@ CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR
return piv_objects[obj].get_attribute(obj, template); return piv_objects[obj].get_attribute(obj, template);
} }
return CKR_OBJECT_HANDLE_INVALID; return CKR_OBJECT_HANDLE_INVALID;
} }
CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids, CK_ULONG n_certs) {
CK_ULONG i, j;
j = 0;
for (i = 0; i < s->slot->token->n_objects; i++)
if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE)
cert_ids[j++] = s->slot->token->objects[i];
fprintf(stderr, "Just to check: %lu %lu\n", j, n_certs);
return CKR_OK;
}
CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len) {
CK_RV rv;
// Store the certificate as an object
rv = do_store_cert(data, len, &cert_objects[piv_objects[cert_id].sub_id].data);
if (rv != CKR_OK)
return rv;
// Extract and store the public key as an object
rv = do_store_pubk(cert_objects[piv_objects[cert_id].sub_id].data, &pubkey_objects[piv_objects[cert_id].sub_id].data);
return CKR_OK;
}
+4
View File
@@ -5,6 +5,10 @@
#include <stdio.h> // TODO: delete #include <stdio.h> // TODO: delete
CK_ULONG piv_2_ykpiv(piv_obj_id_t id);
CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template); CK_RV get_attribute(ykcs11_session_t *s, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template);
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);
#endif #endif
+78
View File
@@ -0,0 +1,78 @@
#include "openssl_utils.h"
#include <stdbool.h>
#include "../tool/util.h" // TODO: share this better?
CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) {
const unsigned char *p = data; // Mandatory temp variable required by OpenSSL
int cert_len;
/**cert = X509_new();
if (*cert == NULL)
return CKR_HOST_MEMORY;*/
//dump_hex(data, len, stderr, CK_TRUE);
if (*p++ != 0x70)
return CKR_FUNCTION_FAILED;
p += get_length(p, &cert_len);
*cert = d2i_X509(NULL, &p, cert_len);
if (*cert == NULL)
return CKR_FUNCTION_FAILED;
/*
BIO *STDout = BIO_new_fp(stderr, BIO_NOCLOSE);
X509_print_ex(STDout, *cert, 0, 0);
BIO_free(STDout);
*/
return CKR_OK;
}
CK_RV free_cert(X509 *cert) {
X509_free((X509 *) cert);
return CKR_OK;
}
CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key) {
*key = X509_get_pubkey(cert);
if (*key == NULL)
return CKR_FUNCTION_FAILED;
return CKR_OK;
}
CK_RV free_key(EVP_PKEY *key) {
EVP_PKEY_free(key);
return CKR_OK;
}
/* #include <stdio.h> */
/* #include <openssl/err.h> */
/* ERR_load_crypto_strings(); */
/* //SSL_load_error_strings(); */
CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) {
fprintf(stderr, "Apply padding to %lu bytes and get %lu\n", in_len, key_len);
if (out_len < key_len)
CKR_BUFFER_TOO_SMALL;
if (RSA_padding_add_PKCS1_type_1(out, key_len, in, in_len) == 0)
return CKR_FUNCTION_FAILED;
return CKR_OK;
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef OPENSSL_UTIL_H
#define OPENSSL_UTIL_H
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include "pkcs11t.h"
CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert);
CK_RV free_cert(X509 *cert);
CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key);
CK_RV free_key(EVP_PKEY *key);
CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len);
#endif
+24 -22
View File
@@ -6,32 +6,34 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
switch (vid) { switch (vid) {
case YUBICO: case YUBICO:
v.get_token_label = YUBICO_get_token_label; v.get_token_label = YUBICO_get_token_label;
v.get_token_manufacturer = YUBICO_get_token_manufacturer; v.get_token_manufacturer = YUBICO_get_token_manufacturer;
v.get_token_model = YUBICO_get_token_model; v.get_token_model = YUBICO_get_token_model;
v.get_token_flags = YUBICO_get_token_flags; v.get_token_flags = YUBICO_get_token_flags;
v.get_token_version = YUBICO_get_token_version; v.get_token_version = YUBICO_get_token_version;
v.get_token_serial = YUBICO_get_token_serial; v.get_token_serial = YUBICO_get_token_serial;
v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num; v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num;
v.get_token_mechanism_list = YUBICO_get_token_mechanism_list; v.get_token_mechanism_list = YUBICO_get_token_mechanism_list;
v.get_token_mechanism_info = YUBICO_get_token_mechanism_info; v.get_token_mechanism_info = YUBICO_get_token_mechanism_info;
v.get_token_objects_num = YUBICO_get_token_objects_num; v.get_token_objects_num = YUBICO_get_token_objects_num;
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;
break; break;
case UNKNOWN: case UNKNOWN:
default: default:
v.get_token_label = NULL; v.get_token_label = NULL;
v.get_token_manufacturer = NULL; v.get_token_manufacturer = NULL;
v.get_token_model = NULL; v.get_token_model = NULL;
v.get_token_flags = NULL; v.get_token_flags = NULL;
v.get_token_version = NULL; v.get_token_version = NULL;
v.get_token_serial = NULL; v.get_token_serial = NULL;
v.get_token_mechanisms_num = NULL; v.get_token_mechanisms_num = NULL;
v.get_token_mechanism_list = NULL; v.get_token_mechanism_list = NULL;
v.get_token_mechanism_info = NULL; v.get_token_mechanism_info = NULL;
v.get_token_objects_num = NULL; v.get_token_objects_num = NULL;
v.get_token_object_list = NULL; v.get_token_object_list = NULL;
v.get_token_raw_certificate = NULL;
} }
return v; return v;
+15 -13
View File
@@ -15,21 +15,23 @@ typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG);
typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR);
typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG); typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG);
typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR);
typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR); typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR, CK_ULONG_PTR);
typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG); typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG);
typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG);
// TODO: replace all the common call 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;
get_t_manufacturer_f get_token_manufacturer; get_t_manufacturer_f get_token_manufacturer;
get_t_model_f get_token_model; get_t_model_f get_token_model;
get_t_flags_f get_token_flags; get_t_flags_f get_token_flags;
get_t_version_f get_token_version; get_t_version_f get_token_version;
get_t_serial_f get_token_serial; get_t_serial_f get_token_serial;
get_t_mechanisms_num_f get_token_mechanisms_num; get_t_mechanisms_num_f get_token_mechanisms_num;
get_t_mechanism_list_f get_token_mechanism_list; get_t_mechanism_list_f get_token_mechanism_list;
get_t_mechanism_info_f get_token_mechanism_info; get_t_mechanism_info_f get_token_mechanism_info;
get_t_objects_num_f get_token_objects_num; get_t_objects_num_f get_token_objects_num;
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;
} 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);
+2
View File
@@ -156,6 +156,8 @@ CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) {
memset(t_info->utcTime, ' ', sizeof(t_info->utcTime)); // No clock present, clear memset(t_info->utcTime, ' ', sizeof(t_info->utcTime)); // No clock present, clear
// TODO: also get token objects here? (and destroy on failure) // TODO: also get token objects here? (and destroy on failure)
slot->token->objects = NULL;
slot->token->n_objects = 0;
return CKR_OK; return CKR_OK;
} }
+126 -67
View File
@@ -23,10 +23,12 @@
#define PIV_MIN_PIN_LEN 6 #define PIV_MIN_PIN_LEN 6
#define PIV_MAX_PIN_LEN 8 #define PIV_MAX_PIN_LEN 8
#define YKCS11_MAX_SLOTS 16 #define YKCS11_MAX_SLOTS 16
#define YKCS11_MAX_SIG_BUF_LEN 1024
#define YKCS11_SESSION_ID 5355104 #define YKCS11_SESSION_ID 5355104
#if YKCS11_DBG #if YKCS11_DBG
#define DBG(x) D(x); #define DBG(x) D(x);
#else #else
@@ -60,9 +62,10 @@ static struct {
static CK_ULONG n_token_objects = 0;*/ static CK_ULONG n_token_objects = 0;*/
static struct { static struct {
CK_BBOOL active; CK_BBOOL active;
CK_MECHANISM mechanism; CK_MECHANISM mechanism;
CK_OBJECT_HANDLE key; CK_ULONG key;
CK_BYTE algo;
} sign_info; } sign_info;
extern CK_FUNCTION_LIST function_list; // TODO: check all return values extern CK_FUNCTION_LIST function_list; // TODO: check all return values
@@ -430,9 +433,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
CK_SESSION_HANDLE_PTR phSession CK_SESSION_HANDLE_PTR phSession
) )
{ {
DIN; DIN; // TODO: pApplication and Notify
token_vendor_t token; token_vendor_t token;
CK_RV rv;
piv_obj_id_t *cert_ids;
CK_ULONG i;
CK_BYTE cert_data[2100]; // Max cert value for ykpiv
CK_ULONG cert_len = sizeof(cert_data);
if (piv_state == NULL) { if (piv_state == NULL) {
DBG(("libykpiv is not initialized or already finalized")); DBG(("libykpiv is not initialized or already finalized"));
@@ -473,27 +481,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
session.slot = slots + slotID; session.slot = slots + slotID;
//session.slot->info.slotID = slotID; // Redundant but required in CK_SESSION_INFO //session.slot->info.slotID = slotID; // Redundant but required in CK_SESSION_INFO
// Get the number of token objects // Store session flags
if (token.get_token_objects_num(piv_state, &session.slot->token->n_objects) != CKR_OK) {
DBG(("Unable to retrieve number of token objects"));
return CKR_FUNCTION_FAILED;
}
// Get memory for the objects
session.slot->token->objects = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_objects);
if (session.slot->token->objects == NULL) {
DBG(("Unable to allocate memory for token objects"));
return CKR_HOST_MEMORY;
}
// Store all the objects available in the token
if (token.get_token_object_list(piv_state,
session.slot->token->objects,
session.slot->token->n_objects) != CKR_OK) {
DBG(("Unable to retrieve token objects"));
return CKR_FUNCTION_FAILED;
}
if ((flags & CKF_RW_SESSION)) { if ((flags & CKF_RW_SESSION)) {
// R/W Session // R/W Session
session.info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session session.info.state = CKS_RW_PUBLIC_SESSION; // Nobody has logged in, default session
@@ -506,13 +494,78 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
session.info.flags = flags; session.info.flags = flags;
session.info.ulDeviceError = 0; session.info.ulDeviceError = 0;
// Get the number of token objects
rv = token.get_token_objects_num(piv_state, &session.slot->token->n_objects, &session.slot->token->n_certs);
if (rv != CKR_OK) {
DBG(("Unable to retrieve number of token objects"));
return rv;
}
// Get memory for the objects
session.slot->token->objects = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_objects);
if (session.slot->token->objects == NULL) {
DBG(("Unable to allocate memory for token object ids"));
return CKR_HOST_MEMORY;
}
// Get memory for the certificates
cert_ids = malloc(sizeof(piv_obj_id_t) * session.slot->token->n_certs);
if (cert_ids == NULL) {
DBG(("Unable to allocate memory for token certificate ids"));
return CKR_HOST_MEMORY;
}
// Save a list of all the available objects in the token // TODO: change behavior based on login status
rv = token.get_token_object_list(piv_state, session.slot->token->objects, session.slot->token->n_objects);
if (rv != CKR_OK) {
DBG(("Unable to retrieve token objects"));
goto failure;
}
// Get a list object ids for available certificates object from the session
rv = get_available_certificate_ids(&session, cert_ids, session.slot->token->n_certs); // TODO: better to get this from token? how?
if (rv != CKR_OK) {
DBG(("Unable to retrieve certificate ids from the session"));
goto failure;
}
// Get the actual certificate data from the token and store it as an X509 object
for (i = 0; i < session.slot->token->n_certs; i++) {
rv = token.get_token_raw_certificate(piv_state, cert_ids[i], cert_data, cert_len);
if (rv != CKR_OK) {
DBG(("Unable to get certificate data from token"));
goto failure;
}
rv = store_cert(cert_ids[i], cert_data, cert_len);
if (rv != CKR_OK) {
DBG(("Unable to store certificate data"));
goto failure;
}
}
session.handle = YKCS11_SESSION_ID; session.handle = YKCS11_SESSION_ID;
// TODO: KEEP TRACK OF THE APPLICATION // TODO: KEEP TRACK OF THE APPLICATION (possble to steal a session?)
*phSession = session.handle; *phSession = session.handle;
DOUT; DOUT;
return CKR_OK; return CKR_OK;
failure:
if (session.slot->token->objects != NULL) {
free(session.slot->token->objects);
session.slot->token->objects = NULL;
}
if (cert_ids != NULL) {
free(cert_ids);
cert_ids = NULL;
}
free_certs(); // TODO
return rv;
} }
CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)( CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)(
@@ -677,7 +730,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
return CKR_USER_TYPE_INVALID; // TODO: only allow regular user for now return CKR_USER_TYPE_INVALID; // TODO: only allow regular user for now
} }
DBG(("You win! %lu", tries)) DBG(("You win! %lu", tries));
// TODO: update session objects now that we're logged in ?
DOUT; DOUT;
return CKR_OK; return CKR_OK;
@@ -856,9 +911,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(
// TODO: remove objects that don't match // TODO: remove objects that don't match
} }
// TODO: do it properly here, jsut a test now // TODO: do it properly here, just a test now
//find_obj.objects = session.slot->token->objects + 3; //find_obj.objects = session.slot->token->objects + 3;
memmove(find_obj.objects, find_obj.objects + 3, sizeof(piv_obj_id_t) * (find_obj.num - 3)); memmove(find_obj.objects, find_obj.objects + 14, sizeof(piv_obj_id_t) * (find_obj.num - 14));
find_obj.num = 1; find_obj.num = 1;
DOUT; DOUT;
@@ -1128,33 +1183,41 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
DBG(("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey)); DBG(("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey));
// Check if mechanism is supported
if (check_sign_mechanism(&session, pMechanism) != CKR_OK) { if (check_sign_mechanism(&session, pMechanism) != CKR_OK) {
DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism)); DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism));
return CKR_MECHANISM_INVALID; return CKR_MECHANISM_INVALID;
} }
memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM));
// Get key algorithm
/*if (get_key_algo(hKey, &sign_info.algo) != CKR_OK) {
DBG(("Unable to retrieve type for key %lu", hKey));
return CKR_FUNCTION_FAILED;
}*/ // TODO: use get attribute instead?
sign_info.algo = YKPIV_ALGO_RSA2048; // TODO: fix
sign_info.key = piv_2_ykpiv(hKey);
if (sign_info.key == 0) {
DBG(("Incorrect key %lu", hKey));
return CKR_KEY_HANDLE_INVALID;
}
// Make sure that both mechanism and key have the same algorithm
if ((is_RSA_mechanism(pMechanism->mechanism) && sign_info.algo == YKPIV_ALGO_ECCP256) ||
(!is_RSA_mechanism(pMechanism->mechanism) && (sign_info.algo != YKPIV_ALGO_ECCP256))) {
DBG(("Key and mechanism algorithm do not match"));
return CKR_ARGUMENTS_BAD;
}
// TODO: also allocate some space for the signature in case of multipart
sign_info.active = CK_TRUE; sign_info.active = CK_TRUE;
memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM));
sign_info.key = hKey;
// TODO: also allocate some space for the signature
DOUT; DOUT;
return CKR_OK; return CKR_OK;
} }
/* TOTOD: DELETE */
CK_BYTE sig_buf[1024];
CK_ULONG sig_len = 1024;
void dump_hex(const unsigned char *buf, unsigned int len, FILE *output, CK_BBOOL space) {
unsigned int i;
for (i = 0; i < len; i++) {
fprintf(output, "%02x%s", buf[i], space == CK_TRUE ? " " : "");
}
fprintf(output, "\n");
}
/* TODO: DELETE END*/
CK_DEFINE_FUNCTION(CK_RV, C_Sign)( CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
CK_SESSION_HANDLE hSession, CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pData, CK_BYTE_PTR pData,
@@ -1164,39 +1227,35 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
) )
{ {
DIN; DIN;
CK_BYTE buf[YKCS11_MAX_SIG_BUF_LEN];
CK_ULONG buf_len = sizeof(buf);
if (sign_info.active == CK_FALSE) if (sign_info.active == CK_FALSE)
return CKR_OPERATION_NOT_INITIALIZED; return CKR_OPERATION_NOT_INITIALIZED;
// TODO: check conditions // TODO: check conditions
char test_buf[] = "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20\xa7\x47\x16\x1b\x15\x5f\xd0\x05\xbc\xbe\x84\x4a\x28\xa9\x6c\x74\xfe\xf6\x6a\x42\x84\xa0\x4e\x05\x7a\x0c\x88\xe2\xc8\x83\xc0\x00";
CK_ULONG sig_len_in = sizeof(test_buf) - 1;
CK_ULONG sig_len_out = 1024;
ykpiv_rc r; ykpiv_rc r;
CK_CHAR key; CK_CHAR algo;
DBG(("Sending %lu bytes to sign", ulDataLen/*sig_len_in*/)); DBG(("Sending %lu bytes to sign", ulDataLen));
dump_hex(pData, ulDataLen, stderr, CK_TRUE); dump_hex(pData, ulDataLen, stderr, CK_TRUE);
if (sign_info.key == PIV_DATA_OBJ_X509_PIV_AUTH) { /* if (do_sign_padding(&sign_info.mechanism, pData, ulDataLen, buf, buf_len, 2048 / 8) != CKR_OK) {
key = YKPIV_KEY_AUTHENTICATION; DBG(("Unable to apply padding scheme"));
DBG(("Using key 9a")); return CKR_FUNCTION_FAILED;
} }*/
else { // TODO: test what happens if there is no key on the card memcpy(buf, pData, ulDataLen); // ykpiv does padding already
key = YKPIV_KEY_SIGNATURE; //dump_hex(buf, 256, stderr, CK_TRUE);
DBG(("Using key 9c")); //*pulSignatureLen = 256;
} DBG(("Using key %lx", sign_info.key)); // TODO: test what happens if there is no key on the card
if ((r = ykpiv_sign_data(piv_state, buf, ulDataLen, pSignature, pulSignatureLen, YKPIV_ALGO_RSA2048, sign_info.key)) != YKPIV_OK) {
// TODO: check that mechanism makes sense for the key that we have (check in signinit). DBG(("Sign error, %s", ykpiv_strerror(r)));
if ((r = ykpiv_sign_data(piv_state, /*pData*/test_buf, /*ulDataLen*/sig_len_in, sig_buf, &sig_len_out, YKPIV_ALGO_RSA2048, key)) != YKPIV_OK) {
DBG(("Sign error %s", ykpiv_strerror(r)));
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
} }
DBG(("Got %lu bytes back", sig_len_out)); DBG(("Got %lu bytes back", *pulSignatureLen));
dump_hex(sig_buf, sig_len_out, stderr, CK_TRUE); dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE);
memcpy(pSignature, sig_buf, sig_len_out); /* memcpy(pSignature, sig_buf, sig_len_out);
*pulSignatureLen = sig_len_out; *pulSignatureLen = sig_len_out;*/
DOUT; DOUT;
return CKR_OK; return CKR_OK;
} }
+3 -2
View File
@@ -8,8 +8,9 @@
typedef struct { typedef struct {
vendor_id_t vid; vendor_id_t vid;
CK_TOKEN_INFO info; CK_TOKEN_INFO info;
piv_obj_id_t *objects; piv_obj_id_t *objects; // List of objects in the token
CK_ULONG n_objects; CK_ULONG n_objects; // TOTAL number of objects in the token
CK_ULONG n_certs; // Number of certificate objects in the token (portion of n_objects)
} ykcs11_token_t; } ykcs11_token_t;
typedef struct { typedef struct {
+16 -5
View File
@@ -210,11 +210,12 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P
} }
#include <stdio.h> // TODO: delete #include <stdio.h> // TODO: delete
static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *obj, CK_ULONG_PTR len) { static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
piv_obj_id_t *obj, CK_ULONG_PTR len, CK_ULONG_PTR num_certs) {
CK_BYTE buf[2048]; CK_BYTE buf[2048];
CK_ULONG buf_len; CK_ULONG buf_len;
piv_obj_id_t certs[4]; piv_obj_id_t certs[4]; // TODO: this can be > 4 if there are retired keys
piv_obj_id_t pvtkeys[4]; piv_obj_id_t pvtkeys[4];
piv_obj_id_t pubkeys[4]; piv_obj_id_t pubkeys[4];
CK_ULONG n_cert = 0; CK_ULONG n_cert = 0;
@@ -267,6 +268,8 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *ob
// We just want the number of objects // We just want the number of objects
// Each cert object counts for 3: cert, pub key, pvt key // Each cert object counts for 3: cert, pub key, pvt key
*len = (n_cert * 3) + token_objects_num; *len = (n_cert * 3) + token_objects_num;
if (num_certs != NULL)
*num_certs = n_cert;
return CKR_OK; return CKR_OK;
} }
@@ -286,10 +289,18 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only, piv_obj_id_t *ob
return CKR_OK; return CKR_OK;
} }
CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num) { CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num, CK_ULONG_PTR num_certs) {
return get_objects(state, CK_TRUE, NULL, num); return get_objects(state, CK_TRUE, NULL, num, num_certs);
} }
CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num) { CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num) {
return get_objects(state, CK_FALSE, obj, &num); return get_objects(state, CK_FALSE, obj, &num, NULL);
}
CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG len) {
if (ykpiv_fetch_object(state, piv_2_ykpiv(obj), data, &len) != YKPIV_OK)
return CKR_FUNCTION_FAILED;
return CKR_OK;
} }
+3 -2
View File
@@ -14,7 +14,8 @@ CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VER
CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num); CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num);
CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num); CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num);
CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info); CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info);
CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num); CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num, CK_ULONG_PTR num_certs);
CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t * obj, CK_ULONG num); CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num);
CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG len);
#endif #endif