Corrected functionality of gnutls_record_get_direction(). Reported by Philip Allison.
[gnutls.git] / lib / gnutls_privkey.c
blobf61524fe81d8bc158aa7e461cfdaedf70a0c147c
1 /*
2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010 Free Software Foundation
4 *
5 * Author: Nikos Mavrogiannopoulos
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
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.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 * MA 02111-1307, USA
23 #include <gnutls_int.h>
24 #include <gnutls/pkcs11.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_datum.h>
29 #include <pkcs11_int.h>
30 #include <gnutls/abstract.h>
31 #include <gnutls_pk.h>
32 #include <x509_int.h>
33 #include <openpgp/openpgp_int.h>
34 #include <openpgp/gnutls_openpgp.h>
35 #include <gnutls_sig.h>
36 #include <abstract_int.h>
38 struct gnutls_privkey_st
40 gnutls_privkey_type_t type;
41 gnutls_pk_algorithm_t pk_algorithm;
43 union
45 gnutls_x509_privkey_t x509;
46 #ifdef ENABLE_PKCS11
47 gnutls_pkcs11_privkey_t pkcs11;
48 #endif
49 #ifdef ENABLE_OPENPGP
50 gnutls_openpgp_privkey_t openpgp;
51 #endif
52 } key;
54 unsigned int flags;
57 /**
58 * gnutls_privkey_get_type:
59 * @key: should contain a #gnutls_privkey_t structure
61 * This function will return the type of the private key. This is
62 * actually the type of the subsystem used to set this private key.
64 * Returns: a member of the #gnutls_privkey_type_t enumeration on
65 * success, or a negative value on error.
66 **/
67 gnutls_privkey_type_t
68 gnutls_privkey_get_type (gnutls_privkey_t key)
70 return key->type;
73 /**
74 * gnutls_privkey_get_pk_algorithm:
75 * @key: should contain a #gnutls_privkey_t structure
76 * @bits: If set will return the number of bits of the parameters (may be NULL)
78 * This function will return the public key algorithm of a private
79 * key and if possible will return a number of bits that indicates
80 * the security parameter of the key.
82 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
83 * success, or a negative value on error.
84 **/
85 int
86 gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key, unsigned int *bits)
88 switch (key->type)
90 #ifdef ENABLE_OPENPGP
91 case GNUTLS_PRIVKEY_OPENPGP:
92 return gnutls_openpgp_privkey_get_pk_algorithm (key->key.openpgp, bits);
93 #endif
94 #ifdef ENABLE_PKCS11
95 case GNUTLS_PRIVKEY_PKCS11:
96 return gnutls_pkcs11_privkey_get_pk_algorithm (key->key.pkcs11, bits);
97 #endif
98 case GNUTLS_PRIVKEY_X509:
99 if (bits)
100 *bits = _gnutls_mpi_get_nbits (key->key.x509->params[0]);
101 return gnutls_x509_privkey_get_pk_algorithm (key->key.x509);
102 default:
103 gnutls_assert ();
104 return GNUTLS_E_INVALID_REQUEST;
109 static int
110 privkey_to_pubkey (gnutls_pk_algorithm_t pk,
111 const bigint_t * params, int params_size,
112 bigint_t * new_params, int *new_params_size)
114 int ret, i;
116 switch (pk)
118 case GNUTLS_PK_RSA:
119 if (*new_params_size < RSA_PUBLIC_PARAMS
120 || params_size < RSA_PRIVATE_PARAMS)
122 gnutls_assert ();
123 return GNUTLS_E_INVALID_REQUEST;
126 new_params[0] = _gnutls_mpi_copy (params[0]);
127 new_params[1] = _gnutls_mpi_copy (params[1]);
129 *new_params_size = RSA_PUBLIC_PARAMS;
131 if (new_params[0] == NULL || new_params[1] == NULL)
133 gnutls_assert ();
134 ret = GNUTLS_E_MEMORY_ERROR;
135 goto cleanup;
138 break;
139 case GNUTLS_PK_DSA:
140 if (*new_params_size < DSA_PUBLIC_PARAMS
141 || params_size < DSA_PRIVATE_PARAMS)
143 gnutls_assert ();
144 return GNUTLS_E_INVALID_REQUEST;
147 new_params[0] = _gnutls_mpi_copy (params[0]);
148 new_params[1] = _gnutls_mpi_copy (params[1]);
149 new_params[2] = _gnutls_mpi_copy (params[2]);
150 new_params[3] = _gnutls_mpi_copy (params[3]);
152 *new_params_size = DSA_PUBLIC_PARAMS;
154 if (new_params[0] == NULL || new_params[1] == NULL ||
155 new_params[2] == NULL || new_params[3] == NULL)
157 gnutls_assert ();
158 ret = GNUTLS_E_MEMORY_ERROR;
159 goto cleanup;
162 break;
163 default:
164 gnutls_assert ();
165 return GNUTLS_E_INVALID_REQUEST;
168 return 0;
169 cleanup:
170 for (i = 0; i < *new_params_size; i++)
171 _gnutls_mpi_release (new_params[i]);
172 return ret;
176 /* Returns the public key of the private key (if possible)
179 _gnutls_privkey_get_public_mpis (gnutls_privkey_t key,
180 bigint_t * params, int *params_size)
182 int ret;
183 gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm (key, NULL);
185 switch (key->type)
187 #ifdef ENABLE_OPENPGP
188 case GNUTLS_PRIVKEY_OPENPGP:
190 bigint_t tmp_params[MAX_PRIV_PARAMS_SIZE];
191 int tmp_params_size = MAX_PRIV_PARAMS_SIZE;
192 uint32_t kid[2], i;
193 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
195 ret =
196 gnutls_openpgp_privkey_get_preferred_key_id (key->key.openpgp,
197 keyid);
198 if (ret == 0)
200 KEYID_IMPORT (kid, keyid);
201 ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, kid,
202 tmp_params,
203 &tmp_params_size);
205 else
206 ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, NULL,
207 tmp_params,
208 &tmp_params_size);
210 if (ret < 0)
212 gnutls_assert ();
213 return ret;
216 ret = privkey_to_pubkey (pk,
217 tmp_params, tmp_params_size,
218 params, params_size);
220 for (i = 0; i < tmp_params_size; i++)
221 _gnutls_mpi_release (&tmp_params[i]);
225 break;
226 #endif
227 case GNUTLS_PRIVKEY_X509:
228 ret = privkey_to_pubkey (pk,
229 key->key.x509->params,
230 key->key.x509->params_size, params,
231 params_size);
232 break;
233 default:
234 gnutls_assert ();
235 return GNUTLS_E_INVALID_REQUEST;
238 return ret;
242 * gnutls_privkey_init:
243 * @key: The structure to be initialized
245 * This function will initialize an private key structure.
247 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
248 * negative error value.
251 gnutls_privkey_init (gnutls_privkey_t * key)
253 *key = gnutls_calloc (1, sizeof (struct gnutls_privkey_st));
254 if (*key == NULL)
256 gnutls_assert ();
257 return GNUTLS_E_MEMORY_ERROR;
260 return 0;
264 * gnutls_privkey_deinit:
265 * @key: The structure to be deinitialized
267 * This function will deinitialize a private key structure.
269 void
270 gnutls_privkey_deinit (gnutls_privkey_t key)
272 if (key == NULL) return;
274 if (key->flags & GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE || key->flags & GNUTLS_PRIVKEY_IMPORT_COPY)
275 switch (key->type)
277 #ifdef ENABLE_OPENPGP
278 case GNUTLS_PRIVKEY_OPENPGP:
279 gnutls_openpgp_privkey_deinit (key->key.openpgp);
280 break;
281 #endif
282 #ifdef ENABLE_PKCS11
283 case GNUTLS_PRIVKEY_PKCS11:
284 gnutls_pkcs11_privkey_deinit (key->key.pkcs11);
285 break;
286 #endif
287 case GNUTLS_PRIVKEY_X509:
288 gnutls_x509_privkey_deinit (key->key.x509);
289 break;
291 gnutls_free (key);
294 /* will fail if the private key contains an actual key.
296 static int check_if_clean(gnutls_privkey_t key)
298 if (key->type != 0)
299 return GNUTLS_E_INVALID_REQUEST;
301 return 0;
304 #ifdef ENABLE_PKCS11
307 * gnutls_privkey_import_pkcs11:
308 * @pkey: The private key
309 * @key: The private key to be imported
310 * @flags: should be zero
312 * This function will import the given private key to the abstract
313 * #gnutls_privkey_t structure.
315 * The #gnutls_pkcs11_privkey_t object must not be deallocated
316 * during the lifetime of this structure.
318 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
319 * negative error value.
322 gnutls_privkey_import_pkcs11 (gnutls_privkey_t pkey,
323 gnutls_pkcs11_privkey_t key, unsigned int flags)
325 int ret;
327 ret = check_if_clean(pkey);
328 if (ret < 0)
330 gnutls_assert();
331 return ret;
334 if (flags & GNUTLS_PRIVKEY_IMPORT_COPY)
335 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
337 pkey->key.pkcs11 = key;
338 pkey->type = GNUTLS_PRIVKEY_PKCS11;
339 pkey->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm (key, NULL);
340 pkey->flags = flags;
342 return 0;
345 #endif /* ENABLE_PKCS11 */
348 * gnutls_privkey_import_x509:
349 * @pkey: The private key
350 * @key: The private key to be imported
351 * @flags: should be zero
353 * This function will import the given private key to the abstract
354 * #gnutls_privkey_t structure.
356 * The #gnutls_x509_privkey_t object must not be deallocated
357 * during the lifetime of this structure.
359 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
360 * negative error value.
363 gnutls_privkey_import_x509 (gnutls_privkey_t pkey,
364 gnutls_x509_privkey_t key, unsigned int flags)
366 int ret;
368 ret = check_if_clean(pkey);
369 if (ret < 0)
371 gnutls_assert();
372 return ret;
375 if (flags & GNUTLS_PRIVKEY_IMPORT_COPY)
377 ret = gnutls_x509_privkey_init(&pkey->key.x509);
378 if (ret < 0)
379 return gnutls_assert_val(ret);
381 ret = gnutls_x509_privkey_cpy(pkey->key.x509, key);
382 if (ret < 0)
384 gnutls_x509_privkey_deinit(pkey->key.x509);
385 return gnutls_assert_val(ret);
388 else
389 pkey->key.x509 = key;
391 pkey->type = GNUTLS_PRIVKEY_X509;
392 pkey->pk_algorithm = gnutls_x509_privkey_get_pk_algorithm (key);
393 pkey->flags = flags;
395 return 0;
398 #ifdef ENABLE_OPENPGP
400 * gnutls_privkey_import_openpgp:
401 * @pkey: The private key
402 * @key: The private key to be imported
403 * @flags: should be zero
405 * This function will import the given private key to the abstract
406 * #gnutls_privkey_t structure.
408 * The #gnutls_openpgp_privkey_t object must not be deallocated
409 * during the lifetime of this structure. The subkey set as
410 * preferred will be used, or the master key otherwise.
412 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
413 * negative error value.
416 gnutls_privkey_import_openpgp (gnutls_privkey_t pkey,
417 gnutls_openpgp_privkey_t key,
418 unsigned int flags)
420 int ret, idx;
421 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
423 ret = check_if_clean(pkey);
424 if (ret < 0)
426 gnutls_assert();
427 return ret;
430 if (flags & GNUTLS_PRIVKEY_IMPORT_COPY)
432 ret = gnutls_openpgp_privkey_init(&pkey->key.openpgp);
433 if (ret < 0)
434 return gnutls_assert_val(ret);
436 ret = _gnutls_openpgp_privkey_cpy(pkey->key.openpgp, key);
437 if (ret < 0)
439 gnutls_openpgp_privkey_deinit(pkey->key.openpgp);
440 return gnutls_assert_val(ret);
443 else
444 pkey->key.openpgp = key;
446 pkey->type = GNUTLS_PRIVKEY_OPENPGP;
448 ret = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid);
449 if (ret == GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR)
451 pkey->pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm(key, NULL);
453 else
455 if (ret < 0)
456 return gnutls_assert_val(ret);
458 idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid);
460 pkey->pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, NULL);
463 pkey->flags = flags;
465 return 0;
467 #endif
470 * gnutls_privkey_sign_data:
471 * @signer: Holds the key
472 * @hash: should be a digest algorithm
473 * @flags: should be 0 for now
474 * @data: holds the data to be signed
475 * @signature: will contain the signature allocate with gnutls_malloc()
477 * This function will sign the given data using a signature algorithm
478 * supported by the private key. Signature algorithms are always used
479 * together with a hash functions. Different hash functions may be
480 * used for the RSA algorithm, but only SHA-1 for the DSA keys.
482 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
483 * negative error value.
485 * Since: 2.12.0
488 gnutls_privkey_sign_data (gnutls_privkey_t signer,
489 gnutls_digest_algorithm_t hash,
490 unsigned int flags,
491 const gnutls_datum_t * data,
492 gnutls_datum_t * signature)
494 int ret;
495 gnutls_datum_t digest;
497 ret = pk_hash_data (signer->pk_algorithm, hash, NULL, data, &digest);
498 if (ret < 0)
500 gnutls_assert ();
501 return ret;
504 ret = pk_prepare_hash (signer->pk_algorithm, hash, &digest);
505 if (ret < 0)
507 gnutls_assert ();
508 goto cleanup;
511 ret = _gnutls_privkey_sign_hash (signer, &digest, signature);
512 _gnutls_free_datum (&digest);
514 if (ret < 0)
516 gnutls_assert ();
517 return ret;
520 return 0;
522 cleanup:
523 _gnutls_free_datum (&digest);
524 return ret;
528 * gnutls_privkey_sign_hash:
529 * @signer: Holds the signer's key
530 * @hash_algo: The hash algorithm used
531 * @flags: zero for now
532 * @hash_data: holds the data to be signed
533 * @signature: will contain newly allocated signature
535 * This function will sign the given hashed data using a signature algorithm
536 * supported by the private key. Signature algorithms are always used
537 * together with a hash functions. Different hash functions may be
538 * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
540 * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine
541 * the hash algorithm.
543 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
544 * negative error value.
546 * Since: 2.12.0
549 gnutls_privkey_sign_hash (gnutls_privkey_t signer,
550 gnutls_digest_algorithm_t hash_algo,
551 unsigned int flags,
552 const gnutls_datum_t * hash_data,
553 gnutls_datum_t * signature)
555 int ret;
556 gnutls_datum_t digest;
558 digest.data = gnutls_malloc (hash_data->size);
559 if (digest.data == NULL)
561 gnutls_assert ();
562 return GNUTLS_E_MEMORY_ERROR;
564 digest.size = hash_data->size;
565 memcpy (digest.data, hash_data->data, digest.size);
567 ret = pk_prepare_hash (signer->pk_algorithm, hash_algo, &digest);
568 if (ret < 0)
570 gnutls_assert ();
571 goto cleanup;
574 ret = _gnutls_privkey_sign_hash (signer, &digest, signature);
575 if (ret < 0)
577 gnutls_assert ();
578 goto cleanup;
581 ret = 0;
583 cleanup:
584 _gnutls_free_datum (&digest);
585 return ret;
589 * _gnutls_privkey_sign_hash:
590 * @key: Holds the key
591 * @data: holds the data to be signed
592 * @signature: will contain the signature allocate with gnutls_malloc()
594 * This function will sign the given data using a signature algorithm
595 * supported by the private key.
597 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
598 * negative error value.
601 _gnutls_privkey_sign_hash (gnutls_privkey_t key,
602 const gnutls_datum_t * hash,
603 gnutls_datum_t * signature)
605 switch (key->type)
607 #ifdef ENABLE_OPENPGP
608 case GNUTLS_PRIVKEY_OPENPGP:
609 return gnutls_openpgp_privkey_sign_hash (key->key.openpgp,
610 hash, signature);
611 #endif
612 #ifdef ENABLE_PKCS11
613 case GNUTLS_PRIVKEY_PKCS11:
614 return _gnutls_pkcs11_privkey_sign_hash (key->key.pkcs11,
615 hash, signature);
616 #endif
617 case GNUTLS_PRIVKEY_X509:
618 return _gnutls_soft_sign (key->key.x509->pk_algorithm,
619 key->key.x509->params,
620 key->key.x509->params_size, hash, signature);
621 default:
622 gnutls_assert ();
623 return GNUTLS_E_INVALID_REQUEST;
628 * gnutls_privkey_decrypt_data:
629 * @key: Holds the key
630 * @flags: zero for now
631 * @ciphertext: holds the data to be decrypted
632 * @plaintext: will contain the decrypted data, allocated with gnutls_malloc()
634 * This function will decrypt the given data using the algorithm
635 * supported by the private key.
637 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
638 * negative error value.
641 gnutls_privkey_decrypt_data (gnutls_privkey_t key,
642 unsigned int flags,
643 const gnutls_datum_t * ciphertext,
644 gnutls_datum_t * plaintext)
646 if (key->pk_algorithm != GNUTLS_PK_RSA)
648 gnutls_assert ();
649 return GNUTLS_E_INVALID_REQUEST;
652 switch (key->type)
654 #ifdef ENABLE_OPENPGP
655 case GNUTLS_PRIVKEY_OPENPGP:
656 return _gnutls_openpgp_privkey_decrypt_data (key->key.openpgp, flags,
657 ciphertext, plaintext);
658 #endif
659 case GNUTLS_PRIVKEY_X509:
660 return _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext,
661 key->key.x509->params,
662 key->key.x509->params_size, 2);
663 #ifdef ENABLE_PKCS11
664 case GNUTLS_PRIVKEY_PKCS11:
665 return _gnutls_pkcs11_privkey_decrypt_data (key->key.pkcs11,
666 flags,
667 ciphertext, plaintext);
668 #endif
669 default:
670 gnutls_assert ();
671 return GNUTLS_E_INVALID_REQUEST;