]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
added gnutls_pkcs11_copy_attached_extension()
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 12 Sep 2014 11:51:39 +0000 (13:51 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 12 Sep 2014 14:32:07 +0000 (16:32 +0200)
lib/Makefile.am
lib/includes/gnutls/pkcs11.h
lib/libgnutls.map
lib/pkcs11.c
lib/pkcs11_int.h
lib/pkcs11_write.c
lib/pkcs11x.h [new file with mode: 0644]
lib/verify-tofu.c
lib/x509/common.c
lib/x509/common.h

index 6acaf8f9b58b266a9b547101799851cef95b043b..fccc8d430c2bc0bf2280153728fecec241ec85b9 100644 (file)
@@ -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
index 93d7ae1f008b3d2366c73f60e4837c2b2386a7db..d3f6c3faaa536e53ad8472bb615904c1e0431193 100644 (file)
@@ -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
 }
index 79ed206991d9a1228d25c7ff8bbed1b483e03f56..eabf261edab15129174797bfbd1f6eaaa79268cd 100644 (file)
@@ -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 {
index 2e2ea561ad3d641d982bc69fd566c6e94d34cb43..c5f3e062fc9d20320451fd8a779667d423e9b89e 100644 (file)
@@ -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;
index 3e932a95eac9023809bcad3dba02e61c5fda0238..18924da75000c8883d48a92b7e4599b4b774338e 100644 (file)
@@ -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,
index cf4bd1a11ee0240f51ba35f3adb21be3b72bad8e..4eaa07f434128e6a798e28dae9d08dd3f03c3d5b 100644 (file)
 #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 (file)
index 0000000..0aac3f6
--- /dev/null
@@ -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
index c6923435290b87b4ca39e5541a12c4e26c5b36d4..d646f30b3c78eb9b829b5ebccfcdaaa5fff216a6 100644 (file)
@@ -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) {
index d85d1b3898e68a2c88baa1cb16b6c08082124093..3087183a58936d40e87de074bcc846afb6e0e311 100644 (file)
@@ -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;
+}
index 48340a12c0fdace8a78db66fba1b1dde8700d6f4..582d482bae1f86302e3dc553e4b0cb9f1947a556 100644 (file)
@@ -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