summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/check.c61
-rw-r--r--src/info.c241
-rw-r--r--src/module.c64
-rw-r--r--src/p11-tests.c5
-rw-r--r--src/p11-tests.h42
6 files changed, 394 insertions, 21 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index d8cbb2d..6b24785 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,6 +4,8 @@ bin_PROGRAMS = p11-tests
p11_tests_LDADD = -ldl
p11_tests_SOURCES = \
+ check.c \
+ info.c \
module.c \
msg.c \
p11-tests.c
diff --git a/src/check.c b/src/check.c
new file mode 100644
index 0000000..61cee45
--- /dev/null
+++ b/src/check.c
@@ -0,0 +1,61 @@
+
+#include "config.h"
+
+#include "p11-tests.h"
+
+int
+p11t_check_returns(const char *message, CK_RV have, CK_RV want)
+{
+ if(have != want)
+ {
+ p11t_msg_print("%s: expected %s but got %s", message,
+ p11t_msg_rv(want), p11t_msg_rv(have));
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+p11t_check_padded_len(const char *message, const CK_UTF8CHAR_PTR padded,
+ CK_ULONG length)
+{
+ CK_ULONG i;
+
+ for(i = 0; i < length; ++i)
+ {
+ if(!padded[i])
+ {
+ p11t_msg_print("%s: not blank padded", message);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int
+p11t_check_ulong(const char *message, CK_ULONG have, CK_ULONG want)
+{
+ if(have != want)
+ {
+ p11t_msg_print("%s: expected 0x%08x but have 0x%08x", message,
+ want, have);
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+p11t_check_mask(const char *message, CK_ULONG flags, CK_ULONG mask)
+{
+ if((flags & ~mask) != 0)
+ {
+ p11t_msg_print("%s: extra flags outside of mask: 0x08x",
+ (flags & ~mask));
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/src/info.c b/src/info.c
new file mode 100644
index 0000000..0071431
--- /dev/null
+++ b/src/info.c
@@ -0,0 +1,241 @@
+
+#include "config.h"
+
+#include "p11-tests.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+CK_INFO p11t_info_global;
+
+CK_ULONG p11t_info_slot_count = 0;
+CK_SLOT_ID_PTR p11t_info_slot_ids = NULL;
+CK_SLOT_INFO_PTR p11t_info_slot_info = NULL;
+CK_TOKEN_INFO_PTR p11t_info_token_info = NULL;
+
+CK_ULONG p11t_info_mech_count = 0;
+CK_MECHANISM_TYPE_PTR p11t_info_mech_types = NULL;
+CK_MECHANISM_INFO_PTR p11t_info_mech_info = NULL;
+
+void
+info_global(void)
+{
+ CK_RV rv;
+
+ /** C_GetInfo */
+
+ assert(p11t_module_funcs);
+
+ /** - NULL argument */
+ rv = (p11t_module_funcs->C_GetInfo)(NULL);
+ p11t_check_returns("C_GetInfo", rv, CKR_ARGUMENTS_BAD);
+
+ /* Obvious crap fill */
+ memset(&p11t_info_global, 0xFF, sizeof(CK_INFO));
+
+ /** - Normal call */
+ rv = (p11t_module_funcs->C_GetInfo)(&p11t_info_global);
+ if(p11t_check_returns("C_GetInfo", rv, CKR_OK))
+ {
+ memset(&p11t_info_global, 0, sizeof(CK_INFO));
+ return;
+ }
+
+ /** - Cryptoki version matches that in library entry point data */
+ if(memcmp(&p11t_info_global.cryptokiVersion, &p11t_module_funcs->version, sizeof(CK_VERSION)) != 0)
+ p11t_msg_print("version from CK_INFO.cryptokiVersion does not match from CK_FUNCTION_LIST.version");
+
+ /** - Space padded strings in CK_INFO */
+ p11t_check_padded("CK_INFO.manufacturerID", p11t_info_global.manufacturerID);
+ p11t_check_padded("CK_INFO.libraryDescription", p11t_info_global.libraryDescription);
+
+ /** - No flags set */
+ p11t_check_ulong("CK_INFO.flags", p11t_info_global.flags, 0);
+}
+
+int
+compar_slot_id(const void *one, const void *two)
+{
+ CK_SLOT_ID a = *((CK_SLOT_ID*)one);
+ CK_SLOT_ID b = *((CK_SLOT_ID*)two);
+ if(a == b)
+ return 0;
+ if(a > b)
+ return 1;
+ return -1;
+}
+
+void
+info_slots(void)
+{
+ CK_SLOT_ID_PTR present, only;
+ CK_ULONG n_present, n_only, count;
+ CK_ULONG i;
+ CK_RV rv;
+
+ /** C_GetSlotList */
+
+ assert(p11t_module_funcs);
+
+ /** - NULL arguments */
+ rv = (p11t_module_funcs->C_GetSlotList)(FALSE, NULL, NULL);
+ p11t_check_returns("C_GetSlotList", rv, CKR_ARGUMENTS_BAD);
+
+ /** - Retrieving the count */
+ rv = (p11t_module_funcs->C_GetSlotList)(FALSE, NULL, &p11t_info_slot_count);
+ p11t_check_returns("C_GetSlotList", rv, CKR_OK);
+
+ if(p11t_info_slot_count == 0)
+ {
+ p11t_msg_print("no slots to test");
+ return;
+ }
+
+ /* Allocate a bit extra. We're going to try and trip up module */
+ p11t_info_slot_ids = calloc(p11t_info_slot_count + 5, sizeof(CK_SLOT_ID));
+ assert(p11t_info_slot_ids);
+
+ p11t_info_slot_info = calloc(p11t_info_slot_count, sizeof(CK_SLOT_INFO));
+ assert(p11t_info_slot_info);
+
+ p11t_info_token_info = calloc(p11t_info_slot_count, sizeof(CK_TOKEN_INFO));
+ assert(p11t_info_token_info);
+
+ /** - Passing buffer space along with zero count. */
+ count = 0;
+ rv = (p11t_module_funcs->C_GetSlotList)(FALSE, p11t_info_slot_ids, &count);
+ p11t_check_returns("C_GetSlotList", rv, CKR_BUFFER_TOO_SMALL);
+ p11t_check_ulong("Count invalid zero space passed to C_GetSlotList", count, p11t_info_slot_count);
+
+ if(p11t_info_slot_count > 1)
+ {
+ /** - Passing buffer space along with low count. */
+ count = 1;
+ rv = (p11t_module_funcs->C_GetSlotList)(FALSE, p11t_info_slot_ids, &count);
+ p11t_check_returns("C_GetSlotList", rv, CKR_BUFFER_TOO_SMALL);
+ p11t_check_ulong("Count invalid when too little space passed to C_GetSlotList", count, p11t_info_slot_count);
+ }
+
+ /** - Passing too much buffer space. */
+ count = p11t_info_slot_ids + 5;
+ rv = (p11t_module_funcs->C_GetSlotList)(FALSE, p11t_info_slot_ids, &count);
+ if(!p11t_check_returns("C_GetSlotList", rv, CKR_OK))
+ {
+ p11t_info_slot_count = 0;
+ return;
+ }
+
+ p11t_check_ulong("Count invalid when too much space passed to C_GetSlotList", count, p11t_info_slot_count);
+
+ /* When we ask for just token valid ones, they should only be the ones we noted with flags */
+ present = calloc(p11t_info_slot_count, sizeof(CK_SLOT_ID));
+ only = calloc(p11t_info_slot_count, sizeof(CK_SLOT_ID));
+ assert(present && only);
+ n_present = 0;
+
+ /* Now go through and load info about each slot */
+ for(i = 0; i < p11t_info_slot_count; ++i)
+ {
+ /** C_GetSlotInfo */
+
+ /** - NULL argument */
+ rv = (p11t_module_funcs->C_GetSlotInfo)(p11t_info_slot_ids[i], NULL);
+ p11t_check_returns("C_GetSlotInfo", rv, CKR_ARGUMENTS_BAD);
+
+ /** - Normal call */
+ rv = (p11t_module_funcs->C_GetSlotInfo)(p11t_info_slot_ids[i], &p11t_info_slot_info[i]);
+ p11t_check_returns("C_GetSlotInfo", rv, CKR_OK);
+
+ /** - Space padded CK_SLOT_INFO fields */
+ p11t_check_padded("CK_SLOT_INFO.slotDescription", p11t_info_slot_info[i].slotDescription);
+ p11t_check_padded("CK_SLOT_INFO.manufacturerID", p11t_info_slot_info[i].manufacturerID);
+
+ /** - CK_SLOT_INFO flags are from valid set */
+ p11t_check_mask("CK_SLOT_INFO.flags", p11t_info_slot_info[i].flags,
+ CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT);
+
+ /** - Track CKF_TOKEN_PRESENT flag and compare to C_GetSlotList(TRUE) */
+ if((p11t_info_slot_info[i].flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT)
+ {
+ /* Note if token is present for later */
+ present[n_present++] = p11t_info_slot_ids[i];
+
+ /** C_GetTokenInfo */
+
+ /** - Null arguments */
+ rv = (p11t_module_funcs->C_GetTokenInfo)(p11t_info_slot_ids[i], NULL);
+ p11t_check_returns("C_GetSlotInfo", rv, CKR_ARGUMENTS_BAD);
+
+ /** - Normal call */
+ rv = (p11t_module_funcs->C_GetTokenInfo)(p11t_info_slot_ids[i], &p11t_info_token_info[i]);
+ p11t_check_returns("C_GetSlotInfo", rv, CKR_OK);
+
+ /** - Space padded CK_TOKEN_INFO fields */
+ p11t_check_padded("CK_TOKEN_INFO.label", p11t_info_token_info[i].label);
+ p11t_check_padded("CK_TOKEN_INFO.manufacturerID", p11t_info_token_info[i].manufacturerID);
+ p11t_check_padded("CK_TOKEN_INFO.model", p11t_info_token_info[i].model);
+ p11t_check_padded("CK_TOKEN_INFO.serialNumber", p11t_info_token_info[i].serialNumber);
+
+ /** - CK_TOKEN_INFO flags are from valid set */
+ p11t_check_mask("CK_TOKEN_INFO.flags", p11t_info_token_info[i].flags,
+ CKF_RNG | CKF_WRITE_PROTECTED | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED |
+ CKF_RESTORE_KEY_NOT_NEEDED | CKF_CLOCK_ON_TOKEN | CKF_PROTECTED_AUTHENTICATION_PATH |
+ CKF_DUAL_CRYPTO_OPERATIONS | CKF_TOKEN_INITIALIZED | CKF_SECONDARY_AUTHENTICATION |
+ CKF_USER_PIN_COUNT_LOW | CKF_USER_PIN_FINAL_TRY | CKF_USER_PIN_LOCKED |
+ CKF_USER_PIN_TO_BE_CHANGED | CKF_SO_PIN_COUNT_LOW | CKF_SO_PIN_FINAL_TRY |
+ CKF_SO_PIN_LOCKED | CKF_SO_PIN_TO_BE_CHANGED);
+
+ /* Can't validate all the statistics, any number is valid */
+
+ /** - Validate token time when CKF_CLOCK_ON_TOKEN */
+ if((p11t_info_token_info[i].flags & CKF_CLOCK_ON_TOKEN) == CKF_CLOCK_ON_TOKEN)
+ {
+ int year, month, day, hour, minute, second, extra, n;
+ char buffer[sizeof(p11t_info_token_info[i].utcTime) + 1];
+
+ memcpy(buffer, (char*)p11t_info_token_info[i].utcTime,
+ sizeof(p11t_info_token_info[i].utcTime));
+ buffer[sizeof(p11t_info_token_info[i].utcTime)] = 0;
+
+ n = sscanf(buffer, "%04d%02d%02d%02d%02d%02d%02d",
+ &year, &month, &day, &hour, &minute, &second, &extra);
+
+ if(n != 7 ||
+ year < 0 || year > 9999 ||
+ month < 1 || month > 12 ||
+ day < 1 || day > 31 ||
+ hour < 0 || hour > 23 ||
+ minute < 0 || minute > 59 ||
+ second < 0 || second > 50 ||
+ extra != 0)
+ {
+ p11t_msg_print("invalid time on token: %s", buffer);
+ }
+ }
+ }
+ else
+ {
+ /** - Calling on slot without token */
+ rv = (p11t_module_funcs->C_GetTokenInfo)(p11t_info_slot_ids[i], &p11t_info_token_info[i]);
+ p11t_check_returns("C_GetSlotInfo", rv, CKR_TOKEN_NOT_PRESENT);
+ }
+ }
+
+ rv = (p11t_module_funcs->C_GetSlotList)(TRUE, only, &n_only);
+ p11t_check_returns("C_GetSlotList (only tokens)", rv, CKR_OK);
+
+ p11t_check_ulong("number of present tokens doesn't match token info flags. ie: CKF_TOKEN_PRESENT", n_only, n_present);
+
+ qsort(only, n_only, sizeof(CK_SLOT_ID), compar_slot_id);
+ qsort(present, n_present, sizeof(CK_SLOT_ID), compar_slot_id);
+ if(memcmp(only, present, sizeof(CK_SLOT_ID) * n_only) != 0)
+ p11t_msg_print("present tokens don't match those in token info flags. ie: CKF_TOKEN_PRESENT");
+}
+
+void
+p11t_info_tests(void)
+{
+ info_global();
+ info_slots();
+}
diff --git a/src/module.c b/src/module.c
index 8677c22..c20bd3c 100644
--- a/src/module.c
+++ b/src/module.c
@@ -10,7 +10,7 @@
#include <string.h>
static void *module = NULL;
-CK_FUNCTION_LIST_PTR p11_funcs = NULL;
+CK_FUNCTION_LIST_PTR p11t_module_funcs = NULL;
static CK_C_INITIALIZE_ARGS init_args;
static int is_initialized = 0;
@@ -144,6 +144,7 @@ unlock_mutex (void *mutex)
void
p11t_module_load(const char *filename)
{
+ CK_FUNCTION_LIST_PTR list;
CK_C_GetFunctionList get_function_list;
CK_RV rv;
@@ -157,15 +158,24 @@ p11t_module_load(const char *filename)
p11t_msg_fatal("couldn't find C_GetFunctionList function in library: %s: %s", filename, dlerror());
/* Get the function list */
- rv = (get_function_list)(&p11_funcs);
+ rv = (get_function_list)(&p11t_module_funcs);
if(rv != CKR_OK)
p11t_msg_fatal("couldn't get function list: %s", p11t_msg_rv(rv));
/* Make sure we have a compatible version */
- if(p11_funcs->version.major != CRYPTOKI_VERSION_MAJOR)
+ if(p11t_module_funcs->version.major != CRYPTOKI_VERSION_MAJOR)
p11t_msg_fatal("incompatible version of pkcs11 module: %d.%d",
- (int)p11_funcs->version.major,
- (int)p11_funcs->version.minor);
+ (int)p11t_module_funcs->version.major,
+ (int)p11t_module_funcs->version.minor);
+
+ /** C_GetFunctionList */
+ rv = (p11t_module_funcs->C_GetFunctionList)(&list);
+ if(rv != CKR_OK)
+ p11t_msg_print("C_GetFunctionList call through function list failed: %s", p11t_msg_rv(rv));
+
+ /** - See if returns same data as library entry point */
+ if(!memcmp(list, p11t_module_funcs, sizeof(*list)) != 0)
+ p11t_msg_print("function lists returned directly and recursively differ");
}
static void
@@ -173,9 +183,12 @@ initialize_common(const char *mode)
{
CK_RV rv;
- assert(p11_funcs);
+ /** C_Initialize **/
+
+ assert(p11t_module_funcs);
- rv = (p11_funcs->C_Initialize) (&init_args);
+ /** - Normal call */
+ rv = (p11t_module_funcs->C_Initialize) (&init_args);
if (rv != CKR_OK)
{
if(rv != CKR_CANT_LOCK)
@@ -190,6 +203,7 @@ initialize_common(const char *mode)
static void
initialize_locking_1(const char *initstr)
{
+ /** - Locking: no threads */
memset(&init_args, 0, sizeof (init_args));
init_args.pReserved = (void*)initstr;
initialize_common("locking mode 1: no threads");
@@ -198,6 +212,7 @@ initialize_locking_1(const char *initstr)
static void
initialize_locking_2(const char *initstr)
{
+ /** - Locking: os locking */
memset(&init_args, 0, sizeof (init_args));
init_args.flags = CKF_OS_LOCKING_OK;
init_args.pReserved = (void*)initstr;
@@ -207,6 +222,7 @@ initialize_locking_2(const char *initstr)
static void
initialize_locking_3(const char *initstr)
{
+ /** - Locking: app locking */
memset(&init_args, 0, sizeof (init_args));
init_args.flags = 0;
init_args.CreateMutex = create_mutex;
@@ -220,6 +236,7 @@ initialize_locking_3(const char *initstr)
static void
initialize_locking_4(const char *initstr)
{
+ /** - Locking: either locking */
memset(&init_args, 0, sizeof (init_args));
init_args.flags = CKF_OS_LOCKING_OK;
init_args.CreateMutex = create_mutex;
@@ -236,14 +253,18 @@ p11t_module_initialize(const char *initstr)
CK_INFO info;
CK_RV rv;
- assert(p11_funcs);
+ assert(p11t_module_funcs);
- /* Some invalid use without initializing */
- rv = (p11_funcs->C_GetInfo)(&info);
- if(rv != CKR_CRYPTOKI_NOT_INITIALIZED)
- p11t_msg_print("shouldn't run without initialize: %s", p11t_msg_rv(rv));
+ /** - Calls without initializing */
+ rv = (p11t_module_funcs->C_GetInfo)(&info);
+ p11t_check_returns("shouldn't run without initialize: %s", rv, CKR_CRYPTOKI_NOT_INITIALIZED);
- /* The various different locking modes */
+ /** - NULL argument */
+ rv = (p11t_module_funcs->C_Initialize) (NULL);
+ p11t_check_returns("should succeed with null argument", rv, CKR_OK);
+ p11t_module_finalize();
+
+ /** - Multiple initialize with C_Finalize between */
initialize_locking_1(initstr);
p11t_module_finalize();
initialize_locking_2(initstr);
@@ -255,8 +276,8 @@ p11t_module_initialize(const char *initstr)
if(!is_initialized)
p11t_msg_fatal("liberal locking strategy failed, can't continue");
- /* Double initialize */
- rv = (p11_funcs->C_Initialize) (&init_args);
+ /** - Double initialize in a row */
+ rv = (p11t_module_funcs->C_Initialize) (&init_args);
if (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)
{
p11t_msg_print("double initialize should return CKR_CRYPTOKI_ALREADY_INITIALIZED: %s", p11t_msg_rv(rv));
@@ -272,14 +293,19 @@ p11t_module_finalize(void)
{
CK_RV rv;
+ /** C_Finalize */
if(is_initialized)
{
- assert(p11_funcs);
- rv = p11_funcs->C_Finalize(NULL);
- if(rv != CKR_OK)
- p11t_msg_print("C_Finalize failed: %s", p11t_msg_rv(rv));
+ /** - Normal call */
+ assert(p11t_module_funcs);
+ rv = p11t_module_funcs->C_Finalize(NULL);
+ p11t_check_returns("C_Finalize", rv, CKR_OK);
is_initialized = 0;
}
+
+ /** - Double finalize in a row */
+ rv = p11t_module_funcs->C_Finalize(NULL);
+ p11t_check_returns("C_Finalize", rv, CKR_CRYPTOKI_NOT_INITIALIZED);
}
void
diff --git a/src/p11-tests.c b/src/p11-tests.c
index b871533..bb67dd7 100644
--- a/src/p11-tests.c
+++ b/src/p11-tests.c
@@ -35,9 +35,14 @@ main(int argc, char* argv[])
if(argc < 1 || argc > 2)
usage();
+ /* Basic module tests */
p11t_module_load(argv[0]);
p11t_module_initialize(argc == 2 ? argv[1] : NULL);
+ p11t_info_tests();
+
+ /* Remaining module tests */
+ p11t_module_finalize();
p11t_module_unload();
return 0;
diff --git a/src/p11-tests.h b/src/p11-tests.h
index cf37346..89b856c 100644
--- a/src/p11-tests.h
+++ b/src/p11-tests.h
@@ -7,7 +7,7 @@
#include <stdarg.h>
/* -------------------------------------------------------------------
- * message.c
+ * msg.c
*/
const char* p11t_msg_rv(CK_RV rv);
@@ -17,13 +17,51 @@ void p11t_msg_print(const char *message, ...);
void p11t_msg_fatal(const char *message, ...);
void p11t_msg_prefix(const char *prefix);
+#define p11t_msg_here() \
+ (__func__ "() at " __FILE__ ":" __LINE__)
+
+/* -------------------------------------------------------------------
+ * check.c
+ */
+
+int p11t_check_returns(const char *message, CK_RV have, CK_RV want);
+
+#define p11t_check_padded(msg, padded) \
+ (p11t_check_padded_len((msg), (padded), sizeof(padded)))
+
+int p11t_check_padded_len(const char *message, const CK_UTF8CHAR_PTR padded, CK_ULONG length);
+
+int p11t_check_ulong(const char *message, CK_ULONG have, CK_ULONG want);
+
+int p11t_check_mask(const char *message, CK_ULONG flags, CK_ULONG mask);
+
+/* -------------------------------------------------------------------
+ * info.c
+ */
+
+extern CK_INFO p11t_info_global;
+
+extern CK_ULONG p11t_info_slot_count;
+extern CK_SLOT_ID_PTR p11t_info_slot_ids;
+extern CK_SLOT_INFO_PTR p11t_info_slot_info;
+extern CK_TOKEN_INFO_PTR p11t_info_token_info;
+
+extern CK_ULONG p11t_info_mech_count;
+extern CK_MECHANISM_TYPE_PTR p11t_info_mech_types;
+extern CK_MECHANISM_INFO_PTR p11t_info_mech_info;
+
+void p11t_info_tests(void);
+
/* -------------------------------------------------------------------
* module.c
*/
+extern CK_FUNCTION_LIST_PTR p11t_module_funcs;
+
void p11t_module_load(const char *filename);
+void p11t_module_unload(void);
+
void p11t_module_initialize(const char *initstr);
void p11t_module_finalize(void);
-void p11t_module_unload(void);
#endif /* P11TESTST_H_ */