summaryrefslogtreecommitdiffstats
path: root/lib/pkcs11_secret.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pkcs11_secret.c')
-rw-r--r--lib/pkcs11_secret.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/lib/pkcs11_secret.c b/lib/pkcs11_secret.c
new file mode 100644
index 0000000..95bbfae
--- /dev/null
+++ b/lib/pkcs11_secret.c
@@ -0,0 +1,150 @@
+/*
+ * GnuTLS PKCS#11 support
+ * Copyright (C) 2010-2012 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos, Stef Walter
+ *
+ * The GnuTLS 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.1 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 program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#include "gnutls_int.h"
+#include <gnutls/pkcs11.h>
+#include <stdio.h>
+#include <string.h>
+#include "errors.h"
+#include <datum.h>
+#include <pkcs11_int.h>
+#include <random.h>
+
+/**
+ * gnutls_pkcs11_copy_secret_key:
+ * @token_url: A PKCS #11 URL specifying a token
+ * @key: The raw key
+ * @label: A name to be used for the stored data
+ * @key_usage: One of GNUTLS_KEY_*
+ * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
+ *
+ * This function will copy a raw secret (symmetric) key into a PKCS #11
+ * token specified by a URL. The key can be marked as sensitive or not.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ *
+ * Since: 2.12.0
+ **/
+int
+gnutls_pkcs11_copy_secret_key(const char *token_url, gnutls_datum_t * key,
+ const char *label,
+ unsigned int key_usage, unsigned int flags
+ /* GNUTLS_PKCS11_OBJ_FLAG_* */ )
+{
+ int ret;
+ struct p11_kit_uri *info = NULL;
+ ck_rv_t rv;
+ struct ck_attribute a[12];
+ ck_object_class_t class = CKO_SECRET_KEY;
+ ck_object_handle_t ctx;
+ ck_key_type_t keytype = CKK_GENERIC_SECRET;
+ ck_bool_t tval = 1;
+ int a_val;
+ uint8_t id[16];
+ struct pkcs11_session_info sinfo;
+
+ PKCS11_CHECK_INIT;
+
+ memset(&sinfo, 0, sizeof(sinfo));
+
+ ret = pkcs11_url_to_info(token_url, &info, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ /* generate a unique ID */
+ ret = gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id));
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret =
+ pkcs11_open_session(&sinfo, NULL, info,
+ SESSION_WRITE |
+ pkcs11_obj_flags_to_int(flags));
+ p11_kit_uri_free(info);
+
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ /* We do not copy key usage flags.
+ */
+ a[0].type = CKA_CLASS;
+ a[0].value = &class;
+ a[0].value_len = sizeof(class);
+ a[1].type = CKA_VALUE;
+ a[1].value = key->data;
+ a[1].value_len = key->size;
+ a[2].type = CKA_TOKEN;
+ a[2].value = &tval;
+ a[2].value_len = sizeof(tval);
+ a[3].type = CKA_PRIVATE;
+ a[3].value = &tval;
+ a[3].value_len = sizeof(tval);
+ a[4].type = CKA_KEY_TYPE;
+ a[4].value = &keytype;
+ a[4].value_len = sizeof(keytype);
+ a[5].type = CKA_ID;
+ a[5].value = id;
+ a[5].value_len = sizeof(id);
+
+ a_val = 6;
+
+ if (label) {
+ a[a_val].type = CKA_LABEL;
+ a[a_val].value = (void *) label;
+ a[a_val].value_len = strlen(label);
+ a_val++;
+ }
+
+ if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE))
+ tval = 1;
+ else
+ tval = 0;
+
+ a[a_val].type = CKA_SENSITIVE;
+ a[a_val].value = &tval;
+ a[a_val].value_len = sizeof(tval);
+ a_val++;
+
+ rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
+ if (rv != CKR_OK) {
+ gnutls_assert();
+ _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
+ ret = pkcs11_rv_to_err(rv);
+ goto cleanup;
+ }
+
+ /* generated!
+ */
+
+ ret = 0;
+
+ cleanup:
+ pkcs11_close_session(&sinfo);
+
+ return ret;
+
+}