Line data Source code
1 : /* 2 : * GnuTLS PKCS#11 support 3 : * Copyright (C) 2010-2012 Free Software Foundation, Inc. 4 : * 5 : * Author: Nikos Mavrogiannopoulos, Stef Walter 6 : * 7 : * The GnuTLS is free software; you can redistribute it and/or 8 : * modify it under the terms of the GNU Lesser General Public License 9 : * as published by the Free Software Foundation; either version 2.1 of 10 : * the License, or (at your option) any later version. 11 : * 12 : * This library is distributed in the hope that it will be useful, but 13 : * WITHOUT ANY WARRANTY; without even the implied warranty of 14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 : * Lesser General Public License for more details. 16 : * 17 : * You should have received a copy of the GNU Lesser General Public License 18 : * along with this program. If not, see <https://www.gnu.org/licenses/> 19 : */ 20 : 21 : #include "gnutls_int.h" 22 : #include <gnutls/pkcs11.h> 23 : #include <stdio.h> 24 : #include <string.h> 25 : #include "errors.h" 26 : #include <datum.h> 27 : #include <pkcs11_int.h> 28 : #include <random.h> 29 : 30 : /** 31 : * gnutls_pkcs11_copy_secret_key: 32 : * @token_url: A PKCS #11 URL specifying a token 33 : * @key: The raw key 34 : * @label: A name to be used for the stored data 35 : * @key_usage: One of GNUTLS_KEY_* 36 : * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_* 37 : * 38 : * This function will copy a raw secret (symmetric) key into a PKCS #11 39 : * token specified by a URL. The key can be marked as sensitive or not. 40 : * 41 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a 42 : * negative error value. 43 : * 44 : * Since: 2.12.0 45 : **/ 46 : int 47 0 : gnutls_pkcs11_copy_secret_key(const char *token_url, gnutls_datum_t * key, 48 : const char *label, 49 : unsigned int key_usage, unsigned int flags 50 : /* GNUTLS_PKCS11_OBJ_FLAG_* */ ) 51 : { 52 0 : int ret; 53 0 : struct p11_kit_uri *info = NULL; 54 0 : ck_rv_t rv; 55 0 : struct ck_attribute a[12]; 56 0 : ck_object_class_t class = CKO_SECRET_KEY; 57 0 : ck_object_handle_t ctx; 58 0 : ck_key_type_t keytype = CKK_GENERIC_SECRET; 59 0 : ck_bool_t tval = 1; 60 0 : int a_val; 61 0 : uint8_t id[16]; 62 0 : struct pkcs11_session_info sinfo; 63 : 64 0 : PKCS11_CHECK_INIT; 65 : 66 0 : memset(&sinfo, 0, sizeof(sinfo)); 67 : 68 0 : ret = pkcs11_url_to_info(token_url, &info, 0); 69 0 : if (ret < 0) { 70 0 : gnutls_assert(); 71 0 : return ret; 72 : } 73 : 74 : /* generate a unique ID */ 75 0 : ret = gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id)); 76 0 : if (ret < 0) { 77 0 : gnutls_assert(); 78 0 : return ret; 79 : } 80 : 81 0 : ret = 82 0 : pkcs11_open_session(&sinfo, NULL, info, 83 : SESSION_WRITE | 84 0 : pkcs11_obj_flags_to_int(flags)); 85 0 : p11_kit_uri_free(info); 86 : 87 0 : if (ret < 0) { 88 0 : gnutls_assert(); 89 0 : return ret; 90 : } 91 : 92 : /* We do not copy key usage flags. 93 : */ 94 0 : a[0].type = CKA_CLASS; 95 0 : a[0].value = &class; 96 0 : a[0].value_len = sizeof(class); 97 0 : a[1].type = CKA_VALUE; 98 0 : a[1].value = key->data; 99 0 : a[1].value_len = key->size; 100 0 : a[2].type = CKA_TOKEN; 101 0 : a[2].value = &tval; 102 0 : a[2].value_len = sizeof(tval); 103 0 : a[3].type = CKA_PRIVATE; 104 0 : a[3].value = &tval; 105 0 : a[3].value_len = sizeof(tval); 106 0 : a[4].type = CKA_KEY_TYPE; 107 0 : a[4].value = &keytype; 108 0 : a[4].value_len = sizeof(keytype); 109 0 : a[5].type = CKA_ID; 110 0 : a[5].value = id; 111 0 : a[5].value_len = sizeof(id); 112 : 113 0 : a_val = 6; 114 : 115 0 : if (label) { 116 0 : a[a_val].type = CKA_LABEL; 117 0 : a[a_val].value = (void *) label; 118 0 : a[a_val].value_len = strlen(label); 119 0 : a_val++; 120 : } 121 : 122 0 : if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) 123 0 : tval = 1; 124 : else 125 0 : tval = 0; 126 : 127 0 : a[a_val].type = CKA_SENSITIVE; 128 0 : a[a_val].value = &tval; 129 0 : a[a_val].value_len = sizeof(tval); 130 0 : a_val++; 131 : 132 0 : rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx); 133 0 : if (rv != CKR_OK) { 134 0 : gnutls_assert(); 135 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv)); 136 0 : ret = pkcs11_rv_to_err(rv); 137 0 : goto cleanup; 138 : } 139 : 140 : /* generated! 141 : */ 142 : 143 : ret = 0; 144 : 145 0 : cleanup: 146 0 : pkcs11_close_session(&sinfo); 147 : 148 0 : return ret; 149 : 150 : }