diff options
Diffstat (limited to 'ckcapi-builtin.c')
-rw-r--r-- | ckcapi-builtin.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/ckcapi-builtin.c b/ckcapi-builtin.c new file mode 100644 index 0000000..94d170e --- /dev/null +++ b/ckcapi-builtin.c @@ -0,0 +1,190 @@ + +#include "ckcapi.h" +#include "pkcs11/pkcs11n.h" + +static const CK_BBOOL ck_true = CK_TRUE; +static const CK_BBOOL ck_false = CK_FALSE; + +static const CK_OBJECT_CLASS cko_netscape_builtin_root_list = CKO_NETSCAPE_BUILTIN_ROOT_LIST; + +static const char ck_root_label[] = "Windows Certificate Roots"; + +#define CK_END_LIST (CK_ULONG)-1 + +static const CK_ATTRIBUTE builtin_root[] = { + { CKA_TOKEN, (void*)&ck_true, sizeof(CK_BBOOL) }, + { CKA_CLASS, (void*)&cko_netscape_builtin_root_list, sizeof(CK_OBJECT_CLASS) }, + { CKA_PRIVATE, (void*)&ck_false, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, (void*)&ck_false, sizeof(CK_BBOOL) }, + { CKA_LABEL, (void*)ck_root_label, sizeof(ck_root_label) }, + { CK_END_LIST, NULL, 0 } +}; + +static const CK_ATTRIBUTE_PTR all_builtins[] = { + (CK_ATTRIBUTE_PTR)&builtin_root, + NULL, +}; + +static CK_ULONG num_builtins = 0; + +typedef struct _BuiltinObject +{ + CkCapiObject obj; + + /* Together these form the unique key. Must be contiguous */ + unsigned int otype; + CK_ULONG builtin_index; +} +BuiltinObject; + +static CK_RV +builtin_attribute(void* obj, CK_ATTRIBUTE_TYPE type, + CK_VOID_PTR data, CK_ULONG_PTR len) +{ + CK_ATTRIBUTE_PTR builtin = (CK_ATTRIBUTE_PTR)obj; + + ASSERT(len); + ASSERT(obj); + + while(builtin->type != CK_END_LIST) + { + if(builtin->type == type) + { + if(builtin->ulValueLen == 0) + return CKR_ATTRIBUTE_TYPE_INVALID; + + if(!data) + { + *len = builtin->ulValueLen; + return CKR_OK; + } + + if(builtin->ulValueLen > *len) + { + *len = builtin->ulValueLen; + return CKR_BUFFER_TOO_SMALL; + } + + *len = builtin->ulValueLen; + memcpy(data, builtin->pValue, builtin->ulValueLen); + return CKR_OK; + } + + builtin++; + } + + return CKR_ATTRIBUTE_TYPE_INVALID; +} + +static void +builtin_release(void* data) +{ + /* Nothing to do to free builtin data */ +} + +static const CkCapiObjectDataVtable builtin_objdata_vtable = { + builtin_attribute, + builtin_attribute, + builtin_attribute, + builtin_attribute, + builtin_release, +}; + +static CK_RV +builtin_load(CkCapiObject* obj, CkCapiObjectData* objdata) +{ + BuiltinObject* bobj = (BuiltinObject*)obj; + + ASSERT(bobj); + ASSERT(objdata); + ASSERT(num_builtins > 0); + + if(bobj->builtin_index > num_builtins) + return CKR_OBJECT_HANDLE_INVALID; + + objdata->data = (void*)all_builtins[bobj->builtin_index]; + objdata->data_funcs = builtin_objdata_vtable; + + return CKR_OK; +} + + +static void +builtin_object_release(void* data) +{ + BuiltinObject* bobj = (BuiltinObject*)data; + ASSERT(bobj); + free(bobj); +} + +static const CkCapiObjectVtable builtin_object_vtable = { + builtin_load, + builtin_object_release, +}; + +static CK_RV +register_builtin_object(CkCapiSession* sess, CK_ULONG index, CK_OBJECT_HANDLE_PTR id) +{ + BuiltinObject* bobj; + CK_RV ret; + + bobj = calloc(sizeof(BuiltinObject), 1); + if(!bobj) + return CKR_HOST_MEMORY; + + bobj->otype = OBJECT_BUILTIN; + bobj->builtin_index = index; + + bobj->obj.id = 0; + bobj->obj.obj_funcs = builtin_object_vtable; + bobj->obj.unique_key = UNIQUE_KEY_AT(bobj, otype); + bobj->obj.unique_len = UNIQUE_KEY_LEN(bobj, otype, builtin_index); + + ret = ckcapi_object_register(sess, &(bobj->obj)); + if(ret != CKR_OK) + { + free(bobj); + return ret; + } + + ASSERT(bobj->obj.id != 0); + *id = bobj->obj.id; + return CKR_OK; +} + +CK_RV +ckcapi_builtin_find_all(CkCapiSession* sess, CK_ATTRIBUTE_PTR match, + CK_ULONG count, CkCapiArray* arr) +{ + CK_OBJECT_HANDLE obj; + CkCapiObjectData objdata; + CK_RV ret = CKR_OK; + CK_ULONG i; + + /* First time around count total number */ + if(!num_builtins) + { + while(all_builtins[num_builtins]) + ++num_builtins; + ASSERT(num_builtins > 0); + } + + /* Match each certificate */ + for(i = 0; i < num_builtins; ++i) + { + objdata.data = (void*)all_builtins[i]; + objdata.data_funcs = builtin_objdata_vtable; + + if(ckcapi_object_data_match(&objdata, match, count)) + { + ret = register_builtin_object(sess, i, &obj); + if(ret != CKR_OK) + break; + + ckcapi_array_append(arr, obj); + } + } + + return ret; +} + |