blob: e6188e3bfc487e3769479aed756f2920f45fa013 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, Linaro Limited
*/
#include <assert.h>
#include <ck_debug.h>
#include <inttypes.h>
#ifdef OPENSSL_FOUND
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#endif
#include <pkcs11.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <utee_defines.h>
#include <util.h>
#include "xtest_test.h"
#include "xtest_helpers.h"
#include <regression_4000_data.h>
/*
* Some PKCS#11 object resources used in the tests
*/
static const CK_BYTE cktest_aes128_key[16];
static const CK_BYTE cktest_aes128_iv[16];
static const CK_AES_CTR_PARAMS cktest_aes_ctr_params = {
.ulCounterBits = 1,
};
static CK_MECHANISM cktest_aes_ecb_mechanism = {
CKM_AES_ECB,
NULL, 0,
};
static CK_MECHANISM cktest_aes_cbc_mechanism = {
CKM_AES_CBC,
(CK_BYTE_PTR)cktest_aes128_iv, sizeof(cktest_aes128_iv),
};
static CK_MECHANISM cktest_aes_ctr_mechanism = {
CKM_AES_CTR,
(CK_BYTE_PTR)&cktest_aes_ctr_params, sizeof(cktest_aes_ctr_params),
};
static CK_MECHANISM cktest_aes_cts_mechanism = {
CKM_AES_CTS,
(CK_BYTE_PTR)cktest_aes128_iv, sizeof(cktest_aes128_iv),
};
static CK_MECHANISM cktest_aes_cmac_mechanism = {
CKM_AES_CMAC, NULL, 0,
};
static CK_MECHANISM cktest_hmac_md5_mechanism = {
CKM_MD5_HMAC, NULL, 0,
};
static CK_MECHANISM cktest_hmac_sha1_mechanism = {
CKM_SHA_1_HMAC, NULL, 0,
};
static CK_MECHANISM cktest_hmac_sha224_mechanism = {
CKM_SHA224_HMAC, NULL, 0,
};
static CK_MECHANISM cktest_hmac_sha256_mechanism = {
CKM_SHA256_HMAC, NULL, 0,
};
static CK_MECHANISM cktest_hmac_sha384_mechanism = {
CKM_SHA384_HMAC, NULL, 0,
};
static CK_MECHANISM cktest_hmac_sha512_mechanism = {
CKM_SHA512_HMAC, NULL, 0,
};
static const CK_ULONG cktest_general_mechanism_hmac_len = 8;
static CK_MECHANISM cktest_aes_cmac_general_mechanism = {
CKM_AES_CMAC_GENERAL,
(CK_VOID_PTR)&cktest_general_mechanism_hmac_len,
sizeof(CK_ULONG),
};
static CK_MECHANISM cktest_hmac_general_md5_mechanism = {
CKM_MD5_HMAC_GENERAL,
(CK_VOID_PTR)&cktest_general_mechanism_hmac_len,
sizeof(CK_ULONG),
};
static CK_MECHANISM cktest_hmac_general_sha1_mechanism = {
CKM_SHA_1_HMAC_GENERAL,
(CK_VOID_PTR)&cktest_general_mechanism_hmac_len,
sizeof(CK_ULONG),
};
static CK_MECHANISM cktest_hmac_general_sha224_mechanism = {
CKM_SHA224_HMAC_GENERAL,
(CK_VOID_PTR)&cktest_general_mechanism_hmac_len,
sizeof(CK_ULONG),
};
static CK_MECHANISM cktest_hmac_general_sha256_mechanism = {
CKM_SHA256_HMAC_GENERAL,
(CK_VOID_PTR)&cktest_general_mechanism_hmac_len,
sizeof(CK_ULONG),
};
static CK_MECHANISM cktest_hmac_general_sha384_mechanism = {
CKM_SHA384_HMAC_GENERAL,
(CK_VOID_PTR)&cktest_general_mechanism_hmac_len,
sizeof(CK_ULONG),
};
static CK_MECHANISM cktest_hmac_general_sha512_mechanism = {
CKM_SHA512_HMAC_GENERAL,
(CK_VOID_PTR)&cktest_general_mechanism_hmac_len,
sizeof(CK_ULONG),
};
static CK_MECHANISM cktest_gensecret_keygen_mechanism = {
CKM_GENERIC_SECRET_KEY_GEN, NULL, 0,
};
static CK_MECHANISM cktest_aes_keygen_mechanism = {
CKM_AES_KEY_GEN, NULL, 0,
};
/*
* Util to find a slot on which to open a session
*/
static CK_RV close_lib(void)
{
return C_Finalize(0);
}
static CK_RV init_lib_and_find_token_slot(CK_SLOT_ID *slot)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID_PTR slots = NULL;
CK_ULONG count = 0;
rv = C_Initialize(0);
if (rv)
return rv;
rv = C_GetSlotList(CK_TRUE, NULL, &count);
if (rv != CKR_OK)
goto bail;
if (count < 1) {
rv = CKR_GENERAL_ERROR;
goto bail;
}
slots = malloc(count * sizeof(CK_SLOT_ID));
if (!slots) {
rv = CKR_HOST_MEMORY;
goto bail;
}
rv = C_GetSlotList(CK_TRUE, slots, &count);
if (rv)
goto bail;
/* Use the last slot */
*slot = slots[count - 1];
bail:
free(slots);
if (rv)
close_lib();
return rv;
}
static void xtest_pkcs11_test_1000(ADBG_Case_t *c)
{
CK_RV rv;
rv = C_Initialize(NULL);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_Finalize(NULL);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_Initialize(NULL);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_Initialize(NULL);
ADBG_EXPECT_CK_RESULT(c, CKR_CRYPTOKI_ALREADY_INITIALIZED, rv);
rv = C_Finalize(NULL);
ADBG_EXPECT_CK_OK(c, rv);
rv = C_Finalize(NULL);
ADBG_EXPECT_CK_RESULT(c, CKR_CRYPTOKI_NOT_INITIALIZED, rv);
}
ADBG_CASE_DEFINE(pkcs11, 1000, xtest_pkcs11_test_1000,
"Initialize and close Cryptoki library");
static void xtest_pkcs11_test_1001(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID_PTR slot_ids = NULL;
CK_ULONG slot_count = 0;
CK_ULONG present_slot_count = 0;
CK_INFO lib_info = { };
CK_SLOT_INFO slot_info = { };
CK_TOKEN_INFO token_info = { };
CK_FUNCTION_LIST_PTR ckfunc_list = NULL;
size_t i = 0;
CK_SLOT_ID max_slot_id = 0;
CK_MECHANISM_TYPE_PTR mecha_types = NULL;
CK_ULONG mecha_count = 0;
CK_MECHANISM_INFO mecha_info = { };
rv = C_Initialize(NULL);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
Do_ADBG_BeginSubCase(c, "Test C_GetFunctionList()");
rv = C_GetFunctionList(&ckfunc_list);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetInfo) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetSlotList) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetSlotInfo) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetTokenInfo) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetMechanismList) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetMechanismInfo))
goto out;
Do_ADBG_EndSubCase(c, "Test C_GetFunctionList()");
Do_ADBG_BeginSubCase(c, "Test C_GetInfo()");
rv = C_GetInfo(&lib_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, "Test C_GetInfo()");
Do_ADBG_BeginSubCase(c, "Test C_GetSlotList()");
rv = C_GetSlotList(0, NULL, &slot_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, slot_count, !=, 0))
goto out;
if (slot_count > 1) {
/* Ensure case non-NULL-buffer and zero-count is tested */
CK_SLOT_ID id = 0;
slot_count = 0;
rv = C_GetSlotList(0, &id, &slot_count);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv))
goto out;
}
rv = C_GetSlotList(1, NULL, &present_slot_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, slot_count, ==,
present_slot_count))
goto out;
slot_ids = calloc(slot_count, sizeof(CK_SLOT_ID));
if (!ADBG_EXPECT_NOT_NULL(c, slot_ids))
goto out;
slot_count--;
rv = C_GetSlotList(1, slot_ids, &slot_count);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv))
goto out;
rv = C_GetSlotList(1, slot_ids, &slot_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, "Test C_GetSlotList()");
Do_ADBG_BeginSubCase(c, "Test C_Get{Slot|Token}Info()");
for (i = 0; i < slot_count; i++) {
CK_SLOT_ID slot = slot_ids[i];
rv = C_GetSlotInfo(slot, &slot_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetTokenInfo(slot, &token_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (max_slot_id < slot)
max_slot_id = slot;
}
Do_ADBG_EndSubCase(c, "Test C_Get{Slot|Token}Info()");
Do_ADBG_BeginSubCase(c, "Test C_GetMechanism{List|Info}()");
for (i = 0; i < slot_count; i++) {
CK_SLOT_ID slot = slot_ids[i];
size_t j = 0;
mecha_count = 0;
rv = C_GetMechanismList(slot, NULL, &mecha_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (mecha_count == 0)
continue;
free(mecha_types);
mecha_types = calloc(mecha_count, sizeof(*mecha_types));
if (!ADBG_EXPECT_NOT_NULL(c, mecha_types))
goto out;
/* Test specific case: valid buffer reference with 0 count */
mecha_count = 0;
rv = C_GetMechanismList(slot, mecha_types, &mecha_count);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv))
goto out;
rv = C_GetMechanismList(slot, mecha_types, &mecha_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
for (j = 0; j < mecha_count; j++) {
rv = C_GetMechanismInfo(slot, mecha_types[j],
&mecha_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
}
}
Do_ADBG_EndSubCase(c, "Test C_GetMechanism{List|Info}()");
Do_ADBG_BeginSubCase(c, "Test C_GetMechanismList() with larger result buffer");
for (i = 0; i < slot_count; i++) {
CK_SLOT_ID slot = slot_ids[i];
CK_ULONG real_mecha_count = 0;
CK_ULONG alloc_mecha_count = 0;
uint8_t *data_ptr = NULL;
size_t j = 0;
rv = C_GetMechanismList(slot, NULL, &real_mecha_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (real_mecha_count == 0)
continue;
/* Allocate more memory for mechanisms than required */
alloc_mecha_count = real_mecha_count + 16;
mecha_count = alloc_mecha_count;
free(mecha_types);
mecha_types = calloc(mecha_count, sizeof(*mecha_types));
if (!ADBG_EXPECT_NOT_NULL(c, mecha_types))
goto out;
memset(mecha_types, 0xCC,
alloc_mecha_count * sizeof(*mecha_types));
rv = C_GetMechanismList(slot, mecha_types, &mecha_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, mecha_count, ==,
real_mecha_count))
goto out;
data_ptr = (uint8_t *)mecha_types;
for (j = real_mecha_count * sizeof(*mecha_types);
j < alloc_mecha_count * sizeof(*mecha_types); j++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, data_ptr[j], ==,
0xCC))
break;
}
Do_ADBG_EndSubCase(c, "Test C_GetMechanismList() with larger result buffer");
Do_ADBG_BeginSubCase(c, "Test C_Get*Info() with invalid reference");
rv = C_GetSlotInfo(max_slot_id + 1, &slot_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv))
goto out;
rv = C_GetTokenInfo(max_slot_id + 1, &token_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv))
goto out;
mecha_count = 1;
if (!mecha_types)
mecha_types = malloc(sizeof(*mecha_types));
if (!ADBG_EXPECT_NOT_NULL(c, mecha_types))
goto out;
rv = C_GetMechanismList(max_slot_id + 1, mecha_types, &mecha_count);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv))
goto out;
rv = C_GetMechanismInfo(max_slot_id + 1, CKM_AES_KEY_GEN, &mecha_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv))
goto out;
rv = C_GetSlotInfo(ULONG_MAX, &slot_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv))
goto out;
rv = C_GetTokenInfo(ULONG_MAX, &token_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv))
goto out;
mecha_count = 1;
rv = C_GetMechanismList(ULONG_MAX, mecha_types, &mecha_count);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv))
goto out;
rv = C_GetMechanismInfo(ULONG_MAX, CKM_AES_KEY_GEN, &mecha_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv))
goto out;
out:
Do_ADBG_EndSubCase(c, NULL);
free(slot_ids);
free(mecha_types);
rv = C_Finalize(NULL);
ADBG_EXPECT_CK_OK(c, rv);
}
ADBG_CASE_DEFINE(pkcs11, 1001, xtest_pkcs11_test_1001,
"PKCS11: List PKCS#11 slots and get information from");
static void xtest_pkcs11_test_1002(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session[3] = { 0 };
CK_FLAGS session_flags = 0;
CK_SESSION_INFO session_info = { };
CK_FUNCTION_LIST_PTR ckfunc_list = NULL;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_GetFunctionList(&ckfunc_list);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_OpenSession) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_CloseSession) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_CloseAllSessions) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetSessionInfo))
goto bail;
Do_ADBG_BeginSubCase(c, "Test C_OpenSession()/C_GetSessionInfo()");
session_flags = CKF_RW_SESSION;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session[0]);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_PARALLEL_NOT_SUPPORTED, rv))
goto bail;
session_flags = CKF_SERIAL_SESSION;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session[0]);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
rv = C_GetSessionInfo(session[0], &session_info);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.slotID, ==, slot) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.flags, ==,
session_flags) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.state, ==,
CKS_RO_PUBLIC_SESSION) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.ulDeviceError, ==, 0))
goto bail;
session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session[1]);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
rv = C_GetSessionInfo(session[1], &session_info);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.slotID, ==, slot) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.flags, ==,
session_flags) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.state, ==,
CKS_RW_PUBLIC_SESSION) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.ulDeviceError, ==, 0))
goto bail;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session[2]);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
rv = C_GetSessionInfo(session[2], &session_info);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.slotID, ==, slot) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.flags, ==,
session_flags) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.state, ==,
CKS_RW_PUBLIC_SESSION) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.ulDeviceError, ==, 0))
goto bail;
Do_ADBG_EndSubCase(c, "Test C_OpenSession()/C_GetSessionInfo()");
Do_ADBG_BeginSubCase(c, "Test C_CloseSession()");
/* Close 2 of them */
rv = C_CloseSession(session[0]);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
rv = C_GetSessionInfo(session[0], &session_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv))
goto bail;
rv = C_GetSessionInfo(session[1], &session_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
rv = C_GetSessionInfo(session[2], &session_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
/* Close all remaining sessions, later calls should failed on session */
rv = C_CloseAllSessions(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
rv = C_CloseSession(session[1]);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv))
goto bail;
rv = C_CloseSession(session[2]);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv))
goto bail;
rv = C_GetSessionInfo(session[1], &session_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv))
goto bail;
rv = C_GetSessionInfo(session[2], &session_info);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv))
goto bail;
/* Open a session, should be closed from library closure */
rv = C_OpenSession(slot, session_flags, NULL, 0, &session[0]);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
bail:
Do_ADBG_EndSubCase(c, NULL);
rv = close_lib();
ADBG_EXPECT_CK_OK(c, rv);
}
ADBG_CASE_DEFINE(pkcs11, 1002, xtest_pkcs11_test_1002,
"PKCS11: Open and close PKCS#11 sessions");
/*
* Helpers for tests where we must log into the token.
* These define the genuine PINs and label to be used with the test token.
*/
static CK_UTF8CHAR test_token_so_pin[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 , 9, 10, };
static CK_UTF8CHAR test_token_user_pin[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
};
static CK_UTF8CHAR test_token_label[] = "PKCS11 TA test token";
static CK_RV init_test_token(CK_SLOT_ID slot)
{
return C_InitToken(slot, test_token_so_pin, sizeof(test_token_so_pin),
test_token_label);
}
/* Login as user, eventually reset user PIN if needed */
static CK_RV init_user_test_token(CK_SLOT_ID slot)
{
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_RV rv = CKR_GENERAL_ERROR;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (rv)
return rv;
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (rv == CKR_OK) {
C_Logout(session);
C_CloseSession(session);
return rv;
}
rv = C_Login(session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
if (rv) {
C_CloseSession(session);
rv = init_test_token(slot);
if (rv)
return rv;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (rv)
return rv;
rv = C_Login(session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
if (rv) {
C_CloseSession(session);
return rv;
}
}
rv = C_InitPIN(session, test_token_user_pin,
sizeof(test_token_user_pin));
C_Logout(session);
C_CloseSession(session);
return rv;
}
static CK_RV test_already_initialized_token(ADBG_Case_t *c, CK_SLOT_ID slot)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_TOKEN_INFO token_info = { };
/* Same content as test_token_so_pin[] but 1 more byte */
CK_UTF8CHAR pin1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, };
/* Same content as test_token_so_pin[] but 1 different byte */
CK_UTF8CHAR pin2[] = { 0, 1, 2, 3, 4, 5, 6, 6, 8, 9, 10, };
CK_FLAGS flags = 0;
Do_ADBG_BeginSubCase(c, "C_InitToken() on initialized token");
rv = C_GetTokenInfo(slot, &token_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_InitToken(slot, test_token_so_pin,
sizeof(test_token_so_pin) - 1, test_token_label);
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, rv, !=, CKR_OK))
goto out;
rv = C_InitToken(slot, pin1, sizeof(pin1), test_token_label);
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, rv, !=, CKR_OK))
goto out;
rv = C_InitToken(slot, pin2, sizeof(pin2), test_token_label);
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, rv, !=, CKR_OK))
goto out;
rv = C_GetTokenInfo(slot, &token_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
flags = token_info.flags;
/* Token should have set CKF_SO_PIN_COUNT_LOW to 1 */
if (!ADBG_EXPECT_TRUE(c, !!(flags & CKF_SO_PIN_COUNT_LOW))) {
rv = CKR_GENERAL_ERROR;
goto out;
}
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetTokenInfo(slot, &token_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
flags = token_info.flags;
/*
* Token should have reset CKF_SO_PIN_COUNT_LOW to 0.
* Other flags should show a sane initialized state.
*/
if (!ADBG_EXPECT_TRUE(c, !(flags & CKF_SO_PIN_COUNT_LOW)) ||
!ADBG_EXPECT_TRUE(c, !!(flags & CKF_TOKEN_INITIALIZED)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_ERROR_STATE)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_INITIALIZED))) {
rv = CKR_GENERAL_ERROR;
goto out;
}
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetTokenInfo(slot, &token_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
flags = token_info.flags;
if (!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_COUNT_LOW)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_FINAL_TRY)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_LOCKED)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_TO_BE_CHANGED)) ||
!ADBG_EXPECT_TRUE(c, !!(flags & CKF_USER_PIN_INITIALIZED)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_ERROR_STATE))) {
rv = CKR_GENERAL_ERROR;
goto out;
}
out:
Do_ADBG_EndSubCase(c, "C_InitToken() on initialized token");
return rv;
}
static CK_RV test_uninitialized_token(ADBG_Case_t *c, CK_SLOT_ID slot)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_TOKEN_INFO token_info = { };
CK_FLAGS flags = 0;
Do_ADBG_BeginSubCase(c, "C_InitToken() on uninitialized token");
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetTokenInfo(slot, &token_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
flags = token_info.flags;
if (!ADBG_EXPECT_TRUE(c, !!(flags & CKF_TOKEN_INITIALIZED)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_ERROR_STATE)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_INITIALIZED))) {
rv = CKR_GENERAL_ERROR;
goto out;
}
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetTokenInfo(slot, &token_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
flags = token_info.flags;
if (!ADBG_EXPECT_TRUE(c, !!(flags & CKF_TOKEN_INITIALIZED)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_COUNT_LOW)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_FINAL_TRY)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_LOCKED)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_TO_BE_CHANGED)) ||
!ADBG_EXPECT_TRUE(c, !!(flags & CKF_USER_PIN_INITIALIZED)) ||
!ADBG_EXPECT_TRUE(c, !(flags & CKF_ERROR_STATE)))
rv = CKR_GENERAL_ERROR;
out:
Do_ADBG_EndSubCase(c, "C_InitToken() on uninitialized token");
return rv;
}
static CK_RV test_login_logout(ADBG_Case_t *c, CK_SLOT_ID slot)
{
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_RV rv = CKR_GENERAL_ERROR;
Do_ADBG_BeginSubCase(c, "Test C_Login()/C_Logout()");
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Logout: should fail as we did not log in yet */
rv = C_Logout(session);
ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv);
/* Login/re-log/logout user */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
ADBG_EXPECT_CK_RESULT(c, CKR_USER_ALREADY_LOGGED_IN, rv);
rv = C_Logout(session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Login/re-log/logout security officer */
rv = C_Login(session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Login(session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
ADBG_EXPECT_CK_RESULT(c, CKR_USER_ALREADY_LOGGED_IN, rv);
rv = C_Logout(session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Login user then SO and reverse */
rv = C_Login(session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
ADBG_EXPECT_CK_OK(c, rv);
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
ADBG_EXPECT_CK_RESULT(c, CKR_USER_ANOTHER_ALREADY_LOGGED_IN, rv);
rv = C_Logout(session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
ADBG_EXPECT_CK_OK(c, rv);
rv = C_Login(session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
ADBG_EXPECT_CK_RESULT(c, CKR_USER_ANOTHER_ALREADY_LOGGED_IN, rv);
rv = C_Logout(session);
ADBG_EXPECT_CK_OK(c, rv);
/* Login context specifc, in an invalid case (need an operation) */
rv = C_Login(session, CKU_CONTEXT_SPECIFIC, test_token_user_pin,
sizeof(test_token_user_pin));
ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv);
rv = C_CloseSession(session);
ADBG_EXPECT_CK_OK(c, rv);
out:
Do_ADBG_EndSubCase(c, "Test C_Login()/C_Logout()");
return rv;
}
static CK_RV test_set_pin(ADBG_Case_t *c, CK_SLOT_ID slot,
CK_USER_TYPE user_type)
{
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_UTF8CHAR some_pin[] = { 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6, 7 };
CK_UTF8CHAR_PTR old_pin = NULL;
CK_USER_TYPE ut = user_type;
size_t old_pin_sz = 0;
CK_RV rv2 = CKR_OK;
CK_RV rv = CKR_OK;
Do_ADBG_BeginSubCase(c, "Test C_SetPIN() user_type %lu", user_type);
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (user_type == CKU_SO) {
old_pin = (CK_UTF8CHAR_PTR)test_token_so_pin;
old_pin_sz = sizeof(test_token_so_pin);
} else {
old_pin = (CK_UTF8CHAR_PTR)test_token_user_pin;
old_pin_sz = sizeof(test_token_user_pin);
ut = CKU_USER;
}
if (ut == user_type) {
rv = C_Login(session, ut, old_pin, old_pin_sz);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out_session;
}
rv = C_SetPIN(session, old_pin, old_pin_sz, some_pin, sizeof(some_pin));
if (!ADBG_EXPECT_CK_OK(c, rv)) {
if (ut == user_type)
goto out_logout;
else
goto out_session;
}
if (ut == user_type) {
rv = C_Logout(session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out_session;
}
rv = C_Login(session, ut, some_pin, sizeof(some_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out_session;
rv = C_SetPIN(session, some_pin, sizeof(some_pin), old_pin, old_pin_sz);
ADBG_EXPECT_CK_OK(c, rv);
out_logout:
rv2 = C_Logout(session);
if (!ADBG_EXPECT_CK_OK(c, rv2) && !rv)
rv = rv2;
out_session:
rv2 = C_CloseSession(session);
if (!ADBG_EXPECT_CK_OK(c, rv2) && !rv)
rv = rv2;
out:
Do_ADBG_EndSubCase(c, "Test C_SetPIN() user_type %lu", user_type);
return rv;
}
static void xtest_pkcs11_test_1003(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_FUNCTION_LIST_PTR ckfunc_list = NULL;
CK_SLOT_ID slot = 0;
CK_TOKEN_INFO token_info = { };
rv = C_GetFunctionList(&ckfunc_list);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_InitToken) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_InitPIN) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_SetPIN) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_Login) ||
!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_Logout))
goto out;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_GetTokenInfo(slot, &token_info);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Abort test if token is about to lock */
if (!ADBG_EXPECT_TRUE(c, !(token_info.flags & CKF_SO_PIN_FINAL_TRY)))
goto out;
if (!(token_info.flags & CKF_TOKEN_INITIALIZED)) {
rv = test_uninitialized_token(c, slot);
if (rv != CKR_OK)
goto out;
}
rv = test_already_initialized_token(c, slot);
if (rv != CKR_OK)
goto out;
rv = test_login_logout(c, slot);
if (rv != CKR_OK)
goto out;
rv = test_set_pin(c, slot, CKU_USER);
if (rv != CKR_OK)
goto out;
rv = test_set_pin(c, slot, CKU_SO);
if (rv != CKR_OK)
goto out;
/*
* CKU_CONTEXT_SPECIFIC is anything not CKU_USER or CKU_SO in order
* to skip the initial login.
*/
test_set_pin(c, slot, CKU_CONTEXT_SPECIFIC);
out:
rv = close_lib();
ADBG_EXPECT_CK_OK(c, rv);
}
ADBG_CASE_DEFINE(pkcs11, 1003, xtest_pkcs11_test_1003,
"PKCS11: Login to PKCS#11 token");
static CK_ATTRIBUTE cktest_token_object[] = {
{ CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) },
{ CKA_VALUE, (void *)cktest_aes128_key, sizeof(cktest_aes128_key) },
};
static CK_ATTRIBUTE cktest_session_object[] = {
{ CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) },
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_VALUE, (void *)cktest_aes128_key, sizeof(cktest_aes128_key) },
};
/* Create session object and token object from a session */
static void test_create_destroy_single_object(ADBG_Case_t *c, bool persistent)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (persistent) {
rv = C_CreateObject(session, cktest_token_object,
ARRAY_SIZE(cktest_token_object),
&obj_hdl);
} else {
rv = C_CreateObject(session, cktest_session_object,
ARRAY_SIZE(cktest_session_object),
&obj_hdl);
}
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DestroyObject(session, obj_hdl);
ADBG_EXPECT_CK_OK(c, rv);
out:
rv = C_CloseSession(session);
ADBG_EXPECT_CK_OK(c, rv);
rv = close_lib();
ADBG_EXPECT_CK_OK(c, rv);
}
static void test_create_destroy_session_objects(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE obj_hdl[512] = { 0 };
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
size_t n = 0;
for (n = 0; n < ARRAY_SIZE(obj_hdl); n++)
obj_hdl[n] = CK_INVALID_HANDLE;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
for (n = 0; n < ARRAY_SIZE(obj_hdl); n++) {
rv = C_CreateObject(session, cktest_session_object,
ARRAY_SIZE(cktest_session_object),
obj_hdl + n);
if (rv == CKR_DEVICE_MEMORY || !ADBG_EXPECT_CK_OK(c, rv))
break;
}
Do_ADBG_Log(" created object count: %zu", n);
rv = C_CloseSession(session);
ADBG_EXPECT_CK_OK(c, rv);
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_CreateObject(session, cktest_session_object,
ARRAY_SIZE(cktest_session_object),
obj_hdl);
ADBG_EXPECT_CK_OK(c, rv);
out:
rv = C_CloseSession(session);
ADBG_EXPECT_CK_OK(c, rv);
rv = close_lib();
ADBG_EXPECT_CK_OK(c, rv);
}
/* Create session object and token object from a session */
static void test_create_objects_in_session(ADBG_Case_t *c, bool readwrite)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE token_obj_hld = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE session_obj_hld = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
if (readwrite)
session_flags |= CKF_RW_SESSION;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_CreateObject(session, cktest_token_object,
ARRAY_SIZE(cktest_token_object),
&token_obj_hld);
if (readwrite) {
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
} else {
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv))
goto out;
}
rv = C_CreateObject(session, cktest_session_object,
ARRAY_SIZE(cktest_session_object),
&session_obj_hld);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out_tobj;
rv = C_DestroyObject(session, session_obj_hld);
ADBG_EXPECT_CK_OK(c, rv);
out_tobj:
if (readwrite) {
rv = C_DestroyObject(session, token_obj_hld);
ADBG_EXPECT_CK_OK(c, rv);
}
out:
rv = C_CloseSession(session);
ADBG_EXPECT_CK_OK(c, rv);
rv = close_lib();
ADBG_EXPECT_CK_OK(c, rv);
}
static void xtest_pkcs11_test_1004(ADBG_Case_t *c)
{
Do_ADBG_BeginSubCase(c, "Create and destroy a volatile object");
test_create_destroy_single_object(c, false /*!persistent*/);
Do_ADBG_EndSubCase(c, "Create and destroy a volatile object");
Do_ADBG_BeginSubCase(c, "Create and destroy a persistent object");
test_create_destroy_single_object(c, true /*persistent*/);
Do_ADBG_EndSubCase(c, "Create and destroy a persistent object");
Do_ADBG_BeginSubCase(c, "Create and destroy many session objects");
test_create_destroy_session_objects(c);
Do_ADBG_EndSubCase(c, "Create and destroy many session objects");
Do_ADBG_BeginSubCase(c, "Create objects in a read-only session");
test_create_objects_in_session(c, false /*!readwrite*/);
Do_ADBG_EndSubCase(c, "Create objects in a read-only session");
Do_ADBG_BeginSubCase(c, "Create objects in a read/write session");
test_create_objects_in_session(c, true /*readwrite*/);
Do_ADBG_EndSubCase(c, "Create objects in a read/write session");
}
ADBG_CASE_DEFINE(pkcs11, 1004, xtest_pkcs11_test_1004,
"PKCS11: create/destroy PKCS#11 simple objects");
static const CK_MECHANISM_TYPE allowed_only_aes_ecb[] = {
CKM_AES_ECB,
};
static const CK_MECHANISM_TYPE allowed_not_aes_ecb[] = {
CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_AES_CTR, CKM_AES_CTS,
CKM_AES_GCM, CKM_AES_CCM,
};
static const CK_MECHANISM_TYPE allowed_only_aes_cbcnopad[] = {
CKM_AES_CBC,
};
static const CK_MECHANISM_TYPE allowed_not_aes_cbcnopad[] = {
CKM_AES_ECB, CKM_AES_CBC_PAD, CKM_AES_CTR, CKM_AES_CTS,
CKM_AES_GCM, CKM_AES_CCM,
};
static const CK_MECHANISM_TYPE allowed_only_aes_ctr[] = {
CKM_AES_CTR,
};
static const CK_MECHANISM_TYPE allowed_not_aes_ctr[] = {
CKM_AES_ECB, CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_AES_CTS,
CKM_AES_GCM, CKM_AES_CCM,
};
static const CK_MECHANISM_TYPE allowed_only_aes_cts[] = {
CKM_AES_CTS,
};
static const CK_MECHANISM_TYPE allowed_not_aes_cts[] = {
CKM_AES_ECB, CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_AES_CTR,
CKM_AES_GCM, CKM_AES_CCM,
};
#define CKTEST_AES_KEY \
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, \
sizeof(CK_OBJECT_CLASS) }, \
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, \
sizeof(CK_KEY_TYPE) }, \
{ CKA_VALUE, (void *)cktest_aes128_key, \
sizeof(cktest_aes128_key) }
#define CKTEST_AES_ALLOWED_KEY(_allowed) \
{ CKA_ALLOWED_MECHANISMS, (void *)_allowed, sizeof(_allowed), }
#define CK_KEY_ALLOWED_AES_TEST(_label, _allowed) \
static CK_ATTRIBUTE _label[] = { \
CKTEST_AES_KEY, \
{ CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, \
{ CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, \
CKTEST_AES_ALLOWED_KEY(_allowed), \
}
#define CK_KEY_ALLOWED_AES_ENC_TEST(_label, _allowed) \
static CK_ATTRIBUTE _label[] = { \
CKTEST_AES_KEY, \
{ CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, \
CKTEST_AES_ALLOWED_KEY(_allowed), \
}
#define CK_KEY_ALLOWED_AES_DEC_TEST(_label, _allowed) \
static CK_ATTRIBUTE _label[] = { \
CKTEST_AES_KEY, \
{ CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, \
CKTEST_AES_ALLOWED_KEY(_allowed), \
}
CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_ecb, allowed_only_aes_ecb);
CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_ecb, allowed_not_aes_ecb);
CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_cbcnopad, allowed_only_aes_cbcnopad);
CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_cbcnopad, allowed_not_aes_cbcnopad);
CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_cts, allowed_only_aes_cts);
CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_cts, allowed_not_aes_cts);
CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_ctr, allowed_only_aes_ctr);
CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_ctr, allowed_not_aes_ctr);
struct cktest_allowed_test {
CK_ATTRIBUTE_PTR attr_key;
CK_ULONG attr_count;
CK_MECHANISM_PTR mechanism;
};
#define CKTEST_KEY_MECHA(key, mecha) { \
.attr_key = key, \
.attr_count = ARRAY_SIZE(key), \
.mechanism = mecha, \
}
static const struct cktest_allowed_test cktest_allowed_valid[] = {
CKTEST_KEY_MECHA(cktest_aes_only_ecb, &cktest_aes_ecb_mechanism),
CKTEST_KEY_MECHA(cktest_aes_only_cbcnopad, &cktest_aes_cbc_mechanism),
CKTEST_KEY_MECHA(cktest_aes_only_cts, &cktest_aes_cts_mechanism),
CKTEST_KEY_MECHA(cktest_aes_only_ctr, &cktest_aes_ctr_mechanism),
};
static const struct cktest_allowed_test cktest_allowed_invalid[] = {
CKTEST_KEY_MECHA(cktest_aes_not_ecb, &cktest_aes_ecb_mechanism),
CKTEST_KEY_MECHA(cktest_aes_not_cbcnopad, &cktest_aes_cbc_mechanism),
CKTEST_KEY_MECHA(cktest_aes_not_cts, &cktest_aes_cts_mechanism),
CKTEST_KEY_MECHA(cktest_aes_not_ctr, &cktest_aes_ctr_mechanism),
};
/* Create session object and token object from a session */
static CK_RV cipher_init_final(ADBG_Case_t *c, CK_SESSION_HANDLE session,
CK_ATTRIBUTE_PTR attr_key, CK_ULONG attr_count,
CK_MECHANISM_PTR mechanism, uint32_t mode,
CK_RV expected_rc)
{
CK_RV rv2 = CKR_GENERAL_ERROR;
CK_RV rv = CKR_GENERAL_ERROR;
CK_OBJECT_HANDLE object = CK_INVALID_HANDLE;
switch (mode) {
case TEE_MODE_ENCRYPT:
case TEE_MODE_DECRYPT:
break;
default:
ADBG_EXPECT_TRUE(c, false);
}
rv = C_CreateObject(session, attr_key, attr_count, &object);
if (!ADBG_EXPECT_CK_OK(c, rv))
return rv;
if (mode == TEE_MODE_ENCRYPT)
rv = C_EncryptInit(session, mechanism, object);
if (mode == TEE_MODE_DECRYPT)
rv = C_DecryptInit(session, mechanism, object);
if (!ADBG_EXPECT_CK_RESULT(c, expected_rc, rv)) {
rv = CKR_GENERAL_ERROR;
goto out;
}
if (rv) {
/*
* If we're here it was the expected error code above and
* we're supposed to return OK below.
*/
rv = CKR_OK;
} else {
if (mode == TEE_MODE_ENCRYPT)
rv = C_EncryptFinal(session, NULL, NULL);
if (mode == TEE_MODE_DECRYPT)
rv = C_DecryptFinal(session, NULL, NULL);
/*
* Check that return value is expected so that operation is
* released
*/
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) {
rv = CKR_GENERAL_ERROR;
goto out;
}
rv = CKR_OK;
}
out:
rv2 = C_DestroyObject(session, object);
ADBG_EXPECT_CK_OK(c, rv2);
if (rv)
return rv;
else
return rv2;
}
CK_KEY_ALLOWED_AES_ENC_TEST(cktest_aes_enc_only_cts, allowed_only_aes_cts);
CK_KEY_ALLOWED_AES_DEC_TEST(cktest_aes_dec_only_ctr, allowed_only_aes_ctr);
static void xtest_pkcs11_test_1005(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION;
size_t n = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
for (n = 0; n < ARRAY_SIZE(cktest_allowed_valid); n++) {
Do_ADBG_BeginSubCase(c, "valid usage #%zu", n);
rv = cipher_init_final(c, session,
cktest_allowed_valid[n].attr_key,
cktest_allowed_valid[n].attr_count,
cktest_allowed_valid[n].mechanism,
TEE_MODE_ENCRYPT,
CKR_OK);
ADBG_EXPECT_CK_OK(c, rv);
Do_ADBG_EndSubCase(c, NULL);
if (rv)
goto out;
}
for (n = 0; n < ARRAY_SIZE(cktest_allowed_invalid); n++) {
Do_ADBG_BeginSubCase(c, "invalid usage #%zu", n);
rv = cipher_init_final(c, session,
cktest_allowed_invalid[n].attr_key,
cktest_allowed_invalid[n].attr_count,
cktest_allowed_invalid[n].mechanism,
TEE_MODE_ENCRYPT,
CKR_KEY_FUNCTION_NOT_PERMITTED);
ADBG_EXPECT_CK_OK(c, rv);
Do_ADBG_EndSubCase(c, NULL);
if (rv)
goto out;
}
out:
rv = C_CloseSession(session);
ADBG_EXPECT_CK_OK(c, rv);
rv = close_lib();
ADBG_EXPECT_CK_OK(c, rv);
}
ADBG_CASE_DEFINE(pkcs11, 1005, xtest_pkcs11_test_1005,
"PKCS11: Check ciphering with valid and invalid keys #1");
static void xtest_pkcs11_test_1006(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Encrypt only AES CTS key */
rv = cipher_init_final(c, session,
cktest_aes_enc_only_cts,
ARRAY_SIZE(cktest_aes_enc_only_cts),
&cktest_aes_cts_mechanism,
TEE_MODE_ENCRYPT,
CKR_OK);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = cipher_init_final(c, session,
cktest_aes_enc_only_cts,
ARRAY_SIZE(cktest_aes_enc_only_cts),
&cktest_aes_cts_mechanism,
TEE_MODE_DECRYPT,
CKR_KEY_FUNCTION_NOT_PERMITTED);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Decrypt only AES CTR key */
rv = cipher_init_final(c, session,
cktest_aes_dec_only_ctr,
ARRAY_SIZE(cktest_aes_dec_only_ctr),
&cktest_aes_ctr_mechanism,
TEE_MODE_ENCRYPT,
CKR_KEY_FUNCTION_NOT_PERMITTED);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = cipher_init_final(c, session,
cktest_aes_dec_only_ctr,
ARRAY_SIZE(cktest_aes_dec_only_ctr),
&cktest_aes_ctr_mechanism,
TEE_MODE_ENCRYPT,
CKR_KEY_FUNCTION_NOT_PERMITTED);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
out:
rv = C_CloseSession(session);
ADBG_EXPECT_CK_OK(c, rv);
rv = close_lib();
ADBG_EXPECT_CK_OK(c, rv);
}
ADBG_CASE_DEFINE(pkcs11, 1006, xtest_pkcs11_test_1006,
"PKCS11: Check ciphering with valid and invalid keys #2");
static CK_RV open_cipher_session(ADBG_Case_t *c,
CK_SLOT_ID slot, CK_SESSION_HANDLE_PTR session,
CK_ATTRIBUTE_PTR attr_key, CK_ULONG attr_count,
CK_MECHANISM_PTR mechanism, uint32_t mode)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_OBJECT_HANDLE object = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION;
switch (mode) {
case TEE_MODE_ENCRYPT:
case TEE_MODE_DECRYPT:
break;
default:
ADBG_EXPECT_TRUE(c, false);
return CKR_GENERAL_ERROR;
}
rv = C_OpenSession(slot, session_flags, NULL, 0, session);
if (rv == CKR_DEVICE_MEMORY)
return rv;
if (!ADBG_EXPECT_CK_OK(c, rv))
return rv;
rv = C_CreateObject(*session, attr_key, attr_count, &object);
if (rv == CKR_DEVICE_MEMORY)
return rv;
if (!ADBG_EXPECT_CK_OK(c, rv))
return rv;
if (mode == TEE_MODE_ENCRYPT)
rv = C_EncryptInit(*session, mechanism, object);
if (mode == TEE_MODE_DECRYPT)
rv = C_DecryptInit(*session, mechanism, object);
if (rv == CKR_DEVICE_MEMORY)
return rv;
if (!ADBG_EXPECT_CK_OK(c, rv))
return CKR_GENERAL_ERROR;
return rv;
}
static void xtest_pkcs11_test_1007(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE sessions[128];
size_t n = 0;
for (n = 0; n < ARRAY_SIZE(sessions); n++)
sessions[n] = CK_INVALID_HANDLE;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
for (n = 0; n < ARRAY_SIZE(sessions); n++) {
rv = open_cipher_session(c, slot, &sessions[n],
cktest_allowed_valid[0].attr_key,
cktest_allowed_valid[0].attr_count,
cktest_allowed_valid[0].mechanism,
TEE_MODE_ENCRYPT);
/* Failure due to memory allocation is not a error case */
if (rv == CKR_DEVICE_MEMORY)
break;
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
}
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, n, >, 0))
goto out;
Do_ADBG_Log(" created sessions count: %zu", n);
/* Closing session with out bound and invalid IDs (or negative ID) */
rv = C_CloseSession(sessions[n - 1] + 1024);
ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv);
rv = C_CloseSession(CK_INVALID_HANDLE);
ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv);
rv = C_CloseSession(~0);
ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv);
/* Closing each session: all related resources shall be free */
for (n = 0; n < ARRAY_SIZE(sessions); n++) {
if (sessions[n] == CK_INVALID_HANDLE)
continue;
rv = C_CloseSession(sessions[n]);
ADBG_EXPECT_CK_OK(c, rv);
sessions[n] = CK_INVALID_HANDLE;
}
/* Open and close another session */
rv = open_cipher_session(c, slot, &sessions[0],
cktest_allowed_valid[0].attr_key,
cktest_allowed_valid[0].attr_count,
cktest_allowed_valid[0].mechanism,
TEE_MODE_ENCRYPT);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_CloseSession(sessions[0]);
ADBG_EXPECT_CK_OK(c, rv);
sessions[0] = CK_INVALID_HANDLE;
out:
for (n = 0; n < ARRAY_SIZE(sessions); n++) {
if (sessions[n] == CK_INVALID_HANDLE)
continue;
rv = C_CloseSession(sessions[n]);
ADBG_EXPECT_CK_OK(c, rv);
}
rv = close_lib();
ADBG_EXPECT_CK_OK(c, rv);
}
ADBG_CASE_DEFINE(pkcs11, 1007, xtest_pkcs11_test_1007,
"PKCS11: Check operations release at session closure");
#define CK_MAC_KEY_AES(_key_array) \
{ \
{ CKA_SIGN, &(CK_BBOOL){CK_TRUE}, \
sizeof(CK_BBOOL) }, \
{ CKA_VERIFY, &(CK_BBOOL){CK_TRUE}, \
sizeof(CK_BBOOL) }, \
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, \
sizeof(CK_OBJECT_CLASS) }, \
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, \
sizeof(CK_KEY_TYPE) }, \
{ CKA_VALUE, (void *)(_key_array), \
sizeof(_key_array) }, \
}
static CK_ATTRIBUTE cktest_aes_cmac_key1[] =
CK_MAC_KEY_AES(mac_cmac_vect1_key);
static CK_ATTRIBUTE cktest_aes_cmac_key2[] =
CK_MAC_KEY_AES(mac_cmac_vect5_key);
static CK_ATTRIBUTE cktest_aes_cmac_key3[] =
CK_MAC_KEY_AES(mac_cmac_vect9_key);
#define CK_MAC_KEY_HMAC(_type, _key_array) \
{ \
{ CKA_SIGN, &(CK_BBOOL){CK_TRUE}, \
sizeof(CK_BBOOL) }, \
{ CKA_VERIFY, &(CK_BBOOL){CK_TRUE}, \
sizeof(CK_BBOOL) }, \
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, \
sizeof(CK_OBJECT_CLASS) }, \
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){_type}, \
sizeof(CK_KEY_TYPE) }, \
{ CKA_VALUE, (void *)(_key_array), \
sizeof(_key_array) }, \
}
static CK_ATTRIBUTE cktest_hmac_md5_key[] =
CK_MAC_KEY_HMAC(CKK_MD5_HMAC, mac_data_md5_key1);
static CK_ATTRIBUTE cktest_hmac_sha1_key[] =
CK_MAC_KEY_HMAC(CKK_SHA_1_HMAC, mac_data_sha1_key1);
static CK_ATTRIBUTE cktest_hmac_sha224_key[] =
CK_MAC_KEY_HMAC(CKK_SHA224_HMAC, mac_data_sha224_key1);
static CK_ATTRIBUTE cktest_hmac_sha256_key1[] =
CK_MAC_KEY_HMAC(CKK_SHA256_HMAC, mac_data_sha256_key1);
static CK_ATTRIBUTE cktest_hmac_sha256_key2[] =
CK_MAC_KEY_HMAC(CKK_SHA256_HMAC, mac_data_sha256_key2);
static CK_ATTRIBUTE cktest_hmac_sha384_key[] =
CK_MAC_KEY_HMAC(CKK_SHA384_HMAC, mac_data_sha384_key1);
static CK_ATTRIBUTE cktest_hmac_sha512_key[] =
CK_MAC_KEY_HMAC(CKK_SHA512_HMAC, mac_data_sha512_key1);
struct mac_test {
CK_ATTRIBUTE_PTR attr_key;
CK_ULONG attr_count;
CK_MECHANISM_PTR mechanism;
size_t in_incr;
const uint8_t *in;
size_t in_len;
const uint8_t *out;
size_t out_len;
bool multiple_incr;
};
#define CKTEST_MAC_TEST(key, mecha, input_incr, input, output, incr) { \
.attr_key = key, \
.attr_count = ARRAY_SIZE(key), \
.mechanism = mecha, \
.in_incr = input_incr, \
.in = input, \
.in_len = ARRAY_SIZE(input), \
.out = output, \
.out_len = ARRAY_SIZE(output), \
.multiple_incr = incr, \
}
#define CKTEST_CMAC_TEST(key, mecha, input_incr, input, output, incr) { \
.attr_key = key, \
.attr_count = ARRAY_SIZE(key), \
.mechanism = mecha, \
.in_incr = input_incr, \
.in = input, \
.in_len = 0, \
.out = output, \
.out_len = ARRAY_SIZE(output), \
.multiple_incr = incr, \
}
static const struct mac_test cktest_mac_cases[] = {
CKTEST_CMAC_TEST(cktest_aes_cmac_key1, &cktest_aes_cmac_mechanism,
0, NULL, mac_cmac_vect1_out, false),
CKTEST_CMAC_TEST(cktest_aes_cmac_key2, &cktest_aes_cmac_mechanism,
0, NULL, mac_cmac_vect5_out, false),
CKTEST_CMAC_TEST(cktest_aes_cmac_key3, &cktest_aes_cmac_mechanism,
0, NULL, mac_cmac_vect9_out, false),
CKTEST_MAC_TEST(cktest_hmac_md5_key, &cktest_hmac_md5_mechanism,
4, mac_data_md5_in1, mac_data_md5_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha1_key, &cktest_hmac_sha1_mechanism,
5, mac_data_sha1_in1, mac_data_sha1_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha224_key, &cktest_hmac_sha224_mechanism,
8, mac_data_sha224_in1, mac_data_sha224_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha256_key1, &cktest_hmac_sha256_mechanism,
1, mac_data_sha256_in1, mac_data_sha256_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha256_key2, &cktest_hmac_sha256_mechanism,
7, mac_data_sha256_in2, mac_data_sha256_out2, false),
CKTEST_MAC_TEST(cktest_hmac_sha384_key, &cktest_hmac_sha384_mechanism,
11, mac_data_sha384_in1, mac_data_sha384_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha512_key, &cktest_hmac_sha512_mechanism,
13, mac_data_sha512_in1, mac_data_sha512_out1, false),
CKTEST_CMAC_TEST(cktest_aes_cmac_key1,
&cktest_aes_cmac_general_mechanism, 0, NULL,
mac_cmac_vect1_out, false),
CKTEST_CMAC_TEST(cktest_aes_cmac_key2,
&cktest_aes_cmac_general_mechanism, 0, NULL,
mac_cmac_vect5_out, false),
CKTEST_CMAC_TEST(cktest_aes_cmac_key3,
&cktest_aes_cmac_general_mechanism, 0, NULL,
mac_cmac_vect9_out, false),
CKTEST_MAC_TEST(cktest_hmac_md5_key,
&cktest_hmac_general_md5_mechanism, 4,
mac_data_md5_in1, mac_data_md5_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha1_key,
&cktest_hmac_general_sha1_mechanism, 5,
mac_data_sha1_in1, mac_data_sha1_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha224_key,
&cktest_hmac_general_sha224_mechanism, 8,
mac_data_sha224_in1, mac_data_sha224_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha256_key1,
&cktest_hmac_general_sha256_mechanism, 1,
mac_data_sha256_in1, mac_data_sha256_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha256_key2,
&cktest_hmac_general_sha256_mechanism, 7,
mac_data_sha256_in2, mac_data_sha256_out2, false),
CKTEST_MAC_TEST(cktest_hmac_sha384_key,
&cktest_hmac_general_sha384_mechanism, 11,
mac_data_sha384_in1, mac_data_sha384_out1, false),
CKTEST_MAC_TEST(cktest_hmac_sha512_key,
&cktest_hmac_general_sha512_mechanism, 13,
mac_data_sha512_in1, mac_data_sha512_out1, false),
};
static bool ckm_is_hmac_general(struct mac_test const *test)
{
switch (test->mechanism->mechanism) {
case CKM_AES_CMAC_GENERAL:
case CKM_MD5_HMAC_GENERAL:
case CKM_SHA_1_HMAC_GENERAL:
case CKM_SHA224_HMAC_GENERAL:
case CKM_SHA256_HMAC_GENERAL:
case CKM_SHA384_HMAC_GENERAL:
case CKM_SHA512_HMAC_GENERAL:
return true;
default:
return false;
}
}
static size_t get_mac_test_len(struct mac_test const *test)
{
if (ckm_is_hmac_general(test))
return (size_t)cktest_general_mechanism_hmac_len;
return test->out_len;
}
static void xtest_pkcs11_test_1008(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION;
CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE;
uint8_t out[512] = { 0 };
CK_ULONG out_size = 0;
struct mac_test const *test = NULL;
size_t n = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_close_lib;
for (n = 0; n < ARRAY_SIZE(cktest_mac_cases); n++) {
test = &cktest_mac_cases[n];
Do_ADBG_BeginSubCase(c, "Sign case %zu algo (%s)", n,
ckm2str(test->mechanism->mechanism));
rv = C_CreateObject(session, test->attr_key, test->attr_count,
&key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
/* Test signature in 1 step */
if (test->in != NULL) {
rv = C_SignInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Pass input buffer of size 0 */
rv = C_SignUpdate(session,
(void *)test->in, 0);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_SignUpdate(session,
(void *)test->in, test->in_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Test too short buffer case */
out_size = 1;
rv = C_SignFinal(session, out, &out_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv))
goto err_destr_obj;
/*
* Test NULL buffer case with size as 0
* to get the out_size
*/
out_size = 0;
rv = C_SignFinal(session, NULL, &out_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/*
* Test NULL buffer case with size as non-zero
* to get the out_size
*/
out_size = 42;
rv = C_SignFinal(session, NULL, &out_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Get to full output */
memset(out, 0, out_size);
rv = C_SignFinal(session, out, &out_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
(void)ADBG_EXPECT_BUFFER(c, test->out,
get_mac_test_len(test),
out, out_size);
}
/* Test 2 step update signature */
rv = C_SignInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
if (test->in != NULL) {
rv = C_SignUpdate(session,
(void *)test->in, test->in_incr);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_SignUpdate(session,
(void *)(test->in + test->in_incr),
test->in_len - test->in_incr);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
}
out_size = sizeof(out);
memset(out, 0, sizeof(out));
rv = C_SignFinal(session, out, &out_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
(void)ADBG_EXPECT_BUFFER(c, test->out,
get_mac_test_len(test), out,
out_size);
/* Test 3 signature in one shot */
if (test->in != NULL) {
rv = C_SignInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Test too short buffer case */
out_size = 1;
rv = C_Sign(session,(void *)test->in, test->in_len,
out, &out_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv))
goto err_destr_obj;
/*
* Test NULL buffer case with size as 0
* to get the out_size
*/
out_size = 0;
rv = C_Sign(session, (void *)test->in, test->in_len,
NULL, &out_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/*
* Test NULL buffer case with size as non-zero
* to get the out_size
*/
out_size = 42;
rv = C_Sign(session, (void *)test->in, test->in_len,
NULL, &out_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Get to full output */
memset(out, 0, out_size);
rv = C_Sign(session,(void *)test->in, test->in_len,
out, &out_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
(void)ADBG_EXPECT_BUFFER(c, test->out,
get_mac_test_len(test),
out, out_size);
}
rv = C_DestroyObject(session, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
}
goto out;
err_destr_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
err:
Do_ADBG_EndSubCase(c, NULL);
out:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
err_close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1008, xtest_pkcs11_test_1008,
"PKCS11: Check Compliance of C_Sign - HMAC algorithms");
static void xtest_pkcs11_test_1009(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION;
CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE;
struct mac_test const *test = NULL;
size_t n = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_close_lib;
for (n = 0; n < ARRAY_SIZE(cktest_mac_cases); n++) {
test = &cktest_mac_cases[n];
Do_ADBG_BeginSubCase(c, "Verify case %zu algo (%s)", n,
ckm2str(test->mechanism->mechanism));
rv = C_CreateObject(session, test->attr_key, test->attr_count,
&key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
/* Test Verification in 1 step */
if (test->in != NULL) {
rv = C_VerifyInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Pass input buffer with size 0 - No affect */
rv = C_VerifyUpdate(session, (void *)test->in, 0);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyUpdate(session, (void *)test->in,
test->in_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyFinal(session,
(void *)test->out,
get_mac_test_len(test));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
}
/* Test 2 step update verification*/
rv = C_VerifyInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
if (test->in != NULL) {
rv = C_VerifyUpdate(session,
(void *)test->in, test->in_incr);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyUpdate(session,
(void *)(test->in + test->in_incr),
test->in_len - test->in_incr);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
}
rv = C_VerifyFinal(session, (void *)test->out,
get_mac_test_len(test));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Error as Operation has already completed */
rv = C_Verify(session,
(void *)test->in, test->in_len,
(void *)test->out, get_mac_test_len(test));
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED,
rv))
goto err_destr_obj;
/* Test 3 verification in one shot */
if (test->in != NULL) {
rv = C_VerifyInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session,
(void *)test->in, test->in_len,
(void *)test->out,
get_mac_test_len(test));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Try calling Verify again */
rv = C_Verify(session,
(void *)test->in, test->in_len,
(void *)test->out,
get_mac_test_len(test));
if (!ADBG_EXPECT_CK_RESULT(c,
CKR_OPERATION_NOT_INITIALIZED,
rv))
goto err_destr_obj;
}
/*
* Test 4 verification
* Error - Signature Length Range with C_VerifyFinal
*/
if (test->in != NULL) {
rv = C_VerifyInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyUpdate(session, (void *)test->in,
test->in_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyFinal(session, (void *)test->out, 3);
if (!ADBG_EXPECT_CK_RESULT(c,
ckm_is_hmac_general(test) ?
CKR_OK :
CKR_SIGNATURE_LEN_RANGE,
rv))
goto err_destr_obj;
}
/*
* Test 5 verification
* Error - Signature Length Range with C_Verify
*/
if (test->in != NULL) {
rv = C_VerifyInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session,
(void *)test->in, test->in_len,
(void *)test->out, 0);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE,
rv))
goto err_destr_obj;
rv = C_VerifyInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session,
(void *)test->in, test->in_len,
(void *)test->out,
TEE_MAX_HASH_SIZE + 1);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE,
rv))
goto err_destr_obj;
}
/* Test 6 verification - Invalid Operation sequence */
if (test->in != NULL) {
rv = C_VerifyInit(session, test->mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session,
(void *)test->in, test->in_len,
(void *)test->out,
get_mac_test_len(test));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
/* Init session has already terminated with C_Verify */
rv = C_VerifyUpdate(session, (void *)test->in,
test->in_len);
if (!ADBG_EXPECT_CK_RESULT(c,
CKR_OPERATION_NOT_INITIALIZED,
rv))
goto err_destr_obj;
}
rv = C_DestroyObject(session, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
}
goto out;
err_destr_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
err:
Do_ADBG_EndSubCase(c, NULL);
out:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
err_close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1009, xtest_pkcs11_test_1009,
"PKCS11: Check Compliance of C_Verify - HMAC Algorithms");
/* Bad key type */
static CK_ATTRIBUTE cktest_generate_gensecret_object_error1[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) },
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
};
/* Missing VALUE_LEN */
static CK_ATTRIBUTE cktest_generate_gensecret_object_error2[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_GENERIC_SECRET},
sizeof(CK_KEY_TYPE) },
};
/* Bad object class */
static CK_ATTRIBUTE cktest_generate_gensecret_object_error3[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_DATA}, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_GENERIC_SECRET},
sizeof(CK_KEY_TYPE) },
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
};
/* Invalid template with CKA_LOCAL */
static CK_ATTRIBUTE cktest_generate_gensecret_object_error4[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
{ CKA_LOCAL, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
/* Valid template to generate a generic secret */
static CK_ATTRIBUTE cktest_generate_gensecret_object_valid1[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_GENERIC_SECRET},
sizeof(CK_KEY_TYPE) },
{ CKA_SIGN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
};
/* Valid template to generate a generic secret with only VALUE_LEN */
static CK_ATTRIBUTE cktest_generate_gensecret_object_valid2[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
{ CKA_SIGN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
/* Valid template to generate an all AES purpose key */
static CK_ATTRIBUTE cktest_generate_aes_object[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) },
{ CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
};
static void xtest_pkcs11_test_1010(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE;
struct mac_test test_sign = CKTEST_MAC_TEST(cktest_hmac_md5_key,
&cktest_hmac_md5_mechanism,
4, mac_data_md5_in1,
mac_data_md5_out1, false);
uint8_t out[512] = { 0 };
CK_ULONG out_len = 512;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/*
* Generate Generic Secret key using invalid templates
*/
Do_ADBG_BeginSubCase(c, "Generate Secret Key with Invalid Templates");
/* NULL Template with !null template length */
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, NULL,
3, &key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
goto err;
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
cktest_generate_gensecret_object_error1,
ARRAY_SIZE(cktest_generate_gensecret_object_error1),
&key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv))
goto err;
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
cktest_generate_gensecret_object_error2,
ARRAY_SIZE(cktest_generate_gensecret_object_error2),
&key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCOMPLETE, rv))
goto err;
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
cktest_generate_gensecret_object_error3,
ARRAY_SIZE(cktest_generate_gensecret_object_error3),
&key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv))
goto err;
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
cktest_generate_gensecret_object_error4,
ARRAY_SIZE(cktest_generate_gensecret_object_error4),
&key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
/*
* Generate a Generic Secret object.
* Try to encrypt with, it should fail...
*/
Do_ADBG_BeginSubCase(c, "Generate Generic Secret Key - Try Encrypting");
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
cktest_generate_gensecret_object_valid1,
ARRAY_SIZE(cktest_generate_gensecret_object_valid1),
&key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_FUNCTION_NOT_PERMITTED, rv))
goto err_destr_obj;
rv = C_DestroyObject(session, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
/*
* Generate a Generic Secret object.
* Try to sign with it, it should pass...
*/
Do_ADBG_BeginSubCase(c, "Generate Generic Secret Key - Try Signing");
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
cktest_generate_gensecret_object_valid2,
ARRAY_SIZE(cktest_generate_gensecret_object_valid2),
&key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
rv = C_SignInit(session, test_sign.mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Sign(session, (void *)test_sign.in, test_sign.in_len,
(void *)out, &out_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_DestroyObject(session, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
/*
* Generate a 128 bit AES Secret Key.
* Try to encrypt with, it should pass...
*/
Do_ADBG_BeginSubCase(c, "Generate AES Key - Try Encrypting");
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
cktest_generate_aes_object,
ARRAY_SIZE(cktest_generate_aes_object),
&key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_EncryptFinal(session, NULL, NULL);
/* Only check that the operation is no more active */
if (!ADBG_EXPECT_TRUE(c, rv != CKR_BUFFER_TOO_SMALL))
goto err;
rv = C_DestroyObject(session, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
goto out;
err_destr_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
err:
Do_ADBG_EndSubCase(c, NULL);
out:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1010, xtest_pkcs11_test_1010,
"PKCS11: Key Generation");
static CK_RV create_data_object(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE *obj_handle,
CK_BBOOL token, CK_BBOOL private,
const char *label)
{
CK_OBJECT_CLASS class = CKO_DATA;
CK_ATTRIBUTE object_template[] = {
{ CKA_CLASS, &class, sizeof(CK_OBJECT_CLASS) },
{ CKA_TOKEN, &token, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &private, sizeof(CK_BBOOL) },
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
};
return C_CreateObject(session, object_template,
ARRAY_SIZE(object_template), obj_handle);
}
static CK_RV test_find_objects(ADBG_Case_t *c, CK_SESSION_HANDLE session,
CK_ATTRIBUTE_PTR find_template,
CK_ULONG attr_count,
CK_OBJECT_HANDLE_PTR obj_found,
CK_ULONG obj_count,
CK_ULONG expected_cnt)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_ULONG hdl_count = 0;
rv = C_FindObjectsInit(session, find_template, attr_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
return rv;
rv = C_FindObjects(session, obj_found, obj_count, &hdl_count);
if (!ADBG_EXPECT_CK_OK(c, rv))
return rv;
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, hdl_count, ==, expected_cnt))
return CKR_GENERAL_ERROR;
rv = C_FindObjectsFinal(session);
if (!ADBG_EXPECT_CK_OK(c, rv))
return rv;
return rv;
}
static void destroy_persistent_objects(ADBG_Case_t *c, CK_SLOT_ID slot)
{
uint32_t rv = CKR_GENERAL_ERROR;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE;
CK_ULONG count = 1;
CK_ATTRIBUTE cktest_find_all_token_objs[] = {
{ CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
/* Login to destroy private objects */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
rv = C_FindObjectsInit(session, cktest_find_all_token_objs,
ARRAY_SIZE(cktest_find_all_token_objs));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
while (1) {
rv = C_FindObjects(session, &obj_hdl, 1, &count);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto bail;
if (!count)
break;
rv = C_DestroyObject(session, obj_hdl);
ADBG_EXPECT_CK_OK(c, rv);
}
rv = C_FindObjectsFinal(session);
ADBG_EXPECT_CK_OK(c, rv);
rv = C_Logout(session);
ADBG_EXPECT_CK_OK(c, rv);
bail:
rv = C_CloseSession(session);
ADBG_EXPECT_CK_OK(c, rv);
}
static void xtest_pkcs11_test_1011(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_OBJECT_HANDLE obj_hdl[10] = { };
CK_OBJECT_HANDLE obj_found[10] = { };
const char *label = "Common Label";
CK_ULONG hdl_count = 0;
size_t n = 0;
uint32_t i = 0;
uint32_t object_id = 0;
bool logged_in = false;
CK_ATTRIBUTE find_template[] = {
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
};
CK_ATTRIBUTE find_token_template[] = {
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
{ CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE find_session_template[] = {
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
{ CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
};
CK_BBOOL bToken = CK_FALSE;
CK_ATTRIBUTE get_attr_template[] = {
{ CKA_TOKEN, &bToken, sizeof(bToken) },
};
for (n = 0; n < ARRAY_SIZE(obj_hdl); n++)
obj_hdl[n] = CK_INVALID_HANDLE;
for (n = 0; n < ARRAY_SIZE(obj_found); n++)
obj_found[n] = CK_INVALID_HANDLE;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/*
* Sub test: Create Session Public/Private,
* Token Public/Private objects and find them
*/
Do_ADBG_BeginSubCase(c, "Find created Data objects when logged in");
/* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(session, &obj_hdl[object_id++], CK_FALSE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(session, &obj_hdl[object_id++], CK_TRUE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE
* Expected error as User not logged in
*/
rv = create_data_object(session, &obj_hdl[object_id], CK_TRUE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto out;
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
logged_in = true;
/* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(session, &obj_hdl[object_id++], CK_TRUE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(session, &obj_hdl[object_id++], CK_FALSE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = test_find_objects(c, session, find_template,
ARRAY_SIZE(find_template),
obj_found, ARRAY_SIZE(obj_found), 4);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Check if object handles returned when creating objects with this
* session are still valid
*/
for (i = 0; i < object_id; i++) {
rv = C_GetAttributeValue(session, obj_hdl[i], get_attr_template,
ARRAY_SIZE(get_attr_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
}
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Pass NULL template with count as 0. All objects should
* get returned
*/
Do_ADBG_BeginSubCase(c, "Find all objects by passing NULL template");
rv = test_find_objects(c, session, NULL, 0, obj_found,
ARRAY_SIZE(obj_found), 4);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: finalize search without getting the handles found
*/
Do_ADBG_BeginSubCase(c, "Initiate and finalize straight a search");
rv = C_FindObjectsInit(session, find_template,
ARRAY_SIZE(find_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_FindObjectsFinal(session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Check if object handles returned when creating objects with this
* session are still valid
*/
for (i = 0; i < object_id; i++) {
rv = C_GetAttributeValue(session, obj_hdl[i], get_attr_template,
ARRAY_SIZE(get_attr_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
}
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Logout and find objects. We will find only public
* objects (2)
*/
Do_ADBG_BeginSubCase(c, "Find created Data objects when logged out");
rv = C_Logout(session);
ADBG_EXPECT_CK_OK(c, rv);
logged_in = false;
rv = test_find_objects(c, session, find_template,
ARRAY_SIZE(find_template),
obj_found, ARRAY_SIZE(obj_found), 2);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test
*/
Do_ADBG_BeginSubCase(c, "Find objects 1 by 1 and match handles");
for (n = 0; n < ARRAY_SIZE(obj_found); n++)
obj_found[n] = CK_INVALID_HANDLE;
rv = C_FindObjectsInit(session, find_template,
ARRAY_SIZE(find_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_FindObjects(session, obj_found, 1, &hdl_count);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, hdl_count, ==, 1) ||
!ADBG_EXPECT_TRUE(c, (obj_found[0] == obj_hdl[0]) ||
(obj_found[0] == obj_hdl[1])))
goto out;
rv = C_FindObjects(session, &obj_found[1], 1, &hdl_count);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, hdl_count, ==, 1) ||
!ADBG_EXPECT_TRUE(c, (obj_found[1] == obj_hdl[0]) ||
(obj_found[1] == obj_hdl[1])) ||
!ADBG_EXPECT_TRUE(c, (obj_found[1] != obj_found[0])))
goto out;
rv = C_FindObjects(session, obj_found, 1, &hdl_count);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, hdl_count, ==, 0))
goto out;
rv = C_FindObjectsFinal(session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Find objects with CKA_TOKEN=TRUE
*/
Do_ADBG_BeginSubCase(c, "Find persistent objects");
rv = test_find_objects(c, session, find_token_template,
ARRAY_SIZE(find_token_template),
obj_found, ARRAY_SIZE(obj_found), 1);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Find only session objects
*/
Do_ADBG_BeginSubCase(c, "Find session objects");
rv = test_find_objects(c, session, find_session_template,
ARRAY_SIZE(find_session_template),
obj_found, ARRAY_SIZE(obj_found), 1);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test:
*/
Do_ADBG_BeginSubCase(c, "Login again and find Data objects");
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
logged_in = true;
rv = test_find_objects(c, session, find_template,
ARRAY_SIZE(find_template),
obj_found, ARRAY_SIZE(obj_found), 3);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Logout(session);
ADBG_EXPECT_CK_OK(c, rv);
logged_in = false;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Close session and open new session, find objects
* without logging and after logging
*/
Do_ADBG_BeginSubCase(c, "Find objects from brand new session");
rv = C_CloseSession(session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto destr_obj;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto destr_obj;
rv = test_find_objects(c, session, find_template,
ARRAY_SIZE(find_template),
obj_found, ARRAY_SIZE(obj_found), 1);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
logged_in = true;
rv = test_find_objects(c, session, find_template,
ARRAY_SIZE(find_template),
obj_found, ARRAY_SIZE(obj_found), 2);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Logout(session);
ADBG_EXPECT_CK_OK(c, rv);
logged_in = false;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: invalid call cases
*/
Do_ADBG_BeginSubCase(c, "Invalid cases");
rv = C_FindObjectsFinal(session);
ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv);
rv = C_FindObjects(session,
obj_found, ARRAY_SIZE(obj_found), &hdl_count);
ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv);
rv = C_FindObjectsInit(session, find_template,
ARRAY_SIZE(find_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_FindObjectsInit(session, find_template,
ARRAY_SIZE(find_template));
ADBG_EXPECT_COMPARE_UNSIGNED(c, rv, !=, CKR_OK);
rv = C_FindObjectsFinal(session);
ADBG_EXPECT_CK_OK(c, rv);
rv = C_FindObjectsInit(session, find_template,
ARRAY_SIZE(find_template));
ADBG_EXPECT_CK_OK(c, rv);
/*
* Intentionally do not finalize the active object search. It should be
* released together with the session closure.
*/
Do_ADBG_EndSubCase(c, NULL);
out:
if (logged_in)
ADBG_EXPECT_CK_OK(c, C_Logout(session));
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
destr_obj:
destroy_persistent_objects(c, slot);
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1011, xtest_pkcs11_test_1011,
"PKCS11: Test Find Objects");
static void xtest_pkcs11_test_1012(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE key_hdl = CK_INVALID_HANDLE;
size_t i = 0;
CK_OBJECT_CLASS obj_class = CKO_DATA;
CK_BBOOL obj_token = CK_FALSE;
CK_BBOOL obj_private = CK_FALSE;
uint8_t obj_value[5] = { 1, 2, 3, 4, 5 };
const char *obj_label = "Label";
CK_ATTRIBUTE object_template[] = {
{ CKA_CLASS, &obj_class, sizeof(obj_class) },
{ CKA_TOKEN, &obj_token, sizeof(obj_token) },
{ CKA_PRIVATE, &obj_private, sizeof(obj_private) },
{ CKA_VALUE, obj_value, sizeof(obj_value) },
{ CKA_LABEL, (CK_UTF8CHAR_PTR)obj_label, strlen(obj_label) },
};
CK_OBJECT_CLASS secret_class = CKO_SECRET_KEY;
CK_BBOOL secret_token = CK_FALSE;
CK_BBOOL secret_private = CK_FALSE;
CK_KEY_TYPE secret_key_type = CKK_GENERIC_SECRET;
CK_ULONG secret_len = 32;
CK_MECHANISM_TYPE secret_allowed_mecha[] = { CKM_SHA_1_HMAC,
CKM_SHA224_HMAC,
CKM_SHA256_HMAC };
CK_ATTRIBUTE secret_template[] = {
{ CKA_CLASS, &secret_class, sizeof(secret_class) },
{ CKA_TOKEN, &secret_token, sizeof(secret_token) },
{ CKA_PRIVATE, &secret_private, sizeof(secret_private) },
{ CKA_KEY_TYPE, &secret_key_type, sizeof(secret_key_type) },
{ CKA_VALUE_LEN, &secret_len, sizeof(secret_len) },
{ CKA_ALLOWED_MECHANISMS, secret_allowed_mecha,
sizeof(secret_allowed_mecha) }
};
CK_BBOOL g_token = CK_TRUE;
CK_BBOOL g_private = CK_TRUE;
CK_OBJECT_CLASS g_class = ~0;
uint8_t g_value[128] = { 0 };
CK_MECHANISM_TYPE g_mecha_list[10] = { 0 };
uint8_t *data_ptr = NULL;
CK_ATTRIBUTE get_attr_template_bc[] = {
{ CKA_TOKEN, &g_token, sizeof(g_token) },
{ CKA_CLASS, &g_class, sizeof(g_class) },
};
CK_ATTRIBUTE get_attr_template_cb[] = {
{ CKA_CLASS, &g_class, sizeof(g_class) },
{ CKA_TOKEN, &g_token, sizeof(g_token) },
};
CK_ATTRIBUTE get_attr_template_query_bc[] = {
{ CKA_TOKEN, NULL, 0 },
{ CKA_CLASS, NULL, 0 },
};
CK_ATTRIBUTE get_attr_template_query_cb[] = {
{ CKA_CLASS, NULL, 0 },
{ CKA_TOKEN, NULL, 0 },
};
CK_ATTRIBUTE get_attr_template_ve[] = {
{ CKA_VALUE, &g_value, sizeof(obj_value) },
};
CK_ATTRIBUTE get_attr_template_vl[] = {
{ CKA_VALUE, &g_value, sizeof(g_value) },
};
CK_ATTRIBUTE get_attr_template_bvecb[] = {
{ CKA_TOKEN, &g_token, sizeof(g_token) },
{ CKA_VALUE, &g_value, sizeof(obj_value) },
{ CKA_CLASS, &g_class, sizeof(g_class) },
{ CKA_TOKEN, &g_private, sizeof(g_private) },
};
CK_ATTRIBUTE get_attr_template_bvlcb[] = {
{ CKA_TOKEN, &g_token, sizeof(g_token) },
{ CKA_VALUE, &g_value, sizeof(g_value) },
{ CKA_CLASS, &g_class, sizeof(g_class) },
{ CKA_TOKEN, &g_private, sizeof(g_private) },
};
CK_ATTRIBUTE get_attr_template_am[] = {
{ CKA_ALLOWED_MECHANISMS, &g_mecha_list, sizeof(g_mecha_list) },
};
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */
rv = C_CreateObject(session, object_template,
ARRAY_SIZE(object_template), &obj_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Sub test: Test Boolean (1 byte) + object class (CK_ULONG)
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - boolean + class");
g_token = CK_TRUE;
g_class = ~0;
rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_bc,
ARRAY_SIZE(get_attr_template_bc));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_DATA);
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE);
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: object class (CK_ULONG) + Test Boolean (1 byte)
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - class + boolean");
g_token = CK_TRUE;
g_class = ~0;
rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_cb,
ARRAY_SIZE(get_attr_template_cb));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_DATA);
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE);
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Query size boolean (1 byte) + object class (CK_ULONG)
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - query size boolean + class");
g_token = CK_TRUE;
g_class = ~0;
rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_query_bc,
ARRAY_SIZE(get_attr_template_query_bc));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c,
get_attr_template_query_bc[0].ulValueLen, ==, 1);
ADBG_EXPECT_COMPARE_UNSIGNED(c,
get_attr_template_query_bc[1].ulValueLen, ==, sizeof(CK_ULONG));
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Query size object class (CK_ULONG) + boolean (1 byte)
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - query size class + boolean");
g_token = CK_TRUE;
g_class = ~0;
rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_query_cb,
ARRAY_SIZE(get_attr_template_query_cb));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c,
get_attr_template_query_cb[0].ulValueLen, ==, sizeof(CK_ULONG));
ADBG_EXPECT_COMPARE_UNSIGNED(c,
get_attr_template_query_cb[1].ulValueLen, ==, 1);
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: value with exact size
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - value with exact size buffer");
memset(g_value, 0xCC, sizeof(g_value));
rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_ve,
ARRAY_SIZE(get_attr_template_ve));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_ve[0].ulValueLen, ==, sizeof(obj_value));
ADBG_EXPECT_EQUAL(c, g_value, obj_value, sizeof(obj_value));
for (i = sizeof(obj_value); i < sizeof(g_value); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_value[i], ==, 0xCC))
break;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: value with larger buffer
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - value with larger buffer");
memset(g_value, 0xCC, sizeof(g_value));
rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_vl,
ARRAY_SIZE(get_attr_template_vl));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_vl[0].ulValueLen, ==, sizeof(obj_value));
ADBG_EXPECT_EQUAL(c, g_value, obj_value, sizeof(obj_value));
for (i = sizeof(obj_value); i < sizeof(g_value); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_value[i], ==, 0xCC))
break;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: bool + value with exact size + class + bool
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - bool + value with exact size + class + bool");
memset(g_value, 0xCC, sizeof(g_value));
g_token = CK_TRUE;
g_private = CK_TRUE;
g_class = ~0;
rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_bvecb,
ARRAY_SIZE(get_attr_template_bvecb));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_bvecb[1].ulValueLen,
==, sizeof(obj_value));
ADBG_EXPECT_EQUAL(c, g_value, obj_value, sizeof(obj_value));
for (i = sizeof(obj_value); i < sizeof(g_value); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_value[i], ==, 0xCC))
break;
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_DATA);
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE);
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE);
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: bool + value with larger buffer + class + bool
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - bool + value with larger buffer + class + bool");
memset(g_value, 0xCC, sizeof(g_value));
g_token = CK_TRUE;
g_private = CK_TRUE;
g_class = ~0;
rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_bvlcb,
ARRAY_SIZE(get_attr_template_bvlcb));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_bvlcb[1].ulValueLen,
==, sizeof(obj_value));
ADBG_EXPECT_EQUAL(c, g_value, obj_value, sizeof(obj_value));
for (i = sizeof(obj_value); i < sizeof(g_value); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_value[i], ==, 0xCC))
break;
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_DATA);
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE);
ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE);
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: allowed mechanism list
*/
Do_ADBG_BeginSubCase(c, "Get Attribute - allowed mechanism list");
memset(g_mecha_list, 0xCC, sizeof(g_mecha_list));
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
secret_template, ARRAY_SIZE(secret_template),
&key_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetAttributeValue(session, key_hdl, get_attr_template_am,
ARRAY_SIZE(get_attr_template_am));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_am[0].ulValueLen, ==,
sizeof(secret_allowed_mecha));
for (i = 0; i < sizeof(secret_allowed_mecha) / sizeof(*secret_allowed_mecha); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_mecha_list[i], ==, secret_allowed_mecha[i]))
break;
data_ptr = (uint8_t *)g_mecha_list;
for (i = sizeof(secret_allowed_mecha); i < sizeof(g_mecha_list); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, data_ptr[i], ==, 0xCC))
break;
Do_ADBG_EndSubCase(c, NULL);
out:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1012, xtest_pkcs11_test_1012,
"PKCS11: Serializer tests");
static void xtest_pkcs11_test_1013(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE rw_session = CK_INVALID_HANDLE;
CK_SESSION_HANDLE ro_session = CK_INVALID_HANDLE;
CK_FLAGS rw_session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_FLAGS ro_session_flags = CKF_SERIAL_SESSION;
CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE;
const char *label = "Dummy Objects";
bool ro_logged_in = false;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Open a RW session */
rv = C_OpenSession(slot, rw_session_flags, NULL, 0, &rw_session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Open a RO session */
rv = C_OpenSession(slot, ro_session_flags, NULL, 0, &ro_session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/*
* Sub test: Check object creation from a R/O Public session
*/
Do_ADBG_BeginSubCase(c, "Create objects in R/O Public Session");
/* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(ro_session, &obj_hdl, CK_FALSE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(ro_session, &obj_hdl, CK_FALSE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto out;
/* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(ro_session, &obj_hdl, CK_TRUE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv))
goto out;
/* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(ro_session, &obj_hdl, CK_TRUE,
CK_TRUE, label);
/* For Token object creation, SESSION_READ_ONLY will take priority */
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Check access for a R/W Public session
*/
Do_ADBG_BeginSubCase(c, "Create objects in R/O Public Session");
/* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(rw_session, &obj_hdl, CK_FALSE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(rw_session, &obj_hdl, CK_FALSE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto out;
/* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(rw_session, &obj_hdl, CK_TRUE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(rw_session, &obj_hdl, CK_TRUE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Check access for a R/O User session
*/
Do_ADBG_BeginSubCase(c, "Create objects in R/O User Session");
/* Login to Test Token */
rv = C_Login(ro_session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ro_logged_in = true;
/* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(ro_session, &obj_hdl, CK_FALSE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(ro_session, &obj_hdl, CK_FALSE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(ro_session, &obj_hdl, CK_TRUE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv))
goto out;
/* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(ro_session, &obj_hdl, CK_TRUE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Check access for a R/W User session
*/
Do_ADBG_BeginSubCase(c, "Create objects in R/W User Session");
/* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(rw_session, &obj_hdl, CK_FALSE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(rw_session, &obj_hdl, CK_FALSE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(rw_session, &obj_hdl, CK_TRUE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(rw_session, &obj_hdl, CK_TRUE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Log out */
ADBG_EXPECT_CK_OK(c, C_Logout(ro_session));
ro_logged_in = false;
/* Close RO session */
ADBG_EXPECT_CK_OK(c, C_CloseSession(ro_session));
ro_session = CK_INVALID_HANDLE;
Do_ADBG_EndSubCase(c, NULL);
/*
* Sub test: Check access for a R/W SO session
*/
Do_ADBG_BeginSubCase(c, "Create objects in R/W SO Session");
/* Login as security officer in RW session */
rv = C_Login(rw_session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(rw_session, &obj_hdl, CK_FALSE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto logout;
/* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(rw_session, &obj_hdl, CK_FALSE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto logout;
/* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */
rv = create_data_object(rw_session, &obj_hdl, CK_TRUE,
CK_FALSE, label);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto logout;
/* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */
rv = create_data_object(rw_session, &obj_hdl, CK_TRUE,
CK_TRUE, label);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto logout;
logout:
ADBG_EXPECT_CK_OK(c, C_Logout(rw_session));
out:
if (ro_logged_in)
ADBG_EXPECT_CK_OK(c, C_Logout(ro_session));
if (ro_session != CK_INVALID_HANDLE)
ADBG_EXPECT_CK_OK(c, C_CloseSession(ro_session));
ADBG_EXPECT_CK_OK(c, C_CloseSession(rw_session));
Do_ADBG_EndSubCase(c, NULL);
destroy_persistent_objects(c, slot);
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1013, xtest_pkcs11_test_1013,
"PKCS11: Object creation upon session type");
static void xtest_pkcs11_test_1014(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE;
const char *id = "1";
const char *label = "Dummy Objects";
const char *new_label = "New Object lable";
size_t n = 0;
char *g_label[100] = { };
char *g_id[100] = { };
CK_MECHANISM_TYPE secret_allowed_mecha[] = { CKM_SHA_1_HMAC,
CKM_SHA224_HMAC,
CKM_SHA256_HMAC };
CK_ATTRIBUTE secret_key_template[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_COPYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_DESTROYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_GENERIC_SECRET},
sizeof(CK_KEY_TYPE) },
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
{ CKA_VALUE, (void *)cktest_aes128_key, sizeof(cktest_aes128_key) },
{ CKA_SIGN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_ALLOWED_MECHANISMS, secret_allowed_mecha,
sizeof(secret_allowed_mecha) },
};
CK_BBOOL g_derive = CK_FALSE;
CK_BBOOL g_sign = CK_FALSE;
CK_BBOOL g_verify = CK_FALSE;
CK_BBOOL g_encrypt = CK_FALSE;
CK_BBOOL g_decrypt = CK_FALSE;
CK_BBOOL g_wrap = CK_FALSE;
CK_BBOOL g_unwrap = CK_FALSE;
uint32_t g_len = 0;
CK_ATTRIBUTE get_template[] = {
{ CKA_LABEL, (CK_UTF8CHAR_PTR)g_label, sizeof(g_label) },
{ CKA_ID, (CK_BYTE_PTR)g_id, sizeof(g_id) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_SIGN, &g_sign, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &g_verify, sizeof(CK_BBOOL) },
{ CKA_ENCRYPT, &g_encrypt, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &g_decrypt, sizeof(CK_BBOOL) },
{ CKA_WRAP, &g_wrap, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &g_unwrap, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &g_len, sizeof(CK_ULONG) },
};
CK_ATTRIBUTE set_template[] = {
{ CKA_LABEL, (CK_UTF8CHAR_PTR)new_label, strlen(new_label) },
{ CKA_ID, (CK_BYTE_PTR)id, strlen(id) },
{ CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_WRAP, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_SIGN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_ENCRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
/* CKA_SENSITIVE -> CK_FALSE to CK_TRUE is allowed */
{ CKA_SENSITIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
/* CKA_EXTRACTABLE -> CK_TRUE to CK_FALSE is allowed */
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
/* CKA_COPYABLE -> CK_TRUE to CK_FALSE is allowed */
{ CKA_COPYABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE set_inv_template1[] = {
/* Attributes Not Modifiable */
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_DATA},
sizeof(CK_OBJECT_CLASS) },
{ CKA_LOCAL, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_SENSITIVE, &(CK_BBOOL){CK_FALSE},
sizeof(CK_BBOOL) },
{ CKA_NEVER_EXTRACTABLE, &(CK_BBOOL){CK_FALSE},
sizeof(CK_BBOOL) },
{ CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_MODIFIABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_DESTROYABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
/* Change not allowed from CK_TRUE -> CK_FALSE */
{ CKA_SENSITIVE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
/* Change not allowed from CK_FALSE -> CK_TRUE */
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_COPYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE set_inv_template2[] = {
{ CKA_APPLICATION, (CK_UTF8CHAR_PTR)label, sizeof(label) },
};
CK_ATTRIBUTE set_trusted_template[] = {
{ CKA_TRUSTED, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Open a RW session */
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Create a secret key object */
rv = C_CreateObject(session, secret_key_template,
ARRAY_SIZE(secret_key_template), &obj_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
Do_ADBG_BeginSubCase(c, "Set attributes on secret key object");
rv = C_GetAttributeValue(session, obj_hdl, get_template,
ARRAY_SIZE(get_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_BUFFER(c, label, strlen(label), g_label,
get_template[0].ulValueLen) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_len, ==, 16) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, get_template[1].ulValueLen, ==, 0))
goto out;
rv = C_SetAttributeValue(session, obj_hdl, set_template,
ARRAY_SIZE(set_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
get_template[0].ulValueLen = sizeof(g_label);
get_template[1].ulValueLen = sizeof(g_id);
rv = C_GetAttributeValue(session, obj_hdl, get_template,
ARRAY_SIZE(get_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_BUFFER(c, new_label, strlen(new_label), g_label,
get_template[0].ulValueLen) ||
!ADBG_EXPECT_BUFFER(c, id, strlen(id), g_id,
get_template[1].ulValueLen) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_FALSE))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test Invalid template with R/O Attributes");
for (n = 0; n < ARRAY_SIZE(set_inv_template1); n++) {
rv = C_SetAttributeValue(session, obj_hdl,
&set_inv_template1[n], 1);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_READ_ONLY, rv))
goto out;
}
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test Invalid template with Invalid Attribute");
rv = C_SetAttributeValue(session, obj_hdl, set_inv_template2,
ARRAY_SIZE(set_inv_template2));
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_TYPE_INVALID, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Set CKA_TRUSTED with and w/o SO Login");
rv = C_SetAttributeValue(session, obj_hdl, set_trusted_template,
ARRAY_SIZE(set_trusted_template));
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_READ_ONLY, rv))
goto out;
/* Login as SO in RW session */
rv = C_Login(session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_SetAttributeValue(session, obj_hdl, set_trusted_template,
ARRAY_SIZE(set_trusted_template));
ADBG_EXPECT_CK_OK(c, rv);
ADBG_EXPECT_CK_OK(c, C_Logout(session));
out:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, obj_hdl));
Do_ADBG_EndSubCase(c, NULL);
close_session:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1014, xtest_pkcs11_test_1014,
"PKCS11: Test C_SetAttributeValue()");
static void xtest_pkcs11_test_1015(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE rw_session = CK_INVALID_HANDLE;
CK_SESSION_HANDLE ro_session = CK_INVALID_HANDLE;
CK_FLAGS rw_session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_FLAGS ro_session_flags = CKF_SERIAL_SESSION;
CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE obj_hdl_ro = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE obj_hdl_cp = CK_INVALID_HANDLE;
const char *label = "Dummy Objects";
CK_ATTRIBUTE secret_key_create_template[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) },
{ CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_COPYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_DESTROYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_VALUE, (void *)cktest_aes128_key, sizeof(cktest_aes128_key) },
};
CK_ATTRIBUTE secret_key_template[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY},
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) },
{ CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_COPYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_DESTROYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
};
CK_BBOOL g_token = CK_FALSE;
CK_BBOOL g_private = CK_FALSE;
CK_BBOOL g_modify = CK_FALSE;
CK_BBOOL g_copy = CK_FALSE;
CK_BBOOL g_destroy = CK_FALSE;
CK_BBOOL g_extract = CK_FALSE;
CK_BBOOL g_sensitive = CK_FALSE;
CK_BBOOL g_nextract = CK_FALSE;
CK_BBOOL g_asensitive = CK_FALSE;
CK_BBOOL g_local = CK_FALSE;
CK_BYTE g_value[16] = { };
CK_ATTRIBUTE get_template[] = {
{ CKA_TOKEN, &g_token, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &g_private, sizeof(CK_BBOOL) },
{ CKA_MODIFIABLE, &g_modify, sizeof(CK_BBOOL) },
{ CKA_COPYABLE, &g_copy, sizeof(CK_BBOOL) },
{ CKA_DESTROYABLE, &g_destroy, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &g_extract, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &g_sensitive, sizeof(CK_BBOOL) },
{ CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE get_value_template[] = {
{ CKA_VALUE, &g_value, sizeof(g_value) }
};
CK_ATTRIBUTE copy_template[] = {
{ CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_MODIFIABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE copy_template_inv[] = {
{ CKA_APPLICATION, (CK_UTF8CHAR_PTR)label, sizeof(label) },
};
CK_ATTRIBUTE copy_template_priv[] = {
{ CKA_PRIVATE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE set_template[] = {
{ CKA_COPYABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
};
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Open a RW session */
rv = C_OpenSession(slot, rw_session_flags, NULL, 0, &rw_session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Open a RO session */
rv = C_OpenSession(slot, ro_session_flags, NULL, 0, &ro_session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
/*
* All objects in this test are session objects hence released at
* session closure on test completion.
*/
/* Generate a secret key object in rw session */
rv = C_GenerateKey(rw_session, &cktest_aes_keygen_mechanism,
secret_key_template,
ARRAY_SIZE(secret_key_template), &obj_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
/* Check its attribute values */
rv = C_GetAttributeValue(rw_session, obj_hdl, get_template,
ARRAY_SIZE(get_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_modify, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_copy, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_destroy, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE))
goto close_session;
/* Check that we can get (secret) CKA_VALUE */
get_value_template[0].ulValueLen = sizeof(g_value);
rv = C_GetAttributeValue(rw_session, obj_hdl, get_value_template,
ARRAY_SIZE(get_value_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, get_value_template[0].ulValueLen,
==, sizeof(g_value)))
goto close_session;
/* Create a secret key object in ro session*/
rv = C_CreateObject(ro_session, secret_key_create_template,
ARRAY_SIZE(secret_key_create_template), &obj_hdl_ro);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
/*
* Duplicate the object generated in RW session using C_GenerateKey() to
* another object. Pass Template as NULL and test the attributes of
* new created object.
*/
Do_ADBG_BeginSubCase(c, "Copy Local Obj with NULL Template");
rv = C_CopyObject(rw_session, obj_hdl, NULL, 0, &obj_hdl_cp);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Check its attribute values, should match the original object.
* CKA_LOCAL shall be TRUE even in copied object as original object
* was generated using C_GenerateKey()
*/
rv = C_GetAttributeValue(rw_session, obj_hdl_cp, get_template,
ARRAY_SIZE(get_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_modify, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_copy, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_destroy, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE))
goto out;
rv = C_DestroyObject(rw_session, obj_hdl_cp);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
obj_hdl_cp = CK_INVALID_HANDLE;
Do_ADBG_EndSubCase(c, NULL);
/*
* Duplicate the object generated in RO session using C_CreateObject()
* to another object. Pass Template as NULL and test the attributes of
* new created object.
*/
Do_ADBG_BeginSubCase(c, "Copy a non-local object with NULL Template");
/* Copy ro session object */
rv = C_CopyObject(ro_session, obj_hdl_ro, NULL, 0, &obj_hdl_cp);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Check its attribute values, should match the original object.
* CKA_LOCAL shall be FALSE even in copied object as original object
* was generated using C_CreateObject()
*/
rv = C_GetAttributeValue(ro_session, obj_hdl_cp, get_template,
ARRAY_SIZE(get_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_modify, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_copy, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_destroy, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE))
goto out;
rv = C_DestroyObject(ro_session, obj_hdl_cp);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
obj_hdl_cp = CK_INVALID_HANDLE;
Do_ADBG_EndSubCase(c, NULL);
/*
* Test copying object with a valid template and check if attributes
* get modified as indicated in the template. Checks modification of
* attributes like CKA_TOKEN, CKA_MODIFIABLE which were not modifiable
* via C_SetAttributeValue(). Also modifies the CKA_SENSITIVE,
* CKA_EXTRACTABLE and checks corresponding values of RO attributes
* CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE.
*/
Do_ADBG_BeginSubCase(c, "Copy Object with Valid Template");
/*
* Copy Session Object as a Token object
* Properties CKA_MODIFIABLE turned to FALSE
* CKA_EXTRACTABLE changed from TRUE to FALSE
* CKA_NEVER_EXTRACTABLE should be FALSE.
* CKA_SENSITIVE set to TRUE
* However CKA_ALWAYS_SENSITIVE should be FALSE
*/
rv = C_CopyObject(rw_session, obj_hdl, copy_template,
ARRAY_SIZE(copy_template), &obj_hdl_cp);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Check the changed attribute values */
rv = C_GetAttributeValue(rw_session, obj_hdl_cp, get_template,
ARRAY_SIZE(get_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_modify, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE))
goto out;
/* Check that we cannot anymore get (secret) CKA_VALUE */
get_value_template[0].ulValueLen = sizeof(g_value);
rv = C_GetAttributeValue(rw_session, obj_hdl_cp, get_value_template,
ARRAY_SIZE(get_value_template));
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_SENSITIVE, rv) ||
!(get_value_template[0].ulValueLen == CK_UNAVAILABLE_INFORMATION))
goto close_session;
/*
* The copied object has CKA_MODIFIABLE set to FALSE. Check if
* call to C_SetAttributeValue() returns CKR_ACTION_PROHIBITED
*/
rv = C_SetAttributeValue(rw_session, obj_hdl_cp, set_template,
ARRAY_SIZE(set_template));
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ACTION_PROHIBITED, rv))
goto out;
rv = C_DestroyObject(rw_session, obj_hdl_cp);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
obj_hdl_cp = CK_INVALID_HANDLE;
Do_ADBG_EndSubCase(c, NULL);
/*
* Test changing the CKA_PRIVATE to TRUE when copying object.
* Fails when user is not logged in. Passes after user logs in
*/
Do_ADBG_BeginSubCase(c, "Copy Object as a Private Object");
/* The first attempt will fail as user is not logged in */
rv = C_CopyObject(rw_session, obj_hdl, copy_template_priv,
ARRAY_SIZE(copy_template_priv), &obj_hdl_cp);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto out;
/* Login to Test Token and repeat*/
rv = C_Login(rw_session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Try copying a public object to a private object - should pass */
rv = C_CopyObject(rw_session, obj_hdl, copy_template_priv,
ARRAY_SIZE(copy_template_priv), &obj_hdl_cp);
if (!ADBG_EXPECT_CK_OK(c, rv)) {
ADBG_EXPECT_CK_OK(c, C_Logout(rw_session));
goto out;
}
if (!ADBG_EXPECT_CK_OK(c, C_Logout(rw_session)))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Copy Object with Invalid Template");
rv = C_CopyObject(rw_session, obj_hdl, copy_template_inv,
ARRAY_SIZE(copy_template_inv), &obj_hdl_cp);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_TYPE_INVALID, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Copy Object with COPYABLE false");
rv = C_SetAttributeValue(rw_session, obj_hdl, set_template,
ARRAY_SIZE(set_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_CopyObject(rw_session, obj_hdl, copy_template,
ARRAY_SIZE(copy_template), &obj_hdl_cp);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ACTION_PROHIBITED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Copy session object to token in RO session");
rv = C_CopyObject(ro_session, obj_hdl_ro, copy_template,
ARRAY_SIZE(copy_template), &obj_hdl_cp);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv))
goto out;
out:
Do_ADBG_EndSubCase(c, NULL);
/* Destroy any token objects which may have been created */
destroy_persistent_objects(c, slot);
close_session:
/* Closing session will also destroy all session objects */
if (ro_session != CK_INVALID_HANDLE)
ADBG_EXPECT_CK_OK(c, C_CloseSession(ro_session));
ADBG_EXPECT_CK_OK(c, C_CloseSession(rw_session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1015, xtest_pkcs11_test_1015,
"PKCS11: Test C_CopyObject()");
static void xtest_pkcs11_test_1016(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
uint8_t buffer[64] = { 0 };
size_t i = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
Do_ADBG_BeginSubCase(c, "Seed random bytes");
memset(buffer, 0xCC, sizeof(buffer));
rv = C_SeedRandom(session, buffer, sizeof(buffer));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Seed random bytes with zero length buffer");
rv = C_SeedRandom(session, buffer, 0);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_SeedRandom(session, NULL, 0);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Generate random bytes");
memset(buffer, 0xCC, sizeof(buffer));
rv = C_GenerateRandom(session, buffer, 61);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Verify that end of buffer is still 0xCC */
for (i = 61; i < sizeof(buffer); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, buffer[i], ==, 0xCC))
break;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Generate random bytes with zero length buffer");
memset(buffer, 0xCC, sizeof(buffer));
rv = C_GenerateRandom(session, buffer, 0);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Verify that whole buffer is still 0xCC */
for (i = 0; i < sizeof(buffer); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, buffer[i], ==, 0xCC))
break;
rv = C_GenerateRandom(session, NULL, 0);
ADBG_EXPECT_CK_OK(c, rv);
out:
Do_ADBG_EndSubCase(c, NULL);
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1016, xtest_pkcs11_test_1016,
"PKCS11: Random number generator tests");
static CK_RV derive_sym_key(CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE parent_key,
CK_MECHANISM_TYPE mechanism, size_t data_len,
CK_OBJECT_HANDLE_PTR derv_key_hdl, size_t key_len,
CK_OBJECT_CLASS key_class, CK_KEY_TYPE key_type,
CK_BBOOL sensitive, CK_BBOOL extble)
{
CK_RV rv = CKR_GENERAL_ERROR;
uint8_t buffer[512] = { 0 };
uint8_t iv[16] = { 0 };
CK_MECHANISM mech_derive = { 0 };
CK_KEY_DERIVATION_STRING_DATA key_derv_param = { 0 };
CK_AES_CBC_ENCRYPT_DATA_PARAMS aes_cbc_param = { };
CK_ATTRIBUTE derived_key_template[] = {
{ CKA_CLASS, &key_class, sizeof(key_class) },
{ CKA_KEY_TYPE, &key_type, sizeof(key_type) },
{ CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &sensitive, sizeof(sensitive) },
{ CKA_EXTRACTABLE, &extble, sizeof(extble) },
{ CKA_VALUE_LEN, &key_len, sizeof(key_len) }
};
if (data_len > sizeof(buffer))
return rv;
switch (mechanism) {
case CKM_AES_ECB_ENCRYPT_DATA:
key_derv_param.pData = buffer;
key_derv_param.ulLen = data_len;
mech_derive.mechanism = mechanism;
mech_derive.pParameter = &key_derv_param;
mech_derive.ulParameterLen = sizeof(key_derv_param);
break;
case CKM_AES_CBC_ENCRYPT_DATA:
memcpy(aes_cbc_param.iv, iv, 16);
aes_cbc_param.pData = buffer;
aes_cbc_param.length = data_len;
mech_derive.mechanism = mechanism;
mech_derive.pParameter = &aes_cbc_param;
mech_derive.ulParameterLen = sizeof(aes_cbc_param);
break;
case CKM_AES_ECB:
/* Not a derivation algorithm */
mech_derive.mechanism = mechanism;
mech_derive.pParameter = NULL;
mech_derive.ulParameterLen = 0;
break;
default:
return rv;
}
/* Don't use VALUE_LEN parameter if key_len passed is 0 */
if (key_len)
rv = C_DeriveKey(session, &mech_derive, parent_key,
derived_key_template,
ARRAY_SIZE(derived_key_template),
derv_key_hdl);
else
/* last attribute in template is the derived key size */
rv = C_DeriveKey(session, &mech_derive, parent_key,
derived_key_template,
ARRAY_SIZE(derived_key_template) - 1,
derv_key_hdl);
return rv;
}
static void xtest_pkcs11_test_1017(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_OBJECT_HANDLE derv_key_hdl = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE aes_key1 = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE aes_key2 = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE aes_key_enc = CK_INVALID_HANDLE;
size_t data_len = 0;
size_t key_len = 0;
CK_BBOOL g_extract = CK_FALSE;
CK_BBOOL g_sensitive = CK_FALSE;
CK_BBOOL g_nextract = CK_FALSE;
CK_BBOOL g_asensitive = CK_FALSE;
CK_BBOOL g_local = CK_FALSE;
CK_OBJECT_CLASS g_class = CKO_VENDOR_DEFINED;
CK_KEY_TYPE g_key_type = CKK_VENDOR_DEFINED;
uint8_t g_val[516] = { 0 };
CK_ULONG secret_len = 0;
CK_ATTRIBUTE get_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_EXTRACTABLE, &g_extract, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &g_sensitive, sizeof(CK_BBOOL) },
{ CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &secret_len, sizeof(secret_len) },
/*
* CKA_VALUE should remain last attribute in template,
* in this test case as we check the length returned
* from last index of the get_template in this test.
*/
{ CKA_VALUE, g_val, sizeof(g_val) },
};
uint32_t idx = ARRAY_SIZE(get_template) - 1;
CK_ATTRIBUTE parent_template1[] = {
{ CKA_SENSITIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
{ CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE parent_template2[] = {
{ CKA_SENSITIVE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
{ CKA_ENCRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE parent_template_wo_derive[] = {
{ CKA_SENSITIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
};
CK_ATTRIBUTE parent_template_w_enc_der[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) },
{ CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
{ CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },
};
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/*
* Parent AES Key 1
* SENSITIVE = TRUE, EXTRACTABLE = FALSE
* ALWAYS_SENSITIVE = TRUE, NEVER_EXTRACTABLE = TRUE
*/
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
parent_template1, ARRAY_SIZE(parent_template1),
&aes_key1);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
/*
* Parent AES Key 2
* SENSITIVE = FALSE, EXTRACTABLE = TRUE
* ALWAYS_SENSITIVE = FALSE, NEVER_EXTRACTABLE = FALSE
*/
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
parent_template2, ARRAY_SIZE(parent_template2),
&aes_key2);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
Do_ADBG_BeginSubCase(c, "Derive Generic secret - AES-ECB Mechanism");
/*
* Use AES key 1 as Parent key
* 1. VALUE_LEN attribute not given in derivation template. Length
* of key should be same as that of data length.
* 2. Derivation template has SENSITIVE = TRUE, EXTRACTABLE = FALSE
* Parent key has ALWAYS_SENSITIVE = TRUE, NEVER_EXTRACTABLE = TRUE
* So derived key, ALWAYS_SENSITIVE will be same as SENSITIVE and
* NEVER_EXTRACTABLE will be opposite of EXTRACTABLE
* 3. LOCAL should be false
*/
data_len = 512;
key_len = 0;
rv = derive_sym_key(session, aes_key1, CKM_AES_ECB_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_GENERIC_SECRET, CK_TRUE, CK_FALSE);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetAttributeValue(session, derv_key_hdl, get_template,
ARRAY_SIZE(get_template) - 1);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, secret_len, ==, data_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==,
CKK_GENERIC_SECRET) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE))
goto out;
rv = C_DestroyObject(session, derv_key_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Derive AES key using AES-EBC");
/*
* Use AES key 2 as Parent key
* 1. VALUE_LEN < DATA_LEN, Derived key should have VALUE_LEN key size
* 2. Derivation template has SENSITIVE = TRUE, EXTRACTABLE = FALSE
* Parent key has ALWAYS_SENSITIVE = FALSE, NEVER_EXTRACTABLE = FALSE
* So derived key, ALWAYS_SENSITIVE will be FALSE and
* NEVER_EXTRACTABLE will be FALSE
* 3. LOCAL should be false
*/
data_len = 32;
key_len = 16;
rv = derive_sym_key(session, aes_key2, CKM_AES_ECB_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_AES, CK_TRUE, CK_FALSE);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* This being a SENSITIVE object, we can't get the VALUE */
rv = C_GetAttributeValue(session, derv_key_hdl, get_template,
ARRAY_SIZE(get_template) - 1);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, secret_len, ==, key_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE))
goto out;
rv = C_DestroyObject(session, derv_key_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Derive AES key using AES-CBC");
/*
* Use AES key 1 as Parent key
* 1. VALUE_LEN = DATA_LEN, Derived key should have VALUE_LEN key size
* 2. Derivation template has SENSITIVE = FALSE, EXTRACTABLE = FALSE
* Parent key has ALWAYS_SENSITIVE = TRUE, NEVER_EXTRACTABLE = TRUE
* So derived key, ALWAYS_SENSITIVE will be same as SENSITIVE and
* NEVER_EXTRACTABLE will be opposite of EXTRACTABLE
* 3. LOCAL should be false
*/
data_len = 32;
key_len = 32;
rv = derive_sym_key(session, aes_key1, CKM_AES_CBC_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_AES, CK_FALSE, CK_FALSE);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetAttributeValue(session, derv_key_hdl, get_template,
ARRAY_SIZE(get_template) - 1);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, secret_len, ==, key_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE))
goto out;
rv = C_DestroyObject(session, derv_key_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Derive Generic secret key using AES-CBC");
/*
* Use AES key 2 as Parent key
* 1. VALUE_LEN < DATA_LEN, Derived key should have VALUE_LEN key size
* 2. Derivation template has SENSITIVE = FALSE, EXTRACTABLE = TRUE
* Parent key has ALWAYS_SENSITIVE = TRUE, NEVER_EXTRACTABLE = TRUE
* So derived key, ALWAYS_SENSITIVE will be same as SENSITIVE and
* NEVER_EXTRACTABLE will be opposite of EXTRACTABLE
* 3. LOCAL should be false
*/
data_len = 512;
key_len = 256;
rv = derive_sym_key(session, aes_key2, CKM_AES_CBC_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_GENERIC_SECRET, CK_FALSE, CK_TRUE);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetAttributeValue(session, derv_key_hdl, get_template,
ARRAY_SIZE(get_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, get_template[idx].ulValueLen, ==,
key_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, secret_len, ==, key_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==,
CKK_GENERIC_SECRET) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE))
goto out;
rv = C_DestroyObject(session, derv_key_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Invalid parameters during derivation");
/* Length of data used for derivation < key length */
data_len = 16;
key_len = 32;
rv = derive_sym_key(session, aes_key1, CKM_AES_ECB_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_AES, CK_FALSE, CK_TRUE);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv))
goto out;
/* Data is not multiple of 16 */
data_len = 18;
key_len = 32;
rv = derive_sym_key(session, aes_key1, CKM_AES_ECB_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_AES, CK_FALSE, CK_TRUE);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv))
goto out;
/* Wrong Mechanism */
rv = derive_sym_key(session, aes_key1, CKM_AES_ECB,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_AES, CK_FALSE, CK_TRUE);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_MECHANISM_INVALID, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Failure if operation already active");
/* Generate an AES key which can perform Encryption */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
parent_template_w_enc_der,
ARRAY_SIZE(parent_template_w_enc_der),
&aes_key_enc);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, aes_key_enc);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Initializing the encryption operation again should not alter or
* terminate already started operation.
*/
rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, aes_key_enc);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_ACTIVE, rv))
goto out;
data_len = 32;
key_len = 32;
rv = derive_sym_key(session, aes_key2, CKM_AES_ECB_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_AES, CK_FALSE, CK_TRUE);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_ACTIVE, rv))
goto out;
rv = C_EncryptFinal(session, NULL, NULL);
/* Only check that the operation is no more active */
if (!ADBG_EXPECT_TRUE(c, rv != CKR_BUFFER_TOO_SMALL))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Failure if parent key CKA_ENCRYPT is TRUE");
data_len = 32;
key_len = 32;
rv = derive_sym_key(session, aes_key_enc, CKM_AES_ECB_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_AES, CK_FALSE, CK_TRUE);
/*
* Not strictly expecting FUNCTION_FAILED but expecting a failure
* as we have added a restriction that keys with attribute CKA_ENCRYPT
* set can't be used for derivation.
*/
if (!ADBG_EXPECT_CK_RESULT(c, CKR_FUNCTION_FAILED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Failure if parent key CKA_DERIVE is FALSE");
rv = C_DestroyObject(session, aes_key1);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
parent_template_wo_derive,
ARRAY_SIZE(parent_template_wo_derive),
&aes_key1);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
data_len = 32;
key_len = 32;
rv = derive_sym_key(session, aes_key1, CKM_AES_ECB_ENCRYPT_DATA,
data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY,
CKK_AES, CK_FALSE, CK_TRUE);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_TYPE_INCONSISTENT, rv))
goto out;
out:
Do_ADBG_EndSubCase(c, NULL);
close_session:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1017, xtest_pkcs11_test_1017,
"PKCS11: AES Key Derivation tests");
/* Digest test patterns */
static const char digest_test_pattern[] = "The quick brown fox jumps over the lazy dog";
static const char digest_test_pattern_empty[] = "";
/* MD5 checksums for digest test patterns */
static const uint8_t digest_test_pattern_md5[] = {
0x9e, 0x10, 0x7d, 0x9d, 0x37, 0x2b, 0xb6, 0x82, 0x6b, 0xd8, 0x1d, 0x35,
0x42, 0xa4, 0x19, 0xd6
};
static const uint8_t digest_test_pattern_empty_md5[] = {
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98,
0xec, 0xf8, 0x42, 0x7e
};
/* SHA-1 checksums for digest test patterns */
static const uint8_t digest_test_pattern_sha1[] = {
0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e, 0xe1,
0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12
};
static const uint8_t digest_test_pattern_empty_sha1[] = {
0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef,
0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09
};
/* SHA-224 checksums for digest test patterns */
static const uint8_t digest_test_pattern_sha224[] = {
0x73, 0x0e, 0x10, 0x9b, 0xd7, 0xa8, 0xa3, 0x2b, 0x1c, 0xb9, 0xd9, 0xa0,
0x9a, 0xa2, 0x32, 0x5d, 0x24, 0x30, 0x58, 0x7d, 0xdb, 0xc0, 0xc3, 0x8b,
0xad, 0x91, 0x15, 0x25
};
static const uint8_t digest_test_pattern_empty_sha224[] = {
0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb,
0x28, 0x82, 0x34, 0xc4, 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a,
0xc5, 0xb3, 0xe4, 0x2f
};
/* SHA-256 checksums for digest test patterns */
static const uint8_t digest_test_pattern_sha256[] = {
0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, 0x69, 0xca, 0x9a, 0xbc,
0xb0, 0x08, 0x2e, 0x4f, 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76,
0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92
};
static const uint8_t digest_test_pattern_empty_sha256[] = {
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8,
0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
};
/* SHA-384 checksums for digest test patterns */
static const uint8_t digest_test_pattern_sha384[] = {
0xca, 0x73, 0x7f, 0x10, 0x14, 0xa4, 0x8f, 0x4c, 0x0b, 0x6d, 0xd4, 0x3c,
0xb1, 0x77, 0xb0, 0xaf, 0xd9, 0xe5, 0x16, 0x93, 0x67, 0x54, 0x4c, 0x49,
0x40, 0x11, 0xe3, 0x31, 0x7d, 0xbf, 0x9a, 0x50, 0x9c, 0xb1, 0xe5, 0xdc,
0x1e, 0x85, 0xa9, 0x41, 0xbb, 0xee, 0x3d, 0x7f, 0x2a, 0xfb, 0xc9, 0xb1
};
static const uint8_t digest_test_pattern_empty_sha384[] = {
0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e,
0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf,
0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b
};
/* SHA-512 checksums for digest test patterns */
static const uint8_t digest_test_pattern_sha512[] = {
0x07, 0xe5, 0x47, 0xd9, 0x58, 0x6f, 0x6a, 0x73, 0xf7, 0x3f, 0xba, 0xc0,
0x43, 0x5e, 0xd7, 0x69, 0x51, 0x21, 0x8f, 0xb7, 0xd0, 0xc8, 0xd7, 0x88,
0xa3, 0x09, 0xd7, 0x85, 0x43, 0x6b, 0xbb, 0x64, 0x2e, 0x93, 0xa2, 0x52,
0xa9, 0x54, 0xf2, 0x39, 0x12, 0x54, 0x7d, 0x1e, 0x8a, 0x3b, 0x5e, 0xd6,
0xe1, 0xbf, 0xd7, 0x09, 0x78, 0x21, 0x23, 0x3f, 0xa0, 0x53, 0x8f, 0x3d,
0xb8, 0x54, 0xfe, 0xe6
};
static const uint8_t digest_test_pattern_empty_sha512[] = {
0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50,
0xd6, 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c,
0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a,
0xf9, 0x27, 0xda, 0x3e
};
#define DIGEST_TEST(_test_name, _mecha, _data, _digest) \
{ \
.test_name = _test_name, \
.mecha = _mecha, \
.data = _data, \
.data_size = sizeof(_data) - 1, \
.digest = _digest, \
.digest_size = sizeof(_digest) \
}
/* Digest simple test suite */
static struct {
const char *test_name;
CK_MECHANISM_TYPE mecha;
const void *data;
CK_ULONG data_size;
const uint8_t *digest;
CK_ULONG digest_size;
} digest_test_patterns[] = {
DIGEST_TEST("CKM_MD5/empty", CKM_MD5, digest_test_pattern_empty,
digest_test_pattern_empty_md5),
DIGEST_TEST("CKM_MD5/test pattern", CKM_MD5, digest_test_pattern,
digest_test_pattern_md5),
DIGEST_TEST("CKM_SHA_1/empty", CKM_SHA_1, digest_test_pattern_empty,
digest_test_pattern_empty_sha1),
DIGEST_TEST("CKM_SHA_1/test pattern", CKM_SHA_1, digest_test_pattern,
digest_test_pattern_sha1),
DIGEST_TEST("CKM_SHA224/empty", CKM_SHA224, digest_test_pattern_empty,
digest_test_pattern_empty_sha224),
DIGEST_TEST("CKM_SHA224/test pattern", CKM_SHA224, digest_test_pattern,
digest_test_pattern_sha224),
DIGEST_TEST("CKM_SHA256/empty", CKM_SHA256, digest_test_pattern_empty,
digest_test_pattern_empty_sha256),
DIGEST_TEST("CKM_SHA256/test pattern", CKM_SHA256, digest_test_pattern,
digest_test_pattern_sha256),
DIGEST_TEST("CKM_SHA384/empty", CKM_SHA384, digest_test_pattern_empty,
digest_test_pattern_empty_sha384),
DIGEST_TEST("CKM_SHA384/test pattern", CKM_SHA384, digest_test_pattern,
digest_test_pattern_sha384),
DIGEST_TEST("CKM_SHA512/empty", CKM_SHA512, digest_test_pattern_empty,
digest_test_pattern_empty_sha512),
DIGEST_TEST("CKM_SHA512/test pattern", CKM_SHA512, digest_test_pattern,
digest_test_pattern_sha512),
};
static CK_ATTRIBUTE digest_generate_aes_object[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_AES }, sizeof(CK_KEY_TYPE) },
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
};
static CK_ATTRIBUTE digest_generate_gensecret_object[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET },
sizeof(CK_KEY_TYPE) },
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){ 32 }, sizeof(CK_ULONG) },
};
static CK_ATTRIBUTE digest_data_object[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_DATA },
sizeof(CK_OBJECT_CLASS) },
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
};
static void xtest_pkcs11_test_1018(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
bool logged_in = false;
uint8_t data[128] = { 0 };
CK_ULONG data_size = 0;
uint8_t digest[64] = { 0 };
CK_ULONG digest_size = 0;
const uint8_t *expect_digest = NULL;
CK_ULONG expect_digest_size = 0;
CK_MECHANISM mechanism = { CKM_MD5, NULL, 0 };
uint8_t secret_data[128] = { 0 };
CK_ULONG secret_data_size __maybe_unused = 0;
CK_ATTRIBUTE digest_get_secret_value[] = {
{ CKA_VALUE, &secret_data, sizeof(secret_data) },
};
CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE;
#ifdef OPENSSL_FOUND
EVP_MD_CTX *mdctx = NULL;
unsigned char hash[EVP_MAX_MD_SIZE] = { 0 };
unsigned int md_len = 0;
int ret = 0;
#endif
size_t i = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Test out simple successful cases with init+update+final*/
for (i = 0; i < ARRAY_SIZE(digest_test_patterns); i++) {
Do_ADBG_BeginSubCase(c, "Simple digest tests - update - %s",
digest_test_patterns[i].test_name);
mechanism.mechanism = digest_test_patterns[i].mecha;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[i].data,
digest_test_patterns[i].data_size);
data_size = digest_test_patterns[i].data_size;
expect_digest = digest_test_patterns[i].digest;
expect_digest_size = digest_test_patterns[i].digest_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestUpdate(session, data, data_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestFinal(session, digest, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_BUFFER(c, expect_digest, expect_digest_size,
digest, digest_size))
goto out;
/* Verify that end of buffer is still 0xCC */
for (i = expect_digest_size; i < sizeof(digest); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest[i], ==,
0xCC))
goto out;
Do_ADBG_EndSubCase(c, NULL);
}
/* Test out simple successful cases */
for (i = 0; i < ARRAY_SIZE(digest_test_patterns); i++) {
Do_ADBG_BeginSubCase(c, "Simple digest tests - oneshot - %s",
digest_test_patterns[i].test_name);
mechanism.mechanism = digest_test_patterns[i].mecha;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[i].data,
digest_test_patterns[i].data_size);
data_size = digest_test_patterns[i].data_size;
expect_digest = digest_test_patterns[i].digest;
expect_digest_size = digest_test_patterns[i].digest_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Digest(session, data, data_size, digest, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_BUFFER(c, expect_digest, expect_digest_size,
digest, digest_size))
goto out;
/* Verify that end of buffer is still 0xCC */
for (i = expect_digest_size; i < sizeof(digest); i++)
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest[i], ==,
0xCC))
goto out;
Do_ADBG_EndSubCase(c, NULL);
}
/* Test out key updates */
Do_ADBG_BeginSubCase(c, "Simple digest tests - AES key update - SHA-256");
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
logged_in = true;
/* Generate AES key */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
digest_generate_aes_object,
ARRAY_SIZE(digest_generate_aes_object),
&key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
memset(secret_data, 0xCC, sizeof(data));
digest_get_secret_value[0].ulValueLen = sizeof(secret_data);
/* Get value of generated secret for verification purposes */
rv = C_GetAttributeValue(session, key_handle, digest_get_secret_value,
ARRAY_SIZE(digest_get_secret_value));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
secret_data_size = digest_get_secret_value[0].ulValueLen;
/* Calculate digest with PKCS11 */
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestUpdate(session, data, data_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestKey(session, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestFinal(session, digest, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Verify digest with openssl */
#ifdef OPENSSL_FOUND
mdctx = EVP_MD_CTX_create();
if (!ADBG_EXPECT_NOT_NULL(c, mdctx))
goto out;
ret = EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1))
goto out;
ret = EVP_DigestUpdate(mdctx, data, data_size);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1))
goto out;
ret = EVP_DigestUpdate(mdctx, secret_data, secret_data_size);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1))
goto out;
ret = EVP_DigestFinal_ex(mdctx, hash, &md_len);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1))
goto out;
EVP_MD_CTX_destroy(mdctx);
mdctx = NULL;
if (!ADBG_EXPECT_BUFFER(c, hash, md_len, digest, digest_size))
goto out;
#else
Do_ADBG_Log("OpenSSL not available, skipping C_DigestKey verification");
#endif
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
key_handle = CK_INVALID_HANDLE;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Simple digest tests - generic secret key update - SHA-256");
/* Generate generic secret key */
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
digest_generate_gensecret_object,
ARRAY_SIZE(digest_generate_gensecret_object),
&key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
memset(secret_data, 0xCC, sizeof(data));
digest_get_secret_value[0].ulValueLen = sizeof(secret_data);
/* Get value of generated secret for verification purposes */
rv = C_GetAttributeValue(session, key_handle, digest_get_secret_value,
ARRAY_SIZE(digest_get_secret_value));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
secret_data_size = digest_get_secret_value[0].ulValueLen;
/* Calculate digest with PKCS11 */
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestUpdate(session, data, data_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestKey(session, key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestFinal(session, digest, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Verify digest with openssl */
#ifdef OPENSSL_FOUND
mdctx = EVP_MD_CTX_create();
if (!ADBG_EXPECT_NOT_NULL(c, mdctx))
goto out;
ret = EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1))
goto out;
ret = EVP_DigestUpdate(mdctx, data, data_size);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1))
goto out;
ret = EVP_DigestUpdate(mdctx, secret_data, secret_data_size);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1))
goto out;
ret = EVP_DigestFinal_ex(mdctx, hash, &md_len);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1))
goto out;
EVP_MD_CTX_destroy(mdctx);
mdctx = NULL;
if (!ADBG_EXPECT_BUFFER(c, hash, md_len, digest, digest_size))
goto out;
#else
Do_ADBG_Log("OpenSSL not available, skipping C_DigestKey verification");
#endif
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
key_handle = CK_INVALID_HANDLE;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Query digest size - C_DigestFinal");
mechanism.mechanism = digest_test_patterns[0].mecha;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = 0;
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
expect_digest = digest_test_patterns[0].digest;
expect_digest_size = digest_test_patterns[0].digest_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestUpdate(session, data, data_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestFinal(session, NULL, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest_size, ==,
expect_digest_size))
goto out;
rv = C_DigestFinal(session, digest, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_BUFFER(c, expect_digest, expect_digest_size,
digest, digest_size))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Query digest size - C_Digest");
mechanism.mechanism = digest_test_patterns[0].mecha;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = 0;
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
expect_digest = digest_test_patterns[0].digest;
expect_digest_size = digest_test_patterns[0].digest_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Digest(session, data, data_size, NULL, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest_size, ==,
expect_digest_size))
goto out;
rv = C_Digest(session, data, data_size, digest, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
if (!ADBG_EXPECT_BUFFER(c, expect_digest, expect_digest_size,
digest, digest_size))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Query digest size - buffer too small");
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = 0;
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestUpdate(session, data, data_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestFinal(session, digest, &digest_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv))
goto out;
if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest_size, ==, 32))
goto out;
rv = C_DigestFinal(session, digest, &digest_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
/* Test bad arguments & operation terminations */
Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestUpdate");
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestUpdate(session, NULL, 10);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
goto out;
rv = C_DigestUpdate(session, data, data_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestFinal with NULL digest");
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestUpdate(session, data, data_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestFinal(session, NULL, NULL);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
goto out;
rv = C_DigestFinal(session, digest, &digest_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestFinal with digest but NULL size");
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestUpdate(session, data, data_size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestFinal(session, digest, NULL);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
goto out;
rv = C_DigestFinal(session, digest, &digest_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test bad arguments - C_Digest with NULL data but non-zero size");
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Digest(session, NULL, 10, digest, &digest_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
goto out;
rv = C_Digest(session, data, data_size, digest, &digest_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test bad arguments - C_Digest with NULL digest");
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Digest(session, data, data_size, NULL, NULL);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
goto out;
rv = C_Digest(session, data, data_size, digest, &digest_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestFinal with digest but NULL size");
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_Digest(session, data, data_size, digest, NULL);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
goto out;
rv = C_Digest(session, data, data_size, digest, &digest_size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestKey with invalid key handle");
rv = C_CreateObject(session, digest_data_object,
ARRAY_SIZE(digest_data_object), &key_handle);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestKey(session, 9999);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_HANDLE_INVALID, rv))
goto out;
rv = C_DigestKey(session, key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestKey with non-secret key type");
mechanism.mechanism = CKM_SHA256;
memset(data, 0xCC, sizeof(data));
memset(digest, 0xCC, sizeof(digest));
digest_size = sizeof(digest);
memcpy(data, digest_test_patterns[0].data,
digest_test_patterns[0].data_size);
data_size = digest_test_patterns[0].data_size;
rv = C_DigestInit(session, &mechanism);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DigestKey(session, key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_INDIGESTIBLE, rv))
goto out;
rv = C_DigestKey(session, key_handle);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv))
goto out;
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
key_handle = CK_INVALID_HANDLE;
out:
#ifdef OPENSSL_FOUND
if (!ADBG_EXPECT_POINTER(c, NULL, mdctx)) {
Do_ADBG_Log("Unexpected failure in openssl functions: %d",
ret);
EVP_MD_CTX_destroy(mdctx);
}
#endif
Do_ADBG_EndSubCase(c, NULL);
if (logged_in)
ADBG_EXPECT_CK_OK(c, C_Logout(session));
if (key_handle != CK_INVALID_HANDLE) {
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
key_handle = CK_INVALID_HANDLE;
}
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1018, xtest_pkcs11_test_1018,
"PKCS11: Digest tests");
/**
* 0:d=0 hl=2 l= 22 cons: SEQUENCE
* 2:d=1 hl=2 l= 20 cons: SET
* 4:d=2 hl=2 l= 18 cons: SEQUENCE
* 6:d=3 hl=2 l= 3 prim: OBJECT :commonName
* 11:d=3 hl=2 l= 11 prim: UTF8STRING :common name
*/
static uint8_t subject_common_name[] = {
0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65
};
/**
* 0:d=0 hl=2 l= 8 prim: OBJECT :prime256v1
*/
static uint8_t ecdsa_nist_p256[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
0x01, 0x07
};
/**
* 0:d=0 hl=2 l= 5 prim: OBJECT :secp384r1
*/
static uint8_t ecdsa_nist_p384[] = {
0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
};
/**
* 0:d=0 hl=2 l= 5 prim: OBJECT :secp521r1
*/
static uint8_t ecdsa_nist_p521[] = {
0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23
};
#define EC_SIGN_TEST(_test_name, _mecha, _data) \
{ \
.test_name = _test_name, \
.mecha = _mecha, \
.data = _data, \
.data_size = sizeof(_data) - 1, \
}
/* List of elliptic curve signing multi stage digest mechas */
static struct {
const char *test_name;
CK_MECHANISM_TYPE mecha;
const void *data;
CK_ULONG data_size;
} ec_sign_tests[] = {
EC_SIGN_TEST("CKM_ECDSA_SHA1", CKM_ECDSA_SHA1, digest_test_pattern),
EC_SIGN_TEST("CKM_ECDSA_SHA224", CKM_ECDSA_SHA224, digest_test_pattern),
EC_SIGN_TEST("CKM_ECDSA_SHA256", CKM_ECDSA_SHA256, digest_test_pattern),
EC_SIGN_TEST("CKM_ECDSA_SHA384", CKM_ECDSA_SHA384, digest_test_pattern),
EC_SIGN_TEST("CKM_ECDSA_SHA512", CKM_ECDSA_SHA512, digest_test_pattern),
};
static int test_ec_operations(ADBG_Case_t *c, CK_SESSION_HANDLE session,
const char *curve_name, uint8_t *curve,
size_t curve_size)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE;
CK_MECHANISM mechanism = {
CKM_EC_KEY_PAIR_GEN, NULL, 0
};
CK_MECHANISM sign_mechanism = {
CKM_ECDSA, NULL, 0
};
CK_BYTE id[] = { 123 };
CK_ATTRIBUTE public_key_template[] = {
{ CKA_ENCRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_EC_PARAMS, ecdsa_nist_p256, sizeof(ecdsa_nist_p256) }
};
CK_ATTRIBUTE private_key_template[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SUBJECT, subject_common_name,
sizeof(subject_common_name) },
{ CKA_ID, id, sizeof(id) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }
};
CK_OBJECT_CLASS g_class = 0;
CK_KEY_TYPE g_key_type = 0;
CK_BYTE g_id[32] = { 0 };
CK_DATE g_start_date = { 0 };
CK_DATE g_end_date = { 0 };
CK_BBOOL g_derive = CK_FALSE;
CK_BBOOL g_local = CK_FALSE;
CK_MECHANISM_TYPE g_keygen_mecha = 0;
CK_BYTE g_subject[64] = { 0 };
CK_BBOOL g_encrypt = CK_FALSE;
CK_BBOOL g_verify = CK_FALSE;
CK_BBOOL g_verify_recover = CK_FALSE;
CK_BBOOL g_wrap = CK_FALSE;
CK_BBOOL g_trusted = CK_FALSE;
CK_BYTE g_public_key_info[1024] = { 0 };
CK_BBOOL g_sensitive = CK_FALSE;
CK_BBOOL g_decrypt = CK_FALSE;
CK_BBOOL g_sign = CK_FALSE;
CK_BBOOL g_sign_recover = CK_FALSE;
CK_BBOOL g_unwrap = CK_FALSE;
CK_BBOOL g_extract = CK_FALSE;
CK_BBOOL g_asensitive = CK_FALSE;
CK_BBOOL g_nextract = CK_FALSE;
CK_BBOOL g_wrap_with_trusted = CK_FALSE;
CK_BBOOL g_always_authenticate = CK_FALSE;
CK_ATTRIBUTE get_public_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_ID, g_id, sizeof(g_id) },
{ CKA_START_DATE, &g_start_date, sizeof(CK_DATE) },
{ CKA_END_DATE, &g_end_date, sizeof(CK_DATE) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(CK_MECHANISM_TYPE) },
{ CKA_SUBJECT, g_subject, sizeof(g_subject) },
{ CKA_ENCRYPT, &g_encrypt, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &g_verify, sizeof(CK_BBOOL) },
{ CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(CK_BBOOL) },
{ CKA_WRAP, &g_wrap, sizeof(CK_BBOOL) },
{ CKA_TRUSTED, &g_trusted, sizeof(CK_BBOOL) },
{ CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) },
};
CK_ATTRIBUTE get_private_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_ID, g_id, sizeof(g_id) },
{ CKA_START_DATE, &g_start_date, sizeof(CK_DATE) },
{ CKA_END_DATE, &g_end_date, sizeof(CK_DATE) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(CK_MECHANISM_TYPE) },
{ CKA_SUBJECT, g_subject, sizeof(g_subject) },
{ CKA_SENSITIVE, &g_sensitive, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &g_decrypt, sizeof(CK_BBOOL) },
{ CKA_SIGN, &g_sign, sizeof(CK_BBOOL) },
{ CKA_SIGN_RECOVER, &g_sign_recover, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &g_unwrap, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &g_extract, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(CK_BBOOL) },
{ CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(CK_BBOOL) },
{ CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(CK_BBOOL) },
{ CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) },
};
uint8_t signature[512] = { 0 };
CK_ULONG signature_len = 0;
size_t i = 0;
Do_ADBG_BeginSubCase(c, "%s: Generate key pair",
curve_name);
public_key_template[3].pValue = curve;
public_key_template[3].ulValueLen = curve_size;
rv = C_GenerateKeyPair(session, &mechanism, public_key_template,
ARRAY_SIZE(public_key_template),
private_key_template,
ARRAY_SIZE(private_key_template),
&public_key, &private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
/* reset get public key template */
memset(g_id, 0, sizeof(g_id));
memset(g_subject, 0, sizeof(g_subject));
memset(g_public_key_info, 0, sizeof(g_public_key_info));
get_public_template[2].ulValueLen = sizeof(g_id);
get_public_template[8].ulValueLen = sizeof(g_subject);
get_public_template[14].ulValueLen = sizeof(g_public_key_info);
rv = C_GetAttributeValue(session, public_key, get_public_template,
ARRAY_SIZE(get_public_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_EC) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==,
CKM_EC_KEY_PAIR_GEN) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE))
goto err_destr_obj;
/* reset get private key template */
memset(g_id, 0, sizeof(g_id));
memset(g_subject, 0, sizeof(g_subject));
memset(g_public_key_info, 0, sizeof(g_public_key_info));
get_private_template[2].ulValueLen = sizeof(g_id);
get_private_template[8].ulValueLen = sizeof(g_subject);
get_private_template[19].ulValueLen = sizeof(g_public_key_info);
rv = C_GetAttributeValue(session, private_key, get_private_template,
ARRAY_SIZE(get_private_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_EC) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==,
CKM_EC_KEY_PAIR_GEN) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE))
goto err_destr_obj;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c,
"%s: Sign & verify tests - oneshot - CKM_ECDSA",
curve_name);
sign_mechanism.mechanism = CKM_ECDSA;
memset(signature, 0, sizeof(signature));
signature_len = sizeof(signature);
rv = C_SignInit(session, &sign_mechanism, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Sign(session, (void *)digest_test_pattern_sha256,
sizeof(digest_test_pattern_sha256), (void *)signature,
&signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyInit(session, &sign_mechanism, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session, (void *)digest_test_pattern_sha256,
sizeof(digest_test_pattern_sha256), (void *)signature,
signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
Do_ADBG_EndSubCase(c, NULL);
for (i = 0; i < ARRAY_SIZE(ec_sign_tests); i++) {
Do_ADBG_BeginSubCase(c, "%s: Sign & verify - oneshot - %s",
curve_name, ec_sign_tests[i].test_name);
sign_mechanism.mechanism = ec_sign_tests[i].mecha;
memset(signature, 0, sizeof(signature));
signature_len = sizeof(signature);
rv = C_SignInit(session, &sign_mechanism, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Sign(session, (void *)ec_sign_tests[i].data,
ec_sign_tests[i].data_size,
(void *)signature, &signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyInit(session, &sign_mechanism, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session, (void *)ec_sign_tests[i].data,
ec_sign_tests[i].data_size,
(void *)signature, signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
Do_ADBG_EndSubCase(c, NULL);
}
Do_ADBG_BeginSubCase(c, "%s: Destroy keys", curve_name);
rv = C_DestroyObject(session, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_DestroyObject(session, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
return 1;
err_destr_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key));
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key));
err:
Do_ADBG_EndSubCase(c, NULL);
return 0;
}
static void xtest_pkcs11_test_1019(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
int ret = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ret = test_ec_operations(c, session, "P-256", ecdsa_nist_p256,
sizeof(ecdsa_nist_p256));
if (!ret)
goto out;
ret = test_ec_operations(c, session, "P-384", ecdsa_nist_p384,
sizeof(ecdsa_nist_p384));
if (!ret)
goto out;
if (level > 0) {
ret = test_ec_operations(c, session, "P-521", ecdsa_nist_p521,
sizeof(ecdsa_nist_p521));
if (!ret)
goto out;
}
out:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1019, xtest_pkcs11_test_1019,
"PKCS11: Elliptic Curve key generation and signing");
#define WRAPPED_TEST_KEY_SIZE 48
static void xtest_pkcs11_test_1020(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
CK_OBJECT_HANDLE wrapping_key1 = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE wrapping_key2 = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE wrapping_key_inv = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE key_sz24 = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE key_sens = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE key_inv = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE;
CK_ATTRIBUTE set_w_unw_template[] = {
{ CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE set_wwt_template[] = {
{ CKA_WRAP_WITH_TRUSTED, &(CK_BBOOL){ CK_TRUE },
sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE set_trusted_template[] = {
{ CKA_TRUSTED, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE wrap_template[] = {
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE unwrap_template[] = {
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE wrapping_key_template[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
{ CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE wrapping_key_temp_w_indirect[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
{ CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_WRAP_TEMPLATE, &wrap_template, sizeof(wrap_template) },
{ CKA_UNWRAP_TEMPLATE, &unwrap_template,
sizeof(unwrap_template) },
};
CK_ATTRIBUTE unwrap_template2[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_AES }, sizeof(CK_KEY_TYPE) },
{ CKA_TOKEN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
};
CK_ATTRIBUTE wrapping_key_temp_w_indirect2[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
{ CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP_TEMPLATE, &unwrap_template2,
sizeof(unwrap_template2) },
};
CK_ATTRIBUTE wrapping_key_template_inv1[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
{ CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE key_template[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
{ CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE key_template_sens[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE key_template_inv1[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE key_sz24_template[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 24 }, sizeof(CK_ULONG) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE new_key_template[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET },
sizeof(CK_KEY_TYPE) },
{ CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE}, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE new_key_template_sens[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_AES }, sizeof(CK_KEY_TYPE) },
{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE new_key_template2[] = {
{ CKA_DERIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE new_key_template3[] = {
{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_ATTRIBUTE new_key_template4[] = {
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET },
sizeof(CK_KEY_TYPE) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
};
CK_BBOOL g_extract = CK_FALSE;
CK_BBOOL g_sensitive = CK_TRUE;
CK_BBOOL g_nextract = CK_TRUE;
CK_BBOOL g_asensitive = CK_TRUE;
CK_BBOOL g_local = CK_TRUE;
CK_BBOOL g_token = CK_FALSE;
CK_BBOOL g_derive = CK_FALSE;
CK_OBJECT_CLASS g_class = CKO_VENDOR_DEFINED;
CK_KEY_TYPE g_key_type = CKK_VENDOR_DEFINED;
uint8_t g_val[WRAPPED_TEST_KEY_SIZE] = { 0 };
CK_ULONG key_len = 0;
uint8_t g_unwrapped_val[WRAPPED_TEST_KEY_SIZE] = { 0 };
CK_ULONG unwrapped_key_len = 0;
/* Keep last attribute as CKA_VALUE */
CK_ATTRIBUTE get_template_unwrapped[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_EXTRACTABLE, &g_extract, sizeof(CK_BBOOL) },
{ CKA_SENSITIVE, &g_sensitive, sizeof(CK_BBOOL) },
{ CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_TOKEN, &g_token, sizeof(CK_BBOOL) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_VALUE_LEN, &unwrapped_key_len,
sizeof(unwrapped_key_len) },
{ CKA_VALUE, g_unwrapped_val, sizeof(g_unwrapped_val) },
};
CK_ATTRIBUTE get_template[] = {
{ CKA_VALUE_LEN, &key_len, sizeof(key_len) },
{ CKA_VALUE, g_val, sizeof(g_val) },
};
uint8_t buf[WRAPPED_TEST_KEY_SIZE] = { 0 };
CK_ULONG size = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Wrapping Key - AES Key */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
wrapping_key_template,
ARRAY_SIZE(wrapping_key_template), &wrapping_key1);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
/* Key to be wrapped - AES key */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
key_template, ARRAY_SIZE(key_template),
&key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
Do_ADBG_BeginSubCase(c, "Test key wrap with AES ECB");
/*
* Test NULL buffer and NULL out_size to verify bad argument processing
*/
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
NULL, NULL);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
goto out;
/*
* Test NULL buffer case with size as 0 to get the out_size
*/
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
NULL, &size);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf)))
goto out;
/*
* Test NULL buffer case with size non zero size to get the out_size
*/
size = 1;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
NULL, &size);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf)))
goto out;
/* Test short buffer */
size = 12;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf)))
goto out;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
buf, &size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Get the size of the original key which was wrapped in key_len.
* This will be compared to the length of the key after unwrapping.
*/
rv = C_GetAttributeValue(session, key, get_template,
ARRAY_SIZE(get_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test key unwrap with AES ECB");
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf,
size, new_key_template, ARRAY_SIZE(new_key_template),
&unwrapped_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* The key created after unwrapping should have CKA_LOCAL = FALSE,
* CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE as FALSE.
* Default value of CKA_EXTRACTABLE if not specified in the template
* is TRUE. We have deliberately set CKA_SENSITIVE to false for
* both original key and unwrapped_key. This is done to be able to
* extract the value of keys and compare them. This is done mainly
* for testing. In actual examples, we expect CKA_SENSITIVE of keys
* to be wrapped to be TRUE.
*/
rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped,
ARRAY_SIZE(get_template_unwrapped));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_BUFFER(c, g_unwrapped_val, unwrapped_key_len, g_val,
key_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==,
CKK_GENERIC_SECRET) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE))
goto out;
rv = C_DestroyObject(session, unwrapped_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Invalid UnWrap cases");
/* Failure when unwrapping as a private session key */
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf,
size, new_key_template4, ARRAY_SIZE(new_key_template4),
&unwrapped_key);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto out;
/* Provide incomplete template */
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf,
size, new_key_template2, ARRAY_SIZE(new_key_template2),
&unwrapped_key);
/*
* The error code can also be CKR_TEMPLATE_INCOMPLETE. The
* current implementation returns CKR_TEMPLATE_INCONSISTENT
*/
if (!ADBG_EXPECT_TRUE(c, rv == CKR_TEMPLATE_INCOMPLETE ||
rv == CKR_TEMPLATE_INCONSISTENT))
goto out;
/* Try unwrapping with a key without CKA_UNWRAP */
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, key, buf, size,
new_key_template, ARRAY_SIZE(new_key_template),
&unwrapped_key);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Invalid Wrap cases");
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
wrapping_key_template_inv1,
ARRAY_SIZE(wrapping_key_template_inv1),
&wrapping_key_inv);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Wrapping key used without CKA_WRAP set */
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key_inv,
key, buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, rv))
goto out;
rv = C_DestroyObject(session, wrapping_key_inv);
ADBG_EXPECT_CK_OK(c, rv);
/* Use invalid wrapping key handle */
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key_inv,
key, buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_HANDLE_INVALID, rv))
goto out;
/* CKA_EXTRACTABLE attribute of the key to be wrapped is CKA_FALSE */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
key_template_inv1, ARRAY_SIZE(key_template_inv1),
&key_inv);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
key_inv, buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_UNEXTRACTABLE, rv))
goto out;
rv = C_DestroyObject(session, key_inv);
ADBG_EXPECT_CK_OK(c, rv);
/* Use invalid key handle */
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
key_inv, buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_HANDLE_INVALID, rv))
goto out;
/* Try wrapping the wrapping key */
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
wrapping_key1, buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_HANDLE_INVALID, rv))
goto out;
/* Use invalid mechanism */
rv = C_WrapKey(session, &cktest_hmac_md5_mechanism, wrapping_key1, key,
buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_MECHANISM_INVALID, rv))
goto out;
/* Try wrapping when an operation is already active */
rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_ACTIVE, rv))
goto out;
rv = C_EncryptFinal(session, NULL, NULL);
/* Only check that the operation is no more active */
if (!ADBG_EXPECT_TRUE(c, rv != CKR_BUFFER_TOO_SMALL))
goto out;
/*
* Try wrapping using CKK_GENERIC_SECRET when mechanism used is
* AES_ECB. Generate a secret key object in rw session.
*/
rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
cktest_generate_gensecret_object_valid1,
ARRAY_SIZE(cktest_generate_gensecret_object_valid1),
&key_inv);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Make the Generic secret key wrapping/unwrapping key */
rv = C_SetAttributeValue(session, key_inv, set_w_unw_template,
ARRAY_SIZE(set_w_unw_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, key_inv, key, buf,
&size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, rv))
goto out;
rv = C_DestroyObject(session, key_inv);
ADBG_EXPECT_CK_OK(c, rv);
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Wrap with different length key");
/* Generate Key of size 192 bits */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
key_sz24_template, ARRAY_SIZE(key_sz24_template),
&key_sz24);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
size = 0;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
key_sz24, buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32))
goto out;
size = 24;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
key_sz24, buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32))
goto out;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
key_sz24, buf, &size);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test Wrap/Unwrap with indirect template");
/* Wrapping Key with indirect templates - AES Key */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
wrapping_key_temp_w_indirect,
ARRAY_SIZE(wrapping_key_temp_w_indirect),
&wrapping_key2);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Attribute mismatch with CKA_WRAP_TEMPLATE.
* Error expected when wrapping a key whose template doesn't match with
* the CKA_WRAP_TEMPLATE in the wrapping_key. In this example, the
* CKA_WRAP_TEMPLATE expects CKA_SENSITIVE of the key to be wrapped to
* be TRUE which is not the case here.
*/
size = sizeof(buf);
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, key,
buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_HANDLE_INVALID, rv))
goto out;
/* Generate SENSITIVE Key */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
key_template_sens, ARRAY_SIZE(key_template_sens),
&key_sens);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2,
key_sens, buf, &size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Unwrap to create key with SENSITIVE set as FALSE.
* This should fail as indirect attribute CKA_UNWRAP_TEMPLATE restricts
* creation of key with CKA_SENSITIVE as FALSE.
*/
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
size, new_key_template, ARRAY_SIZE(new_key_template),
&unwrapped_key);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv))
goto out;
/* Unwrap a wrapped sensitive key to create a SENSITIVE key */
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
size, new_key_template_sens,
ARRAY_SIZE(new_key_template_sens), &unwrapped_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Get the attributes of created. Skip last attribute in
* get_template_wrapped as that is CKA_VALUE which would give an
* error for a sensitive key
*/
rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped,
ARRAY_SIZE(get_template_unwrapped) - 1);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE))
goto out;
if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)) ||
!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, wrapping_key2)) ||
!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_sens)))
goto out;
/* Create wrapping key with indirect template specifying class & key */
rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
wrapping_key_temp_w_indirect2,
ARRAY_SIZE(wrapping_key_temp_w_indirect2),
&wrapping_key2);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
size = sizeof(buf);
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, key,
buf, &size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/* Use minimal new key template just specifying attribute of key */
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
size, new_key_template2, ARRAY_SIZE(new_key_template2),
&unwrapped_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped,
ARRAY_SIZE(get_template_unwrapped) - 1);
/* Destroy created token object */
if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)))
goto out;
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE))
goto out;
/*
* Unwrap with NULL template when CKA_UNWRAP_TEMPLATE has all
* attributes to generate a key
*/
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
size, NULL, 0, &unwrapped_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped,
ARRAY_SIZE(get_template_unwrapped) - 1);
/* Destroy created token object */
if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)))
goto out;
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE)) {
goto out;
}
/* Unwrap and try create a Private token object */
rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
size, new_key_template3, ARRAY_SIZE(new_key_template3),
&unwrapped_key);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Test usage of CKA_WRAP_WITH_TRUSTED");
/* Set Attribute WRAP_WITH_TRUSTED on the key */
rv = C_SetAttributeValue(session, key, set_wwt_template,
ARRAY_SIZE(set_wwt_template));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
/*
* Try wrapping the key with attribute CKA_WRAP_WITH_TRUSTED with
* normal wrapping key
*/
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
buf, &size);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_NOT_WRAPPABLE, rv))
goto out;
/* Login as SO in RW session */
rv = C_Login(session, CKU_SO, test_token_so_pin,
sizeof(test_token_so_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_SetAttributeValue(session, wrapping_key1, set_trusted_template,
ARRAY_SIZE(set_trusted_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_CK_OK(c, C_Logout(session)))
goto out;
rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
buf, &size);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
out:
Do_ADBG_EndSubCase(c, NULL);
close_session:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1020, xtest_pkcs11_test_1020,
"PKCS11: AES Key Wrap/UnWrap tests");
#define RSA_SIGN_TEST(_test_name, _mecha, _data) \
{ \
.test_name = _test_name, \
.mecha = _mecha, \
.data = _data, \
.data_size = sizeof(_data) - 1, \
}
/* List of RSA PKCS signing multi stage digest mechanisms */
static struct {
const char *test_name;
CK_MECHANISM_TYPE mecha;
const void *data;
CK_ULONG data_size;
} rsa_pkcs_sign_tests[] = {
RSA_SIGN_TEST("CKM_MD5_RSA_PKCS", CKM_MD5_RSA_PKCS,
digest_test_pattern),
RSA_SIGN_TEST("CKM_SHA1_RSA_PKCS", CKM_SHA1_RSA_PKCS,
digest_test_pattern),
RSA_SIGN_TEST("CKM_SHA224_RSA_PKCS", CKM_SHA224_RSA_PKCS,
digest_test_pattern),
RSA_SIGN_TEST("CKM_SHA256_RSA_PKCS", CKM_SHA256_RSA_PKCS,
digest_test_pattern),
RSA_SIGN_TEST("CKM_SHA384_RSA_PKCS", CKM_SHA384_RSA_PKCS,
digest_test_pattern),
RSA_SIGN_TEST("CKM_SHA512_RSA_PKCS", CKM_SHA512_RSA_PKCS,
digest_test_pattern),
};
static int test_rsa_pkcs_operations(ADBG_Case_t *c,
CK_SESSION_HANDLE session,
const char *rsa_name, uint32_t rsa_bits)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE;
CK_MECHANISM mechanism = {
CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0
};
CK_MECHANISM sign_mechanism = {
CKM_RSA_PKCS, NULL, 0
};
CK_ULONG modulus_bits = 0;
CK_BYTE public_exponent[] = { 1, 0, 1 };
CK_BYTE id[] = { 123 };
CK_ATTRIBUTE public_key_template[] = {
{ CKA_ENCRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_ULONG) },
{ CKA_PUBLIC_EXPONENT, public_exponent,
sizeof(public_exponent) }
};
CK_ATTRIBUTE private_key_template[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SUBJECT, subject_common_name,
sizeof(subject_common_name) },
{ CKA_ID, id, sizeof(id) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }
};
CK_OBJECT_CLASS g_class = 0;
CK_KEY_TYPE g_key_type = 0;
CK_BYTE g_id[32] = { 0 };
CK_DATE g_start_date = { 0 };
CK_DATE g_end_date = { 0 };
CK_BBOOL g_derive = CK_FALSE;
CK_BBOOL g_local = CK_FALSE;
CK_MECHANISM_TYPE g_keygen_mecha = 0;
CK_BYTE g_subject[64] = { 0 };
CK_BBOOL g_encrypt = CK_FALSE;
CK_BBOOL g_verify = CK_FALSE;
CK_BBOOL g_verify_recover = CK_FALSE;
CK_BBOOL g_wrap = CK_FALSE;
CK_BBOOL g_trusted = CK_FALSE;
CK_BYTE g_public_key_info[1024] = { 0 };
CK_BBOOL g_sensitive = CK_FALSE;
CK_BBOOL g_decrypt = CK_FALSE;
CK_BBOOL g_sign = CK_FALSE;
CK_BBOOL g_sign_recover = CK_FALSE;
CK_BBOOL g_unwrap = CK_FALSE;
CK_BBOOL g_extract = CK_FALSE;
CK_BBOOL g_asensitive = CK_FALSE;
CK_BBOOL g_nextract = CK_FALSE;
CK_BBOOL g_wrap_with_trusted = CK_FALSE;
CK_BBOOL g_always_authenticate = CK_FALSE;
/* Note: Tests below expects specific order of elements */
CK_ATTRIBUTE get_public_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_ID, g_id, sizeof(g_id) },
{ CKA_START_DATE, &g_start_date, sizeof(CK_DATE) },
{ CKA_END_DATE, &g_end_date, sizeof(CK_DATE) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(CK_MECHANISM_TYPE) },
{ CKA_SUBJECT, g_subject, sizeof(g_subject) },
{ CKA_ENCRYPT, &g_encrypt, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &g_verify, sizeof(CK_BBOOL) },
{ CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(CK_BBOOL) },
{ CKA_WRAP, &g_wrap, sizeof(CK_BBOOL) },
{ CKA_TRUSTED, &g_trusted, sizeof(CK_BBOOL) },
{ CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) },
};
/* Note: Tests below expects specific order of elements */
CK_ATTRIBUTE get_private_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_ID, g_id, sizeof(g_id) },
{ CKA_START_DATE, &g_start_date, sizeof(CK_DATE) },
{ CKA_END_DATE, &g_end_date, sizeof(CK_DATE) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(CK_MECHANISM_TYPE) },
{ CKA_SUBJECT, g_subject, sizeof(g_subject) },
{ CKA_SENSITIVE, &g_sensitive, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &g_decrypt, sizeof(CK_BBOOL) },
{ CKA_SIGN, &g_sign, sizeof(CK_BBOOL) },
{ CKA_SIGN_RECOVER, &g_sign_recover, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &g_unwrap, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &g_extract, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(CK_BBOOL) },
{ CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(CK_BBOOL) },
{ CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(CK_BBOOL) },
{ CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) },
};
uint8_t signature[512] = { 0 };
CK_ULONG signature_len = 0;
size_t i = 0;
Do_ADBG_BeginSubCase(c, "%s: Generate key pair", rsa_name);
modulus_bits = rsa_bits;
rv = C_GenerateKeyPair(session, &mechanism, public_key_template,
ARRAY_SIZE(public_key_template),
private_key_template,
ARRAY_SIZE(private_key_template),
&public_key, &private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
/* reset get public key template */
memset(g_id, 0, sizeof(g_id));
assert(get_public_template[2].type == CKA_ID);
get_public_template[2].ulValueLen = sizeof(g_id);
memset(g_subject, 0, sizeof(g_subject));
assert(get_public_template[8].type == CKA_SUBJECT);
get_public_template[8].ulValueLen = sizeof(g_subject);
memset(g_public_key_info, 0, sizeof(g_public_key_info));
assert(get_public_template[14].type == CKA_PUBLIC_KEY_INFO);
get_public_template[14].ulValueLen = sizeof(g_public_key_info);
rv = C_GetAttributeValue(session, public_key, get_public_template,
ARRAY_SIZE(get_public_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==,
CKM_RSA_PKCS_KEY_PAIR_GEN) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE))
goto err_destr_obj;
/* reset get private key template */
memset(g_id, 0, sizeof(g_id));
assert(get_private_template[2].type == CKA_ID);
get_private_template[2].ulValueLen = sizeof(g_id);
memset(g_subject, 0, sizeof(g_subject));
assert(get_private_template[8].type == CKA_SUBJECT);
get_private_template[8].ulValueLen = sizeof(g_subject);
memset(g_public_key_info, 0, sizeof(g_public_key_info));
assert(get_private_template[19].type == CKA_PUBLIC_KEY_INFO);
get_private_template[19].ulValueLen = sizeof(g_public_key_info);
rv = C_GetAttributeValue(session, private_key, get_private_template,
ARRAY_SIZE(get_private_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==,
CKM_RSA_PKCS_KEY_PAIR_GEN) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE))
goto err_destr_obj;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c,
"%s: Sign & verify tests - oneshot - CKM_RSA_PKCS",
rsa_name);
sign_mechanism.mechanism = CKM_RSA_PKCS;
memset(signature, 0, sizeof(signature));
signature_len = sizeof(signature);
rv = C_SignInit(session, &sign_mechanism, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Sign(session, (void *)digest_test_pattern_sha256,
sizeof(digest_test_pattern_sha256), (void *)signature,
&signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyInit(session, &sign_mechanism, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session, (void *)digest_test_pattern_sha256,
sizeof(digest_test_pattern_sha256), (void *)signature,
signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
for (i = 0; i < ARRAY_SIZE(rsa_pkcs_sign_tests); i++) {
/*
* Note: this order of end/begin here is just to get ADBG
* SubCases in sync with error handling.
*/
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "%s: Sign & verify - oneshot - %s",
rsa_name,
rsa_pkcs_sign_tests[i].test_name);
sign_mechanism.mechanism = rsa_pkcs_sign_tests[i].mecha;
memset(signature, 0, sizeof(signature));
signature_len = sizeof(signature);
rv = C_SignInit(session, &sign_mechanism, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Sign(session, (void *)rsa_pkcs_sign_tests[i].data,
rsa_pkcs_sign_tests[i].data_size,
(void *)signature, &signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyInit(session, &sign_mechanism, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session, (void *)rsa_pkcs_sign_tests[i].data,
rsa_pkcs_sign_tests[i].data_size,
(void *)signature, signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
}
rv = C_DestroyObject(session, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_pub_obj;
rv = C_DestroyObject(session, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
return 1;
err_destr_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key));
err_destr_pub_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key));
err:
Do_ADBG_EndSubCase(c, NULL);
return 0;
}
static void xtest_pkcs11_test_1021(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
int ret = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ret = test_rsa_pkcs_operations(c, session, "RSA-1024", 1024);
if (!ret)
goto out;
ret = test_rsa_pkcs_operations(c, session, "RSA-2048", 2048);
if (!ret)
goto out;
if (level > 0) {
ret = test_rsa_pkcs_operations(c, session, "RSA-3072", 3072);
if (!ret)
goto out;
ret = test_rsa_pkcs_operations(c, session, "RSA-4096", 4096);
if (!ret)
goto out;
}
out:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1021, xtest_pkcs11_test_1021,
"PKCS11: RSA PKCS key generation and signing");
#define RSA_PSS_HASH_SIGN_TEST(_test_name, _min_rsa_bits, _mecha, _hash_algo, _mgf_algo, \
_salt_len, _data) \
{ \
.test_name = _test_name, \
.min_rsa_bits = _min_rsa_bits, \
.mecha = _mecha, \
.hash_algo = _hash_algo, \
.mgf_algo = _mgf_algo, \
.salt_len = _salt_len, \
.data = _data, \
.data_size = sizeof(_data), \
}
#define RSA_PSS_CSTR_SIGN_TEST(_test_name, _min_rsa_bits, _mecha, _hash_algo, \
_mgf_algo, _salt_len, _data) \
{ \
.test_name = _test_name, \
.min_rsa_bits = _min_rsa_bits, \
.mecha = _mecha, \
.hash_algo = _hash_algo, \
.mgf_algo = _mgf_algo, \
.salt_len = _salt_len, \
.data = _data, \
.data_size = sizeof(_data) - 1, \
}
/* List of RSA PSS signing multi stage digest mechanisms */
static struct {
const char *test_name;
uint32_t min_rsa_bits;
CK_MECHANISM_TYPE mecha;
CK_MECHANISM_TYPE hash_algo;
CK_RSA_PKCS_MGF_TYPE mgf_algo;
CK_ULONG salt_len;
const void *data;
CK_ULONG data_size;
} rsa_pss_sign_tests[] = {
RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA1", 1024, CKM_RSA_PKCS_PSS,
CKM_SHA_1, CKG_MGF1_SHA1, 20,
digest_test_pattern_sha1),
RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA1/mech", 1024,
CKM_SHA1_RSA_PKCS_PSS, CKM_SHA_1, CKG_MGF1_SHA1,
20, digest_test_pattern),
RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA224", 1024, CKM_RSA_PKCS_PSS,
CKM_SHA224, CKG_MGF1_SHA224, 28,
digest_test_pattern_sha224),
RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA224/mech", 1024,
CKM_SHA224_RSA_PKCS_PSS, CKM_SHA224,
CKG_MGF1_SHA224, 28, digest_test_pattern),
RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA256", 1024, CKM_RSA_PKCS_PSS,
CKM_SHA256, CKG_MGF1_SHA256, 32,
digest_test_pattern_sha256),
RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA256/mech", 1024,
CKM_SHA256_RSA_PKCS_PSS, CKM_SHA256,
CKG_MGF1_SHA256, 32, digest_test_pattern),
RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA384", 1024, CKM_RSA_PKCS_PSS,
CKM_SHA384, CKG_MGF1_SHA384, 48,
digest_test_pattern_sha384),
RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA384/mech", 1024,
CKM_SHA384_RSA_PKCS_PSS, CKM_SHA384,
CKG_MGF1_SHA384, 48, digest_test_pattern),
RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA512", 2048, CKM_RSA_PKCS_PSS,
CKM_SHA512, CKG_MGF1_SHA512, 64,
digest_test_pattern_sha512),
RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA512/mech", 2048,
CKM_SHA512_RSA_PKCS_PSS, CKM_SHA512,
CKG_MGF1_SHA512, 64, digest_test_pattern),
};
static int test_rsa_pss_operations(ADBG_Case_t *c,
CK_SESSION_HANDLE session,
const char *rsa_name, uint32_t rsa_bits)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE;
CK_MECHANISM mechanism = {
CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0
};
CK_MECHANISM sign_mechanism = {
CKM_RSA_PKCS_PSS, NULL, 0
};
CK_RSA_PKCS_PSS_PARAMS pss_params = {
CKM_SHA256, CKG_MGF1_SHA256, 32,
};
CK_ULONG modulus_bits = 0;
CK_BYTE public_exponent[] = { 1, 0, 1 };
CK_BYTE id[] = { 123 };
CK_ATTRIBUTE public_key_template[] = {
{ CKA_ENCRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_ULONG) },
{ CKA_PUBLIC_EXPONENT, public_exponent,
sizeof(public_exponent) }
};
CK_ATTRIBUTE private_key_template[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SUBJECT, subject_common_name,
sizeof(subject_common_name) },
{ CKA_ID, id, sizeof(id) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }
};
CK_OBJECT_CLASS g_class = 0;
CK_KEY_TYPE g_key_type = 0;
CK_BYTE g_id[32] = { 0 };
CK_DATE g_start_date = { 0 };
CK_DATE g_end_date = { 0 };
CK_BBOOL g_derive = CK_FALSE;
CK_BBOOL g_local = CK_FALSE;
CK_MECHANISM_TYPE g_keygen_mecha = 0;
CK_BYTE g_subject[64] = { 0 };
CK_BBOOL g_encrypt = CK_FALSE;
CK_BBOOL g_verify = CK_FALSE;
CK_BBOOL g_verify_recover = CK_FALSE;
CK_BBOOL g_wrap = CK_FALSE;
CK_BBOOL g_trusted = CK_FALSE;
CK_BYTE g_public_key_info[1024] = { 0 };
CK_BBOOL g_sensitive = CK_FALSE;
CK_BBOOL g_decrypt = CK_FALSE;
CK_BBOOL g_sign = CK_FALSE;
CK_BBOOL g_sign_recover = CK_FALSE;
CK_BBOOL g_unwrap = CK_FALSE;
CK_BBOOL g_extract = CK_FALSE;
CK_BBOOL g_asensitive = CK_FALSE;
CK_BBOOL g_nextract = CK_FALSE;
CK_BBOOL g_wrap_with_trusted = CK_FALSE;
CK_BBOOL g_always_authenticate = CK_FALSE;
/* Note: Tests below expects specific order of elements */
CK_ATTRIBUTE get_public_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_ID, g_id, sizeof(g_id) },
{ CKA_START_DATE, &g_start_date, sizeof(CK_DATE) },
{ CKA_END_DATE, &g_end_date, sizeof(CK_DATE) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(CK_MECHANISM_TYPE) },
{ CKA_SUBJECT, g_subject, sizeof(g_subject) },
{ CKA_ENCRYPT, &g_encrypt, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &g_verify, sizeof(CK_BBOOL) },
{ CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(CK_BBOOL) },
{ CKA_WRAP, &g_wrap, sizeof(CK_BBOOL) },
{ CKA_TRUSTED, &g_trusted, sizeof(CK_BBOOL) },
{ CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) },
};
/* Note: Tests below expects specific order of elements */
CK_ATTRIBUTE get_private_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_ID, g_id, sizeof(g_id) },
{ CKA_START_DATE, &g_start_date, sizeof(CK_DATE) },
{ CKA_END_DATE, &g_end_date, sizeof(CK_DATE) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(CK_MECHANISM_TYPE) },
{ CKA_SUBJECT, g_subject, sizeof(g_subject) },
{ CKA_SENSITIVE, &g_sensitive, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &g_decrypt, sizeof(CK_BBOOL) },
{ CKA_SIGN, &g_sign, sizeof(CK_BBOOL) },
{ CKA_SIGN_RECOVER, &g_sign_recover, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &g_unwrap, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &g_extract, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(CK_BBOOL) },
{ CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(CK_BBOOL) },
{ CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(CK_BBOOL) },
{ CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) },
};
uint8_t signature[512] = { 0 };
CK_ULONG signature_len = 0;
size_t i = 0;
Do_ADBG_BeginSubCase(c, "%s: Generate key pair", rsa_name);
modulus_bits = rsa_bits;
rv = C_GenerateKeyPair(session, &mechanism, public_key_template,
ARRAY_SIZE(public_key_template),
private_key_template,
ARRAY_SIZE(private_key_template),
&public_key, &private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
/* reset get public key template */
memset(g_id, 0, sizeof(g_id));
assert(get_public_template[2].type == CKA_ID);
get_public_template[2].ulValueLen = sizeof(g_id);
memset(g_subject, 0, sizeof(g_subject));
assert(get_public_template[8].type == CKA_SUBJECT);
get_public_template[8].ulValueLen = sizeof(g_subject);
memset(g_public_key_info, 0, sizeof(g_public_key_info));
assert(get_public_template[14].type == CKA_PUBLIC_KEY_INFO);
get_public_template[14].ulValueLen = sizeof(g_public_key_info);
rv = C_GetAttributeValue(session, public_key, get_public_template,
ARRAY_SIZE(get_public_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==,
CKM_RSA_PKCS_KEY_PAIR_GEN) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE))
goto err_destr_obj;
/* reset get private key template */
memset(g_id, 0, sizeof(g_id));
assert(get_private_template[2].type == CKA_ID);
get_private_template[2].ulValueLen = sizeof(g_id);
memset(g_subject, 0, sizeof(g_subject));
assert(get_private_template[8].type == CKA_SUBJECT);
get_private_template[8].ulValueLen = sizeof(g_subject);
memset(g_public_key_info, 0, sizeof(g_public_key_info));
assert(get_private_template[19].type == CKA_PUBLIC_KEY_INFO);
get_private_template[19].ulValueLen = sizeof(g_public_key_info);
rv = C_GetAttributeValue(session, private_key, get_private_template,
ARRAY_SIZE(get_private_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==,
CKM_RSA_PKCS_KEY_PAIR_GEN) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE))
goto err_destr_obj;
for (i = 0; i < ARRAY_SIZE(rsa_pss_sign_tests); i++) {
/*
* Note: this order of end/begin here is just to get ADBG
* SubCases in sync with error handling.
*/
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "%s: Sign & verify - oneshot - %s",
rsa_name,
rsa_pss_sign_tests[i].test_name);
sign_mechanism.mechanism = rsa_pss_sign_tests[i].mecha;
sign_mechanism.pParameter = &pss_params;
sign_mechanism.ulParameterLen = sizeof(pss_params);
pss_params.hashAlg = rsa_pss_sign_tests[i].hash_algo;
pss_params.mgf = rsa_pss_sign_tests[i].mgf_algo;
pss_params.sLen = rsa_pss_sign_tests[i].salt_len;
memset(signature, 0, sizeof(signature));
signature_len = sizeof(signature);
rv = C_SignInit(session, &sign_mechanism, private_key);
if (rsa_bits >= rsa_pss_sign_tests[i].min_rsa_bits) {
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
} else {
if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_SIZE_RANGE, rv))
goto err_destr_obj;
continue;
}
rv = C_Sign(session, (void *)rsa_pss_sign_tests[i].data,
rsa_pss_sign_tests[i].data_size,
(void *)signature, &signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_VerifyInit(session, &sign_mechanism, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Verify(session, (void *)rsa_pss_sign_tests[i].data,
rsa_pss_sign_tests[i].data_size,
(void *)signature, signature_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
}
rv = C_DestroyObject(session, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_pub_obj;
rv = C_DestroyObject(session, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
return 1;
err_destr_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key));
err_destr_pub_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key));
err:
Do_ADBG_EndSubCase(c, NULL);
return 0;
}
static void xtest_pkcs11_test_1022(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
int ret = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ret = test_rsa_pss_operations(c, session, "RSA-1024", 1024);
if (!ret)
goto out;
ret = test_rsa_pss_operations(c, session, "RSA-2048", 2048);
if (!ret)
goto out;
if (level > 0) {
ret = test_rsa_pss_operations(c, session, "RSA-3072", 3072);
if (!ret)
goto out;
ret = test_rsa_pss_operations(c, session, "RSA-4096", 4096);
if (!ret)
goto out;
}
out:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1022, xtest_pkcs11_test_1022,
"PKCS11: RSA PSS key generation and signing");
static const char rsa_oaep_message[] = "Hello World";
static char rsa_oaep_label[] = "TestLabel";
#define RSA_OAEP_CRYPT_TEST(_test_name, _min_rsa_bits, _hash_algo, _mgf_algo, \
_source_data, _source_data_len) \
{ \
.test_name = _test_name, \
.min_rsa_bits = _min_rsa_bits, \
.hash_algo = _hash_algo, \
.mgf_algo = _mgf_algo, \
.source_data = _source_data, \
.source_data_len = _source_data_len, \
}
/* List of RSA OAEP crypto params to test out */
static struct {
const char *test_name;
uint32_t min_rsa_bits;
CK_MECHANISM_TYPE hash_algo;
CK_RSA_PKCS_MGF_TYPE mgf_algo;
void *source_data;
size_t source_data_len;
} rsa_oaep_crypt_tests[] = {
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA1", 1024, CKM_SHA_1, CKG_MGF1_SHA1,
NULL, 0),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA1/label", 1024, CKM_SHA_1,
CKG_MGF1_SHA1, rsa_oaep_label,
sizeof(rsa_oaep_label)),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA224", 1024, CKM_SHA224,
CKG_MGF1_SHA224, NULL, 0),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA224/label", 1024, CKM_SHA224,
CKG_MGF1_SHA224, rsa_oaep_label,
sizeof(rsa_oaep_label)),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA256", 1024, CKM_SHA256,
CKG_MGF1_SHA256, NULL, 0),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA256/label", 1024, CKM_SHA256,
CKG_MGF1_SHA256, rsa_oaep_label,
sizeof(rsa_oaep_label)),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA384", 1024, CKM_SHA384,
CKG_MGF1_SHA384, NULL, 0),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA384/label", 1024, CKM_SHA384,
CKG_MGF1_SHA384, rsa_oaep_label,
sizeof(rsa_oaep_label)),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA512", 2048, CKM_SHA512,
CKG_MGF1_SHA512, NULL, 0),
RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA512/label", 2048, CKM_SHA512,
CKG_MGF1_SHA512, rsa_oaep_label,
sizeof(rsa_oaep_label)),
};
static int test_rsa_oaep_operations(ADBG_Case_t *c,
CK_SESSION_HANDLE session,
const char *rsa_name, uint32_t rsa_bits)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE;
CK_MECHANISM mechanism = {
CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0
};
CK_MECHANISM crypt_mechanism = {
CKM_RSA_PKCS_OAEP, NULL, 0
};
CK_RSA_PKCS_OAEP_PARAMS oaep_params = {
CKM_SHA256, CKG_MGF1_SHA256, CKZ_DATA_SPECIFIED, NULL, 0
};
CK_BYTE public_exponent[] = { 1, 0, 1 };
CK_BYTE id[] = { 123 };
CK_ULONG modulus_bits = 0;
CK_ATTRIBUTE public_key_template[] = {
{ CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_ULONG) },
{ CKA_PUBLIC_EXPONENT, public_exponent,
sizeof(public_exponent) }
};
CK_ATTRIBUTE private_key_template[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SUBJECT, subject_common_name,
sizeof(subject_common_name) },
{ CKA_ID, id, sizeof(id) },
{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }
};
CK_OBJECT_CLASS g_class = 0;
CK_KEY_TYPE g_key_type = 0;
CK_BYTE g_id[32] = { 0 };
CK_DATE g_start_date = { 0 };
CK_DATE g_end_date = { 0 };
CK_BBOOL g_derive = CK_FALSE;
CK_BBOOL g_local = CK_FALSE;
CK_MECHANISM_TYPE g_keygen_mecha = 0;
CK_BYTE g_subject[64] = { 0 };
CK_BBOOL g_encrypt = CK_FALSE;
CK_BBOOL g_verify = CK_FALSE;
CK_BBOOL g_verify_recover = CK_FALSE;
CK_BBOOL g_wrap = CK_FALSE;
CK_BBOOL g_trusted = CK_FALSE;
CK_BYTE g_public_key_info[1024] = { 0 };
CK_BBOOL g_sensitive = CK_FALSE;
CK_BBOOL g_decrypt = CK_FALSE;
CK_BBOOL g_sign = CK_FALSE;
CK_BBOOL g_sign_recover = CK_FALSE;
CK_BBOOL g_unwrap = CK_FALSE;
CK_BBOOL g_extract = CK_FALSE;
CK_BBOOL g_asensitive = CK_FALSE;
CK_BBOOL g_nextract = CK_FALSE;
CK_BBOOL g_wrap_with_trusted = CK_FALSE;
CK_BBOOL g_always_authenticate = CK_FALSE;
/* Note: Tests below expects specific order of elements */
CK_ATTRIBUTE get_public_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_ID, g_id, sizeof(g_id) },
{ CKA_START_DATE, &g_start_date, sizeof(CK_DATE) },
{ CKA_END_DATE, &g_end_date, sizeof(CK_DATE) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(CK_MECHANISM_TYPE) },
{ CKA_SUBJECT, g_subject, sizeof(g_subject) },
{ CKA_ENCRYPT, &g_encrypt, sizeof(CK_BBOOL) },
{ CKA_VERIFY, &g_verify, sizeof(CK_BBOOL) },
{ CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(CK_BBOOL) },
{ CKA_WRAP, &g_wrap, sizeof(CK_BBOOL) },
{ CKA_TRUSTED, &g_trusted, sizeof(CK_BBOOL) },
{ CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) },
};
/* Note: Tests below expects specific order of elements */
CK_ATTRIBUTE get_private_template[] = {
{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
{ CKA_KEY_TYPE, &g_key_type, sizeof(CK_KEY_TYPE) },
{ CKA_ID, g_id, sizeof(g_id) },
{ CKA_START_DATE, &g_start_date, sizeof(CK_DATE) },
{ CKA_END_DATE, &g_end_date, sizeof(CK_DATE) },
{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
{ CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(CK_MECHANISM_TYPE) },
{ CKA_SUBJECT, g_subject, sizeof(g_subject) },
{ CKA_SENSITIVE, &g_sensitive, sizeof(CK_BBOOL) },
{ CKA_DECRYPT, &g_decrypt, sizeof(CK_BBOOL) },
{ CKA_SIGN, &g_sign, sizeof(CK_BBOOL) },
{ CKA_SIGN_RECOVER, &g_sign_recover, sizeof(CK_BBOOL) },
{ CKA_UNWRAP, &g_unwrap, sizeof(CK_BBOOL) },
{ CKA_EXTRACTABLE, &g_extract, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(CK_BBOOL) },
{ CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(CK_BBOOL) },
{ CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(CK_BBOOL) },
{ CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(CK_BBOOL) },
{ CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) },
};
uint8_t ciphertext[512] = { 0 };
CK_ULONG ciphertext_len = 0;
uint8_t plaintext[512] = { 0 };
CK_ULONG plaintext_len = 0;
size_t i = 0;
Do_ADBG_BeginSubCase(c, "%s: Generate key pair", rsa_name);
modulus_bits = rsa_bits;
rv = C_GenerateKeyPair(session, &mechanism, public_key_template,
ARRAY_SIZE(public_key_template),
private_key_template,
ARRAY_SIZE(private_key_template),
&public_key, &private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
/* reset get public key template */
memset(g_id, 0, sizeof(g_id));
assert(get_public_template[2].type == CKA_ID);
get_public_template[2].ulValueLen = sizeof(g_id);
memset(g_subject, 0, sizeof(g_subject));
assert(get_public_template[8].type == CKA_SUBJECT);
get_public_template[8].ulValueLen = sizeof(g_subject);
memset(g_public_key_info, 0, sizeof(g_public_key_info));
assert(get_public_template[14].type == CKA_PUBLIC_KEY_INFO);
get_public_template[14].ulValueLen = sizeof(g_public_key_info);
rv = C_GetAttributeValue(session, public_key,
get_public_template,
ARRAY_SIZE(get_public_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==,
CKM_RSA_PKCS_KEY_PAIR_GEN) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE))
goto err_destr_obj;
/* reset get private key template */
memset(g_id, 0, sizeof(g_id));
assert(get_private_template[2].type == CKA_ID);
get_private_template[2].ulValueLen = sizeof(g_id);
memset(g_subject, 0, sizeof(g_subject));
assert(get_private_template[8].type == CKA_SUBJECT);
get_private_template[8].ulValueLen = sizeof(g_subject);
memset(g_public_key_info, 0, sizeof(g_public_key_info));
assert(get_private_template[19].type == CKA_PUBLIC_KEY_INFO);
get_private_template[19].ulValueLen = sizeof(g_public_key_info);
rv = C_GetAttributeValue(session, private_key,
get_private_template,
ARRAY_SIZE(get_private_template));
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==,
CKM_RSA_PKCS_KEY_PAIR_GEN) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) ||
!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE))
goto err_destr_obj;
for (i = 0; i < ARRAY_SIZE(rsa_oaep_crypt_tests); i++) {
/*
* Note: this order of end/begin here is just to get ADBG
* SubCases in sync with error handling.
*/
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "%s: Encrypt & decrypt - oneshot - %s",
rsa_name,
rsa_oaep_crypt_tests[i].test_name);
crypt_mechanism.mechanism = CKM_RSA_PKCS_OAEP;
crypt_mechanism.pParameter = &oaep_params;
crypt_mechanism.ulParameterLen = sizeof(oaep_params);
oaep_params.hashAlg = rsa_oaep_crypt_tests[i].hash_algo;
oaep_params.mgf = rsa_oaep_crypt_tests[i].mgf_algo;
oaep_params.pSourceData = rsa_oaep_crypt_tests[i].source_data;
oaep_params.ulSourceDataLen = rsa_oaep_crypt_tests[i].source_data_len;
memset(ciphertext, 0, sizeof(ciphertext));
memset(plaintext, 0, sizeof(plaintext));
ciphertext_len = 0;
memcpy(plaintext, rsa_oaep_message, sizeof(rsa_oaep_message));
plaintext_len = sizeof(rsa_oaep_message);
rv = C_EncryptInit(session, &crypt_mechanism, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Encrypt(session, plaintext, plaintext_len, NULL,
&ciphertext_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Encrypt(session, plaintext, plaintext_len, ciphertext,
&ciphertext_len);
if (rsa_bits >= rsa_oaep_crypt_tests[i].min_rsa_bits) {
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
} else {
if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv))
goto err_destr_obj;
continue;
}
memset(plaintext, 0, sizeof(plaintext));
plaintext_len = 0;
rv = C_DecryptInit(session, &crypt_mechanism, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Decrypt(session, ciphertext, ciphertext_len, NULL,
&plaintext_len);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_obj;
rv = C_Decrypt(session, ciphertext, ciphertext_len, plaintext,
&plaintext_len);
if (!ADBG_EXPECT_CK_OK(c, rv) ||
!ADBG_EXPECT_BUFFER(c, rsa_oaep_message,
sizeof(rsa_oaep_message), plaintext,
plaintext_len))
goto err_destr_obj;
}
rv = C_DestroyObject(session, private_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err_destr_pub_obj;
rv = C_DestroyObject(session, public_key);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto err;
Do_ADBG_EndSubCase(c, NULL);
return 1;
err_destr_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key));
err_destr_pub_obj:
ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key));
err:
Do_ADBG_EndSubCase(c, NULL);
return 0;
}
static void xtest_pkcs11_test_1023(ADBG_Case_t *c)
{
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
int ret = 0;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
ret = test_rsa_oaep_operations(c, session, "RSA-1024", 1024);
if (!ret)
goto out;
ret = test_rsa_oaep_operations(c, session, "RSA-2048", 2048);
if (!ret)
goto out;
if (level > 0) {
ret = test_rsa_oaep_operations(c, session, "RSA-3072", 3072);
if (!ret)
goto out;
ret = test_rsa_oaep_operations(c, session, "RSA-4096", 4096);
if (!ret)
goto out;
}
out:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
}
ADBG_CASE_DEFINE(pkcs11, 1023, xtest_pkcs11_test_1023,
"PKCS11: RSA OAEP key generation and crypto operations");
static const char x509_example_root_ca[] =
"-----BEGIN CERTIFICATE-----\n"
"MIICDTCCAZOgAwIBAgIBATAKBggqhkjOPQQDAzA+MQswCQYDVQQGEwJGSTEVMBMG\n"
"A1UECgwMTWFudWZhY3R1cmVyMRgwFgYDVQQDDA9FeGFtcGxlIFJvb3QgQ0EwIBcN\n"
"MjEwODE0MDc1NTU1WhgPOTk5OTEyMzEyMzU5NTlaMD4xCzAJBgNVBAYTAkZJMRUw\n"
"EwYDVQQKDAxNYW51ZmFjdHVyZXIxGDAWBgNVBAMMD0V4YW1wbGUgUm9vdCBDQTB2\n"
"MBAGByqGSM49AgEGBSuBBAAiA2IABP6jFf4PuIo0t78AeONf2ENbip4GdG9rfstp\n"
"bWMvH/0BIn2ioMbapYSK1WcVlOKUaZRrbRzoYWD7ZpwSYFwtd1XmMQkLJ1baIdrt\n"
"jibL9yBCYRJJLsmTHn5UiLCoA2EiFaNjMGEwHQYDVR0OBBYEFApC6125F2th+ujZ\n"
"PVxTtsI8llA1MB8GA1UdIwQYMBaAFApC6125F2th+ujZPVxTtsI8llA1MA8GA1Ud\n"
"EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMACW\n"
"r0/EpTD1uJ9JLsyC8aGP2rSr44J50K6fT0h3LZWMhL5fGkkNTCdmuWbWZznTswIx\n"
"APjyNm4f///vWUN3XFd+BRhS2YHR43c0K4oNVyLqigoMoSqu0zXt9Xm+Lsu5iqgJ\n"
"NQ==\n"
"-----END CERTIFICATE-----\n";
static void xtest_pkcs11_test_1024(ADBG_Case_t *c)
{
#ifndef OPENSSL_FOUND
Do_ADBG_Log("OpenSSL not available, skipping X.509 Certificate tests");
#else
CK_RV rv = CKR_GENERAL_ERROR;
CK_SLOT_ID slot = 0;
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
BIO *x509_bio = NULL;
X509 *x509_cert = NULL;
uint8_t *x509_cert_der = NULL;
int x509_cert_der_size = 0;
X509_NAME *x509_subject_name = NULL;
uint8_t *x509_subject_name_der = NULL;
int x509_subject_name_der_size = 0;
X509_NAME *x509_issuer_name = NULL;
uint8_t *x509_issuer_name_der = NULL;
int x509_issuer_name_der_size = 0;
ASN1_INTEGER *x509_serial_number = NULL;
uint8_t *x509_serial_number_der = NULL;
int x509_serial_number_der_size = 0;
uint8_t *p = NULL;
CK_BYTE id[] = { 123 };
const char *label = "example-root-ca";
/* Note: Tests below expects specific order of elements */
CK_ATTRIBUTE certificate_object[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE },
sizeof(CK_OBJECT_CLASS) },
{ CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 },
sizeof(CK_CERTIFICATE_TYPE) },
{ CKA_CERTIFICATE_CATEGORY,
&(CK_ULONG){ CK_CERTIFICATE_CATEGORY_UNSPECIFIED },
sizeof(CK_ULONG) },
{ CKA_NAME_HASH_ALGORITHM, &(CK_MECHANISM_TYPE){ CKM_SHA_1 },
sizeof(CK_MECHANISM_TYPE) },
{ CKA_ID, id, sizeof(id) },
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
{ CKA_VALUE, NULL, 0 },
{ CKA_ISSUER, NULL, 0 },
{ CKA_SUBJECT, NULL, 0 },
{ CKA_SERIAL_NUMBER, NULL, 0 },
};
/* Note: Tests below expects specific order of elements */
CK_ATTRIBUTE certificate_object2[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE },
sizeof(CK_OBJECT_CLASS) },
{ CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 },
sizeof(CK_CERTIFICATE_TYPE) },
{ CKA_ID, id, sizeof(id) },
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
{ CKA_VALUE, NULL, 0 },
{ CKA_ISSUER, NULL, 0 },
{ CKA_SUBJECT, NULL, 0 },
{ CKA_SERIAL_NUMBER, NULL, 0 },
};
/* Note: Tests below expects specific order of elements */
/* CKA_CERTIFICATE_CATEGORY is specified below with invalid ID */
CK_ATTRIBUTE invalid_category_object[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE },
sizeof(CK_OBJECT_CLASS) },
{ CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 },
sizeof(CK_CERTIFICATE_TYPE) },
{ CKA_CERTIFICATE_CATEGORY, &(CK_ULONG){ -1 },
sizeof(CK_ULONG) },
{ CKA_ID, id, sizeof(id) },
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
{ CKA_VALUE, NULL, 0 },
{ CKA_ISSUER, NULL, 0 },
{ CKA_SUBJECT, NULL, 0 },
{ CKA_SERIAL_NUMBER, NULL, 0 },
};
/* Note: Tests below expects specific order of elements */
/* CKA_CERTIFICATE_CATEGORY is specified below with invalid size */
CK_ATTRIBUTE invalid_category_object2[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE },
sizeof(CK_OBJECT_CLASS) },
{ CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 },
sizeof(CK_CERTIFICATE_TYPE) },
{ CKA_CERTIFICATE_CATEGORY,
&(CK_ULONG){ CK_CERTIFICATE_CATEGORY_UNSPECIFIED }, 0 },
{ CKA_ID, id, sizeof(id) },
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
{ CKA_VALUE, NULL, 0 },
{ CKA_ISSUER, NULL, 0 },
{ CKA_SUBJECT, NULL, 0 },
{ CKA_SERIAL_NUMBER, NULL, 0 },
};
/* Note: Tests below expects specific order of elements */
/* CKA_NAME_HASH_ALGORITHM is specified below with invalid size */
CK_ATTRIBUTE invalid_name_hash_alg_size[] = {
{ CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE },
sizeof(CK_OBJECT_CLASS) },
{ CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 },
sizeof(CK_CERTIFICATE_TYPE) },
{ CKA_NAME_HASH_ALGORITHM, &(CK_MECHANISM_TYPE){ CKM_SHA_1 },
sizeof(CK_MECHANISM_TYPE) - 1 },
{ CKA_ID, id, sizeof(id) },
{ CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) },
{ CKA_VALUE, NULL, 0 },
{ CKA_ISSUER, NULL, 0 },
{ CKA_SUBJECT, NULL, 0 },
{ CKA_SERIAL_NUMBER, NULL, 0 },
};
CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE;
rv = init_lib_and_find_token_slot(&slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
return;
rv = init_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = init_user_test_token(slot);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_lib;
/* Login to Test Token */
rv = C_Login(session, CKU_USER, test_token_user_pin,
sizeof(test_token_user_pin));
if (!ADBG_EXPECT_CK_OK(c, rv))
goto close_session;
Do_ADBG_BeginSubCase(c, "Import X.509 Certificate");
/* Parse PEM to OpenSSL's internal X509 format */
x509_bio = BIO_new_mem_buf(x509_example_root_ca, -1);
if (!ADBG_EXPECT_NOT_NULL(c, x509_bio))
goto out;
x509_cert = PEM_read_bio_X509(x509_bio, NULL, 0, NULL);
if (!ADBG_EXPECT_NOT_NULL(c, x509_cert))
goto out;
BIO_free(x509_bio);
x509_bio = NULL;
/* Make DER version for storing it in token */
x509_cert_der_size = i2d_X509(x509_cert, NULL);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_cert_der_size, >, 0))
goto out;
x509_cert_der = OPENSSL_malloc(x509_cert_der_size);
if (!ADBG_EXPECT_NOT_NULL(c, x509_cert_der))
goto out;
p = x509_cert_der;
x509_cert_der_size = i2d_X509(x509_cert, &p);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_cert_der_size, >, 0))
goto out;
/* Extract needed details from certificate */
/* Extract subject name */
x509_subject_name = X509_get_subject_name(x509_cert);
if (!ADBG_EXPECT_NOT_NULL(c, x509_subject_name))
goto out;
x509_subject_name_der_size = i2d_X509_NAME(x509_subject_name, NULL);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_subject_name_der_size, >, 0))
goto out;
x509_subject_name_der = OPENSSL_malloc(x509_subject_name_der_size);
if (!ADBG_EXPECT_NOT_NULL(c, x509_subject_name_der))
goto out;
p = x509_subject_name_der;
x509_subject_name_der_size = i2d_X509_NAME(x509_subject_name, &p);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_subject_name_der_size, >, 0))
goto out;
/* Extract issuer's name */
x509_issuer_name = X509_get_issuer_name(x509_cert);
if (!ADBG_EXPECT_NOT_NULL(c, x509_issuer_name))
goto out;
x509_issuer_name_der_size = i2d_X509_NAME(x509_issuer_name, NULL);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_issuer_name_der_size, >, 0))
goto out;
x509_issuer_name_der = OPENSSL_malloc(x509_issuer_name_der_size);
if (!ADBG_EXPECT_NOT_NULL(c, x509_issuer_name_der))
goto out;
p = x509_issuer_name_der;
x509_issuer_name_der_size = i2d_X509_NAME(x509_issuer_name, &p);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_issuer_name_der_size, >, 0))
goto out;
/* Extract certificate's serial number */
x509_serial_number = X509_get_serialNumber(x509_cert);
if (!ADBG_EXPECT_NOT_NULL(c, x509_serial_number))
goto out;
x509_serial_number_der_size = i2d_ASN1_INTEGER(x509_serial_number, NULL);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_serial_number_der_size, >, 0))
goto out;
x509_serial_number_der = OPENSSL_malloc(x509_serial_number_der_size);
if (!ADBG_EXPECT_NOT_NULL(c, x509_serial_number_der))
goto out;
p = x509_serial_number_der;
x509_serial_number_der_size = i2d_ASN1_INTEGER(x509_serial_number, &p);
if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_serial_number_der_size, >, 0))
goto out;
/* Create the actual object in session */
assert(certificate_object[7].type == CKA_VALUE);
certificate_object[7].pValue = x509_cert_der;
certificate_object[7].ulValueLen = x509_cert_der_size;
assert(certificate_object[8].type == CKA_ISSUER);
certificate_object[8].pValue = x509_issuer_name_der;
certificate_object[8].ulValueLen = x509_issuer_name_der_size;
assert(certificate_object[9].type == CKA_SUBJECT);
certificate_object[9].pValue = x509_subject_name_der;
certificate_object[9].ulValueLen = x509_subject_name_der_size;
assert(certificate_object[10].type == CKA_SERIAL_NUMBER);
certificate_object[10].pValue = x509_serial_number_der;
certificate_object[10].ulValueLen = x509_serial_number_der_size;
rv = C_CreateObject(session, certificate_object,
ARRAY_SIZE(certificate_object), &obj_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DestroyObject(session, obj_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Import X.509 Certificate with default values");
/* Create the actual object in session */
assert(certificate_object2[5].type == CKA_VALUE);
certificate_object2[5].pValue = x509_cert_der;
certificate_object2[5].ulValueLen = x509_cert_der_size;
assert(certificate_object2[6].type == CKA_ISSUER);
certificate_object2[6].pValue = x509_issuer_name_der;
certificate_object2[6].ulValueLen = x509_issuer_name_der_size;
assert(certificate_object2[7].type == CKA_SUBJECT);
certificate_object2[7].pValue = x509_subject_name_der;
certificate_object2[7].ulValueLen = x509_subject_name_der_size;
assert(certificate_object2[8].type == CKA_SERIAL_NUMBER);
certificate_object2[8].pValue = x509_serial_number_der;
certificate_object2[8].ulValueLen = x509_serial_number_der_size;
rv = C_CreateObject(session, certificate_object2,
ARRAY_SIZE(certificate_object2), &obj_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
rv = C_DestroyObject(session, obj_hdl);
if (!ADBG_EXPECT_CK_OK(c, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Try import with invalid category");
/* Create the actual object in session */
assert(invalid_category_object[6].type == CKA_VALUE);
invalid_category_object[6].pValue = x509_cert_der;
invalid_category_object[6].ulValueLen = x509_cert_der_size;
assert(invalid_category_object[7].type == CKA_ISSUER);
invalid_category_object[7].pValue = x509_issuer_name_der;
invalid_category_object[7].ulValueLen = x509_issuer_name_der_size;
assert(invalid_category_object[8].type == CKA_SUBJECT);
invalid_category_object[8].pValue = x509_subject_name_der;
invalid_category_object[8].ulValueLen = x509_subject_name_der_size;
assert(invalid_category_object[9].type == CKA_SERIAL_NUMBER);
invalid_category_object[9].pValue = x509_serial_number_der;
invalid_category_object[9].ulValueLen = x509_serial_number_der_size;
rv = C_CreateObject(session, invalid_category_object,
ARRAY_SIZE(invalid_category_object), &obj_hdl);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Try import with invalid category size");
/* Create the actual object in session */
assert(invalid_category_object2[6].type == CKA_VALUE);
invalid_category_object2[6].pValue = x509_cert_der;
invalid_category_object2[6].ulValueLen = x509_cert_der_size;
assert(invalid_category_object2[7].type == CKA_ISSUER);
invalid_category_object2[7].pValue = x509_issuer_name_der;
invalid_category_object2[7].ulValueLen = x509_issuer_name_der_size;
assert(invalid_category_object2[8].type == CKA_SUBJECT);
invalid_category_object2[8].pValue = x509_subject_name_der;
invalid_category_object2[8].ulValueLen = x509_subject_name_der_size;
assert(invalid_category_object2[9].type == CKA_SERIAL_NUMBER);
invalid_category_object2[9].pValue = x509_serial_number_der;
invalid_category_object2[9].ulValueLen = x509_serial_number_der_size;
rv = C_CreateObject(session, invalid_category_object2,
ARRAY_SIZE(invalid_category_object2), &obj_hdl);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv))
goto out;
Do_ADBG_EndSubCase(c, NULL);
Do_ADBG_BeginSubCase(c, "Try import with invalid name hash alg size");
/* Create the actual object in session */
assert(invalid_name_hash_alg_size[6].type == CKA_VALUE);
invalid_name_hash_alg_size[6].pValue = x509_cert_der;
invalid_name_hash_alg_size[6].ulValueLen = x509_cert_der_size;
assert(invalid_name_hash_alg_size[7].type == CKA_ISSUER);
invalid_name_hash_alg_size[7].pValue = x509_issuer_name_der;
invalid_name_hash_alg_size[7].ulValueLen = x509_issuer_name_der_size;
assert(invalid_name_hash_alg_size[8].type == CKA_SUBJECT);
invalid_name_hash_alg_size[8].pValue = x509_subject_name_der;
invalid_name_hash_alg_size[8].ulValueLen = x509_subject_name_der_size;
assert(invalid_name_hash_alg_size[9].type == CKA_SERIAL_NUMBER);
invalid_name_hash_alg_size[9].pValue = x509_serial_number_der;
invalid_name_hash_alg_size[9].ulValueLen = x509_serial_number_der_size;
rv = C_CreateObject(session, invalid_name_hash_alg_size,
ARRAY_SIZE(invalid_name_hash_alg_size), &obj_hdl);
if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv))
goto out;
out:
OPENSSL_free(x509_serial_number_der);
OPENSSL_free(x509_issuer_name_der);
OPENSSL_free(x509_subject_name_der);
OPENSSL_free(x509_cert_der);
X509_free(x509_cert);
BIO_free(x509_bio);
Do_ADBG_EndSubCase(c, NULL);
close_session:
ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
close_lib:
ADBG_EXPECT_CK_OK(c, close_lib());
#endif
}
ADBG_CASE_DEFINE(pkcs11, 1024, xtest_pkcs11_test_1024,
"PKCS11: X509 Certificate operations");