diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-09-12 13:51:39 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-09-12 16:32:07 +0200 |
commit | 1faeb8bf19a551ead2046c914cd55c7bf583d58e (patch) | |
tree | 8d10c7aeca2825bfeaa5fad40b313e8710716d4e | |
parent | 76a00c50a4735d799dc1ad492fe5db049e3bc4e6 (diff) | |
download | gnutls-1faeb8bf19a551ead2046c914cd55c7bf583d58e.tar.gz |
added gnutls_pkcs11_copy_attached_extension()
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/pkcs11.h | 11 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/pkcs11.c | 67 | ||||
-rw-r--r-- | lib/pkcs11_int.h | 4 | ||||
-rw-r--r-- | lib/pkcs11_write.c | 182 | ||||
-rw-r--r-- | lib/pkcs11x.h | 26 | ||||
-rw-r--r-- | lib/verify-tofu.c | 70 | ||||
-rw-r--r-- | lib/x509/common.c | 55 | ||||
-rw-r--r-- | lib/x509/common.h | 4 |
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 |