1 | /* |
2 | * GnuTLS PKCS#11 support |
3 | * Copyright (C) 2010-2012 Free Software Foundation, Inc. |
4 | * Copyright (C) 2012 Nikos Mavrogiannopoulos |
5 | * |
6 | * Author: Nikos Mavrogiannopoulos |
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 <http://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 <gnutls_errors.h> |
27 | #include <gnutls_datum.h> |
28 | #include <pkcs11_int.h> |
29 | #include <gnutls/abstract.h> |
30 | #include <gnutls_pk.h> |
31 | #include <x509_int.h> |
32 | #include <openpgp/openpgp_int.h> |
33 | #include <openpgp/gnutls_openpgp.h> |
34 | #include <gnutls_sig.h> |
35 | #include <algorithms.h> |
36 | #include <abstract_int.h> |
37 | |
38 | /** |
39 | * gnutls_privkey_get_type: |
40 | * @key: should contain a #gnutls_privkey_t structure |
41 | * |
42 | * This function will return the type of the private key. This is |
43 | * actually the type of the subsystem used to set this private key. |
44 | * |
45 | * Returns: a member of the #gnutls_privkey_type_t enumeration on |
46 | * success, or a negative error code on error. |
47 | * |
48 | * Since: 2.12.0 |
49 | **/ |
50 | gnutls_privkey_type_t |
51 | gnutls_privkey_get_type (gnutls_privkey_t key) |
52 | { |
53 | return key->type; |
54 | } |
55 | |
56 | /** |
57 | * gnutls_privkey_get_pk_algorithm: |
58 | * @key: should contain a #gnutls_privkey_t structure |
59 | * @bits: If set will return the number of bits of the parameters (may be NULL) |
60 | * |
61 | * This function will return the public key algorithm of a private |
62 | * key and if possible will return a number of bits that indicates |
63 | * the security parameter of the key. |
64 | * |
65 | * Returns: a member of the #gnutls_pk_algorithm_t enumeration on |
66 | * success, or a negative error code on error. |
67 | * |
68 | * Since: 2.12.0 |
69 | **/ |
70 | int |
71 | gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key, unsigned int *bits) |
72 | { |
73 | switch (key->type) |
74 | { |
75 | #ifdef ENABLE_OPENPGP |
76 | case GNUTLS_PRIVKEY_OPENPGP: |
77 | return gnutls_openpgp_privkey_get_pk_algorithm (key->key.openpgp, bits); |
78 | #endif |
79 | #ifdef ENABLE_PKCS11 |
80 | case GNUTLS_PRIVKEY_PKCS11: |
81 | return gnutls_pkcs11_privkey_get_pk_algorithm (key->key.pkcs11, bits); |
82 | #endif |
83 | case GNUTLS_PRIVKEY_X509: |
84 | if (bits) |
85 | *bits = _gnutls_mpi_get_nbits (key->key.x509->params.params[0]); |
86 | return gnutls_x509_privkey_get_pk_algorithm (key->key.x509); |
87 | case GNUTLS_PRIVKEY_EXT: |
88 | if (bits) |
89 | *bits = 0; |
90 | return key->pk_algorithm; |
91 | default: |
92 | gnutls_assert (); |
93 | return GNUTLS_E_INVALID_REQUEST; |
94 | } |
95 | |
96 | } |
97 | |
98 | static int |
99 | privkey_to_pubkey (gnutls_pk_algorithm_t pk, |
100 | const gnutls_pk_params_st* priv, |
101 | gnutls_pk_params_st* pub) |
102 | { |
103 | int ret; |
104 | |
105 | switch (pk) |
106 | { |
107 | case GNUTLS_PK_RSA: |
108 | pub->params[0] = _gnutls_mpi_copy (priv->params[0]); |
109 | pub->params[1] = _gnutls_mpi_copy (priv->params[1]); |
110 | |
111 | pub->params_nr = RSA_PUBLIC_PARAMS; |
112 | |
113 | if (pub->params[0] == NULL || pub->params[1] == NULL) |
114 | { |
115 | gnutls_assert (); |
116 | ret = GNUTLS_E_MEMORY_ERROR; |
117 | goto cleanup; |
118 | } |
119 | |
120 | break; |
121 | case GNUTLS_PK_DSA: |
122 | pub->params[0] = _gnutls_mpi_copy (priv->params[0]); |
123 | pub->params[1] = _gnutls_mpi_copy (priv->params[1]); |
124 | pub->params[2] = _gnutls_mpi_copy (priv->params[2]); |
125 | pub->params[3] = _gnutls_mpi_copy (priv->params[3]); |
126 | |
127 | pub->params_nr = DSA_PUBLIC_PARAMS; |
128 | |
129 | if (pub->params[0] == NULL || pub->params[1] == NULL || |
130 | pub->params[2] == NULL || pub->params[3] == NULL) |
131 | { |
132 | gnutls_assert (); |
133 | ret = GNUTLS_E_MEMORY_ERROR; |
134 | goto cleanup; |
135 | } |
136 | |
137 | break; |
138 | case GNUTLS_PK_EC: |
139 | pub->params[ECC_X] = _gnutls_mpi_copy (priv->params[ECC_X]); |
140 | pub->params[ECC_Y] = _gnutls_mpi_copy (priv->params[ECC_Y]); |
141 | |
142 | pub->params_nr = ECC_PUBLIC_PARAMS; |
143 | pub->flags = priv->flags; |
144 | |
145 | if (pub->params[ECC_X] == NULL || pub->params[ECC_Y] == NULL) |
146 | { |
147 | gnutls_assert (); |
148 | ret = GNUTLS_E_MEMORY_ERROR; |
149 | goto cleanup; |
150 | } |
151 | |
152 | break; |
153 | default: |
154 | gnutls_assert (); |
155 | return GNUTLS_E_INVALID_REQUEST; |
156 | } |
157 | |
158 | return 0; |
159 | cleanup: |
160 | gnutls_pk_params_release(pub); |
161 | return ret; |
162 | } |
163 | |
164 | |
165 | /* Returns the public key of the private key (if possible) |
166 | */ |
167 | int |
168 | _gnutls_privkey_get_public_mpis (gnutls_privkey_t key, |
169 | gnutls_pk_params_st * params) |
170 | { |
171 | int ret; |
172 | gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm (key, NULL); |
173 | |
174 | switch (key->type) |
175 | { |
176 | #ifdef ENABLE_OPENPGP |
177 | case GNUTLS_PRIVKEY_OPENPGP: |
178 | { |
179 | gnutls_pk_params_st tmp_params; |
180 | uint32_t kid[2]; |
181 | uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; |
182 | |
183 | ret = |
184 | gnutls_openpgp_privkey_get_preferred_key_id (key->key.openpgp, |
185 | keyid); |
186 | if (ret == 0) |
187 | { |
188 | KEYID_IMPORT (kid, keyid); |
189 | ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, kid, |
190 | &tmp_params); |
191 | } |
192 | else |
193 | ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, NULL, |
194 | &tmp_params); |
195 | |
196 | if (ret < 0) |
197 | { |
198 | gnutls_assert (); |
199 | return ret; |
200 | } |
201 | |
202 | ret = privkey_to_pubkey (pk, |
203 | &tmp_params, |
204 | params); |
205 | |
206 | gnutls_pk_params_release(&tmp_params); |
207 | } |
208 | |
209 | break; |
210 | #endif |
211 | case GNUTLS_PRIVKEY_X509: |
212 | ret = privkey_to_pubkey (pk, |
213 | &key->key.x509->params, |
214 | params); |
215 | break; |
216 | default: |
217 | gnutls_assert (); |
218 | return GNUTLS_E_INVALID_REQUEST; |
219 | } |
220 | |
221 | return ret; |
222 | } |
223 | |
224 | /** |
225 | * gnutls_privkey_init: |
226 | * @key: The structure to be initialized |
227 | * |
228 | * This function will initialize an private key structure. |
229 | * |
230 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
231 | * negative error value. |
232 | * |
233 | * Since: 2.12.0 |
234 | **/ |
235 | int |
236 | gnutls_privkey_init (gnutls_privkey_t * key) |
237 | { |
238 | *key = gnutls_calloc (1, sizeof (struct gnutls_privkey_st)); |
239 | if (*key == NULL) |
240 | { |
241 | gnutls_assert (); |
242 | return GNUTLS_E_MEMORY_ERROR; |
243 | } |
244 | |
245 | return 0; |
246 | } |
247 | |
248 | /** |
249 | * gnutls_privkey_deinit: |
250 | * @key: The structure to be deinitialized |
251 | * |
252 | * This function will deinitialize a private key structure. |
253 | * |
254 | * Since: 2.12.0 |
255 | **/ |
256 | void |
257 | gnutls_privkey_deinit (gnutls_privkey_t key) |
258 | { |
259 | if (key == NULL) return; |
260 | |
261 | if (key->flags & GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE || key->flags & GNUTLS_PRIVKEY_IMPORT_COPY) |
262 | switch (key->type) |
263 | { |
264 | #ifdef ENABLE_OPENPGP |
265 | case GNUTLS_PRIVKEY_OPENPGP: |
266 | gnutls_openpgp_privkey_deinit (key->key.openpgp); |
267 | break; |
268 | #endif |
269 | #ifdef ENABLE_PKCS11 |
270 | case GNUTLS_PRIVKEY_PKCS11: |
271 | gnutls_pkcs11_privkey_deinit (key->key.pkcs11); |
272 | break; |
273 | #endif |
274 | case GNUTLS_PRIVKEY_X509: |
275 | gnutls_x509_privkey_deinit (key->key.x509); |
276 | break; |
277 | case GNUTLS_PRIVKEY_EXT: |
278 | if (key->key.ext.deinit_func != NULL) |
279 | key->key.ext.deinit_func(key, key->key.ext.userdata); |
280 | break; |
281 | default: |
282 | break; |
283 | } |
284 | gnutls_free (key); |
285 | } |
286 | |
287 | /* will fail if the private key contains an actual key. |
288 | */ |
289 | static int check_if_clean(gnutls_privkey_t key) |
290 | { |
291 | if (key->type != 0) |
292 | return GNUTLS_E_INVALID_REQUEST; |
293 | |
294 | return 0; |
295 | } |
296 | |
297 | #ifdef ENABLE_PKCS11 |
298 | |
299 | /** |
300 | * gnutls_privkey_import_pkcs11: |
301 | * @pkey: The private key |
302 | * @key: The private key to be imported |
303 | * @flags: Flags for the import |
304 | * |
305 | * This function will import the given private key to the abstract |
306 | * #gnutls_privkey_t structure. |
307 | * |
308 | * The #gnutls_pkcs11_privkey_t object must not be deallocated |
309 | * during the lifetime of this structure. |
310 | * |
311 | * @flags might be zero or one of %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE |
312 | * and %GNUTLS_PRIVKEY_IMPORT_COPY. |
313 | * |
314 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
315 | * negative error value. |
316 | * |
317 | * Since: 2.12.0 |
318 | **/ |
319 | int |
320 | gnutls_privkey_import_pkcs11 (gnutls_privkey_t pkey, |
321 | gnutls_pkcs11_privkey_t key, unsigned int flags) |
322 | { |
323 | int ret; |
324 | |
325 | ret = check_if_clean(pkey); |
326 | if (ret < 0) |
327 | { |
328 | gnutls_assert(); |
329 | return ret; |
330 | } |
331 | |
332 | if (flags & GNUTLS_PRIVKEY_IMPORT_COPY) |
333 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
334 | |
335 | pkey->key.pkcs11 = key; |
336 | pkey->type = GNUTLS_PRIVKEY_PKCS11; |
337 | pkey->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm (key, NULL); |
338 | pkey->flags = flags; |
339 | |
340 | if (pkey->pin.data) |
341 | gnutls_pkcs11_privkey_set_pin_function(key, pkey->pin.cb, pkey->pin.data); |
342 | |
343 | return 0; |
344 | } |
345 | |
346 | /** |
347 | * gnutls_privkey_import_pkcs11_url: |
348 | * @key: A key of type #gnutls_pubkey_t |
349 | * @url: A PKCS 11 url |
350 | * |
351 | * This function will import a PKCS 11 private key to a #gnutls_private_key_t |
352 | * structure. |
353 | * |
354 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
355 | * negative error value. |
356 | * |
357 | * Since: 3.1.0 |
358 | **/ |
359 | int |
360 | gnutls_privkey_import_pkcs11_url (gnutls_privkey_t key, const char *url) |
361 | { |
362 | gnutls_pkcs11_privkey_t pkey; |
363 | int ret; |
364 | |
365 | ret = gnutls_pkcs11_privkey_init (&pkey); |
366 | if (ret < 0) |
367 | { |
368 | gnutls_assert (); |
369 | return ret; |
370 | } |
371 | |
372 | if (key->pin.cb) |
373 | gnutls_pkcs11_privkey_set_pin_function(pkey, key->pin.cb, key->pin.data); |
374 | |
375 | ret = gnutls_pkcs11_privkey_import_url (pkey, url, 0); |
376 | if (ret < 0) |
377 | { |
378 | gnutls_assert (); |
379 | goto cleanup; |
380 | } |
381 | |
382 | ret = gnutls_privkey_import_pkcs11 (key, pkey, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE); |
383 | if (ret < 0) |
384 | { |
385 | gnutls_assert (); |
386 | goto cleanup; |
387 | } |
388 | |
389 | return 0; |
390 | |
391 | cleanup: |
392 | gnutls_pkcs11_privkey_deinit (pkey); |
393 | |
394 | return ret; |
395 | } |
396 | |
397 | #endif /* ENABLE_PKCS11 */ |
398 | |
399 | /** |
400 | * gnutls_privkey_import_ext: |
401 | * @pkey: The private key |
402 | * @pk: The public key algorithm |
403 | * @userdata: private data to be provided to the callbacks |
404 | * @sign_func: callback for signature operations |
405 | * @decrypt_func: callback for decryption operations |
406 | * @flags: Flags for the import |
407 | * |
408 | * This function will associate the given callbacks with the |
409 | * #gnutls_privkey_t structure. At least one of the two callbacks |
410 | * must be non-null. |
411 | * |
412 | * See also gnutls_privkey_import_ext2(). |
413 | * |
414 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
415 | * negative error value. |
416 | * |
417 | * Since: 3.0 |
418 | **/ |
419 | int |
420 | gnutls_privkey_import_ext (gnutls_privkey_t pkey, |
421 | gnutls_pk_algorithm_t pk, |
422 | void* userdata, |
423 | gnutls_privkey_sign_func sign_func, |
424 | gnutls_privkey_decrypt_func decrypt_func, |
425 | unsigned int flags) |
426 | { |
427 | return gnutls_privkey_import_ext2( pkey, pk, userdata, sign_func, decrypt_func, |
428 | NULL, flags); |
429 | } |
430 | |
431 | /** |
432 | * gnutls_privkey_import_ext2: |
433 | * @pkey: The private key |
434 | * @pk: The public key algorithm |
435 | * @userdata: private data to be provided to the callbacks |
436 | * @sign_func: callback for signature operations |
437 | * @decrypt_func: callback for decryption operations |
438 | * @deinit_func: a deinitialization function |
439 | * @flags: Flags for the import |
440 | * |
441 | * This function will associate the given callbacks with the |
442 | * #gnutls_privkey_t structure. At least one of the two callbacks |
443 | * must be non-null. If a deinitialization function is provided |
444 | * then flags is assumed to contain %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE. |
445 | * |
446 | * Note that the signing function is supposed to "raw" sign data, i.e., |
447 | * without any hashing or preprocessing. In case of RSA the DigestInfo |
448 | * will be provided, and the signing function is expected to do the PKCS #1 |
449 | * 1.5 padding and the exponentiation. |
450 | * |
451 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
452 | * negative error value. |
453 | * |
454 | * Since: 3.1 |
455 | **/ |
456 | int |
457 | gnutls_privkey_import_ext2 (gnutls_privkey_t pkey, |
458 | gnutls_pk_algorithm_t pk, |
459 | void* userdata, |
460 | gnutls_privkey_sign_func sign_func, |
461 | gnutls_privkey_decrypt_func decrypt_func, |
462 | gnutls_privkey_deinit_func deinit_func, |
463 | unsigned int flags) |
464 | { |
465 | int ret; |
466 | |
467 | ret = check_if_clean(pkey); |
468 | if (ret < 0) |
469 | { |
470 | gnutls_assert(); |
471 | return ret; |
472 | } |
473 | |
474 | if (sign_func == NULL && decrypt_func == NULL) |
475 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
476 | |
477 | pkey->key.ext.sign_func = sign_func; |
478 | pkey->key.ext.decrypt_func = decrypt_func; |
479 | pkey->key.ext.deinit_func = deinit_func; |
480 | pkey->key.ext.userdata = userdata; |
481 | pkey->type = GNUTLS_PRIVKEY_EXT; |
482 | pkey->pk_algorithm = pk; |
483 | pkey->flags = flags; |
484 | |
485 | /* Ensure gnutls_privkey_deinit() calls the deinit_func */ |
486 | if (deinit_func) |
487 | pkey->flags |= GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE; |
488 | |
489 | return 0; |
490 | } |
491 | |
492 | /** |
493 | * gnutls_privkey_import_x509: |
494 | * @pkey: The private key |
495 | * @key: The private key to be imported |
496 | * @flags: Flags for the import |
497 | * |
498 | * This function will import the given private key to the abstract |
499 | * #gnutls_privkey_t structure. |
500 | * |
501 | * The #gnutls_x509_privkey_t object must not be deallocated |
502 | * during the lifetime of this structure. |
503 | * |
504 | * @flags might be zero or one of %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE |
505 | * and %GNUTLS_PRIVKEY_IMPORT_COPY. |
506 | * |
507 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
508 | * negative error value. |
509 | * |
510 | * Since: 2.12.0 |
511 | **/ |
512 | int |
513 | gnutls_privkey_import_x509 (gnutls_privkey_t pkey, |
514 | gnutls_x509_privkey_t key, unsigned int flags) |
515 | { |
516 | int ret; |
517 | |
518 | ret = check_if_clean(pkey); |
519 | if (ret < 0) |
520 | { |
521 | gnutls_assert(); |
522 | return ret; |
523 | } |
524 | |
525 | if (flags & GNUTLS_PRIVKEY_IMPORT_COPY) |
526 | { |
527 | ret = gnutls_x509_privkey_init(&pkey->key.x509); |
528 | if (ret < 0) |
529 | return gnutls_assert_val(ret); |
530 | |
531 | ret = gnutls_x509_privkey_cpy(pkey->key.x509, key); |
532 | if (ret < 0) |
533 | { |
534 | gnutls_x509_privkey_deinit(pkey->key.x509); |
535 | return gnutls_assert_val(ret); |
536 | } |
537 | } |
538 | else |
539 | pkey->key.x509 = key; |
540 | |
541 | pkey->type = GNUTLS_PRIVKEY_X509; |
542 | pkey->pk_algorithm = gnutls_x509_privkey_get_pk_algorithm (key); |
543 | pkey->flags = flags; |
544 | |
545 | return 0; |
546 | } |
547 | |
548 | #ifdef ENABLE_OPENPGP |
549 | /** |
550 | * gnutls_privkey_import_openpgp: |
551 | * @pkey: The private key |
552 | * @key: The private key to be imported |
553 | * @flags: Flags for the import |
554 | * |
555 | * This function will import the given private key to the abstract |
556 | * #gnutls_privkey_t structure. |
557 | * |
558 | * The #gnutls_openpgp_privkey_t object must not be deallocated |
559 | * during the lifetime of this structure. The subkey set as |
560 | * preferred will be used, or the master key otherwise. |
561 | * |
562 | * @flags might be zero or one of %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE |
563 | * and %GNUTLS_PRIVKEY_IMPORT_COPY. |
564 | * |
565 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
566 | * negative error value. |
567 | * |
568 | * Since: 2.12.0 |
569 | **/ |
570 | int |
571 | gnutls_privkey_import_openpgp (gnutls_privkey_t pkey, |
572 | gnutls_openpgp_privkey_t key, |
573 | unsigned int flags) |
574 | { |
575 | int ret, idx; |
576 | uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; |
577 | |
578 | ret = check_if_clean(pkey); |
579 | if (ret < 0) |
580 | { |
581 | gnutls_assert(); |
582 | return ret; |
583 | } |
584 | |
585 | if (flags & GNUTLS_PRIVKEY_IMPORT_COPY) |
586 | { |
587 | ret = gnutls_openpgp_privkey_init(&pkey->key.openpgp); |
588 | if (ret < 0) |
589 | return gnutls_assert_val(ret); |
590 | |
591 | ret = _gnutls_openpgp_privkey_cpy(pkey->key.openpgp, key); |
592 | if (ret < 0) |
593 | { |
594 | gnutls_openpgp_privkey_deinit(pkey->key.openpgp); |
595 | return gnutls_assert_val(ret); |
596 | } |
597 | } |
598 | else |
599 | pkey->key.openpgp = key; |
600 | |
601 | pkey->type = GNUTLS_PRIVKEY_OPENPGP; |
602 | |
603 | ret = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid); |
604 | if (ret == GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR) |
605 | { |
606 | pkey->pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm(key, NULL); |
607 | } |
608 | else |
609 | { |
610 | if (ret < 0) |
611 | return gnutls_assert_val(ret); |
612 | |
613 | idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid); |
614 | |
615 | pkey->pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, NULL); |
616 | } |
617 | |
618 | pkey->flags = flags; |
619 | |
620 | return 0; |
621 | } |
622 | |
623 | /** |
624 | * gnutls_privkey_import_openpgp_raw: |
625 | * @pkey: The private key |
626 | * @data: The private key data to be imported |
627 | * @format: The format of the private key |
628 | * @keyid: The key id to use (optional) |
629 | * @password: A password (optional) |
630 | * |
631 | * This function will import the given private key to the abstract |
632 | * #gnutls_privkey_t structure. |
633 | * |
634 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
635 | * negative error value. |
636 | * |
637 | * Since: 3.1.0 |
638 | **/ |
639 | int gnutls_privkey_import_openpgp_raw (gnutls_privkey_t pkey, |
640 | const gnutls_datum_t * data, |
641 | gnutls_openpgp_crt_fmt_t format, |
642 | const gnutls_openpgp_keyid_t keyid, |
643 | const char* password) |
644 | { |
645 | gnutls_openpgp_privkey_t xpriv; |
646 | int ret; |
647 | |
648 | ret = gnutls_openpgp_privkey_init(&xpriv); |
649 | if (ret < 0) |
650 | return gnutls_assert_val(ret); |
651 | |
652 | ret = gnutls_openpgp_privkey_import(xpriv, data, format, password, 0); |
653 | if (ret < 0) |
654 | { |
655 | gnutls_assert(); |
656 | goto cleanup; |
657 | } |
658 | |
659 | if(keyid) |
660 | { |
661 | ret = gnutls_openpgp_privkey_set_preferred_key_id(xpriv, keyid); |
662 | if (ret < 0) |
663 | { |
664 | gnutls_assert(); |
665 | goto cleanup; |
666 | } |
667 | } |
668 | |
669 | ret = gnutls_privkey_import_openpgp(pkey, xpriv, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE); |
670 | if (ret < 0) |
671 | { |
672 | gnutls_assert(); |
673 | goto cleanup; |
674 | } |
675 | |
676 | ret = 0; |
677 | |
678 | cleanup: |
679 | gnutls_openpgp_privkey_deinit(xpriv); |
680 | |
681 | return ret; |
682 | } |
683 | #endif |
684 | |
685 | /** |
686 | * gnutls_privkey_sign_data: |
687 | * @signer: Holds the key |
688 | * @hash: should be a digest algorithm |
689 | * @flags: Zero or one of %gnutls_privkey_flags_t |
690 | * @data: holds the data to be signed |
691 | * @signature: will contain the signature allocate with gnutls_malloc() |
692 | * |
693 | * This function will sign the given data using a signature algorithm |
694 | * supported by the private key. Signature algorithms are always used |
695 | * together with a hash functions. Different hash functions may be |
696 | * used for the RSA algorithm, but only the SHA family for the DSA keys. |
697 | * |
698 | * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine |
699 | * the hash algorithm. |
700 | * |
701 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
702 | * negative error value. |
703 | * |
704 | * Since: 2.12.0 |
705 | **/ |
706 | int |
707 | gnutls_privkey_sign_data (gnutls_privkey_t signer, |
708 | gnutls_digest_algorithm_t hash, |
709 | unsigned int flags, |
710 | const gnutls_datum_t * data, |
711 | gnutls_datum_t * signature) |
712 | { |
713 | int ret; |
714 | gnutls_datum_t digest; |
715 | const mac_entry_st* me = mac_to_entry(hash); |
716 | |
717 | if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA) |
718 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
719 | |
720 | ret = pk_hash_data (signer->pk_algorithm, me, NULL, data, &digest); |
721 | if (ret < 0) |
722 | { |
723 | gnutls_assert (); |
724 | return ret; |
725 | } |
726 | |
727 | ret = pk_prepare_hash (signer->pk_algorithm, me, &digest); |
728 | if (ret < 0) |
729 | { |
730 | gnutls_assert (); |
731 | goto cleanup; |
732 | } |
733 | |
734 | ret = gnutls_privkey_sign_raw_data (signer, flags, &digest, signature); |
735 | _gnutls_free_datum (&digest); |
736 | |
737 | if (ret < 0) |
738 | { |
739 | gnutls_assert (); |
740 | return ret; |
741 | } |
742 | |
743 | return 0; |
744 | |
745 | cleanup: |
746 | _gnutls_free_datum (&digest); |
747 | return ret; |
748 | } |
749 | |
750 | /** |
751 | * gnutls_privkey_sign_hash: |
752 | * @signer: Holds the signer's key |
753 | * @hash_algo: The hash algorithm used |
754 | * @flags: Zero or one of %gnutls_privkey_flags_t |
755 | * @hash_data: holds the data to be signed |
756 | * @signature: will contain newly allocated signature |
757 | * |
758 | * This function will sign the given hashed data using a signature algorithm |
759 | * supported by the private key. Signature algorithms are always used |
760 | * together with a hash functions. Different hash functions may be |
761 | * used for the RSA algorithm, but only SHA-XXX for the DSA keys. |
762 | * |
763 | * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine |
764 | * the hash algorithm. |
765 | * |
766 | * Note that if %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA flag is specified this function |
767 | * will ignore @hash_algo and perform a raw PKCS1 signature. |
768 | * |
769 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
770 | * negative error value. |
771 | * |
772 | * Since: 2.12.0 |
773 | **/ |
774 | int |
775 | gnutls_privkey_sign_hash (gnutls_privkey_t signer, |
776 | gnutls_digest_algorithm_t hash_algo, |
777 | unsigned int flags, |
778 | const gnutls_datum_t * hash_data, |
779 | gnutls_datum_t * signature) |
780 | { |
781 | int ret; |
782 | gnutls_datum_t digest; |
783 | |
784 | if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA) |
785 | return gnutls_privkey_sign_raw_data (signer, flags, hash_data, signature); |
786 | |
787 | digest.data = gnutls_malloc (hash_data->size); |
788 | if (digest.data == NULL) |
789 | { |
790 | gnutls_assert (); |
791 | return GNUTLS_E_MEMORY_ERROR; |
792 | } |
793 | digest.size = hash_data->size; |
794 | memcpy (digest.data, hash_data->data, digest.size); |
795 | |
796 | ret = pk_prepare_hash (signer->pk_algorithm, mac_to_entry(hash_algo), &digest); |
797 | if (ret < 0) |
798 | { |
799 | gnutls_assert (); |
800 | goto cleanup; |
801 | } |
802 | |
803 | ret = gnutls_privkey_sign_raw_data (signer, flags, &digest, signature); |
804 | if (ret < 0) |
805 | { |
806 | gnutls_assert (); |
807 | goto cleanup; |
808 | } |
809 | |
810 | ret = 0; |
811 | |
812 | cleanup: |
813 | _gnutls_free_datum (&digest); |
814 | return ret; |
815 | } |
816 | |
817 | /** |
818 | * gnutls_privkey_sign_raw_data: |
819 | * @key: Holds the key |
820 | * @flags: should be zero |
821 | * @data: holds the data to be signed |
822 | * @signature: will contain the signature allocate with gnutls_malloc() |
823 | * |
824 | * This function will sign the given data using a signature algorithm |
825 | * supported by the private key. Note that this is a low-level function |
826 | * and does not apply any preprocessing or hash on the signed data. |
827 | * For example on an RSA key the input @data should be of the DigestInfo |
828 | * PKCS #1 1.5 format. Use it only if you know what are you doing. |
829 | * |
830 | * Note this function is equivalent to using the %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA |
831 | * flag with gnutls_privkey_sign_hash(). |
832 | * |
833 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
834 | * negative error value. |
835 | * |
836 | * Since: 3.1.10 |
837 | **/ |
838 | int |
839 | gnutls_privkey_sign_raw_data (gnutls_privkey_t key, |
840 | unsigned flags, |
841 | const gnutls_datum_t * data, |
842 | gnutls_datum_t * signature) |
843 | { |
844 | switch (key->type) |
845 | { |
846 | #ifdef ENABLE_OPENPGP |
847 | case GNUTLS_PRIVKEY_OPENPGP: |
848 | return gnutls_openpgp_privkey_sign_hash (key->key.openpgp, |
849 | data, signature); |
850 | #endif |
851 | #ifdef ENABLE_PKCS11 |
852 | case GNUTLS_PRIVKEY_PKCS11: |
853 | return _gnutls_pkcs11_privkey_sign_hash (key->key.pkcs11, |
854 | data, signature); |
855 | #endif |
856 | case GNUTLS_PRIVKEY_X509: |
857 | return _gnutls_pk_sign (key->key.x509->pk_algorithm, |
858 | signature, data, &key->key.x509->params); |
859 | case GNUTLS_PRIVKEY_EXT: |
860 | if (key->key.ext.sign_func == NULL) |
861 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
862 | return key->key.ext.sign_func(key, key->key.ext.userdata, data, signature); |
863 | default: |
864 | gnutls_assert (); |
865 | return GNUTLS_E_INVALID_REQUEST; |
866 | } |
867 | } |
868 | |
869 | /** |
870 | * gnutls_privkey_decrypt_data: |
871 | * @key: Holds the key |
872 | * @flags: zero for now |
873 | * @ciphertext: holds the data to be decrypted |
874 | * @plaintext: will contain the decrypted data, allocated with gnutls_malloc() |
875 | * |
876 | * This function will decrypt the given data using the algorithm |
877 | * supported by the private key. |
878 | * |
879 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
880 | * negative error value. |
881 | * |
882 | * Since: 2.12.0 |
883 | **/ |
884 | int |
885 | gnutls_privkey_decrypt_data (gnutls_privkey_t key, |
886 | unsigned int flags, |
887 | const gnutls_datum_t * ciphertext, |
888 | gnutls_datum_t * plaintext) |
889 | { |
890 | switch (key->type) |
891 | { |
892 | #ifdef ENABLE_OPENPGP |
893 | case GNUTLS_PRIVKEY_OPENPGP: |
894 | return _gnutls_openpgp_privkey_decrypt_data (key->key.openpgp, flags, |
895 | ciphertext, plaintext); |
896 | #endif |
897 | case GNUTLS_PRIVKEY_X509: |
898 | return _gnutls_pk_decrypt (key->pk_algorithm, plaintext, ciphertext, |
899 | &key->key.x509->params); |
900 | #ifdef ENABLE_PKCS11 |
901 | case GNUTLS_PRIVKEY_PKCS11: |
902 | return _gnutls_pkcs11_privkey_decrypt_data (key->key.pkcs11, |
903 | flags, |
904 | ciphertext, plaintext); |
905 | #endif |
906 | case GNUTLS_PRIVKEY_EXT: |
907 | if (key->key.ext.decrypt_func == NULL) |
908 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
909 | |
910 | return key->key.ext.decrypt_func(key, key->key.ext.userdata, ciphertext, plaintext); |
911 | default: |
912 | gnutls_assert (); |
913 | return GNUTLS_E_INVALID_REQUEST; |
914 | } |
915 | } |
916 | |
917 | /** |
918 | * gnutls_privkey_import_x509_raw: |
919 | * @pkey: The private key |
920 | * @data: The private key data to be imported |
921 | * @format: The format of the private key |
922 | * @password: A password (optional) |
923 | * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t |
924 | * |
925 | * This function will import the given private key to the abstract |
926 | * #gnutls_privkey_t structure. |
927 | * |
928 | * The supported formats are basic unencrypted key, PKCS8, PKCS12, |
929 | * and the openssl format. |
930 | * |
931 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
932 | * negative error value. |
933 | * |
934 | * Since: 3.1.0 |
935 | **/ |
936 | int gnutls_privkey_import_x509_raw (gnutls_privkey_t pkey, |
937 | const gnutls_datum_t * data, |
938 | gnutls_x509_crt_fmt_t format, |
939 | const char* password, unsigned int flags) |
940 | { |
941 | gnutls_x509_privkey_t xpriv; |
942 | int ret; |
943 | |
944 | ret = gnutls_x509_privkey_init(&xpriv); |
945 | if (ret < 0) |
946 | return gnutls_assert_val(ret); |
947 | |
948 | ret = gnutls_x509_privkey_import2(xpriv, data, format, password, flags); |
949 | if (ret < 0) |
950 | { |
951 | gnutls_assert(); |
952 | goto cleanup; |
953 | } |
954 | |
955 | ret = gnutls_privkey_import_x509(pkey, xpriv, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE); |
956 | if (ret < 0) |
957 | { |
958 | gnutls_assert(); |
959 | goto cleanup; |
960 | } |
961 | |
962 | return 0; |
963 | |
964 | cleanup: |
965 | gnutls_x509_privkey_deinit(xpriv); |
966 | |
967 | return ret; |
968 | } |
969 | |
970 | /** |
971 | * gnutls_privkey_import_url: |
972 | * @key: A key of type #gnutls_privkey_t |
973 | * @url: A PKCS 11 url |
974 | * @flags: should be zero |
975 | * |
976 | * This function will import a PKCS11 or TPM URL as a |
977 | * private key. The supported URL types can be checked |
978 | * using gnutls_url_is_supported(). |
979 | * |
980 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a |
981 | * negative error value. |
982 | * |
983 | * Since: 3.1.0 |
984 | **/ |
985 | int |
986 | gnutls_privkey_import_url (gnutls_privkey_t key, const char *url, unsigned int flags) |
987 | { |
988 | if (strncmp(url, "pkcs11:" , 7) == 0) |
989 | #ifdef ENABLE_PKCS11 |
990 | return gnutls_privkey_import_pkcs11_url(key, url); |
991 | #else |
992 | return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); |
993 | #endif |
994 | |
995 | if (strncmp(url, "tpmkey:" , 7) == 0) |
996 | #ifdef HAVE_TROUSERS |
997 | return gnutls_privkey_import_tpm_url(key, url, NULL, NULL, 0); |
998 | #else |
999 | return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); |
1000 | #endif |
1001 | |
1002 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); |
1003 | } |
1004 | |
1005 | /** |
1006 | * gnutls_privkey_set_pin_function: |
1007 | * @key: A key of type #gnutls_privkey_t |
1008 | * @fn: the callback |
1009 | * @userdata: data associated with the callback |
1010 | * |
1011 | * This function will set a callback function to be used when |
1012 | * required to access the object. This function overrides any other |
1013 | * global PIN functions. |
1014 | * |
1015 | * Note that this function must be called right after initialization |
1016 | * to have effect. |
1017 | * |
1018 | * Since: 3.1.0 |
1019 | * |
1020 | **/ |
1021 | void gnutls_privkey_set_pin_function (gnutls_privkey_t key, |
1022 | gnutls_pin_callback_t fn, void *userdata) |
1023 | { |
1024 | key->pin.cb = fn; |
1025 | key->pin.data = userdata; |
1026 | } |
1027 | |
1028 | /** |
1029 | * gnutls_privkey_status: |
1030 | * @key: Holds the key |
1031 | * |
1032 | * Checks the status of the private key token. This function |
1033 | * is an actual wrapper over gnutls_pkcs11_privkey_status(), and |
1034 | * if the private key is a PKCS #11 token it will check whether |
1035 | * it is inserted or not. |
1036 | * |
1037 | * Returns: this function will return non-zero if the token |
1038 | * holding the private key is still available (inserted), and zero otherwise. |
1039 | * |
1040 | * Since: 3.1.10 |
1041 | * |
1042 | **/ |
1043 | int |
1044 | gnutls_privkey_status (gnutls_privkey_t key) |
1045 | { |
1046 | switch (key->type) |
1047 | { |
1048 | #ifdef ENABLE_PKCS11 |
1049 | case GNUTLS_PRIVKEY_PKCS11: |
1050 | return gnutls_pkcs11_privkey_status (key->key.pkcs11); |
1051 | #endif |
1052 | default: |
1053 | return 1; |
1054 | } |
1055 | } |
1056 | |