2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
5 * Authors: Nikos Mavrogiannopoulos, Stef Walter
7 * The GnuTLS is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser 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>
28 #include <gnutls_sig.h>
29 #include <gnutls_pk.h>
31 #include <p11-kit/uri.h>
33 struct gnutls_pkcs11_privkey_st {
34 gnutls_pk_algorithm_t pk_algorithm;
36 struct p11_kit_uri *info;
38 struct pkcs11_session_info sinfo;
39 ck_object_handle_t obj; /* the key in the session */
41 struct pin_info_st pin;
45 * gnutls_pkcs11_privkey_init:
46 * @key: The structure to be initialized
48 * This function will initialize an private key structure.
50 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
51 * negative error value.
53 int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
57 *key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
60 return GNUTLS_E_MEMORY_ERROR;
63 (*key)->info = p11_kit_uri_new();
64 if ((*key)->info == NULL) {
67 return GNUTLS_E_MEMORY_ERROR;
74 * gnutls_pkcs11_privkey_deinit:
75 * @key: The structure to be initialized
77 * This function will deinitialize a private key structure.
79 void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
81 p11_kit_uri_free(key->info);
82 if (key->sinfo.init != 0)
83 pkcs11_close_session(&key->sinfo);
88 * gnutls_pkcs11_privkey_get_pk_algorithm:
89 * @key: should contain a #gnutls_pkcs11_privkey_t structure
90 * @bits: if bits is non null it will hold the size of the parameters' in bits
92 * This function will return the public key algorithm of a private
95 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
96 * success, or a negative error code on error.
99 gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
103 *bits = 0; /* FIXME */
104 return key->pk_algorithm;
108 * gnutls_pkcs11_privkey_get_info:
109 * @pkey: should contain a #gnutls_pkcs11_privkey_t structure
110 * @itype: Denotes the type of information requested
111 * @output: where output will be stored
112 * @output_size: contains the maximum size of the output and will be overwritten with actual
114 * This function will return information about the PKCS 11 private key such
115 * as the label, id as well as token information where the key is stored. When
116 * output is text it returns null terminated string although #output_size contains
117 * the size of the actual data only.
119 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
122 gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,
123 gnutls_pkcs11_obj_info_t itype,
124 void *output, size_t * output_size)
126 return pkcs11_get_info(pkey->info, itype, output, output_size);
130 find_object(struct pkcs11_session_info *sinfo,
131 struct pin_info_st *pin_info,
132 ck_object_handle_t * _obj,
133 struct p11_kit_uri *info, unsigned int flags)
136 ck_object_handle_t obj;
137 struct ck_attribute *attrs;
138 unsigned long attr_count;
143 pkcs11_open_session(sinfo, pin_info, info,
144 flags & SESSION_LOGIN);
150 attrs = p11_kit_uri_get_attributes(info, &attr_count);
151 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, attrs,
155 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
156 ret = pkcs11_rv_to_err(rv);
160 if (pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count)
161 == CKR_OK && count == 1) {
163 pkcs11_find_objects_final(sinfo);
167 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
168 pkcs11_find_objects_final(sinfo);
170 pkcs11_close_session(sinfo);
175 #define FIND_OBJECT(sinfo, pin_info, obj, key) \
179 ret = find_object (sinfo, pin_info, &obj, key->info, \
181 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
182 if (_gnutls_token_func) \
184 rret = pkcs11_call_token_func (key->info, retries++); \
185 if (rret == 0) continue; \
187 return gnutls_assert_val(ret); \
188 } else if (ret < 0) { \
189 return gnutls_assert_val(ret); \
195 * _gnutls_pkcs11_privkey_sign_hash:
196 * @key: Holds the key
197 * @hash: holds the data to be signed (should be output of a hash)
198 * @signature: will contain the signature allocated with gnutls_malloc()
200 * This function will sign the given data using a signature algorithm
201 * supported by the private key. It is assumed that the given data
202 * are the output of a hash function.
204 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
205 * negative error value.
208 _gnutls_pkcs11_privkey_sign_hash(gnutls_pkcs11_privkey_t key,
209 const gnutls_datum_t * hash,
210 gnutls_datum_t * signature)
214 struct ck_mechanism mech;
215 gnutls_datum_t tmp = { NULL, 0 };
216 unsigned long siglen;
217 struct pkcs11_session_info _sinfo;
218 struct pkcs11_session_info *sinfo;
219 ck_object_handle_t obj;
223 if (key->sinfo.init != 0) {
228 memset(sinfo, 0, sizeof(*sinfo));
229 FIND_OBJECT(sinfo, &key->pin, obj, key);
232 mech.mechanism = pk_to_mech(key->pk_algorithm);
233 mech.parameter = NULL;
234 mech.parameter_len = 0;
236 /* Initialize signing operation; using the private key discovered
238 rv = pkcs11_sign_init(sinfo->module, sinfo->pks, &mech, obj);
241 ret = pkcs11_rv_to_err(rv);
245 /* Work out how long the signature must be: */
246 rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
250 ret = pkcs11_rv_to_err(rv);
254 tmp.data = gnutls_malloc(siglen);
257 rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
261 ret = pkcs11_rv_to_err(rv);
266 if (key->pk_algorithm == GNUTLS_PK_EC
267 || key->pk_algorithm == GNUTLS_PK_DSA) {
268 unsigned int hlen = siglen / 2;
271 if (siglen % 2 != 0) {
273 ret = GNUTLS_E_PK_SIGN_FAILED;
280 s.data = &tmp.data[hlen];
283 ret = _gnutls_encode_ber_rs_raw(signature, &r, &s);
289 gnutls_free(tmp.data);
292 signature->size = siglen;
293 signature->data = tmp.data;
299 if (sinfo != &key->sinfo)
300 pkcs11_close_session(sinfo);
302 gnutls_free(tmp.data);
308 * gnutls_pkcs11_privkey_status:
309 * @key: Holds the key
311 * Checks the status of the private key token.
313 * Returns: this function will return non-zero if the token
314 * holding the private key is still available (inserted), and zero otherwise.
319 int gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)
323 struct pkcs11_session_info _sinfo;
324 struct pkcs11_session_info *sinfo;
325 ck_object_handle_t obj;
326 struct ck_session_info session_info;
330 if (key->sinfo.init != 0) {
335 memset(sinfo, 0, sizeof(*sinfo));
336 FIND_OBJECT(sinfo, &key->pin, obj, key);
339 rv = (sinfo->module)->C_GetSessionInfo(sinfo->pks, &session_info);
347 if (sinfo != &key->sinfo)
348 pkcs11_close_session(sinfo);
354 * gnutls_pkcs11_privkey_import_url:
355 * @pkey: The structure to store the parsed key
356 * @url: a PKCS 11 url identifying the key
357 * @flags: sequence of GNUTLS_PKCS_PRIVKEY_*
359 * This function will "import" a PKCS 11 URL identifying a private
360 * key to the #gnutls_pkcs11_privkey_t structure. In reality since
361 * in most cases keys cannot be exported, the private key structure
362 * is being associated with the available operations on the token.
364 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
365 * negative error value.
368 gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
369 const char *url, unsigned int flags)
372 struct ck_attribute *attr;
373 ck_object_handle_t obj;
374 struct ck_attribute a[4];
375 ck_key_type_t key_type;
376 struct pkcs11_session_info sinfo;
380 memset(&sinfo, 0, sizeof(sinfo));
382 ret = pkcs11_url_to_info(url, &pkey->info);
390 attr = p11_kit_uri_get_attribute(pkey->info, CKA_CLASS);
391 if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
392 *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
394 return GNUTLS_E_INVALID_REQUEST;
397 attr = p11_kit_uri_get_attribute(pkey->info, CKA_ID);
398 if (!attr || !attr->value_len) {
399 attr = p11_kit_uri_get_attribute(pkey->info, CKA_LABEL);
400 if (!attr || !attr->value_len) {
402 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
406 FIND_OBJECT(&sinfo, &pkey->pin, obj, pkey);
408 a[0].type = CKA_KEY_TYPE;
409 a[0].value = &key_type;
410 a[0].value_len = sizeof(key_type);
412 if (pkcs11_get_attribute_value(sinfo.module, sinfo.pks, obj, a, 1)
414 pkey->pk_algorithm = mech_to_pk(key_type);
415 if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) {
417 ("Cannot determine PKCS #11 key algorithm\n");
418 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
425 if (pkey->sinfo.init)
426 pkcs11_close_session(&pkey->sinfo);
428 if (sinfo.tinfo.max_session_count != 1) {
429 /* We do not keep the session open in tokens that can
430 * only support a single session.
432 memcpy(&pkey->sinfo, &sinfo, sizeof(pkey->sinfo));
438 pkcs11_close_session(&sinfo);
444 * _gnutls_pkcs11_privkey_decrypt_data:
445 * @key: Holds the key
446 * @flags: should be 0 for now
447 * @ciphertext: holds the data to be signed
448 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
450 * This function will decrypt the given data using the public key algorithm
451 * supported by the private key.
453 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
454 * negative error value.
457 _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
459 const gnutls_datum_t * ciphertext,
460 gnutls_datum_t * plaintext)
464 struct ck_mechanism mech;
465 unsigned long siglen;
466 ck_object_handle_t obj;
467 struct pkcs11_session_info _sinfo;
468 struct pkcs11_session_info *sinfo;
472 if (key->sinfo.init != 0) {
477 memset(sinfo, 0, sizeof(*sinfo));
478 FIND_OBJECT(sinfo, &key->pin, obj, key);
481 if (key->pk_algorithm != GNUTLS_PK_RSA)
482 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
484 mech.mechanism = CKM_RSA_PKCS;
485 mech.parameter = NULL;
486 mech.parameter_len = 0;
488 /* Initialize signing operation; using the private key discovered
490 rv = pkcs11_decrypt_init(sinfo->module, sinfo->pks, &mech, obj);
493 ret = pkcs11_rv_to_err(rv);
497 /* Work out how long the plaintext must be: */
498 rv = pkcs11_decrypt(sinfo->module, sinfo->pks, ciphertext->data,
499 ciphertext->size, NULL, &siglen);
502 ret = pkcs11_rv_to_err(rv);
506 plaintext->data = gnutls_malloc(siglen);
507 plaintext->size = siglen;
509 rv = pkcs11_decrypt(sinfo->module, sinfo->pks, ciphertext->data,
510 ciphertext->size, plaintext->data, &siglen);
512 gnutls_free(plaintext->data);
514 ret = pkcs11_rv_to_err(rv);
518 plaintext->size = siglen;
523 if (key->sinfo.init == 0)
524 pkcs11_close_session(sinfo);
530 * gnutls_pkcs11_privkey_export_url:
531 * @key: Holds the PKCS 11 key
532 * @detailed: non zero if a detailed URL is required
533 * @url: will contain an allocated url
535 * This function will export a URL identifying the given key.
537 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
538 * negative error value.
541 gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,
542 gnutls_pkcs11_url_type_t detailed,
547 ret = pkcs11_info_to_url(key->info, detailed, url);
558 * gnutls_pkcs11_privkey_generate:
560 * @pk: the public key algorithm
561 * @bits: the security bits
563 * @flags: should be zero
565 * This function will generate a private key in the specified
566 * by the @url token. The private key will be generate within
567 * the token and will not be exportable.
569 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
570 * negative error value.
575 gnutls_pkcs11_privkey_generate(const char *url, gnutls_pk_algorithm_t pk,
576 unsigned int bits, const char *label,
579 return gnutls_pkcs11_privkey_generate2(url, pk, bits, label, 0,
584 * gnutls_pkcs11_privkey_generate2:
586 * @pk: the public key algorithm
587 * @bits: the security bits
589 * @fmt: the format of output params. PEM or DER.
590 * @pubkey: will hold the public key (may be %NULL)
591 * @flags: should be zero
593 * This function will generate a private key in the specified
594 * by the @url token. The private key will be generate within
595 * the token and will not be exportable. This function will
596 * store the DER-encoded public key in the SubjectPublicKeyInfo format
597 * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
599 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
600 * negative error value.
605 gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
606 unsigned int bits, const char *label,
607 gnutls_x509_crt_fmt_t fmt,
608 gnutls_datum_t * pubkey,
612 const ck_bool_t tval = 1;
613 const ck_bool_t fval = 0;
614 struct pkcs11_session_info sinfo;
615 struct p11_kit_uri *info = NULL;
617 struct ck_attribute a[10], p[10];
618 ck_object_handle_t pub, priv;
619 unsigned long _bits = bits;
621 struct ck_mechanism mech;
622 gnutls_pubkey_t pkey = NULL;
623 gnutls_pkcs11_obj_t obj = NULL;
627 memset(&sinfo, 0, sizeof(sinfo));
629 ret = pkcs11_url_to_info(url, &info);
636 pkcs11_open_session(&sinfo, NULL, info,
638 pkcs11_obj_flags_to_int(flags));
639 p11_kit_uri_free(info);
646 /* a holds the public key template
647 * and p the private key */
649 mech.parameter = NULL;
650 mech.parameter_len = 0;
651 mech.mechanism = pk_to_genmech(pk);
655 p[p_val].type = CKA_DECRYPT;
656 p[p_val].value = (void *) &tval;
657 p[p_val].value_len = sizeof(tval);
660 p[p_val].type = CKA_SIGN;
661 p[p_val].value = (void *) &tval;
662 p[p_val].value_len = sizeof(tval);
665 a[a_val].type = CKA_ENCRYPT;
666 a[a_val].value = (void *) &tval;
667 a[a_val].value_len = sizeof(tval);
670 a[a_val].type = CKA_VERIFY;
671 a[a_val].value = (void *) &tval;
672 a[a_val].value_len = sizeof(tval);
675 a[a_val].type = CKA_MODULUS_BITS;
676 a[a_val].value = &_bits;
677 a[a_val].value_len = sizeof(_bits);
681 p[p_val].type = CKA_SIGN;
682 p[p_val].value = (void *) &tval;
683 p[p_val].value_len = sizeof(tval);
686 a[a_val].type = CKA_VERIFY;
687 a[a_val].value = (void *) &tval;
688 a[a_val].value_len = sizeof(tval);
691 a[a_val].type = CKA_MODULUS_BITS;
692 a[a_val].value = &_bits;
693 a[a_val].value_len = sizeof(_bits);
697 p[p_val].type = CKA_SIGN;
698 p[p_val].value = (void *) &tval;
699 p[p_val].value_len = sizeof(tval);
702 a[a_val].type = CKA_VERIFY;
703 a[a_val].value = (void *) &tval;
704 a[a_val].value_len = sizeof(tval);
707 a[a_val].type = CKA_MODULUS_BITS;
708 a[a_val].value = &_bits;
709 a[a_val].value_len = sizeof(_bits);
713 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
717 /* a private key is set always as private unless
718 * requested otherwise
720 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
721 p[p_val].type = CKA_PRIVATE;
722 p[p_val].value = (void *) &fval;
723 p[p_val].value_len = sizeof(fval);
726 p[p_val].type = CKA_PRIVATE;
727 p[p_val].value = (void *) &tval;
728 p[p_val].value_len = sizeof(tval);
732 p[p_val].type = CKA_TOKEN;
733 p[p_val].value = (void *) &tval;
734 p[p_val].value_len = sizeof(tval);
738 p[p_val].type = CKA_LABEL;
739 p[p_val].value = (void *) label;
740 p[p_val].value_len = strlen(label);
743 a[a_val].type = CKA_LABEL;
744 a[a_val].value = (void *) label;
745 a[a_val].value_len = strlen(label);
749 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) {
750 p[p_val].type = CKA_SENSITIVE;
751 p[p_val].value = (void *) &tval;
752 p[p_val].value_len = sizeof(tval);
755 p[p_val].type = CKA_SENSITIVE;
756 p[p_val].value = (void *) &fval;
757 p[p_val].value_len = sizeof(fval);
761 rv = pkcs11_generate_key_pair(sinfo.module, sinfo.pks, &mech, a,
762 a_val, p, p_val, &pub, &priv);
765 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
766 ret = pkcs11_rv_to_err(rv);
770 /* extract the public key */
772 ret = gnutls_pubkey_init(&pkey);
778 ret = gnutls_pkcs11_obj_init(&obj);
784 obj->pk_algorithm = pk;
785 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
787 pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub,
788 mech.mechanism, obj->pubkey);
794 ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
800 ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
810 gnutls_pkcs11_obj_deinit(obj);
812 gnutls_pubkey_deinit(pkey);
814 pkcs11_close_session(&sinfo);
820 * gnutls_pkcs11_privkey_set_pin_function:
821 * @key: The private key
823 * @userdata: data associated with the callback
825 * This function will set a callback function to be used when
826 * required to access the object. This function overrides the global
827 * set using gnutls_pkcs11_set_pin_function().
833 gnutls_pkcs11_privkey_set_pin_function(gnutls_pkcs11_privkey_t key,
834 gnutls_pin_callback_t fn,
838 key->pin.data = userdata;