Started major overhaul of slot vendors and token vendors.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
#include "mechanisms.h"
|
||||
|
||||
// Supported mechanisms for signature
|
||||
static const CK_MECHANISM_TYPE sign[] = {
|
||||
CKM_RSA_PKCS,
|
||||
CKM_RSA_PKCS_PSS,
|
||||
CKM_RSA_X_509,
|
||||
CKM_SHA1_RSA_PKCS,
|
||||
CKM_SHA256_RSA_PKCS,
|
||||
CKM_SHA384_RSA_PKCS,
|
||||
CKM_SHA512_RSA_PKCS,
|
||||
CKM_SHA1_RSA_PKCS_PSS,
|
||||
CKM_SHA256_RSA_PKCS_PSS,
|
||||
CKM_SHA384_RSA_PKCS_PSS,
|
||||
CKM_SHA512_RSA_PKCS_PSS,
|
||||
CKM_ECDSA,
|
||||
CKM_ECDSA_SHA1
|
||||
};
|
||||
|
||||
CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m, const CK_OBJECT_HANDLE k) {
|
||||
|
||||
CK_ULONG i;
|
||||
CK_BBOOL supported = CK_FALSE;
|
||||
|
||||
/* Check if mechanism is supported by the module */
|
||||
for (i = 0; i < sizeof(sign) / sizeof(CK_MECHANISM_TYPE); i++) {
|
||||
if (m->mechanism == sign[i]) {
|
||||
supported = CK_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (supported == CK_FALSE)
|
||||
return CKR_MECHANISM_INVALID;
|
||||
|
||||
/* Check if mechanism is supported by the token */
|
||||
|
||||
|
||||
CK_OK;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef MECHANISMS_H
|
||||
#define MECHANISMS_H
|
||||
|
||||
#include "pkcs11t.h"
|
||||
|
||||
|
||||
CK_RV check_sign_mechanism(const CK_MECHANISM_PTR m, const CK_OBJECT_HANDLE k);
|
||||
|
||||
|
||||
#endif
|
||||
+95
-8
@@ -1,4 +1,5 @@
|
||||
#include "utils.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
CK_BBOOL has_token(const ykcs11_slot_t *slot) {
|
||||
@@ -7,7 +8,7 @@ CK_BBOOL has_token(const ykcs11_slot_t *slot) {
|
||||
|
||||
}
|
||||
|
||||
CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len,
|
||||
CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len,
|
||||
ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token) {
|
||||
|
||||
CK_BYTE i;
|
||||
@@ -40,6 +41,7 @@ CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len,
|
||||
strncpy(slots[*n_slots].info.slotDescription, p, sizeof(slots[*n_slots].info.slotDescription));
|
||||
}
|
||||
else {
|
||||
// Supported slot
|
||||
vendor = get_vendor(slots[*n_slots].vid);
|
||||
|
||||
// Values must NOT be null terminated and ' ' padded
|
||||
@@ -48,31 +50,116 @@ CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len,
|
||||
s = slots[*n_slots].info.slotDescription;
|
||||
l = sizeof(slots[*n_slots].info.slotDescription);
|
||||
if (vendor.get_slot_description(s, l) != CKR_OK)
|
||||
return CK_FALSE;
|
||||
goto failure;
|
||||
|
||||
memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID));
|
||||
s = slots[*n_slots].info.manufacturerID;
|
||||
l = sizeof(slots[*n_slots].info.manufacturerID);
|
||||
if(vendor.get_slot_manufacturer(s, l) != CKR_OK)
|
||||
return CK_FALSE;
|
||||
goto failure;
|
||||
|
||||
if (vendor.get_slot_flags(&slots[*n_slots].info.flags) != CKR_OK)
|
||||
return CK_FALSE;
|
||||
goto failure;
|
||||
|
||||
// Treating hw and fw version the same
|
||||
if (vendor.get_slot_version(&slots[*n_slots].info.hardwareVersion) != CKR_OK)
|
||||
return CK_FALSE;
|
||||
goto failure;
|
||||
|
||||
if (vendor.get_slot_version(&slots[*n_slots].info.firmwareVersion) != CKR_OK)
|
||||
return CK_FALSE;
|
||||
goto failure;
|
||||
|
||||
if (has_token(slots + *n_slots))
|
||||
if (has_token(slots + *n_slots)) {
|
||||
// Save token information
|
||||
(*n_with_token)++;
|
||||
|
||||
if (create_token(p, slots + *n_slots) != CKR_OK)
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
(*n_slots)++;
|
||||
p += i + 1;
|
||||
}
|
||||
|
||||
return CK_TRUE;
|
||||
return CKR_OK;
|
||||
|
||||
failure:
|
||||
// TODO: destroy all token objects
|
||||
for (i = 0; i < *n_slots; i++)
|
||||
if (has_token(slots + i))
|
||||
destroy_token(slots + i);
|
||||
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot) {
|
||||
vendor_t token_vendor;
|
||||
CK_TOKEN_INFO_PTR t_info;
|
||||
fprintf(stderr, "Now trying to get token info from %s\n", p); // TODO: is p needed?
|
||||
|
||||
slot->token = malloc(sizeof(ykcs11_token_t)); // TODO: free
|
||||
if (slot->token == NULL)
|
||||
return CKR_HOST_MEMORY;
|
||||
|
||||
slot->token->vid = YUBICO; // TODO: this must become "slot_vendor.get_token_vid()"
|
||||
token_vendor = get_vendor(slot->token->vid);
|
||||
|
||||
t_info = &slot->token->info;
|
||||
|
||||
memset(t_info->label, ' ', sizeof(t_info->label));
|
||||
if (token_vendor.get_token_label(t_info->label, sizeof(t_info->label)) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
memset(t_info->manufacturerID, ' ', sizeof(t_info->manufacturerID));
|
||||
if(token_vendor.get_token_manufacturer(t_info->manufacturerID, sizeof(t_info->manufacturerID)) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
memset(t_info->model, ' ', sizeof(t_info->model));
|
||||
if(token_vendor.get_token_model(t_info->model, sizeof(t_info->model)) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
memset(t_info->serialNumber, ' ', sizeof(t_info->serialNumber));
|
||||
if(token_vendor.get_token_serial(t_info->serialNumber, sizeof(t_info->serialNumber)) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
if (token_vendor.get_token_flags(&t_info->flags) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
t_info->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
t_info->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
t_info->ulMaxRwSessionCount = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
t_info->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
t_info->ulMaxPinLen = 8;
|
||||
|
||||
t_info->ulMinPinLen = 6;
|
||||
|
||||
t_info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
t_info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
t_info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
t_info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
//ykpiv_get_version(piv_state, buf, sizeof(buf));
|
||||
//if (token_vendor.get_token_version(buf, strlen(buf), &ver) != CKR_OK) // TODO: fix this
|
||||
// return CKR_FUNCTION_FAILED;
|
||||
|
||||
//t_info->hardwareVersion = ver; // version number of hardware // TODO: fix
|
||||
|
||||
//t_info->firmwareVersion = ver; // version number of firmware // TODO: fix
|
||||
|
||||
memset(t_info->utcTime, ' ', sizeof(t_info->utcTime)); // No clock present, clear
|
||||
|
||||
// TODO: also get token objects here? (and destroy on failure)
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
void destroy_token(ykcs11_slot_t *slot) {
|
||||
free(slot->token);
|
||||
slot->token = NULL;
|
||||
}
|
||||
|
||||
+4
-9
@@ -1,16 +1,11 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include "pkcs11t.h"
|
||||
#include "vendors.h"
|
||||
|
||||
typedef struct {
|
||||
vendor_id_t vid;
|
||||
CK_SLOT_INFO info;
|
||||
} ykcs11_slot_t; // TODO: move this
|
||||
#include "ykcs11.h"
|
||||
|
||||
CK_BBOOL has_token(const ykcs11_slot_t *slot);
|
||||
CK_BBOOL parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len,
|
||||
CK_RV parse_readers(const CK_BYTE_PTR readers, const CK_ULONG len,
|
||||
ykcs11_slot_t *slots, CK_ULONG_PTR n_slots, CK_ULONG_PTR n_with_token);
|
||||
|
||||
CK_RV create_token(CK_BYTE_PTR p, ykcs11_slot_t *slot);
|
||||
void destroy_token(ykcs11_slot_t *slot);
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ vendor_t get_vendor(vendor_id_t vid) {
|
||||
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_objects_num = YUBICO_get_token_objects_num;
|
||||
v.get_token_object_list = YUBICO_get_token_object_list;
|
||||
break;
|
||||
|
||||
@@ -48,7 +48,7 @@ vendor_t get_vendor(vendor_id_t vid) {
|
||||
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_objects_num = NULL;
|
||||
v.get_token_object_list = NULL;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -23,8 +23,8 @@ 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)(CK_ULONG_PTR);
|
||||
typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG_PTR);
|
||||
typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR);
|
||||
typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG);
|
||||
|
||||
|
||||
typedef struct {
|
||||
@@ -41,7 +41,7 @@ typedef struct {
|
||||
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_objects_num_f get_token_objects_num;
|
||||
get_t_object_list_f get_token_object_list;
|
||||
} vendor_t;
|
||||
|
||||
|
||||
+115
-112
@@ -1,8 +1,10 @@
|
||||
#include "ykcs11.h"
|
||||
#include "pkcs11.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ykpiv.h>
|
||||
#include <string.h>
|
||||
#include "vendors.h"
|
||||
//#include "vendors.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define D(x) do { \
|
||||
@@ -44,8 +46,7 @@ static ykcs11_slot_t slots[YKCS11_MAX_SLOTS]; // TODO: build at runtime?
|
||||
static CK_ULONG n_slots = 0;
|
||||
static CK_ULONG n_slots_with_token = 0;
|
||||
|
||||
static CK_SESSION_HANDLE session = CK_INVALID_HANDLE; // TODO: support multiple sessions?
|
||||
static CK_SESSION_INFO session_info;
|
||||
static ykcs11_session_t session; // TODO: support multiple sessions?
|
||||
|
||||
static struct {
|
||||
CK_BBOOL active;
|
||||
@@ -54,8 +55,8 @@ static struct {
|
||||
piv_obj_id_t *objects;
|
||||
} find_obj;
|
||||
|
||||
static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tide this up, also build at runtime (during open session)?
|
||||
static CK_ULONG n_token_objects = 0;
|
||||
/*static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tide this up, also build at runtime (during open session)? And include inside a session struct?
|
||||
static CK_ULONG n_token_objects = 0;*/
|
||||
|
||||
static struct {
|
||||
CK_BBOOL active;
|
||||
@@ -236,8 +237,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(
|
||||
{
|
||||
DIN;
|
||||
CK_VERSION ver = {0, 0};
|
||||
vendor_id_t vid;
|
||||
vendor_t vendor;
|
||||
vendor_t token_vendor;
|
||||
CK_BYTE buf[64];
|
||||
|
||||
if (piv_state == NULL)
|
||||
@@ -246,10 +246,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(
|
||||
if (slotID >= n_slots)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
vid = slots[slotID].vid;
|
||||
|
||||
if (vid == UNKNOWN) {
|
||||
DBG(("No support for token in slot %lu", slotID));
|
||||
if (slots[slotID].vid == UNKNOWN) {
|
||||
DBG(("No support for slot %lu", slotID));
|
||||
return CKR_TOKEN_NOT_RECOGNIZED;
|
||||
}
|
||||
|
||||
@@ -258,57 +256,29 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
}
|
||||
|
||||
vendor = get_vendor(vid); // TODO: make a token field in slot_t ?
|
||||
if (slots[slotID].token->vid == UNKNOWN) {
|
||||
DBG(("No support for token in slot %lu", slotID));
|
||||
return CKR_TOKEN_NOT_RECOGNIZED;
|
||||
}
|
||||
|
||||
memset(pInfo->label, ' ', sizeof(pInfo->label));
|
||||
if (vendor.get_token_label(pInfo->label, sizeof(pInfo->label)) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
token_vendor = get_vendor(slots[slotID].token->vid);
|
||||
|
||||
memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
|
||||
if(vendor.get_token_manufacturer(pInfo->manufacturerID, sizeof(pInfo->manufacturerID)) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
memset(pInfo->model, ' ', sizeof(pInfo->model));
|
||||
if(vendor.get_token_model(pInfo->model, sizeof(pInfo->model)) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber));
|
||||
if(vendor.get_token_serial(pInfo->serialNumber, sizeof(pInfo->serialNumber)) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
// bit flags indicating capabilities and status of the device as defined below // TODO: what about other flags? Like last attempt
|
||||
if (vendor.get_token_flags(&pInfo->flags) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
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
|
||||
|
||||
pInfo->ulMaxRwSessionCount = CK_UNAVAILABLE_INFORMATION; // maximum number of read/write sessions that can be opened with the token at one time by a single TODO: should this be 1?
|
||||
|
||||
pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION; // number of read/write sessions that this application currently has open with the token
|
||||
|
||||
pInfo->ulMaxPinLen = PIV_MAX_PIN_LEN; // maximum length in bytes of the PIN
|
||||
|
||||
pInfo->ulMinPinLen = PIV_MIN_PIN_LEN; // minimum length in bytes of the PIN
|
||||
|
||||
pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
|
||||
|
||||
ykpiv_get_version(piv_state, buf, sizeof(buf));
|
||||
if (vendor.get_token_version(buf, strlen(buf), &ver) != CKR_OK)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
pInfo->hardwareVersion = ver; // version number of hardware
|
||||
|
||||
pInfo->firmwareVersion = ver; // version number of firmware
|
||||
|
||||
memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime)); // No clock present, clear
|
||||
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
@@ -406,7 +376,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)(
|
||||
if (vendor.get_token_mechanism_info(type, pInfo) != CKR_OK)
|
||||
return CKR_MECHANISM_INVALID;
|
||||
|
||||
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
}
|
||||
@@ -459,7 +428,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
|
||||
{
|
||||
DIN;
|
||||
|
||||
vendor_t vendor;
|
||||
vendor_t token_vendor;
|
||||
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
@@ -468,6 +437,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
if (slots[slotID].vid == UNKNOWN) {
|
||||
DBG(("No support for slot %lu", slotID));
|
||||
return CKR_TOKEN_NOT_RECOGNIZED;
|
||||
}
|
||||
|
||||
if (slots[slotID].token->vid == UNKNOWN) {
|
||||
DBG(("No support for token in slot %lu", slotID));
|
||||
return CKR_TOKEN_NOT_RECOGNIZED;
|
||||
}
|
||||
@@ -477,44 +451,59 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
}
|
||||
|
||||
vendor = get_vendor(slots[slotID].vid); // TODO: make a token field in slot_t ?
|
||||
|
||||
// Store all the objects available in the token
|
||||
n_token_objects = sizeof(token_objects) / sizeof(piv_obj_id_t);
|
||||
if (vendor.get_token_object_list(piv_state, token_objects, &n_token_objects) != CKR_OK) {
|
||||
DBG(("Unable to retrieve token objects"));
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
if ((flags & CKF_SERIAL_SESSION) == 0) { // TODO: check more error conditions
|
||||
DBG(("Open session called without CKF_SERIAL_SESSION set"));
|
||||
return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (session != CK_INVALID_HANDLE) {
|
||||
if (session.handle != CK_INVALID_HANDLE) {
|
||||
DBG(("A session with this or another token already exists"));
|
||||
return CKR_SESSION_COUNT;
|
||||
}
|
||||
|
||||
// TODO: make sue we don't open a session with an UNKNOWN slot/token
|
||||
if ((flags & CKF_SERIAL_SESSION) == 0) { // TODO: check more error conditions
|
||||
DBG(("Open session called without CKF_SERIAL_SESSION set")); // Reuired by specs
|
||||
return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
session = YKCS11_SESSION_ID;
|
||||
session_info.slotID = slotID;
|
||||
// TODO: KEEP TRACK OF THE APPLICATION
|
||||
token_vendor = get_vendor(slots[slotID].token->vid);
|
||||
|
||||
// Store the slot
|
||||
session.slot = slots + slotID;
|
||||
//session.slot->info.slotID = slotID; // Redundant but required in CK_SESSION_INFO
|
||||
|
||||
// Get the number of token objects
|
||||
if (token_vendor.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_vendor.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)) {
|
||||
// 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
|
||||
}
|
||||
else {
|
||||
// R/O Session
|
||||
session_info.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default session
|
||||
session.info.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default session
|
||||
}
|
||||
|
||||
session_info.flags = flags;
|
||||
session_info.ulDeviceError = 0;
|
||||
session.info.flags = flags;
|
||||
session.info.ulDeviceError = 0;
|
||||
|
||||
*phSession = session;
|
||||
session.handle = YKCS11_SESSION_ID;
|
||||
// TODO: KEEP TRACK OF THE APPLICATION
|
||||
|
||||
*phSession = session.handle;
|
||||
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
@@ -529,16 +518,21 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)(
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if (session == CK_INVALID_HANDLE) {
|
||||
if (session.handle == CK_INVALID_HANDLE) {
|
||||
DBG(("There is no existing session"));
|
||||
return CKR_SESSION_CLOSED;
|
||||
}
|
||||
|
||||
if (hSession != YKCS11_SESSION_ID)
|
||||
if (hSession != YKCS11_SESSION_ID) {
|
||||
DBG(("Unknown session %lu", hSession));
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
session = CK_INVALID_HANDLE;
|
||||
memset(&session_info, 0, sizeof(CK_SESSION_INFO));
|
||||
free(session.slot->token->objects); // TODO: make objects survive a session so there is no need to get them again?
|
||||
session.slot->token->objects = NULL;
|
||||
|
||||
memset(&session, 0, sizeof(ykcs11_session_t));
|
||||
session.handle = CK_INVALID_HANDLE;
|
||||
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
@@ -549,18 +543,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)(
|
||||
)
|
||||
{
|
||||
DIN;
|
||||
CK_RV rv;
|
||||
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if (session_info.slotID != slotID)
|
||||
if (session.slot != slots + slotID)
|
||||
return CKR_SLOT_ID_INVALID;
|
||||
|
||||
session = CK_INVALID_HANDLE;
|
||||
memset(&session_info, 0, sizeof(CK_SESSION_INFO)); // TODO: Better to call close session?
|
||||
rv = C_CloseSession(session.handle);
|
||||
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)(
|
||||
@@ -576,10 +570,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)(
|
||||
if (pInfo == NULL)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
if (hSession != session)
|
||||
if (hSession != session.handle)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
memcpy(pInfo, &session_info, sizeof(CK_SESSION_INFO));
|
||||
memcpy(pInfo, &session.info, sizeof(CK_SESSION_INFO));
|
||||
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
@@ -635,25 +629,25 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
|
||||
|
||||
DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen));
|
||||
|
||||
if (session == CK_INVALID_HANDLE)
|
||||
if (session.handle == CK_INVALID_HANDLE)
|
||||
return CKR_SESSION_CLOSED;
|
||||
|
||||
if (hSession != session)
|
||||
if (hSession != session.handle)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
if (userType != CKU_SO &&
|
||||
if (userType != CKU_SO && // TODO: what can SO do?
|
||||
userType != CKU_USER &&
|
||||
userType != CKU_CONTEXT_SPECIFIC)
|
||||
return CKR_USER_TYPE_INVALID;
|
||||
|
||||
if ((session_info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these?
|
||||
if ((session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these?
|
||||
DBG(("Tried to log-in to a read-only session"));
|
||||
return CKR_SESSION_READ_ONLY_EXISTS;
|
||||
}
|
||||
|
||||
switch (userType) {
|
||||
case CKU_USER:
|
||||
if (session_info.state == CKS_RW_USER_FUNCTIONS)
|
||||
if (session.info.state == CKS_RW_USER_FUNCTIONS)
|
||||
return CKR_USER_ALREADY_LOGGED_IN;
|
||||
|
||||
tries = 0;
|
||||
@@ -747,10 +741,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)(
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if (session != YKCS11_SESSION_ID)
|
||||
if (session.handle != YKCS11_SESSION_ID)
|
||||
return CKR_SESSION_CLOSED;
|
||||
|
||||
if (hSession != session)
|
||||
if (hSession != session.handle)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
if (pTemplate == NULL_PTR || ulCount == 0)
|
||||
@@ -800,25 +794,28 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if (session != YKCS11_SESSION_ID)
|
||||
if (session.handle != YKCS11_SESSION_ID)
|
||||
return CKR_SESSION_CLOSED;
|
||||
|
||||
if (hSession != session)
|
||||
return CKR_SESSION_HANDLE_INVALID; // TODO: or session closed?
|
||||
if (hSession != session.handle)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
if (find_obj.active == CK_TRUE)
|
||||
return CKR_OPERATION_ACTIVE;
|
||||
|
||||
if (slots[session_info.slotID].vid == UNKNOWN) {
|
||||
DBG(("Slot %lu is tokenless/unsupported", session_info.slotID));
|
||||
return CKR_SLOT_ID_INVALID;
|
||||
//vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?;
|
||||
|
||||
find_obj.idx = 0;
|
||||
find_obj.num = session.slot->token->n_objects;
|
||||
|
||||
find_obj.objects = malloc(sizeof(piv_obj_id_t) * find_obj.num);
|
||||
if (find_obj.objects == NULL) {
|
||||
DBG(("Unable to allocate memory for finding objects"));
|
||||
return CKR_HOST_MEMORY;
|
||||
}
|
||||
vendor = get_vendor(slots[session_info.slotID].vid); // TODO: make a token field in slot_t ?;
|
||||
memcpy(find_obj.objects, session.slot->token->objects, sizeof(piv_obj_id_t) * find_obj.num); // TODO: add another 'num' field for then objects have to be excluded because of attribute matching;
|
||||
|
||||
find_obj.active = CK_TRUE;
|
||||
find_obj.idx = 0;
|
||||
find_obj.num = n_token_objects; // TOTO: actually malloc here so that the array can be changed
|
||||
find_obj.objects = token_objects;
|
||||
|
||||
if (ulCount == 0) {
|
||||
DBG(("Find ALL the objects!"));
|
||||
@@ -838,9 +835,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(
|
||||
// TODO: remove objects that don't match
|
||||
}
|
||||
|
||||
// TOTO: do it properly here, jsut a test now
|
||||
// TODO: do it properly here, jsut a test now
|
||||
find_obj.num = 1;
|
||||
find_obj.objects = token_objects + 3;
|
||||
find_obj.objects = session.slot->token->objects + 3;
|
||||
|
||||
DOUT;
|
||||
return CKR_OK;
|
||||
@@ -858,10 +855,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)(
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if (session != YKCS11_SESSION_ID)
|
||||
if (session.handle != YKCS11_SESSION_ID)
|
||||
return CKR_SESSION_CLOSED;
|
||||
|
||||
if (hSession != session)
|
||||
if (hSession != session.handle)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
if (phObject == NULL_PTR ||
|
||||
@@ -898,15 +895,18 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)(
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if (session != YKCS11_SESSION_ID)
|
||||
if (session.handle != YKCS11_SESSION_ID)
|
||||
return CKR_SESSION_CLOSED;
|
||||
|
||||
if (hSession != session)
|
||||
if (hSession != session.handle)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
if (find_obj.active != CK_TRUE)
|
||||
return CKR_OPERATION_NOT_INITIALIZED;
|
||||
|
||||
free(find_obj.objects);
|
||||
find_obj.objects = NULL;
|
||||
|
||||
find_obj.active = CK_FALSE;
|
||||
|
||||
DOUT;
|
||||
@@ -1088,17 +1088,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
|
||||
if (piv_state == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if (session != YKCS11_SESSION_ID)
|
||||
if (session.handle != YKCS11_SESSION_ID)
|
||||
return CKR_SESSION_CLOSED;
|
||||
|
||||
if (hSession != session)
|
||||
if (hSession != session.handle)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
if (pMechanism == NULL_PTR ||
|
||||
hKey == NULL_PTR)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
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 more", pMechanism->mechanism, hKey));
|
||||
|
||||
if (check_sign_mechanism(pMechanism, hKey) == CK_FALSE) // TODO: do we need session here?
|
||||
return CKR_MECHANISM_INVALID;
|
||||
|
||||
sign_info.active = CK_TRUE;
|
||||
memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM));
|
||||
@@ -1140,19 +1143,19 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
|
||||
ykpiv_rc r;
|
||||
CK_CHAR key;
|
||||
|
||||
DBG(("Sending %lu bytes to sign", /*ulDataLen*/sig_len_in));
|
||||
dump_hex(test_buf, sig_len_in, stderr, CK_TRUE);
|
||||
DBG(("Sending %lu bytes to sign", ulDataLen/*sig_len_in*/));
|
||||
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 {
|
||||
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.
|
||||
// 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)));
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef YKCS11_H
|
||||
#define YKCS11_H
|
||||
|
||||
#include "pkcs11t.h"
|
||||
#include "vendors.h"
|
||||
|
||||
typedef struct {
|
||||
vendor_id_t vid;
|
||||
CK_TOKEN_INFO info;
|
||||
piv_obj_id_t *objects;
|
||||
CK_ULONG n_objects;
|
||||
} ykcs11_token_t;
|
||||
|
||||
typedef struct {
|
||||
vendor_id_t vid;
|
||||
CK_SLOT_INFO info;
|
||||
ykcs11_token_t *token;
|
||||
} ykcs11_slot_t;
|
||||
|
||||
typedef struct {
|
||||
CK_SESSION_HANDLE handle;
|
||||
CK_SESSION_INFO info; /* slotid, state, flags, deviceerror */
|
||||
ykcs11_slot_t *slot;
|
||||
} ykcs11_session_t;
|
||||
|
||||
#endif
|
||||
@@ -29,6 +29,7 @@ YKCS11_0.1.0
|
||||
global:
|
||||
C_Initialize;
|
||||
C_GetFunctionList;
|
||||
# TODO: add more here
|
||||
local:
|
||||
*;
|
||||
};
|
||||
+24
-15
@@ -132,7 +132,6 @@ CK_RV YUBICO_get_slot_flags(CK_FLAGS_PTR flags) {
|
||||
*flags = slot_flags;
|
||||
return CKR_OK;
|
||||
|
||||
|
||||
}
|
||||
|
||||
CK_RV YUBICO_get_slot_version(CK_VERSION_PTR version) {
|
||||
@@ -251,21 +250,18 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P
|
||||
return CKR_MECHANISM_INVALID;
|
||||
|
||||
}
|
||||
|
||||
/*CK_RV YUBICO_get_token_objects_num(CK_ULONG_PTR num) {
|
||||
|
||||
*num = token_objects_num;
|
||||
return CKR_OK;
|
||||
}*/
|
||||
#include <stdio.h>
|
||||
CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG_PTR len) {
|
||||
#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) {
|
||||
CK_BYTE buf[2048];
|
||||
CK_ULONG buf_len;
|
||||
|
||||
piv_obj_id_t certs[4];
|
||||
CK_ULONG n_cert = 0;
|
||||
|
||||
if (state == NULL || obj == NULL || len == NULL_PTR)
|
||||
if (state == NULL || len == NULL_PTR)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
if (num_only == CK_FALSE && obj == NULL)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
buf_len = sizeof(buf);
|
||||
@@ -293,10 +289,18 @@ CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULO
|
||||
if (ykpiv_fetch_object(state, YKPIV_OBJ_CARD_AUTH, buf, &buf_len) == YKPIV_OK) {
|
||||
n_cert++;
|
||||
certs[3] = PIV_CERT_OBJ_X509_CARD_AUTH;
|
||||
fprintf(stderr, "Found CARD AUTH cert\n");
|
||||
fprintf(stderr, "Found CARD AUTH cert (9e)\n");
|
||||
}
|
||||
|
||||
if (n_cert + token_objects_num > *len)
|
||||
fprintf(stderr, "The total number of objects for this token is %lu\n", n_cert + token_objects_num);
|
||||
|
||||
if (num_only == CK_TRUE) {
|
||||
// We just want the number of objects
|
||||
*len = n_cert + token_objects_num;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
if (*len < n_cert + token_objects_num)
|
||||
return CKR_BUFFER_TOO_SMALL;
|
||||
|
||||
// Copy mandatory data objects
|
||||
@@ -305,8 +309,13 @@ CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULO
|
||||
// Copy certificates
|
||||
memcpy(obj + token_objects_num, certs, n_cert * sizeof(piv_obj_id_t));
|
||||
|
||||
*len = token_objects_num + n_cert;
|
||||
fprintf(stderr, "The total number of objects for this token is %lu\n", *len);
|
||||
|
||||
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_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num) {
|
||||
return get_objects(state, CK_FALSE, obj, &num);
|
||||
}
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ 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(CK_ULONG_PTR num);
|
||||
CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t * obj, CK_ULONG_PTR num);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user