summaryrefslogtreecommitdiff
path: root/p11-capi-builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'p11-capi-builtin.c')
-rw-r--r--p11-capi-builtin.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/p11-capi-builtin.c b/p11-capi-builtin.c
new file mode 100644
index 0000000..2757cb3
--- /dev/null
+++ b/p11-capi-builtin.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2007 Stef Walter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "p11-capi.h"
+#include "p11-capi-object.h"
+#include "p11-capi-session.h"
+#include "p11-capi-token.h"
+
+#include "pkcs11/pkcs11n.h"
+
+/* --------------------------------------------------------------------------
+ * BUILT IN VALUES
+ */
+
+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";
+
+/* --------------------------------------------------------------------------
+ * BUILT IN OBJECTS
+ */
+
+#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 }
+};
+
+typedef struct _BuiltinMatch
+{
+ CK_ATTRIBUTE_PTR attr;
+ CK_ULONG slot_flags;
+}
+BuiltinMatch;
+
+static const BuiltinMatch all_builtins[] = {
+ { (CK_ATTRIBUTE_PTR)&builtin_root, P11c_SLOT_TRUSTED | P11c_SLOT_CA | P11c_SLOT_CERTS },
+ { NULL, 0 }
+};
+
+/* This is filled in later */
+static CK_ULONG num_builtins = 0;
+
+/* --------------------------------------------------------------------------
+ * IMPLEMENTATION
+ */
+
+/* Represents a loaded builtin object */
+typedef struct _BuiltinObject
+{
+ P11cObject obj;
+ CK_ATTRIBUTE_PTR attr;
+}
+BuiltinObject;
+
+typedef struct _BuiltinObjectData
+{
+ P11cObjectData base;
+ CK_ATTRIBUTE_PTR attr;
+}
+BuiltinObjectData;
+
+static CK_RV
+builtin_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr)
+{
+ BuiltinObjectData* bdata = (BuiltinObjectData*)objdata;
+ CK_ATTRIBUTE_PTR builtin = bdata->attr;
+
+ ASSERT(attr);
+ ASSERT(bdata);
+
+ while(builtin->type != CK_END_LIST)
+ {
+ if(builtin->type == attr->type)
+ {
+ if(builtin->ulValueLen == 0)
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ return p11c_return_data(attr, builtin->pValue, builtin->ulValueLen);
+ }
+
+ builtin++;
+ }
+
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+}
+
+static void
+builtin_data_release(void* data)
+{
+ BuiltinObjectData* bdata = (BuiltinObjectData*)data;
+ ASSERT(bdata);
+ free(bdata);
+}
+
+static const P11cObjectDataVtable builtin_objdata_vtable = {
+ builtin_attribute,
+ builtin_attribute,
+ builtin_attribute,
+ builtin_data_release,
+};
+
+static CK_RV
+builtin_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata)
+{
+ BuiltinObject* bobj = (BuiltinObject*)obj;
+ BuiltinObjectData* bdata;
+
+ ASSERT(bobj);
+ ASSERT(objdata);
+ ASSERT(num_builtins > 0);
+
+ bdata = (BuiltinObjectData*)calloc(1, sizeof(BuiltinObjectData));
+ if(!bdata)
+ return CKR_HOST_MEMORY;
+
+ /* Simple, just use same data */
+ bdata->attr = bobj->attr;
+
+ bdata->base.object = obj->id;
+ bdata->base.data_funcs = &builtin_objdata_vtable;
+
+ *objdata = &(bdata->base);
+ return CKR_OK;
+}
+
+static unsigned int
+builtin_hash_func(P11cObject* obj)
+{
+ return p11c_hash_pointer(((BuiltinObject*)obj)->attr);
+}
+
+static int
+builtin_equal_func(P11cObject* one, P11cObject* two)
+{
+ return ((BuiltinObject*)one)->attr == ((BuiltinObject*)two)->attr;
+}
+
+static void
+builtin_object_release(void* data)
+{
+ BuiltinObject* bobj = (BuiltinObject*)data;
+ ASSERT(bobj);
+ free(bobj);
+}
+
+static const P11cObjectVtable builtin_object_vtable = {
+ builtin_load_data,
+ builtin_hash_func,
+ builtin_equal_func,
+ builtin_object_release,
+};
+
+static CK_RV
+register_builtin_object(P11cSession* sess, CK_ATTRIBUTE_PTR attr, P11cObject** obj)
+{
+ BuiltinObject* bobj;
+ CK_RV ret;
+
+ bobj = calloc(1, sizeof(BuiltinObject));
+ if(!bobj)
+ return CKR_HOST_MEMORY;
+
+ bobj->attr = attr;
+
+ bobj->obj.id = 0;
+ bobj->obj.obj_funcs = &builtin_object_vtable;
+
+ ret = p11c_token_register_object(sess->slot, &(bobj->obj));
+ if(ret != CKR_OK)
+ {
+ free(bobj);
+ return ret;
+ }
+
+ ASSERT(bobj->obj.id != 0);
+ *obj = &(bobj->obj);
+ return CKR_OK;
+}
+
+CK_RV
+p11c_builtin_find(P11cSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR match,
+ CK_ULONG count, P11cArray* arr)
+{
+ P11cObject* obj;
+ BuiltinObjectData bdata;
+ CK_RV ret = CKR_OK;
+ CK_ULONG i, fl;
+
+ /* First time around count total number */
+ if(!num_builtins)
+ {
+ while(all_builtins[num_builtins].attr)
+ ++num_builtins;
+ ASSERT(num_builtins > 0);
+ }
+
+ /* Match each certificate */
+ for(i = 0; i < num_builtins; ++i)
+ {
+ /* Only apply built in objects to appropriate slots */
+ fl = p11c_token_get_flags(sess->slot) & all_builtins[i].slot_flags;
+ if(fl != all_builtins[i].slot_flags)
+ continue;
+
+ bdata.attr = all_builtins[i].attr;
+ bdata.base.object = 0;
+ bdata.base.data_funcs = &builtin_objdata_vtable;
+
+ if(p11c_object_data_match(&bdata.base, match, count))
+ {
+ ret = register_builtin_object(sess, all_builtins[i].attr, &obj);
+ if(ret != CKR_OK)
+ break;
+
+ p11c_array_append(arr, obj->id);
+ }
+ }
+
+ return ret;
+}
+