From b9596b33f51d31b50f78a9a6df105c0e4293d5ca Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Mon, 27 Jul 2015 17:03:29 +0200 Subject: [PATCH] Started major overhaul of slot vendors and token vendors. --- ykcs11/mechanisms.c | 40 ++++++++ ykcs11/mechanisms.h | 10 ++ ykcs11/utils.c | 103 +++++++++++++++++-- ykcs11/utils.h | 13 +-- ykcs11/vendors.c | 4 +- ykcs11/vendors.h | 6 +- ykcs11/ykcs11.c | 243 ++++++++++++++++++++++---------------------- ykcs11/ykcs11.h | 26 +++++ ykcs11/ykcs11.map | 1 + ykcs11/yubico.c | 39 ++++--- ykcs11/yubico.h | 4 +- 11 files changed, 330 insertions(+), 159 deletions(-) create mode 100644 ykcs11/mechanisms.c create mode 100644 ykcs11/mechanisms.h create mode 100644 ykcs11/ykcs11.h diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c new file mode 100644 index 0000000..b232d9d --- /dev/null +++ b/ykcs11/mechanisms.c @@ -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; + +} diff --git a/ykcs11/mechanisms.h b/ykcs11/mechanisms.h new file mode 100644 index 0000000..5c5e02f --- /dev/null +++ b/ykcs11/mechanisms.h @@ -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 diff --git a/ykcs11/utils.c b/ykcs11/utils.c index 81dac8d..236153d 100644 --- a/ykcs11/utils.c +++ b/ykcs11/utils.c @@ -1,4 +1,5 @@ #include "utils.h" +#include #include 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; } diff --git a/ykcs11/utils.h b/ykcs11/utils.h index 804cef0..6190913 100644 --- a/ykcs11/utils.h +++ b/ykcs11/utils.h @@ -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 diff --git a/ykcs11/vendors.c b/ykcs11/vendors.c index 2b75387..b4fd55d 100644 --- a/ykcs11/vendors.c +++ b/ykcs11/vendors.c @@ -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; } diff --git a/ykcs11/vendors.h b/ykcs11/vendors.h index 6b0d2f0..cba0763 100644 --- a/ykcs11/vendors.h +++ b/ykcs11/vendors.h @@ -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; diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index a7dacb8..934076b 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -1,8 +1,10 @@ +#include "ykcs11.h" #include "pkcs11.h" #include +#include #include #include -#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,58 +256,30 @@ 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; - - 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; + token_vendor = get_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 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!")); @@ -832,15 +829,15 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)( find_obj.active = CK_FALSE; return CKR_ARGUMENTS_BAD; } - + for (i = 0; i < ulCount; i++) { DBG(("Parameter %lu\nType: %lu Value: %lu Len: %lu", i, pTemplate[i].type, *((CK_ULONG_PTR)pTemplate[i].pValue), pTemplate[i].ulValueLen)); // 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 || @@ -885,7 +882,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)( *pulObjectCount = 1; DBG(("Returning object %lu", *phObject)); - + return CKR_OK; } @@ -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,24 +1088,27 @@ 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)); sign_info.key = hKey; // TODO: also allocate some space for the signature - - + + DOUT; return CKR_OK; } @@ -1132,27 +1135,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)( 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; - - 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))); diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h new file mode 100644 index 0000000..0814875 --- /dev/null +++ b/ykcs11/ykcs11.h @@ -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 diff --git a/ykcs11/ykcs11.map b/ykcs11/ykcs11.map index b6b62ac..3b83e98 100644 --- a/ykcs11/ykcs11.map +++ b/ykcs11/ykcs11.map @@ -29,6 +29,7 @@ YKCS11_0.1.0 global: C_Initialize; C_GetFunctionList; +# TODO: add more here local: *; }; \ No newline at end of file diff --git a/ykcs11/yubico.c b/ykcs11/yubico.c index be80b60..c3f8f17 100644 --- a/ykcs11/yubico.c +++ b/ykcs11/yubico.c @@ -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,23 +250,20 @@ 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 -CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG_PTR len) { +#include // 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); if (ykpiv_fetch_object(state, YKPIV_OBJ_AUTHENTICATION, buf, &buf_len) == YKPIV_OK) { n_cert++; @@ -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); +} diff --git a/ykcs11/yubico.h b/ykcs11/yubico.h index 4e884b8..73edc71 100644 --- a/ykcs11/yubico.h +++ b/ykcs11/yubico.h @@ -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