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
);