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 2.1 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 p11_kit_uri *info = NULL;
55 size_t der_size, id_size;
58 struct ck_attribute a[16];
59 ck_object_class_t class = CKO_CERTIFICATE;
60 ck_certificate_type_t type = CKC_X_509;
61 ck_object_handle_t obj;
63 unsigned long category;
64 struct pkcs11_session_info sinfo;
68 memset(&sinfo, 0, sizeof(sinfo));
70 ret = pkcs11_url_to_info(token_url, &info);
77 pkcs11_open_session(&sinfo, NULL, info,
79 pkcs11_obj_flags_to_int(flags));
80 p11_kit_uri_free(info);
89 gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL,
91 if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
96 der = gnutls_malloc(der_size);
99 ret = GNUTLS_E_MEMORY_ERROR;
104 gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der,
111 id_size = sizeof(id);
112 ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL);
114 id_size = sizeof(id);
115 ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
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 = crt->raw_dn.data;
144 a[a_val].value_len = crt->raw_dn.size;
148 a[a_val].type = CKA_LABEL;
149 a[a_val].value = (void *) label;
150 a[a_val].value_len = strlen(label);
154 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
156 a[a_val].type = CKA_CERTIFICATE_CATEGORY;
157 a[a_val].value = (void *) &category;
158 a[a_val].value_len = sizeof(category);
162 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
163 a[a_val].type = CKA_TRUSTED;
164 a[a_val].value = (void *) &tval;
165 a[a_val].value_len = sizeof(tval);
168 a[a_val].type = CKA_PRIVATE;
169 a[a_val].value = (void *) &fval;
170 a[a_val].value_len = sizeof(fval);
173 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE) {
174 a[a_val].type = CKA_PRIVATE;
175 a[a_val].value = (void *) &tval;
176 a[a_val].value_len = sizeof(tval);
178 } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
179 a[a_val].type = CKA_PRIVATE;
180 a[a_val].value = (void *) &fval;
181 a[a_val].value_len = sizeof(fval);
186 rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &obj);
189 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
190 ret = pkcs11_rv_to_err(rv);
201 pkcs11_close_session(&sinfo);
207 * gnutls_pkcs11_copy_x509_privkey:
208 * @token_url: A PKCS #11 URL specifying a token
209 * @key: A private key
210 * @label: A name to be used for the stored data
211 * @key_usage: One of GNUTLS_KEY_*
212 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
214 * This function will copy a private key into a PKCS #11 token specified by
215 * a URL. It is highly recommended flags to contain %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE
216 * unless there is a strong reason not to.
218 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
219 * negative error value.
224 gnutls_pkcs11_copy_x509_privkey(const char *token_url,
225 gnutls_x509_privkey_t key,
227 unsigned int key_usage, unsigned int flags)
230 struct p11_kit_uri *info = NULL;
234 struct ck_attribute a[16];
235 ck_object_class_t class = CKO_PRIVATE_KEY;
236 ck_object_handle_t obj;
239 gnutls_pk_algorithm_t pk;
240 gnutls_datum_t p, q, g, y, x;
241 gnutls_datum_t m, e, d, u, exp1, exp2;
242 struct pkcs11_session_info sinfo;
246 memset(&sinfo, 0, sizeof(sinfo));
248 memset(&p, 0, sizeof(p));
249 memset(&q, 0, sizeof(q));
250 memset(&g, 0, sizeof(g));
251 memset(&y, 0, sizeof(y));
252 memset(&x, 0, sizeof(x));
253 memset(&m, 0, sizeof(m));
254 memset(&e, 0, sizeof(e));
255 memset(&d, 0, sizeof(d));
256 memset(&u, 0, sizeof(u));
257 memset(&exp1, 0, sizeof(exp1));
258 memset(&exp2, 0, sizeof(exp2));
260 ret = pkcs11_url_to_info(token_url, &info);
266 id_size = sizeof(id);
267 ret = gnutls_x509_privkey_get_key_id(key, 0, id, &id_size);
269 p11_kit_uri_free(info);
275 pkcs11_open_session(&sinfo, NULL, info,
277 pkcs11_obj_flags_to_int(flags));
278 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) {
311 a[a_val].type = CKA_PRIVATE;
312 a[a_val].value = (void *) &fval;
313 a[a_val].value_len = sizeof(fval);
316 a[a_val].type = CKA_PRIVATE;
317 a[a_val].value = (void *) &tval;
318 a[a_val].value_len = sizeof(tval);
323 a[a_val].type = CKA_LABEL;
324 a[a_val].value = (void *) label;
325 a[a_val].value_len = strlen(label);
329 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) {
330 a[a_val].type = CKA_SENSITIVE;
331 a[a_val].value = (void *) &tval;
332 a[a_val].value_len = sizeof(tval);
335 a[a_val].type = CKA_SENSITIVE;
336 a[a_val].value = (void *) &fval;
337 a[a_val].value_len = sizeof(fval);
341 pk = gnutls_x509_privkey_get_pk_algorithm(key);
347 gnutls_x509_privkey_export_rsa_raw2(key, &m,
359 a[a_val].type = CKA_MODULUS;
360 a[a_val].value = m.data;
361 a[a_val].value_len = m.size;
364 a[a_val].type = CKA_PUBLIC_EXPONENT;
365 a[a_val].value = e.data;
366 a[a_val].value_len = e.size;
369 a[a_val].type = CKA_PRIVATE_EXPONENT;
370 a[a_val].value = d.data;
371 a[a_val].value_len = d.size;
374 a[a_val].type = CKA_PRIME_1;
375 a[a_val].value = p.data;
376 a[a_val].value_len = p.size;
379 a[a_val].type = CKA_PRIME_2;
380 a[a_val].value = q.data;
381 a[a_val].value_len = q.size;
384 a[a_val].type = CKA_COEFFICIENT;
385 a[a_val].value = u.data;
386 a[a_val].value_len = u.size;
389 a[a_val].type = CKA_EXPONENT_1;
390 a[a_val].value = exp1.data;
391 a[a_val].value_len = exp1.size;
394 a[a_val].type = CKA_EXPONENT_2;
395 a[a_val].value = exp2.data;
396 a[a_val].value_len = exp2.size;
404 gnutls_x509_privkey_export_dsa_raw(key, &p, &q,
413 a[a_val].type = CKA_PRIME;
414 a[a_val].value = p.data;
415 a[a_val].value_len = p.size;
418 a[a_val].type = CKA_SUBPRIME;
419 a[a_val].value = q.data;
420 a[a_val].value_len = q.size;
423 a[a_val].type = CKA_BASE;
424 a[a_val].value = g.data;
425 a[a_val].value_len = g.size;
428 a[a_val].type = CKA_VALUE;
429 a[a_val].value = x.data;
430 a[a_val].value_len = x.size;
438 _gnutls_x509_write_ecc_params(&key->params,
446 _gnutls_mpi_dprint_lz(&key->params.
455 a[a_val].type = CKA_EC_PARAMS;
456 a[a_val].value = p.data;
457 a[a_val].value_len = p.size;
460 a[a_val].type = CKA_VALUE;
461 a[a_val].value = x.data;
462 a[a_val].value_len = x.size;
469 ret = GNUTLS_E_INVALID_REQUEST;
473 rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &obj);
476 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
477 ret = pkcs11_rv_to_err(rv);
493 gnutls_free(exp1.data);
494 gnutls_free(exp2.data);
514 ret = GNUTLS_E_INVALID_REQUEST;
519 pkcs11_close_session(&sinfo);
525 struct delete_data_st {
526 struct p11_kit_uri *info;
527 unsigned int deleted; /* how many */
531 delete_obj_url(struct pkcs11_session_info *sinfo,
532 struct token_info *info,
533 struct ck_info *lib_info, void *input)
535 struct delete_data_st *find_data = input;
536 struct ck_attribute a[4];
537 struct ck_attribute *attr;
538 ck_object_class_t class;
539 ck_certificate_type_t type = (ck_certificate_type_t) - 1;
541 ck_object_handle_t obj;
542 unsigned long count, a_vals;
545 if (info == NULL) { /* we don't support multiple calls */
547 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
550 /* do not bother reading the token if basic fields do not match
552 if (!p11_kit_uri_match_module_info(find_data->info, lib_info) ||
553 !p11_kit_uri_match_token_info(find_data->info, &info->tinfo)) {
555 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
558 /* Find objects with given class and type */
559 class = CKO_CERTIFICATE; /* default */
562 attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
565 && attr->value_len == sizeof(ck_object_class_t))
566 class = *((ck_object_class_t *) attr->value);
567 if (class == CKO_CERTIFICATE)
570 a[a_vals].type = CKA_CLASS;
571 a[a_vals].value = &class;
572 a[a_vals].value_len = sizeof(class);
576 attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
578 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
582 if (type != (ck_certificate_type_t) - 1) {
583 a[a_vals].type = CKA_CERTIFICATE_TYPE;
584 a[a_vals].value = &type;
585 a[a_vals].value_len = sizeof type;
589 attr = p11_kit_uri_get_attribute(find_data->info, CKA_LABEL);
591 memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
595 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
599 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
600 ret = pkcs11_rv_to_err(rv);
604 while (pkcs11_find_objects
605 (sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK
607 rv = pkcs11_destroy_object(sinfo->module, sinfo->pks, obj);
610 ("p11: Cannot destroy object: %s\n",
611 pkcs11_strerror(rv));
613 find_data->deleted++;
621 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
627 pkcs11_find_objects_final(sinfo);
634 * gnutls_pkcs11_delete_url:
635 * @object_url: The URL of the object to delete.
636 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
638 * This function will delete objects matching the given URL.
639 * Note that not all tokens support the delete operation.
641 * Returns: On success, the number of objects deleted is returned, otherwise a
642 * negative error value.
646 int gnutls_pkcs11_delete_url(const char *object_url, unsigned int flags)
649 struct delete_data_st find_data;
653 memset(&find_data, 0, sizeof(find_data));
655 ret = pkcs11_url_to_info(object_url, &find_data.info);
662 _pkcs11_traverse_tokens(delete_obj_url, &find_data,
663 find_data.info, NULL,
665 pkcs11_obj_flags_to_int(flags));
666 p11_kit_uri_free(find_data.info);
673 return find_data.deleted;
678 * gnutls_pkcs11_token_init:
679 * @token_url: A PKCS #11 URL specifying a token
680 * @so_pin: Security Officer's PIN
681 * @label: A name to be used for the token
683 * This function will initialize (format) a token. If the token is
684 * at a factory defaults state the security officer's PIN given will be
685 * set to be the default. Otherwise it should match the officer's PIN.
687 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
688 * negative error value.
691 gnutls_pkcs11_token_init(const char *token_url,
692 const char *so_pin, const char *label)
695 struct p11_kit_uri *info = NULL;
697 struct ck_function_list *module;
703 ret = pkcs11_url_to_info(token_url, &info);
709 ret = pkcs11_find_slot(&module, &slot, info, NULL);
710 p11_kit_uri_free(info);
717 /* so it seems memset has other uses than zeroing! */
718 memset(flabel, ' ', sizeof(flabel));
720 memcpy(flabel, label, strlen(label));
722 rv = pkcs11_init_token(module, slot, (uint8_t *) so_pin,
723 strlen(so_pin), (uint8_t *) flabel);
726 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
727 return pkcs11_rv_to_err(rv);
735 * gnutls_pkcs11_token_set_pin:
736 * @token_url: A PKCS #11 URL specifying a token
737 * @oldpin: old user's PIN
738 * @newpin: new user's PIN
739 * @flags: one of #gnutls_pin_flag_t.
741 * This function will modify or set a user's PIN for the given token.
742 * If it is called to set a user pin for first time the oldpin must
745 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
746 * negative error value.
749 gnutls_pkcs11_token_set_pin(const char *token_url,
751 const char *newpin, unsigned int flags)
754 struct p11_kit_uri *info = NULL;
756 unsigned int ses_flags;
757 struct pkcs11_session_info sinfo;
761 memset(&sinfo, 0, sizeof(sinfo));
763 ret = pkcs11_url_to_info(token_url, &info);
769 if (((flags & GNUTLS_PIN_USER) && oldpin == NULL) ||
770 (flags & GNUTLS_PIN_SO))
771 ses_flags = SESSION_WRITE | SESSION_LOGIN | SESSION_SO;
773 ses_flags = SESSION_WRITE | SESSION_LOGIN;
775 ret = pkcs11_open_session(&sinfo, NULL, info, ses_flags);
776 p11_kit_uri_free(info);
783 if (oldpin == NULL) {
784 rv = pkcs11_init_pin(sinfo.module, sinfo.pks,
785 (uint8_t *) newpin, strlen(newpin));
788 _gnutls_debug_log("p11: %s\n",
789 pkcs11_strerror(rv));
790 ret = pkcs11_rv_to_err(rv);
794 rv = pkcs11_set_pin(sinfo.module, sinfo.pks,
795 oldpin, strlen(oldpin),
796 newpin, strlen(newpin));
799 _gnutls_debug_log("p11: %s\n",
800 pkcs11_strerror(rv));
801 ret = pkcs11_rv_to_err(rv);
809 pkcs11_close_session(&sinfo);
815 * gnutls_pkcs11_token_get_random:
816 * @token_url: A PKCS #11 URL specifying a token
817 * @len: The number of bytes of randomness to request
818 * @rnddata: A pointer to the memory area to be filled with random data
820 * This function will get random data from the given token.
821 * It will store rnddata and fill the memory pointed to by rnddata with
822 * len random bytes from the token.
824 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
825 * negative error value.
828 gnutls_pkcs11_token_get_random(const char *token_url,
829 void *rnddata, size_t len)
832 struct p11_kit_uri *info = NULL;
834 struct pkcs11_session_info sinfo;
838 memset(&sinfo, 0, sizeof(sinfo));
840 ret = pkcs11_url_to_info(token_url, &info);
846 ret = pkcs11_open_session(&sinfo, NULL, info, 0);
847 p11_kit_uri_free(info);
854 rv = _gnutls_pkcs11_get_random(sinfo.module, sinfo.pks, rnddata, len);
857 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
858 ret = pkcs11_rv_to_err(rv);
865 pkcs11_close_session(&sinfo);