2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
5 * Authors: Nikos Mavrogiannopoulos, Stef Walter
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 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 Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>
21 #include <gnutls_int.h>
22 #include <gnutls/pkcs11.h>
25 #include <gnutls_errors.h>
26 #include <gnutls_datum.h>
27 #include <pkcs11_int.h>
29 static const ck_bool_t tval = 1;
30 static const ck_bool_t fval = 0;
33 * gnutls_pkcs11_copy_x509_crt:
34 * @token_url: A PKCS #11 URL specifying a token
36 * @label: A name to be used for the stored data
37 * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
39 * This function will copy a certificate into a PKCS #11 token specified by
40 * a URL. The certificate can be marked as trusted or not.
42 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
43 * negative error value.
48 gnutls_pkcs11_copy_x509_crt (const char *token_url,
49 gnutls_x509_crt_t crt, const char *label,
53 struct ck_function_list *module;
54 ck_session_handle_t pks;
55 struct p11_kit_uri *info = NULL;
57 size_t der_size, id_size;
60 struct ck_attribute a[16];
61 ck_object_class_t class = CKO_CERTIFICATE;
62 ck_certificate_type_t type = CKC_X_509;
63 ck_object_handle_t obj;
65 gnutls_datum_t subject = { NULL, 0 };
67 ret = pkcs11_url_to_info (token_url, &info);
75 pkcs11_open_session (&module, &pks, info,
76 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
77 p11_kit_uri_free (info);
85 ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_DER, NULL, &der_size);
86 if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
92 der = gnutls_malloc (der_size);
96 ret = GNUTLS_E_MEMORY_ERROR;
100 ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_DER, der, &der_size);
107 id_size = sizeof (id);
108 ret = gnutls_x509_crt_get_key_id (crt, 0, id, &id_size);
115 ret = gnutls_x509_crt_get_raw_dn (crt, &subject);
122 /* FIXME: copy key usage flags */
124 a[0].type = CKA_CLASS;
126 a[0].value_len = sizeof (class);
129 a[1].value_len = id_size;
130 a[2].type = CKA_VALUE;
132 a[2].value_len = der_size;
133 a[3].type = CKA_TOKEN;
134 a[3].value = (void*)&tval;
135 a[3].value_len = sizeof (tval);
136 a[4].type = CKA_CERTIFICATE_TYPE;
138 a[4].value_len = sizeof (type);
142 a[a_val].type = CKA_SUBJECT;
143 a[a_val].value = subject.data;
144 a[a_val].value_len = subject.size;
149 a[a_val].type = CKA_LABEL;
150 a[a_val].value = (void *) label;
151 a[a_val].value_len = strlen (label);
155 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED)
157 a[a_val].type = CKA_TRUSTED;
158 a[a_val].value = (void*)&tval;
159 a[a_val].value_len = sizeof (tval);
162 a[a_val].type = CKA_PRIVATE;
163 a[a_val].value = (void*)&fval;
164 a[a_val].value_len = sizeof(fval);
169 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE)
171 a[a_val].type = CKA_PRIVATE;
172 a[a_val].value = (void*)&tval;
173 a[a_val].value_len = sizeof(tval);
176 else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
178 a[a_val].type = CKA_PRIVATE;
179 a[a_val].value = (void*)&fval;
180 a[a_val].value_len = sizeof(fval);
185 rv = pkcs11_create_object (module, pks, a, a_val, &obj);
189 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
190 ret = pkcs11_rv_to_err (rv);
201 pkcs11_close_session (module, pks);
202 _gnutls_free_datum(&subject);
208 * gnutls_pkcs11_copy_x509_privkey:
209 * @token_url: A PKCS #11 URL specifying a token
210 * @key: A private key
211 * @label: A name to be used for the stored data
212 * @key_usage: One of GNUTLS_KEY_*
213 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
215 * This function will copy a private key into a PKCS #11 token specified by
216 * a URL. It is highly recommended flags to contain %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE
217 * unless there is a strong reason not to.
219 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
220 * negative error value.
225 gnutls_pkcs11_copy_x509_privkey (const char *token_url,
226 gnutls_x509_privkey_t key,
228 unsigned int key_usage, unsigned int flags)
231 struct ck_function_list *module;
232 ck_session_handle_t pks = 0;
233 struct p11_kit_uri *info = NULL;
237 struct ck_attribute a[16];
238 ck_object_class_t class = CKO_PRIVATE_KEY;
239 ck_object_handle_t obj;
242 gnutls_pk_algorithm_t pk;
243 gnutls_datum_t p, q, g, y, x;
244 gnutls_datum_t m, e, d, u, exp1, exp2;
246 memset(&p, 0, sizeof(p));
247 memset(&q, 0, sizeof(q));
248 memset(&g, 0, sizeof(g));
249 memset(&y, 0, sizeof(y));
250 memset(&x, 0, sizeof(x));
251 memset(&m, 0, sizeof(m));
252 memset(&e, 0, sizeof(e));
253 memset(&d, 0, sizeof(d));
254 memset(&u, 0, sizeof(u));
255 memset(&exp1, 0, sizeof(exp1));
256 memset(&exp2, 0, sizeof(exp2));
258 ret = pkcs11_url_to_info (token_url, &info);
265 id_size = sizeof (id);
266 ret = gnutls_x509_privkey_get_key_id (key, 0, id, &id_size);
269 p11_kit_uri_free (info);
275 pkcs11_open_session (&module, &pks, info,
276 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
277 p11_kit_uri_free (info);
285 /* FIXME: copy key usage flags */
287 a[a_val].type = CKA_CLASS;
288 a[a_val].value = &class;
289 a[a_val].value_len = sizeof (class);
292 a[a_val].type = CKA_ID;
294 a[a_val].value_len = id_size;
297 a[a_val].type = CKA_KEY_TYPE;
298 a[a_val].value = &type;
299 a[a_val].value_len = sizeof (type);
302 a[a_val].type = CKA_TOKEN;
303 a[a_val].value = (void*)&tval;
304 a[a_val].value_len = sizeof (tval);
307 /* a private key is set always as private unless
308 * requested otherwise
310 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE)
312 a[a_val].type = CKA_PRIVATE;
313 a[a_val].value = (void*)&fval;
314 a[a_val].value_len = sizeof(fval);
319 a[a_val].type = CKA_PRIVATE;
320 a[a_val].value = (void*)&tval;
321 a[a_val].value_len = sizeof (tval);
327 a[a_val].type = CKA_LABEL;
328 a[a_val].value = (void *) label;
329 a[a_val].value_len = strlen (label);
333 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE)
335 a[a_val].type = CKA_SENSITIVE;
336 a[a_val].value = (void*)&tval;
337 a[a_val].value_len = sizeof (tval);
342 a[a_val].type = CKA_SENSITIVE;
343 a[a_val].value = (void*)&fval;
344 a[a_val].value_len = sizeof (fval);
348 pk = gnutls_x509_privkey_get_pk_algorithm (key);
355 gnutls_x509_privkey_export_rsa_raw2 (key, &m,
357 &q, &u, &exp1, &exp2);
366 a[a_val].type = CKA_MODULUS;
367 a[a_val].value = m.data;
368 a[a_val].value_len = m.size;
371 a[a_val].type = CKA_PUBLIC_EXPONENT;
372 a[a_val].value = e.data;
373 a[a_val].value_len = e.size;
376 a[a_val].type = CKA_PRIVATE_EXPONENT;
377 a[a_val].value = d.data;
378 a[a_val].value_len = d.size;
381 a[a_val].type = CKA_PRIME_1;
382 a[a_val].value = p.data;
383 a[a_val].value_len = p.size;
386 a[a_val].type = CKA_PRIME_2;
387 a[a_val].value = q.data;
388 a[a_val].value_len = q.size;
391 a[a_val].type = CKA_COEFFICIENT;
392 a[a_val].value = u.data;
393 a[a_val].value_len = u.size;
396 a[a_val].type = CKA_EXPONENT_1;
397 a[a_val].value = exp1.data;
398 a[a_val].value_len = exp1.size;
401 a[a_val].type = CKA_EXPONENT_2;
402 a[a_val].value = exp2.data;
403 a[a_val].value_len = exp2.size;
410 ret = gnutls_x509_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
419 a[a_val].type = CKA_PRIME;
420 a[a_val].value = p.data;
421 a[a_val].value_len = p.size;
424 a[a_val].type = CKA_SUBPRIME;
425 a[a_val].value = q.data;
426 a[a_val].value_len = q.size;
429 a[a_val].type = CKA_BASE;
430 a[a_val].value = g.data;
431 a[a_val].value_len = g.size;
434 a[a_val].type = CKA_VALUE;
435 a[a_val].value = x.data;
436 a[a_val].value_len = x.size;
443 ret = _gnutls_x509_write_ecc_params(&key->params, &p);
450 ret = _gnutls_mpi_dprint_lz(&key->params.params[ECC_K], &x);
459 a[a_val].type = CKA_EC_PARAMS;
460 a[a_val].value = p.data;
461 a[a_val].value_len = p.size;
464 a[a_val].type = CKA_VALUE;
465 a[a_val].value = x.data;
466 a[a_val].value_len = x.size;
473 ret = GNUTLS_E_INVALID_REQUEST;
477 rv = pkcs11_create_object (module, pks, a, a_val, &obj);
481 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
482 ret = pkcs11_rv_to_err (rv);
493 gnutls_free (m.data);
494 gnutls_free (e.data);
495 gnutls_free (d.data);
496 gnutls_free (p.data);
497 gnutls_free (q.data);
498 gnutls_free (u.data);
499 gnutls_free (exp1.data);
500 gnutls_free (exp2.data);
505 gnutls_free (p.data);
506 gnutls_free (q.data);
507 gnutls_free (g.data);
508 gnutls_free (y.data);
509 gnutls_free (x.data);
514 gnutls_free (p.data);
515 gnutls_free (x.data);
520 ret = GNUTLS_E_INVALID_REQUEST;
525 pkcs11_close_session (module, pks);
531 struct delete_data_st
533 struct p11_kit_uri *info;
534 unsigned int deleted; /* how many */
538 delete_obj_url (struct ck_function_list *module,
539 ck_session_handle_t pks,
540 struct token_info *info,
541 struct ck_info *lib_info, void *input)
543 struct delete_data_st *find_data = input;
544 struct ck_attribute a[4];
545 struct ck_attribute *attr;
546 ck_object_class_t class;
547 ck_certificate_type_t type = (ck_certificate_type_t)-1;
549 ck_object_handle_t obj;
550 unsigned long count, a_vals;
555 { /* we don't support multiple calls */
557 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
560 /* do not bother reading the token if basic fields do not match
562 if (!p11_kit_uri_match_module_info (find_data->info, lib_info) ||
563 !p11_kit_uri_match_token_info (find_data->info, &info->tinfo))
566 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
569 /* Find objects with given class and type */
570 class = CKO_CERTIFICATE; /* default */
573 attr = p11_kit_uri_get_attribute (find_data->info, CKA_CLASS);
576 if(attr->value && attr->value_len == sizeof (ck_object_class_t))
577 class = *((ck_object_class_t*)attr->value);
578 if (class == CKO_CERTIFICATE)
582 a[a_vals].type = CKA_CLASS;
583 a[a_vals].value = &class;
584 a[a_vals].value_len = sizeof (class);
587 attr = p11_kit_uri_get_attribute (find_data->info, CKA_ID);
590 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
594 if (type != (ck_certificate_type_t)-1)
596 a[a_vals].type = CKA_CERTIFICATE_TYPE;
597 a[a_vals].value = &type;
598 a[a_vals].value_len = sizeof type;
602 attr = p11_kit_uri_get_attribute (find_data->info, CKA_LABEL);
605 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
609 rv = pkcs11_find_objects_init (module, pks, a, a_vals);
613 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
614 ret = pkcs11_rv_to_err (rv);
618 while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1)
620 rv = pkcs11_destroy_object (module, pks, obj);
624 ("pkcs11: Cannot destroy object: %s\n", pkcs11_strerror (rv));
628 find_data->deleted++;
637 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
645 pkcs11_find_objects_final (module, pks);
652 * gnutls_pkcs11_delete_url:
653 * @object_url: The URL of the object to delete.
654 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
656 * This function will delete objects matching the given URL.
657 * Note that not all tokens support the delete operation.
659 * Returns: On success, the number of objects deleted is returned, otherwise a
660 * negative error value.
665 gnutls_pkcs11_delete_url (const char *object_url, unsigned int flags)
668 struct delete_data_st find_data;
670 memset (&find_data, 0, sizeof (find_data));
672 ret = pkcs11_url_to_info (object_url, &find_data.info);
680 _pkcs11_traverse_tokens (delete_obj_url, &find_data, find_data.info,
681 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
682 p11_kit_uri_free (find_data.info);
690 return find_data.deleted;
695 * gnutls_pkcs11_token_init:
696 * @token_url: A PKCS #11 URL specifying a token
697 * @so_pin: Security Officer's PIN
698 * @label: A name to be used for the token
700 * This function will initialize (format) a token. If the token is
701 * at a factory defaults state the security officer's PIN given will be
702 * set to be the default. Otherwise it should match the officer's PIN.
704 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
705 * negative error value.
708 gnutls_pkcs11_token_init (const char *token_url,
709 const char *so_pin, const char *label)
712 struct p11_kit_uri *info = NULL;
714 struct ck_function_list *module;
718 ret = pkcs11_url_to_info (token_url, &info);
725 ret = pkcs11_find_slot (&module, &slot, info, NULL);
726 p11_kit_uri_free (info);
734 /* so it seems memset has other uses than zeroing! */
735 memset (flabel, ' ', sizeof (flabel));
737 memcpy (flabel, label, strlen (label));
740 pkcs11_init_token (module, slot, (uint8_t*)so_pin, strlen (so_pin),
745 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
746 return pkcs11_rv_to_err (rv);
754 * gnutls_pkcs11_token_set_pin:
755 * @token_url: A PKCS #11 URL specifying a token
756 * @oldpin: old user's PIN
757 * @newpin: new user's PIN
758 * @flags: one of #gnutls_pkcs11_pin_flag_t.
760 * This function will modify or set a user's PIN for the given token.
761 * If it is called to set a user pin for first time the oldpin must
764 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
765 * negative error value.
768 gnutls_pkcs11_token_set_pin (const char *token_url,
770 const char *newpin, unsigned int flags)
773 struct ck_function_list *module;
774 ck_session_handle_t pks;
775 struct p11_kit_uri *info = NULL;
777 unsigned int ses_flags;
779 ret = pkcs11_url_to_info (token_url, &info);
786 if (((flags & GNUTLS_PKCS11_PIN_USER) && oldpin == NULL) ||
787 (flags & GNUTLS_PKCS11_PIN_SO))
788 ses_flags = SESSION_WRITE | SESSION_LOGIN | SESSION_SO;
790 ses_flags = SESSION_WRITE | SESSION_LOGIN;
792 ret = pkcs11_open_session (&module, &pks, info, ses_flags);
793 p11_kit_uri_free (info);
803 rv = pkcs11_init_pin (module, pks, (uint8_t *) newpin, strlen (newpin));
807 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
808 ret = pkcs11_rv_to_err (rv);
814 rv = pkcs11_set_pin (module, pks,
815 oldpin, strlen (oldpin),
816 newpin, strlen (newpin));
820 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
821 ret = pkcs11_rv_to_err (rv);
829 pkcs11_close_session (module, pks);