Line data Source code
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 : **/
78 72 : int gnutls_pkcs11_privkey_init(gnutls_pkcs11_privkey_t * key)
79 : {
80 72 : int ret;
81 72 : FAIL_IF_LIB_ERROR;
82 :
83 72 : *key = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_privkey_st));
84 72 : if (*key == NULL) {
85 0 : gnutls_assert();
86 0 : return GNUTLS_E_MEMORY_ERROR;
87 : }
88 :
89 72 : (*key)->uinfo = p11_kit_uri_new();
90 72 : if ((*key)->uinfo == NULL) {
91 0 : free(*key);
92 0 : gnutls_assert();
93 0 : return GNUTLS_E_MEMORY_ERROR;
94 : }
95 :
96 72 : ret = gnutls_mutex_init(&(*key)->mutex);
97 72 : if (ret < 0) {
98 0 : gnutls_assert();
99 0 : p11_kit_uri_free((*key)->uinfo);
100 0 : free(*key);
101 0 : 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
121 0 : gnutls_pkcs11_privkey_cpy(gnutls_pkcs11_privkey_t dst,
122 : gnutls_pkcs11_privkey_t src)
123 : {
124 0 : 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 : **/
133 61 : void gnutls_pkcs11_privkey_deinit(gnutls_pkcs11_privkey_t key)
134 : {
135 61 : p11_kit_uri_free(key->uinfo);
136 61 : gnutls_free(key->url);
137 61 : if (key->sinfo.init != 0)
138 59 : pkcs11_close_session(&key->sinfo);
139 61 : gnutls_mutex_deinit(&key->mutex);
140 61 : gnutls_free(key);
141 61 : }
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
155 416 : gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key,
156 : unsigned int *bits)
157 : {
158 416 : if (bits)
159 282 : *bits = key->bits;
160 416 : 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
178 0 : 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 0 : return pkcs11_get_info(pkey->uinfo, itype, output, output_size);
183 : }
184 :
185 : static int
186 75 : 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 75 : int ret;
192 75 : ck_object_handle_t ctx;
193 75 : struct ck_attribute *attrs;
194 75 : unsigned long attr_count;
195 75 : unsigned long count;
196 75 : ck_rv_t rv;
197 :
198 75 : ret =
199 75 : pkcs11_open_session(sinfo, pin_info, info,
200 : flags & SESSION_LOGIN);
201 75 : if (ret < 0) {
202 2 : gnutls_assert();
203 2 : return ret;
204 : }
205 :
206 73 : attrs = p11_kit_uri_get_attributes(info, &attr_count);
207 73 : rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, attrs,
208 : attr_count);
209 73 : if (rv != CKR_OK) {
210 0 : gnutls_assert();
211 0 : _gnutls_debug_log("p11: FindObjectsInit failed.\n");
212 0 : ret = pkcs11_rv_to_err(rv);
213 0 : goto fail;
214 : }
215 :
216 73 : if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count)
217 73 : == CKR_OK && count == 1) {
218 73 : *_ctx = ctx;
219 73 : pkcs11_find_objects_final(sinfo);
220 73 : return 0;
221 : }
222 :
223 0 : ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
224 0 : pkcs11_find_objects_final(sinfo);
225 0 : fail:
226 0 : pkcs11_close_session(sinfo);
227 :
228 0 : 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. */
235 3 : static int reopen_privkey_session(void * _privkey)
236 : {
237 3 : int ret;
238 3 : gnutls_pkcs11_privkey_t privkey = _privkey;
239 :
240 3 : memset(&privkey->sinfo, 0, sizeof(privkey->sinfo));
241 3 : privkey->ref = 0;
242 3 : 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 :
296 43 : static const struct hash_mappings_st *hash_to_map(gnutls_digest_algorithm_t hash)
297 : {
298 43 : unsigned i;
299 86 : for (i=0;i<sizeof(hash_mappings)/sizeof(hash_mappings[0]);i++) {
300 86 : if (hash == hash_mappings[i].id)
301 43 : 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
321 249 : _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 249 : ck_rv_t rv;
328 249 : int ret;
329 249 : struct ck_mechanism mech;
330 249 : gnutls_datum_t tmp = { NULL, 0 };
331 249 : unsigned long siglen;
332 249 : struct pkcs11_session_info *sinfo;
333 249 : unsigned req_login = 0;
334 249 : unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
335 249 : struct ck_rsa_pkcs_pss_params rsa_pss_params;
336 :
337 249 : PKCS11_CHECK_INIT_PRIVKEY(key);
338 :
339 249 : sinfo = &key->sinfo;
340 :
341 249 : if (se->pk == GNUTLS_PK_RSA_PSS) {
342 43 : const struct hash_mappings_st *map = hash_to_map(se->hash);
343 :
344 43 : if (unlikely(map == NULL))
345 0 : return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
346 :
347 43 : if (unlikely(!key->rsa_pss_ok))
348 0 : return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
349 :
350 43 : rsa_pss_params.hash_alg = map->phash;
351 43 : rsa_pss_params.mgf = map->mgf_id;
352 43 : rsa_pss_params.s_len = spki_params->salt_size;
353 :
354 43 : mech.mechanism = CKM_RSA_PKCS_PSS;
355 43 : mech.parameter = &rsa_pss_params;
356 43 : mech.parameter_len = sizeof(rsa_pss_params);
357 : } else {
358 206 : ret = pk_to_mech(se->pk);
359 :
360 0 : if (ret == -1)
361 0 : return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
362 :
363 206 : mech.mechanism = ret;
364 206 : mech.parameter = NULL;
365 206 : mech.parameter_len = 0;
366 : }
367 :
368 249 : ret = gnutls_mutex_lock(&key->mutex);
369 249 : if (ret != 0)
370 0 : return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
371 :
372 : /* Initialize signing operation; using the private key discovered
373 : * earlier. */
374 249 : REPEAT_ON_INVALID_HANDLE(rv = pkcs11_sign_init(sinfo->module, sinfo->pks, &mech, key->ref));
375 249 : if (rv != CKR_OK) {
376 2 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
377 2 : gnutls_assert();
378 2 : ret = pkcs11_rv_to_err(rv);
379 2 : goto cleanup;
380 : }
381 :
382 247 : retry_login:
383 249 : if (key->reauth || req_login) {
384 4 : if (req_login)
385 2 : login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
386 4 : ret =
387 4 : pkcs11_login(&key->sinfo, &key->pin,
388 : key->uinfo, login_flags);
389 4 : if (ret < 0) {
390 0 : gnutls_assert();
391 0 : _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 249 : rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
398 : NULL, &siglen);
399 249 : if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
400 2 : req_login = 1;
401 2 : goto retry_login;
402 : }
403 :
404 247 : if (rv != CKR_OK) {
405 0 : gnutls_assert();
406 0 : ret = pkcs11_rv_to_err(rv);
407 0 : goto cleanup;
408 : }
409 :
410 247 : tmp.data = gnutls_malloc(siglen);
411 247 : tmp.size = siglen;
412 :
413 247 : rv = pkcs11_sign(sinfo->module, sinfo->pks, hash->data, hash->size,
414 : tmp.data, &siglen);
415 247 : if (rv != CKR_OK) {
416 0 : gnutls_assert();
417 0 : ret = pkcs11_rv_to_err(rv);
418 0 : goto cleanup;
419 : }
420 :
421 :
422 247 : if (key->pk_algorithm == GNUTLS_PK_ECDSA
423 247 : || key->pk_algorithm == GNUTLS_PK_DSA) {
424 105 : unsigned int hlen = siglen / 2;
425 105 : gnutls_datum_t r, s;
426 :
427 105 : if (siglen % 2 != 0) {
428 0 : gnutls_assert();
429 0 : ret = GNUTLS_E_PK_SIGN_FAILED;
430 0 : goto cleanup;
431 : }
432 :
433 105 : r.data = tmp.data;
434 105 : r.size = hlen;
435 :
436 105 : s.data = &tmp.data[hlen];
437 105 : s.size = hlen;
438 :
439 105 : ret = _gnutls_encode_ber_rs_raw(signature, &r, &s);
440 105 : if (ret < 0) {
441 0 : gnutls_assert();
442 0 : goto cleanup;
443 : }
444 :
445 105 : gnutls_free(tmp.data);
446 : } else {
447 142 : signature->size = siglen;
448 142 : signature->data = tmp.data;
449 : }
450 :
451 : ret = 0;
452 :
453 249 : cleanup:
454 249 : gnutls_mutex_unlock(&key->mutex);
455 249 : if (sinfo != &key->sinfo)
456 : pkcs11_close_session(sinfo);
457 249 : if (ret < 0)
458 2 : 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 : **/
475 0 : unsigned gnutls_pkcs11_privkey_status(gnutls_pkcs11_privkey_t key)
476 : {
477 0 : ck_rv_t rv;
478 0 : int ret;
479 0 : struct ck_session_info session_info;
480 :
481 0 : PKCS11_CHECK_INIT_PRIVKEY(key);
482 :
483 0 : REPEAT_ON_INVALID_HANDLE(rv = (key->sinfo.module)->C_GetSessionInfo(key->sinfo.pks, &session_info));
484 0 : if (rv != CKR_OK) {
485 0 : ret = 0;
486 0 : goto cleanup;
487 : }
488 : ret = 1;
489 :
490 0 : cleanup:
491 :
492 0 : 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
510 72 : gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
511 : const char *url, unsigned int flags)
512 : {
513 72 : int ret;
514 72 : struct ck_attribute *attr;
515 72 : struct ck_attribute a[4];
516 72 : ck_key_type_t key_type;
517 72 : ck_bool_t reauth = 0;
518 :
519 72 : PKCS11_CHECK_INIT;
520 :
521 72 : memset(&pkey->sinfo, 0, sizeof(pkey->sinfo));
522 :
523 72 : if (pkey->url)
524 0 : gnutls_free(pkey->url);
525 :
526 72 : if (pkey->uinfo) {
527 72 : p11_kit_uri_free(pkey->uinfo);
528 72 : pkey->uinfo = NULL;
529 : }
530 :
531 72 : pkey->url = gnutls_strdup(url);
532 72 : if (pkey->url == NULL)
533 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
534 :
535 72 : ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY);
536 72 : if (ret < 0) {
537 0 : gnutls_assert();
538 0 : goto cleanup;
539 : }
540 :
541 72 : pkey->flags = flags;
542 :
543 72 : attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_CLASS);
544 72 : if (!attr || attr->value_len != sizeof(ck_object_class_t) ||
545 72 : *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) {
546 0 : gnutls_assert();
547 0 : ret = GNUTLS_E_INVALID_REQUEST;
548 0 : goto cleanup;
549 : }
550 :
551 72 : attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_ID);
552 72 : if (!attr) {
553 49 : attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_LABEL);
554 49 : if (!attr) {
555 0 : gnutls_assert();
556 0 : ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
557 0 : goto cleanup;
558 : }
559 : }
560 :
561 72 : FIND_OBJECT(pkey);
562 :
563 70 : pkey->pk_algorithm = GNUTLS_PK_UNKNOWN;
564 70 : a[0].type = CKA_KEY_TYPE;
565 70 : a[0].value = &key_type;
566 70 : a[0].value_len = sizeof(key_type);
567 70 : if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
568 : == CKR_OK) {
569 79 : pkey->pk_algorithm = key_type_to_pk(key_type);
570 : }
571 :
572 70 : if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) {
573 0 : _gnutls_debug_log
574 : ("Cannot determine PKCS #11 key algorithm\n");
575 0 : ret = GNUTLS_E_UNKNOWN_ALGORITHM;
576 0 : goto cleanup;
577 : }
578 :
579 :
580 70 : if (pkey->pk_algorithm == GNUTLS_PK_RSA) { /* determine whether it can do rsa-pss */
581 61 : ck_bool_t tval = 0;
582 :
583 61 : a[0].type = CKA_MODULUS;
584 61 : a[0].value = NULL;
585 61 : a[0].value_len = 0;
586 61 : a[1].type = CKA_SIGN;
587 61 : a[1].value = &tval;
588 61 : a[1].value_len = sizeof(tval);
589 61 : if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 2)
590 : == CKR_OK) {
591 52 : pkey->bits = a[0].value_len*8;
592 : }
593 :
594 61 : ret = gnutls_pkcs11_token_check_mechanism(url, CKM_RSA_PKCS_PSS, NULL, 0, 0);
595 61 : if (ret != 0 && tval) {
596 49 : pkey->rsa_pss_ok = 1;
597 : } else {
598 61 : _gnutls_debug_log("Detected incompatible with TLS1.3 RSA key! (%s)\n", url);
599 : }
600 : }
601 :
602 70 : a[0].type = CKA_ALWAYS_AUTHENTICATE;
603 70 : a[0].value = &reauth;
604 70 : a[0].value_len = sizeof(reauth);
605 :
606 70 : if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1)
607 : == CKR_OK) {
608 69 : pkey->reauth = reauth;
609 : }
610 :
611 72 : ret = 0;
612 :
613 : return ret;
614 :
615 0 : cleanup:
616 0 : if (pkey->uinfo != NULL) {
617 0 : p11_kit_uri_free(pkey->uinfo);
618 0 : pkey->uinfo = NULL;
619 : }
620 0 : gnutls_free(pkey->url);
621 :
622 0 : 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
639 0 : _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 0 : ck_rv_t rv;
645 0 : int ret;
646 0 : struct ck_mechanism mech;
647 0 : unsigned long siglen;
648 0 : unsigned req_login = 0;
649 0 : unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
650 :
651 0 : PKCS11_CHECK_INIT_PRIVKEY(key);
652 :
653 0 : if (key->pk_algorithm != GNUTLS_PK_RSA)
654 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
655 :
656 0 : mech.mechanism = CKM_RSA_PKCS;
657 0 : mech.parameter = NULL;
658 0 : mech.parameter_len = 0;
659 :
660 0 : ret = gnutls_mutex_lock(&key->mutex);
661 0 : if (ret != 0)
662 0 : return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
663 :
664 : /* Initialize signing operation; using the private key discovered
665 : * earlier. */
666 0 : REPEAT_ON_INVALID_HANDLE(rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks, &mech, key->ref));
667 0 : if (rv != CKR_OK) {
668 0 : gnutls_assert();
669 0 : ret = pkcs11_rv_to_err(rv);
670 0 : goto cleanup;
671 : }
672 :
673 0 : retry_login:
674 0 : if (key->reauth || req_login) {
675 0 : if (req_login)
676 0 : login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
677 0 : ret =
678 0 : pkcs11_login(&key->sinfo, &key->pin,
679 : key->uinfo, login_flags);
680 0 : if (ret < 0) {
681 0 : gnutls_assert();
682 0 : _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 0 : rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
689 0 : ciphertext->size, NULL, &siglen);
690 0 : if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
691 0 : req_login = 1;
692 0 : goto retry_login;
693 : }
694 :
695 0 : if (rv != CKR_OK) {
696 0 : gnutls_assert();
697 0 : ret = pkcs11_rv_to_err(rv);
698 0 : goto cleanup;
699 : }
700 :
701 0 : plaintext->data = gnutls_malloc(siglen);
702 0 : plaintext->size = siglen;
703 :
704 0 : rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks, ciphertext->data,
705 0 : ciphertext->size, plaintext->data, &siglen);
706 0 : if (rv != CKR_OK) {
707 0 : gnutls_free(plaintext->data);
708 0 : gnutls_assert();
709 0 : ret = pkcs11_rv_to_err(rv);
710 0 : goto cleanup;
711 : }
712 :
713 0 : plaintext->size = siglen;
714 :
715 0 : ret = 0;
716 :
717 0 : cleanup:
718 0 : gnutls_mutex_unlock(&key->mutex);
719 0 : 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
743 2 : _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 2 : ck_rv_t rv;
750 2 : int ret;
751 2 : struct ck_mechanism mech;
752 2 : unsigned long siglen = ciphertext->size;
753 2 : unsigned req_login = 0;
754 2 : unsigned login_flags = SESSION_LOGIN|SESSION_CONTEXT_SPECIFIC;
755 2 : unsigned char *buffer;
756 2 : volatile unsigned char value;
757 2 : unsigned char mask;
758 :
759 2 : PKCS11_CHECK_INIT_PRIVKEY(key);
760 :
761 2 : if (key->pk_algorithm != GNUTLS_PK_RSA)
762 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
763 :
764 2 : mech.mechanism = CKM_RSA_PKCS;
765 2 : mech.parameter = NULL;
766 2 : mech.parameter_len = 0;
767 :
768 2 : ret = gnutls_mutex_lock(&key->mutex);
769 2 : if (ret != 0)
770 0 : return gnutls_assert_val(GNUTLS_E_LOCKING_ERROR);
771 :
772 2 : buffer = gnutls_malloc(siglen);
773 2 : if (!buffer) {
774 0 : gnutls_assert();
775 0 : return GNUTLS_E_MEMORY_ERROR;
776 : }
777 :
778 : /* Initialize signing operation; using the private key discovered
779 : * earlier. */
780 2 : REPEAT_ON_INVALID_HANDLE(
781 : rv = pkcs11_decrypt_init(key->sinfo.module, key->sinfo.pks,
782 : &mech, key->ref)
783 2 : );
784 2 : if (rv != CKR_OK) {
785 0 : gnutls_assert();
786 0 : ret = pkcs11_rv_to_err(rv);
787 0 : goto cleanup;
788 : }
789 :
790 2 : retry_login:
791 2 : if (key->reauth || req_login) {
792 0 : if (req_login)
793 0 : login_flags = SESSION_FORCE_LOGIN|SESSION_LOGIN;
794 0 : ret =
795 0 : pkcs11_login(&key->sinfo, &key->pin,
796 : key->uinfo, login_flags);
797 0 : if (ret < 0) {
798 0 : gnutls_assert();
799 0 : _gnutls_debug_log("PKCS #11 login failed, trying operation anyway\n");
800 : /* let's try the operation anyway */
801 : }
802 : }
803 :
804 2 : ret = 0;
805 2 : siglen = ciphertext->size;
806 2 : rv = pkcs11_decrypt(key->sinfo.module, key->sinfo.pks,
807 : ciphertext->data, ciphertext->size,
808 : buffer, &siglen);
809 2 : if (unlikely(rv == CKR_USER_NOT_LOGGED_IN && req_login == 0)) {
810 0 : req_login = 1;
811 0 : goto retry_login;
812 : }
813 :
814 : /* NOTE: These branches are not side-channel silent */
815 2 : if (rv != CKR_OK) {
816 0 : gnutls_assert();
817 0 : ret = pkcs11_rv_to_err(rv);
818 2 : } else if (siglen != plaintext_size) {
819 0 : 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 2 : mask = ((uint32_t)ret >> 31) - 1U;
826 98 : for (size_t i = 0; i < plaintext_size; i++) {
827 96 : value = (buffer[i] & mask) + (plaintext[i] & ~mask);
828 96 : plaintext[i] = value;
829 : }
830 :
831 2 : cleanup:
832 2 : gnutls_mutex_unlock(&key->mutex);
833 2 : gnutls_free(buffer);
834 2 : 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
849 0 : gnutls_pkcs11_privkey_export_url(gnutls_pkcs11_privkey_t key,
850 : gnutls_pkcs11_url_type_t detailed,
851 : char **url)
852 : {
853 0 : int ret;
854 :
855 0 : ret = pkcs11_info_to_url(key->uinfo, detailed, url);
856 0 : if (ret < 0) {
857 0 : gnutls_assert();
858 0 : 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
936 1 : _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 1 : struct ck_mechanism mech = { CKM_DSA_PARAMETER_GEN };
941 1 : struct ck_attribute attr = { CKA_PRIME_BITS, &bits, sizeof(bits) };
942 1 : ck_object_handle_t key;
943 1 : ck_rv_t rv;
944 :
945 : /* Generate DSA parameters from prime length. */
946 :
947 1 : rv = pkcs11_generate_key(module, session, &mech, &attr, 1, &key);
948 1 : if (rv != CKR_OK) {
949 0 : gnutls_assert();
950 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
951 0 : return pkcs11_rv_to_err(rv);
952 : }
953 :
954 : /* Retrieve generated parameters to be used with the new key pair. */
955 :
956 1 : a[*a_val + 0].type = CKA_PRIME;
957 1 : a[*a_val + 0].value = params->prime;
958 1 : a[*a_val + 0].value_len = sizeof(params->prime);
959 :
960 1 : a[*a_val + 1].type = CKA_SUBPRIME;
961 1 : a[*a_val + 1].value = params->subprime;
962 1 : a[*a_val + 1].value_len = sizeof(params->subprime);
963 :
964 1 : a[*a_val + 2].type = CKA_BASE;
965 1 : a[*a_val + 2].value = params->generator;
966 1 : a[*a_val + 2].value_len = sizeof(params->generator);
967 :
968 1 : rv = pkcs11_get_attribute_value(module, session, key, &a[*a_val], 3);
969 1 : if (rv != CKR_OK) {
970 0 : gnutls_assert();
971 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
972 0 : return pkcs11_rv_to_err(rv);
973 : }
974 :
975 1 : *a_val += 3;
976 :
977 1 : 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
1011 9 : 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 9 : int ret;
1020 9 : const ck_bool_t tval = 1;
1021 9 : const ck_bool_t fval = 0;
1022 9 : struct pkcs11_session_info sinfo;
1023 9 : struct p11_kit_uri *info = NULL;
1024 9 : ck_rv_t rv;
1025 9 : struct ck_attribute a[22], p[22];
1026 9 : ck_object_handle_t pub_ctx, priv_ctx;
1027 9 : unsigned long _bits = bits;
1028 9 : int a_val, p_val;
1029 9 : struct ck_mechanism mech;
1030 9 : gnutls_pubkey_t pkey = NULL;
1031 9 : gnutls_pkcs11_obj_t obj = NULL;
1032 9 : gnutls_datum_t der = {NULL, 0};
1033 9 : ck_key_type_t key_type;
1034 9 : uint8_t id[20];
1035 9 : struct dsa_params dsa_params;
1036 :
1037 9 : PKCS11_CHECK_INIT;
1038 9 : FIX_KEY_USAGE(pk, key_usage);
1039 :
1040 9 : memset(&sinfo, 0, sizeof(sinfo));
1041 :
1042 9 : ret = pkcs11_url_to_info(url, &info, 0);
1043 9 : if (ret < 0) {
1044 0 : gnutls_assert();
1045 0 : return ret;
1046 : }
1047 :
1048 9 : ret =
1049 9 : pkcs11_open_session(&sinfo, NULL, info,
1050 : SESSION_WRITE |
1051 9 : pkcs11_obj_flags_to_int(flags));
1052 9 : p11_kit_uri_free(info);
1053 :
1054 9 : if (ret < 0) {
1055 0 : gnutls_assert();
1056 0 : goto cleanup;
1057 : }
1058 :
1059 : /* a holds the public key template
1060 : * and p the private key */
1061 9 : a_val = p_val = 0;
1062 9 : mech.parameter = NULL;
1063 9 : mech.parameter_len = 0;
1064 9 : mech.mechanism = pk_to_genmech(pk, &key_type);
1065 :
1066 9 : if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_NO_STORE_PUBKEY)) {
1067 9 : a[a_val].type = CKA_TOKEN;
1068 9 : a[a_val].value = (void *) &tval;
1069 9 : a[a_val].value_len = sizeof(tval);
1070 9 : a_val++;
1071 :
1072 9 : a[a_val].type = CKA_PRIVATE;
1073 9 : a[a_val].value = (void *) &fval;
1074 9 : a[a_val].value_len = sizeof(fval);
1075 9 : a_val++;
1076 : }
1077 :
1078 9 : a[a_val].type = CKA_ID;
1079 9 : if (cid == NULL || cid->size == 0) {
1080 8 : ret = gnutls_rnd(GNUTLS_RND_NONCE, id, sizeof(id));
1081 8 : if (ret < 0) {
1082 0 : gnutls_assert();
1083 0 : goto cleanup;
1084 : }
1085 :
1086 8 : a[a_val].value = (void *) id;
1087 8 : a[a_val].value_len = sizeof(id);
1088 : } else {
1089 1 : a[a_val].value = (void *) cid->data;
1090 1 : a[a_val].value_len = cid->size;
1091 : }
1092 :
1093 9 : p[p_val].type = CKA_ID;
1094 9 : p[p_val].value = a[a_val].value;
1095 9 : p[p_val].value_len = a[a_val].value_len;
1096 9 : a_val++;
1097 9 : p_val++;
1098 :
1099 9 : switch (pk) {
1100 5 : case GNUTLS_PK_RSA:
1101 5 : p[p_val].type = CKA_DECRYPT;
1102 5 : if (key_usage & (GNUTLS_KEY_DECIPHER_ONLY|GNUTLS_KEY_ENCIPHER_ONLY)) {
1103 5 : p[p_val].value = (void *) &tval;
1104 5 : p[p_val].value_len = sizeof(tval);
1105 : } else {
1106 0 : p[p_val].value = (void *) &fval;
1107 0 : p[p_val].value_len = sizeof(fval);
1108 : }
1109 5 : p_val++;
1110 :
1111 5 : p[p_val].type = CKA_SIGN;
1112 5 : if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
1113 5 : p[p_val].value = (void *) &tval;
1114 5 : p[p_val].value_len = sizeof(tval);
1115 : } else {
1116 0 : p[p_val].value = (void *) &fval;
1117 0 : p[p_val].value_len = sizeof(fval);
1118 : }
1119 5 : p_val++;
1120 :
1121 5 : a[a_val].type = CKA_ENCRYPT;
1122 5 : a[a_val].value = (void *) &tval;
1123 5 : a[a_val].value_len = sizeof(tval);
1124 5 : a_val++;
1125 :
1126 5 : a[a_val].type = CKA_VERIFY;
1127 5 : a[a_val].value = (void *) &tval;
1128 5 : a[a_val].value_len = sizeof(tval);
1129 5 : a_val++;
1130 :
1131 5 : a[a_val].type = CKA_MODULUS_BITS;
1132 5 : a[a_val].value = &_bits;
1133 5 : a[a_val].value_len = sizeof(_bits);
1134 5 : a_val++;
1135 :
1136 5 : a[a_val].type = CKA_PUBLIC_EXPONENT;
1137 5 : a[a_val].value = (char*)def_rsa_pub_exp;
1138 5 : a[a_val].value_len = sizeof(def_rsa_pub_exp);
1139 5 : a_val++;
1140 :
1141 5 : break;
1142 1 : case GNUTLS_PK_DSA:
1143 1 : p[p_val].type = CKA_SIGN;
1144 1 : if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
1145 1 : p[p_val].value = (void *) &tval;
1146 1 : p[p_val].value_len = sizeof(tval);
1147 : } else {
1148 0 : p[p_val].value = (void *) &fval;
1149 0 : p[p_val].value_len = sizeof(fval);
1150 : }
1151 1 : p_val++;
1152 :
1153 1 : a[a_val].type = CKA_VERIFY;
1154 1 : a[a_val].value = (void *) &tval;
1155 1 : a[a_val].value_len = sizeof(tval);
1156 1 : a_val++;
1157 :
1158 1 : ret = _dsa_params_generate(sinfo.module, sinfo.pks, _bits,
1159 : &dsa_params, a, &a_val);
1160 1 : if (ret < 0) {
1161 0 : goto cleanup;
1162 : }
1163 :
1164 : break;
1165 3 : case GNUTLS_PK_ECDSA:
1166 3 : p[p_val].type = CKA_SIGN;
1167 3 : if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
1168 3 : p[p_val].value = (void *) &tval;
1169 3 : p[p_val].value_len = sizeof(tval);
1170 : } else {
1171 0 : p[p_val].value = (void *) &fval;
1172 0 : p[p_val].value_len = sizeof(fval);
1173 : }
1174 3 : p_val++;
1175 :
1176 3 : a[a_val].type = CKA_VERIFY;
1177 3 : a[a_val].value = (void *) &tval;
1178 3 : a[a_val].value_len = sizeof(tval);
1179 3 : a_val++;
1180 :
1181 3 : if (GNUTLS_BITS_ARE_CURVE(bits)) {
1182 0 : bits = GNUTLS_BITS_TO_CURVE(bits);
1183 : } else {
1184 3 : bits = _gnutls_ecc_bits_to_curve(pk, bits);
1185 : }
1186 :
1187 3 : ret = _gnutls_x509_write_ecc_params(bits, &der);
1188 3 : if (ret < 0) {
1189 0 : gnutls_assert();
1190 0 : goto cleanup;
1191 : }
1192 :
1193 3 : a[a_val].type = CKA_EC_PARAMS;
1194 3 : a[a_val].value = der.data;
1195 3 : a[a_val].value_len = der.size;
1196 3 : a_val++;
1197 :
1198 3 : break;
1199 0 : case GNUTLS_PK_EDDSA_ED25519:
1200 0 : p[p_val].type = CKA_SIGN;
1201 0 : p[p_val].value = (void *) &tval;
1202 0 : p[p_val].value_len = sizeof(tval);
1203 0 : p_val++;
1204 :
1205 0 : a[a_val].type = CKA_VERIFY;
1206 0 : a[a_val].value = (void *) &tval;
1207 0 : a[a_val].value_len = sizeof(tval);
1208 0 : a_val++;
1209 :
1210 0 : ret = _gnutls_x509_write_ecc_params(GNUTLS_ECC_CURVE_ED25519, &der);
1211 0 : if (ret < 0) {
1212 0 : gnutls_assert();
1213 0 : goto cleanup;
1214 : }
1215 :
1216 0 : a[a_val].type = CKA_EC_PARAMS;
1217 0 : a[a_val].value = der.data;
1218 0 : a[a_val].value_len = der.size;
1219 0 : a_val++;
1220 0 : break;
1221 : default:
1222 0 : ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1223 0 : goto cleanup;
1224 : }
1225 :
1226 : /*
1227 : * on request, add the CKA_WRAP/CKA_UNWRAP key attribute
1228 : */
1229 9 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_KEY_WRAP) {
1230 0 : p[p_val].type = CKA_UNWRAP;
1231 0 : p[p_val].value = (void*)&tval;
1232 0 : p[p_val].value_len = sizeof(tval);
1233 0 : p_val++;
1234 0 : a[a_val].type = CKA_WRAP;
1235 0 : a[a_val].value = (void*)&tval;
1236 0 : a[a_val].value_len = sizeof(tval);
1237 0 : a_val++;
1238 : }
1239 :
1240 : /* a private key is set always as private unless
1241 : * requested otherwise
1242 : */
1243 9 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
1244 0 : p[p_val].type = CKA_PRIVATE;
1245 0 : p[p_val].value = (void *) &fval;
1246 0 : p[p_val].value_len = sizeof(fval);
1247 0 : p_val++;
1248 : } else {
1249 9 : p[p_val].type = CKA_PRIVATE;
1250 9 : p[p_val].value = (void *) &tval;
1251 9 : p[p_val].value_len = sizeof(tval);
1252 9 : p_val++;
1253 : }
1254 :
1255 9 : p[p_val].type = CKA_TOKEN;
1256 9 : p[p_val].value = (void *) &tval;
1257 9 : p[p_val].value_len = sizeof(tval);
1258 9 : p_val++;
1259 :
1260 9 : if (label) {
1261 9 : p[p_val].type = CKA_LABEL;
1262 9 : p[p_val].value = (void *) label;
1263 9 : p[p_val].value_len = strlen(label);
1264 9 : p_val++;
1265 :
1266 9 : a[a_val].type = CKA_LABEL;
1267 9 : a[a_val].value = (void *) label;
1268 9 : a[a_val].value_len = strlen(label);
1269 9 : a_val++;
1270 : }
1271 :
1272 9 : if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) {
1273 8 : p[p_val].type = CKA_SENSITIVE;
1274 8 : p[p_val].value = (void *) &tval;
1275 8 : p[p_val].value_len = sizeof(tval);
1276 8 : p_val++;
1277 : } else {
1278 1 : p[p_val].type = CKA_SENSITIVE;
1279 1 : p[p_val].value = (void *) &fval;
1280 1 : p[p_val].value_len = sizeof(fval);
1281 1 : p_val++;
1282 : }
1283 :
1284 9 : rv = pkcs11_generate_key_pair(sinfo.module, sinfo.pks, &mech, a,
1285 : a_val, p, p_val, &pub_ctx, &priv_ctx);
1286 9 : if (rv != CKR_OK) {
1287 0 : gnutls_assert();
1288 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
1289 0 : ret = pkcs11_rv_to_err(rv);
1290 0 : goto cleanup;
1291 : }
1292 :
1293 : /* extract the public key */
1294 9 : if (pubkey) {
1295 :
1296 9 : ret = gnutls_pubkey_init(&pkey);
1297 9 : if (ret < 0) {
1298 0 : gnutls_assert();
1299 0 : goto cleanup;
1300 : }
1301 :
1302 9 : ret = gnutls_pkcs11_obj_init(&obj);
1303 9 : if (ret < 0) {
1304 0 : gnutls_assert();
1305 0 : goto cleanup;
1306 : }
1307 :
1308 9 : obj->pk_algorithm = pk;
1309 9 : obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1310 9 : ret =
1311 9 : pkcs11_read_pubkey(sinfo.module, sinfo.pks, pub_ctx,
1312 : key_type, obj);
1313 9 : if (ret < 0) {
1314 0 : gnutls_assert();
1315 0 : goto cleanup;
1316 : }
1317 :
1318 9 : ret = gnutls_pubkey_import_pkcs11(pkey, obj, 0);
1319 9 : if (ret < 0) {
1320 0 : gnutls_assert();
1321 0 : goto cleanup;
1322 : }
1323 :
1324 9 : ret = gnutls_pubkey_export2(pkey, fmt, pubkey);
1325 9 : if (ret < 0) {
1326 0 : gnutls_assert();
1327 0 : goto cleanup;
1328 : }
1329 : }
1330 :
1331 9 : cleanup:
1332 9 : if (obj != NULL)
1333 9 : gnutls_pkcs11_obj_deinit(obj);
1334 9 : if (pkey != NULL)
1335 9 : gnutls_pubkey_deinit(pkey);
1336 :
1337 9 : if (sinfo.pks != 0)
1338 9 : pkcs11_close_session(&sinfo);
1339 9 : gnutls_free(der.data);
1340 :
1341 9 : 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 : */
1347 4 : static int load_pubkey_obj(gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t pub)
1348 : {
1349 4 : int ret, iret;
1350 4 : gnutls_x509_crt_t crt;
1351 :
1352 4 : ret = gnutls_pubkey_import_url(pub, pkey->url, pkey->flags);
1353 4 : if (ret >= 0) {
1354 : return ret;
1355 : }
1356 2 : iret = ret;
1357 :
1358 : /* else try certificate */
1359 2 : ret = gnutls_x509_crt_init(&crt);
1360 2 : if (ret < 0) {
1361 0 : gnutls_assert();
1362 0 : return ret;
1363 : }
1364 :
1365 2 : gnutls_x509_crt_set_pin_function(crt, pkey->pin.cb, pkey->pin.data);
1366 :
1367 2 : ret = gnutls_x509_crt_import_url(crt, pkey->url, pkey->flags);
1368 2 : if (ret < 0) {
1369 1 : ret = iret;
1370 1 : goto cleanup;
1371 : }
1372 :
1373 1 : ret = gnutls_pubkey_import_x509(pub, crt, 0);
1374 :
1375 2 : cleanup:
1376 2 : gnutls_x509_crt_deinit(crt);
1377 2 : return ret;
1378 : }
1379 :
1380 : int
1381 27 : _pkcs11_privkey_get_pubkey (gnutls_pkcs11_privkey_t pkey, gnutls_pubkey_t *pub, unsigned flags)
1382 : {
1383 27 : gnutls_pubkey_t pubkey = NULL;
1384 27 : gnutls_pkcs11_obj_t obj = NULL;
1385 27 : ck_key_type_t key_type;
1386 27 : int ret;
1387 :
1388 27 : PKCS11_CHECK_INIT_PRIVKEY(pkey);
1389 :
1390 27 : if (!pkey) {
1391 0 : gnutls_assert();
1392 0 : return GNUTLS_E_INVALID_REQUEST;
1393 : }
1394 :
1395 27 : ret = gnutls_pubkey_init(&pubkey);
1396 27 : if (ret < 0) {
1397 0 : gnutls_assert();
1398 0 : goto cleanup;
1399 : }
1400 :
1401 27 : ret = gnutls_pkcs11_obj_init(&obj);
1402 27 : if (ret < 0) {
1403 0 : gnutls_assert();
1404 0 : goto cleanup;
1405 : }
1406 :
1407 27 : obj->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm(pkey, 0);
1408 27 : obj->type = GNUTLS_PKCS11_OBJ_PUBKEY;
1409 27 : pk_to_genmech(obj->pk_algorithm, &key_type);
1410 :
1411 27 : 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 27 : if (key_type != CKK_RSA) {
1415 : /* try opening the public key object if it exists */
1416 4 : ret = load_pubkey_obj(pkey, pubkey);
1417 4 : if (ret < 0) {
1418 1 : gnutls_assert();
1419 1 : goto cleanup;
1420 : }
1421 : } else {
1422 23 : ret = pkcs11_read_pubkey(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, key_type, obj);
1423 23 : if (ret < 0) {
1424 0 : gnutls_assert();
1425 0 : goto cleanup;
1426 : }
1427 :
1428 23 : ret = gnutls_pubkey_import_pkcs11(pubkey, obj, 0);
1429 23 : if (ret < 0) {
1430 0 : gnutls_assert();
1431 0 : goto cleanup;
1432 : }
1433 : }
1434 :
1435 26 : *pub = pubkey;
1436 :
1437 26 : pubkey = NULL;
1438 26 : ret = 0;
1439 :
1440 27 : cleanup:
1441 27 : if (obj != NULL)
1442 27 : gnutls_pkcs11_obj_deinit(obj);
1443 27 : if (pubkey != NULL)
1444 1 : 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
1467 1 : 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 1 : int ret;
1473 1 : gnutls_pubkey_t pubkey = NULL;
1474 :
1475 1 : ret = _pkcs11_privkey_get_pubkey(pkey, &pubkey, flags);
1476 1 : if (ret < 0)
1477 0 : return gnutls_assert_val(ret);
1478 :
1479 1 : ret = gnutls_pubkey_export2(pubkey, fmt, data);
1480 1 : if (ret < 0) {
1481 0 : gnutls_assert();
1482 0 : goto cleanup;
1483 : }
1484 :
1485 : ret = 0;
1486 :
1487 1 : cleanup:
1488 1 : if (pubkey != NULL)
1489 1 : 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
1508 13 : gnutls_pkcs11_privkey_set_pin_function(gnutls_pkcs11_privkey_t key,
1509 : gnutls_pin_callback_t fn,
1510 : void *userdata)
1511 : {
1512 13 : key->pin.cb = fn;
1513 13 : key->pin.data = userdata;
1514 13 : }
|