summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--freeipa.spec.in2
-rw-r--r--ipapython/Makefile2
-rw-r--r--ipapython/ipap11helper/Makefile20
-rw-r--r--ipapython/ipap11helper/library.c86
-rw-r--r--ipapython/ipap11helper/library.h48
-rw-r--r--ipapython/ipap11helper/p11helper.c2104
-rw-r--r--ipapython/ipap11helper/setup.py44
8 files changed, 2306 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index b968b5706..5b3f401d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,6 +70,7 @@ freeipa2-dev-doc
/ipapython/version.py
!/ipapython/Makefile
!/ipapython/py_default_encoding/Makefile
+!/ipapython/ipap11helper/Makefile
/ipaplatform/setup.py
/ipaplatform/tasks.py
diff --git a/freeipa.spec.in b/freeipa.spec.in
index c978b716c..0b66fe6e0 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -831,10 +831,12 @@ fi
%dir %{python_sitelib}/ipaplatform
%{python_sitelib}/ipaplatform/*
%attr(0644,root,root) %{python_sitearch}/default_encoding_utf8.so
+%attr(0644,root,root) %{python_sitearch}/_ipap11helper.so
%{python_sitelib}/ipapython-*.egg-info
%{python_sitelib}/freeipa-*.egg-info
%{python_sitelib}/ipaplatform-*.egg-info
%{python_sitearch}/python_default_encoding-*.egg-info
+%{python_sitearch}/_ipap11helper-*.egg-info
%dir %attr(0755,root,root) %{_sysconfdir}/ipa/
%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/default.conf
%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/ca.crt
diff --git a/ipapython/Makefile b/ipapython/Makefile
index e09956ad3..b2cf719fd 100644
--- a/ipapython/Makefile
+++ b/ipapython/Makefile
@@ -3,7 +3,7 @@ PACKAGEDIR ?= $(DESTDIR)/$(PYTHONLIBDIR)/ipa
CONFIGDIR ?= $(DESTDIR)/etc/ipa
TESTS = $(wildcard test/*.py)
-SUBDIRS = py_default_encoding
+SUBDIRS = py_default_encoding ipap11helper
all:
@for subdir in $(SUBDIRS); do \
diff --git a/ipapython/ipap11helper/Makefile b/ipapython/ipap11helper/Makefile
new file mode 100644
index 000000000..88f17f705
--- /dev/null
+++ b/ipapython/ipap11helper/Makefile
@@ -0,0 +1,20 @@
+PYTHONLIBDIR ?= $(shell python2 -c "from distutils.sysconfig import *; print get_python_lib()")
+PACKAGEDIR ?= $(DESTDIR)/$(PYTHONLIBDIR)/ipa
+CONFIGDIR ?= $(DESTDIR)/etc/ipa
+
+all:
+ python2 setup.py build
+
+install:
+ if [ "$(DESTDIR)" = "" ]; then \
+ python2 setup.py install; \
+ else \
+ python2 setup.py install --root $(DESTDIR); \
+ fi
+
+clean:
+ rm -rf build
+
+distclean: clean
+
+maintainer-clean: distclean
diff --git a/ipapython/ipap11helper/library.c b/ipapython/ipap11helper/library.c
new file mode 100644
index 000000000..51e24ebc2
--- /dev/null
+++ b/ipapython/ipap11helper/library.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2014 FreeIPA Contributors see COPYING for license
+ *
+ * This code is based on PKCS#11 code from SoftHSM project:
+ * https://github.com/opendnssec/SoftHSMv2/
+ * Original license follows:
+ */
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ library.c
+
+ Support function for handling PKCS#11 libraries
+ *****************************************************************************/
+
+#include "library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+// Load the PKCS#11 library
+CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle)
+{
+ CK_C_GetFunctionList pGetFunctionList = NULL;
+
+ void* pDynLib = NULL;
+
+ // Load PKCS #11 library
+ if (module)
+ {
+ pDynLib = dlopen(module, RTLD_NOW | RTLD_LOCAL);
+ }
+ /*
+ else
+ {
+ pDynLib = dlopen(DEFAULT_PKCS11_LIB, RTLD_NOW | RTLD_LOCAL);
+ }
+ */
+
+ if (pDynLib == NULL)
+ {
+ // Failed to load the PKCS #11 library
+ return NULL;
+ }
+
+ // Retrieve the entry point for C_GetFunctionList
+ pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
+
+ // Store the handle so we can dlclose it later
+ *moduleHandle = pDynLib;
+
+ return pGetFunctionList;
+}
+
+void unloadLibrary(void* moduleHandle)
+{
+ if (moduleHandle)
+ {
+ dlclose(moduleHandle);
+ }
+}
diff --git a/ipapython/ipap11helper/library.h b/ipapython/ipap11helper/library.h
new file mode 100644
index 000000000..2ceb9e375
--- /dev/null
+++ b/ipapython/ipap11helper/library.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 FreeIPA Contributors see COPYING for license
+ *
+ * This code is based on PKCS#11 code from SoftHSM project:
+ * https://github.com/opendnssec/SoftHSMv2/
+ * Original license follows:
+ */
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ library.h
+
+ Support function for handling PKCS#11 libraries
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_LIBRARY_H
+#define _SOFTHSM_V2_BIN_LIBRARY_H
+
+#include <p11-kit/pkcs11.h>
+
+CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle);
+void unloadLibrary(void* moduleHandle);
+
+#endif // !_SOFTHSM_V2_BIN_LIBRARY_H
diff --git a/ipapython/ipap11helper/p11helper.c b/ipapython/ipap11helper/p11helper.c
new file mode 100644
index 000000000..df5302a7f
--- /dev/null
+++ b/ipapython/ipap11helper/p11helper.c
@@ -0,0 +1,2104 @@
+/*
+ * Copyright (C) 2014 FreeIPA Contributors see COPYING for license
+ *
+ * This code is based on PKCS#11 code snippets from NLnetLabs:
+ * http://www.nlnetlabs.nl/publications/hsm/examples/pkcs11/
+ * Original license follows:
+ */
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <Python.h>
+#include "structmember.h"
+
+#include <openssl/asn1.h>
+#include <openssl/x509.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+#include <openssl/bio.h>
+
+#include <p11-kit/pkcs11.h>
+#include <p11-kit/uri.h>
+
+#include "library.h"
+
+// compat TODO
+#define CKM_AES_KEY_WRAP (0x1090)
+#define CKM_AES_KEY_WRAP_PAD (0x1091)
+
+// TODO
+#define CKA_COPYABLE (0x0017)
+
+CK_BBOOL true = CK_TRUE;
+CK_BBOOL false = CK_FALSE;
+
+#define MAX_TEMPLATE_LEN 32
+
+/**
+ * P11_Helper type
+ */
+typedef struct {
+PyObject_HEAD
+CK_SLOT_ID slot;
+CK_FUNCTION_LIST_PTR p11;
+CK_SESSION_HANDLE session;
+} P11_Helper;
+
+typedef enum {
+ sec_en_cka_copyable = 0,
+ sec_en_cka_decrypt = 1,
+ sec_en_cka_derive = 2,
+ sec_en_cka_encrypt = 3,
+ sec_en_cka_extractable = 4,
+ sec_en_cka_modifiable = 5,
+ sec_en_cka_private = 6,
+ sec_en_cka_sensitive = 7,
+ sec_en_cka_sign = 8,
+ sec_en_cka_unwrap = 9,
+ sec_en_cka_verify = 10,
+ sec_en_cka_wrap = 11,
+ sec_en_cka_wrap_with_trusted = 12
+} secrect_key_enum;
+
+typedef enum {
+ pub_en_cka_copyable = 0,
+ pub_en_cka_derive = 1,
+ pub_en_cka_encrypt = 2,
+ pub_en_cka_modifiable = 3,
+ pub_en_cka_private = 4,
+ pub_en_cka_trusted = 5,
+ pub_en_cka_verify = 6,
+ pub_en_cka_verify_recover = 7,
+ pub_en_cka_wrap = 8
+} public_key_enum;
+
+typedef enum {
+ priv_en_cka_always_authenticate = 0,
+ priv_en_cka_copyable = 1,
+ priv_en_cka_decrypt = 2,
+ priv_en_cka_derive = 3,
+ priv_en_cka_extractable = 4,
+ priv_en_cka_modifiable = 5,
+ priv_en_cka_private = 6,
+ priv_en_cka_sensitive = 7,
+ priv_en_cka_sign = 8,
+ priv_en_cka_sign_recover = 9,
+ priv_en_cka_unwrap = 10,
+ priv_en_cka_wrap_with_trusted = 11
+} private_key_enum;
+
+typedef struct {
+PyObject* py_obj;
+CK_BBOOL* bool;
+} PyObj2Bool_mapping_t;
+
+/**
+ * ipap11helper Exceptions
+ */
+static PyObject *ipap11helperException; //parent class for all exceptions
+
+static PyObject *ipap11helperError; //general error
+static PyObject *ipap11helperNotFound; //key not found
+static PyObject *ipap11helperDuplicationError; //key already exists
+
+/***********************************************************************
+ * Support functions
+ */
+
+CK_BBOOL* pyobj_to_bool(PyObject* pyobj) {
+ if (PyObject_IsTrue(pyobj))
+ return &true;
+ return &false;
+
+}
+
+void convert_py2bool(PyObj2Bool_mapping_t* mapping, int length) {
+ int i;
+ for (i = 0; i < length; ++i) {
+ PyObject* py_obj = mapping[i].py_obj;
+ if (py_obj != NULL) {
+ Py_INCREF(py_obj);
+ mapping[i].bool = pyobj_to_bool(py_obj);
+ Py_DECREF(py_obj);
+ }
+ }
+}
+
+/**
+ * Convert a unicode string to the utf8 encoded char array
+ * :param unicode: input python unicode object
+ * :param l length: of returned string
+ * Returns NULL if an error occurs, else pointer to string
+ */
+unsigned char* unicode_to_char_array(PyObject *unicode, Py_ssize_t *l) {
+ PyObject* utf8_str = PyUnicode_AsUTF8String(unicode);
+ if (utf8_str == NULL) {
+ PyErr_SetString(ipap11helperError, "Unable to encode UTF-8");
+ return NULL;
+ }
+ Py_XINCREF(utf8_str);
+ unsigned char* bytes = (unsigned char*) PyString_AS_STRING(utf8_str);
+ if (bytes == NULL) {
+ PyErr_SetString(ipap11helperError, "Unable to get bytes from string");
+ *l = 0;
+ } else {
+ *l = PyString_Size(utf8_str);
+ }
+ Py_XDECREF(utf8_str);
+ return bytes;
+}
+
+/**
+ * Convert utf-8 encoded char array to unicode object
+ */
+PyObject* char_array_to_unicode(const char* array, unsigned long l) {
+ return PyUnicode_DecodeUTF8(array, l, "strict");
+}
+
+/**
+ * Tests result value of pkc11 operations
+ * :return: 1 if everything is ok, 0 if an error occurs and set the error message
+ */
+int check_return_value(CK_RV rv, const char *message) {
+ char* errmsg = NULL;
+ if (rv != CKR_OK) {
+ if (asprintf(&errmsg, "Error at %s: 0x%x\n", message, (unsigned int) rv)
+ == -1) {
+ PyErr_SetString(ipap11helperError,
+ "DOUBLE ERROR: Creating the error message caused an error");
+ return 0; //
+ }
+ if (errmsg != NULL) {
+ PyErr_SetString(ipap11helperError, errmsg);
+ free(errmsg);
+ }
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Fill template structure with pointers to attributes passed as independent
+ * variables.
+ * Variables with NULL values will be omitted from template.
+ *
+ * @warning input variables should not be modified when template is in use
+ */
+int _fill_template_from_parts(CK_ATTRIBUTE_PTR attr, CK_ULONG_PTR template_len,
+ CK_BYTE_PTR id, CK_ULONG id_len, CK_BYTE_PTR label, CK_ULONG label_len,
+ CK_OBJECT_CLASS *class, CK_BBOOL *cka_wrap, CK_BBOOL *cka_unwrap) {
+ int cnt = 0;
+ if (label != NULL) {
+ attr->type = CKA_LABEL;
+ attr->pValue = (void *) label;
+ attr->ulValueLen = label_len;
+ ++attr;
+ ++cnt;
+ assert(cnt < *template_len);
+ }
+ if (id != NULL) {
+ attr->type = CKA_ID;
+ attr->pValue = (void *) id;
+ attr->ulValueLen = id_len;
+ ++attr;
+ ++cnt;
+ assert(cnt < *template_len);
+ }
+ if (cka_wrap != NULL) {
+ attr->type = CKA_WRAP;
+ attr->pValue = (void *) cka_wrap;
+ attr->ulValueLen = sizeof(CK_BBOOL);
+ ++attr;
+ ++cnt;
+ assert(cnt < *template_len);
+ }
+ if (cka_unwrap != NULL) {
+ attr->type = CKA_UNWRAP;
+ attr->pValue = (void *) cka_unwrap;
+ attr->ulValueLen = sizeof(CK_BBOOL);
+ ++attr;
+ ++cnt;
+ assert(cnt < *template_len);
+ }
+
+ if (class != NULL) {
+ attr->type = CKA_CLASS;
+ attr->pValue = (void *) class;
+ attr->ulValueLen = sizeof(CK_OBJECT_CLASS);
+ ++attr;
+ ++cnt;
+ assert(cnt < *template_len);
+ }
+ *template_len = cnt;
+ return 1;
+}
+
+/**
+ * Parse string to P11-kit representation of PKCS#11 URI.
+ *
+ * @pre *urip is NULL
+ * @post
+ *
+ * @retval 0 in case of error
+ * @retval 1 when urip is filled with pointer to new URI structure
+ */
+int _parse_uri(const char *uri_str, P11KitUri **urip) {
+ P11KitUriResult result;
+ P11KitUri *uri = NULL;
+
+ assert(urip != NULL && *urip == NULL);
+
+ uri = p11_kit_uri_new();
+ if (!uri) {
+ PyErr_SetString(ipap11helperError, "Cannot initialize URI parser");
+ return 0;
+ }
+
+ result = p11_kit_uri_parse(uri_str, P11_KIT_URI_FOR_OBJECT, uri);
+ if (result != P11_KIT_URI_OK) {
+ PyErr_SetString(ipap11helperError, "Cannot parse URI");
+ goto cleanup;
+ }
+
+ if (p11_kit_uri_any_unrecognized(uri)) {
+ PyErr_SetString(ipap11helperError, "PKCS#11 URI contains "
+ "unsupported attributes");
+ goto cleanup;
+ }
+
+ *urip = uri;
+ return 1;
+
+ cleanup: p11_kit_uri_free(uri);
+ return 0;
+}
+
+/*
+ * Find keys matching specified template.
+ * Function returns list of key handles via objects parameter.
+ *
+ * :param template: PKCS#11 template for attribute matching
+ * :param objects: found objects, NULL if no objects fit criteria
+ * :param objects_count: number of objects in objects array
+ * :return: 1 if success, otherwise return 0 and set the exception
+ */
+int _find_key(P11_Helper* self, CK_ATTRIBUTE_PTR template,
+ CK_ULONG template_len, CK_OBJECT_HANDLE **objects,
+ unsigned int *objects_count) {
+ CK_OBJECT_HANDLE result_object;
+ CK_ULONG objectCount;
+ CK_OBJECT_HANDLE *result_objects = NULL;
+ CK_OBJECT_HANDLE *tmp_objects_ptr = NULL;
+ unsigned int count = 0;
+ unsigned int allocated = 0;
+ CK_RV rv;
+
+ rv = self->p11->C_FindObjectsInit(self->session, template, template_len);
+ if (!check_return_value(rv, "Find key init"))
+ return 0;
+
+ rv = self->p11->C_FindObjects(self->session, &result_object, 1,
+ &objectCount);
+ if (!check_return_value(rv, "Find key"))
+ return 0;
+
+ while (objectCount > 0) {
+ if (allocated <= count) {
+ allocated += 32;
+ tmp_objects_ptr = (CK_OBJECT_HANDLE*) realloc(result_objects,
+ allocated * sizeof(CK_OBJECT_HANDLE));
+ if (tmp_objects_ptr == NULL) {
+ *objects_count = 0;
+ PyErr_SetString(ipap11helperError, "_find_key realloc failed");
+ if (result_objects != NULL)
+ free(result_objects);
+ return 0;
+ } else {
+ result_objects = tmp_objects_ptr;
+ }
+ }
+ result_objects[count] = result_object;
+ count++;
+ rv = self->p11->C_FindObjects(self->session, &result_object, 1,
+ &objectCount);
+ if (!check_return_value(rv, "Check for duplicated key")) {
+ if (result_objects != NULL)
+ free(result_objects);
+ return 0;
+ }
+ }
+
+ rv = self->p11->C_FindObjectsFinal(self->session);
+ if (!check_return_value(rv, "Find objects final")) {
+ if (result_objects != NULL)
+ free(result_objects);
+ return 0;
+ }
+
+ *objects = result_objects;
+ *objects_count = count;
+ return 1;
+}
+
+/*
+ * Test if object with specified label, id and class exists
+ *
+ * :param id: key ID, (if value is NULL, will not be used to find key)
+ * :param id_len: key ID length
+ * :param label key: label (if value is NULL, will not be used to find key)
+ * :param label_len: key label length
+ * :param class key: class
+
+ * :return: 1 if object was found, 0 if object doesnt exists, -1 if error
+ * and set the exception
+ *
+ */
+int _id_exists(P11_Helper* self, CK_BYTE_PTR id, CK_ULONG id_len,
+ CK_OBJECT_CLASS class) {
+
+ CK_RV rv;
+ CK_ULONG object_count = 0;
+ CK_OBJECT_HANDLE result_object = 0;
+ CK_OBJECT_CLASS class_sec = CKO_SECRET_KEY;
+
+ CK_ATTRIBUTE template_pub_priv[] = { { CKA_ID, id, id_len },
+ { CKA_CLASS, &class, sizeof(CK_OBJECT_CLASS) }, };
+
+ CK_ATTRIBUTE template_sec[] = { { CKA_ID, id, id_len },
+ { CKA_CLASS, &class_sec, sizeof(CK_OBJECT_CLASS) }, };
+
+ CK_ATTRIBUTE template_id[] = { { CKA_ID, id, id_len },};
+
+ /*
+ * Only one secret key with same ID is allowed
+ */
+ if (class == CKO_SECRET_KEY){
+ rv = self->p11->C_FindObjectsInit(self->session, template_id, 1);
+ if (!check_return_value(rv, "id, label exists init"))
+ return -1;
+
+ rv = self->p11->C_FindObjects(self->session, &result_object, 1,
+ &object_count);
+ if (!check_return_value(rv, "id, label exists"))
+ return -1;
+
+ rv = self->p11->C_FindObjectsFinal(self->session);
+ if (!check_return_value(rv, "id, label exists final"))
+ return -1;
+
+ if (object_count > 0) {
+ /* object found */
+ return 1;
+ }
+ return 0;
+ }
+
+ /*
+ * Public and private keys can share one ID, but
+ */
+
+ /* test if secret key with same ID exists*/
+ rv = self->p11->C_FindObjectsInit(self->session, template_sec, 2);
+ if (!check_return_value(rv, "id, label exists init"))
+ return -1;
+
+ rv = self->p11->C_FindObjects(self->session, &result_object, 1,
+ &object_count);
+ if (!check_return_value(rv, "id, label exists"))
+ return -1;
+
+ rv = self->p11->C_FindObjectsFinal(self->session);
+ if (!check_return_value(rv, "id, label exists final"))
+ return -1;
+
+ if (object_count > 0) {
+ /* object found */
+ return 1;
+ }
+
+ /* test if pub/private key with same id exists*/
+ object_count = 0;
+
+ rv = self->p11->C_FindObjectsInit(self->session, template_pub_priv, 2);
+ if (!check_return_value(rv, "id, label exists init"))
+ return -1;
+
+ rv = self->p11->C_FindObjects(self->session, &result_object, 1,
+ &object_count);
+ if (!check_return_value(rv, "id, label exists"))
+ return -1;
+
+ rv = self->p11->C_FindObjectsFinal(self->session);
+ if (!check_return_value(rv, "id, label exists final"))
+ return -1;
+
+ if (object_count > 0) {
+ return 1; /* Object found*/
+ }
+
+ return 0; /* Object not found*/
+}
+
+/***********************************************************************
+ * P11_Helper object
+ */
+
+static void P11_Helper_dealloc(P11_Helper* self) {
+ self->ob_type->tp_free((PyObject*) self);
+}
+
+static PyObject *
+P11_Helper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ P11_Helper *self;
+
+ self = (P11_Helper *) type->tp_alloc(type, 0);
+ if (self != NULL) {
+
+ self->slot = 0;
+ self->session = 0;
+ self->p11 = NULL;
+ }
+
+ return (PyObject *) self;
+}
+
+static int P11_Helper_init(P11_Helper *self, PyObject *args, PyObject *kwds) {
+ const char* user_pin = NULL;
+ const char* library_path = NULL;
+ CK_RV rv;
+ void *module_handle = NULL;
+
+ /* Parse method args*/
+ if (!PyArg_ParseTuple(args, "iss", &self->slot, &user_pin, &library_path))
+ return -1;
+
+ CK_C_GetFunctionList pGetFunctionList = loadLibrary(library_path,
+ &module_handle);
+ if (!pGetFunctionList) {
+ PyErr_SetString(ipap11helperError, "Could not load the library.");
+ return -1;
+ }
+
+ /*
+ * Load the function list
+ */
+ (*pGetFunctionList)(&self->p11);
+
+ /*
+ * Initialize
+ */
+ rv = self->p11->C_Initialize(NULL);
+ if (!check_return_value(rv, "initialize"))
+ return -1;
+
+ /*
+ *Start session
+ */
+ rv = self->p11->C_OpenSession(self->slot,
+ CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &self->session);
+ if (!check_return_value(rv, "open session"))
+ return -1;
+
+ /*
+ * Login
+ */
+ rv = self->p11->C_Login(self->session, CKU_USER, (CK_BYTE*) user_pin,
+ strlen((char *) user_pin));
+ if (!check_return_value(rv, "log in"))
+ return -1;
+
+ return 0;
+}
+
+static PyMemberDef P11_Helper_members[] = { { NULL } /* Sentinel */
+};
+
+/*
+ * Finalize operations with pkcs11 library
+ */
+static PyObject *
+P11_Helper_finalize(P11_Helper* self) {
+ CK_RV rv;
+
+ if (self->p11 == NULL)
+ return Py_None;
+
+ /*
+ * Logout
+ */
+ rv = self->p11->C_Logout(self->session);
+ if (rv != CKR_USER_NOT_LOGGED_IN) {
+ if (!check_return_value(rv, "log out"))
+ return NULL;
+ }
+
+ /*
+ * End session
+ */
+ rv = self->p11->C_CloseSession(self->session);
+ if (!check_return_value(rv, "close session"))
+ return NULL;
+
+ /*
+ * Finalize
+ */
+ self->p11->C_Finalize(NULL);
+
+ self->p11 = NULL;
+ self->session = 0;
+ self->slot = 0;
+
+ return Py_None;
+}
+
+/********************************************************************
+ * Methods working with keys
+ */
+
+/**
+ * Generate master key
+ *
+ *:return: master key handle
+ */
+static PyObject *
+P11_Helper_generate_master_key(P11_Helper* self, PyObject *args, PyObject *kwds) {
+
+ PyObj2Bool_mapping_t attrs[] = { { NULL, &true }, //sec_en_cka_copyable
+ { NULL, &false }, //sec_en_cka_decrypt
+ { NULL, &false }, //sec_en_cka_derive
+ { NULL, &false }, //sec_en_cka_encrypt
+ { NULL, &true }, //sec_en_cka_extractable
+ { NULL, &true }, //sec_en_cka_modifiable
+ { NULL, &true }, //sec_en_cka_private
+ { NULL, &true }, //sec_en_cka_sensitive
+ { NULL, &false }, //sec_en_cka_sign
+ { NULL, &true }, //sec_en_cka_unwrap
+ { NULL, &false }, //sec_en_cka_verify
+ { NULL, &true }, //sec_en_cka_wrap
+ { NULL, &false } //sec_en_cka_wrap_with_trusted
+ };
+
+ CK_ULONG key_length = 16;
+ CK_RV rv;
+ CK_OBJECT_HANDLE master_key;
+ CK_BYTE *id = NULL;
+ int id_length = 0;
+
+ PyObject *label_unicode = NULL;
+ Py_ssize_t label_length = 0;
+ int r;
+ static char *kwlist[] = { "subject", "id", "key_length", "cka_copyable",
+ "cka_decrypt", "cka_derive", "cka_encrypt", "cka_extractable",
+ "cka_modifiable", "cka_private", "cka_sensitive", "cka_sign",
+ "cka_unwrap", "cka_verify", "cka_wrap", "cka_wrap_with_trusted",
+ NULL };
+ //TODO check long overflow
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Us#|kOOOOOOOOOOOOO", kwlist,
+ &label_unicode, &id, &id_length, &key_length,
+ &attrs[sec_en_cka_copyable].py_obj,
+ &attrs[sec_en_cka_decrypt].py_obj, &attrs[sec_en_cka_derive].py_obj,
+ &attrs[sec_en_cka_encrypt].py_obj,
+ &attrs[sec_en_cka_extractable].py_obj,
+ &attrs[sec_en_cka_modifiable].py_obj,
+ &attrs[sec_en_cka_private].py_obj,
+ &attrs[sec_en_cka_sensitive].py_obj, &attrs[sec_en_cka_sign].py_obj,
+ &attrs[sec_en_cka_unwrap].py_obj, &attrs[sec_en_cka_verify].py_obj,
+ &attrs[sec_en_cka_wrap].py_obj,
+ &attrs[sec_en_cka_wrap_with_trusted].py_obj)) {
+ return NULL;
+ }
+
+ Py_XINCREF(label_unicode);
+ CK_BYTE *label = (unsigned char*) unicode_to_char_array(label_unicode,
+ &label_length);
+ Py_XDECREF(label_unicode);
+ CK_MECHANISM mechanism = { //TODO param?
+ CKM_AES_KEY_GEN, NULL_PTR, 0 };
+
+ if ((key_length != 16) && (key_length != 24) && (key_length != 32)) {
+ PyErr_SetString(ipap11helperError,
+ "generate_master_key: key length allowed values are: 16, 24 and 32");
+ return NULL;
+ }
+
+ //TODO free label if check failed
+ //TODO is label freed inside???? dont we use freed value later
+ r = _id_exists(self, id, id_length, CKO_SECRET_KEY);
+ if (r == 1) {
+ PyErr_SetString(ipap11helperDuplicationError,
+ "Master key with same ID already exists");
+ return NULL;
+ } else if (r == -1) {
+ return NULL;
+ }
+
+ /* Process keyword boolean arguments */
+ convert_py2bool(attrs, sizeof(attrs) / sizeof(PyObj2Bool_mapping_t));
+
+ CK_ATTRIBUTE symKeyTemplate[] = {
+ { CKA_ID, id, id_length },
+ { CKA_LABEL, label, label_length },
+ { CKA_TOKEN, &true, sizeof(CK_BBOOL) },
+ { CKA_VALUE_LEN, &key_length, sizeof(key_length) },
+ //{CKA_COPYABLE, attrs[sec_en_cka_copyable].bool, sizeof(CK_BBOOL)}, //TODO Softhsm doesn't support it
+ { CKA_DECRYPT, attrs[sec_en_cka_decrypt].bool, sizeof(CK_BBOOL) },
+ { CKA_DERIVE, attrs[sec_en_cka_derive].bool, sizeof(CK_BBOOL) },
+ { CKA_ENCRYPT, attrs[sec_en_cka_encrypt].bool, sizeof(CK_BBOOL) },
+ { CKA_EXTRACTABLE, attrs[sec_en_cka_extractable].bool, sizeof(CK_BBOOL) },
+ { CKA_MODIFIABLE, attrs[sec_en_cka_modifiable].bool, sizeof(CK_BBOOL) },
+ { CKA_PRIVATE, attrs[sec_en_cka_private].bool, sizeof(CK_BBOOL) },
+ { CKA_SENSITIVE, attrs[sec_en_cka_sensitive].bool, sizeof(CK_BBOOL) },
+ { CKA_SIGN, attrs[sec_en_cka_sign].bool, sizeof(CK_BBOOL) },
+ { CKA_UNWRAP, attrs[sec_en_cka_unwrap].bool, sizeof(CK_BBOOL) },
+ { CKA_VERIFY, attrs[sec_en_cka_verify].bool, sizeof(CK_BBOOL) },
+ { CKA_WRAP, attrs[sec_en_cka_wrap].bool, sizeof(CK_BBOOL) },
+ { CKA_WRAP_WITH_TRUSTED, attrs[sec_en_cka_wrap_with_trusted].bool, sizeof(CK_BBOOL) }
+ };
+
+ rv = self->p11->C_GenerateKey(self->session, &mechanism, symKeyTemplate,
+ sizeof(symKeyTemplate) / sizeof(CK_ATTRIBUTE), &master_key);
+ if (!check_return_value(rv, "generate master key"))
+ return NULL;
+
+ return Py_BuildValue("k", master_key);;
+}
+
+/**
+ * Generate replica keys
+ *
+ * :returns: tuple (public_key_handle, private_key_handle)
+ */
+static PyObject *
+P11_Helper_generate_replica_key_pair(P11_Helper* self, PyObject *args,
+ PyObject *kwds) {
+ CK_RV rv;
+ int r;
+ CK_ULONG modulus_bits = 2048;
+ CK_BYTE *id = NULL;
+ int id_length = 0;
+ PyObject* label_unicode = NULL;
+ Py_ssize_t label_length = 0;
+
+ PyObj2Bool_mapping_t attrs_pub[] = { { NULL, &true }, //pub_en_cka_copyable
+ { NULL, &false }, //pub_en_cka_derive
+ { NULL, &false }, //pub_en_cka_encrypt
+ { NULL, &true }, //pub_en_cka_modifiable
+ { NULL, &true }, //pub_en_cka_private
+ { NULL, &false }, //pub_en_cka_trusted
+ { NULL, &false }, //pub_en_cka_verify
+ { NULL, &false }, //pub_en_cka_verify_recover
+ { NULL, &true }, //pub_en_cka_wrap
+ };
+
+ PyObj2Bool_mapping_t attrs_priv[] = { { NULL, &false }, //priv_en_cka_always_authenticate
+ { NULL, &true }, //priv_en_cka_copyable
+ { NULL, &false }, //priv_en_cka_decrypt
+ { NULL, &false }, //priv_en_cka_derive
+ { NULL, &false }, //priv_en_cka_extractable
+ { NULL, &true }, //priv_en_cka_modifiable
+ { NULL, &true }, //priv_en_cka_private
+ { NULL, &true }, //priv_en_cka_sensitive
+ { NULL, &false }, //priv_en_cka_sign
+ { NULL, &false }, //priv_en_cka_sign_recover
+ { NULL, &true }, //priv_en_cka_unwrap
+ { NULL, &false } //priv_en_cka_wrap_with_trusted
+ };
+
+ static char *kwlist[] = { "label", "id", "modulus_bits",
+ /* public key kw */
+ "pub_cka_copyable", "pub_cka_derive", "pub_cka_encrypt",
+ "pub_cka_modifiable", "pub_cka_private", "pub_cka_trusted",
+ "pub_cka_verify", "pub_cka_verify_recover", "pub_cka_wrap",
+ /* private key kw*/
+ "priv_cka_always_authenticate", "priv_cka_copyable",
+ "priv_cka_decrypt", "priv_cka_derive", "priv_cka_extractable",
+ "priv_cka_modifiable", "priv_cka_private", "priv_cka_sensitive",
+ "priv_cka_sign", "priv_cka_sign_recover", "priv_cka_unwrap",
+ "priv_cka_wrap_with_trusted", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Us#|kOOOOOOOOOOOOOOOOOOOOO",
+ kwlist, &label_unicode, &id, &id_length, &modulus_bits,
+ /* public key kw */
+ &attrs_pub[pub_en_cka_copyable].py_obj,
+ &attrs_pub[pub_en_cka_derive].py_obj,
+ &attrs_pub[pub_en_cka_encrypt].py_obj,
+ &attrs_pub[pub_en_cka_modifiable].py_obj,
+ &attrs_pub[pub_en_cka_private].py_obj,
+ &attrs_pub[pub_en_cka_trusted].py_obj,
+ &attrs_pub[pub_en_cka_verify].py_obj,
+ &attrs_pub[pub_en_cka_verify_recover].py_obj,
+ &attrs_pub[pub_en_cka_wrap].py_obj,
+ /* private key kw*/
+ &attrs_priv[priv_en_cka_always_authenticate].py_obj,
+ &attrs_priv[priv_en_cka_copyable].py_obj,
+ &attrs_priv[priv_en_cka_decrypt].py_obj,
+ &attrs_priv[priv_en_cka_derive].py_obj,
+ &attrs_priv[priv_en_cka_extractable].py_obj,
+ &attrs_priv[priv_en_cka_modifiable].py_obj,
+ &attrs_priv[priv_en_cka_private].py_obj,
+ &attrs_priv[priv_en_cka_sensitive].py_obj,
+ &attrs_priv[priv_en_cka_sign].py_obj,
+ &attrs_priv[priv_en_cka_sign_recover].py_obj,
+ &attrs_priv[priv_en_cka_unwrap].py_obj,
+ &attrs_priv[priv_en_cka_wrap_with_trusted].py_obj)) {
+ return NULL;
+ }
+
+ Py_XINCREF(label_unicode);
+ CK_BYTE *label = unicode_to_char_array(label_unicode, &label_length);
+ Py_XDECREF(label_unicode);
+
+ CK_OBJECT_HANDLE public_key, private_key;
+ CK_MECHANISM mechanism = {
+ CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+
+ //TODO free variables
+
+ r = _id_exists(self, id, id_length, CKO_PRIVATE_KEY);
+ if (r == 1) {
+ PyErr_SetString(ipap11helperDuplicationError,
+ "Private key with same ID already exists");
+ return NULL;
+ } else if (r == -1) {
+ return NULL;
+ }
+
+ r = _id_exists(self, id, id_length, CKO_PUBLIC_KEY);
+ if (r == 1) {
+ PyErr_SetString(ipap11helperDuplicationError,
+ "Public key with same ID already exists");
+ return NULL;
+ } else if (r == -1) {
+ return NULL;
+ }
+
+ /* Process keyword boolean arguments */
+ convert_py2bool(attrs_pub,
+ sizeof(attrs_pub) / sizeof(PyObj2Bool_mapping_t));
+ convert_py2bool(attrs_priv,
+ sizeof(attrs_priv) / sizeof(PyObj2Bool_mapping_t));
+
+ CK_BYTE public_exponent[] = { 1, 0, 1 }; /* 65537 (RFC 6376 section 3.3.1)*/
+ CK_ATTRIBUTE publicKeyTemplate[] = {
+ { CKA_ID, id, id_length },
+ { CKA_LABEL, label, label_length },
+ { CKA_TOKEN, &true, sizeof(true) },
+ { CKA_MODULUS_BITS, &modulus_bits, sizeof(modulus_bits) },
+ { CKA_PUBLIC_EXPONENT, public_exponent, 3 },
+ //{CKA_COPYABLE, attrs_pub[pub_en_cka_copyable].bool, sizeof(CK_BBOOL)}, //TODO Softhsm doesn't support it
+ { CKA_DERIVE, attrs_pub[pub_en_cka_derive].bool, sizeof(CK_BBOOL) },
+ { CKA_ENCRYPT, attrs_pub[pub_en_cka_encrypt].bool, sizeof(CK_BBOOL) },
+ { CKA_MODIFIABLE, attrs_pub[pub_en_cka_modifiable].bool, sizeof(CK_BBOOL) },
+ { CKA_PRIVATE, attrs_pub[pub_en_cka_private].bool, sizeof(CK_BBOOL) },
+ { CKA_TRUSTED, attrs_pub[pub_en_cka_trusted].bool, sizeof(CK_BBOOL) },
+ { CKA_VERIFY, attrs_pub[pub_en_cka_verify].bool, sizeof(CK_BBOOL) },
+ { CKA_VERIFY_RECOVER, attrs_pub[pub_en_cka_verify_recover].bool, sizeof(CK_BBOOL) },
+ { CKA_WRAP, attrs_pub[pub_en_cka_wrap].bool, sizeof(CK_BBOOL) }, };
+
+ CK_ATTRIBUTE privateKeyTemplate[] = {
+ { CKA_ID, id, id_length },
+ { CKA_LABEL, label, label_length },
+ { CKA_TOKEN, &true, sizeof(true) },
+ { CKA_ALWAYS_AUTHENTICATE, attrs_priv[priv_en_cka_always_authenticate].bool, sizeof(CK_BBOOL) },
+ //{CKA_COPYABLE, attrs_priv[priv_en_cka_copyable].bool, sizeof(CK_BBOOL)}, //TODO Softhsm doesn't support it
+ { CKA_DECRYPT, attrs_priv[priv_en_cka_decrypt].bool, sizeof(CK_BBOOL) },
+ { CKA_DERIVE, attrs_priv[priv_en_cka_derive].bool, sizeof(CK_BBOOL) },
+ { CKA_EXTRACTABLE, attrs_priv[priv_en_cka_extractable].bool, sizeof(CK_BBOOL) },
+ { CKA_MODIFIABLE, attrs_priv[priv_en_cka_modifiable].bool, sizeof(CK_BBOOL) },
+ { CKA_PRIVATE, attrs_priv[priv_en_cka_private].bool, sizeof(CK_BBOOL) },
+ { CKA_SENSITIVE, attrs_priv[priv_en_cka_sensitive].bool, sizeof(CK_BBOOL) },
+ { CKA_SIGN, attrs_priv[priv_en_cka_sign].bool, sizeof(CK_BBOOL) },
+ { CKA_SIGN_RECOVER, attrs_priv[priv_en_cka_sign].bool, sizeof(CK_BBOOL) },
+ { CKA_UNWRAP, attrs_priv[priv_en_cka_unwrap].bool, sizeof(CK_BBOOL) },
+ { CKA_WRAP_WITH_TRUSTED, attrs_priv[priv_en_cka_wrap_with_trusted].bool, sizeof(CK_BBOOL) }
+ };
+
+ rv = self->p11->C_GenerateKeyPair(self->session, &mechanism,
+ publicKeyTemplate, sizeof(publicKeyTemplate) / sizeof(CK_ATTRIBUTE),
+ privateKeyTemplate,
+ sizeof(privateKeyTemplate) / sizeof(CK_ATTRIBUTE), &public_key,
+ &private_key);
+ if (!check_return_value(rv, "generate key pair"))
+ return NULL;
+
+ return Py_BuildValue("(kk)", public_key, private_key);
+}
+
+/**
+ * Find key
+ */
+static PyObject *
+P11_Helper_find_keys(P11_Helper* self, PyObject *args, PyObject *kwds) {
+ CK_OBJECT_CLASS class = CKO_VENDOR_DEFINED;
+ CK_OBJECT_CLASS *class_ptr = &class;
+ CK_BYTE *id = NULL; //TODO free
+ CK_BBOOL *ckawrap = NULL;
+ CK_BBOOL *ckaunwrap = NULL;
+ int id_length = 0;
+ PyObject *label_unicode = NULL;
+ PyObject *cka_wrap_bool = NULL;
+ PyObject *cka_unwrap_bool = NULL;
+ Py_ssize_t label_length = 0;
+ CK_OBJECT_HANDLE *objects = NULL;
+ unsigned int objects_len = 0;
+ PyObject *result_list = NULL;
+ const char *uri_str = NULL; //TODO free?
+ P11KitUri *uri = NULL;
+ CK_BYTE *label = NULL; //TODO free
+ CK_ATTRIBUTE template_static[MAX_TEMPLATE_LEN];
+ CK_ATTRIBUTE_PTR template = template_static;
+ CK_ULONG template_len = MAX_TEMPLATE_LEN;
+
+ static char *kwlist[] = { "objclass", "label", "id", "cka_wrap",
+ "cka_unwrap", "uri", NULL };
+ //TODO check long overflow
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iUz#OOs", kwlist, &class,
+ &label_unicode, &id, &id_length, &cka_wrap_bool, &cka_unwrap_bool,
+ &uri_str)) {
+ return NULL;
+ }
+
+ if (label_unicode != NULL) {
+ Py_INCREF(label_unicode);
+ label = (unsigned char*) unicode_to_char_array(label_unicode,
+ &label_length); //TODO verify signed/unsigned
+ Py_DECREF(label_unicode);
+ }
+
+ if (cka_wrap_bool != NULL) {
+ Py_INCREF(cka_wrap_bool);
+ if (PyObject_IsTrue(cka_wrap_bool)) {
+ ckawrap = &true;
+ } else {
+ ckawrap = &false;
+ }
+ Py_DECREF(cka_wrap_bool);
+ }
+
+ if (cka_unwrap_bool != NULL) {
+ Py_INCREF(cka_unwrap_bool);
+ if (PyObject_IsTrue(cka_unwrap_bool)) {
+ ckaunwrap = &true;
+ } else {
+ ckaunwrap = &false;
+ }
+ Py_DECREF(cka_unwrap_bool);
+ }
+
+ if (class == CKO_VENDOR_DEFINED)
+ class_ptr = NULL;
+
+ if (uri_str == NULL)
+ _fill_template_from_parts(template, &template_len, id, id_length, label,
+ label_length, class_ptr, ckawrap, ckaunwrap);
+ else {
+ if (!_parse_uri(uri_str, &uri))
+ return 0;
+ template = p11_kit_uri_get_attributes(uri, &template_len);
+ /* Do not deallocate URI while you are using the template.
+ * Template contains pointers to values inside URI! */
+ }
+
+ if (!_find_key(self, template, template_len, &objects, &objects_len))
+ return NULL;
+
+ if (uri != NULL)
+ p11_kit_uri_free(uri);
+
+ result_list = PyList_New(objects_len);
+ if (result_list == NULL) {
+ PyErr_SetString(ipap11helperError,
+ "Unable to create list with results");
+ if (objects != NULL) {
+ free(objects);
+ }
+ return NULL;
+ }
+ Py_INCREF(result_list);
+ for (int i = 0; i < objects_len; ++i) {
+ if (PyList_SetItem(result_list, i, Py_BuildValue("k", objects[i]))
+ == -1) {
+ PyErr_SetString(ipap11helperError,
+ "Unable to add to value to result list");
+ if (objects != NULL) {
+ free(objects);
+ }
+ return NULL;
+ }
+ }
+
+ return result_list;
+}
+
+/**
+ * delete key
+ */
+static PyObject *
+P11_Helper_delete_key(P11_Helper* self, PyObject *args, PyObject *kwds) {
+ CK_RV rv;
+ CK_OBJECT_HANDLE key_handle = 0;
+ static char *kwlist[] = { "key_handle", NULL };
+ //TODO check long overflow
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "k|", kwlist, &key_handle)) {
+ return NULL;
+ }
+ rv = self->p11->C_DestroyObject(self->session, key_handle);
+ if (!check_return_value(rv, "object deletion")) {
+ return NULL;
+ }
+
+ return Py_None;
+}
+
+/**
+ * export secret key
+ */
+//TODO remove, we don't want to export secret key
+static PyObject *
+P11_Helper_export_secret_key(P11_Helper* self, PyObject *args, PyObject *kwds) {
+ CK_RV rv;
+ CK_UTF8CHAR_PTR value = NULL;
+ CK_OBJECT_HANDLE key_handle = 0;
+ PyObject *ret = NULL;
+ static char *kwlist[] = { "key_handle", NULL };
+ //TODO check long overflow
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "k|", kwlist, &key_handle)) {
+ return NULL;
+ }
+
+ //TODO which attributes should be returned ????
+ CK_ATTRIBUTE obj_template[] = { { CKA_VALUE, NULL_PTR, 0 } };
+
+ rv = self->p11->C_GetAttributeValue(self->session, key_handle, obj_template,
+ 1);
+ if (!check_return_value(rv, "get attribute value - prepare")) {
+ return NULL;
+ }
+
+ /* Set proper size for attributes*/
+ value = (CK_UTF8CHAR_PTR) malloc(
+ obj_template[0].ulValueLen * sizeof(CK_BYTE));
+ obj_template[0].pValue = value;
+
+ rv = self->p11->C_GetAttributeValue(self->session, key_handle, obj_template,
+ 1);
+ if (!check_return_value(rv, "get attribute value")) {
+ free(value);
+ return NULL;
+ }
+
+ if (obj_template[0].ulValueLen <= 0) {
+ PyErr_SetString(ipap11helperNotFound, "Value not found");
+ free(value);
+ return NULL;
+ }
+ ret = Py_BuildValue("{s:s#}", "value", obj_template[0].pValue,
+ obj_template[0].ulValueLen);
+ free(value);
+ return ret;
+}
+
+/**
+ * export RSA public key
+ */
+static PyObject *
+P11_Helper_export_RSA_public_key(P11_Helper* self, CK_OBJECT_HANDLE object) {
+ CK_RV rv;
+ PyObject *ret = NULL;
+
+ int pp_len;
+ unsigned char *pp = NULL;
+ EVP_PKEY *pkey = NULL;
+ BIGNUM *e = NULL;
+ BIGNUM *n = NULL;
+ RSA *rsa = NULL;
+ CK_BYTE_PTR modulus = NULL;
+ CK_BYTE_PTR exponent = NULL;
+ CK_OBJECT_CLASS class = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE key_type = CKK_RSA;
+
+ CK_ATTRIBUTE obj_template[] = { { CKA_MODULUS, NULL_PTR, 0 }, {
+ CKA_PUBLIC_EXPONENT, NULL_PTR, 0 }, { CKA_CLASS, &class,
+ sizeof(class) }, { CKA_KEY_TYPE, &key_type, sizeof(key_type) } };
+
+ rv = self->p11->C_GetAttributeValue(self->session, object, obj_template, 4);
+ if (!check_return_value(rv, "get RSA public key values - prepare"))
+ return NULL;
+
+ /* Set proper size for attributes*/
+ modulus = (CK_BYTE_PTR) malloc(
+ obj_template[0].ulValueLen * sizeof(CK_BYTE));
+ obj_template[0].pValue = modulus;
+ exponent = (CK_BYTE_PTR) malloc(
+ obj_template[1].ulValueLen * sizeof(CK_BYTE));
+ obj_template[1].pValue = exponent;
+
+ rv = self->p11->C_GetAttributeValue(self->session, object, obj_template, 4);
+ if (!check_return_value(rv, "get RSA public key values"))
+ return NULL;
+
+ /* Check if the key is RSA public key */
+ if (class != CKO_PUBLIC_KEY) {
+ PyErr_SetString(ipap11helperError,
+ "export_RSA_public_key: required public key class");
+ return NULL;
+ }
+
+ if (key_type != CKK_RSA) {
+ PyErr_SetString(ipap11helperError,
+ "export_RSA_public_key: required RSA key type");
+ return NULL;
+ }
+
+ rsa = RSA_new();
+ pkey = EVP_PKEY_new();
+ n = BN_bin2bn((const unsigned char *) modulus,
+ obj_template[0].ulValueLen * sizeof(CK_BYTE), NULL);
+ if (n == NULL) {
+ PyErr_SetString(ipap11helperError,
+ "export_RSA_public_key: internal error: unable to convert modulus");
+ goto final;
+ }
+
+ e = BN_bin2bn((const unsigned char *) exponent,
+ obj_template[1].ulValueLen * sizeof(CK_BYTE), NULL);
+ if (e == NULL) {
+ PyErr_SetString(ipap11helperError,
+ "export_RSA_public_key: internal error: unable to convert exponent");
+ goto final;
+ }
+
+ /* set modulus and exponent */
+ rsa->n = n;
+ rsa->e = e;
+
+ if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) {
+ PyErr_SetString(ipap11helperError,
+ "export_RSA_public_key: internal error: EVP_PKEY_set1_RSA failed");
+ goto final;
+ }
+
+ pp_len = i2d_PUBKEY(pkey, &pp);
+ ret = Py_BuildValue("s#", pp, pp_len);
+
+ final: if (rsa != NULL) {
+ RSA_free(rsa); // this free also 'n' and 'e'
+ } else {
+ if (n != NULL)
+ BN_free(n);
+ if (e != NULL)
+ BN_free(e);
+ }
+
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ if (pp != NULL)
+ free(pp);
+ return ret;
+}
+
+/**
+ * Export public key
+ *
+ * Export public key in SubjectPublicKeyInfo (RFC5280) DER encoded format
+ */
+static PyObject *
+P11_Helper_export_public_key(P11_Helper* self, PyObject *args, PyObject *kwds) {
+ CK_RV rv;
+ CK_OBJECT_HANDLE object = 0;
+ CK_OBJECT_CLASS class = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE key_type = CKK_RSA;
+ static char *kwlist[] = { "key_handle", NULL };
+ //TODO check long overflow
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "k|", kwlist, &object)) {
+ return NULL;
+ }
+
+ CK_ATTRIBUTE obj_template[] = { { CKA_CLASS, &class, sizeof(class) }, {
+ CKA_KEY_TYPE, &key_type, sizeof(key_type) } };
+
+ rv = self->p11->C_GetAttributeValue(self->session, object, obj_template, 2);
+ if (!check_return_value(rv, "export_public_key: get RSA public key values"))
+ return NULL;
+
+ if (class != CKO_PUBLIC_KEY) {
+ PyErr_SetString(ipap11helperError,
+ "export_public_key: required public key class");
+ return NULL;
+ }
+
+ switch (key_type) {
+ case CKK_RSA:
+ return P11_Helper_export_RSA_public_key(self, object);
+ break;
+ default:
+ PyErr_SetString(ipap11helperError,
+ "export_public_key: unsupported key type");
+ }
+
+ return NULL;
+}
+
+/**
+ * Import RSA public key
+ *
+ */
+static PyObject *
+P11_Helper_import_RSA_public_key(P11_Helper* self, CK_UTF8CHAR *label,
+ Py_ssize_t label_length, CK_BYTE *id, Py_ssize_t id_length,
+ EVP_PKEY *pkey, CK_BBOOL* cka_copyable, CK_BBOOL* cka_derive,
+ CK_BBOOL* cka_encrypt, CK_BBOOL* cka_modifiable, CK_BBOOL* cka_private,
+ CK_BBOOL* cka_trusted, CK_BBOOL* cka_verify,
+ CK_BBOOL* cka_verify_recover, CK_BBOOL* cka_wrap) {
+ CK_RV rv;
+ CK_OBJECT_CLASS class = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_BBOOL *cka_token = &true;
+ RSA *rsa = NULL;
+ CK_BYTE_PTR modulus = NULL;
+ int modulus_len = 0;
+ CK_BYTE_PTR exponent = NULL;
+ int exponent_len = 0;
+
+ if (pkey->type != EVP_PKEY_RSA) {
+ PyErr_SetString(ipap11helperError, "Required RSA public key");
+ return NULL;
+ }
+
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL) {
+ PyErr_SetString(ipap11helperError,
+ "import_RSA_public_key: EVP_PKEY_get1_RSA error");
+ free(pkey);
+ return NULL;
+ }
+
+ /* convert BIGNUM to binary array */
+ modulus = (CK_BYTE_PTR) malloc(BN_num_bytes(rsa->n));
+ modulus_len = BN_bn2bin(rsa->n, (unsigned char *) modulus);
+ if (modulus == NULL) {
+ PyErr_SetString(ipap11helperError,
+ "import_RSA_public_key: BN_bn2bin modulus error");
+ //TODO free
+ return NULL;
+ }
+
+ exponent = (CK_BYTE_PTR) malloc(BN_num_bytes(rsa->e));
+ exponent_len = BN_bn2bin(rsa->e, (unsigned char *) exponent);
+ if (exponent == NULL) {
+ PyErr_SetString(ipap11helperError,
+ "import_RSA_public_key: BN_bn2bin exponent error");
+ //TODO free
+ return NULL;
+ }
+
+ CK_ATTRIBUTE template[] = {
+ { CKA_ID, id, id_length },
+ { CKA_CLASS, &class, sizeof(class) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, cka_token, sizeof(CK_BBOOL) },
+ { CKA_LABEL, label, label_length },
+ { CKA_MODULUS, modulus, modulus_len },
+ { CKA_PUBLIC_EXPONENT, exponent, exponent_len },
+ //{CKA_COPYABLE, cka_copyable, sizeof(CK_BBOOL)}, //TODO Softhsm doesn't support it
+ { CKA_DERIVE, cka_derive, sizeof(CK_BBOOL) },
+ { CKA_ENCRYPT, cka_encrypt, sizeof(CK_BBOOL) },
+ { CKA_MODIFIABLE, cka_modifiable, sizeof(CK_BBOOL) },
+ { CKA_PRIVATE, cka_private, sizeof(CK_BBOOL) },
+ { CKA_TRUSTED, cka_trusted, sizeof(CK_BBOOL) },
+ { CKA_VERIFY, cka_verify, sizeof(CK_BBOOL) },
+ { CKA_VERIFY_RECOVER, cka_verify_recover, sizeof(CK_BBOOL) },
+ { CKA_WRAP, cka_wrap, sizeof(CK_BBOOL) }, };
+ CK_OBJECT_HANDLE object;
+
+ rv = self->p11->C_CreateObject(self->session, template,
+ sizeof(template) / sizeof(CK_ATTRIBUTE), &object);
+ if (!check_return_value(rv, "create public key object"))
+ return NULL;
+
+ if (rsa != NULL)
+ RSA_free(rsa);
+
+ return Py_BuildValue("k", object);
+}
+
+/**
+ * Import RSA public key
+ *
+ */
+static PyObject *
+P11_Helper_import_public_key(P11_Helper* self, PyObject *args, PyObject *kwds) {
+ int r;
+ PyObject *ret = NULL;
+ PyObject *label_unicode = NULL;
+ CK_BYTE *id = NULL;
+ CK_BYTE *data = NULL;
+ CK_UTF8CHAR *label = NULL;
+ Py_ssize_t id_length = 0;
+ Py_ssize_t data_length = 0;
+ Py_ssize_t label_length = 0;
+ EVP_PKEY *pkey = NULL;
+
+ PyObj2Bool_mapping_t attrs_pub[] = { { NULL, &true }, //pub_en_cka_copyable
+ { NULL, &false }, //pub_en_cka_derive
+ { NULL, &false }, //pub_en_cka_encrypt
+ { NULL, &true }, //pub_en_cka_modifiable
+ { NULL, &true }, //pub_en_cka_private
+ { NULL, &false }, //pub_en_cka_trusted
+ { NULL, &true }, //pub_en_cka_verify
+ { NULL, &true }, //pub_en_cka_verify_recover
+ { NULL, &false }, //pub_en_cka_wrap
+ };
+
+ static char *kwlist[] = { "label", "id", "data",
+ /* public key attributes */
+ "cka_copyable", "cka_derive", "cka_encrypt", "cka_modifiable",
+ "cka_private", "cka_trusted", "cka_verify", "cka_verify_recover",
+ "cka_wrap", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Us#s#|OOOOOOOOO", kwlist,
+ &label_unicode, &id, &id_length, &data, &data_length,
+ /* public key attributes */
+ &attrs_pub[pub_en_cka_copyable].py_obj,
+ &attrs_pub[pub_en_cka_derive].py_obj,
+ &attrs_pub[pub_en_cka_encrypt].py_obj,
+ &attrs_pub[pub_en_cka_modifiable].py_obj,
+ &attrs_pub[pub_en_cka_private].py_obj,
+ &attrs_pub[pub_en_cka_trusted].py_obj,
+ &attrs_pub[pub_en_cka_verify].py_obj,
+ &attrs_pub[pub_en_cka_verify_recover].py_obj,
+ &attrs_pub[pub_en_cka_wrap].py_obj)) {
+ return NULL;
+ }
+ Py_XINCREF(label_unicode);
+ label = (unsigned char*) unicode_to_char_array(label_unicode,
+ &label_length);
+ Py_XDECREF(label_unicode);
+
+ r = _id_exists(self, id, id_length, CKO_PUBLIC_KEY);
+ if (r == 1) {
+ PyErr_SetString(ipap11helperDuplicationError,
+ "Public key with same ID already exists");
+ return NULL;
+ } else if (r == -1) {
+ return NULL;
+ }
+
+ /* Process keyword boolean arguments */
+ convert_py2bool(attrs_pub,
+ sizeof(attrs_pub) / sizeof(PyObj2Bool_mapping_t));
+
+ /* decode from ASN1 DER */
+ pkey = d2i_PUBKEY(NULL, (const unsigned char **) &data, data_length);
+ if (pkey == NULL) {
+ PyErr_SetString(ipap11helperError,
+ "import_public_key: d2i_PUBKEY error");
+ return NULL;
+ }
+ switch (pkey->type) {
+ case EVP_PKEY_RSA:
+ ret = P11_Helper_import_RSA_public_key(self, label, label_length,
+ id, id_length, pkey, attrs_pub[pub_en_cka_copyable].bool,
+ attrs_pub[pub_en_cka_derive].bool,
+ attrs_pub[pub_en_cka_encrypt].bool,
+ attrs_pub[pub_en_cka_modifiable].bool,
+ attrs_pub[pub_en_cka_private].bool,
+ attrs_pub[pub_en_cka_trusted].bool,
+ attrs_pub[pub_en_cka_verify].bool,
+ attrs_pub[pub_en_cka_verify_recover].bool,
+ attrs_pub[pub_en_cka_wrap].bool);
+ break;
+ case EVP_PKEY_DSA:
+ ret = NULL;
+ PyErr_SetString(ipap11helperError, "DSA is not supported");
+ break;
+ case EVP_PKEY_EC:
+ ret = NULL;
+ PyErr_SetString(ipap11helperError, "EC is not supported");
+ break;
+ default:
+ ret = NULL;
+ PyErr_SetString(ipap11helperError, "Unsupported key type");
+ }
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ return ret;
+}
+
+/**
+ * Export wrapped key
+ *
+ */
+static PyObject *
+P11_Helper_export_wrapped_key(P11_Helper* self, PyObject *args, PyObject *kwds) {
+ CK_RV rv;
+ CK_OBJECT_HANDLE object_key = 0;
+ CK_OBJECT_HANDLE object_wrapping_key = 0;
+ CK_BYTE_PTR wrapped_key = NULL;
+ CK_ULONG wrapped_key_len = 0;
+ CK_MECHANISM wrapping_mech = { CKM_RSA_PKCS, NULL, 0 };
+ CK_MECHANISM_TYPE wrapping_mech_type = CKM_RSA_PKCS;
+ /* currently we don't support parameter in mechanism */
+
+ static char *kwlist[] = { "key", "wrapping_key", "wrapping_mech", NULL };
+ //TODO check long overflow
+ //TODO export method
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "kkk|", kwlist, &object_key,
+ &object_wrapping_key, &wrapping_mech_type)) {
+ return NULL;
+ }
+ wrapping_mech.mechanism = wrapping_mech_type;
+
+ rv = self->p11->C_WrapKey(self->session, &wrapping_mech,
+ object_wrapping_key, object_key, NULL, &wrapped_key_len);
+ if (!check_return_value(rv, "key wrapping: get buffer length"))
+ return 0;
+ wrapped_key = malloc(wrapped_key_len);
+ if (wrapped_key == NULL) {
+ rv = CKR_HOST_MEMORY;
+ check_return_value(rv, "key wrapping: buffer allocation");
+ return 0;
+ }
+ rv = self->p11->C_WrapKey(self->session, &wrapping_mech,
+ object_wrapping_key, object_key, wrapped_key, &wrapped_key_len);
+ if (!check_return_value(rv, "key wrapping: wrapping"))
+ return NULL;
+
+ return Py_BuildValue("s#", wrapped_key, wrapped_key_len);
+
+}
+
+/**
+ * Import wrapped secret key
+ *
+ */
+static PyObject *
+P11_Helper_import_wrapped_secret_key(P11_Helper* self, PyObject *args,
+ PyObject *kwds) {
+ CK_RV rv;
+ int r;
+ CK_BYTE_PTR wrapped_key = NULL;
+ CK_ULONG wrapped_key_len = 0;
+ CK_ULONG unwrapping_key_object = 0;
+ CK_OBJECT_HANDLE unwrapped_key_object = 0;
+ PyObject *label_unicode = NULL;
+ CK_BYTE *id = NULL;
+ CK_UTF8CHAR *label = NULL;
+ Py_ssize_t id_length = 0;
+ Py_ssize_t label_length = 0;
+ CK_MECHANISM wrapping_mech = { CKM_RSA_PKCS, NULL, 0 };
+ CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
+ CK_KEY_TYPE key_type = CKK_RSA;
+
+ PyObj2Bool_mapping_t attrs[] = { { NULL, &true }, //sec_en_cka_copyable
+ { NULL, &false }, //sec_en_cka_decrypt
+ { NULL, &false }, //sec_en_cka_derive
+ { NULL, &false }, //sec_en_cka_encrypt
+ { NULL, &true }, //sec_en_cka_extractable
+ { NULL, &true }, //sec_en_cka_modifiable
+ { NULL, &true }, //sec_en_cka_private
+ { NULL, &true }, //sec_en_cka_sensitive
+ { NULL, &false }, //sec_en_cka_sign
+ { NULL, &true }, //sec_en_cka_unwrap
+ { NULL, &false }, //sec_en_cka_verify
+ { NULL, &true }, //sec_en_cka_wrap
+ { NULL, &false } //sec_en_cka_wrap_with_trusted
+ };
+
+ static char *kwlist[] = { "label", "id", "data", "unwrapping_key",
+ "wrapping_mech", "key_type",
+ // secret key attrs
+ "cka_copyable", "cka_decrypt", "cka_derive", "cka_encrypt",
+ "cka_extractable", "cka_modifiable", "cka_private", "cka_sensitive",
+ "cka_sign", "cka_unwrap", "cka_verify", "cka_wrap",
+ "cka_wrap_with_trusted", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Us#s#kkk|OOOOOOOOOOOOO",
+ kwlist, &label_unicode, &id, &id_length, &wrapped_key,
+ &wrapped_key_len, &unwrapping_key_object, &wrapping_mech.mechanism,
+ &key_type,
+ // secret key attrs
+ &attrs[sec_en_cka_copyable].py_obj,
+ &attrs[sec_en_cka_decrypt].py_obj, &attrs[sec_en_cka_derive].py_obj,
+ &attrs[sec_en_cka_encrypt].py_obj,
+ &attrs[sec_en_cka_extractable].py_obj,
+ &attrs[sec_en_cka_modifiable].py_obj,
+ &attrs[sec_en_cka_private].py_obj,
+ &attrs[sec_en_cka_sensitive].py_obj, &attrs[sec_en_cka_sign].py_obj,
+ &attrs[sec_en_cka_unwrap].py_obj, &attrs[sec_en_cka_verify].py_obj,
+ &attrs[sec_en_cka_wrap].py_obj,
+ &attrs[sec_en_cka_wrap_with_trusted].py_obj)) {
+ return NULL;
+ }
+ Py_XINCREF(label_unicode);
+ label = (unsigned char*) unicode_to_char_array(label_unicode,
+ &label_length); //TODO verify signed/unsigned
+ Py_XDECREF(label_unicode);
+
+ r = _id_exists(self, id, id_length, key_class);
+ if (r == 1) {
+ PyErr_SetString(ipap11helperDuplicationError,
+ "Secret key with same ID already exists");
+ return NULL;
+ } else if (r == -1) {
+ return NULL;
+ }
+
+ /* Process keyword boolean arguments */
+ convert_py2bool(attrs, sizeof(attrs) / sizeof(PyObj2Bool_mapping_t));
+
+ CK_ATTRIBUTE template[] = {
+ { CKA_CLASS, &key_class, sizeof(key_class) },
+ { CKA_KEY_TYPE, &key_type, sizeof(key_type) },
+ { CKA_ID, id, id_length },
+ { CKA_LABEL, label, label_length },
+ { CKA_TOKEN, &true, sizeof(CK_BBOOL) },
+ //{CKA_COPYABLE, attrs[sec_en_cka_copyable].bool, sizeof(CK_BBOOL)}, //TODO Softhsm doesn't support it
+ { CKA_DECRYPT, attrs[sec_en_cka_decrypt].bool, sizeof(CK_BBOOL) },
+ { CKA_DERIVE, attrs[sec_en_cka_derive].bool, sizeof(CK_BBOOL) },
+ { CKA_ENCRYPT, attrs[sec_en_cka_encrypt].bool, sizeof(CK_BBOOL) },
+ { CKA_EXTRACTABLE, attrs[sec_en_cka_extractable].bool, sizeof(CK_BBOOL) },
+ { CKA_MODIFIABLE, attrs[sec_en_cka_modifiable].bool, sizeof(CK_BBOOL) },
+ { CKA_PRIVATE, attrs[sec_en_cka_private].bool, sizeof(CK_BBOOL) },
+ { CKA_SENSITIVE, attrs[sec_en_cka_sensitive].bool, sizeof(CK_BBOOL) },
+ { CKA_SIGN, attrs[sec_en_cka_sign].bool, sizeof(CK_BBOOL) },
+ { CKA_UNWRAP, attrs[sec_en_cka_unwrap].bool, sizeof(CK_BBOOL) },
+ { CKA_VERIFY, attrs[sec_en_cka_verify].bool, sizeof(CK_BBOOL) },
+ { CKA_WRAP, attrs[sec_en_cka_wrap].bool, sizeof(CK_BBOOL) },
+ { CKA_WRAP_WITH_TRUSTED, attrs[sec_en_cka_wrap_with_trusted].bool, sizeof(CK_BBOOL) }
+ };
+
+ rv = self->p11->C_UnwrapKey(self->session, &wrapping_mech,
+ unwrapping_key_object, wrapped_key, wrapped_key_len, template,
+ sizeof(template) / sizeof(CK_ATTRIBUTE), &unwrapped_key_object);
+ if (!check_return_value(rv, "import_wrapped_key: key unwrapping")) {
+ return NULL;
+ }
+
+ return Py_BuildValue("k", unwrapped_key_object);
+
+}
+
+/**
+ * Import wrapped private key
+ *
+ */
+static PyObject *
+P11_Helper_import_wrapped_private_key(P11_Helper* self, PyObject *args,
+ PyObject *kwds) {
+ CK_RV rv;
+ int r;
+ CK_BYTE_PTR wrapped_key = NULL;
+ CK_ULONG wrapped_key_len = 0;
+ CK_ULONG unwrapping_key_object = 0;
+ CK_OBJECT_HANDLE unwrapped_key_object = 0;
+ PyObject *label_unicode = NULL;
+ CK_BYTE *id = NULL;
+ CK_UTF8CHAR *label = NULL;
+ Py_ssize_t id_length = 0;
+ Py_ssize_t label_length = 0;
+ CK_MECHANISM wrapping_mech = { CKM_RSA_PKCS, NULL, 0 };
+ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE key_type = CKK_RSA;
+
+ PyObj2Bool_mapping_t attrs_priv[] = { { NULL, &false }, //priv_en_cka_always_authenticate
+ { NULL, &true }, //priv_en_cka_copyable
+ { NULL, &false }, //priv_en_cka_decrypt
+ { NULL, &false }, //priv_en_cka_derive
+ { NULL, &true }, //priv_en_cka_extractable
+ { NULL, &true }, //priv_en_cka_modifiable
+ { NULL, &true }, //priv_en_cka_private
+ { NULL, &true }, //priv_en_cka_sensitive
+ { NULL, &true }, //priv_en_cka_sign
+ { NULL, &true }, //priv_en_cka_sign_recover
+ { NULL, &false }, //priv_en_cka_unwrap
+ { NULL, &false } //priv_en_cka_wrap_with_trusted
+ };
+
+ static char *kwlist[] = { "label", "id", "data", "unwrapping_key",
+ "wrapping_mech", "key_type",
+ // private key attrs
+ "cka_always_authenticate", "cka_copyable", "cka_decrypt",
+ "cka_derive", "cka_extractable", "cka_modifiable", "cka_private",
+ "cka_sensitive", "cka_sign", "cka_sign_recover", "cka_unwrap",
+ "cka_wrap_with_trusted", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "Us#s#kkk|OOOOOOOOOOOO",
+ kwlist, &label_unicode, &id, &id_length, &wrapped_key,
+ &wrapped_key_len, &unwrapping_key_object, &wrapping_mech.mechanism,
+ &key_type,
+ // private key attrs
+ &attrs_priv[priv_en_cka_always_authenticate].py_obj,
+ &attrs_priv[priv_en_cka_copyable].py_obj,
+ &attrs_priv[priv_en_cka_decrypt].py_obj,
+ &attrs_priv[priv_en_cka_derive].py_obj,
+ &attrs_priv[priv_en_cka_extractable].py_obj,
+ &attrs_priv[priv_en_cka_modifiable].py_obj,
+ &attrs_priv[priv_en_cka_private].py_obj,
+ &attrs_priv[priv_en_cka_sensitive].py_obj,
+ &attrs_priv[priv_en_cka_sign].py_obj,
+ &attrs_priv[priv_en_cka_sign_recover].py_obj,
+ &attrs_priv[priv_en_cka_unwrap].py_obj,
+ &attrs_priv[priv_en_cka_wrap_with_trusted].py_obj)) {
+ return NULL;
+ }
+ Py_XINCREF(label_unicode);
+ label = (unsigned char*) unicode_to_char_array(label_unicode,
+ &label_length); //TODO verify signed/unsigned
+ Py_XDECREF(label_unicode);
+
+ r = _id_exists(self, id, id_length, CKO_SECRET_KEY);
+ if (r == 1) {
+ PyErr_SetString(ipap11helperDuplicationError,
+ "Secret key with same ID already exists");
+ return NULL;
+ } else if (r == -1) {
+ return NULL;
+ }
+
+ /* Process keyword boolean arguments */
+ convert_py2bool(attrs_priv,
+ sizeof(attrs_priv) / sizeof(PyObj2Bool_mapping_t));
+
+ CK_ATTRIBUTE template[] = {
+ { CKA_CLASS, &key_class, sizeof(key_class) },
+ { CKA_KEY_TYPE, &key_type, sizeof(key_type) },
+ { CKA_ID, id, id_length },
+ { CKA_LABEL, label, label_length },
+ { CKA_TOKEN, &true, sizeof(CK_BBOOL) },
+ { CKA_ALWAYS_AUTHENTICATE, attrs_priv[priv_en_cka_always_authenticate].bool, sizeof(CK_BBOOL) },
+ //{CKA_COPYABLE, attrs_priv[priv_en_cka_copyable].bool, sizeof(CK_BBOOL)}, //TODO Softhsm doesn't support it
+ { CKA_DECRYPT, attrs_priv[priv_en_cka_decrypt].bool, sizeof(CK_BBOOL) },
+ { CKA_DERIVE, attrs_priv[priv_en_cka_derive].bool, sizeof(CK_BBOOL) },
+ { CKA_EXTRACTABLE, attrs_priv[priv_en_cka_extractable].bool, sizeof(CK_BBOOL) },
+ { CKA_MODIFIABLE, attrs_priv[priv_en_cka_modifiable].bool, sizeof(CK_BBOOL) },
+ { CKA_PRIVATE, attrs_priv[priv_en_cka_private].bool, sizeof(CK_BBOOL) },
+ { CKA_SENSITIVE, attrs_priv[priv_en_cka_sensitive].bool, sizeof(CK_BBOOL) },
+ { CKA_SIGN, attrs_priv[priv_en_cka_sign].bool, sizeof(CK_BBOOL) },
+ { CKA_SIGN_RECOVER, attrs_priv[priv_en_cka_sign].bool, sizeof(CK_BBOOL) },
+ { CKA_UNWRAP, attrs_priv[priv_en_cka_unwrap].bool, sizeof(CK_BBOOL) },
+ { CKA_WRAP_WITH_TRUSTED, attrs_priv[priv_en_cka_wrap_with_trusted].bool, sizeof(CK_BBOOL) }
+ };
+
+ rv = self->p11->C_UnwrapKey(self->session, &wrapping_mech,
+ unwrapping_key_object, wrapped_key, wrapped_key_len, template,
+ sizeof(template) / sizeof(CK_ATTRIBUTE), &unwrapped_key_object);
+ if (!check_return_value(rv, "import_wrapped_key: key unwrapping")) {
+ return NULL;
+ }
+
+ return PyLong_FromUnsignedLong(unwrapped_key_object);
+
+}
+
+/*
+ * Set object attributes
+ */
+static PyObject *
+P11_Helper_set_attribute(P11_Helper* self, PyObject *args, PyObject *kwds) {
+ PyObject *ret = Py_None;
+ PyObject *value = NULL;
+ CK_ULONG object = 0;
+ unsigned long attr = 0;
+ CK_ATTRIBUTE attribute;
+ CK_RV rv;
+ Py_ssize_t len = 0;
+
+ static char *kwlist[] = { "key_object", "attr", "value", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "kkO|", kwlist, &object, &attr,
+ &value)) {
+ return NULL;
+ }
+ Py_XINCREF(value);
+ attribute.type = attr;
+ switch (attr) {
+ case CKA_ALWAYS_AUTHENTICATE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_COPYABLE:
+ case CKA_ENCRYPT:
+ case CKA_EXTRACTABLE:
+ case CKA_DECRYPT:
+ case CKA_DERIVE:
+ case CKA_LOCAL:
+ case CKA_MODIFIABLE:
+ case CKA_NEVER_EXTRACTABLE:
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_TOKEN:
+ case CKA_TRUSTED:
+ case CKA_UNWRAP:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ case CKA_WRAP_WITH_TRUSTED:
+ attribute.pValue = PyObject_IsTrue(value) ? &true : &false;
+ attribute.ulValueLen = sizeof(CK_BBOOL);
+ break;
+ case CKA_ID:
+ if (!PyString_Check(value)) {
+ PyErr_SetString(ipap11helperError, "String value expected");
+ ret = NULL;
+ goto final;
+ }
+ if (PyString_AsStringAndSize(value, (char **) &attribute.pValue,
+ &attribute.ulValueLen) == -1) {
+ ret = NULL;
+ goto final;
+ }
+ break;
+ case CKA_LABEL:
+ if (!PyUnicode_Check(value)) {
+ PyErr_SetString(ipap11helperError, "Unicode value expected");
+ ret = NULL;
+ goto final;
+ }
+ attribute.pValue = unicode_to_char_array(value, &len);
+ /* check for conversion error */
+ if (attribute.pValue == NULL) {
+ ret = NULL;
+ goto final;
+ }
+ attribute.ulValueLen = len;
+ break;
+ case CKA_KEY_TYPE:
+ if (!PyInt_Check(value)) {
+ PyErr_SetString(ipap11helperError, "Integer value expected");
+ ret = NULL;
+ goto final;
+ }
+ unsigned long lv = PyInt_AsUnsignedLongMask(value);
+ attribute.pValue = &lv;
+ attribute.ulValueLen = sizeof(unsigned long);
+ break;
+ default:
+ ret = NULL;
+ PyErr_SetString(ipap11helperError, "Unknown attribute");
+ goto final;
+ }
+
+ CK_ATTRIBUTE template[] = { attribute };
+
+ rv = self->p11->C_SetAttributeValue(self->session, object, template, 1);
+ if (!check_return_value(rv, "set_attribute"))
+ ret = NULL;
+ final:
+ Py_XDECREF(value);
+ return ret;
+}
+
+/*
+ * Get object attributes
+ */
+static PyObject *
+P11_Helper_get_attribute(P11_Helper* self, PyObject *args, PyObject *kwds) {
+ PyObject *ret = NULL;
+ void *value = NULL;
+ CK_ULONG object = 0;
+ unsigned long attr = 0;
+ CK_ATTRIBUTE attribute;
+ CK_RV rv;
+
+ static char *kwlist[] = { "key_object", "attr", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "kk|", kwlist, &object,
+ &attr)) {
+ return NULL;
+ }
+
+ attribute.type = attr;
+ attribute.pValue = NULL_PTR;
+ attribute.ulValueLen = 0;
+ CK_ATTRIBUTE template[] = { attribute };
+
+ rv = self->p11->C_GetAttributeValue(self->session, object, template, 1);
+ // attribute doesn't exists
+ if (rv == CKR_ATTRIBUTE_TYPE_INVALID
+ || template[0].ulValueLen == (unsigned long) -1) {
+ PyErr_SetString(ipap11helperNotFound, "attribute does not exist");
+ ret = NULL;
+ goto final;
+ }
+ if (!check_return_value(rv, "get_attribute init")) {
+ ret = NULL;
+ goto final;
+ }
+ value = malloc(template[0].ulValueLen);
+ template[0].pValue = value;
+
+ rv = self->p11->C_GetAttributeValue(self->session, object, template, 1);
+ if (!check_return_value(rv, "get_attribute")) {
+ ret = NULL;
+ goto final;
+ }
+
+ switch (attr) {
+ case CKA_ALWAYS_AUTHENTICATE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_COPYABLE:
+ case CKA_ENCRYPT:
+ case CKA_EXTRACTABLE:
+ case CKA_DECRYPT:
+ case CKA_DERIVE:
+ case CKA_LOCAL:
+ case CKA_MODIFIABLE:
+ case CKA_NEVER_EXTRACTABLE:
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_TOKEN:
+ case CKA_TRUSTED:
+ case CKA_UNWRAP:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ case CKA_WRAP_WITH_TRUSTED:
+ /* booleans */
+ ret = PyBool_FromLong(*(CK_BBOOL*) value);
+ break;
+ case CKA_LABEL:
+ /* unicode string */
+ ret = char_array_to_unicode(value, template[0].ulValueLen);
+ break;
+ case CKA_MODULUS:
+ case CKA_PUBLIC_EXPONENT:
+ case CKA_ID:
+ /* byte arrays */
+ ret = Py_BuildValue("s#", value, template[0].ulValueLen);
+ break;
+ case CKA_KEY_TYPE:
+ /* unsigned long */
+ ret = Py_BuildValue("k", *(unsigned long *) value);
+ break;
+ default:
+ ret = NULL;
+ PyErr_SetString(ipap11helperError, "Unknown attribute");
+ goto final;
+ }
+
+ final: if (value != NULL)
+ free(value);
+ return ret;
+}
+
+static PyMethodDef P11_Helper_methods[] = { { "finalize",
+ (PyCFunction) P11_Helper_finalize, METH_NOARGS,
+ "Finalize operations with pkcs11 library" }, { "generate_master_key",
+ (PyCFunction) P11_Helper_generate_master_key, METH_VARARGS
+ | METH_KEYWORDS, "Generate master key" }, {
+ "generate_replica_key_pair",
+ (PyCFunction) P11_Helper_generate_replica_key_pair, METH_VARARGS
+ | METH_KEYWORDS, "Generate replica key pair" }, { "find_keys",
+ (PyCFunction) P11_Helper_find_keys, METH_VARARGS | METH_KEYWORDS,
+ "Find keys" }, { "delete_key", (PyCFunction) P11_Helper_delete_key,
+ METH_VARARGS | METH_KEYWORDS, "Delete key" }, {
+ "export_secret_key", //TODO deprecated, delete it
+ (PyCFunction) P11_Helper_export_secret_key,
+ METH_VARARGS | METH_KEYWORDS, "Export secret key" }, {
+ "export_public_key", (PyCFunction) P11_Helper_export_public_key,
+ METH_VARARGS | METH_KEYWORDS, "Export public key" }, {
+ "import_public_key", (PyCFunction) P11_Helper_import_public_key,
+ METH_VARARGS | METH_KEYWORDS, "Import public key" }, {
+ "export_wrapped_key", (PyCFunction) P11_Helper_export_wrapped_key,
+ METH_VARARGS | METH_KEYWORDS, "Export wrapped private key" }, {
+ "import_wrapped_secret_key",
+ (PyCFunction) P11_Helper_import_wrapped_secret_key, METH_VARARGS
+ | METH_KEYWORDS, "Import wrapped secret key" }, {
+ "import_wrapped_private_key",
+ (PyCFunction) P11_Helper_import_wrapped_private_key, METH_VARARGS
+ | METH_KEYWORDS, "Import wrapped private key" }, {
+ "set_attribute", (PyCFunction) P11_Helper_set_attribute, METH_VARARGS
+ | METH_KEYWORDS, "Set attribute" }, { "get_attribute",
+ (PyCFunction) P11_Helper_get_attribute, METH_VARARGS | METH_KEYWORDS,
+ "Get attribute" }, { NULL } /* Sentinel */
+};
+
+static PyTypeObject P11_HelperType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/
+"_ipap11helper.P11_Helper", /*tp_name*/
+sizeof(P11_Helper), /*tp_basicsize*/
+0, /*tp_itemsize*/
+(destructor) P11_Helper_dealloc, /*tp_dealloc*/
+0, /*tp_print*/
+0, /*tp_getattr*/
+0, /*tp_setattr*/
+0, /*tp_compare*/
+0, /*tp_repr*/
+0, /*tp_as_number*/
+0, /*tp_as_sequence*/
+0, /*tp_as_mapping*/
+0, /*tp_hash */
+0, /*tp_call*/
+0, /*tp_str*/
+0, /*tp_getattro*/
+0, /*tp_setattro*/
+0, /*tp_as_buffer*/
+Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+"P11_Helper objects", /* tp_doc */
+0, /* tp_traverse */
+0, /* tp_clear */
+0, /* tp_richcompare */
+0, /* tp_weaklistoffset */
+0, /* tp_iter */
+0, /* tp_iternext */
+P11_Helper_methods, /* tp_methods */
+P11_Helper_members, /* tp_members */
+0, /* tp_getset */
+0, /* tp_base */
+0, /* tp_dict */
+0, /* tp_descr_get */
+0, /* tp_descr_set */
+0, /* tp_dictoffset */
+(initproc) P11_Helper_init, /* tp_init */
+0, /* tp_alloc */
+P11_Helper_new, /* tp_new */
+};
+
+static PyMethodDef module_methods[] = { { NULL } /* Sentinel */
+};
+
+#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+PyMODINIT_FUNC init_ipap11helper(void) {
+ PyObject* m;
+
+ if (PyType_Ready(&P11_HelperType) < 0)
+ return;
+
+ /*
+ * Setting up P11_Helper module
+ */
+ m = Py_InitModule3("_ipap11helper", module_methods,
+ "Example module that creates an extension type.");
+
+ if (m == NULL)
+ return;
+
+ /*
+ * Setting up P11_Helper
+ */
+ Py_INCREF(&P11_HelperType);
+ PyModule_AddObject(m, "P11_Helper", (PyObject *) &P11_HelperType);
+
+ /*
+ * Setting up P11_Helper Exceptions
+ */
+ ipap11helperException = PyErr_NewException("_ipap11helper.Exception", NULL,
+ NULL);
+ Py_INCREF(ipap11helperException);
+ PyModule_AddObject(m, "Exception", ipap11helperException);
+
+ ipap11helperError = PyErr_NewException("_ipap11helper.Error",
+ ipap11helperException, NULL);
+ Py_INCREF(ipap11helperError);
+ PyModule_AddObject(m, "Error", ipap11helperError);
+
+ ipap11helperNotFound = PyErr_NewException("_ipap11helper.NotFound",
+ ipap11helperException, NULL);
+ Py_INCREF(ipap11helperNotFound);
+ PyModule_AddObject(m, "NotFound", ipap11helperNotFound);
+
+ ipap11helperDuplicationError = PyErr_NewException(
+ "_ipap11helper.DuplicationError", ipap11helperException, NULL);
+ Py_INCREF(ipap11helperDuplicationError);
+ PyModule_AddObject(m, "DuplicationError", ipap11helperDuplicationError);
+
+ /**
+ * Setting up module attributes
+ */
+
+ /* Key Classes*/
+ PyObject *P11_Helper_CLASS_PUBKEY_obj = PyInt_FromLong(CKO_PUBLIC_KEY);
+ PyObject_SetAttrString(m, "KEY_CLASS_PUBLIC_KEY",
+ P11_Helper_CLASS_PUBKEY_obj);
+ Py_XDECREF(P11_Helper_CLASS_PUBKEY_obj);
+
+ PyObject *P11_Helper_CLASS_PRIVKEY_obj = PyInt_FromLong(CKO_PRIVATE_KEY);
+ PyObject_SetAttrString(m, "KEY_CLASS_PRIVATE_KEY",
+ P11_Helper_CLASS_PRIVKEY_obj);
+ Py_XDECREF(P11_Helper_CLASS_PRIVKEY_obj);
+
+ PyObject *P11_Helper_CLASS_SECRETKEY_obj = PyInt_FromLong(CKO_SECRET_KEY);
+ PyObject_SetAttrString(m, "KEY_CLASS_SECRET_KEY",
+ P11_Helper_CLASS_SECRETKEY_obj);
+ Py_XDECREF(P11_Helper_CLASS_SECRETKEY_obj);
+
+ /* Key types*/
+ PyObject *P11_Helper_KEY_TYPE_RSA_obj = PyInt_FromLong(CKK_RSA);
+ PyObject_SetAttrString(m, "KEY_TYPE_RSA", P11_Helper_KEY_TYPE_RSA_obj);
+ Py_XDECREF(P11_Helper_KEY_TYPE_RSA_obj);
+
+ PyObject *P11_Helper_KEY_TYPE_AES_obj = PyInt_FromLong(CKK_AES);
+ PyObject_SetAttrString(m, "KEY_TYPE_AES", P11_Helper_KEY_TYPE_AES_obj);
+ Py_XDECREF(P11_Helper_KEY_TYPE_AES_obj);
+
+ /* Wrapping mech type*/
+ PyObject *P11_Helper_MECH_RSA_PKCS_obj = PyInt_FromLong(CKM_RSA_PKCS);
+ PyObject_SetAttrString(m, "MECH_RSA_PKCS", P11_Helper_MECH_RSA_PKCS_obj);
+ Py_XDECREF(P11_Helper_MECH_RSA_PKCS_obj);
+
+ PyObject *P11_Helper_MECH_RSA_PKCS_OAEP_obj = PyInt_FromLong(
+ CKM_RSA_PKCS_OAEP);
+ PyObject_SetAttrString(m, "MECH_RSA_PKCS_OAEP",
+ P11_Helper_MECH_RSA_PKCS_OAEP_obj);
+ Py_XDECREF(P11_Helper_MECH_RSA_PKCS_OAEP_obj);
+
+ PyObject *P11_Helper_MECH_AES_KEY_WRAP_obj = PyInt_FromLong(
+ CKM_AES_KEY_WRAP);
+ PyObject_SetAttrString(m, "MECH_AES_KEY_WRAP",
+ P11_Helper_MECH_AES_KEY_WRAP_obj);
+ Py_XDECREF(P11_Helper_MECH_AES_KEY_WRAP_obj);
+
+ PyObject *P11_Helper_MECH_AES_KEY_WRAP_PAD_obj = PyInt_FromLong(
+ CKM_AES_KEY_WRAP_PAD);
+ PyObject_SetAttrString(m, "MECH_AES_KEY_WRAP_PAD",
+ P11_Helper_MECH_AES_KEY_WRAP_PAD_obj);
+ Py_XDECREF(P11_Helper_MECH_AES_KEY_WRAP_PAD_obj);
+
+ /* Key attributes */
+ PyObject *P11_Helper_ATTR_CKA_ALWAYS_AUTHENTICATE_obj = PyInt_FromLong(
+ CKA_ALWAYS_AUTHENTICATE);
+ PyObject_SetAttrString(m, "CKA_ALWAYS_AUTHENTICATE",
+ P11_Helper_ATTR_CKA_ALWAYS_AUTHENTICATE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_ALWAYS_AUTHENTICATE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_ALWAYS_SENSITIVE_obj = PyInt_FromLong(
+ CKA_ALWAYS_SENSITIVE);
+ PyObject_SetAttrString(m, "CKA_ALWAYS_SENSITIVE",
+ P11_Helper_ATTR_CKA_ALWAYS_SENSITIVE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_ALWAYS_SENSITIVE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_COPYABLE_obj = PyInt_FromLong(CKA_COPYABLE);
+ PyObject_SetAttrString(m, "CKA_COPYABLE", P11_Helper_ATTR_CKA_COPYABLE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_COPYABLE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_DECRYPT_obj = PyInt_FromLong(CKA_DECRYPT);
+ PyObject_SetAttrString(m, "CKA_DECRYPT", P11_Helper_ATTR_CKA_DECRYPT_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_DECRYPT_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_DERIVE_obj = PyInt_FromLong(CKA_DERIVE);
+ PyObject_SetAttrString(m, "CKA_DERIVE", P11_Helper_ATTR_CKA_DERIVE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_DERIVE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_ENCRYPT_obj = PyInt_FromLong(CKA_ENCRYPT);
+ PyObject_SetAttrString(m, "CKA_ENCRYPT", P11_Helper_ATTR_CKA_ENCRYPT_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_ENCRYPT_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_EXTRACTABLE_obj = PyInt_FromLong(
+ CKA_EXTRACTABLE);
+ PyObject_SetAttrString(m, "CKA_EXTRACTABLE",
+ P11_Helper_ATTR_CKA_EXTRACTABLE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_EXTRACTABLE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_ID_obj = PyInt_FromLong(CKA_ID);
+ PyObject_SetAttrString(m, "CKA_ID", P11_Helper_ATTR_CKA_ID_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_ID_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_KEY_TYPE_obj = PyInt_FromLong(CKA_KEY_TYPE);
+ PyObject_SetAttrString(m, "CKA_KEY_TYPE", P11_Helper_ATTR_CKA_KEY_TYPE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_KEY_TYPE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_LOCAL_obj = PyInt_FromLong(CKA_LOCAL);
+ PyObject_SetAttrString(m, "CKA_LOCAL", P11_Helper_ATTR_CKA_LOCAL_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_LOCAL_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_MODIFIABLE_obj = PyInt_FromLong(
+ CKA_MODIFIABLE);
+ PyObject_SetAttrString(m, "CKA_MODIFIABLE",
+ P11_Helper_ATTR_CKA_MODIFIABLE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_MODIFIABLE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_MODULUS_obj = PyInt_FromLong(CKA_MODULUS);
+ PyObject_SetAttrString(m, "CKA_MODULUS", P11_Helper_ATTR_CKA_MODULUS_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_MODULUS_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_NEVER_EXTRACTABLE_obj = PyInt_FromLong(
+ CKA_NEVER_EXTRACTABLE);
+ PyObject_SetAttrString(m, "CKA_NEVER_EXTRACTABLE",
+ P11_Helper_ATTR_CKA_NEVER_EXTRACTABLE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_NEVER_EXTRACTABLE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_PRIVATE_obj = PyInt_FromLong(CKA_PRIVATE);
+ PyObject_SetAttrString(m, "CKA_PRIVATE", P11_Helper_ATTR_CKA_PRIVATE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_PRIVATE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_PUBLIC_EXPONENT_obj
+ = PyInt_FromLong(CKA_PUBLIC_EXPONENT);
+ PyObject_SetAttrString(m, "CKA_PUBLIC_EXPONENT",
+ P11_Helper_ATTR_CKA_PUBLIC_EXPONENT_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_PUBLIC_EXPONENT_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_SENSITIVE_obj = PyInt_FromLong(CKA_SENSITIVE);
+ PyObject_SetAttrString(m, "CKA_SENSITIVE",
+ P11_Helper_ATTR_CKA_SENSITIVE_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_SENSITIVE_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_SIGN_obj = PyInt_FromLong(CKA_SIGN);
+ PyObject_SetAttrString(m, "CKA_SIGN", P11_Helper_ATTR_CKA_SIGN_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_SIGN_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_SIGN_RECOVER_obj = PyInt_FromLong(
+ CKA_SIGN_RECOVER);
+ PyObject_SetAttrString(m, "CKA_SIGN_RECOVER",
+ P11_Helper_ATTR_CKA_SIGN_RECOVER_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_SIGN_RECOVER_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_TRUSTED_obj = PyInt_FromLong(CKA_TRUSTED);
+ PyObject_SetAttrString(m, "CKA_TRUSTED", P11_Helper_ATTR_CKA_TRUSTED_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_TRUSTED_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_VERIFY_obj = PyInt_FromLong(CKA_VERIFY);
+ PyObject_SetAttrString(m, "CKA_VERIFY", P11_Helper_ATTR_CKA_VERIFY_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_VERIFY_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_VERIFY_RECOVER_obj = PyInt_FromLong(
+ CKA_VERIFY_RECOVER);
+ PyObject_SetAttrString(m, "CKA_VERIFY_RECOVER",
+ P11_Helper_ATTR_CKA_VERIFY_RECOVER_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_VERIFY_RECOVER_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_UNWRAP_obj = PyInt_FromLong(CKA_UNWRAP);
+ PyObject_SetAttrString(m, "CKA_UNWRAP", P11_Helper_ATTR_CKA_UNWRAP_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_UNWRAP_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_WRAP_obj = PyInt_FromLong(CKA_WRAP);
+ PyObject_SetAttrString(m, "CKA_WRAP", P11_Helper_ATTR_CKA_WRAP_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_WRAP_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_WRAP_WITH_TRUSTED_obj = PyInt_FromLong(
+ CKA_WRAP_WITH_TRUSTED);
+ PyObject_SetAttrString(m, "CKA_WRAP_WITH_TRUSTED",
+ P11_Helper_ATTR_CKA_WRAP_WITH_TRUSTED_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_WRAP_WITH_TRUSTED_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_TOKEN_obj = PyInt_FromLong(CKA_TOKEN);
+ PyObject_SetAttrString(m, "CKA_TOKEN", P11_Helper_ATTR_CKA_TOKEN_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_TOKEN_obj);
+
+ PyObject *P11_Helper_ATTR_CKA_LABEL_obj = PyInt_FromLong(CKA_LABEL);
+ PyObject_SetAttrString(m, "CKA_LABEL", P11_Helper_ATTR_CKA_LABEL_obj);
+ Py_XDECREF(P11_Helper_ATTR_CKA_LABEL_obj);
+
+}
diff --git a/ipapython/ipap11helper/setup.py b/ipapython/ipap11helper/setup.py
new file mode 100644
index 000000000..338cdcb2e
--- /dev/null
+++ b/ipapython/ipap11helper/setup.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
+#
+
+from distutils.core import setup, Extension
+from distutils.sysconfig import get_python_inc
+import sys
+import os
+
+python_header = os.path.join(get_python_inc(plat_specific=0), 'Python.h')
+if not os.path.exists(python_header):
+ sys.exit("Cannot find Python development packages that provide Python.h")
+
+module = Extension('_ipap11helper',
+ define_macros = [],
+ include_dirs = [],
+ libraries = ['dl', 'crypto', 'p11-kit'],
+ library_dirs = [],
+ extra_compile_args = [
+ '-std=c99',
+ '-I/usr/include/p11-kit-1',
+ '-ggdb3',
+ '-O2',
+ '-W',
+ '-pedantic',
+ '-Wall',
+ '-Wno-unused-parameter',
+ '-Wbad-function-cast',
+ '-Wextra',
+ ],
+ sources = ['p11helper.c', 'library.c'])
+
+setup(name='_ipap11helper',
+ version='0.1',
+ description='FreeIPA pkcs11 helper',
+ author='Martin Basti, Petr Spacek',
+ author_email='mbasti@redhat.com, pspacek@redhat.com',
+ license='GPLv2+',
+ url='http://www.freeipa.org',
+ long_description="""
+ FreeIPA pkcs11 key manipulation utils.
+""",
+ ext_modules = [module])