1 /*
2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 * Copyright (C) 2017 Red Hat, Inc.
5 *
6 * Authors: Nikos Mavrogiannopoulos, Stef Walter
7 *
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 */
21
22 #include "gnutls_int.h"
23 #include <gnutls/pkcs11.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "errors.h"
27 #include <datum.h>
28 #include <pkcs11_int.h>
29 #include <tls-sig.h>
30 #include <pk.h>
31 #include <fips.h>
32 #include "urls.h"
33 #include "locks.h"
34 #include <p11-kit/uri.h>
35
36 /* In case of a fork, it will invalidate the open session
37 * in the privkey and start another */
38 #define PKCS11_CHECK_INIT_PRIVKEY(k) \
39 ret = _gnutls_pkcs11_check_init(PROV_INIT_ALL, k, reopen_privkey_session); \
40 if (ret < 0) \
41 return gnutls_assert_val(ret)
42
43 #define FIND_OBJECT(key) \
44 do { \
45 int retries = 0; \
46 int rret; \
47 ret = find_object (&key->sinfo, &key->pin, &key->ref, key->uinfo, \
48 SESSION_LOGIN); \
49 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { \
50 if (_gnutls_token_func) \
51 { \
52 rret = pkcs11_call_token_func (key->uinfo, retries++); \
53 if (rret == 0) continue; \
54 } \
55 return gnutls_assert_val(ret); \
56 } else if (ret < 0) { \
57 return gnutls_assert_val(ret); \
58 } \
59 break; \
60 } while (1);
61
62
63 /**
64 * gnutls_pkcs11_privkey_init:
65 * @key: A pointer to the type to be initialized
66 *
67 * This function will initialize an private key structure. This
68 * structure can be used for accessing an underlying PKCS#11 object.
69 *
70 * In versions of GnuTLS later than 3.5.11 the object is protected
71 * using locks and a single %gnutls_pkcs11_privkey_t can be re-used
72 * by many threads. However, for performance it is recommended to utilize
73 * one object per key per thread.
74 *
75 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
76 * negative error value.
77 **/
gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)78 int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
79 {
80 int ret;
81 FAIL_IF_LIB_ERROR;
82
83 *key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
84 if (*key == NULL) {
85 gnutls_assert();
86 return GNUTLS_E_MEMORY_ERROR;
87 }
88
89 (*key)->uinfo = p11_kit_uri_new();
90 if ((*key)->uinfo == NULL) {
91 free(*key);
92 gnutls_assert();
93 return GNUTLS_E_MEMORY_ERROR;
94 }
95
96 ret = gnutls_mutex_init(&(*key)->mutex);
97 if (ret < 0) {
98 gnutls_assert();
99 p11_kit_uri_free((*key)->uinfo);
100 free(*key);
101 return GNUTLS_E_LOCKING_ERROR;
102 }
103
104 return 0;
105 }
106
107 /**
108 * gnutls_pkcs11_privkey_cpy:
109 * @dst: The destination key, which should be initialized.
110 * @src: The source key
111 *
112 * This function will copy a private key from source to destination
113 * key. Destination has to be initialized.
114 *
115 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
116 * negative error value.
117 *
118 * Since: 3.4.0
119 **/
120 int
gnutls_pkcs11_privkey_cpy(gnutls_pkcs11_privkey_t dst,gnutls_pkcs11_privkey_t src)121 gnutls_pkcs11_privkey_cpy(gnutls_pkcs11_privkey_t dst,
122 gnutls_pkcs11_privkey_t src)
123 {
124 return gnutls_pkcs11_privkey_import_url(dst, src->url, src->flags);
125 }
126
127 /**
128 * gnutls_pkcs11_privkey_deinit:
129 * @key: the key to be deinitialized
130 *
131 * This function will deinitialize a private key structure.
132 **/
gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)133 void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
134 {
135 p11_kit_uri_free(key->uinfo);
136 gnutls_free(key->url);
137 if (key->sinfo.init != 0)
138 pkcs11_close_session(&key->sinfo);
139 gnutls_mutex_deinit(&key->mutex);
140 gnutls_free(key);
141 }
142
143 /**
144 * gnutls_pkcs11_privkey_get_pk_algorithm:
145 * @key: should contain a #gnutls_pkcs11_privkey_t type
146 * @bits: if bits is non null it will hold the size of the parameters' in bits
147 *
148 * This function will return the public key algorithm of a private
149 * key.
150 *
151 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
152 * success, or a negative error code on error.
153 **/
154 int
gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,unsigned int * bits)155 gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
156 unsigned int *bits)
157 {
158 if (bits)
159 *bits = key->bits;
160 return key->pk_algorithm;
161 }
162
163 /**
164 * gnutls_pkcs11_privkey_get_info:
165 * @pkey: should contain a #gnutls_pkcs11_privkey_t type
166 * @itype: Denotes the type of information requested
167 * @output: where output will be stored
168 * @output_size: contains the maximum size of the output and will be overwritten with actual
169 *
170 * This function will return information about the PKCS 11 private key such
171 * as the label, id as well as token information where the key is stored. When
172 * output is text it returns null terminated string although #output_size contains
173 * the size of the actual data only.
174 *
175 * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error.
176 **/
177 int
gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,gnutls_pkcs11_obj_info_t itype,void * output,size_t * output_size)178 gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,
179 gnutls_pkcs11_obj_info_t itype,
180 void *output, size_t * output_size)
181 {
182 return pkcs11_get_info(pkey->uinfo, itype, output, output_size);
183 }
184
185 static int
find_object(struct pkcs11_session_info * sinfo,struct pin_info_st * pin_info,ck_object_handle_t * _ctx,struct p11_kit_uri * info,unsigned int flags)186 find_object(struct pkcs11_session_info *sinfo,
187 struct pin_info_st *pin_info,
188 ck_object_handle_t * _ctx,
189 struct p11_kit_uri *info, unsigned int flags)
190 {
191 int ret;
192 ck_object_handle_t ctx;
193 struct ck_attribute *attrs;
194 unsigned long attr_count;
195 unsigned long count;
196 ck_rv_t rv;
197
198 ret =
199 pkcs11_open_session(sinfo, pin_info, info,
200 flags & SESSION_LOGIN);
201 if (ret < 0) {
202 gnutls_assert();
203 return ret;
204 }
205
206 attrs = p11_kit_uri_get_attributes(info, &attr_count);
207 rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, attrs,
208 attr_count);
209 if (rv != CKR_OK) {
210 gnutls_assert();
211 _gnutls_debug_log("p11: FindObjectsInit failed.\n");
212 ret = pkcs11_rv_to_err(rv);
213 goto fail;
214 }
215
216 if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count)
217 == CKR_OK && count == 1) {
218 *_ctx = ctx;
219 pkcs11_find_objects_final(sinfo);
220 return 0;
221 }
222
223 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
224 pkcs11_find_objects_final(sinfo);
225 fail:
226 pkcs11_close_session(sinfo);
227
228 return ret;
229 }
230
231 /* callback function to be passed in _gnutls_pkcs11_check_init().
232 * It is run, only when a fork has been detected, and data have
233 * been re-initialized. In that case we reset the session and re-open
234 * the object. */
reopen_privkey_session(void * _privkey)235 static int reopen_privkey_session(void * _privkey)
236 {
237 int ret;
238 gnutls_pkcs11_privkey_t privkey = _privkey;
239
240 memset(&privkey->sinfo, 0, sizeof(privkey->sinfo));
241 privkey->ref = 0;
242 FIND_OBJECT(privkey);
243
244 return 0;
245 }
246
247 #define REPEAT_ON_INVALID_HANDLE(expr) \
248 if ((expr) == CKR_SESSION_HANDLE_INVALID) { \
249 ret = reopen_privkey_session(key); \
250 if (ret < 0) \
251 return gnutls_assert_val(ret); \
252 expr; \
253 }
254
255 struct hash_mappings_st {
256 gnutls_digest_algorithm_t id;
257 unsigned long phash; /* pkcs11 hash ID */
258 unsigned long mgf_id;
259 };
260
261
262 #ifndef CKG_MGF1_SHA224
263 # define CKG_MGF1_SHA224 0x00000005UL
264 # define CKG_MGF1_SHA256 0x00000002UL
265 # define CKG_MGF1_SHA384 0x00000003UL
266 # define CKG_MGF1_SHA512 0x00000004UL
267
268 struct ck_rsa_pkcs_pss_params {
269 ck_mechanism_type_t hash_alg;
270 /* ck_rsa_pkcs_mgf_type_t is not defined in old versions of p11-kit */
271 unsigned long mgf;
272 unsigned long s_len;
273 };
274 #endif
275
276 static const struct hash_mappings_st hash_mappings[] =
277 {
278 {.id = GNUTLS_DIG_SHA224,
279 .phash = CKM_SHA224,
280 .mgf_id = CKG_MGF1_SHA224
281 },
282 {.id = GNUTLS_DIG_SHA256,
283 .phash = CKM_SHA256,
284 .mgf_id = CKG_MGF1_SHA256
285 },
286 {.id = GNUTLS_DIG_SHA384,
287 .phash = CKM_SHA384,
288 .mgf_id = CKG_MGF1_SHA384
289 },
290 {.id = GNUTLS_DIG_SHA512,
291 .phash = CKM_SHA512,
292 .mgf_id = CKG_MGF1_SHA512
293 }
294 };
295
hash_to_map(gnutls_digest_algorithm_t hash)296 static const struct hash_mappings_st *hash_to_map(gnutls_digest_algorithm_t hash)
297 {
298 unsigned i;
299 for (i=0;i<sizeof(hash_mappings)/sizeof(hash_mappings[0]);i++) {
300 if (hash == hash_mappings[i].id)
301 return &hash_mappings[i];
302 }
303 return NULL;
304 }
305
306 /*-
307 * _gnutls_pkcs11_privkey_sign:
308 * @key: Holds the key
309 * @hash: holds the data to be signed (should be output of a hash)
310 * @signature: will contain the signature allocated with gnutls_malloc()
311 *
312 * This function will sign the given data using a signature algorithm
313 * supported by the private key. It is assumed that the given data
314 * are the output of a hash function. Input is the same as in
315 * privkey_sign_raw_data().
316 *
317 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
318 * negative error value.
319 -*/
320 int
_gnutls_pkcs11_privkey_sign(gnutls_pkcs11_privkey_t key,const gnutls_sign_entry_st * se,const gnutls_datum_t * hash,gnutls_datum_t * signature,gnutls_x509_spki_st * spki_params)321 _gnutls_pkcs11_privkey_sign(gnutls_pkcs11_privkey_t key,
322 const gnutls_sign_entry_st *se,
323 const gnutls_datum_t * hash,
324 gnutls_datum_t * signature,
325 gnutls_x509_spki_st *spki_params)
326 {
327 ck_rv_t rv;
328 int ret;
329 struct ck_mechanism mech;
330 gnutls_datum_t tmp = { NULL, 0 };
331 unsigned long siglen;
332 struct pkcs11_session_info *sinfo;
333 unsigned req_login = 0;
334 unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
335 struct ck_rsa_pkcs_pss_params rsa_pss_params;
336
337 PKCS11_CHECK_INIT_PRIVKEY(key);
338
339 sinfo = &key->sinfo;
340
341 if (se->pk == GNUTLS_PK_RSA_PSS) {
342 const struct hash_mappings_st *map = hash_to_map(se->hash);
343
344 if (unlikely(map == NULL))
345 return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
346
347 if (unlikely(!key->rsa_pss_ok))
348 return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
349
350 rsa_pss_params.hash_alg = map->phash;
351 rsa_pss_params.mgf = map->mgf_id;
352 rsa_pss_params.s_len = spki_params->salt_size;
353
354 mech.mechanism = CKM_RSA_PKCS_PSS;
355 mech.parameter = &rsa_pss_params;
356 mech.parameter_len = sizeof(rsa_pss_params);
357 } else {
358 ret = pk_to_mech(se->pk);
359
360 if (ret == -1)
361 return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
362
363 mech.mechanism = ret;
364 mech.parameter = NULL;
365 mech.parameter_len = 0;
366 }
367
368 ret = gnutls_mutex_lock(&key->mutex);
369 if (ret != 0)
370 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
371
372 /* Initialize signing operation; using the private key discovered
373 * earlier. */
374 REPEAT_ON_INVALID_HANDLE(rv = pkcs11_sign_init(sinfo->module, sinfo->pks, &mech, key->ref));
375 if (rv != CKR_OK) {
376 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
377 gnutls_assert();
378 ret = pkcs11_rv_to_err(rv);
379 goto cleanup;
380 }
381
382 retry_login:
383 if (key->reauth || req_login) {
384 if (req_login)
385 login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
386 ret =
387 pkcs11_login(&key->sinfo, &key->pin,
388 key->uinfo, login_flags);
389 if (ret < 0) {
390 gnutls_assert();
391 _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
392 /* let's try the operation anyway */
393 }
394 }
395
396 /* Work out how long the signature must be: */
397 rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
398 NULL, &siglen);
399 if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
400 req_login = 1;
401 goto retry_login;
402 }
403
404 if (rv != CKR_OK) {
405 gnutls_assert();
406 ret = pkcs11_rv_to_err(rv);
407 goto cleanup;
408 }
409
410 tmp.data = gnutls_malloc(siglen);
411 tmp.size = siglen;
412
413 rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
414 tmp.data, &siglen);
415 if (rv != CKR_OK) {
416 gnutls_assert();
417 ret = pkcs11_rv_to_err(rv);
418 goto cleanup;
419 }
420
421
422 if (key->pk_algorithm == GNUTLS_PK_ECDSA
423 || key->pk_algorithm == GNUTLS_PK_DSA) {
424 unsigned int hlen = siglen / 2;
425 gnutls_datum_t r, s;
426
427 if (siglen % 2 != 0) {
428 gnutls_assert();
429 ret = GNUTLS_E_PK_SIGN_FAILED;
430 goto cleanup;
431 }
432
433 r.data = tmp.data;
434 r.size = hlen;
435
436 s.data = &tmp.data[hlen];
437 s.size = hlen;
438
439 ret = _gnutls_encode_ber_rs_raw(signature, &r, &s);
440 if (ret < 0) {
441 gnutls_assert();
442 goto cleanup;
443 }
444
445 gnutls_free(tmp.data);
446 } else {
447 signature->size = siglen;
448 signature->data = tmp.data;
449 }
450
451 ret = 0;
452
453 cleanup:
454 gnutls_mutex_unlock(&key->mutex);
455 if (sinfo != &key->sinfo)
456 pkcs11_close_session(sinfo);
457 if (ret < 0)
458 gnutls_free(tmp.data);
459
460 return ret;
461 }
462
463 /**
464 * gnutls_pkcs11_privkey_status:
465 * @key: Holds the key
466 *
467 * Checks the status of the private key token.
468 *
469 * Returns: this function will return non-zero if the token
470 * holding the private key is still available (inserted), and zero otherwise.
471 *
472 * Since: 3.1.9
473 *
474 **/
gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)475 unsigned gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)
476 {
477 ck_rv_t rv;
478 int ret;
479 struct ck_session_info session_info;
480
481 PKCS11_CHECK_INIT_PRIVKEY(key);
482
483 REPEAT_ON_INVALID_HANDLE(rv = (key->sinfo.module)->C_GetSessionInfo(key->sinfo.pks, &session_info));
484 if (rv != CKR_OK) {
485 ret = 0;
486 goto cleanup;
487 }
488 ret = 1;
489
490 cleanup:
491
492 return ret;
493 }
494
495 /**
496 * gnutls_pkcs11_privkey_import_url:
497 * @pkey: The private key
498 * @url: a PKCS 11 url identifying the key
499 * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags
500 *
501 * This function will "import" a PKCS 11 URL identifying a private
502 * key to the #gnutls_pkcs11_privkey_t type. In reality since
503 * in most cases keys cannot be exported, the private key structure
504 * is being associated with the available operations on the token.
505 *
506 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
507 * negative error value.
508 **/
509 int
gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,const char * url,unsigned int flags)510 gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
511 const char *url, unsigned int flags)
512 {
513 int ret;
514 struct ck_attribute *attr;
515 struct ck_attribute a[4];
516 ck_key_type_t key_type;
517 ck_bool_t reauth = 0;
518
519 PKCS11_CHECK_INIT;
520
521 memset(&pkey->sinfo, 0, sizeof(pkey->sinfo));
522
523 if (pkey->url)
524 gnutls_free(pkey->url);
525
526 if (pkey->uinfo) {
527 p11_kit_uri_free(pkey->uinfo);
528 pkey->uinfo = NULL;
529 }
530
531 pkey->url = gnutls_strdup(url);
532 if (pkey->url == NULL)
533 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
534
535 ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY);
536 if (ret < 0) {
537 gnutls_assert();
538 goto cleanup;
539 }
540
541 pkey->flags = flags;
542
543 attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_CLASS);
544 if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
545 *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
546 gnutls_assert();
547 ret = GNUTLS_E_INVALID_REQUEST;
548 goto cleanup;
549 }
550
551 attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_ID);
552 if (!attr) {
553 attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_LABEL);
554 if (!attr) {
555 gnutls_assert();
556 ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
557 goto cleanup;
558 }
559 }
560
561 FIND_OBJECT(pkey);
562
563 pkey->pk_algorithm = GNUTLS_PK_UNKNOWN;
564 a[0].type = CKA_KEY_TYPE;
565 a[0].value = &key_type;
566 a[0].value_len = sizeof(key_type);
567 if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
568 == CKR_OK) {
569 pkey->pk_algorithm = key_type_to_pk(key_type);
570 }
571
572 if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) {
573 _gnutls_debug_log
574 ("Cannot determine PKCS #11 key algorithm\n");
575 ret = GNUTLS_E_UNKNOWN_ALGORITHM;
576 goto cleanup;
577 }
578
579
580 if (pkey->pk_algorithm == GNUTLS_PK_RSA) { /* determine whether it can do rsa-pss */
581 ck_bool_t tval = 0;
582
583 a[0].type = CKA_MODULUS;
584 a[0].value = NULL;
585 a[0].value_len = 0;
586 a[1].type = CKA_SIGN;
587 a[1].value = &tval;
588 a[1].value_len = sizeof(tval);
589 if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 2)
590 == CKR_OK) {
591 pkey->bits = a[0].value_len*8;
592 }
593
594 ret = gnutls_pkcs11_token_check_mechanism(url, CKM_RSA_PKCS_PSS, NULL, 0, 0);
595 if (ret != 0 && tval) {
596 pkey->rsa_pss_ok = 1;
597 } else {
598 _gnutls_debug_log("Detected incompatible with TLS1.3 RSA key! (%s)\n", url);
599 }
600 }
601
602 a[0].type = CKA_ALWAYS_AUTHENTICATE;
603 a[0].value = &reauth;
604 a[0].value_len = sizeof(reauth);
605
606 if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
607 == CKR_OK) {
608 pkey->reauth = reauth;
609 }
610
611 ret = 0;
612
613 return ret;
614
615 cleanup:
616 if (pkey->uinfo != NULL) {
617 p11_kit_uri_free(pkey->uinfo);
618 pkey->uinfo = NULL;
619 }
620 gnutls_free(pkey->url);
621
622 return ret;
623 }
624
625 /*-
626 * _gnutls_pkcs11_privkey_decrypt_data:
627 * @key: Holds the key
628 * @flags: should be 0 for now
629 * @ciphertext: holds the data to be signed
630 * @plaintext: will contain the plaintext, allocated with gnutls_malloc()
631 *
632 * This function will decrypt the given data using the public key algorithm
633 * supported by the private key.
634 *
635 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
636 * negative error value.
637 -*/
638 int
_gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,unsigned int flags,const gnutls_datum_t * ciphertext,gnutls_datum_t * plaintext)639 _gnutls_pkcs11_privkey_decrypt_data(gnutls_pkcs11_privkey_t key,
640 unsigned int flags,
641 const gnutls_datum_t * ciphertext,
642 gnutls_datum_t * plaintext)
643 {
644 ck_rv_t rv;
645 int ret;
646 struct ck_mechanism mech;
647 unsigned long siglen;
648 unsigned req_login = 0;
649 unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
650
651 PKCS11_CHECK_INIT_PRIVKEY(key);
652
653 if (key->pk_algorithm != GNUTLS_PK_RSA)
654 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
655
656 mech.mechanism = CKM_RSA_PKCS;
657 mech.parameter = NULL;
658 mech.parameter_len = 0;
659
660 ret = gnutls_mutex_lock(&key->mutex);
661 if (ret != 0)
662 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
663
664 /* Initialize signing operation; using the private key discovered
665 * earlier. */
666 REPEAT_ON_INVALID_HANDLE(rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks, &mech, key->ref));
667 if (rv != CKR_OK) {
668 gnutls_assert();
669 ret = pkcs11_rv_to_err(rv);
670 goto cleanup;
671 }
672
673 retry_login:
674 if (key->reauth || req_login) {
675 if (req_login)
676 login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
677 ret =
678 pkcs11_login(&key->sinfo, &key->pin,
679 key->uinfo, login_flags);
680 if (ret < 0) {
681 gnutls_assert();
682 _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
683 /* let's try the operation anyway */
684 }
685 }
686
687 /* Work out how long the plaintext must be: */
688 rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
689 ciphertext->size, NULL, &siglen);
690 if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
691 req_login = 1;
692 goto retry_login;
693 }
694
695 if (rv != CKR_OK) {
696 gnutls_assert();
697 ret = pkcs11_rv_to_err(rv);
698 goto cleanup;
699 }
700
701 plaintext->data = gnutls_malloc(siglen);
702 plaintext->size = siglen;
703
704 rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
705 ciphertext->size, plaintext->data, &siglen);
706 if (rv != CKR_OK) {
707 gnutls_free(plaintext->data);
708 gnutls_assert();
709 ret = pkcs11_rv_to_err(rv);
710 goto cleanup;
711 }
712
713 plaintext->size = siglen;
714
715 ret = 0;
716
717 cleanup:
718 gnutls_mutex_unlock(&key->mutex);
719 return ret;
720 }
721
722 /*-
723 * _gnutls_pkcs11_privkey_decrypt_data2:
724 * @key: Holds the key
725 * @flags: should be 0 for now
726 * @ciphertext: holds the data to be signed
727 * @plaintext: a preallocated buffer that will be filled with the plaintext
728 * @plaintext_size: size of the plaintext
729 *
730 * This function will decrypt the given data using the public key algorithm
731 * supported by the private key.
732 * Unlike with _gnutls_pkcs11_privkey_decrypt_data the plaintext size is known
733 * and provided by the caller, if the plaintext size differs from the requested
734 * one, the operation fails and the provided buffer is left unchanged.
735 * NOTE: plaintext_size must be exactly the size of the payload in the
736 * ciphertext, otherwise an error is returned and the plaintext buffer is left
737 * unchanged.
738 *
739 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
740 * negative error value.
741 -*/
742 int
_gnutls_pkcs11_privkey_decrypt_data2(gnutls_pkcs11_privkey_t key,unsigned int flags,const gnutls_datum_t * ciphertext,unsigned char * plaintext,size_t plaintext_size)743 _gnutls_pkcs11_privkey_decrypt_data2(gnutls_pkcs11_privkey_t key,
744 unsigned int flags,
745 const gnutls_datum_t * ciphertext,
746 unsigned char * plaintext,
747 size_t plaintext_size)
748 {
749 ck_rv_t rv;
750 int ret;
751 struct ck_mechanism mech;
752 unsigned long siglen = ciphertext->size;
753 unsigned req_login = 0;
754 unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
755 unsigned char *buffer;
756 volatile unsigned char value;
757 unsigned char mask;
758
759 PKCS11_CHECK_INIT_PRIVKEY(key);
760
761 if (key->pk_algorithm != GNUTLS_PK_RSA)
762 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
763
764 mech.mechanism = CKM_RSA_PKCS;
765 mech.parameter = NULL;
766 mech.parameter_len = 0;
767
768 ret = gnutls_mutex_lock(&key->mutex);
769 if (ret != 0)
770 return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
771
772 buffer = gnutls_malloc(siglen);
773 if (!buffer) {
774 gnutls_assert();
775 return GNUTLS_E_MEMORY_ERROR;
776 }
777
778 /* Initialize signing operation; using the private key discovered
779 * earlier. */
780 REPEAT_ON_INVALID_HANDLE(
781 rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks,
782 &mech, key->ref)
783 );
784 if (rv != CKR_OK) {
785 gnutls_assert();
786 ret = pkcs11_rv_to_err(rv);
787 goto cleanup;
788 }
789
790 retry_login:
791 if (key->reauth || req_login) {
792 if (req_login)
793 login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
794 ret =
795 pkcs11_login(&key->sinfo, &key->pin,
796 key->uinfo, login_flags);
797 if (ret < 0) {
798 gnutls_assert();
799 _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
800 /* let's try the operation anyway */
801 }
802 }
803
804 ret = 0;
805 siglen = ciphertext->size;
806 rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks,
807 ciphertext->data, ciphertext->size,
808 buffer, &siglen);
809 if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
810 req_login = 1;
811 goto retry_login;
812 }
813
814 /* NOTE: These branches are not side-channel silent */
815 if (rv != CKR_OK) {
816 gnutls_assert();
817 ret = pkcs11_rv_to_err(rv);
818 } else if (siglen != plaintext_size) {
819 gnutls_assert();
820 ret = GNUTLS_E_INVALID_REQUEST;
821 }
822
823 /* conditionally copy buffer in a side-channel silent way */
824 /* on success mask is 0xFF, on failure it is 0 */
825 mask = ((uint32_t)ret >> 31) - 1U;
826 for (size_t i = 0; i < plaintext_size; i++) {
827 value = (buffer[i] & mask) + (plaintext[i] & ~mask);
828 plaintext[i] = value;
829 }
830
831 cleanup:
832 gnutls_mutex_unlock(&key->mutex);
833 gnutls_free(buffer);
834 return ret;
835 }
836
837 /**
838 * gnutls_pkcs11_privkey_export_url:
839 * @key: Holds the PKCS 11 key
840 * @detailed: non zero if a detailed URL is required
841 * @url: will contain an allocated url
842 *
843 * This function will export a URL identifying the given key.
844 *
845 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
846 * negative error value.
847 **/
848 int
gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,gnutls_pkcs11_url_type_t detailed,char ** url)849 gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,
850 gnutls_pkcs11_url_type_t detailed,
851 char **url)
852 {
853 int ret;
854
855 ret = pkcs11_info_to_url(key->uinfo, detailed, url);
856 if (ret < 0) {
857 gnutls_assert();
858 return ret;
859 }
860
861 return 0;
862 }
863
864 #if 0
865 /**
866 * gnutls_pkcs11_privkey_generate:
867 * @url: a token URL
868 * @pk: the public key algorithm
869 * @bits: the security bits
870 * @label: a label
871 * @flags: should be zero
872 *
873 * This function will generate a private key in the specified
874 * by the @url token. The private key will be generate within
875 * the token and will not be exportable.
876 *
877 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
878 * negative error value.
879 *
880 * Since: 3.0
881 **/
882 int
883 gnutls_pkcs11_privkey_generate(const char *url, gnutls_pk_algorithm_t pk,
884 unsigned int bits, const char *label,
885 unsigned int flags)
886 {
887 int x;
888 }
889
890 /**
891 * gnutls_pkcs11_privkey_generate2:
892 * @url: a token URL
893 * @pk: the public key algorithm
894 * @bits: the security bits
895 * @label: a label
896 * @fmt: the format of output params. PEM or DER
897 * @pubkey: will hold the public key (may be %NULL)
898 * @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
899 *
900 * This function will generate a private key in the specified
901 * by the @url token. The private key will be generate within
902 * the token and will not be exportable. This function will
903 * store the DER-encoded public key in the SubjectPublicKeyInfo format
904 * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
905 *
906 * Note that when generating an elliptic curve key, the curve
907 * can be substituted in the place of the bits parameter using the
908 * GNUTLS_CURVE_TO_BITS() macro.
909 *
910 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
911 * negative error value.
912 *
913 * Since: 3.1.5
914 **/
915 int
916 gnutls_pkcs11_privkey_generate2(const char *url, gnutls_pk_algorithm_t pk,
917 unsigned int bits, const char *label,
918 gnutls_x509_crt_fmt_t fmt,
919 gnutls_datum_t * pubkey,
920 unsigned int flags)
921 {
922 int x;
923 }
924 #endif
925
926 static const char def_rsa_pub_exp[3] = { 1,0,1 }; // 65537 = 0x10001
927
928 struct dsa_params {
929 /* FIPS 186-3 maximal size for L and N length pair is (3072,256). */
930 uint8_t prime[384];
931 uint8_t subprime[32];
932 uint8_t generator[384];
933 };
934
935 static int
_dsa_params_generate(struct ck_function_list * module,ck_session_handle_t session,unsigned long bits,struct dsa_params * params,struct ck_attribute * a,int * a_val)936 _dsa_params_generate(struct ck_function_list *module, ck_session_handle_t session,
937 unsigned long bits, struct dsa_params *params,
938 struct ck_attribute *a, int *a_val)
939 {
940 struct ck_mechanism mech = { CKM_DSA_PARAMETER_GEN };
941 struct ck_attribute attr = { CKA_PRIME_BITS, &bits, sizeof(bits) };
942 ck_object_handle_t key;
943 ck_rv_t rv;
944
945 /* Generate DSA parameters from prime length. */
946
947 rv = pkcs11_generate_key(module, session, &mech, &attr, 1, &key);
948 if (rv != CKR_OK) {
949 gnutls_assert();
950 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
951 return pkcs11_rv_to_err(rv);
952 }
953
954 /* Retrieve generated parameters to be used with the new key pair. */
955
956 a[*a_val + 0].type = CKA_PRIME;
957 a[*a_val + 0].value = params->prime;
958 a[*a_val + 0].value_len = sizeof(params->prime);
959
960 a[*a_val + 1].type = CKA_SUBPRIME;
961 a[*a_val + 1].value = params->subprime;
962 a[*a_val + 1].value_len = sizeof(params->subprime);
963
964 a[*a_val + 2].type = CKA_BASE;
965 a[*a_val + 2].value = params->generator;
966 a[*a_val + 2].value_len = sizeof(params->generator);
967
968 rv = pkcs11_get_attribute_value(module, session, key, &a[*a_val], 3);
969 if (rv != CKR_OK) {
970 gnutls_assert();
971 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
972 return pkcs11_rv_to_err(rv);
973 }
974
975 *a_val += 3;
976
977 return 0;
978 }
979
980 /**
981 * gnutls_pkcs11_privkey_generate3:
982 * @url: a token URL
983 * @pk: the public key algorithm
984 * @bits: the security bits
985 * @label: a label
986 * @cid: The CKA_ID to use for the new object
987 * @fmt: the format of output params. PEM or DER
988 * @pubkey: will hold the public key (may be %NULL)
989 * @key_usage: One of GNUTLS_KEY_*
990 * @flags: zero or an OR'ed sequence of %GNUTLS_PKCS11_OBJ_FLAGs
991 *
992 * This function will generate a private key in the specified
993 * by the @url token. The private key will be generate within
994 * the token and will not be exportable. This function will
995 * store the DER-encoded public key in the SubjectPublicKeyInfo format
996 * in @pubkey. The @pubkey should be deinitialized using gnutls_free().
997 *
998 * Note that when generating an elliptic curve key, the curve
999 * can be substituted in the place of the bits parameter using the
1000 * GNUTLS_CURVE_TO_BITS() macro.
1001 *
1002 * Since 3.6.3 the objects are marked as sensitive by default unless
1003 * %GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified.
1004 *
1005 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1006 * negative error value.
1007 *
1008 * Since: 3.4.0
1009 **/
1010 int
gnutls_pkcs11_privkey_generate3(const char * url,gnutls_pk_algorithm_t pk,unsigned int bits,const char * label,const gnutls_datum_t * cid,gnutls_x509_crt_fmt_t fmt,gnutls_datum_t * pubkey,unsigned int key_usage,unsigned int flags)1011 gnutls_pkcs11_privkey_generate3(const char *url, gnutls_pk_algorithm_t pk,
1012 unsigned int bits, const char *label,
1013 const gnutls_datum_t *cid,
1014 gnutls_x509_crt_fmt_t fmt,
1015 gnutls_datum_t * pubkey,
1016 unsigned int key_usage,
1017 unsigned int flags)
1018 {
1019 int ret;
1020 const ck_bool_t tval = 1;
1021 const ck_bool_t fval = 0;
1022 struct pkcs11_session_info sinfo;
1023 struct p11_kit_uri *info = NULL;
1024 ck_rv_t rv;
1025 struct ck_attribute a[22], p[22];
1026 ck_object_handle_t pub_ctx, priv_ctx;
1027 unsigned long _bits = bits;
1028 int a_val, p_val;
1029 struct ck_mechanism mech;
1030 gnutls_pubkey_t pkey = NULL;
1031 gnutls_pkcs11_obj_t obj = NULL;
1032 gnutls_datum_t der = {NULL, 0};
1033 ck_key_type_t key_type;
1034 uint8_t id[20];
1035 struct dsa_params dsa_params;
1036
1037 PKCS11_CHECK_INIT;
1038 FIX_KEY_USAGE(pk, key_usage);
1039
1040 memset(&sinfo, 0, sizeof(sinfo));
1041
1042 ret = pkcs11_url_to_info(url, &info, 0);
1043 if (ret < 0) {
1044 gnutls_assert();
1045 return ret;
1046 }
1047
1048 ret =
1049 pkcs11_open_session(&sinfo, NULL, info,
1050 SESSION_WRITE |
1051 pkcs11_obj_flags_to_int(flags));
1052 p11_kit_uri_free(info);
1053
1054 if (ret < 0) {
1055 gnutls_assert();
1056 goto cleanup;
1057 }
1058
1059 /* a holds the public key template
1060 * and p the private key */
1061 a_val = p_val = 0;
1062 mech.parameter = NULL;
1063 mech.parameter_len = 0;
1064 mech.mechanism = pk_to_genmech(pk, &key_type);
1065
1066 if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_NO_STORE_PUBKEY)) {
1067 a[a_val].type = CKA_TOKEN;
1068 a[a_val].value = (void *) &tval;
1069 a[a_val].value_len = sizeof(tval);
1070 a_val++;
1071
1072 a[a_val].type = CKA_PRIVATE;
1073 a[a_val].value = (void *) &fval;
1074 a[a_val].value_len = sizeof(fval);
1075 a_val++;
1076 }
1077
1078 a[a_val].type = CKA_ID;
1079 if (cid == NULL || cid->size == 0) {
1080 ret = gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id));
1081 if (ret < 0) {
1082 gnutls_assert();
1083 goto cleanup;
1084 }
1085
1086 a[a_val].value = (void *) id;
1087 a[a_val].value_len = sizeof(id);
1088 } else {
1089 a[a_val].value = (void *) cid->data;
1090 a[a_val].value_len = cid->size;
1091 }
1092
1093 p[p_val].type = CKA_ID;
1094 p[p_val].value = a[a_val].value;
1095 p[p_val].value_len = a[a_val].value_len;
1096 a_val++;
1097 p_val++;
1098
1099 switch (pk) {
1100 case GNUTLS_PK_RSA:
1101 p[p_val].type = CKA_DECRYPT;
1102 if (key_usage & (GNUTLS_KEY_DECIPHER_ONLY|GNUTLS_KEY_ENCIPHER_ONLY)) {
1103 p[p_val].value = (void *) &tval;
1104 p[p_val].value_len = sizeof(tval);
1105 } else {
1106 p[p_val].value = (void *) &fval;
1107 p[p_val].value_len = sizeof(fval);
1108 }
1109 p_val++;
1110
1111 p[p_val].type = CKA_SIGN;
1112 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
1113 p[p_val].value = (void *) &tval;
1114 p[p_val].value_len = sizeof(tval);
1115 } else {
1116 p[p_val].value = (void *) &fval;
1117 p[p_val].value_len = sizeof(fval);
1118 }
1119 p_val++;
1120
1121 a[a_val].type = CKA_ENCRYPT;
1122 a[a_val].value = (void *) &tval;
1123 a[a_val].value_len = sizeof(tval);
1124 a_val++;
1125
1126 a[a_val].type = CKA_VERIFY;
1127 a[a_val].value = (void *) &tval;
1128 a[a_val].value_len = sizeof(tval);
1129 a_val++;
1130
1131 a[a_val].type = CKA_MODULUS_BITS;
1132 a[a_val].value = &_bits;
1133 a[a_val].value_len = sizeof(_bits);
1134 a_val++;
1135
1136 a[a_val].type = CKA_PUBLIC_EXPONENT;
1137 a[a_val].value = (char*)def_rsa_pub_exp;
1138 a[a_val].value_len = sizeof(def_rsa_pub_exp);
1139 a_val++;
1140
1141 break;
1142 case GNUTLS_PK_DSA:
1143 p[p_val].type = CKA_SIGN;
1144 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
1145 p[p_val].value = (void *) &tval;
1146 p[p_val].value_len = sizeof(tval);
1147 } else {
1148 p[p_val].value = (void *) &fval;
1149 p[p_val].value_len = sizeof(fval);
1150 }
1151 p_val++;
1152
1153 a[a_val].type = CKA_VERIFY;
1154 a[a_val].value = (void *) &tval;
1155 a[a_val].value_len = sizeof(tval);
1156 a_val++;
1157
1158 ret = _dsa_params_generate(sinfo.module, sinfo.pks, _bits,
1159 &dsa_params, a, &a_val);
1160 if (ret < 0) {
1161 goto cleanup;
1162 }
1163
1164 break;
1165 case GNUTLS_PK_ECDSA:
1166 p[p_val].type = CKA_SIGN;
1167 if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
1168 p[p_val].value = (void *) &tval;
1169 p[p_val].value_len = sizeof(tval);
1170 } else {
1171 p[p_val].value = (void *) &fval;
1172 p[p_val].value_len = sizeof(fval);
1173 }
1174 p_val++;
1175
1176 a[a_val].type = CKA_VERIFY;
1177 a[a_val].value = (void *) &tval;
1178 a[a_val].value_len = sizeof(tval);
1179 a_val++;
1180
1181 if (GNUTLS_BITS_ARE_CURVE(bits)) {
1182 bits = GNUTLS_BITS_TO_CURVE(bits);
1183 } else {
1184 bits = _gnutls_ecc_bits_to_curve(pk, bits);
1185 }
1186
1187 ret = _gnutls_x509_write_ecc_params(bits, &der);
1188 if (ret < 0) {
1189 gnutls_assert();
1190 goto cleanup;
1191 }
1192
1193 a[a_val].type = CKA_EC_PARAMS;
1194 a[a_val].value = der.data;
1195 a[a_val].value_len = der.size;
1196 a_val++;
1197
1198 break;
1199 case GNUTLS_PK_EDDSA_ED25519:
1200 p[p_val].type = CKA_SIGN;
1201 p[p_val].value = (void *) &tval;
1202 p[p_val].value_len = sizeof(tval);
1203 p_val++;
1204
1205 a[a_val].type = CKA_VERIFY;
1206 a[a_val].value = (void *) &tval;
1207 a[a_val].value_len = sizeof(tval);
1208 a_val++;
1209
1210 ret = _gnutls_x509_write_ecc_params(GNUTLS_ECC_CURVE_ED25519, &der);
1211 if (ret < 0) {
1212 gnutls_assert();
1213 goto cleanup;
1214 }
1215
1216 a[a_val].type = CKA_EC_PARAMS;
1217 a[a_val].value = der.data;
1218 a[a_val].value_len = der.size;
1219 a_val++;
1220 break;
1221 default:
1222 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1223 goto cleanup;
1224 }
1225
1226 /*
1227 * on request, add the CKA_WRAP/CKA_UNWRAP key attribute
1228 */
1229 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP) {
1230 p[p_val].type = CKA_UNWRAP;
1231 p[p_val].value = (void*)&tval;
1232 p[p_val].value_len = sizeof(tval);
1233 p_val++;
1234 a[a_val].type = CKA_WRAP;
1235 a[a_val].value = (void*)&tval;
1236 a[a_val].value_len = sizeof(tval);
1237 a_val++;
1238 }
1239
1240 /* a private key is set always as private unless
1241 * requested otherwise
1242 */
1243 if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
1244 p[p_val].type = CKA_PRIVATE;
1245 p[p_val].value = (void *) &fval;
1246 p[p_val].value_len = sizeof(fval);
1247 p_val++;
1248 } else {
1249 p[p_val].type = CKA_PRIVATE;
1250 p[p_val].value = (void *) &tval;
1251 p[p_val].value_len = sizeof(tval);
1252 p_val++;
1253 }
1254
1255 p[p_val].type = CKA_TOKEN;
1256 p[p_val].value = (void *) &tval;
1257 p[p_val].value_len = sizeof(tval);
1258 p_val++;
1259
1260 if (label) {
1261 p[p_val].type = CKA_LABEL;
1262 p[p_val].value = (void *) label;
1263 p[p_val].value_len = strlen(label);
1264 p_val++;
1265
1266 a[a_val].type = CKA_LABEL;
1267 a[a_val].value = (void *) label;
1268 a[a_val].value_len = strlen(label);
1269 a_val++;
1270 }
1271
1272 if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) {
1273 p[p_val].type = CKA_SENSITIVE;
1274 p[p_val].value = (void *) &tval;
1275 p[p_val].value_len = sizeof(tval);
1276 p_val++;
1277 } else {
1278 p[p_val].type = CKA_SENSITIVE;
1279 p[p_val].value = (void *) &fval;
1280 p[p_val].value_len = sizeof(fval);
1281 p_val++;
1282 }
1283
1284 rv = pkcs11_generate_key_pair(sinfo.module, sinfo.pks, &mech, a,
1285 a_val, p, p_val, &pub_ctx, &priv_ctx);
1286 if (rv != CKR_OK) {
1287 gnutls_assert();
1288 _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
1289 ret = pkcs11_rv_to_err(rv);
1290 goto cleanup;
1291 }
1292
1293 /* extract the public key */
1294 if (pubkey) {
1295
1296 ret = gnutls_pubkey_init(&pkey);
1297 if (ret < 0) {
1298 gnutls_assert();
1299 goto cleanup;
1300 }
1301
1302 ret = gnutls_pkcs11_obj_init(&obj);
1303 if (ret < 0) {
1304 gnutls_assert();
1305 goto cleanup;
1306 }
1307
1308 obj->pk_algorithm = pk;
1309 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1310 ret =
1311 pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub_ctx,
1312 key_type, obj);
1313 if (ret < 0) {
1314 gnutls_assert();
1315 goto cleanup;
1316 }
1317
1318 ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
1319 if (ret < 0) {
1320 gnutls_assert();
1321 goto cleanup;
1322 }
1323
1324 ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
1325 if (ret < 0) {
1326 gnutls_assert();
1327 goto cleanup;
1328 }
1329 }
1330
1331 cleanup:
1332 if (obj != NULL)
1333 gnutls_pkcs11_obj_deinit(obj);
1334 if (pkey != NULL)
1335 gnutls_pubkey_deinit(pkey);
1336
1337 if (sinfo.pks != 0)
1338 pkcs11_close_session(&sinfo);
1339 gnutls_free(der.data);
1340
1341 return ret;
1342 }
1343
1344 /* loads a the corresponding to the private key public key either from
1345 * a public key object or from a certificate.
1346 */
load_pubkey_obj(gnutls_pkcs11_privkey_t pkey,gnutls_pubkey_t pub)1347 static int load_pubkey_obj(gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t pub)
1348 {
1349 int ret, iret;
1350 gnutls_x509_crt_t crt;
1351
1352 ret = gnutls_pubkey_import_url(pub, pkey->url, pkey->flags);
1353 if (ret >= 0) {
1354 return ret;
1355 }
1356 iret = ret;
1357
1358 /* else try certificate */
1359 ret = gnutls_x509_crt_init(&crt);
1360 if (ret < 0) {
1361 gnutls_assert();
1362 return ret;
1363 }
1364
1365 gnutls_x509_crt_set_pin_function(crt, pkey->pin.cb, pkey->pin.data);
1366
1367 ret = gnutls_x509_crt_import_url(crt, pkey->url, pkey->flags);
1368 if (ret < 0) {
1369 ret = iret;
1370 goto cleanup;
1371 }
1372
1373 ret = gnutls_pubkey_import_x509(pub, crt, 0);
1374
1375 cleanup:
1376 gnutls_x509_crt_deinit(crt);
1377 return ret;
1378 }
1379
1380 int
_pkcs11_privkey_get_pubkey(gnutls_pkcs11_privkey_t pkey,gnutls_pubkey_t * pub,unsigned flags)1381 _pkcs11_privkey_get_pubkey (gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t *pub, unsigned flags)
1382 {
1383 gnutls_pubkey_t pubkey = NULL;
1384 gnutls_pkcs11_obj_t obj = NULL;
1385 ck_key_type_t key_type;
1386 int ret;
1387
1388 PKCS11_CHECK_INIT_PRIVKEY(pkey);
1389
1390 if (!pkey) {
1391 gnutls_assert();
1392 return GNUTLS_E_INVALID_REQUEST;
1393 }
1394
1395 ret = gnutls_pubkey_init(&pubkey);
1396 if (ret < 0) {
1397 gnutls_assert();
1398 goto cleanup;
1399 }
1400
1401 ret = gnutls_pkcs11_obj_init(&obj);
1402 if (ret < 0) {
1403 gnutls_assert();
1404 goto cleanup;
1405 }
1406
1407 obj->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm(pkey, 0);
1408 obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1409 pk_to_genmech(obj->pk_algorithm, &key_type);
1410
1411 gnutls_pubkey_set_pin_function(pubkey, pkey->pin.cb, pkey->pin.data);
1412
1413 /* we can only read the public key from RSA keys */
1414 if (key_type != CKK_RSA) {
1415 /* try opening the public key object if it exists */
1416 ret = load_pubkey_obj(pkey, pubkey);
1417 if (ret < 0) {
1418 gnutls_assert();
1419 goto cleanup;
1420 }
1421 } else {
1422 ret = pkcs11_read_pubkey(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, key_type, obj);
1423 if (ret < 0) {
1424 gnutls_assert();
1425 goto cleanup;
1426 }
1427
1428 ret = gnutls_pubkey_import_pkcs11(pubkey, obj, 0);
1429 if (ret < 0) {
1430 gnutls_assert();
1431 goto cleanup;
1432 }
1433 }
1434
1435 *pub = pubkey;
1436
1437 pubkey = NULL;
1438 ret = 0;
1439
1440 cleanup:
1441 if (obj != NULL)
1442 gnutls_pkcs11_obj_deinit(obj);
1443 if (pubkey != NULL)
1444 gnutls_pubkey_deinit(pubkey);
1445
1446 return ret;
1447 }
1448
1449 /**
1450 * gnutls_pkcs11_privkey_export_pubkey
1451 * @pkey: The private key
1452 * @fmt: the format of output params. PEM or DER.
1453 * @data: will hold the public key
1454 * @flags: should be zero
1455 *
1456 * This function will extract the public key (modulus and public
1457 * exponent) from the private key specified by the @url private key.
1458 * This public key will be stored in @pubkey in the format specified
1459 * by @fmt. @pubkey should be deinitialized using gnutls_free().
1460 *
1461 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1462 * negative error value.
1463 *
1464 * Since: 3.3.7
1465 **/
1466 int
gnutls_pkcs11_privkey_export_pubkey(gnutls_pkcs11_privkey_t pkey,gnutls_x509_crt_fmt_t fmt,gnutls_datum_t * data,unsigned int flags)1467 gnutls_pkcs11_privkey_export_pubkey(gnutls_pkcs11_privkey_t pkey,
1468 gnutls_x509_crt_fmt_t fmt,
1469 gnutls_datum_t * data,
1470 unsigned int flags)
1471 {
1472 int ret;
1473 gnutls_pubkey_t pubkey = NULL;
1474
1475 ret = _pkcs11_privkey_get_pubkey(pkey, &pubkey, flags);
1476 if (ret < 0)
1477 return gnutls_assert_val(ret);
1478
1479 ret = gnutls_pubkey_export2(pubkey, fmt, data);
1480 if (ret < 0) {
1481 gnutls_assert();
1482 goto cleanup;
1483 }
1484
1485 ret = 0;
1486
1487 cleanup:
1488 if (pubkey != NULL)
1489 gnutls_pubkey_deinit(pubkey);
1490
1491 return ret;
1492 }
1493
1494 /**
1495 * gnutls_pkcs11_privkey_set_pin_function:
1496 * @key: The private key
1497 * @fn: the callback
1498 * @userdata: data associated with the callback
1499 *
1500 * This function will set a callback function to be used when
1501 * required to access the object. This function overrides the global
1502 * set using gnutls_pkcs11_set_pin_function().
1503 *
1504 * Since: 3.1.0
1505 *
1506 **/
1507 void
gnutls_pkcs11_privkey_set_pin_function(gnutls_pkcs11_privkey_t key,gnutls_pin_callback_t fn,void * userdata)1508 gnutls_pkcs11_privkey_set_pin_function(gnutls_pkcs11_privkey_t key,
1509 gnutls_pin_callback_t fn,
1510 void *userdata)
1511 {
1512 key->pin.cb = fn;
1513 key->pin.data = userdata;
1514 }
1515