Correctly restore gnutls_record_recv() in DTLS mode if interrupted during the retrasm...
[gnutls.git] / lib / pkcs11_write.c
blobaa474a6694beea484fae6a1cd4f3c445a43fa079
1 /*
2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 *
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>
23 #include <stdio.h>
24 #include <string.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;
32 /**
33 * gnutls_pkcs11_copy_x509_crt:
34 * @token_url: A PKCS #11 URL specifying a token
35 * @crt: A certificate
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.
45 * Since: 2.12.0
46 **/
47 int
48 gnutls_pkcs11_copy_x509_crt (const char *token_url,
49 gnutls_x509_crt_t crt, const char *label,
50 unsigned int flags)
52 int ret;
53 struct ck_function_list *module;
54 ck_session_handle_t pks;
55 struct p11_kit_uri *info = NULL;
56 ck_rv_t rv;
57 size_t der_size, id_size;
58 uint8_t *der = NULL;
59 uint8_t id[20];
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;
64 int a_val;
65 gnutls_datum_t subject = { NULL, 0 };
67 ret = pkcs11_url_to_info (token_url, &info);
68 if (ret < 0)
70 gnutls_assert ();
71 return ret;
74 ret =
75 pkcs11_open_session (&module, &pks, info,
76 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
77 p11_kit_uri_free (info);
79 if (ret < 0)
81 gnutls_assert ();
82 return ret;
85 ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_DER, NULL, &der_size);
86 if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
88 gnutls_assert ();
89 goto cleanup;
92 der = gnutls_malloc (der_size);
93 if (der == NULL)
95 gnutls_assert ();
96 ret = GNUTLS_E_MEMORY_ERROR;
97 goto cleanup;
100 ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_DER, der, &der_size);
101 if (ret < 0)
103 gnutls_assert ();
104 goto cleanup;
107 id_size = sizeof (id);
108 ret = gnutls_x509_crt_get_key_id (crt, 0, id, &id_size);
109 if (ret < 0)
111 gnutls_assert ();
112 goto cleanup;
115 ret = gnutls_x509_crt_get_raw_dn (crt, &subject);
116 if (ret < 0)
118 gnutls_assert ();
119 goto cleanup;
122 /* FIXME: copy key usage flags */
124 a[0].type = CKA_CLASS;
125 a[0].value = &class;
126 a[0].value_len = sizeof (class);
127 a[1].type = CKA_ID;
128 a[1].value = id;
129 a[1].value_len = id_size;
130 a[2].type = CKA_VALUE;
131 a[2].value = der;
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;
137 a[4].value = &type;
138 a[4].value_len = sizeof (type);
140 a_val = 5;
142 a[a_val].type = CKA_SUBJECT;
143 a[a_val].value = subject.data;
144 a[a_val].value_len = subject.size;
145 a_val++;
147 if (label)
149 a[a_val].type = CKA_LABEL;
150 a[a_val].value = (void *) label;
151 a[a_val].value_len = strlen (label);
152 a_val++;
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);
160 a_val++;
162 a[a_val].type = CKA_PRIVATE;
163 a[a_val].value = (void*)&fval;
164 a[a_val].value_len = sizeof(fval);
165 a_val++;
167 else
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);
174 a_val++;
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);
181 a_val++;
185 rv = pkcs11_create_object (module, pks, a, a_val, &obj);
186 if (rv != CKR_OK)
188 gnutls_assert ();
189 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
190 ret = pkcs11_rv_to_err (rv);
191 goto cleanup;
194 /* generated!
197 ret = 0;
199 cleanup:
200 gnutls_free (der);
201 pkcs11_close_session (module, pks);
202 _gnutls_free_datum(&subject);
203 return ret;
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.
222 * Since: 2.12.0
225 gnutls_pkcs11_copy_x509_privkey (const char *token_url,
226 gnutls_x509_privkey_t key,
227 const char *label,
228 unsigned int key_usage, unsigned int flags)
230 int ret;
231 struct ck_function_list *module;
232 ck_session_handle_t pks = 0;
233 struct p11_kit_uri *info = NULL;
234 ck_rv_t rv;
235 size_t id_size;
236 uint8_t id[20];
237 struct ck_attribute a[16];
238 ck_object_class_t class = CKO_PRIVATE_KEY;
239 ck_object_handle_t obj;
240 ck_key_type_t type;
241 int a_val;
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);
259 if (ret < 0)
261 gnutls_assert ();
262 return ret;
265 id_size = sizeof (id);
266 ret = gnutls_x509_privkey_get_key_id (key, 0, id, &id_size);
267 if (ret < 0)
269 p11_kit_uri_free (info);
270 gnutls_assert ();
271 return ret;
274 ret =
275 pkcs11_open_session (&module, &pks, info,
276 SESSION_WRITE | pkcs11_obj_flags_to_int (flags));
277 p11_kit_uri_free (info);
279 if (ret < 0)
281 gnutls_assert ();
282 return ret;
285 /* FIXME: copy key usage flags */
286 a_val = 0;
287 a[a_val].type = CKA_CLASS;
288 a[a_val].value = &class;
289 a[a_val].value_len = sizeof (class);
290 a_val++;
292 a[a_val].type = CKA_ID;
293 a[a_val].value = id;
294 a[a_val].value_len = id_size;
295 a_val++;
297 a[a_val].type = CKA_KEY_TYPE;
298 a[a_val].value = &type;
299 a[a_val].value_len = sizeof (type);
300 a_val++;
302 a[a_val].type = CKA_TOKEN;
303 a[a_val].value = (void*)&tval;
304 a[a_val].value_len = sizeof (tval);
305 a_val++;
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);
315 a_val++;
317 else
319 a[a_val].type = CKA_PRIVATE;
320 a[a_val].value = (void*)&tval;
321 a[a_val].value_len = sizeof (tval);
322 a_val++;
325 if (label)
327 a[a_val].type = CKA_LABEL;
328 a[a_val].value = (void *) label;
329 a[a_val].value_len = strlen (label);
330 a_val++;
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);
338 a_val++;
340 else
342 a[a_val].type = CKA_SENSITIVE;
343 a[a_val].value = (void*)&fval;
344 a[a_val].value_len = sizeof (fval);
345 a_val++;
348 pk = gnutls_x509_privkey_get_pk_algorithm (key);
349 switch (pk)
351 case GNUTLS_PK_RSA:
354 ret =
355 gnutls_x509_privkey_export_rsa_raw2 (key, &m,
356 &e, &d, &p,
357 &q, &u, &exp1, &exp2);
358 if (ret < 0)
360 gnutls_assert ();
361 goto cleanup;
364 type = CKK_RSA;
366 a[a_val].type = CKA_MODULUS;
367 a[a_val].value = m.data;
368 a[a_val].value_len = m.size;
369 a_val++;
371 a[a_val].type = CKA_PUBLIC_EXPONENT;
372 a[a_val].value = e.data;
373 a[a_val].value_len = e.size;
374 a_val++;
376 a[a_val].type = CKA_PRIVATE_EXPONENT;
377 a[a_val].value = d.data;
378 a[a_val].value_len = d.size;
379 a_val++;
381 a[a_val].type = CKA_PRIME_1;
382 a[a_val].value = p.data;
383 a[a_val].value_len = p.size;
384 a_val++;
386 a[a_val].type = CKA_PRIME_2;
387 a[a_val].value = q.data;
388 a[a_val].value_len = q.size;
389 a_val++;
391 a[a_val].type = CKA_COEFFICIENT;
392 a[a_val].value = u.data;
393 a[a_val].value_len = u.size;
394 a_val++;
396 a[a_val].type = CKA_EXPONENT_1;
397 a[a_val].value = exp1.data;
398 a[a_val].value_len = exp1.size;
399 a_val++;
401 a[a_val].type = CKA_EXPONENT_2;
402 a[a_val].value = exp2.data;
403 a[a_val].value_len = exp2.size;
404 a_val++;
406 break;
408 case GNUTLS_PK_DSA:
410 ret = gnutls_x509_privkey_export_dsa_raw (key, &p, &q, &g, &y, &x);
411 if (ret < 0)
413 gnutls_assert ();
414 goto cleanup;
417 type = CKK_DSA;
419 a[a_val].type = CKA_PRIME;
420 a[a_val].value = p.data;
421 a[a_val].value_len = p.size;
422 a_val++;
424 a[a_val].type = CKA_SUBPRIME;
425 a[a_val].value = q.data;
426 a[a_val].value_len = q.size;
427 a_val++;
429 a[a_val].type = CKA_BASE;
430 a[a_val].value = g.data;
431 a[a_val].value_len = g.size;
432 a_val++;
434 a[a_val].type = CKA_VALUE;
435 a[a_val].value = x.data;
436 a[a_val].value_len = x.size;
437 a_val++;
439 break;
441 case GNUTLS_PK_EC:
443 ret = _gnutls_x509_write_ecc_params(&key->params, &p);
444 if (ret < 0)
446 gnutls_assert ();
447 goto cleanup;
450 ret = _gnutls_mpi_dprint_lz(&key->params.params[ECC_K], &x);
451 if (ret < 0)
453 gnutls_assert ();
454 goto cleanup;
457 type = CKK_ECDSA;
459 a[a_val].type = CKA_EC_PARAMS;
460 a[a_val].value = p.data;
461 a[a_val].value_len = p.size;
462 a_val++;
464 a[a_val].type = CKA_VALUE;
465 a[a_val].value = x.data;
466 a[a_val].value_len = x.size;
467 a_val++;
469 break;
471 default:
472 gnutls_assert ();
473 ret = GNUTLS_E_INVALID_REQUEST;
474 goto cleanup;
477 rv = pkcs11_create_object (module, pks, a, a_val, &obj);
478 if (rv != CKR_OK)
480 gnutls_assert ();
481 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
482 ret = pkcs11_rv_to_err (rv);
483 goto cleanup;
486 ret = 0;
488 cleanup:
489 switch (pk)
491 case GNUTLS_PK_RSA:
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);
501 break;
503 case GNUTLS_PK_DSA:
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);
510 break;
512 case GNUTLS_PK_EC:
514 gnutls_free (p.data);
515 gnutls_free (x.data);
516 break;
518 default:
519 gnutls_assert ();
520 ret = GNUTLS_E_INVALID_REQUEST;
521 break;
524 if (pks != 0)
525 pkcs11_close_session (module, pks);
527 return ret;
531 struct delete_data_st
533 struct p11_kit_uri *info;
534 unsigned int deleted; /* how many */
537 static int
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;
548 ck_rv_t rv;
549 ck_object_handle_t obj;
550 unsigned long count, a_vals;
551 int found = 0, ret;
554 if (info == NULL)
555 { /* we don't support multiple calls */
556 gnutls_assert ();
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))
565 gnutls_assert ();
566 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
569 /* Find objects with given class and type */
570 class = CKO_CERTIFICATE; /* default */
571 a_vals = 0;
573 attr = p11_kit_uri_get_attribute (find_data->info, CKA_CLASS);
574 if (attr != NULL)
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)
579 type = CKC_X_509;
582 a[a_vals].type = CKA_CLASS;
583 a[a_vals].value = &class;
584 a[a_vals].value_len = sizeof (class);
585 a_vals++;
587 attr = p11_kit_uri_get_attribute (find_data->info, CKA_ID);
588 if (attr != NULL)
590 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
591 a_vals++;
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;
599 a_vals++;
602 attr = p11_kit_uri_get_attribute (find_data->info, CKA_LABEL);
603 if (attr != NULL)
605 memcpy (a + a_vals, attr, sizeof (struct ck_attribute));
606 a_vals++;
609 rv = pkcs11_find_objects_init (module, pks, a, a_vals);
610 if (rv != CKR_OK)
612 gnutls_assert ();
613 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
614 ret = pkcs11_rv_to_err (rv);
615 goto cleanup;
618 while (pkcs11_find_objects (module, pks, &obj, 1, &count) == CKR_OK && count == 1)
620 rv = pkcs11_destroy_object (module, pks, obj);
621 if (rv != CKR_OK)
623 _gnutls_debug_log
624 ("pkcs11: Cannot destroy object: %s\n", pkcs11_strerror (rv));
626 else
628 find_data->deleted++;
631 found = 1;
634 if (found == 0)
636 gnutls_assert ();
637 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
639 else
641 ret = 0;
644 cleanup:
645 pkcs11_find_objects_final (module, pks);
647 return ret;
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.
662 * Since: 2.12.0
665 gnutls_pkcs11_delete_url (const char *object_url, unsigned int flags)
667 int ret;
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);
673 if (ret < 0)
675 gnutls_assert ();
676 return ret;
679 ret =
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);
684 if (ret < 0)
686 gnutls_assert ();
687 return ret;
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)
711 int ret;
712 struct p11_kit_uri *info = NULL;
713 ck_rv_t rv;
714 struct ck_function_list *module;
715 ck_slot_id_t slot;
716 char flabel[32];
718 ret = pkcs11_url_to_info (token_url, &info);
719 if (ret < 0)
721 gnutls_assert ();
722 return ret;
725 ret = pkcs11_find_slot (&module, &slot, info, NULL);
726 p11_kit_uri_free (info);
728 if (ret < 0)
730 gnutls_assert ();
731 return ret;
734 /* so it seems memset has other uses than zeroing! */
735 memset (flabel, ' ', sizeof (flabel));
736 if (label != NULL)
737 memcpy (flabel, label, strlen (label));
739 rv =
740 pkcs11_init_token (module, slot, (uint8_t*)so_pin, strlen (so_pin),
741 (uint8_t*)flabel);
742 if (rv != CKR_OK)
744 gnutls_assert ();
745 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
746 return pkcs11_rv_to_err (rv);
749 return 0;
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
762 * be NULL.
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,
769 const char *oldpin,
770 const char *newpin, unsigned int flags)
772 int ret;
773 struct ck_function_list *module;
774 ck_session_handle_t pks;
775 struct p11_kit_uri *info = NULL;
776 ck_rv_t rv;
777 unsigned int ses_flags;
779 ret = pkcs11_url_to_info (token_url, &info);
780 if (ret < 0)
782 gnutls_assert ();
783 return ret;
786 if (((flags & GNUTLS_PKCS11_PIN_USER) && oldpin == NULL) ||
787 (flags & GNUTLS_PKCS11_PIN_SO))
788 ses_flags = SESSION_WRITE | SESSION_LOGIN | SESSION_SO;
789 else
790 ses_flags = SESSION_WRITE | SESSION_LOGIN;
792 ret = pkcs11_open_session (&module, &pks, info, ses_flags);
793 p11_kit_uri_free (info);
795 if (ret < 0)
797 gnutls_assert ();
798 return ret;
801 if (oldpin == NULL)
803 rv = pkcs11_init_pin (module, pks, (uint8_t *) newpin, strlen (newpin));
804 if (rv != CKR_OK)
806 gnutls_assert ();
807 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
808 ret = pkcs11_rv_to_err (rv);
809 goto finish;
812 else
814 rv = pkcs11_set_pin (module, pks,
815 oldpin, strlen (oldpin),
816 newpin, strlen (newpin));
817 if (rv != CKR_OK)
819 gnutls_assert ();
820 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv));
821 ret = pkcs11_rv_to_err (rv);
822 goto finish;
826 ret = 0;
828 finish:
829 pkcs11_close_session (module, pks);
830 return ret;