diff --git a/libsks/src/pkcs11_api.c b/libsks/src/pkcs11_api.c index 370264aa..3a0b6ff7 100644 --- a/libsks/src/pkcs11_api.c +++ b/libsks/src/pkcs11_api.c @@ -25,6 +25,13 @@ static int inited; return CKR_ARGUMENTS_BAD; \ } while (0) +#define SANITY_SESSION_FLAGS(flags) \ + do { \ + if (flags & ~(CKF_RW_SESSION | \ + CKF_SERIAL_SESSION)) \ + return CKR_ARGUMENTS_BAD; \ + } while (0) + #define REGISTER_CK_FUNCTION(_function) ._function = _function #define DO_NOT_REGISTER_CK_FUNCTION(_function) ._function = NULL @@ -41,10 +48,10 @@ static const CK_FUNCTION_LIST libsks_function_list = { REGISTER_CK_FUNCTION(C_InitToken), DO_NOT_REGISTER_CK_FUNCTION(C_InitPIN), DO_NOT_REGISTER_CK_FUNCTION(C_SetPIN), - DO_NOT_REGISTER_CK_FUNCTION(C_OpenSession), - DO_NOT_REGISTER_CK_FUNCTION(C_CloseSession), - DO_NOT_REGISTER_CK_FUNCTION(C_CloseAllSessions), - DO_NOT_REGISTER_CK_FUNCTION(C_GetSessionInfo), + REGISTER_CK_FUNCTION(C_OpenSession), + REGISTER_CK_FUNCTION(C_CloseSession), + REGISTER_CK_FUNCTION(C_CloseAllSessions), + REGISTER_CK_FUNCTION(C_GetSessionInfo), DO_NOT_REGISTER_CK_FUNCTION(C_GetOperationState), DO_NOT_REGISTER_CK_FUNCTION(C_SetOperationState), DO_NOT_REGISTER_CK_FUNCTION(C_Login), @@ -342,41 +349,103 @@ CK_RV C_OpenSession(CK_SLOT_ID slot, CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session) { - (void)slot; - (void)flags; - (void)cookie; - (void)callback; - (void)session; + CK_RV rv; + SANITY_LIB_INIT; + SANITY_SESSION_FLAGS(flags); - return CKR_FUNCTION_NOT_SUPPORTED; + /* Specific mandated flag */ + if (!(flags & CKF_SERIAL_SESSION)) + return CKR_SESSION_PARALLEL_NOT_SUPPORTED; + rv = sks_ck_open_session(slot, flags, cookie, callback, session); + + switch (rv) { + case CKR_CRYPTOKI_NOT_INITIALIZED: + case CKR_DEVICE_ERROR: + case CKR_DEVICE_MEMORY: + case CKR_DEVICE_REMOVED: + case CKR_FUNCTION_FAILED: + case CKR_GENERAL_ERROR: + case CKR_HOST_MEMORY: + case CKR_OK: + case CKR_SESSION_COUNT: + case CKR_SESSION_PARALLEL_NOT_SUPPORTED: + case CKR_SESSION_READ_WRITE_SO_EXISTS: + case CKR_SLOT_ID_INVALID: + case CKR_TOKEN_NOT_PRESENT: + case CKR_TOKEN_NOT_RECOGNIZED: + case CKR_TOKEN_WRITE_PROTECTED: + case CKR_ARGUMENTS_BAD: + break; + default: + ASSERT(rv); + } + + return rv; } CK_RV C_CloseSession(CK_SESSION_HANDLE session) { - (void)session; + CK_RV rv; + SANITY_LIB_INIT; - return CKR_FUNCTION_NOT_SUPPORTED; + rv = sks_ck_close_session(session); + + switch (rv) { + case CKR_CRYPTOKI_NOT_INITIALIZED: + case CKR_DEVICE_ERROR: + case CKR_DEVICE_MEMORY: + case CKR_DEVICE_REMOVED: + case CKR_FUNCTION_FAILED: + case CKR_GENERAL_ERROR: + case CKR_HOST_MEMORY: + case CKR_OK: + case CKR_SESSION_CLOSED: + case CKR_SESSION_HANDLE_INVALID: + break; + default: + ASSERT(rv); + } + + return rv; } CK_RV C_CloseAllSessions(CK_SLOT_ID slot) { - (void)slot; + CK_RV rv; + SANITY_LIB_INIT; - return CKR_FUNCTION_NOT_SUPPORTED; + rv = sks_ck_close_all_sessions(slot); + + switch (rv) { + case CKR_CRYPTOKI_NOT_INITIALIZED: + case CKR_DEVICE_ERROR: + case CKR_DEVICE_MEMORY: + case CKR_DEVICE_REMOVED: + case CKR_FUNCTION_FAILED: + case CKR_GENERAL_ERROR: + case CKR_HOST_MEMORY: + case CKR_OK: + case CKR_SLOT_ID_INVALID: + case CKR_TOKEN_NOT_PRESENT: + break; + default: + ASSERT(rv); + } + + return rv; } CK_RV C_GetSessionInfo(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info) { - (void)session; - (void)info; SANITY_LIB_INIT; + SANITY_NONNULL_PTR(info); - return CKR_FUNCTION_NOT_SUPPORTED; + return sks_ck_get_session_info(session, info); } CK_RV C_InitPIN(CK_SESSION_HANDLE session, diff --git a/libsks/src/pkcs11_token.c b/libsks/src/pkcs11_token.c index fccfbbaf..98b9f426 100644 --- a/libsks/src/pkcs11_token.c +++ b/libsks/src/pkcs11_token.c @@ -253,3 +253,70 @@ CK_RV sks_ck_token_mechanism_info(CK_SLOT_ID slot, } return rv; } + +/* + * TODO: with following code, the session identifier are abstracted by the SKS + * library. It could be better to let the TA provide the handle, so that + * several applications can see the same session identifiers. + */ +CK_RV sks_ck_open_session(CK_SLOT_ID slot, + CK_FLAGS flags, + CK_VOID_PTR cookie, + CK_NOTIFY callback, + CK_SESSION_HANDLE_PTR session) +{ + uint32_t ctrl[1] = { slot }; + unsigned long cmd; + uint32_t handle; + size_t out_sz = sizeof(handle); + CK_RV rv; + + if (cookie || callback) { + LOG_ERROR("C_OpenSession does not handle callback yet\n"); + return CKR_FUNCTION_NOT_SUPPORTED; + } + + if (flags & CKF_RW_SESSION) + cmd = SKS_CMD_CK_OPEN_RW_SESSION; + else + cmd = SKS_CMD_CK_OPEN_RO_SESSION; + + rv = ck_invoke_ta(NULL, cmd, &ctrl, sizeof(ctrl), + NULL, 0, &handle, &out_sz); + if (rv) + return rv; + + *session = handle; + + return CKR_OK; +} + +CK_RV sks_ck_close_session(CK_SESSION_HANDLE session) +{ + uint32_t ctrl[1] = { (uint32_t)session }; + + return ck_invoke_ta(NULL, SKS_CMD_CK_CLOSE_SESSION, + &ctrl, sizeof(ctrl), NULL, 0, NULL, NULL); +} + +/* + * Scan all registered session handle by the lib + * and close all session related to the target slot. + */ +CK_RV sks_ck_close_all_sessions(CK_SLOT_ID slot) +{ + uint32_t ctrl[1] = { (uint32_t)slot }; + + return ck_invoke_ta(NULL, SKS_CMD_CK_CLOSE_ALL_SESSIONS, + &ctrl, sizeof(ctrl), NULL, 0, NULL, NULL); +} + +CK_RV sks_ck_get_session_info(CK_SESSION_HANDLE session, + CK_SESSION_INFO_PTR info) +{ + uint32_t ctrl[1] = { (uint32_t)session }; + size_t info_size = sizeof(CK_SESSION_INFO); + + return ck_invoke_ta(NULL, SKS_CMD_CK_SESSION_INFO, + &ctrl, sizeof(ctrl), NULL, 0, info, &info_size); +} diff --git a/libsks/src/pkcs11_token.h b/libsks/src/pkcs11_token.h index affdee4a..d52ab9ef 100644 --- a/libsks/src/pkcs11_token.h +++ b/libsks/src/pkcs11_token.h @@ -30,4 +30,14 @@ CK_RV sks_ck_init_token(CK_SLOT_ID slot, CK_ULONG pin_len, CK_UTF8CHAR_PTR label); +CK_RV sks_ck_open_session(CK_SLOT_ID slot, + CK_FLAGS flags, + CK_VOID_PTR cookie, + CK_NOTIFY callback, + CK_SESSION_HANDLE_PTR session); +CK_RV sks_ck_close_session(CK_SESSION_HANDLE session); +CK_RV sks_ck_close_all_sessions(CK_SLOT_ID slot); +CK_RV sks_ck_get_session_info(CK_SESSION_HANDLE session, + CK_SESSION_INFO_PTR info); + #endif /*__PKCS11_TOKEN_H*/