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 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 gnutls_datum_t subject
= { NULL
, 0 };
64 struct pkcs11_session_info sinfo
;
66 memset(&sinfo
, 0, sizeof(sinfo
));
68 ret
= pkcs11_url_to_info (token_url
, &info
);
76 pkcs11_open_session (&sinfo
, NULL
, info
,
77 SESSION_WRITE
| pkcs11_obj_flags_to_int (flags
));
78 p11_kit_uri_free (info
);
86 ret
= gnutls_x509_crt_export (crt
, GNUTLS_X509_FMT_DER
, NULL
, &der_size
);
87 if (ret
< 0 && ret
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
93 der
= gnutls_malloc (der_size
);
97 ret
= GNUTLS_E_MEMORY_ERROR
;
101 ret
= gnutls_x509_crt_export (crt
, GNUTLS_X509_FMT_DER
, der
, &der_size
);
108 id_size
= sizeof (id
);
109 ret
= gnutls_x509_crt_get_key_id (crt
, 0, id
, &id_size
);
116 ret
= gnutls_x509_crt_get_raw_dn (crt
, &subject
);
123 /* FIXME: copy key usage flags */
125 a
[0].type
= CKA_CLASS
;
127 a
[0].value_len
= sizeof (class);
130 a
[1].value_len
= id_size
;
131 a
[2].type
= CKA_VALUE
;
133 a
[2].value_len
= der_size
;
134 a
[3].type
= CKA_TOKEN
;
135 a
[3].value
= (void*)&tval
;
136 a
[3].value_len
= sizeof (tval
);
137 a
[4].type
= CKA_CERTIFICATE_TYPE
;
139 a
[4].value_len
= sizeof (type
);
143 a
[a_val
].type
= CKA_SUBJECT
;
144 a
[a_val
].value
= subject
.data
;
145 a
[a_val
].value_len
= subject
.size
;
150 a
[a_val
].type
= CKA_LABEL
;
151 a
[a_val
].value
= (void *) label
;
152 a
[a_val
].value_len
= strlen (label
);
156 if (flags
& GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED
)
158 a
[a_val
].type
= CKA_TRUSTED
;
159 a
[a_val
].value
= (void*)&tval
;
160 a
[a_val
].value_len
= sizeof (tval
);
163 a
[a_val
].type
= CKA_PRIVATE
;
164 a
[a_val
].value
= (void*)&fval
;
165 a
[a_val
].value_len
= sizeof(fval
);
170 if (flags
& GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE
)
172 a
[a_val
].type
= CKA_PRIVATE
;
173 a
[a_val
].value
= (void*)&tval
;
174 a
[a_val
].value_len
= sizeof(tval
);
177 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
);
190 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv
));
191 ret
= pkcs11_rv_to_err (rv
);
202 pkcs11_close_session (&sinfo
);
203 _gnutls_free_datum(&subject
);
209 * gnutls_pkcs11_copy_x509_privkey:
210 * @token_url: A PKCS #11 URL specifying a token
211 * @key: A private key
212 * @label: A name to be used for the stored data
213 * @key_usage: One of GNUTLS_KEY_*
214 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
216 * This function will copy a private key into a PKCS #11 token specified by
217 * a URL. It is highly recommended flags to contain %GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE
218 * unless there is a strong reason not to.
220 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
221 * negative error value.
226 gnutls_pkcs11_copy_x509_privkey (const char *token_url
,
227 gnutls_x509_privkey_t key
,
229 unsigned int key_usage
, unsigned int flags
)
232 struct p11_kit_uri
*info
= NULL
;
236 struct ck_attribute a
[16];
237 ck_object_class_t
class = CKO_PRIVATE_KEY
;
238 ck_object_handle_t obj
;
241 gnutls_pk_algorithm_t pk
;
242 gnutls_datum_t p
, q
, g
, y
, x
;
243 gnutls_datum_t m
, e
, d
, u
, exp1
, exp2
;
244 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
);
267 id_size
= sizeof (id
);
268 ret
= gnutls_x509_privkey_get_key_id (key
, 0, id
, &id_size
);
271 p11_kit_uri_free (info
);
277 pkcs11_open_session (&sinfo
, NULL
, info
,
278 SESSION_WRITE
| pkcs11_obj_flags_to_int (flags
));
279 p11_kit_uri_free (info
);
287 /* FIXME: copy key usage flags */
289 a
[a_val
].type
= CKA_CLASS
;
290 a
[a_val
].value
= &class;
291 a
[a_val
].value_len
= sizeof (class);
294 a
[a_val
].type
= CKA_ID
;
296 a
[a_val
].value_len
= id_size
;
299 a
[a_val
].type
= CKA_KEY_TYPE
;
300 a
[a_val
].value
= &type
;
301 a
[a_val
].value_len
= sizeof (type
);
304 a
[a_val
].type
= CKA_TOKEN
;
305 a
[a_val
].value
= (void*)&tval
;
306 a
[a_val
].value_len
= sizeof (tval
);
309 /* a private key is set always as private unless
310 * requested otherwise
312 if (flags
& GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE
)
314 a
[a_val
].type
= CKA_PRIVATE
;
315 a
[a_val
].value
= (void*)&fval
;
316 a
[a_val
].value_len
= sizeof(fval
);
321 a
[a_val
].type
= CKA_PRIVATE
;
322 a
[a_val
].value
= (void*)&tval
;
323 a
[a_val
].value_len
= sizeof (tval
);
329 a
[a_val
].type
= CKA_LABEL
;
330 a
[a_val
].value
= (void *) label
;
331 a
[a_val
].value_len
= strlen (label
);
335 if (flags
& GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE
)
337 a
[a_val
].type
= CKA_SENSITIVE
;
338 a
[a_val
].value
= (void*)&tval
;
339 a
[a_val
].value_len
= sizeof (tval
);
344 a
[a_val
].type
= CKA_SENSITIVE
;
345 a
[a_val
].value
= (void*)&fval
;
346 a
[a_val
].value_len
= sizeof (fval
);
350 pk
= gnutls_x509_privkey_get_pk_algorithm (key
);
357 gnutls_x509_privkey_export_rsa_raw2 (key
, &m
,
359 &q
, &u
, &exp1
, &exp2
);
368 a
[a_val
].type
= CKA_MODULUS
;
369 a
[a_val
].value
= m
.data
;
370 a
[a_val
].value_len
= m
.size
;
373 a
[a_val
].type
= CKA_PUBLIC_EXPONENT
;
374 a
[a_val
].value
= e
.data
;
375 a
[a_val
].value_len
= e
.size
;
378 a
[a_val
].type
= CKA_PRIVATE_EXPONENT
;
379 a
[a_val
].value
= d
.data
;
380 a
[a_val
].value_len
= d
.size
;
383 a
[a_val
].type
= CKA_PRIME_1
;
384 a
[a_val
].value
= p
.data
;
385 a
[a_val
].value_len
= p
.size
;
388 a
[a_val
].type
= CKA_PRIME_2
;
389 a
[a_val
].value
= q
.data
;
390 a
[a_val
].value_len
= q
.size
;
393 a
[a_val
].type
= CKA_COEFFICIENT
;
394 a
[a_val
].value
= u
.data
;
395 a
[a_val
].value_len
= u
.size
;
398 a
[a_val
].type
= CKA_EXPONENT_1
;
399 a
[a_val
].value
= exp1
.data
;
400 a
[a_val
].value_len
= exp1
.size
;
403 a
[a_val
].type
= CKA_EXPONENT_2
;
404 a
[a_val
].value
= exp2
.data
;
405 a
[a_val
].value_len
= exp2
.size
;
412 ret
= gnutls_x509_privkey_export_dsa_raw (key
, &p
, &q
, &g
, &y
, &x
);
421 a
[a_val
].type
= CKA_PRIME
;
422 a
[a_val
].value
= p
.data
;
423 a
[a_val
].value_len
= p
.size
;
426 a
[a_val
].type
= CKA_SUBPRIME
;
427 a
[a_val
].value
= q
.data
;
428 a
[a_val
].value_len
= q
.size
;
431 a
[a_val
].type
= CKA_BASE
;
432 a
[a_val
].value
= g
.data
;
433 a
[a_val
].value_len
= g
.size
;
436 a
[a_val
].type
= CKA_VALUE
;
437 a
[a_val
].value
= x
.data
;
438 a
[a_val
].value_len
= x
.size
;
445 ret
= _gnutls_x509_write_ecc_params(&key
->params
, &p
);
452 ret
= _gnutls_mpi_dprint_lz(&key
->params
.params
[ECC_K
], &x
);
461 a
[a_val
].type
= CKA_EC_PARAMS
;
462 a
[a_val
].value
= p
.data
;
463 a
[a_val
].value_len
= p
.size
;
466 a
[a_val
].type
= CKA_VALUE
;
467 a
[a_val
].value
= x
.data
;
468 a
[a_val
].value_len
= x
.size
;
475 ret
= GNUTLS_E_INVALID_REQUEST
;
479 rv
= pkcs11_create_object (sinfo
.module
, sinfo
.pks
, a
, a_val
, &obj
);
483 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv
));
484 ret
= pkcs11_rv_to_err (rv
);
495 gnutls_free (m
.data
);
496 gnutls_free (e
.data
);
497 gnutls_free (d
.data
);
498 gnutls_free (p
.data
);
499 gnutls_free (q
.data
);
500 gnutls_free (u
.data
);
501 gnutls_free (exp1
.data
);
502 gnutls_free (exp2
.data
);
507 gnutls_free (p
.data
);
508 gnutls_free (q
.data
);
509 gnutls_free (g
.data
);
510 gnutls_free (y
.data
);
511 gnutls_free (x
.data
);
516 gnutls_free (p
.data
);
517 gnutls_free (x
.data
);
522 ret
= GNUTLS_E_INVALID_REQUEST
;
527 pkcs11_close_session (&sinfo
);
533 struct delete_data_st
535 struct p11_kit_uri
*info
;
536 unsigned int deleted
; /* how many */
540 delete_obj_url (struct pkcs11_session_info
* sinfo
,
541 struct token_info
*info
,
542 struct ck_info
*lib_info
, void *input
)
544 struct delete_data_st
*find_data
= input
;
545 struct ck_attribute a
[4];
546 struct ck_attribute
*attr
;
547 ck_object_class_t
class;
548 ck_certificate_type_t type
= (ck_certificate_type_t
)-1;
550 ck_object_handle_t obj
;
551 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 (sinfo
->module
, sinfo
->pks
, a
, a_vals
);
613 _gnutls_debug_log ("pk11: FindObjectsInit failed.\n");
614 ret
= pkcs11_rv_to_err (rv
);
618 while (pkcs11_find_objects (sinfo
->module
, sinfo
->pks
, &obj
, 1, &count
) == CKR_OK
&& count
== 1)
620 rv
= pkcs11_destroy_object (sinfo
->module
, sinfo
->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 (sinfo
);
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 NULL
, 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_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 p11_kit_uri
*info
= NULL
;
775 unsigned int ses_flags
;
776 struct pkcs11_session_info sinfo
;
778 memset(&sinfo
, 0, sizeof(sinfo
));
780 ret
= pkcs11_url_to_info (token_url
, &info
);
787 if (((flags
& GNUTLS_PIN_USER
) && oldpin
== NULL
) ||
788 (flags
& GNUTLS_PIN_SO
))
789 ses_flags
= SESSION_WRITE
| SESSION_LOGIN
| SESSION_SO
;
791 ses_flags
= SESSION_WRITE
| SESSION_LOGIN
;
793 ret
= pkcs11_open_session (&sinfo
, NULL
, info
, ses_flags
);
794 p11_kit_uri_free (info
);
804 rv
= pkcs11_init_pin (sinfo
.module
, sinfo
.pks
, (uint8_t *) newpin
, strlen (newpin
));
808 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv
));
809 ret
= pkcs11_rv_to_err (rv
);
815 rv
= pkcs11_set_pin (sinfo
.module
, sinfo
.pks
,
816 oldpin
, strlen (oldpin
),
817 newpin
, strlen (newpin
));
821 _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv
));
822 ret
= pkcs11_rv_to_err (rv
);
830 pkcs11_close_session (&sinfo
);