#include "config.h" #include "p11-tests.h" #include #include #include CK_INFO p11t_slot_global; CK_ULONG p11t_slot_count = 0; CK_SLOT_ID_PTR p11t_slot_ids = NULL; CK_SLOT_INFO_PTR p11t_slot_info = NULL; CK_TOKEN_INFO_PTR p11t_slot_token_info = NULL; CK_ULONG *p11t_slot_mech_count; CK_MECHANISM_INFO_PTR *p11t_slot_mech_info; void slot_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_slot_global, 0xFF, sizeof(CK_INFO)); /** - Normal call */ rv = (p11t_module_funcs->C_GetInfo)(&p11t_slot_global); if(p11t_check_returns("C_GetInfo", rv, CKR_OK)) { memset(&p11t_slot_global, 0, sizeof(CK_INFO)); return; } /** - Cryptoki version matches that in library entry point data */ if(memcmp(&p11t_slot_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_slot_global.manufacturerID); p11t_check_padded("CK_INFO.libraryDescription", p11t_slot_global.libraryDescription); /** - No flags set */ p11t_check_ulong("CK_INFO.flags", p11t_slot_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 slot_info(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_slot_count); p11t_check_returns("C_GetSlotList", rv, CKR_OK); if(p11t_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_slot_ids = calloc(p11t_slot_count + 5, sizeof(CK_SLOT_ID)); assert(p11t_slot_ids); p11t_slot_info = calloc(p11t_slot_count, sizeof(CK_SLOT_INFO)); assert(p11t_slot_info); p11t_slot_token_info = calloc(p11t_slot_count, sizeof(CK_TOKEN_INFO)); assert(p11t_slot_token_info); /** - Passing buffer space along with zero count. */ count = 0; rv = (p11t_module_funcs->C_GetSlotList)(FALSE, p11t_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_slot_count); if(p11t_slot_count > 1) { /** - Passing buffer space along with low count. */ count = 1; rv = (p11t_module_funcs->C_GetSlotList)(FALSE, p11t_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_slot_count); } /** - Passing too much buffer space. */ count = p11t_slot_count + 5; rv = (p11t_module_funcs->C_GetSlotList)(FALSE, p11t_slot_ids, &count); if(!p11t_check_returns("C_GetSlotList", rv, CKR_OK)) { p11t_slot_count = 0; return; } p11t_check_ulong("Count invalid when too much space passed to C_GetSlotList", count, p11t_slot_count); /* When we ask for just token valid ones, they should only be the ones we noted with flags */ present = calloc(p11t_slot_count, sizeof(CK_SLOT_ID)); only = calloc(p11t_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_slot_count; ++i) { /** C_GetSlotInfo */ /** - NULL argument */ rv = (p11t_module_funcs->C_GetSlotInfo)(p11t_slot_ids[i], NULL); p11t_check_returns("C_GetSlotInfo", rv, CKR_ARGUMENTS_BAD); /** - Normal call */ rv = (p11t_module_funcs->C_GetSlotInfo)(p11t_slot_ids[i], &p11t_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_slot_info[i].slotDescription); p11t_check_padded("CK_SLOT_INFO.manufacturerID", p11t_slot_info[i].manufacturerID); /** - CK_SLOT_INFO flags are from valid set */ p11t_check_mask("CK_SLOT_INFO.flags", p11t_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_slot_info[i].flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT) { /* Note if token is present for later */ present[n_present++] = p11t_slot_ids[i]; /** C_GetTokenInfo */ /** - Null arguments */ rv = (p11t_module_funcs->C_GetTokenInfo)(p11t_slot_ids[i], NULL); p11t_check_returns("C_GetSlotInfo", rv, CKR_ARGUMENTS_BAD); /** - Normal call */ rv = (p11t_module_funcs->C_GetTokenInfo)(p11t_slot_ids[i], &p11t_slot_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_slot_token_info[i].label); p11t_check_padded("CK_TOKEN_INFO.manufacturerID", p11t_slot_token_info[i].manufacturerID); p11t_check_padded("CK_TOKEN_INFO.model", p11t_slot_token_info[i].model); p11t_check_padded("CK_TOKEN_INFO.serialNumber", p11t_slot_token_info[i].serialNumber); /** - CK_TOKEN_INFO flags are from valid set */ p11t_check_mask("CK_TOKEN_INFO.flags", p11t_slot_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_slot_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_slot_token_info[i].utcTime) + 1]; memcpy(buffer, (char*)p11t_slot_token_info[i].utcTime, sizeof(p11t_slot_token_info[i].utcTime)); buffer[sizeof(p11t_slot_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_slot_ids[i], &p11t_slot_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 slot_events(void) { /** C_WaitForSlotEvent */ /** - Not Implemented */ } void slot_mechanisms(void) { CK_MECHANISM_TYPE_PTR mech_list; CK_MECHANISM_INFO_PTR mech_info; CK_SLOT_ID slot_id; CK_ULONG mech_count, value; CK_ULONG i, j; CK_RV rv; assert(p11t_module_funcs); /** C_GetMechanismList */ if(!p11t_slot_count) return; /* - Invalid Slot */ mech_count = 0; rv = (p11t_module_funcs->C_GetMechanismList)((CK_ULONG)-10, NULL, &mech_count); p11t_check_returns("C_GetMechanismList invalid slot id", rv, CKR_SLOT_ID_INVALID); p11t_slot_mech_count = calloc(p11t_slot_count, sizeof(CK_ULONG)); assert(p11t_slot_mech_count); p11t_slot_mech_info = calloc(p11t_slot_count, sizeof(CK_MECHANISM_INFO_PTR)); assert(p11t_slot_mech_info); for(i = 0; i < p11t_slot_count; ++i) { slot_id = p11t_slot_ids[i]; /** - Null arguments */ rv = (p11t_module_funcs->C_GetMechanismList)(slot_id, NULL, NULL); p11t_check_returns("C_GetMechanismList null arguments", rv, CKR_ARGUMENTS_BAD); /** - Without buffer */ rv = (p11t_module_funcs->C_GetMechanismList)(slot_id, NULL, &mech_count); p11t_check_returns("C_GetMechanismList without buffer", rv, CKR_OK); if(mech_count > 0) { mech_list = calloc(mech_count + 5, sizeof(CK_MECHANISM_TYPE)); assert(mech_list); /** - Zero count but buffer present */ value = 0; rv = (p11t_module_funcs->C_GetMechanismList)(slot_id, mech_list, &value); p11t_check_returns("C_GetMechanismList zero buffer", rv, CKR_BUFFER_TOO_SMALL); p11t_check_ulong("should have number of mechs", value, mech_count); if(mech_count > 1) { /** - Low count but buffer present */ value = 1; rv = (p11t_module_funcs->C_GetMechanismList)(slot_id, mech_list, &value); p11t_check_returns("C_GetMechanismList low buffer", rv, CKR_BUFFER_TOO_SMALL); p11t_check_ulong("should have number of mechs", value, mech_count); } /* - Call with too much buffer */ value = mech_count + 5; rv = (p11t_module_funcs->C_GetMechanismList)(slot_id, mech_list, &value); p11t_check_returns("C_GetMechanismList high buffer", rv, CKR_OK); p11t_check_ulong("should have number of mechs", value, mech_count); mech_info = calloc(mech_count, sizeof(CK_MECHANISM_INFO)); assert(mech_info); /** C_GetMechanismInfo */ /** - Invalid mechanism */ rv = (p11t_module_funcs->C_GetMechanismInfo)(slot_id, (CK_ULONG)-10, mech_info); p11t_check_returns("C_GetMechanismInfo with invalid mech", rv, CKR_MECHANISM_INVALID); /** - Null arguments */ rv = (p11t_module_funcs->C_GetMechanismInfo)(slot_id, mech_list[0], NULL); p11t_check_returns("C_GetMechanismInfo with null arg", rv, CKR_ARGUMENTS_BAD); /** - Invalid slot id */ rv = (p11t_module_funcs->C_GetMechanismInfo)((CK_ULONG)-11, mech_list[0], mech_info); p11t_check_returns("C_GetMechanismInfo with invalid slot", rv, CKR_SLOT_ID_INVALID); for(j = 0; j < mech_count; ++j) { /** - Normal call */ rv = (p11t_module_funcs->C_GetMechanismInfo)(slot_id, mech_list[i], &mech_info[i]); p11t_check_returns("C_GetMechanismInfo", rv, CKR_OK); if(mech_info[i].ulMinKeySize > mech_info[i].ulMaxKeySize) p11t_msg_print("Mechanism min key size is greater than max"); p11t_check_mask("CK_MECHANISM_INFO.flags", mech_info[i].flags, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_DIGEST | CKF_SIGN | CKF_SIGN_RECOVER | CKF_VERIFY | CKF_VERIFY_RECOVER | CKF_GENERATE | CKF_GENERATE_KEY_PAIR | CKF_WRAP | CKF_UNWRAP | CKF_DERIVE); p11t_check_nflag("CK_MECHANISM_INFO.flags", mech_info[i].flags, CKF_EXTENSION); } p11t_slot_mech_info[i] = mech_info; } p11t_slot_mech_count[i] = mech_count; } } void slot_init_token(void) { /** C_InitToken */ /** - Not Implemented */ } void p11t_slot_tests(void) { slot_global(); slot_info(); slot_events(); slot_mechanisms(); }