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 += 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
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -17,6 +17,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
|
|||||||
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:
|
||||||
@@ -32,6 +33,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
|
|||||||
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,9 +15,10 @@ 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;
|
||||||
@@ -30,6 +31,7 @@ typedef struct {
|
|||||||
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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+123
-64
@@ -24,9 +24,11 @@
|
|||||||
#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
|
||||||
@@ -62,7 +64,8 @@ static struct {
|
|||||||
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
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user