Line data Source code
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 :
37 122 : static void mark_flags(unsigned flags, struct ck_attribute *a, unsigned *a_val, unsigned trusted)
38 : {
39 122 : static const unsigned long category = 2;
40 :
41 122 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_CA) {
42 92 : a[*a_val].type = CKA_CERTIFICATE_CATEGORY;
43 92 : a[*a_val].value = (void *) &category;
44 92 : a[*a_val].value_len = sizeof(category);
45 92 : (*a_val)++;
46 : }
47 :
48 122 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_DISTRUSTED) {
49 0 : if (trusted) {
50 0 : a[*a_val].type = CKA_X_DISTRUSTED;
51 0 : a[*a_val].value = (void *) &tval;
52 0 : a[*a_val].value_len = sizeof(tval);
53 0 : (*a_val)++;
54 : } else {
55 0 : _gnutls_debug_log("p11: ignoring the distrusted flag as it is not valid on non-p11-kit-trust modules\n");
56 : }
57 : }
58 :
59 122 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED) {
60 96 : a[*a_val].type = CKA_TRUSTED;
61 96 : a[*a_val].value = (void *) &tval;
62 96 : a[*a_val].value_len = sizeof(tval);
63 96 : (*a_val)++;
64 :
65 96 : a[*a_val].type = CKA_PRIVATE;
66 96 : a[*a_val].value = (void *) &fval;
67 96 : a[*a_val].value_len = sizeof(fval);
68 96 : (*a_val)++;
69 : } else {
70 26 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE) {
71 17 : a[*a_val].type = CKA_PRIVATE;
72 17 : a[*a_val].value = (void *) &tval;
73 17 : a[*a_val].value_len = sizeof(tval);
74 17 : (*a_val)++;
75 9 : } else if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
76 7 : a[*a_val].type = CKA_PRIVATE;
77 7 : a[*a_val].value = (void *) &fval;
78 7 : a[*a_val].value_len = sizeof(fval);
79 7 : (*a_val)++;
80 : }
81 : }
82 122 : }
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
103 119 : 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 119 : int ret;
109 119 : struct p11_kit_uri *info = NULL;
110 119 : ck_rv_t rv;
111 119 : size_t der_size, id_size, serial_size;
112 119 : gnutls_datum_t serial_der = {NULL, 0};
113 119 : uint8_t *der = NULL;
114 119 : uint8_t serial[128];
115 119 : uint8_t id[20];
116 119 : struct ck_attribute a[MAX_ASIZE];
117 119 : ck_object_class_t class = CKO_CERTIFICATE;
118 119 : ck_certificate_type_t type = CKC_X_509;
119 119 : ck_object_handle_t ctx;
120 119 : unsigned a_val;
121 119 : struct pkcs11_session_info sinfo;
122 :
123 119 : PKCS11_CHECK_INIT;
124 :
125 119 : ret = pkcs11_url_to_info(token_url, &info, 0);
126 119 : if (ret < 0) {
127 0 : gnutls_assert();
128 0 : return ret;
129 : }
130 :
131 119 : ret =
132 119 : pkcs11_open_session(&sinfo, NULL, info,
133 : SESSION_WRITE |
134 119 : pkcs11_obj_flags_to_int(flags));
135 119 : p11_kit_uri_free(info);
136 :
137 119 : if (ret < 0) {
138 0 : gnutls_assert();
139 0 : return ret;
140 : }
141 :
142 119 : der_size = 0;
143 119 : ret =
144 119 : gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, NULL,
145 : &der_size);
146 119 : if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
147 0 : gnutls_assert();
148 0 : goto cleanup;
149 : }
150 :
151 119 : der = gnutls_malloc(der_size);
152 119 : if (der == NULL) {
153 0 : gnutls_assert();
154 0 : ret = GNUTLS_E_MEMORY_ERROR;
155 0 : goto cleanup;
156 : }
157 :
158 119 : ret =
159 119 : gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_DER, der,
160 : &der_size);
161 119 : if (ret < 0) {
162 0 : gnutls_assert();
163 0 : goto cleanup;
164 : }
165 :
166 119 : a[0].type = CKA_CLASS;
167 119 : a[0].value = &class;
168 119 : a[0].value_len = sizeof(class);
169 :
170 119 : a[1].type = CKA_ID;
171 119 : if (cid == NULL || cid->size == 0) {
172 115 : id_size = sizeof(id);
173 115 : ret = gnutls_x509_crt_get_subject_key_id(crt, id, &id_size, NULL);
174 115 : if (ret < 0) {
175 28 : id_size = sizeof(id);
176 28 : ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
177 28 : if (ret < 0) {
178 0 : gnutls_assert();
179 0 : goto cleanup;
180 : }
181 : }
182 :
183 115 : a[1].value = id;
184 115 : a[1].value_len = id_size;
185 : } else {
186 4 : a[1].value = cid->data;
187 4 : 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 119 : a[2].type = CKA_VALUE;
193 119 : a[2].value = der;
194 119 : a[2].value_len = der_size;
195 119 : a[3].type = CKA_TOKEN;
196 119 : a[3].value = (void *) &tval;
197 119 : a[3].value_len = sizeof(tval);
198 119 : a[4].type = CKA_CERTIFICATE_TYPE;
199 119 : a[4].value = &type;
200 119 : a[4].value_len = sizeof(type);
201 :
202 119 : a_val = 5;
203 :
204 119 : a[a_val].type = CKA_SUBJECT;
205 119 : a[a_val].value = crt->raw_dn.data;
206 119 : a[a_val].value_len = crt->raw_dn.size;
207 119 : a_val++;
208 :
209 119 : if (crt->raw_issuer_dn.size > 0) {
210 119 : a[a_val].type = CKA_ISSUER;
211 119 : a[a_val].value = crt->raw_issuer_dn.data;
212 119 : a[a_val].value_len = crt->raw_issuer_dn.size;
213 119 : a_val++;
214 : }
215 :
216 119 : serial_size = sizeof(serial);
217 119 : if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) {
218 119 : ret = _gnutls_x509_ext_gen_number(serial, serial_size, &serial_der);
219 119 : if (ret >= 0) {
220 119 : a[a_val].type = CKA_SERIAL_NUMBER;
221 119 : a[a_val].value = (void *) serial_der.data;
222 119 : a[a_val].value_len = serial_der.size;
223 119 : a_val++;
224 : }
225 : }
226 :
227 119 : if (label) {
228 119 : a[a_val].type = CKA_LABEL;
229 119 : a[a_val].value = (void *) label;
230 119 : a[a_val].value_len = strlen(label);
231 119 : a_val++;
232 : }
233 :
234 119 : mark_flags(flags, a, &a_val, sinfo.trusted);
235 :
236 119 : rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
237 119 : if (rv != CKR_OK) {
238 1 : gnutls_assert();
239 1 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
240 1 : ret = pkcs11_rv_to_err(rv);
241 1 : goto cleanup;
242 : }
243 :
244 : /* generated!
245 : */
246 :
247 : ret = 0;
248 :
249 119 : cleanup:
250 119 : gnutls_free(der);
251 119 : gnutls_free(serial_der.data);
252 119 : pkcs11_close_session(&sinfo);
253 119 : return ret;
254 :
255 : }
256 :
257 3 : static void clean_pubkey(struct ck_attribute *a, unsigned a_val)
258 : {
259 3 : unsigned i;
260 :
261 29 : for (i=0;i<a_val;i++) {
262 26 : switch(a[i].type) {
263 6 : 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 6 : gnutls_free(a[i].value);
272 6 : break;
273 : }
274 26 : }
275 3 : }
276 :
277 3 : static int add_pubkey(gnutls_pubkey_t pubkey, struct ck_attribute *a, unsigned *a_val)
278 : {
279 3 : gnutls_pk_algorithm_t pk;
280 3 : int ret;
281 :
282 3 : pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
283 :
284 3 : switch (pk) {
285 1 : case GNUTLS_PK_RSA_PSS:
286 : case GNUTLS_PK_RSA: {
287 1 : 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 1 : ret = gnutls_pubkey_export_rsa_raw2(pubkey, &m, &e, GNUTLS_EXPORT_FLAG_NO_LZ);
293 1 : if (ret < 0) {
294 0 : gnutls_assert();
295 0 : return ret;
296 : }
297 :
298 :
299 1 : a[*a_val].type = CKA_MODULUS;
300 1 : a[*a_val].value = m.data;
301 1 : a[*a_val].value_len = m.size;
302 1 : (*a_val)++;
303 :
304 1 : a[*a_val].type = CKA_PUBLIC_EXPONENT;
305 1 : a[*a_val].value = e.data;
306 1 : a[*a_val].value_len = e.size;
307 1 : (*a_val)++;
308 1 : break;
309 : }
310 0 : case GNUTLS_PK_DSA: {
311 0 : gnutls_datum_t p, q, g, y;
312 :
313 0 : ret = gnutls_pubkey_export_dsa_raw2(pubkey, &p, &q, &g, &y, GNUTLS_EXPORT_FLAG_NO_LZ);
314 0 : if (ret < 0) {
315 0 : gnutls_assert();
316 0 : return ret;
317 : }
318 :
319 0 : a[*a_val].type = CKA_PRIME;
320 0 : a[*a_val].value = p.data;
321 0 : a[*a_val].value_len = p.size;
322 0 : (*a_val)++;
323 :
324 0 : a[*a_val].type = CKA_SUBPRIME;
325 0 : a[*a_val].value = q.data;
326 0 : a[*a_val].value_len = q.size;
327 0 : (*a_val)++;
328 :
329 0 : a[*a_val].type = CKA_BASE;
330 0 : a[*a_val].value = g.data;
331 0 : a[*a_val].value_len = g.size;
332 0 : (*a_val)++;
333 :
334 0 : a[*a_val].type = CKA_VALUE;
335 0 : a[*a_val].value = y.data;
336 0 : a[*a_val].value_len = y.size;
337 0 : (*a_val)++;
338 0 : break;
339 : }
340 1 : case GNUTLS_PK_EC: {
341 1 : gnutls_datum_t params, point;
342 :
343 1 : ret = gnutls_pubkey_export_ecc_x962(pubkey, ¶ms, &point);
344 1 : if (ret < 0) {
345 0 : gnutls_assert();
346 0 : return ret;
347 : }
348 :
349 1 : a[*a_val].type = CKA_EC_PARAMS;
350 1 : a[*a_val].value = params.data;
351 1 : a[*a_val].value_len = params.size;
352 1 : (*a_val)++;
353 :
354 1 : a[*a_val].type = CKA_EC_POINT;
355 1 : a[*a_val].value = point.data;
356 1 : a[*a_val].value_len = point.size;
357 1 : (*a_val)++;
358 1 : break;
359 : }
360 1 : case GNUTLS_PK_EDDSA_ED25519: {
361 1 : gnutls_datum_t params, ecpoint;
362 :
363 1 : ret =
364 1 : _gnutls_x509_write_ecc_params(pubkey->params.curve,
365 : ¶ms);
366 1 : if (ret < 0) {
367 0 : gnutls_assert();
368 0 : return ret;
369 : }
370 :
371 1 : a[*a_val].type = CKA_EC_PARAMS;
372 1 : a[*a_val].value = params.data;
373 1 : a[*a_val].value_len = params.size;
374 1 : (*a_val)++;
375 :
376 2 : ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
377 1 : pubkey->params.raw_pub.data,
378 1 : pubkey->params.raw_pub.size,
379 : &ecpoint);
380 1 : if (ret < 0) {
381 0 : gnutls_assert();
382 0 : return ret;
383 : }
384 :
385 1 : a[*a_val].type = CKA_EC_POINT;
386 1 : a[*a_val].value = ecpoint.data;
387 1 : a[*a_val].value_len = ecpoint.size;
388 1 : (*a_val)++;
389 1 : break;
390 : }
391 :
392 0 : default:
393 0 : _gnutls_debug_log("requested writing public key of unsupported type %u\n", (unsigned)pk);
394 0 : 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
420 3 : 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 3 : int ret;
426 3 : struct p11_kit_uri *info = NULL;
427 3 : ck_rv_t rv;
428 3 : size_t id_size;
429 3 : uint8_t id[20];
430 3 : struct ck_attribute a[MAX_ASIZE];
431 3 : gnutls_pk_algorithm_t pk;
432 3 : ck_object_class_t class = CKO_PUBLIC_KEY;
433 3 : ck_object_handle_t ctx;
434 3 : unsigned a_val;
435 3 : ck_key_type_t type;
436 3 : struct pkcs11_session_info sinfo;
437 :
438 3 : PKCS11_CHECK_INIT;
439 :
440 3 : ret = pkcs11_url_to_info(token_url, &info, 0);
441 3 : if (ret < 0) {
442 0 : gnutls_assert();
443 0 : return ret;
444 : }
445 :
446 3 : ret =
447 3 : pkcs11_open_session(&sinfo, NULL, info,
448 : SESSION_WRITE |
449 3 : pkcs11_obj_flags_to_int(flags));
450 3 : p11_kit_uri_free(info);
451 :
452 3 : if (ret < 0) {
453 0 : gnutls_assert();
454 0 : return ret;
455 : }
456 :
457 3 : a[0].type = CKA_CLASS;
458 3 : a[0].value = &class;
459 3 : a[0].value_len = sizeof(class);
460 :
461 3 : a[1].type = CKA_TOKEN;
462 3 : a[1].value = (void *) &tval;
463 3 : a[1].value_len = sizeof(tval);
464 :
465 3 : a_val = 2;
466 :
467 3 : ret = add_pubkey(pubkey, a, &a_val);
468 3 : if (ret < 0) {
469 0 : gnutls_assert();
470 0 : goto cleanup;
471 : }
472 :
473 3 : if (label) {
474 3 : a[a_val].type = CKA_LABEL;
475 3 : a[a_val].value = (void *) label;
476 3 : a[a_val].value_len = strlen(label);
477 3 : a_val++;
478 : }
479 :
480 3 : pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
481 3 : type = pk_to_key_type(pk);
482 3 : FIX_KEY_USAGE(pk, key_usage);
483 :
484 3 : a[a_val].type = CKA_KEY_TYPE;
485 3 : a[a_val].value = &type;
486 3 : a[a_val].value_len = sizeof(type);
487 3 : a_val++;
488 :
489 3 : a[a_val].type = CKA_ID;
490 3 : if (cid == NULL || cid->size == 0) {
491 3 : id_size = sizeof(id);
492 3 : ret = gnutls_pubkey_get_key_id(pubkey, 0, id, &id_size);
493 3 : if (ret < 0) {
494 0 : gnutls_assert();
495 0 : goto cleanup;
496 : }
497 :
498 3 : a[a_val].value = id;
499 3 : a[a_val].value_len = id_size;
500 : } else {
501 0 : a[a_val].value = cid->data;
502 0 : a[a_val].value_len = cid->size;
503 : }
504 3 : a_val++;
505 :
506 3 : mark_flags(flags, a, &a_val, sinfo.trusted);
507 :
508 3 : a[a_val].type = CKA_VERIFY;
509 3 : if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
510 3 : a[a_val].value = (void*)&tval;
511 3 : a[a_val].value_len = sizeof(tval);
512 : } else {
513 0 : a[a_val].value = (void*)&fval;
514 0 : a[a_val].value_len = sizeof(fval);
515 : }
516 3 : a_val++;
517 :
518 3 : if (pk == GNUTLS_PK_RSA) {
519 1 : a[a_val].type = CKA_ENCRYPT;
520 1 : if (key_usage & (GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_DECIPHER_ONLY)) {
521 1 : a[a_val].value = (void*)&tval;
522 1 : a[a_val].value_len = sizeof(tval);
523 : } else {
524 0 : a[a_val].value = (void*)&fval;
525 0 : a[a_val].value_len = sizeof(fval);
526 : }
527 1 : a_val++;
528 : }
529 :
530 3 : rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
531 3 : if (rv != CKR_OK) {
532 0 : gnutls_assert();
533 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
534 0 : ret = pkcs11_rv_to_err(rv);
535 0 : goto cleanup;
536 : }
537 :
538 : /* generated!
539 : */
540 :
541 : ret = 0;
542 :
543 3 : cleanup:
544 3 : clean_pubkey(a, a_val);
545 3 : pkcs11_close_session(&sinfo);
546 3 : 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
570 0 : 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 0 : int ret;
577 0 : struct p11_kit_uri *info = NULL;
578 0 : ck_rv_t rv;
579 0 : struct ck_attribute a[MAX_ASIZE];
580 0 : ck_object_handle_t ctx;
581 0 : unsigned a_vals;
582 0 : struct pkcs11_session_info sinfo;
583 0 : ck_object_class_t class;
584 0 : gnutls_datum_t spki = {NULL, 0};
585 :
586 0 : PKCS11_CHECK_INIT;
587 :
588 0 : ret = pkcs11_url_to_info(token_url, &info, 0);
589 0 : if (ret < 0) {
590 0 : gnutls_assert();
591 0 : return ret;
592 : }
593 :
594 0 : ret =
595 0 : pkcs11_open_session(&sinfo, NULL, info,
596 : SESSION_WRITE |
597 0 : pkcs11_obj_flags_to_int(flags));
598 0 : p11_kit_uri_free(info);
599 :
600 0 : if (ret < 0) {
601 0 : gnutls_assert();
602 0 : return ret;
603 : }
604 :
605 0 : ret = x509_crt_to_raw_pubkey(crt, &spki);
606 0 : if (ret < 0) {
607 0 : gnutls_assert();
608 0 : goto cleanup;
609 : }
610 :
611 0 : class = CKO_X_CERTIFICATE_EXTENSION;
612 0 : a_vals = 0;
613 0 : a[a_vals].type = CKA_CLASS;
614 0 : a[a_vals].value = &class;
615 0 : a[a_vals++].value_len = sizeof(class);
616 :
617 0 : a[a_vals].type = CKA_PUBLIC_KEY_INFO;
618 0 : a[a_vals].value = spki.data;
619 0 : a[a_vals++].value_len = spki.size;
620 :
621 0 : a[a_vals].type = CKA_VALUE;
622 0 : a[a_vals].value = data->data;
623 0 : a[a_vals++].value_len = data->size;
624 :
625 0 : a[a_vals].type = CKA_TOKEN;
626 0 : a[a_vals].value = (void *) &tval;
627 0 : a[a_vals++].value_len = sizeof(tval);
628 :
629 0 : if (label) {
630 0 : a[a_vals].type = CKA_LABEL;
631 0 : a[a_vals].value = (void *) label;
632 0 : a[a_vals++].value_len = strlen(label);
633 : }
634 :
635 0 : rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_vals, &ctx);
636 0 : if (rv != CKR_OK) {
637 0 : gnutls_assert();
638 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
639 0 : ret = pkcs11_rv_to_err(rv);
640 0 : goto cleanup;
641 : }
642 :
643 : ret = 0;
644 :
645 0 : cleanup:
646 0 : pkcs11_close_session(&sinfo);
647 0 : gnutls_free(spki.data);
648 0 : 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
673 32 : 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 32 : int ret;
680 32 : struct p11_kit_uri *info = NULL;
681 32 : ck_rv_t rv;
682 32 : size_t id_size;
683 32 : uint8_t id[20];
684 32 : struct ck_attribute a[32];
685 32 : ck_object_class_t class = CKO_PRIVATE_KEY;
686 32 : ck_object_handle_t ctx;
687 32 : ck_key_type_t type;
688 32 : int a_val;
689 32 : gnutls_pk_algorithm_t pk;
690 32 : gnutls_datum_t p, q, g, y, x;
691 32 : gnutls_datum_t m, e, d, u, exp1, exp2;
692 32 : struct pkcs11_session_info sinfo;
693 :
694 32 : PKCS11_CHECK_INIT;
695 :
696 32 : memset(&p, 0, sizeof(p));
697 32 : memset(&q, 0, sizeof(q));
698 32 : memset(&g, 0, sizeof(g));
699 32 : memset(&y, 0, sizeof(y));
700 32 : memset(&x, 0, sizeof(x));
701 32 : memset(&m, 0, sizeof(m));
702 32 : memset(&e, 0, sizeof(e));
703 32 : memset(&d, 0, sizeof(d));
704 32 : memset(&u, 0, sizeof(u));
705 32 : memset(&exp1, 0, sizeof(exp1));
706 32 : memset(&exp2, 0, sizeof(exp2));
707 :
708 32 : ret = pkcs11_url_to_info(token_url, &info, 0);
709 32 : if (ret < 0) {
710 0 : gnutls_assert();
711 0 : return ret;
712 : }
713 :
714 32 : ret =
715 32 : pkcs11_open_session(&sinfo, NULL, info,
716 : SESSION_WRITE |
717 32 : pkcs11_obj_flags_to_int(flags));
718 32 : p11_kit_uri_free(info);
719 :
720 32 : if (ret < 0) {
721 0 : gnutls_assert();
722 0 : return ret;
723 : }
724 :
725 32 : pk = gnutls_x509_privkey_get_pk_algorithm(key);
726 32 : FIX_KEY_USAGE(pk, key_usage);
727 :
728 32 : a_val = 0;
729 32 : a[a_val].type = CKA_CLASS;
730 32 : a[a_val].value = &class;
731 32 : a[a_val].value_len = sizeof(class);
732 32 : a_val++;
733 :
734 32 : a[a_val].type = CKA_ID;
735 32 : if (cid == NULL || cid->size == 0) {
736 32 : id_size = sizeof(id);
737 32 : ret = gnutls_x509_privkey_get_key_id(key, 0, id, &id_size);
738 32 : if (ret < 0) {
739 0 : p11_kit_uri_free(info);
740 0 : gnutls_assert();
741 0 : return ret;
742 : }
743 :
744 32 : a[a_val].value = id;
745 32 : a[a_val].value_len = id_size;
746 : } else {
747 0 : a[a_val].value = cid->data;
748 0 : a[a_val].value_len = cid->size;
749 : }
750 32 : a_val++;
751 :
752 32 : a[a_val].type = CKA_SIGN;
753 32 : if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE) {
754 30 : a[a_val].value = (void*)&tval;
755 30 : a[a_val].value_len = sizeof(tval);
756 : } else {
757 2 : a[a_val].value = (void*)&fval;
758 2 : a[a_val].value_len = sizeof(fval);
759 : }
760 32 : a_val++;
761 :
762 32 : if (pk == GNUTLS_PK_RSA) {
763 20 : a[a_val].type = CKA_DECRYPT;
764 20 : if ((key_usage & (GNUTLS_KEY_ENCIPHER_ONLY|GNUTLS_KEY_DECIPHER_ONLY)) ||
765 : (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT)) {
766 12 : a[a_val].value = (void*)&tval;
767 12 : a[a_val].value_len = sizeof(tval);
768 : } else {
769 8 : a[a_val].value = (void*)&fval;
770 8 : a[a_val].value_len = sizeof(fval);
771 : }
772 : a_val++;
773 : }
774 :
775 32 : a[a_val].type = CKA_TOKEN;
776 32 : a[a_val].value = (void *) &tval;
777 32 : a[a_val].value_len = sizeof(tval);
778 32 : a_val++;
779 :
780 : /* a private key is set always as private unless
781 : * requested otherwise
782 : */
783 32 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) {
784 0 : a[a_val].type = CKA_PRIVATE;
785 0 : a[a_val].value = (void *) &fval;
786 0 : a[a_val].value_len = sizeof(fval);
787 0 : a_val++;
788 : } else {
789 32 : a[a_val].type = CKA_PRIVATE;
790 32 : a[a_val].value = (void *) &tval;
791 32 : a[a_val].value_len = sizeof(tval);
792 32 : a_val++;
793 : }
794 :
795 32 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_ALWAYS_AUTH) {
796 0 : a[a_val].type = CKA_ALWAYS_AUTHENTICATE;
797 0 : a[a_val].value = (void *) &tval;
798 0 : a[a_val].value_len = sizeof(tval);
799 0 : a_val++;
800 : }
801 :
802 32 : if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_EXTRACTABLE) {
803 0 : a[a_val].type = CKA_EXTRACTABLE;
804 0 : a[a_val].value = (void *) &tval;
805 0 : a[a_val].value_len = sizeof(tval);
806 0 : (a_val)++;
807 : } else {
808 32 : a[a_val].type = CKA_EXTRACTABLE;
809 32 : a[a_val].value = (void *) &fval;
810 32 : a[a_val].value_len = sizeof(fval);
811 32 : (a_val)++;
812 : }
813 :
814 32 : if (label) {
815 32 : a[a_val].type = CKA_LABEL;
816 32 : a[a_val].value = (void *) label;
817 32 : a[a_val].value_len = strlen(label);
818 32 : a_val++;
819 : }
820 :
821 32 : if (!(flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_SENSITIVE)) {
822 32 : a[a_val].type = CKA_SENSITIVE;
823 32 : a[a_val].value = (void *) &tval;
824 32 : a[a_val].value_len = sizeof(tval);
825 32 : a_val++;
826 : } else {
827 0 : a[a_val].type = CKA_SENSITIVE;
828 0 : a[a_val].value = (void *) &fval;
829 0 : a[a_val].value_len = sizeof(fval);
830 0 : a_val++;
831 : }
832 :
833 32 : switch (pk) {
834 22 : case GNUTLS_PK_RSA:
835 : case GNUTLS_PK_RSA_PSS:
836 : {
837 :
838 22 : ret = _gnutls_params_get_rsa_raw(&key->params, &m, &e, &d, &p,
839 : &q, &u, &exp1, &exp2,
840 : GNUTLS_EXPORT_FLAG_NO_LZ);
841 22 : if (ret < 0) {
842 0 : gnutls_assert();
843 0 : goto cleanup;
844 : }
845 :
846 22 : type = CKK_RSA;
847 :
848 22 : a[a_val].type = CKA_MODULUS;
849 22 : a[a_val].value = m.data;
850 22 : a[a_val].value_len = m.size;
851 22 : a_val++;
852 :
853 22 : a[a_val].type = CKA_PUBLIC_EXPONENT;
854 22 : a[a_val].value = e.data;
855 22 : a[a_val].value_len = e.size;
856 22 : a_val++;
857 :
858 22 : a[a_val].type = CKA_PRIVATE_EXPONENT;
859 22 : a[a_val].value = d.data;
860 22 : a[a_val].value_len = d.size;
861 22 : a_val++;
862 :
863 22 : a[a_val].type = CKA_PRIME_1;
864 22 : a[a_val].value = p.data;
865 22 : a[a_val].value_len = p.size;
866 22 : a_val++;
867 :
868 22 : a[a_val].type = CKA_PRIME_2;
869 22 : a[a_val].value = q.data;
870 22 : a[a_val].value_len = q.size;
871 22 : a_val++;
872 :
873 22 : a[a_val].type = CKA_COEFFICIENT;
874 22 : a[a_val].value = u.data;
875 22 : a[a_val].value_len = u.size;
876 22 : a_val++;
877 :
878 22 : a[a_val].type = CKA_EXPONENT_1;
879 22 : a[a_val].value = exp1.data;
880 22 : a[a_val].value_len = exp1.size;
881 22 : a_val++;
882 :
883 22 : a[a_val].type = CKA_EXPONENT_2;
884 22 : a[a_val].value = exp2.data;
885 22 : a[a_val].value_len = exp2.size;
886 22 : a_val++;
887 :
888 22 : break;
889 : }
890 1 : case GNUTLS_PK_DSA:
891 : {
892 1 : ret = _gnutls_params_get_dsa_raw(&key->params, &p, &q, &g, &y, &x,
893 : GNUTLS_EXPORT_FLAG_NO_LZ);
894 1 : if (ret < 0) {
895 0 : gnutls_assert();
896 0 : goto cleanup;
897 : }
898 :
899 1 : type = CKK_DSA;
900 :
901 1 : a[a_val].type = CKA_PRIME;
902 1 : a[a_val].value = p.data;
903 1 : a[a_val].value_len = p.size;
904 1 : a_val++;
905 :
906 1 : a[a_val].type = CKA_SUBPRIME;
907 1 : a[a_val].value = q.data;
908 1 : a[a_val].value_len = q.size;
909 1 : a_val++;
910 :
911 1 : a[a_val].type = CKA_BASE;
912 1 : a[a_val].value = g.data;
913 1 : a[a_val].value_len = g.size;
914 1 : a_val++;
915 :
916 1 : a[a_val].type = CKA_VALUE;
917 1 : a[a_val].value = x.data;
918 1 : a[a_val].value_len = x.size;
919 1 : a_val++;
920 :
921 1 : break;
922 : }
923 6 : case GNUTLS_PK_EC:
924 : {
925 6 : ret =
926 6 : _gnutls_x509_write_ecc_params(key->params.curve,
927 : &p);
928 6 : if (ret < 0) {
929 0 : gnutls_assert();
930 0 : goto cleanup;
931 : }
932 :
933 6 : ret =
934 6 : _gnutls_mpi_dprint(key->params.
935 : params[ECC_K], &x);
936 6 : if (ret < 0) {
937 0 : gnutls_assert();
938 0 : goto cleanup;
939 : }
940 :
941 6 : type = CKK_ECDSA;
942 :
943 6 : a[a_val].type = CKA_EC_PARAMS;
944 6 : a[a_val].value = p.data;
945 6 : a[a_val].value_len = p.size;
946 6 : a_val++;
947 :
948 6 : a[a_val].type = CKA_VALUE;
949 6 : a[a_val].value = x.data;
950 6 : a[a_val].value_len = x.size;
951 6 : a_val++;
952 :
953 6 : break;
954 : }
955 : #ifdef HAVE_CKM_EDDSA
956 3 : case GNUTLS_PK_EDDSA_ED25519:
957 : {
958 3 : ret =
959 3 : _gnutls_x509_write_ecc_params(key->params.curve,
960 : &p);
961 3 : if (ret < 0) {
962 0 : gnutls_assert();
963 0 : goto cleanup;
964 : }
965 :
966 3 : type = CKK_EC_EDWARDS;
967 :
968 3 : a[a_val].type = CKA_EC_PARAMS;
969 3 : a[a_val].value = p.data;
970 3 : a[a_val].value_len = p.size;
971 3 : a_val++;
972 :
973 3 : a[a_val].type = CKA_VALUE;
974 3 : a[a_val].value = key->params.raw_priv.data;
975 3 : a[a_val].value_len = key->params.raw_priv.size;
976 3 : a_val++;
977 :
978 3 : break;
979 : }
980 : #endif
981 0 : default:
982 0 : gnutls_assert();
983 0 : ret = GNUTLS_E_INVALID_REQUEST;
984 0 : goto cleanup;
985 : }
986 :
987 32 : a[a_val].type = CKA_KEY_TYPE;
988 32 : a[a_val].value = &type;
989 32 : a[a_val].value_len = sizeof(type);
990 32 : a_val++;
991 :
992 32 : rv = pkcs11_create_object(sinfo.module, sinfo.pks, a, a_val, &ctx);
993 32 : if (rv != CKR_OK) {
994 0 : gnutls_assert();
995 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
996 0 : ret = pkcs11_rv_to_err(rv);
997 0 : goto cleanup;
998 : }
999 :
1000 : ret = 0;
1001 :
1002 32 : cleanup:
1003 32 : switch (pk) {
1004 22 : case GNUTLS_PK_RSA_PSS:
1005 : case GNUTLS_PK_RSA:
1006 : {
1007 22 : gnutls_free(m.data);
1008 22 : gnutls_free(e.data);
1009 22 : gnutls_free(d.data);
1010 22 : gnutls_free(p.data);
1011 22 : gnutls_free(q.data);
1012 22 : gnutls_free(u.data);
1013 22 : gnutls_free(exp1.data);
1014 22 : gnutls_free(exp2.data);
1015 22 : break;
1016 : }
1017 1 : case GNUTLS_PK_DSA:
1018 : {
1019 1 : gnutls_free(p.data);
1020 1 : gnutls_free(q.data);
1021 1 : gnutls_free(g.data);
1022 1 : gnutls_free(y.data);
1023 1 : gnutls_free(x.data);
1024 1 : break;
1025 : }
1026 9 : case GNUTLS_PK_EC:
1027 : case GNUTLS_PK_EDDSA_ED25519:
1028 : {
1029 9 : gnutls_free(p.data);
1030 9 : gnutls_free(x.data);
1031 9 : break;
1032 : }
1033 0 : default:
1034 0 : gnutls_assert();
1035 : ret = GNUTLS_E_INVALID_REQUEST;
1036 : break;
1037 : }
1038 :
1039 32 : if (sinfo.pks != 0)
1040 32 : 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
1052 25 : 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 25 : struct delete_data_st *find_data = input;
1057 25 : struct ck_attribute a[4];
1058 25 : struct ck_attribute *attr;
1059 25 : ck_object_class_t class;
1060 25 : ck_certificate_type_t type = (ck_certificate_type_t) - 1;
1061 25 : ck_rv_t rv;
1062 25 : ck_object_handle_t ctx;
1063 25 : unsigned long count, a_vals;
1064 25 : int found = 0, ret;
1065 :
1066 25 : if (tinfo == NULL) { /* we don't support multiple calls */
1067 0 : gnutls_assert();
1068 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1069 : }
1070 :
1071 : /* do not bother reading the token if basic fields do not match
1072 : */
1073 50 : if (!p11_kit_uri_match_module_info(find_data->info, lib_info) ||
1074 25 : !p11_kit_uri_match_token_info(find_data->info, tinfo)) {
1075 0 : gnutls_assert();
1076 0 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1077 : }
1078 :
1079 : /* Find objects with given class and type */
1080 25 : class = CKO_CERTIFICATE; /* default */
1081 25 : a_vals = 0;
1082 :
1083 25 : attr = p11_kit_uri_get_attribute(find_data->info, CKA_CLASS);
1084 25 : if (attr != NULL) {
1085 9 : if (attr->value
1086 9 : && attr->value_len == sizeof(ck_object_class_t))
1087 9 : class = *((ck_object_class_t *) attr->value);
1088 9 : if (class == CKO_CERTIFICATE)
1089 1 : type = CKC_X_509;
1090 :
1091 9 : a[a_vals].type = CKA_CLASS;
1092 9 : a[a_vals].value = &class;
1093 9 : a[a_vals].value_len = sizeof(class);
1094 9 : a_vals++;
1095 : }
1096 :
1097 25 : attr = p11_kit_uri_get_attribute(find_data->info, CKA_ID);
1098 25 : if (attr != NULL) {
1099 0 : memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1100 0 : a_vals++;
1101 : }
1102 :
1103 25 : if (type != (ck_certificate_type_t) - 1) {
1104 1 : a[a_vals].type = CKA_CERTIFICATE_TYPE;
1105 1 : a[a_vals].value = &type;
1106 1 : a[a_vals].value_len = sizeof type;
1107 1 : a_vals++;
1108 : }
1109 :
1110 25 : attr = p11_kit_uri_get_attribute(find_data->info, CKA_LABEL);
1111 25 : if (attr != NULL) {
1112 25 : memcpy(a + a_vals, attr, sizeof(struct ck_attribute));
1113 25 : a_vals++;
1114 : }
1115 :
1116 25 : rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a,
1117 : a_vals);
1118 25 : if (rv != CKR_OK) {
1119 0 : gnutls_assert();
1120 0 : _gnutls_debug_log("p11: FindObjectsInit failed.\n");
1121 0 : ret = pkcs11_rv_to_err(rv);
1122 0 : goto cleanup;
1123 : }
1124 :
1125 50 : while (pkcs11_find_objects
1126 : (sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK
1127 50 : && count == 1) {
1128 25 : rv = pkcs11_destroy_object(sinfo->module, sinfo->pks, ctx);
1129 25 : if (rv != CKR_OK) {
1130 0 : _gnutls_debug_log
1131 : ("p11: Cannot destroy object: %s\n",
1132 : pkcs11_strerror(rv));
1133 : } else {
1134 25 : find_data->deleted++;
1135 : }
1136 :
1137 : found = 1;
1138 : }
1139 :
1140 25 : if (found == 0) {
1141 0 : gnutls_assert();
1142 : ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1143 : } else {
1144 : ret = 0;
1145 : }
1146 :
1147 25 : cleanup:
1148 25 : pkcs11_find_objects_final(sinfo);
1149 :
1150 25 : 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 : **/
1167 25 : int gnutls_pkcs11_delete_url(const char *object_url, unsigned int flags)
1168 : {
1169 25 : int ret;
1170 25 : struct delete_data_st find_data;
1171 :
1172 25 : PKCS11_CHECK_INIT;
1173 :
1174 25 : memset(&find_data, 0, sizeof(find_data));
1175 :
1176 25 : ret = pkcs11_url_to_info(object_url, &find_data.info, 0);
1177 25 : if (ret < 0) {
1178 0 : gnutls_assert();
1179 0 : return ret;
1180 : }
1181 :
1182 25 : ret =
1183 25 : _pkcs11_traverse_tokens(delete_obj_url_cb, &find_data,
1184 : find_data.info, NULL,
1185 : SESSION_WRITE |
1186 25 : pkcs11_obj_flags_to_int(flags));
1187 25 : p11_kit_uri_free(find_data.info);
1188 :
1189 25 : if (ret < 0) {
1190 0 : gnutls_assert();
1191 0 : return ret;
1192 : }
1193 :
1194 25 : 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
1212 100 : gnutls_pkcs11_token_init(const char *token_url,
1213 : const char *so_pin, const char *label)
1214 : {
1215 100 : int ret;
1216 100 : struct p11_kit_uri *info = NULL;
1217 100 : ck_rv_t rv;
1218 100 : struct ck_function_list *module;
1219 100 : ck_slot_id_t slot;
1220 100 : char flabel[32];
1221 :
1222 100 : PKCS11_CHECK_INIT;
1223 :
1224 100 : ret = pkcs11_url_to_info(token_url, &info, 0);
1225 100 : if (ret < 0) {
1226 0 : gnutls_assert();
1227 0 : return ret;
1228 : }
1229 :
1230 100 : ret = pkcs11_find_slot(&module, &slot, info, NULL, NULL, NULL);
1231 100 : p11_kit_uri_free(info);
1232 :
1233 100 : if (ret < 0) {
1234 0 : gnutls_assert();
1235 0 : return ret;
1236 : }
1237 :
1238 : /* so it seems memset has other uses than zeroing! */
1239 100 : memset(flabel, ' ', sizeof(flabel));
1240 100 : if (label != NULL)
1241 100 : memcpy(flabel, label, strlen(label));
1242 :
1243 100 : rv = pkcs11_init_token(module, slot, (uint8_t *) so_pin,
1244 : strlen(so_pin), (uint8_t *) flabel);
1245 100 : if (rv != CKR_OK) {
1246 0 : gnutls_assert();
1247 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
1248 0 : 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
1274 19 : gnutls_pkcs11_token_set_pin(const char *token_url,
1275 : const char *oldpin,
1276 : const char *newpin, unsigned int flags)
1277 : {
1278 19 : int ret;
1279 19 : struct p11_kit_uri *info = NULL;
1280 19 : ck_rv_t rv;
1281 19 : unsigned int ses_flags;
1282 19 : struct pkcs11_session_info sinfo;
1283 :
1284 19 : PKCS11_CHECK_INIT;
1285 :
1286 19 : ret = pkcs11_url_to_info(token_url, &info, 0);
1287 19 : if (ret < 0) {
1288 0 : gnutls_assert();
1289 0 : return ret;
1290 : }
1291 :
1292 19 : if (((flags & GNUTLS_PIN_USER) && oldpin == NULL) ||
1293 4 : (flags & GNUTLS_PIN_SO))
1294 : ses_flags = SESSION_WRITE | SESSION_LOGIN | SESSION_SO;
1295 : else
1296 0 : ses_flags = SESSION_WRITE | SESSION_LOGIN;
1297 :
1298 19 : ret = pkcs11_open_session(&sinfo, NULL, info, ses_flags);
1299 19 : p11_kit_uri_free(info);
1300 :
1301 19 : if (ret < 0) {
1302 0 : gnutls_assert();
1303 0 : return ret;
1304 : }
1305 :
1306 19 : if (oldpin == NULL && !(flags & GNUTLS_PIN_SO)) {
1307 : /* This changes only the user PIN */
1308 15 : rv = pkcs11_init_pin(sinfo.module, sinfo.pks,
1309 : (uint8_t *) newpin, strlen(newpin));
1310 15 : if (rv != CKR_OK) {
1311 0 : gnutls_assert();
1312 0 : _gnutls_debug_log("p11: %s\n",
1313 : pkcs11_strerror(rv));
1314 0 : ret = pkcs11_rv_to_err(rv);
1315 0 : goto finish;
1316 : }
1317 : } else {
1318 4 : struct p11_kit_pin *pin;
1319 4 : unsigned oldpin_size;
1320 :
1321 4 : oldpin_size = L(oldpin);
1322 :
1323 4 : if (!(sinfo.tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)) {
1324 4 : if (newpin == NULL)
1325 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1326 :
1327 4 : if (oldpin == NULL) {
1328 4 : struct pin_info_st pin_info;
1329 4 : memset(&pin_info, 0, sizeof(pin_info));
1330 :
1331 4 : ret = pkcs11_retrieve_pin(&pin_info, info, &sinfo.tinfo, 0, CKU_SO, &pin);
1332 4 : if (ret < 0) {
1333 0 : gnutls_assert();
1334 0 : goto finish;
1335 : }
1336 4 : oldpin = (const char*)p11_kit_pin_get_value(pin, NULL);
1337 4 : oldpin_size = p11_kit_pin_get_length(pin);
1338 : }
1339 : }
1340 :
1341 8 : rv = pkcs11_set_pin(sinfo.module, sinfo.pks,
1342 : oldpin, oldpin_size,
1343 4 : newpin, L(newpin));
1344 4 : if (rv != CKR_OK) {
1345 0 : gnutls_assert();
1346 0 : _gnutls_debug_log("p11: %s\n",
1347 : pkcs11_strerror(rv));
1348 0 : ret = pkcs11_rv_to_err(rv);
1349 0 : goto finish;
1350 : }
1351 : }
1352 :
1353 : ret = 0;
1354 :
1355 19 : finish:
1356 19 : pkcs11_close_session(&sinfo);
1357 19 : 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
1375 0 : gnutls_pkcs11_token_get_random(const char *token_url,
1376 : void *rnddata, size_t len)
1377 : {
1378 0 : int ret;
1379 0 : struct p11_kit_uri *info = NULL;
1380 0 : ck_rv_t rv;
1381 0 : struct pkcs11_session_info sinfo;
1382 :
1383 0 : PKCS11_CHECK_INIT;
1384 :
1385 0 : ret = pkcs11_url_to_info(token_url, &info, 0);
1386 0 : if (ret < 0) {
1387 0 : gnutls_assert();
1388 0 : return ret;
1389 : }
1390 :
1391 0 : ret = pkcs11_open_session(&sinfo, NULL, info, 0);
1392 0 : p11_kit_uri_free(info);
1393 :
1394 0 : if (ret < 0) {
1395 0 : gnutls_assert();
1396 0 : return ret;
1397 : }
1398 :
1399 0 : rv = _gnutls_pkcs11_get_random(sinfo.module, sinfo.pks, rnddata, len);
1400 0 : if (rv != CKR_OK) {
1401 0 : gnutls_assert();
1402 0 : _gnutls_debug_log("p11: %s\n", pkcs11_strerror(rv));
1403 0 : ret = pkcs11_rv_to_err(rv);
1404 0 : goto finish;
1405 : }
1406 :
1407 : ret = 0;
1408 :
1409 0 : finish:
1410 0 : pkcs11_close_session(&sinfo);
1411 0 : 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
|