From 9d75f49f5818d4cf0f960f2fa113aaefff543df7 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 5 Dec 2008 17:39:21 +0000 Subject: Implement GetAttributeValue tests. --- src/check.c | 30 +++++++ src/module.c | 13 ++- src/object.c | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/p11-tests.h | 7 ++ src/session.c | 28 ++++--- src/slot.c | 8 ++ 6 files changed, 308 insertions(+), 22 deletions(-) diff --git a/src/check.c b/src/check.c index 7e45f5f..01b19fb 100644 --- a/src/check.c +++ b/src/check.c @@ -55,6 +55,36 @@ p11t_check_ulong(const char *message, CK_ULONG have, CK_ULONG want) return 1; } +int +p11t_check_bool(const char *message, CK_BBOOL value) +{ + if(value != CK_FALSE && value != CK_TRUE) + { + p11t_msg_print("%s: expected CK_TRUE or CK_FALSE but got 0x%02x", + message, (int)value); + return 0; + } + + return 1; +} + +int +p11t_check_string(const char *message, CK_UTF8CHAR_PTR value, CK_ULONG length) +{ + CK_ULONG i; + + for(i = 0; i < length; ++i) + { + if(!value[i]) + { + p11t_msg_print("%s: is null terminated", message); + return 0; + } + } + + return 1; +} + int p11t_check_mask(const char *message, CK_ULONG flags, CK_ULONG mask) { diff --git a/src/module.c b/src/module.c index 9e018e7..e47ba38 100644 --- a/src/module.c +++ b/src/module.c @@ -17,6 +17,12 @@ static CK_C_INITIALIZE_ARGS init_args; static void (*init_func)(void) = NULL; static int is_initialized = 0; +void +p11t_module_config(const char *name, const char *value) +{ + if(strcmp(name, "init-string") == 0) + init_string = value; +} static CK_RV create_mutex(void **mutex) @@ -342,10 +348,3 @@ p11t_module_unload(void) dlclose(module); module = NULL; } - -void -p11t_module_config(const char *name, const char *value) -{ - if(strcmp(name, "init-string") == 0) - init_string = value; -} diff --git a/src/object.c b/src/object.c index 450c795..71e6a0d 100644 --- a/src/object.c +++ b/src/object.c @@ -4,6 +4,14 @@ #include "p11-tests.h" #include +#include + +/* An very likey to be invalid attribute */ +#define CKA_INVALID (CKA_VENDOR_DEFINED | 0x00FFFFFF) + +/* ---------------------------------------------------------------------------------- + * TESTS + */ static void create_object(CK_SESSION_HANDLE session_rw, CK_SESSION_HANDLE session_ro) @@ -30,7 +38,7 @@ destroy_object(CK_SESSION_HANDLE session_rw, CK_SESSION_HANDLE session_ro) } static void -find_all_objects(CK_SESSION_HANDLE session) +find_objects(CK_SESSION_HANDLE session) { CK_OBJECT_HANDLE_PTR objects; CK_OBJECT_HANDLE extra; @@ -138,7 +146,185 @@ find_all_objects(CK_SESSION_HANDLE session) rv = (p11t_module_funcs->C_FindObjects)(session, &extra, 1, &count); p11t_check_returns("C_FindObjectsFinal: extra call", rv, CKR_OPERATION_NOT_INITIALIZED); } +} + +static void +test_get_attribute_value(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) +{ + CK_OBJECT_CLASS klass; + CK_ATTRIBUTE attrs[4]; + CK_BYTE buffer[8]; + CK_BBOOL bools[3]; + CK_RV rv; + + assert(p11t_module_funcs); + + /** C_GetAttributeValue */ + + attrs[0].type = CKA_CLASS; + + if(p11t_test_unexpected) + { + /** - Invalid session */ + rv = (p11t_module_funcs->C_GetAttributeValue)((CK_SESSION_HANDLE)-57, object, attrs, 1); + p11t_check_returns("C_GetAttributeValue: invalid session", rv, CKR_SESSION_HANDLE_INVALID); + + /** - Invalid object */ + rv = (p11t_module_funcs->C_GetAttributeValue)(session, (CK_OBJECT_HANDLE)-58, attrs, 1); + p11t_check_returns("C_GetAttributeValue: invalid object", rv, CKR_OBJECT_HANDLE_INVALID); + + /** - No template */ + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, NULL, 0); + p11t_check_returns("C_GetAttributeValue: no template", rv, CKR_ARGUMENTS_BAD); + + /** - Buffer too small */ + attrs[0].pValue = buffer; + attrs[0].ulValueLen = 2; + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 1); + p11t_check_returns("C_GetAttributeValue: buffer too small", rv, CKR_BUFFER_TOO_SMALL); + p11t_check_ulong("C_GetAttributeValue: should return size", attrs[0].ulValueLen, sizeof(CK_OBJECT_CLASS)); + } + + /** - Retrieve attribute length */ + attrs[0].pValue = NULL; + attrs[0].ulValueLen = 0; + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 1); + p11t_check_returns("C_GetAttributeValue: get size", rv, CKR_OK); + p11t_check_ulong("C_GetAttributeValue: size of class", attrs[0].ulValueLen, sizeof(CK_OBJECT_CLASS)); + + /** - Retrieve single attribute */ + attrs[0].pValue = buffer; + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 1); + p11t_check_returns("C_GetAttributeValue: get object", rv, CKR_OK); + /* The actual class of this object */ + klass = *((CK_OBJECT_CLASS*)attrs[0].pValue); + + if(p11t_test_unexpected) + { + /* + * Now we do a bit of testing to retrieve a valid and invalid attribute + * at the same time. + */ + + attrs[0].type = CKA_INVALID; + attrs[1].type = CKA_CLASS; + attrs[0].ulValueLen = attrs[1].ulValueLen = 0; + attrs[0].pValue = attrs[0].pValue = NULL; + + /** - With one invalid attribute, no buffer. */ + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 2); + p11t_check_returns("C_GetAttributeValue: with one invalid attribute", rv, CKR_ATTRIBUTE_TYPE_INVALID); + p11t_check_ulong("C_GetAttributeValue: should set invalid attribute to -1", attrs[0].ulValueLen, CK_INVALID); + p11t_check_ulong("C_GetAttributeValue: should set valid attribute to size", attrs[1].ulValueLen, sizeof(CK_OBJECT_CLASS)); + + /** - With one invalid attribute, with buffer. */ + attrs[1].pValue = buffer; + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 2); + p11t_check_returns("C_GetAttributeValue: with one invalid attribute, buffer", rv, CKR_ATTRIBUTE_TYPE_INVALID); + p11t_check_ulong("C_GetAttributeValue: should set invalid attribute to -1", attrs[0].ulValueLen, CK_INVALID); + p11t_check_ulong("C_GetAttributeValue: should set valid attribute to size", attrs[1].ulValueLen, sizeof(CK_OBJECT_CLASS)); + p11t_check_ulong("C_GetAttributeValue: should set valid attribute", *((CK_OBJECT_CLASS*)attrs[1].pValue), klass); + } + + /* + * Now we do a bit of testing of other attributes and retrieving sets. + * Since we can't list which attributes an object has, we only + * work with 'storage' type attributes and their standard 4 attributes. + */ + + switch(klass) + { + case CKO_CERTIFICATE: + case CKO_DATA: + case CKO_PRIVATE_KEY: + case CKO_PUBLIC_KEY: + case CKO_SECRET_KEY: + break; + default: + return; + } + + memset(attrs, 0, sizeof(attrs)); + attrs[0].type = CKA_CLASS; + attrs[1].type = CKA_TOKEN; + attrs[2].type = CKA_PRIVATE; + attrs[3].type = CKA_MODIFIABLE; + attrs[4].type = CKA_LABEL; + + /** - Multiple attributes, no buffer. */ + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 5); + p11t_check_returns("C_GetAttributeValue: multiple attrs, no buffer", rv, CKR_OK); + p11t_check_ulong("C_GetAttributeValue: CKA_CLASS size", attrs[0].ulValueLen, sizeof(CK_OBJECT_CLASS)); + p11t_check_ulong("C_GetAttributeValue: CKA_TOKEN size", attrs[1].ulValueLen, sizeof(CK_BBOOL)); + p11t_check_ulong("C_GetAttributeValue: CKA_PRIVATE size", attrs[2].ulValueLen, sizeof(CK_BBOOL)); + p11t_check_ulong("C_GetAttributeValue: CKA_MODIFIABLE size", attrs[3].ulValueLen, sizeof(CK_BBOOL)); + + if(attrs[4].ulValueLen) + attrs[4].pValue = malloc(attrs[4].ulValueLen); + attrs[3].pValue = &bools[0]; + attrs[2].pValue = &bools[1]; + attrs[1].pValue = &bools[2]; + + if(p11t_test_unexpected) + { + /** - Multiple attributes, some buffers */ + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 5); + p11t_check_returns("C_GetAttributeValue: multiple attrs, some buffer", rv, CKR_OK); + p11t_check_ulong("C_GetAttributeValue: CKA_CLASS no buffer, size", attrs[0].ulValueLen, sizeof(CK_OBJECT_CLASS)); + p11t_check_bool("C_GetAttributeValue: CKA_TOKEN", *((CK_BBOOL*)attrs[1].pValue)); + p11t_check_bool("C_GetAttributeValue: CKA_PRIVATE", *((CK_BBOOL*)attrs[2].pValue)); + p11t_check_bool("C_GetAttributeValue: CKA_MODIFIABLE", *((CK_BBOOL*)attrs[3].pValue)); + + attrs[0].pValue = buffer; + attrs[0].ulValueLen = 2; + + /** - Multiple attributes, one small buffer */ + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 5); + p11t_check_returns("C_GetAttributeValue: multiple attrs, one small buffer", rv, CKR_BUFFER_TOO_SMALL); + p11t_check_ulong("C_GetAttributeValue: CKA_CLASS no buffer, size", attrs[0].ulValueLen, sizeof(CK_OBJECT_CLASS)); + p11t_check_bool("C_GetAttributeValue: CKA_TOKEN", *((CK_BBOOL*)attrs[1].pValue)); + p11t_check_bool("C_GetAttributeValue: CKA_PRIVATE", *((CK_BBOOL*)attrs[2].pValue)); + p11t_check_bool("C_GetAttributeValue: CKA_MODIFIABLE", *((CK_BBOOL*)attrs[3].pValue)); + } + + attrs[0].pValue = buffer; + attrs[0].ulValueLen = sizeof(CK_OBJECT_CLASS); + + /** - Multiple attributes, with buffers */ + rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, attrs, 5); + p11t_check_returns("C_GetAttributeValue: multiple attrs, with buffers", rv, CKR_OK); + p11t_check_ulong("C_GetAttributeValue: CKA_CLASS no buffer, size", attrs[0].ulValueLen, sizeof(CK_OBJECT_CLASS)); + p11t_check_ulong("C_GetAttributeValue: CKA_CLASS value", *((CK_ULONG*)attrs[0].pValue), klass); + p11t_check_bool("C_GetAttributeValue: CKA_TOKEN", *((CK_BBOOL*)attrs[1].pValue)); + p11t_check_bool("C_GetAttributeValue: CKA_PRIVATE", *((CK_BBOOL*)attrs[2].pValue)); + p11t_check_bool("C_GetAttributeValue: CKA_MODIFIABLE", *((CK_BBOOL*)attrs[3].pValue)); + p11t_check_string("C_GetAttributeValue: CKA_LABEL", attrs[4].pValue, attrs[4].ulValueLen); +} + +static void +test_objects(CK_SESSION_HANDLE session) +{ + CK_OBJECT_HANDLE_PTR objects; + CK_ULONG n_objects; + CK_ULONG i; + + assert(p11t_module_funcs); + + objects = p11t_object_find(session, NULL, 0, &n_objects); + if(!objects || !n_objects) + return; + + for(i = 0; i < n_objects; ++i) + { + /** C_GetObjectSize */ + + /** - Not Implemented */ + + test_get_attribute_value(session, objects[i]); + } + + free (objects); } void @@ -157,14 +343,16 @@ p11t_object_tests(void) if(session_ro == CK_INVALID) continue; - if(p11t_session_login(session_ro)) - continue; + find_objects(session_ro); + test_objects(session_ro); - find_all_objects(session_ro); + if(!p11t_session_login(session_ro)) + continue; if(session_rw != CK_INVALID) { - find_all_objects(session_rw); + find_objects(session_rw); + test_objects(session_rw); create_object(session_rw, session_ro); copy_object(session_rw, session_ro); destroy_object(session_rw, session_ro); @@ -173,3 +361,49 @@ p11t_object_tests(void) p11t_session_close_all(p11t_slot_ids[i]); } } + +/* ---------------------------------------------------------------------------------- + * METHODS + */ + +CK_OBJECT_HANDLE_PTR +p11t_object_find(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attrs, + CK_ULONG n_attrs, CK_ULONG_PTR n_objects) +{ + CK_OBJECT_HANDLE_PTR objects; + CK_OBJECT_HANDLE dummy_obj; + CK_ATTRIBUTE dummy_attr; + CK_ULONG count; + + assert(p11t_module_funcs); + + if(!attrs) + attrs = &dummy_attr; + + if((p11t_module_funcs->C_FindObjectsInit)(session, attrs, n_attrs) != CKR_OK) + return NULL; + + if((p11t_module_funcs->C_FindObjects)(session, &dummy_obj, 0, &count) != CKR_OK) + return NULL; + + if(!count) + return NULL; + + objects = calloc(count, sizeof(CK_OBJECT_HANDLE)); + assert(objects); + + if((p11t_module_funcs->C_FindObjects)(session, objects, count, n_objects) != CKR_OK) + { + free(objects); + return NULL; + } + + if((p11t_module_funcs->C_FindObjectsFinal)(session) != CKR_OK) + { + free(objects); + return NULL; + } + + return objects; +} + diff --git a/src/p11-tests.h b/src/p11-tests.h index d30e1cc..1118e92 100644 --- a/src/p11-tests.h +++ b/src/p11-tests.h @@ -44,6 +44,10 @@ int p11t_check_flag(const char *message, CK_ULONG flags, CK_ULONG flag); int p11t_check_nflag(const char *message, CK_ULONG flags, CK_ULONG nflag); +int p11t_check_bool(const char *message, CK_BBOOL value); + +int p11t_check_string(const char *message, CK_UTF8CHAR_PTR value, CK_ULONG length); + /* ------------------------------------------------------------------- * config.c */ @@ -69,6 +73,9 @@ void p11t_module_finalize(void); * object.c */ +CK_OBJECT_HANDLE_PTR p11t_object_find(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attrs, + CK_ULONG n_attrs, CK_ULONG_PTR n_objects); + void p11t_object_tests(void); /* ------------------------------------------------------------------- diff --git a/src/session.c b/src/session.c index 51bc050..45faaa3 100644 --- a/src/session.c +++ b/src/session.c @@ -8,6 +8,20 @@ static const char *login_user_pin = NULL; static const char *login_so_pin = NULL; + +void +p11t_session_config(const char *name, const char *value) +{ + if(strcmp(name, "login-user-pin") == 0) + login_user_pin = value; + if(strcmp(name, "login-so-pin") == 0) + login_so_pin = value; +} + +/* ---------------------------------------------------------------------------------- + * TESTS + */ + void session_info(CK_SESSION_HANDLE session, CK_SLOT_ID slot, CK_FLAGS flags, CK_STATE state) { @@ -343,6 +357,10 @@ p11t_session_tests() } } +/* ---------------------------------------------------------------------------------- + * METHODS + */ + CK_SESSION_HANDLE p11t_session_open(CK_SLOT_ID slot, int readwrite) { @@ -442,13 +460,3 @@ p11t_session_close_all(CK_SLOT_ID slot) return 1; return 0; } - -void -p11t_session_config(const char *name, const char *value) -{ - if(strcmp(name, "login-user-pin") == 0) - login_user_pin = value; - if(strcmp(name, "login-so-pin") == 0) - login_so_pin = value; -} - diff --git a/src/slot.c b/src/slot.c index 6919846..2c1353a 100644 --- a/src/slot.c +++ b/src/slot.c @@ -17,6 +17,10 @@ CK_TOKEN_INFO_PTR p11t_slot_token_info = NULL; CK_ULONG *p11t_slot_mech_count; CK_MECHANISM_INFO_PTR *p11t_slot_mech_info; +/* ---------------------------------------------------------------------------------- + * TESTS + */ + void slot_global(void) { @@ -394,6 +398,10 @@ p11t_slot_tests(void) slot_mechanisms(); } +/* ---------------------------------------------------------------------------------- + * METHODS + */ + CK_TOKEN_INFO_PTR p11t_slot_get_token_info(CK_SLOT_ID slot) { -- cgit v1.2.3