2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010,2011 Free Software Foundation
5 * Author: Nikos Mavrogiannopoulos
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 #include <gnutls_int.h>
24 #include <gnutls/pkcs11.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_datum.h>
29 #include <pkcs11_int.h>
30 #include <gnutls_sig.h>
31 #include <p11-kit/uri.h>
33 struct gnutls_pkcs11_privkey_st
35 gnutls_pk_algorithm_t pk_algorithm;
37 struct p11_kit_uri *info;
38 gnutls_pkcs11_pin_callback_t pin_func;
43 * gnutls_pkcs11_privkey_init:
44 * @key: The structure to be initialized
46 * This function will initialize an private key structure.
48 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
49 * negative error value.
52 gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t * key)
54 *key = gnutls_calloc (1, sizeof (struct gnutls_pkcs11_privkey_st));
58 return GNUTLS_E_MEMORY_ERROR;
61 (*key)->info = p11_kit_uri_new ();
62 if ((*key)->info == NULL)
66 return GNUTLS_E_MEMORY_ERROR;
73 * gnutls_pkcs11_privkey_deinit:
74 * @key: The structure to be initialized
76 * This function will deinitialize a private key structure.
79 gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key)
81 p11_kit_uri_free (key->info);
86 * gnutls_pkcs11_privkey_get_pk_algorithm:
87 * @key: should contain a #gnutls_pkcs11_privkey_t structure
89 * This function will return the public key algorithm of a private
92 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
93 * success, or a negative value on error.
96 gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key,
100 *bits = 0; /* FIXME */
101 return key->pk_algorithm;
105 * gnutls_pkcs11_privkey_get_info:
106 * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
107 * @itype: Denotes the type of information requested
108 * @output: where output will be stored
109 * @output_size: contains the maximum size of the output and will be overwritten with actual
111 * This function will return information about the PKCS 11 private key such
112 * as the label, id as well as token information where the key is stored. When
113 * output is text it returns null terminated string although #output_size contains
114 * the size of the actual data only.
116 * Returns: zero on success or a negative value on error.
119 gnutls_pkcs11_privkey_get_info (gnutls_pkcs11_privkey_t pkey,
120 gnutls_pkcs11_obj_info_t itype,
121 void *output, size_t * output_size)
123 return pkcs11_get_info (pkey->info, itype, output, output_size);
127 #define FIND_OBJECT(module, pks, obj, key) \
131 ret = pkcs11_find_object (&module, &pks, &obj, key->info, \
133 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
136 rret = pkcs11_call_token_func (key->info, retries++); \
137 if (rret == 0) continue; \
141 } else if (ret < 0) { \
147 * _gnutls_pkcs11_privkey_sign_hash:
148 * @key: Holds the key
149 * @hash: holds the data to be signed (should be output of a hash)
150 * @signature: will contain the signature allocated with gnutls_malloc()
152 * This function will sign the given data using a signature algorithm
153 * supported by the private key. It is assumed that the given data
154 * are the output of a hash function.
156 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
157 * negative error value.
160 _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key,
161 const gnutls_datum_t * hash,
162 gnutls_datum_t * signature)
166 struct ck_mechanism mech;
167 unsigned long siglen;
168 struct ck_function_list *module;
169 ck_session_handle_t pks;
170 ck_object_handle_t obj;
172 FIND_OBJECT (module, pks, obj, key);
175 key->pk_algorithm == GNUTLS_PK_DSA ? CKM_DSA : CKM_RSA_PKCS;
176 mech.parameter = NULL;
177 mech.parameter_len = 0;
179 /* Initialize signing operation; using the private key discovered
181 rv = pkcs11_sign_init (module, pks, &mech, obj);
185 ret = pkcs11_rv_to_err (rv);
189 /* Work out how long the signature must be: */
190 rv = pkcs11_sign (module, pks, hash->data, hash->size, NULL, &siglen);
194 ret = pkcs11_rv_to_err (rv);
198 signature->data = gnutls_malloc (siglen);
199 signature->size = siglen;
201 rv = pkcs11_sign (module, pks, hash->data, hash->size, signature->data, &siglen);
204 gnutls_free (signature->data);
206 ret = pkcs11_rv_to_err (rv);
210 signature->size = siglen;
215 pkcs11_close_session (module, pks);
221 * gnutls_pkcs11_privkey_import_url:
222 * @pkey: The structure to store the parsed key
223 * @url: a PKCS 11 url identifying the key
224 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
226 * This function will "import" a PKCS 11 URL identifying a private
227 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
228 * in most cases keys cannot be exported, the private key structure
229 * is being associated with the available operations on the token.
231 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
232 * negative error value.
235 gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t pkey,
236 const char *url, unsigned int flags)
239 struct ck_function_list *module;
240 struct ck_attribute *attr;
241 ck_session_handle_t pks;
242 ck_object_handle_t obj;
243 struct ck_attribute a[4];
244 ck_key_type_t key_type;
246 ret = pkcs11_url_to_info (url, &pkey->info);
255 attr = p11_kit_uri_get_attribute (pkey->info, CKA_CLASS);
256 if (!attr || attr->value_len != sizeof (ck_object_class_t) ||
257 *(ck_object_class_t*)attr->value != CKO_PRIVATE_KEY)
260 return GNUTLS_E_INVALID_REQUEST;
263 attr = p11_kit_uri_get_attribute (pkey->info, CKA_ID);
264 if (!attr || !attr->value_len)
267 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
270 FIND_OBJECT (module, pks, obj, pkey);
271 a[0].type = CKA_KEY_TYPE;
272 a[0].value = &key_type;
273 a[0].value_len = sizeof (key_type);
275 if (pkcs11_get_attribute_value (module, pks, obj, a, 1) == CKR_OK)
280 pkey->pk_algorithm = GNUTLS_PK_RSA;
283 pkey->pk_algorithm = GNUTLS_PK_DSA;
286 _gnutls_debug_log("Cannot determine PKCS #11 key algorithm\n");
287 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
295 pkcs11_close_session (module, pks);
301 * _gnutls_pkcs11_privkey_decrypt_data:
302 * @key: Holds the key
303 * @flags: should be 0 for now
304 * @ciphertext: holds the data to be signed
305 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
307 * This function will decrypt the given data using the public key algorithm
308 * supported by the private key.
310 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
311 * negative error value.
314 _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key,
316 const gnutls_datum_t * ciphertext,
317 gnutls_datum_t * plaintext)
321 struct ck_mechanism mech;
322 unsigned long siglen;
323 struct ck_function_list *module;
324 ck_session_handle_t pks;
325 ck_object_handle_t obj;
327 FIND_OBJECT (module, pks, obj, key);
330 key->pk_algorithm == GNUTLS_PK_DSA ? CKM_DSA : CKM_RSA_PKCS;
331 mech.parameter = NULL;
332 mech.parameter_len = 0;
334 /* Initialize signing operation; using the private key discovered
336 rv = pkcs11_decrypt_init (module, pks, &mech, obj);
340 ret = pkcs11_rv_to_err (rv);
344 /* Work out how long the plaintext must be: */
345 rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
350 ret = pkcs11_rv_to_err (rv);
354 plaintext->data = gnutls_malloc (siglen);
355 plaintext->size = siglen;
357 rv = pkcs11_decrypt (module, pks, ciphertext->data, ciphertext->size,
358 plaintext->data, &siglen);
361 gnutls_free (plaintext->data);
363 ret = pkcs11_rv_to_err (rv);
367 plaintext->size = siglen;
372 pkcs11_close_session (module, pks);
378 * gnutls_pkcs11_privkey_export_url:
379 * @key: Holds the PKCS 11 key
380 * @detailed: non zero if a detailed URL is required
381 * @url: will contain an allocated url
383 * This function will export a URL identifying the given key.
385 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
386 * negative error value.
389 gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key,
390 gnutls_pkcs11_url_type_t detailed,
395 ret = pkcs11_info_to_url (key->info, detailed, url);