1 /*
2  * GnuTLS PKCS#11 support
3  * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4  *
5  * Authors: Nikos Mavrogiannopoulos, Stef Walter
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>
19  */
20 
21 #include "gnutls_int.h"
22 #include <gnutls/pkcs11.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include "errors.h"
26 #include <datum.h>
27 #include <pkcs11_int.h>
28 #include "pkcs11x.h"
29 #include <x509/common.h>
30 #include "pk.h"
31 
32 static const ck_bool_t tval = 1;
33 static const ck_bool_t fval = 0;
34 
35 #define MAX_ASIZE 24
36 
mark_flags(unsigned flags,struct ck_attribute * a,unsigned * a_val,unsigned trusted)37 static void mark_flags(unsigned flags, struct ck_attribute *a, unsigned *a_val, unsigned trusted)
38 {
39 	static const unsigned long category = 2;
40 
41 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
42 		a[*a_val].type = CKA_CERTIFICATE_CATEGORY;
43 		a[*a_val].value = (void *) &category;
44 		a[*a_val].value_len = sizeof(category);
45 		(*a_val)++;
46 	}
47 
48 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_DISTRUSTED) {
49 		if (trusted) {
50 			a[*a_val].type = CKA_X_DISTRUSTED;
51 			a[*a_val].value = (void *) &tval;
52 			a[*a_val].value_len = sizeof(tval);
53 			(*a_val)++;
54 		} else {
55 			_gnutls_debug_log("p11: ignoring the distrusted flag as it is not valid on non-p11-kit-trust modules\n");
56 		}
57 	}
58 
59 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
60 		a[*a_val].type = CKA_TRUSTED;
61 		a[*a_val].value = (void *) &tval;
62 		a[*a_val].value_len = sizeof(tval);
63 		(*a_val)++;
64 
65 		a[*a_val].type = CKA_PRIVATE;
66 		a[*a_val].value = (void *) &fval;
67 		a[*a_val].value_len = sizeof(fval);
68 		(*a_val)++;
69 	} else {
70 		if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE) {
71 			a[*a_val].type = CKA_PRIVATE;
72 			a[*a_val].value = (void *) &tval;
73 			a[*a_val].value_len = sizeof(tval);
74 			(*a_val)++;
75 		} else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
76 			a[*a_val].type = CKA_PRIVATE;
77 			a[*a_val].value = (void *) &fval;
78 			a[*a_val].value_len = sizeof(fval);
79 			(*a_val)++;
80 		}
81 	}
82 }
83 
84 /**
85  * gnutls_pkcs11_copy_x509_crt2:
86  * @token_url: A PKCS #11 URL specifying a token
87  * @crt: The certificate to copy
88  * @label: The name to be used for the stored data
89  * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key
90  * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
91  *
92  * This function will copy a certificate into a PKCS #11 token specified by
93  * a URL. Valid flags to mark the certificate: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED,
94  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA,
95  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH.
96  *
97  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
98  *   negative error value.
99  *
100  * Since: 3.4.0
101  **/
102 int
gnutls_pkcs11_copy_x509_crt2(const char * token_url,gnutls_x509_crt_t crt,const char * label,const gnutls_datum_t * cid,unsigned int flags)103 gnutls_pkcs11_copy_x509_crt2(const char *token_url,
104 			    gnutls_x509_crt_t crt, const char *label,
105 			    const gnutls_datum_t *cid,
106 			    unsigned int flags)
107 {
108 	int ret;
109 	struct p11_kit_uri *info = NULL;
110 	ck_rv_t rv;
111 	size_t der_size, id_size, serial_size;
112 	gnutls_datum_t serial_der = {NULL, 0};
113 	uint8_t *der = NULL;
114 	uint8_t serial[128];
115 	uint8_t id[20];
116 	struct ck_attribute a[MAX_ASIZE];
117 	ck_object_class_t class = CKO_CERTIFICATE;
118 	ck_certificate_type_t type = CKC_X_509;
119 	ck_object_handle_t ctx;
120 	unsigned a_val;
121 	struct pkcs11_session_info sinfo;
122 
123 	PKCS11_CHECK_INIT;
124 
125 	ret = pkcs11_url_to_info(token_url, &info, 0);
126 	if (ret < 0) {
127 		gnutls_assert();
128 		return ret;
129 	}
130 
131 	ret =
132 	    pkcs11_open_session(&sinfo, NULL, info,
133 				SESSION_WRITE |
134 				pkcs11_obj_flags_to_int(flags));
135 	p11_kit_uri_free(info);
136 
137 	if (ret < 0) {
138 		gnutls_assert();
139 		return ret;
140 	}
141 
142 	der_size = 0;
143 	ret =
144 	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL,
145 				   &der_size);
146 	if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
147 		gnutls_assert();
148 		goto cleanup;
149 	}
150 
151 	der = gnutls_malloc(der_size);
152 	if (der == NULL) {
153 		gnutls_assert();
154 		ret = GNUTLS_E_MEMORY_ERROR;
155 		goto cleanup;
156 	}
157 
158 	ret =
159 	    gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der,
160 				   &der_size);
161 	if (ret < 0) {
162 		gnutls_assert();
163 		goto cleanup;
164 	}
165 
166 	a[0].type = CKA_CLASS;
167 	a[0].value = &class;
168 	a[0].value_len = sizeof(class);
169 
170 	a[1].type = CKA_ID;
171 	if (cid == NULL || cid->size == 0) {
172 		id_size = sizeof(id);
173 		ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL);
174 		if (ret < 0) {
175 			id_size = sizeof(id);
176 			ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
177 			if (ret < 0) {
178 			  gnutls_assert();
179 			  goto cleanup;
180 			}
181 		}
182 
183 		a[1].value = id;
184 		a[1].value_len = id_size;
185 	} else {
186 		a[1].value = cid->data;
187 		a[1].value_len = cid->size;
188 	}
189 
190 	/* we do not use the key usage flags; these are apparent from
191 	 * the certificate itself. */
192 	a[2].type = CKA_VALUE;
193 	a[2].value = der;
194 	a[2].value_len = der_size;
195 	a[3].type = CKA_TOKEN;
196 	a[3].value = (void *) &tval;
197 	a[3].value_len = sizeof(tval);
198 	a[4].type = CKA_CERTIFICATE_TYPE;
199 	a[4].value = &type;
200 	a[4].value_len = sizeof(type);
201 
202 	a_val = 5;
203 
204 	a[a_val].type = CKA_SUBJECT;
205 	a[a_val].value = crt->raw_dn.data;
206 	a[a_val].value_len = crt->raw_dn.size;
207 	a_val++;
208 
209 	if (crt->raw_issuer_dn.size > 0) {
210 		a[a_val].type = CKA_ISSUER;
211 		a[a_val].value = crt->raw_issuer_dn.data;
212 		a[a_val].value_len = crt->raw_issuer_dn.size;
213 		a_val++;
214 	}
215 
216 	serial_size = sizeof(serial);
217 	if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) {
218 		ret = _gnutls_x509_ext_gen_number(serial, serial_size, &serial_der);
219 		if (ret >= 0) {
220 			a[a_val].type = CKA_SERIAL_NUMBER;
221 			a[a_val].value = (void *) serial_der.data;
222 			a[a_val].value_len = serial_der.size;
223 			a_val++;
224 		}
225 	}
226 
227 	if (label) {
228 		a[a_val].type = CKA_LABEL;
229 		a[a_val].value = (void *) label;
230 		a[a_val].value_len = strlen(label);
231 		a_val++;
232 	}
233 
234 	mark_flags(flags, a, &a_val, sinfo.trusted);
235 
236 	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
237 	if (rv != CKR_OK) {
238 		gnutls_assert();
239 		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
240 		ret = pkcs11_rv_to_err(rv);
241 		goto cleanup;
242 	}
243 
244 	/* generated!
245 	 */
246 
247 	ret = 0;
248 
249       cleanup:
250 	gnutls_free(der);
251 	gnutls_free(serial_der.data);
252 	pkcs11_close_session(&sinfo);
253 	return ret;
254 
255 }
256 
clean_pubkey(struct ck_attribute * a,unsigned a_val)257 static void clean_pubkey(struct ck_attribute *a, unsigned a_val)
258 {
259 	unsigned i;
260 
261 	for (i=0;i<a_val;i++) {
262 		switch(a[i].type) {
263 			case CKA_MODULUS:
264 			case CKA_PUBLIC_EXPONENT:
265 			case CKA_PRIME:
266 			case CKA_SUBPRIME:
267 			case CKA_VALUE:
268 			case CKA_BASE:
269 			case CKA_EC_PARAMS:
270 			case CKA_EC_POINT:
271 				gnutls_free(a[i].value);
272 				break;
273 		}
274 	}
275 }
276 
add_pubkey(gnutls_pubkey_t pubkey,struct ck_attribute * a,unsigned * a_val)277 static int add_pubkey(gnutls_pubkey_t pubkey, struct ck_attribute *a, unsigned *a_val)
278 {
279 	gnutls_pk_algorithm_t pk;
280 	int ret;
281 
282 	pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
283 
284 	switch (pk) {
285 	case GNUTLS_PK_RSA_PSS:
286 	case GNUTLS_PK_RSA: {
287 		gnutls_datum_t m, e;
288 
289 		/* PKCS#11 defines integers as unsigned having most significant byte
290 		 * first, e.g., 32768 = 0x80 0x00. This is interpreted literraly by
291 		 * some HSMs which do not accept an integer with a leading zero */
292 		ret = gnutls_pubkey_export_rsa_raw2(pubkey, &m, &e, GNUTLS_EXPORT_FLAG_NO_LZ);
293 		if (ret < 0) {
294 			gnutls_assert();
295 			return ret;
296 		}
297 
298 
299 		a[*a_val].type = CKA_MODULUS;
300 		a[*a_val].value = m.data;
301 		a[*a_val].value_len = m.size;
302 		(*a_val)++;
303 
304 		a[*a_val].type = CKA_PUBLIC_EXPONENT;
305 		a[*a_val].value = e.data;
306 		a[*a_val].value_len = e.size;
307 		(*a_val)++;
308 		break;
309 	}
310 	case GNUTLS_PK_DSA: {
311 		gnutls_datum_t p, q, g, y;
312 
313 		ret = gnutls_pubkey_export_dsa_raw2(pubkey, &p, &q, &g, &y, GNUTLS_EXPORT_FLAG_NO_LZ);
314 		if (ret < 0) {
315 			gnutls_assert();
316 			return ret;
317 		}
318 
319 		a[*a_val].type = CKA_PRIME;
320 		a[*a_val].value = p.data;
321 		a[*a_val].value_len = p.size;
322 		(*a_val)++;
323 
324 		a[*a_val].type = CKA_SUBPRIME;
325 		a[*a_val].value = q.data;
326 		a[*a_val].value_len = q.size;
327 		(*a_val)++;
328 
329 		a[*a_val].type = CKA_BASE;
330 		a[*a_val].value = g.data;
331 		a[*a_val].value_len = g.size;
332 		(*a_val)++;
333 
334 		a[*a_val].type = CKA_VALUE;
335 		a[*a_val].value = y.data;
336 		a[*a_val].value_len = y.size;
337 		(*a_val)++;
338 		break;
339 	}
340 	case GNUTLS_PK_EC: {
341 		gnutls_datum_t params, point;
342 
343 		ret = gnutls_pubkey_export_ecc_x962(pubkey, &params, &point);
344 		if (ret < 0) {
345 			gnutls_assert();
346 			return ret;
347 		}
348 
349 		a[*a_val].type = CKA_EC_PARAMS;
350 		a[*a_val].value = params.data;
351 		a[*a_val].value_len = params.size;
352 		(*a_val)++;
353 
354 		a[*a_val].type = CKA_EC_POINT;
355 		a[*a_val].value = point.data;
356 		a[*a_val].value_len = point.size;
357 		(*a_val)++;
358 		break;
359 	}
360 	case GNUTLS_PK_EDDSA_ED25519: {
361 		gnutls_datum_t params, ecpoint;
362 
363 		ret =
364 		    _gnutls_x509_write_ecc_params(pubkey->params.curve,
365 						  &params);
366 		if (ret < 0) {
367 			gnutls_assert();
368 			return ret;
369 		}
370 
371 		a[*a_val].type = CKA_EC_PARAMS;
372 		a[*a_val].value = params.data;
373 		a[*a_val].value_len = params.size;
374 		(*a_val)++;
375 
376 		ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
377 						 pubkey->params.raw_pub.data,
378 						 pubkey->params.raw_pub.size,
379 						 &ecpoint);
380 		if (ret < 0) {
381 			gnutls_assert();
382 			return ret;
383 		}
384 
385 		a[*a_val].type = CKA_EC_POINT;
386 		a[*a_val].value = ecpoint.data;
387 		a[*a_val].value_len = ecpoint.size;
388 		(*a_val)++;
389 		break;
390 	}
391 
392 	default:
393 		_gnutls_debug_log("requested writing public key of unsupported type %u\n", (unsigned)pk);
394 		return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
395 	}
396 
397 	return 0;
398 }
399 
400 /**
401  * gnutls_pkcs11_copy_pubkey:
402  * @token_url: A PKCS #11 URL specifying a token
403  * @pubkey: The public key to copy
404  * @label: The name to be used for the stored data
405  * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key
406  * @key_usage: One of GNUTLS_KEY_*
407  * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
408  *
409  * This function will copy a public key object into a PKCS #11 token specified by
410  * a URL. Valid flags to mark the key: %GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED,
411  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE, %GNUTLS_PKCS11_OBJ_FLAG_MARK_CA,
412  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH.
413  *
414  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
415  *   negative error value.
416  *
417  * Since: 3.4.6
418  **/
419 int
gnutls_pkcs11_copy_pubkey(const char * token_url,gnutls_pubkey_t pubkey,const char * label,const gnutls_datum_t * cid,unsigned int key_usage,unsigned int flags)420 gnutls_pkcs11_copy_pubkey(const char *token_url,
421 			  gnutls_pubkey_t pubkey, const char *label,
422 			  const gnutls_datum_t *cid,
423 			  unsigned int key_usage, unsigned int flags)
424 {
425 	int ret;
426 	struct p11_kit_uri *info = NULL;
427 	ck_rv_t rv;
428 	size_t id_size;
429 	uint8_t id[20];
430 	struct ck_attribute a[MAX_ASIZE];
431 	gnutls_pk_algorithm_t pk;
432 	ck_object_class_t class = CKO_PUBLIC_KEY;
433 	ck_object_handle_t ctx;
434 	unsigned a_val;
435 	ck_key_type_t type;
436 	struct pkcs11_session_info sinfo;
437 
438 	PKCS11_CHECK_INIT;
439 
440 	ret = pkcs11_url_to_info(token_url, &info, 0);
441 	if (ret < 0) {
442 		gnutls_assert();
443 		return ret;
444 	}
445 
446 	ret =
447 	    pkcs11_open_session(&sinfo, NULL, info,
448 				SESSION_WRITE |
449 				pkcs11_obj_flags_to_int(flags));
450 	p11_kit_uri_free(info);
451 
452 	if (ret < 0) {
453 		gnutls_assert();
454 		return ret;
455 	}
456 
457 	a[0].type = CKA_CLASS;
458 	a[0].value = &class;
459 	a[0].value_len = sizeof(class);
460 
461 	a[1].type = CKA_TOKEN;
462 	a[1].value = (void *) &tval;
463 	a[1].value_len = sizeof(tval);
464 
465 	a_val = 2;
466 
467 	ret = add_pubkey(pubkey, a, &a_val);
468 	if (ret < 0) {
469 		gnutls_assert();
470 		goto cleanup;
471 	}
472 
473 	if (label) {
474 		a[a_val].type = CKA_LABEL;
475 		a[a_val].value = (void *) label;
476 		a[a_val].value_len = strlen(label);
477 		a_val++;
478 	}
479 
480 	pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
481 	type = pk_to_key_type(pk);
482 	FIX_KEY_USAGE(pk, key_usage);
483 
484 	a[a_val].type = CKA_KEY_TYPE;
485 	a[a_val].value = &type;
486 	a[a_val].value_len = sizeof(type);
487 	a_val++;
488 
489 	a[a_val].type = CKA_ID;
490 	if (cid == NULL || cid->size == 0) {
491 		id_size = sizeof(id);
492 		ret = gnutls_pubkey_get_key_id(pubkey, 0, id, &id_size);
493 		if (ret < 0) {
494 			  gnutls_assert();
495 			  goto cleanup;
496 		}
497 
498 		a[a_val].value = id;
499 		a[a_val].value_len = id_size;
500 	} else {
501 		a[a_val].value = cid->data;
502 		a[a_val].value_len = cid->size;
503 	}
504 	a_val++;
505 
506 	mark_flags(flags, a, &a_val, sinfo.trusted);
507 
508 	a[a_val].type = CKA_VERIFY;
509 	if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
510 		a[a_val].value = (void*)&tval;
511 		a[a_val].value_len = sizeof(tval);
512 	} else {
513 		a[a_val].value = (void*)&fval;
514 		a[a_val].value_len = sizeof(fval);
515 	}
516 	a_val++;
517 
518 	if (pk == GNUTLS_PK_RSA) {
519 		a[a_val].type = CKA_ENCRYPT;
520 		if (key_usage & (GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_DECIPHER_ONLY)) {
521 			a[a_val].value = (void*)&tval;
522 			a[a_val].value_len = sizeof(tval);
523 		} else {
524 			a[a_val].value = (void*)&fval;
525 			a[a_val].value_len = sizeof(fval);
526 		}
527 		a_val++;
528 	}
529 
530 	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
531 	if (rv != CKR_OK) {
532 		gnutls_assert();
533 		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
534 		ret = pkcs11_rv_to_err(rv);
535 		goto cleanup;
536 	}
537 
538 	/* generated!
539 	 */
540 
541 	ret = 0;
542 
543       cleanup:
544 	clean_pubkey(a, a_val);
545 	pkcs11_close_session(&sinfo);
546 	return ret;
547 
548 }
549 
550 
551 /**
552  * gnutls_pkcs11_copy_attached_extension:
553  * @token_url: A PKCS #11 URL specifying a token
554  * @crt: An X.509 certificate object
555  * @data: the attached extension
556  * @label: A name to be used for the attached extension (may be %NULL)
557  * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
558  *
559  * This function will copy an the attached extension in @data for
560  * the certificate provided in @crt in the PKCS #11 token specified
561  * by the URL (typically a trust module). The extension must be in
562  * RFC5280 Extension format.
563  *
564  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
565  *   negative error value.
566  *
567  * Since: 3.3.8
568  **/
569 int
gnutls_pkcs11_copy_attached_extension(const char * token_url,gnutls_x509_crt_t crt,gnutls_datum_t * data,const char * label,unsigned int flags)570 gnutls_pkcs11_copy_attached_extension(const char *token_url,
571 		       gnutls_x509_crt_t crt,
572 		       gnutls_datum_t *data,
573 		       const char *label,
574 		       unsigned int flags)
575 {
576 	int ret;
577 	struct p11_kit_uri *info = NULL;
578 	ck_rv_t rv;
579 	struct ck_attribute a[MAX_ASIZE];
580 	ck_object_handle_t ctx;
581 	unsigned a_vals;
582 	struct pkcs11_session_info sinfo;
583 	ck_object_class_t class;
584 	gnutls_datum_t spki = {NULL, 0};
585 
586 	PKCS11_CHECK_INIT;
587 
588 	ret = pkcs11_url_to_info(token_url, &info, 0);
589 	if (ret < 0) {
590 		gnutls_assert();
591 		return ret;
592 	}
593 
594 	ret =
595 	    pkcs11_open_session(&sinfo, NULL, info,
596 				SESSION_WRITE |
597 				pkcs11_obj_flags_to_int(flags));
598 	p11_kit_uri_free(info);
599 
600 	if (ret < 0) {
601 		gnutls_assert();
602 		return ret;
603 	}
604 
605 	ret = x509_crt_to_raw_pubkey(crt, &spki);
606 	if (ret < 0) {
607 		gnutls_assert();
608 		goto cleanup;
609 	}
610 
611 	class = CKO_X_CERTIFICATE_EXTENSION;
612 	a_vals = 0;
613 	a[a_vals].type = CKA_CLASS;
614 	a[a_vals].value = &class;
615 	a[a_vals++].value_len = sizeof(class);
616 
617 	a[a_vals].type = CKA_PUBLIC_KEY_INFO;
618 	a[a_vals].value = spki.data;
619 	a[a_vals++].value_len = spki.size;
620 
621 	a[a_vals].type = CKA_VALUE;
622 	a[a_vals].value = data->data;
623 	a[a_vals++].value_len = data->size;
624 
625 	a[a_vals].type = CKA_TOKEN;
626 	a[a_vals].value = (void *) &tval;
627 	a[a_vals++].value_len = sizeof(tval);
628 
629 	if (label) {
630 		a[a_vals].type = CKA_LABEL;
631 		a[a_vals].value = (void *) label;
632 		a[a_vals++].value_len = strlen(label);
633 	}
634 
635 	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_vals, &ctx);
636 	if (rv != CKR_OK) {
637 		gnutls_assert();
638 		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
639 		ret = pkcs11_rv_to_err(rv);
640 		goto cleanup;
641 	}
642 
643 	ret = 0;
644 
645       cleanup:
646 	pkcs11_close_session(&sinfo);
647 	gnutls_free(spki.data);
648 	return ret;
649 
650 }
651 
652 /**
653  * gnutls_pkcs11_copy_x509_privkey2:
654  * @token_url: A PKCS #11 URL specifying a token
655  * @key: A private key
656  * @label: A name to be used for the stored data
657  * @cid: The CKA_ID to set for the object -if NULL, the ID will be derived from the public key
658  * @key_usage: One of GNUTLS_KEY_*
659  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
660  *
661  * This function will copy a private key into a PKCS #11 token specified by
662  * a URL.
663  *
664  * Since 3.6.3 the objects are marked as sensitive by default unless
665  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified.
666  *
667  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
668  *   negative error value.
669  *
670  * Since: 3.4.0
671  **/
672 int
gnutls_pkcs11_copy_x509_privkey2(const char * token_url,gnutls_x509_privkey_t key,const char * label,const gnutls_datum_t * cid,unsigned int key_usage,unsigned int flags)673 gnutls_pkcs11_copy_x509_privkey2(const char *token_url,
674 				gnutls_x509_privkey_t key,
675 				const char *label,
676 				const gnutls_datum_t *cid,
677 				unsigned int key_usage, unsigned int flags)
678 {
679 	int ret;
680 	struct p11_kit_uri *info = NULL;
681 	ck_rv_t rv;
682 	size_t id_size;
683 	uint8_t id[20];
684 	struct ck_attribute a[32];
685 	ck_object_class_t class = CKO_PRIVATE_KEY;
686 	ck_object_handle_t ctx;
687 	ck_key_type_t type;
688 	int a_val;
689 	gnutls_pk_algorithm_t pk;
690 	gnutls_datum_t p, q, g, y, x;
691 	gnutls_datum_t m, e, d, u, exp1, exp2;
692 	struct pkcs11_session_info sinfo;
693 
694 	PKCS11_CHECK_INIT;
695 
696 	memset(&p, 0, sizeof(p));
697 	memset(&q, 0, sizeof(q));
698 	memset(&g, 0, sizeof(g));
699 	memset(&y, 0, sizeof(y));
700 	memset(&x, 0, sizeof(x));
701 	memset(&m, 0, sizeof(m));
702 	memset(&e, 0, sizeof(e));
703 	memset(&d, 0, sizeof(d));
704 	memset(&u, 0, sizeof(u));
705 	memset(&exp1, 0, sizeof(exp1));
706 	memset(&exp2, 0, sizeof(exp2));
707 
708 	ret = pkcs11_url_to_info(token_url, &info, 0);
709 	if (ret < 0) {
710 		gnutls_assert();
711 		return ret;
712 	}
713 
714 	ret =
715 	    pkcs11_open_session(&sinfo, NULL, info,
716 				SESSION_WRITE |
717 				pkcs11_obj_flags_to_int(flags));
718 	p11_kit_uri_free(info);
719 
720 	if (ret < 0) {
721 		gnutls_assert();
722 		return ret;
723 	}
724 
725 	pk = gnutls_x509_privkey_get_pk_algorithm(key);
726 	FIX_KEY_USAGE(pk, key_usage);
727 
728 	a_val = 0;
729 	a[a_val].type = CKA_CLASS;
730 	a[a_val].value = &class;
731 	a[a_val].value_len = sizeof(class);
732 	a_val++;
733 
734 	a[a_val].type = CKA_ID;
735 	if (cid == NULL || cid->size == 0) {
736 		id_size = sizeof(id);
737 		ret = gnutls_x509_privkey_get_key_id(key, 0, id, &id_size);
738 		if (ret < 0) {
739 			p11_kit_uri_free(info);
740 			gnutls_assert();
741 			return ret;
742 		}
743 
744 		a[a_val].value = id;
745 		a[a_val].value_len = id_size;
746 	} else {
747 		a[a_val].value = cid->data;
748 		a[a_val].value_len = cid->size;
749 	}
750 	a_val++;
751 
752 	a[a_val].type = CKA_SIGN;
753 	if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
754 		a[a_val].value = (void*)&tval;
755 		a[a_val].value_len = sizeof(tval);
756 	} else {
757 		a[a_val].value = (void*)&fval;
758 		a[a_val].value_len = sizeof(fval);
759 	}
760 	a_val++;
761 
762 	if (pk == GNUTLS_PK_RSA) {
763 		a[a_val].type = CKA_DECRYPT;
764 		if ((key_usage & (GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_DECIPHER_ONLY)) ||
765 		    (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT)) {
766 			a[a_val].value = (void*)&tval;
767 			a[a_val].value_len = sizeof(tval);
768 		} else {
769 			a[a_val].value = (void*)&fval;
770 			a[a_val].value_len = sizeof(fval);
771 		}
772 		a_val++;
773 	}
774 
775 	a[a_val].type = CKA_TOKEN;
776 	a[a_val].value = (void *) &tval;
777 	a[a_val].value_len = sizeof(tval);
778 	a_val++;
779 
780 	/* a private key is set always as private unless
781 	 * requested otherwise
782 	 */
783 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
784 		a[a_val].type = CKA_PRIVATE;
785 		a[a_val].value = (void *) &fval;
786 		a[a_val].value_len = sizeof(fval);
787 		a_val++;
788 	} else {
789 		a[a_val].type = CKA_PRIVATE;
790 		a[a_val].value = (void *) &tval;
791 		a[a_val].value_len = sizeof(tval);
792 		a_val++;
793 	}
794 
795 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH) {
796 		a[a_val].type = CKA_ALWAYS_AUTHENTICATE;
797 		a[a_val].value = (void *) &tval;
798 		a[a_val].value_len = sizeof(tval);
799 		a_val++;
800 	}
801 
802 	if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_EXTRACTABLE) {
803 		a[a_val].type = CKA_EXTRACTABLE;
804 		a[a_val].value = (void *) &tval;
805 		a[a_val].value_len = sizeof(tval);
806 		(a_val)++;
807 	} else {
808 		a[a_val].type = CKA_EXTRACTABLE;
809 		a[a_val].value = (void *) &fval;
810 		a[a_val].value_len = sizeof(fval);
811 		(a_val)++;
812 	}
813 
814 	if (label) {
815 		a[a_val].type = CKA_LABEL;
816 		a[a_val].value = (void *) label;
817 		a[a_val].value_len = strlen(label);
818 		a_val++;
819 	}
820 
821 	if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) {
822 		a[a_val].type = CKA_SENSITIVE;
823 		a[a_val].value = (void *) &tval;
824 		a[a_val].value_len = sizeof(tval);
825 		a_val++;
826 	} else {
827 		a[a_val].type = CKA_SENSITIVE;
828 		a[a_val].value = (void *) &fval;
829 		a[a_val].value_len = sizeof(fval);
830 		a_val++;
831 	}
832 
833 	switch (pk) {
834 	case GNUTLS_PK_RSA:
835 	case GNUTLS_PK_RSA_PSS:
836 		{
837 
838 			ret = _gnutls_params_get_rsa_raw(&key->params, &m, &e, &d, &p,
839 							 &q, &u, &exp1, &exp2,
840 							 GNUTLS_EXPORT_FLAG_NO_LZ);
841 			if (ret < 0) {
842 				gnutls_assert();
843 				goto cleanup;
844 			}
845 
846 			type = CKK_RSA;
847 
848 			a[a_val].type = CKA_MODULUS;
849 			a[a_val].value = m.data;
850 			a[a_val].value_len = m.size;
851 			a_val++;
852 
853 			a[a_val].type = CKA_PUBLIC_EXPONENT;
854 			a[a_val].value = e.data;
855 			a[a_val].value_len = e.size;
856 			a_val++;
857 
858 			a[a_val].type = CKA_PRIVATE_EXPONENT;
859 			a[a_val].value = d.data;
860 			a[a_val].value_len = d.size;
861 			a_val++;
862 
863 			a[a_val].type = CKA_PRIME_1;
864 			a[a_val].value = p.data;
865 			a[a_val].value_len = p.size;
866 			a_val++;
867 
868 			a[a_val].type = CKA_PRIME_2;
869 			a[a_val].value = q.data;
870 			a[a_val].value_len = q.size;
871 			a_val++;
872 
873 			a[a_val].type = CKA_COEFFICIENT;
874 			a[a_val].value = u.data;
875 			a[a_val].value_len = u.size;
876 			a_val++;
877 
878 			a[a_val].type = CKA_EXPONENT_1;
879 			a[a_val].value = exp1.data;
880 			a[a_val].value_len = exp1.size;
881 			a_val++;
882 
883 			a[a_val].type = CKA_EXPONENT_2;
884 			a[a_val].value = exp2.data;
885 			a[a_val].value_len = exp2.size;
886 			a_val++;
887 
888 			break;
889 		}
890 	case GNUTLS_PK_DSA:
891 		{
892 			ret = _gnutls_params_get_dsa_raw(&key->params, &p, &q, &g, &y, &x,
893 							 GNUTLS_EXPORT_FLAG_NO_LZ);
894 			if (ret < 0) {
895 				gnutls_assert();
896 				goto cleanup;
897 			}
898 
899 			type = CKK_DSA;
900 
901 			a[a_val].type = CKA_PRIME;
902 			a[a_val].value = p.data;
903 			a[a_val].value_len = p.size;
904 			a_val++;
905 
906 			a[a_val].type = CKA_SUBPRIME;
907 			a[a_val].value = q.data;
908 			a[a_val].value_len = q.size;
909 			a_val++;
910 
911 			a[a_val].type = CKA_BASE;
912 			a[a_val].value = g.data;
913 			a[a_val].value_len = g.size;
914 			a_val++;
915 
916 			a[a_val].type = CKA_VALUE;
917 			a[a_val].value = x.data;
918 			a[a_val].value_len = x.size;
919 			a_val++;
920 
921 			break;
922 		}
923 	case GNUTLS_PK_EC:
924 		{
925 			ret =
926 			    _gnutls_x509_write_ecc_params(key->params.curve,
927 							  &p);
928 			if (ret < 0) {
929 				gnutls_assert();
930 				goto cleanup;
931 			}
932 
933 			ret =
934 			    _gnutls_mpi_dprint(key->params.
935 						params[ECC_K], &x);
936 			if (ret < 0) {
937 				gnutls_assert();
938 				goto cleanup;
939 			}
940 
941 			type = CKK_ECDSA;
942 
943 			a[a_val].type = CKA_EC_PARAMS;
944 			a[a_val].value = p.data;
945 			a[a_val].value_len = p.size;
946 			a_val++;
947 
948 			a[a_val].type = CKA_VALUE;
949 			a[a_val].value = x.data;
950 			a[a_val].value_len = x.size;
951 			a_val++;
952 
953 			break;
954 		}
955 #ifdef HAVE_CKM_EDDSA
956 	case GNUTLS_PK_EDDSA_ED25519:
957 		{
958 			ret =
959 			    _gnutls_x509_write_ecc_params(key->params.curve,
960 							  &p);
961 			if (ret < 0) {
962 				gnutls_assert();
963 				goto cleanup;
964 			}
965 
966 			type = CKK_EC_EDWARDS;
967 
968 			a[a_val].type = CKA_EC_PARAMS;
969 			a[a_val].value = p.data;
970 			a[a_val].value_len = p.size;
971 			a_val++;
972 
973 			a[a_val].type = CKA_VALUE;
974 			a[a_val].value = key->params.raw_priv.data;
975 			a[a_val].value_len = key->params.raw_priv.size;
976 			a_val++;
977 
978 			break;
979 		}
980 #endif
981 	default:
982 		gnutls_assert();
983 		ret = GNUTLS_E_INVALID_REQUEST;
984 		goto cleanup;
985 	}
986 
987 	a[a_val].type = CKA_KEY_TYPE;
988 	a[a_val].value = &type;
989 	a[a_val].value_len = sizeof(type);
990 	a_val++;
991 
992 	rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
993 	if (rv != CKR_OK) {
994 		gnutls_assert();
995 		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
996 		ret = pkcs11_rv_to_err(rv);
997 		goto cleanup;
998 	}
999 
1000 	ret = 0;
1001 
1002       cleanup:
1003 	switch (pk) {
1004 	case GNUTLS_PK_RSA_PSS:
1005 	case GNUTLS_PK_RSA:
1006 		{
1007 			gnutls_free(m.data);
1008 			gnutls_free(e.data);
1009 			gnutls_free(d.data);
1010 			gnutls_free(p.data);
1011 			gnutls_free(q.data);
1012 			gnutls_free(u.data);
1013 			gnutls_free(exp1.data);
1014 			gnutls_free(exp2.data);
1015 			break;
1016 		}
1017 	case GNUTLS_PK_DSA:
1018 		{
1019 			gnutls_free(p.data);
1020 			gnutls_free(q.data);
1021 			gnutls_free(g.data);
1022 			gnutls_free(y.data);
1023 			gnutls_free(x.data);
1024 			break;
1025 		}
1026 	case GNUTLS_PK_EC:
1027 	case GNUTLS_PK_EDDSA_ED25519:
1028 		{
1029 			gnutls_free(p.data);
1030 			gnutls_free(x.data);
1031 			break;
1032 		}
1033 	default:
1034 		gnutls_assert();
1035 		ret = GNUTLS_E_INVALID_REQUEST;
1036 		break;
1037 	}
1038 
1039 	if (sinfo.pks != 0)
1040 		pkcs11_close_session(&sinfo);
1041 
1042 	return ret;
1043 
1044 }
1045 
1046 struct delete_data_st {
1047 	struct p11_kit_uri *info;
1048 	unsigned int deleted;	/* how many */
1049 };
1050 
1051 static int
delete_obj_url_cb(struct ck_function_list * module,struct pkcs11_session_info * sinfo,struct ck_token_info * tinfo,struct ck_info * lib_info,void * input)1052 delete_obj_url_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo,
1053 		  struct ck_token_info *tinfo,
1054 		  struct ck_info *lib_info, void *input)
1055 {
1056 	struct delete_data_st *find_data = input;
1057 	struct ck_attribute a[4];
1058 	struct ck_attribute *attr;
1059 	ck_object_class_t class;
1060 	ck_certificate_type_t type = (ck_certificate_type_t) - 1;
1061 	ck_rv_t rv;
1062 	ck_object_handle_t ctx;
1063 	unsigned long count, a_vals;
1064 	int found = 0, ret;
1065 
1066 	if (tinfo == NULL) {	/* we don't support multiple calls */
1067 		gnutls_assert();
1068 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1069 	}
1070 
1071 	/* do not bother reading the token if basic fields do not match
1072 	 */
1073 	if (!p11_kit_uri_match_module_info(find_data->info, lib_info) ||
1074 	    !p11_kit_uri_match_token_info(find_data->info, tinfo)) {
1075 		gnutls_assert();
1076 		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1077 	}
1078 
1079 	/* Find objects with given class and type */
1080 	class = CKO_CERTIFICATE;	/* default  */
1081 	a_vals = 0;
1082 
1083 	attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
1084 	if (attr != NULL) {
1085 		if (attr->value
1086 		    && attr->value_len == sizeof(ck_object_class_t))
1087 			class = *((ck_object_class_t *) attr->value);
1088 		if (class == CKO_CERTIFICATE)
1089 			type = CKC_X_509;
1090 
1091 		a[a_vals].type = CKA_CLASS;
1092 		a[a_vals].value = &class;
1093 		a[a_vals].value_len = sizeof(class);
1094 		a_vals++;
1095 	}
1096 
1097 	attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
1098 	if (attr != NULL) {
1099 		memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1100 		a_vals++;
1101 	}
1102 
1103 	if (type != (ck_certificate_type_t) - 1) {
1104 		a[a_vals].type = CKA_CERTIFICATE_TYPE;
1105 		a[a_vals].value = &type;
1106 		a[a_vals].value_len = sizeof type;
1107 		a_vals++;
1108 	}
1109 
1110 	attr = p11_kit_uri_get_attribute(find_data->info, CKA_LABEL);
1111 	if (attr != NULL) {
1112 		memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1113 		a_vals++;
1114 	}
1115 
1116 	rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
1117 				      a_vals);
1118 	if (rv != CKR_OK) {
1119 		gnutls_assert();
1120 		_gnutls_debug_log("p11: FindObjectsInit failed.\n");
1121 		ret = pkcs11_rv_to_err(rv);
1122 		goto cleanup;
1123 	}
1124 
1125 	while (pkcs11_find_objects
1126 	       (sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK
1127 	       && count == 1) {
1128 		rv = pkcs11_destroy_object(sinfo->module, sinfo->pks, ctx);
1129 		if (rv != CKR_OK) {
1130 			_gnutls_debug_log
1131 			    ("p11: Cannot destroy object: %s\n",
1132 			     pkcs11_strerror(rv));
1133 		} else {
1134 			find_data->deleted++;
1135 		}
1136 
1137 		found = 1;
1138 	}
1139 
1140 	if (found == 0) {
1141 		gnutls_assert();
1142 		ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1143 	} else {
1144 		ret = 0;
1145 	}
1146 
1147       cleanup:
1148 	pkcs11_find_objects_final(sinfo);
1149 
1150 	return ret;
1151 }
1152 
1153 
1154 /**
1155  * gnutls_pkcs11_delete_url:
1156  * @object_url: The URL of the object to delete.
1157  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1158  *
1159  * This function will delete objects matching the given URL.
1160  * Note that not all tokens support the delete operation.
1161  *
1162  * Returns: On success, the number of objects deleted is returned, otherwise a
1163  *   negative error value.
1164  *
1165  * Since: 2.12.0
1166  **/
gnutls_pkcs11_delete_url(const char * object_url,unsigned int flags)1167 int gnutls_pkcs11_delete_url(const char *object_url, unsigned int flags)
1168 {
1169 	int ret;
1170 	struct delete_data_st find_data;
1171 
1172 	PKCS11_CHECK_INIT;
1173 
1174 	memset(&find_data, 0, sizeof(find_data));
1175 
1176 	ret = pkcs11_url_to_info(object_url, &find_data.info, 0);
1177 	if (ret < 0) {
1178 		gnutls_assert();
1179 		return ret;
1180 	}
1181 
1182 	ret =
1183 	    _pkcs11_traverse_tokens(delete_obj_url_cb, &find_data,
1184 				    find_data.info, NULL,
1185 				    SESSION_WRITE |
1186 				    pkcs11_obj_flags_to_int(flags));
1187 	p11_kit_uri_free(find_data.info);
1188 
1189 	if (ret < 0) {
1190 		gnutls_assert();
1191 		return ret;
1192 	}
1193 
1194 	return find_data.deleted;
1195 
1196 }
1197 
1198 /**
1199  * gnutls_pkcs11_token_init:
1200  * @token_url: A PKCS #11 URL specifying a token
1201  * @so_pin: Security Officer's PIN
1202  * @label: A name to be used for the token
1203  *
1204  * This function will initialize (format) a token. If the token is
1205  * at a factory defaults state the security officer's PIN given will be
1206  * set to be the default. Otherwise it should match the officer's PIN.
1207  *
1208  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1209  *   negative error value.
1210  **/
1211 int
gnutls_pkcs11_token_init(const char * token_url,const char * so_pin,const char * label)1212 gnutls_pkcs11_token_init(const char *token_url,
1213 			 const char *so_pin, const char *label)
1214 {
1215 	int ret;
1216 	struct p11_kit_uri *info = NULL;
1217 	ck_rv_t rv;
1218 	struct ck_function_list *module;
1219 	ck_slot_id_t slot;
1220 	char flabel[32];
1221 
1222 	PKCS11_CHECK_INIT;
1223 
1224 	ret = pkcs11_url_to_info(token_url, &info, 0);
1225 	if (ret < 0) {
1226 		gnutls_assert();
1227 		return ret;
1228 	}
1229 
1230 	ret = pkcs11_find_slot(&module, &slot, info, NULL, NULL, NULL);
1231 	p11_kit_uri_free(info);
1232 
1233 	if (ret < 0) {
1234 		gnutls_assert();
1235 		return ret;
1236 	}
1237 
1238 	/* so it seems memset has other uses than zeroing! */
1239 	memset(flabel, ' ', sizeof(flabel));
1240 	if (label != NULL)
1241 		memcpy(flabel, label, strlen(label));
1242 
1243 	rv = pkcs11_init_token(module, slot, (uint8_t *) so_pin,
1244 			       strlen(so_pin), (uint8_t *) flabel);
1245 	if (rv != CKR_OK) {
1246 		gnutls_assert();
1247 		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
1248 		return pkcs11_rv_to_err(rv);
1249 	}
1250 
1251 	return 0;
1252 
1253 }
1254 
1255 #define L(x) ((x==NULL)?0:strlen(x))
1256 
1257 /**
1258  * gnutls_pkcs11_token_set_pin:
1259  * @token_url: A PKCS #11 URL specifying a token
1260  * @oldpin: old user's PIN
1261  * @newpin: new user's PIN
1262  * @flags: one of #gnutls_pin_flag_t.
1263  *
1264  * This function will modify or set a user or administrator's PIN for
1265  * the given token.  If it is called to set a PIN for first time
1266  * the oldpin must be %NULL. When setting the admin's PIN with the
1267  * %GNUTLS_PIN_SO flag, the @oldpin value must be provided (this requirement
1268  * is relaxed after GnuTLS 3.6.5 since which the PIN will be requested if missing).
1269  *
1270  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1271  *   negative error value.
1272  **/
1273 int
gnutls_pkcs11_token_set_pin(const char * token_url,const char * oldpin,const char * newpin,unsigned int flags)1274 gnutls_pkcs11_token_set_pin(const char *token_url,
1275 			    const char *oldpin,
1276 			    const char *newpin, unsigned int flags)
1277 {
1278 	int ret;
1279 	struct p11_kit_uri *info = NULL;
1280 	ck_rv_t rv;
1281 	unsigned int ses_flags;
1282 	struct pkcs11_session_info sinfo;
1283 
1284 	PKCS11_CHECK_INIT;
1285 
1286 	ret = pkcs11_url_to_info(token_url, &info, 0);
1287 	if (ret < 0) {
1288 		gnutls_assert();
1289 		return ret;
1290 	}
1291 
1292 	if (((flags & GNUTLS_PIN_USER) && oldpin == NULL) ||
1293 	    (flags & GNUTLS_PIN_SO))
1294 		ses_flags = SESSION_WRITE | SESSION_LOGIN | SESSION_SO;
1295 	else
1296 		ses_flags = SESSION_WRITE | SESSION_LOGIN;
1297 
1298 	ret = pkcs11_open_session(&sinfo, NULL, info, ses_flags);
1299 	p11_kit_uri_free(info);
1300 
1301 	if (ret < 0) {
1302 		gnutls_assert();
1303 		return ret;
1304 	}
1305 
1306 	if (oldpin == NULL && !(flags & GNUTLS_PIN_SO)) {
1307 		/* This changes only the user PIN */
1308 		rv = pkcs11_init_pin(sinfo.module, sinfo.pks,
1309 				     (uint8_t *) newpin, strlen(newpin));
1310 		if (rv != CKR_OK) {
1311 			gnutls_assert();
1312 			_gnutls_debug_log("p11: %s\n",
1313 					  pkcs11_strerror(rv));
1314 			ret = pkcs11_rv_to_err(rv);
1315 			goto finish;
1316 		}
1317 	} else {
1318 		struct p11_kit_pin *pin;
1319 		unsigned oldpin_size;
1320 
1321 		oldpin_size = L(oldpin);
1322 
1323 		if (!(sinfo.tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
1324 			if (newpin == NULL)
1325 				return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1326 
1327 			if (oldpin == NULL) {
1328 				struct pin_info_st pin_info;
1329 				memset(&pin_info, 0, sizeof(pin_info));
1330 
1331 				ret = pkcs11_retrieve_pin(&pin_info, info, &sinfo.tinfo, 0, CKU_SO, &pin);
1332 				if (ret < 0) {
1333 					gnutls_assert();
1334 					goto finish;
1335 				}
1336 				oldpin = (const char*)p11_kit_pin_get_value(pin, NULL);
1337 				oldpin_size = p11_kit_pin_get_length(pin);
1338 			}
1339 		}
1340 
1341 		rv = pkcs11_set_pin(sinfo.module, sinfo.pks,
1342 				    oldpin, oldpin_size,
1343 				    newpin, L(newpin));
1344 		if (rv != CKR_OK) {
1345 			gnutls_assert();
1346 			_gnutls_debug_log("p11: %s\n",
1347 					  pkcs11_strerror(rv));
1348 			ret = pkcs11_rv_to_err(rv);
1349 			goto finish;
1350 		}
1351 	}
1352 
1353 	ret = 0;
1354 
1355       finish:
1356 	pkcs11_close_session(&sinfo);
1357 	return ret;
1358 
1359 }
1360 
1361 /**
1362  * gnutls_pkcs11_token_get_random:
1363  * @token_url: A PKCS #11 URL specifying a token
1364  * @len:       The number of bytes of randomness to request
1365  * @rnddata:   A pointer to the memory area to be filled with random data
1366  *
1367  * This function will get random data from the given token.
1368  * It will store rnddata and fill the memory pointed to by rnddata with
1369  * len random bytes from the token.
1370  *
1371  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1372  *   negative error value.
1373  **/
1374 int
gnutls_pkcs11_token_get_random(const char * token_url,void * rnddata,size_t len)1375 gnutls_pkcs11_token_get_random(const char *token_url,
1376 			       void *rnddata, size_t len)
1377 {
1378 	int ret;
1379 	struct p11_kit_uri *info = NULL;
1380 	ck_rv_t rv;
1381 	struct pkcs11_session_info sinfo;
1382 
1383 	PKCS11_CHECK_INIT;
1384 
1385 	ret = pkcs11_url_to_info(token_url, &info, 0);
1386 	if (ret < 0) {
1387 		gnutls_assert();
1388 		return ret;
1389 	}
1390 
1391 	ret = pkcs11_open_session(&sinfo, NULL, info, 0);
1392 	p11_kit_uri_free(info);
1393 
1394 	if (ret < 0) {
1395 		gnutls_assert();
1396 		return ret;
1397 	}
1398 
1399 	rv = _gnutls_pkcs11_get_random(sinfo.module, sinfo.pks, rnddata, len);
1400 	if (rv != CKR_OK) {
1401 		gnutls_assert();
1402 		_gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
1403 		ret = pkcs11_rv_to_err(rv);
1404 		goto finish;
1405 	}
1406 
1407 	ret = 0;
1408 
1409       finish:
1410 	pkcs11_close_session(&sinfo);
1411 	return ret;
1412 
1413 }
1414 
1415 #if 0
1416 /* For documentation purposes */
1417 
1418 
1419 /**
1420  * gnutls_pkcs11_copy_x509_crt:
1421  * @token_url: A PKCS #11 URL specifying a token
1422  * @crt: A certificate
1423  * @label: A name to be used for the stored data
1424  * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
1425  *
1426  * This function will copy a certificate into a PKCS #11 token specified by
1427  * a URL. The certificate can be marked as trusted or not.
1428  *
1429  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1430  *   negative error value.
1431  *
1432  * Since: 2.12.0
1433  **/
1434 int gnutls_pkcs11_copy_x509_crt(const char *token_url,
1435 			    gnutls_x509_crt_t crt, const char *label,
1436 			    unsigned int flags)
1437 {
1438 	int x;
1439 }
1440 
1441 /**
1442  * gnutls_pkcs11_copy_x509_privkey:
1443  * @token_url: A PKCS #11 URL specifying a token
1444  * @key: A private key
1445  * @label: A name to be used for the stored data
1446  * @key_usage: One of GNUTLS_KEY_*
1447  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1448  *
1449  * This function will copy a private key into a PKCS #11 token specified by
1450  * a URL.
1451  *
1452  * Since 3.6.3 the objects are marked as sensitive by default unless
1453  * %GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE is specified.
1454  *
1455  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1456  *   negative error value.
1457  *
1458  * Since: 2.12.0
1459  **/
1460 int gnutls_pkcs11_copy_x509_privkey(const char *token_url,
1461 				gnutls_x509_privkey_t key,
1462 				const char *label,
1463 				unsigned int key_usage, unsigned int flags)
1464 {
1465 	int x;
1466 }
1467 
1468 #endif
1469