summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-09-12 13:51:39 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-09-12 16:32:07 +0200
commit1faeb8bf19a551ead2046c914cd55c7bf583d58e (patch)
tree8d10c7aeca2825bfeaa5fad40b313e8710716d4e
parent76a00c50a4735d799dc1ad492fe5db049e3bc4e6 (diff)
downloadgnutls-1faeb8bf19a551ead2046c914cd55c7bf583d58e.tar.gz
added gnutls_pkcs11_copy_attached_extension()
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/includes/gnutls/pkcs11.h11
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/pkcs11.c67
-rw-r--r--lib/pkcs11_int.h4
-rw-r--r--lib/pkcs11_write.c182
-rw-r--r--lib/pkcs11x.h26
-rw-r--r--lib/verify-tofu.c70
-rw-r--r--lib/x509/common.c55
-rw-r--r--lib/x509/common.h4
10 files changed, 292 insertions, 130 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 6acaf8f9b5..fccc8d430c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -113,7 +113,7 @@ HFILES = abstract_int.h debug.h gnutls_compress.h gnutls_cipher.h \
priority_options.h
if ENABLE_PKCS11
-HFILES += pkcs11_int.h
+HFILES += pkcs11_int.h pkcs11x.h
endif
# Separate so we can create the documentation
diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h
index 93d7ae1f00..d3f6c3faaa 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -179,7 +179,8 @@ int gnutls_pkcs11_copy_x509_privkey(const char *token_url,
/*GNUTLS_KEY_* */ ,
unsigned int flags
/* GNUTLS_PKCS11_OBJ_FLAG_* */
- );
+);
+
int gnutls_pkcs11_delete_url(const char *object_url, unsigned int flags
/* GNUTLS_PKCS11_OBJ_FLAG_* */ );
@@ -395,6 +396,14 @@ int
gnutls_pkcs11_token_get_random(const char *token_url,
void *data, size_t len);
+int
+gnutls_pkcs11_copy_attached_extension(const char *token_url,
+ gnutls_x509_crt_t crt,
+ gnutls_datum_t *data,
+ const char *label,
+ unsigned int flags);
+
+
/* *INDENT-OFF* */
#ifdef __cplusplus
}
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 79ed206991..eabf261eda 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1030,6 +1030,7 @@ GNUTLS_3_1_0 {
gnutls_x509_ext_deinit;
gnutls_x509_ext_print;
gnutls_x509_othername_to_virtual;
+ gnutls_pkcs11_copy_attached_extension;
} GNUTLS_3_0_0;
GNUTLS_FIPS140 {
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index 2e2ea561ad..c5f3e062fc 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -36,7 +36,7 @@
#include <pin.h>
#include <pkcs11_int.h>
#include <p11-kit/p11-kit.h>
-#include <p11-kit/pkcs11x.h>
+#include "pkcs11x.h"
#include <p11-kit/pin.h>
#include <atfork.h>
@@ -1181,41 +1181,60 @@ _pkcs11_traverse_tokens(find_func_t find_func, void *input,
return ret;
}
-/* imports an object from a token to a pkcs11_obj_t structure.
- */
-static int
-pkcs11_obj_import(ck_object_class_t class, gnutls_pkcs11_obj_t obj,
- const gnutls_datum_t * data,
- const gnutls_datum_t * id,
- const gnutls_datum_t * label,
- struct ck_token_info *tinfo, struct ck_info *lib_info)
+ck_object_class_t pkcs11_type_to_class(gnutls_pkcs11_obj_type_t type)
{
- struct ck_attribute attr;
- int ret;
+ switch (type) {
+ case GNUTLS_PKCS11_OBJ_X509_CRT:
+ return CKO_CERTIFICATE;
+ case GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION:
+ return CKO_X_CERTIFICATE_EXTENSION;
+ case GNUTLS_PKCS11_OBJ_PUBKEY:
+ return CKO_PUBLIC_KEY;
+ case GNUTLS_PKCS11_OBJ_PRIVKEY:
+ return CKO_PRIVATE_KEY;
+ case GNUTLS_PKCS11_OBJ_SECRET_KEY:
+ return CKO_SECRET_KEY;
+ case GNUTLS_PKCS11_OBJ_DATA:
+ return CKO_DATA;
+ default:
+ return -1;
+ }
+}
+static gnutls_pkcs11_obj_type_t pkcs11_class_to_type(ck_object_class_t class)
+{
switch (class) {
case CKO_CERTIFICATE:
- obj->type = GNUTLS_PKCS11_OBJ_X509_CRT;
- break;
+ return GNUTLS_PKCS11_OBJ_X509_CRT;
case CKO_X_CERTIFICATE_EXTENSION:
- obj->type = GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION;
- break;
+ return GNUTLS_PKCS11_OBJ_X509_CRT_EXTENSION;
case CKO_PUBLIC_KEY:
- obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
- break;
+ return GNUTLS_PKCS11_OBJ_PUBKEY;
case CKO_PRIVATE_KEY:
- obj->type = GNUTLS_PKCS11_OBJ_PRIVKEY;
- break;
+ return GNUTLS_PKCS11_OBJ_PRIVKEY;
case CKO_SECRET_KEY:
- obj->type = GNUTLS_PKCS11_OBJ_SECRET_KEY;
- break;
+ return GNUTLS_PKCS11_OBJ_SECRET_KEY;
case CKO_DATA:
- obj->type = GNUTLS_PKCS11_OBJ_DATA;
- break;
+ return GNUTLS_PKCS11_OBJ_DATA;
default:
_gnutls_debug_log("unknown pkcs11 object class %x\n", (unsigned)class);
- obj->type = GNUTLS_PKCS11_OBJ_UNKNOWN;
+ return GNUTLS_PKCS11_OBJ_UNKNOWN;
}
+}
+
+/* imports an object from a token to a pkcs11_obj_t structure.
+ */
+static int
+pkcs11_obj_import(ck_object_class_t class, gnutls_pkcs11_obj_t obj,
+ const gnutls_datum_t * data,
+ const gnutls_datum_t * id,
+ const gnutls_datum_t * label,
+ struct ck_token_info *tinfo, struct ck_info *lib_info)
+{
+ struct ck_attribute attr;
+ int ret;
+
+ obj->type = pkcs11_class_to_type(class);
attr.type = CKA_CLASS;
attr.value = &class;
diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h
index 3e932a95ea..18924da750 100644
--- a/lib/pkcs11_int.h
+++ b/lib/pkcs11_int.h
@@ -51,6 +51,8 @@ struct token_info {
struct gnutls_pkcs11_obj_st {
gnutls_datum_t raw;
gnutls_pkcs11_obj_type_t type;
+ ck_object_class_t class;
+
unsigned int flags;
struct p11_kit_uri *info;
@@ -182,6 +184,8 @@ static inline int pk_to_genmech(gnutls_pk_algorithm_t pk, ck_key_type_t *type)
}
}
+ck_object_class_t pkcs11_type_to_class(gnutls_pkcs11_obj_type_t type);
+
ck_rv_t
pkcs11_generate_key_pair(struct ck_function_list * module,
ck_session_handle_t sess,
diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c
index cf4bd1a11e..4eaa07f434 100644
--- a/lib/pkcs11_write.c
+++ b/lib/pkcs11_write.c
@@ -25,10 +25,50 @@
#include <gnutls_errors.h>
#include <gnutls_datum.h>
#include <pkcs11_int.h>
+#include "pkcs11x.h"
+#include <x509/common.h>
static const ck_bool_t tval = 1;
static const ck_bool_t fval = 0;
+#define MAX_ASIZE 16
+
+static void mark_flags(unsigned flags, struct ck_attribute *a, unsigned *a_val)
+{
+ static const unsigned long category = 2;
+
+ if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
+ a[*a_val].type = CKA_CERTIFICATE_CATEGORY;
+ a[*a_val].value = (void *) &category;
+ a[*a_val].value_len = sizeof(category);
+ (*a_val)++;
+ }
+
+ if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
+ a[*a_val].type = CKA_TRUSTED;
+ a[*a_val].value = (void *) &tval;
+ a[*a_val].value_len = sizeof(tval);
+ (*a_val)++;
+
+ a[*a_val].type = CKA_PRIVATE;
+ a[*a_val].value = (void *) &fval;
+ a[*a_val].value_len = sizeof(fval);
+ (*a_val)++;
+ } else {
+ if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE) {
+ a[*a_val].type = CKA_PRIVATE;
+ a[*a_val].value = (void *) &tval;
+ a[*a_val].value_len = sizeof(tval);
+ (*a_val)++;
+ } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
+ a[*a_val].type = CKA_PRIVATE;
+ a[*a_val].value = (void *) &fval;
+ a[*a_val].value_len = sizeof(fval);
+ (*a_val)++;
+ }
+ }
+}
+
/**
* gnutls_pkcs11_copy_x509_crt:
* @token_url: A PKCS #11 URL specifying a token
@@ -37,7 +77,9 @@ static const ck_bool_t fval = 0;
* @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
*
* This function will copy a certificate into a PKCS #11 token specified by
- * a URL. The certificate can be marked as trusted or not.
+ * a URL. Valid flags to mark the certificate: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED,
+ * %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE,
+ * %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA.
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
@@ -55,12 +97,11 @@ gnutls_pkcs11_copy_x509_crt(const char *token_url,
size_t der_size, id_size;
uint8_t *der = NULL;
uint8_t id[20];
- struct ck_attribute a[16];
+ struct ck_attribute a[MAX_ASIZE];
ck_object_class_t class = CKO_CERTIFICATE;
ck_certificate_type_t type = CKC_X_509;
ck_object_handle_t obj;
- int a_val;
- unsigned long category;
+ unsigned a_val;
struct pkcs11_session_info sinfo;
PKCS11_CHECK_INIT;
@@ -151,37 +192,7 @@ gnutls_pkcs11_copy_x509_crt(const char *token_url,
a_val++;
}
- if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
- category = 2;
- a[a_val].type = CKA_CERTIFICATE_CATEGORY;
- a[a_val].value = (void *) &category;
- a[a_val].value_len = sizeof(category);
- a_val++;
- }
-
- if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
- a[a_val].type = CKA_TRUSTED;
- a[a_val].value = (void *) &tval;
- a[a_val].value_len = sizeof(tval);
- a_val++;
-
- a[a_val].type = CKA_PRIVATE;
- a[a_val].value = (void *) &fval;
- a[a_val].value_len = sizeof(fval);
- a_val++;
- } else {
- if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE) {
- a[a_val].type = CKA_PRIVATE;
- a[a_val].value = (void *) &tval;
- a[a_val].value_len = sizeof(tval);
- a_val++;
- } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
- a[a_val].type = CKA_PRIVATE;
- a[a_val].value = (void *) &fval;
- a[a_val].value_len = sizeof(fval);
- a_val++;
- }
- }
+ mark_flags(flags, a, &a_val);
rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &obj);
if (rv != CKR_OK) {
@@ -203,6 +214,107 @@ gnutls_pkcs11_copy_x509_crt(const char *token_url,
}
+
+/**
+ * gnutls_pkcs11_copy_attached_extension:
+ * @token_url: A PKCS #11 URL specifying a token
+ * @obj: A pkcs11 object
+ * @label: A name to be used for the stored data
+ * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
+ *
+ * This function will copy an object into a PKCS #11 token specified by
+ * a URL.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ *
+ * Since: 3.3.8
+ **/
+int
+gnutls_pkcs11_copy_attached_extension(const char *token_url,
+ gnutls_x509_crt_t crt,
+ gnutls_datum_t *data,
+ const char *label,
+ unsigned int flags)
+{
+ int ret;
+ struct p11_kit_uri *info = NULL;
+ ck_rv_t rv;
+ struct ck_attribute a[MAX_ASIZE];
+ ck_object_handle_t hobj;
+ unsigned a_vals;
+ struct pkcs11_session_info sinfo;
+ ck_object_class_t class;
+ gnutls_datum_t spki = {NULL, 0};
+
+ PKCS11_CHECK_INIT;
+
+ memset(&sinfo, 0, sizeof(sinfo));
+
+ ret = pkcs11_url_to_info(token_url, &info);
+ 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;
+ }
+
+ ret = x509_crt_to_raw_pubkey(crt, &spki);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ class = CKO_X_CERTIFICATE_EXTENSION;
+ a_vals = 0;
+ a[a_vals].type = CKA_CLASS;
+ a[a_vals].value = &class;
+ a[a_vals++].value_len = sizeof(class);
+
+ a[a_vals].type = CKA_PUBLIC_KEY_INFO;
+ a[a_vals].value = spki.data;
+ a[a_vals++].value_len = spki.size;
+
+ a[a_vals].type = CKA_VALUE;
+ a[a_vals].value = data->data;
+ a[a_vals++].value_len = data->size;
+
+ a[a_vals].type = CKA_TOKEN;
+ a[a_vals].value = (void *) &tval;
+ a[a_vals++].value_len = sizeof(tval);
+
+ if (label) {
+ a[a_vals].type = CKA_LABEL;
+ a[a_vals].value = (void *) label;
+ a[a_vals++].value_len = strlen(label);
+ }
+
+ rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_vals, &hobj);
+ if (rv != CKR_OK) {
+ gnutls_assert();
+ _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
+ ret = pkcs11_rv_to_err(rv);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ pkcs11_close_session(&sinfo);
+ gnutls_free(spki.data);
+ return ret;
+
+}
+
/**
* gnutls_pkcs11_copy_x509_privkey:
* @token_url: A PKCS #11 URL specifying a token
diff --git a/lib/pkcs11x.h b/lib/pkcs11x.h
new file mode 100644
index 0000000000..0aac3f6f10
--- /dev/null
+++ b/lib/pkcs11x.h
@@ -0,0 +1,26 @@
+/*
+ * GnuTLS PKCS#11 support
+ * Copyright (C) 2014 Red Hat
+ *
+ * Authors: Nikos Mavrogiannopoulos
+ *
+ * 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 <http://www.gnu.org/licenses/>
+ */
+
+#ifndef PKCS11X_H
+#define PKCS11X_H
+
+#include <p11-kit/pkcs11x.h>
+
+#endif
diff --git a/lib/verify-tofu.c b/lib/verify-tofu.c
index c692343529..d646f30b3c 100644
--- a/lib/verify-tofu.c
+++ b/lib/verify-tofu.c
@@ -133,7 +133,7 @@ gnutls_verify_stored_pubkey(const char *db_name,
tdb = &default_tdb;
if (cert_type == GNUTLS_CRT_X509)
- ret = x509_crt_to_raw_pubkey(cert, &pubkey);
+ ret = x509_raw_crt_to_raw_pubkey(cert, &pubkey);
else
ret = pgp_crt_to_raw_pubkey(cert, &pubkey);
@@ -382,72 +382,6 @@ static int raw_pubkey_to_base64(const gnutls_datum_t * raw,
return 0;
}
-/* Converts an X.509 certificate to subjectPublicKeyInfo */
-int x509_crt_to_raw_pubkey(const gnutls_datum_t * cert,
- gnutls_datum_t * rpubkey)
-{
- gnutls_x509_crt_t crt = NULL;
- gnutls_pubkey_t pubkey = NULL;
- size_t size;
- int ret;
-
- ret = gnutls_x509_crt_init(&crt);
- if (ret < 0)
- return gnutls_assert_val(ret);
-
- ret = gnutls_pubkey_init(&pubkey);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret = gnutls_x509_crt_import(crt, cert, GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- size = 0;
- ret =
- gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, NULL, &size);
- if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
- gnutls_assert();
- goto cleanup;
- }
-
- rpubkey->data = gnutls_malloc(size);
- if (rpubkey->data == NULL)
- if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
- ret = GNUTLS_E_MEMORY_ERROR;
- gnutls_assert();
- goto cleanup;
- }
-
- ret =
- gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER,
- rpubkey->data, &size);
- if (ret < 0) {
- gnutls_free(rpubkey->data);
- gnutls_assert();
- goto cleanup;
- }
-
- rpubkey->size = size;
- ret = 0;
-
- cleanup:
- gnutls_x509_crt_deinit(crt);
- gnutls_pubkey_deinit(pubkey);
-
- return ret;
-}
-
static int pgp_crt_to_raw_pubkey(const gnutls_datum_t * cert,
gnutls_datum_t * rpubkey)
{
@@ -654,7 +588,7 @@ gnutls_store_pubkey(const char *db_name,
tdb = &default_tdb;
if (cert_type == GNUTLS_CRT_X509)
- ret = x509_crt_to_raw_pubkey(cert, &pubkey);
+ ret = x509_raw_crt_to_raw_pubkey(cert, &pubkey);
else
ret = pgp_crt_to_raw_pubkey(cert, &pubkey);
if (ret < 0) {
diff --git a/lib/x509/common.c b/lib/x509/common.c
index d85d1b3898..3087183a58 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -1895,3 +1895,58 @@ int _gnutls_copy_data(gnutls_datum_t* str, uint8_t *out, size_t *out_size)
return 0;
}
+
+/* Converts an X.509 certificate to subjectPublicKeyInfo */
+int x509_crt_to_raw_pubkey(gnutls_x509_crt_t crt,
+ gnutls_datum_t * rpubkey)
+{
+ gnutls_pubkey_t pubkey = NULL;
+ int ret;
+
+ ret = gnutls_pubkey_init(&pubkey);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret =
+ gnutls_pubkey_export2(pubkey, GNUTLS_X509_FMT_DER, rpubkey);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ gnutls_pubkey_deinit(pubkey);
+ return ret;
+}
+
+/* Converts an X.509 certificate to subjectPublicKeyInfo */
+int x509_raw_crt_to_raw_pubkey(const gnutls_datum_t * cert,
+ gnutls_datum_t * rpubkey)
+{
+ gnutls_x509_crt_t crt = NULL;
+ int ret;
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = gnutls_x509_crt_import(crt, cert, GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = x509_crt_to_raw_pubkey(crt, rpubkey);
+ cleanup:
+ gnutls_x509_crt_deinit(crt);
+
+ return ret;
+}
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 48340a12c0..582d482bae 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -215,7 +215,9 @@ int _gnutls_copy_data(gnutls_datum_t* str, uint8_t *out, size_t *out_size);
int _san_othername_to_virtual(const char *oid, size_t oid_size);
int _gnutls_x509_decode_ext(const gnutls_datum_t *der, gnutls_x509_ext_st *out);
-int x509_crt_to_raw_pubkey(const gnutls_datum_t * cert,
+int x509_raw_crt_to_raw_pubkey(const gnutls_datum_t * cert,
gnutls_datum_t * rpubkey);
+int x509_crt_to_raw_pubkey(gnutls_x509_crt_t crt,
+ gnutls_datum_t * rpubkey);
#endif