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