First crude signature implementation plus additional refactor.
This commit is contained in:
+4
-2
@@ -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 += mechanisms.c mechanisms.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 += obj_types.h objects.h objects.c
|
||||
libykcs11_la_SOURCES += utils.c utils.h
|
||||
libykcs11_la_SOURCES += openssl_utils.c openssl_utils.h
|
||||
libykcs11_la_SOURCES += objects.c objects.h obj_types.h
|
||||
|
||||
#internal.h
|
||||
#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 += $(PCSC_WIN_LIBS) $(PCSC_MACOSX_LIBS)
|
||||
libykcs11_la_LIBADD = $(LIBNSPR) ../lib/libykpiv.la
|
||||
libykcs11_la_LIBADD += ../tool/libpiv_util.la
|
||||
|
||||
libykcs11_la_LDFLAGS = -no-undefined
|
||||
libykcs11_la_LDFLAGS += -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||
|
||||
+18
-1
@@ -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)
|
||||
return CKR_MECHANISM_INVALID;
|
||||
|
||||
// TODO: also check that parametes make sens if any?
|
||||
// TODO: also check that parametes make sense if any?
|
||||
|
||||
CKR_OK;
|
||||
|
||||
@@ -84,3 +84,20 @@ CK_BBOOL is_RSA_mechanism(CK_MECHANISM_TYPE m) {
|
||||
// Not reached
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,4 +7,7 @@
|
||||
CK_RV check_sign_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR 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
|
||||
|
||||
+2
-2
@@ -103,12 +103,12 @@ typedef struct {
|
||||
X509 *data;
|
||||
} piv_cert_obj_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct { // TODO: enough to use the public key for the parameters?
|
||||
CK_BBOOL todo;
|
||||
} piv_pvtk_obj_t;
|
||||
|
||||
typedef struct {
|
||||
CK_BBOOL todo;
|
||||
EVP_PKEY *data;
|
||||
} piv_pubk_obj_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
+64
-1
@@ -3,6 +3,9 @@
|
||||
#include <ykpiv.h>
|
||||
#include <string.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_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_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 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#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_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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -6,32 +6,34 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
|
||||
|
||||
switch (vid) {
|
||||
case YUBICO:
|
||||
v.get_token_label = YUBICO_get_token_label;
|
||||
v.get_token_manufacturer = YUBICO_get_token_manufacturer;
|
||||
v.get_token_model = YUBICO_get_token_model;
|
||||
v.get_token_flags = YUBICO_get_token_flags;
|
||||
v.get_token_version = YUBICO_get_token_version;
|
||||
v.get_token_serial = YUBICO_get_token_serial;
|
||||
v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num;
|
||||
v.get_token_mechanism_list = YUBICO_get_token_mechanism_list;
|
||||
v.get_token_mechanism_info = YUBICO_get_token_mechanism_info;
|
||||
v.get_token_objects_num = YUBICO_get_token_objects_num;
|
||||
v.get_token_object_list = YUBICO_get_token_object_list;
|
||||
v.get_token_label = YUBICO_get_token_label;
|
||||
v.get_token_manufacturer = YUBICO_get_token_manufacturer;
|
||||
v.get_token_model = YUBICO_get_token_model;
|
||||
v.get_token_flags = YUBICO_get_token_flags;
|
||||
v.get_token_version = YUBICO_get_token_version;
|
||||
v.get_token_serial = YUBICO_get_token_serial;
|
||||
v.get_token_mechanisms_num = YUBICO_get_token_mechanisms_num;
|
||||
v.get_token_mechanism_list = YUBICO_get_token_mechanism_list;
|
||||
v.get_token_mechanism_info = YUBICO_get_token_mechanism_info;
|
||||
v.get_token_objects_num = YUBICO_get_token_objects_num;
|
||||
v.get_token_object_list = YUBICO_get_token_object_list;
|
||||
v.get_token_raw_certificate = YUBICO_get_token_raw_certificate;
|
||||
break;
|
||||
|
||||
case UNKNOWN:
|
||||
default:
|
||||
v.get_token_label = NULL;
|
||||
v.get_token_manufacturer = NULL;
|
||||
v.get_token_model = NULL;
|
||||
v.get_token_flags = NULL;
|
||||
v.get_token_version = NULL;
|
||||
v.get_token_serial = NULL;
|
||||
v.get_token_mechanisms_num = NULL;
|
||||
v.get_token_mechanism_list = NULL;
|
||||
v.get_token_mechanism_info = NULL;
|
||||
v.get_token_objects_num = NULL;
|
||||
v.get_token_object_list = NULL;
|
||||
v.get_token_label = NULL;
|
||||
v.get_token_manufacturer = NULL;
|
||||
v.get_token_model = NULL;
|
||||
v.get_token_flags = NULL;
|
||||
v.get_token_version = NULL;
|
||||
v.get_token_serial = NULL;
|
||||
v.get_token_mechanisms_num = NULL;
|
||||
v.get_token_mechanism_list = NULL;
|
||||
v.get_token_mechanism_info = NULL;
|
||||
v.get_token_objects_num = NULL;
|
||||
v.get_token_object_list = NULL;
|
||||
v.get_token_raw_certificate = NULL;
|
||||
}
|
||||
|
||||
return v;
|
||||
|
||||
+15
-13
@@ -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_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_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_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 {
|
||||
get_t_label_f get_token_label;
|
||||
get_t_manufacturer_f get_token_manufacturer;
|
||||
get_t_model_f get_token_model;
|
||||
get_t_flags_f get_token_flags;
|
||||
get_t_version_f get_token_version;
|
||||
get_t_serial_f get_token_serial;
|
||||
get_t_mechanisms_num_f get_token_mechanisms_num;
|
||||
get_t_mechanism_list_f get_token_mechanism_list;
|
||||
get_t_mechanism_info_f get_token_mechanism_info;
|
||||
get_t_objects_num_f get_token_objects_num;
|
||||
get_t_object_list_f get_token_object_list;
|
||||
get_t_label_f get_token_label;
|
||||
get_t_manufacturer_f get_token_manufacturer;
|
||||
get_t_model_f get_token_model;
|
||||
get_t_flags_f get_token_flags;
|
||||
get_t_version_f get_token_version;
|
||||
get_t_serial_f get_token_serial;
|
||||
get_t_mechanisms_num_f get_token_mechanisms_num;
|
||||
get_t_mechanism_list_f get_token_mechanism_list;
|
||||
get_t_mechanism_info_f get_token_mechanism_info;
|
||||
get_t_objects_num_f get_token_objects_num;
|
||||
get_t_object_list_f get_token_object_list;
|
||||
get_t_raw_certificate_f get_token_raw_certificate;
|
||||
} token_vendor_t;
|
||||
|
||||
token_vendor_t get_token_vendor(vendor_id_t vid);
|
||||
|
||||
@@ -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
|
||||
|
||||
// TODO: also get token objects here? (and destroy on failure)
|
||||
slot->token->objects = NULL;
|
||||
slot->token->n_objects = 0;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
+130
-71
@@ -23,10 +23,12 @@
|
||||
#define PIV_MIN_PIN_LEN 6
|
||||
#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
|
||||
|
||||
|
||||
#if YKCS11_DBG
|
||||
#define DBG(x) D(x);
|
||||
#else
|
||||
@@ -60,9 +62,10 @@ static struct {
|
||||
static CK_ULONG n_token_objects = 0;*/
|
||||
|
||||
static struct {
|
||||
CK_BBOOL active;
|
||||
CK_MECHANISM mechanism;
|
||||
CK_OBJECT_HANDLE key;
|
||||
CK_BBOOL active;
|
||||
CK_MECHANISM mechanism;
|
||||
CK_ULONG key;
|
||||
CK_BYTE algo;
|
||||
} sign_info;
|
||||
|
||||
extern CK_FUNCTION_LIST function_list; // TODO: check all return values
|
||||
@@ -269,7 +272,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(
|
||||
token = get_token_vendor(slots[slotID].token->vid);
|
||||
|
||||
memcpy(pInfo, &slots[slotID].token->info, sizeof(CK_TOKEN_INFO));
|
||||
|
||||
|
||||
// Overwrite value that are application specific
|
||||
pInfo->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; // TODO: should this be 1?
|
||||
pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION; // number of sessions that this application currently has open with the token
|
||||
@@ -283,7 +286,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(
|
||||
pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
}
|
||||
@@ -430,9 +433,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
|
||||
CK_SESSION_HANDLE_PTR phSession
|
||||
)
|
||||
{
|
||||
DIN;
|
||||
DIN; // TODO: pApplication and Notify
|
||||
|
||||
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) {
|
||||
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->info.slotID = slotID; // Redundant but required in CK_SESSION_INFO
|
||||
|
||||
// Get the number of token objects
|
||||
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;
|
||||
}
|
||||
|
||||
// Store session flags
|
||||
if ((flags & CKF_RW_SESSION)) {
|
||||
// R/W 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.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;
|
||||
// TODO: KEEP TRACK OF THE APPLICATION
|
||||
// TODO: KEEP TRACK OF THE APPLICATION (possble to steal a session?)
|
||||
|
||||
*phSession = session.handle;
|
||||
|
||||
DOUT;
|
||||
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)(
|
||||
@@ -677,7 +730,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
|
||||
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;
|
||||
return CKR_OK;
|
||||
@@ -856,9 +911,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(
|
||||
// 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;
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
// Check if mechanism is supported
|
||||
if (check_sign_mechanism(&session, pMechanism) != CKR_OK) {
|
||||
DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism));
|
||||
return CKR_MECHANISM_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
// 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;
|
||||
|
||||
DOUT;
|
||||
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_SESSION_HANDLE hSession,
|
||||
CK_BYTE_PTR pData,
|
||||
@@ -1164,39 +1227,35 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
|
||||
)
|
||||
{
|
||||
DIN;
|
||||
CK_BYTE buf[YKCS11_MAX_SIG_BUF_LEN];
|
||||
CK_ULONG buf_len = sizeof(buf);
|
||||
|
||||
if (sign_info.active == CK_FALSE)
|
||||
return CKR_OPERATION_NOT_INITIALIZED;
|
||||
|
||||
// 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;
|
||||
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);
|
||||
|
||||
if (sign_info.key == PIV_DATA_OBJ_X509_PIV_AUTH) {
|
||||
key = YKPIV_KEY_AUTHENTICATION;
|
||||
DBG(("Using key 9a"));
|
||||
}
|
||||
else { // TODO: test what happens if there is no key on the card
|
||||
key = YKPIV_KEY_SIGNATURE;
|
||||
DBG(("Using key 9c"));
|
||||
}
|
||||
|
||||
// TODO: check that mechanism makes sense for the key that we have (check in signinit).
|
||||
|
||||
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)));
|
||||
/* if (do_sign_padding(&sign_info.mechanism, pData, ulDataLen, buf, buf_len, 2048 / 8) != CKR_OK) {
|
||||
DBG(("Unable to apply padding scheme"));
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}*/
|
||||
memcpy(buf, pData, ulDataLen); // ykpiv does padding already
|
||||
//dump_hex(buf, 256, stderr, CK_TRUE);
|
||||
//*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) {
|
||||
DBG(("Sign error, %s", ykpiv_strerror(r)));
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
DBG(("Got %lu bytes back", sig_len_out));
|
||||
dump_hex(sig_buf, sig_len_out, stderr, CK_TRUE);
|
||||
memcpy(pSignature, sig_buf, sig_len_out);
|
||||
*pulSignatureLen = sig_len_out;
|
||||
DBG(("Got %lu bytes back", *pulSignatureLen));
|
||||
dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE);
|
||||
/* memcpy(pSignature, sig_buf, sig_len_out);
|
||||
*pulSignatureLen = sig_len_out;*/
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
+3
-2
@@ -8,8 +8,9 @@
|
||||
typedef struct {
|
||||
vendor_id_t vid;
|
||||
CK_TOKEN_INFO info;
|
||||
piv_obj_id_t *objects;
|
||||
CK_ULONG n_objects;
|
||||
piv_obj_id_t *objects; // List of objects in the token
|
||||
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;
|
||||
|
||||
typedef struct {
|
||||
|
||||
+16
-5
@@ -210,11 +210,12 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P
|
||||
|
||||
}
|
||||
#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_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 pubkeys[4];
|
||||
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
|
||||
// Each cert object counts for 3: cert, pub key, pvt key
|
||||
*len = (n_cert * 3) + token_objects_num;
|
||||
if (num_certs != NULL)
|
||||
*num_certs = n_cert;
|
||||
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;
|
||||
}
|
||||
|
||||
CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num) {
|
||||
return get_objects(state, CK_TRUE, NULL, 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, num_certs);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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_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_objects_num(ykpiv_state *state, CK_ULONG_PTR num);
|
||||
CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t * obj, CK_ULONG 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_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG len);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user