Honor uninitialized private key in destructor
[gnutls.git] / lib / gnutls_privkey.c
blob2f5d06b5b5f7ebf728b76cccd4369b01e08c3206
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 <pakchois/pakchois.h>
25 #include <gnutls/pkcs11.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <gnutls_errors.h>
29 #include <gnutls_datum.h>
30 #include <pkcs11_int.h>
31 #include <gnutls/abstract.h>
32 #include <gnutls_pk.h>
33 #include <x509_int.h>
34 #include <openpgp/openpgp_int.h>
35 #include <openpgp/gnutls_openpgp.h>
36 #include <gnutls_sig.h>
37 #include <abstract_int.h>
39 struct gnutls_privkey_st
41 gnutls_privkey_type_t type;
42 gnutls_pk_algorithm_t pk_algorithm;
44 union
46 gnutls_x509_privkey_t x509;
47 gnutls_pkcs11_privkey_t pkcs11;
48 #ifdef ENABLE_OPENPGP
49 gnutls_openpgp_privkey_t openpgp;
50 #endif
51 } key;
53 unsigned int flags;
56 /**
57 * gnutls_privkey_get_type:
58 * @key: should contain a #gnutls_privkey_t structure
60 * This function will return the type of the private key. This is
61 * actually the type of the subsystem used to set this private key.
63 * Returns: a member of the #gnutls_privkey_type_t enumeration on
64 * success, or a negative value on error.
65 **/
66 gnutls_privkey_type_t
67 gnutls_privkey_get_type (gnutls_privkey_t key)
69 return key->type;
72 /**
73 * gnutls_privkey_get_pk_algorithm:
74 * @key: should contain a #gnutls_privkey_t structure
75 * @bits: If set will return the number of bits of the parameters (may be NULL)
77 * This function will return the public key algorithm of a private
78 * key and if possible will return a number of bits that indicates
79 * the security parameter of the key.
81 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
82 * success, or a negative value on error.
83 **/
84 int
85 gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key, unsigned int *bits)
87 switch (key->type)
89 #ifdef ENABLE_OPENPGP
90 case GNUTLS_PRIVKEY_OPENPGP:
91 return gnutls_openpgp_privkey_get_pk_algorithm (key->key.openpgp, bits);
92 #endif
93 case GNUTLS_PRIVKEY_PKCS11:
94 return gnutls_pkcs11_privkey_get_pk_algorithm (key->key.pkcs11, bits);
95 case GNUTLS_PRIVKEY_X509:
96 if (bits)
97 *bits = _gnutls_mpi_get_nbits (key->key.x509->params[0]);
98 return gnutls_x509_privkey_get_pk_algorithm (key->key.x509);
99 default:
100 gnutls_assert ();
101 return GNUTLS_E_INVALID_REQUEST;
106 static int
107 privkey_to_pubkey (gnutls_pk_algorithm_t pk,
108 const bigint_t * params, int params_size,
109 bigint_t * new_params, int *new_params_size)
111 int ret, i;
113 switch (pk)
115 case GNUTLS_PK_RSA:
116 if (*new_params_size < RSA_PUBLIC_PARAMS
117 || params_size < RSA_PRIVATE_PARAMS)
119 gnutls_assert ();
120 return GNUTLS_E_INVALID_REQUEST;
123 new_params[0] = _gnutls_mpi_copy (params[0]);
124 new_params[1] = _gnutls_mpi_copy (params[1]);
126 *new_params_size = RSA_PUBLIC_PARAMS;
128 if (new_params[0] == NULL || new_params[1] == NULL)
130 gnutls_assert ();
131 ret = GNUTLS_E_MEMORY_ERROR;
132 goto cleanup;
135 break;
136 case GNUTLS_PK_DSA:
137 if (*new_params_size < DSA_PUBLIC_PARAMS
138 || params_size < DSA_PRIVATE_PARAMS)
140 gnutls_assert ();
141 return GNUTLS_E_INVALID_REQUEST;
144 new_params[0] = _gnutls_mpi_copy (params[0]);
145 new_params[1] = _gnutls_mpi_copy (params[1]);
146 new_params[2] = _gnutls_mpi_copy (params[2]);
147 new_params[3] = _gnutls_mpi_copy (params[3]);
149 *new_params_size = DSA_PUBLIC_PARAMS;
151 if (new_params[0] == NULL || new_params[1] == NULL ||
152 new_params[2] == NULL || new_params[3] == NULL)
154 gnutls_assert ();
155 ret = GNUTLS_E_MEMORY_ERROR;
156 goto cleanup;
159 break;
160 default:
161 gnutls_assert ();
162 return GNUTLS_E_INVALID_REQUEST;
165 return 0;
166 cleanup:
167 for (i = 0; i < *new_params_size; i++)
168 _gnutls_mpi_release (new_params[i]);
169 return ret;
173 /* Returns the public key of the private key (if possible)
176 _gnutls_privkey_get_public_mpis (gnutls_privkey_t key,
177 bigint_t * params, int *params_size)
179 int ret;
180 gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm (key, NULL);
182 switch (key->type)
184 #ifdef ENABLE_OPENPGP
185 case GNUTLS_PRIVKEY_OPENPGP:
187 bigint_t tmp_params[MAX_PRIV_PARAMS_SIZE];
188 int tmp_params_size = MAX_PRIV_PARAMS_SIZE;
189 uint32_t kid[2], i;
190 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
192 ret =
193 gnutls_openpgp_privkey_get_preferred_key_id (key->key.openpgp,
194 keyid);
195 if (ret == 0)
197 KEYID_IMPORT (kid, keyid);
198 ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, kid,
199 tmp_params,
200 &tmp_params_size);
202 else
203 ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, NULL,
204 tmp_params,
205 &tmp_params_size);
207 if (ret < 0)
209 gnutls_assert ();
210 return ret;
213 ret = privkey_to_pubkey (pk,
214 tmp_params, tmp_params_size,
215 params, params_size);
217 for (i = 0; i < tmp_params_size; i++)
218 _gnutls_mpi_release (&tmp_params[i]);
222 break;
223 #endif
224 case GNUTLS_PRIVKEY_X509:
225 ret = privkey_to_pubkey (pk,
226 key->key.x509->params,
227 key->key.x509->params_size, params,
228 params_size);
229 break;
230 default:
231 gnutls_assert ();
232 return GNUTLS_E_INVALID_REQUEST;
235 return ret;
239 * gnutls_privkey_init:
240 * @key: The structure to be initialized
242 * This function will initialize an private key structure.
244 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
245 * negative error value.
248 gnutls_privkey_init (gnutls_privkey_t * key)
250 *key = gnutls_calloc (1, sizeof (struct gnutls_privkey_st));
251 if (*key == NULL)
253 gnutls_assert ();
254 return GNUTLS_E_MEMORY_ERROR;
257 return 0;
261 * gnutls_privkey_deinit:
262 * @key: The structure to be deinitialized
264 * This function will deinitialize a private key structure.
266 void
267 gnutls_privkey_deinit (gnutls_privkey_t key)
269 if (key == NULL) return;
271 if (key->flags & GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE)
272 switch (key->type)
274 #ifdef ENABLE_OPENPGP
275 case GNUTLS_PRIVKEY_OPENPGP:
276 gnutls_openpgp_privkey_deinit (key->key.openpgp);
277 break;
278 #endif
279 case GNUTLS_PRIVKEY_PKCS11:
280 gnutls_pkcs11_privkey_deinit (key->key.pkcs11);
281 break;
282 case GNUTLS_PRIVKEY_X509:
283 gnutls_x509_privkey_deinit (key->key.x509);
284 break;
286 gnutls_free (key);
289 /* will fail if the private key contains an actual key.
291 static int check_if_clean(gnutls_privkey_t key)
293 if (key->type != 0)
294 return GNUTLS_E_INVALID_REQUEST;
296 return 0;
300 * gnutls_privkey_import_pkcs11:
301 * @pkey: The private key
302 * @key: The private key to be imported
303 * @flags: should be zero
305 * This function will import the given private key to the abstract
306 * #gnutls_privkey_t structure.
308 * The #gnutls_pkcs11_privkey_t object must not be deallocated
309 * during the lifetime of this structure.
311 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
312 * negative error value.
315 gnutls_privkey_import_pkcs11 (gnutls_privkey_t pkey,
316 gnutls_pkcs11_privkey_t key, unsigned int flags)
318 int ret;
320 ret = check_if_clean(pkey);
321 if (ret < 0)
323 gnutls_assert();
324 return ret;
327 pkey->key.pkcs11 = key;
328 pkey->type = GNUTLS_PRIVKEY_PKCS11;
329 pkey->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm (key, NULL);
330 pkey->flags = flags;
332 return 0;
336 * gnutls_privkey_import_x509:
337 * @pkey: The private key
338 * @key: The private key to be imported
339 * @flags: should be zero
341 * This function will import the given private key to the abstract
342 * #gnutls_privkey_t structure.
344 * The #gnutls_x509_privkey_t object must not be deallocated
345 * during the lifetime of this structure.
347 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
348 * negative error value.
351 gnutls_privkey_import_x509 (gnutls_privkey_t pkey,
352 gnutls_x509_privkey_t key, unsigned int flags)
354 int ret;
356 ret = check_if_clean(pkey);
357 if (ret < 0)
359 gnutls_assert();
360 return ret;
363 pkey->key.x509 = key;
364 pkey->type = GNUTLS_PRIVKEY_X509;
365 pkey->pk_algorithm = gnutls_x509_privkey_get_pk_algorithm (key);
366 pkey->flags = flags;
368 return 0;
371 #ifdef ENABLE_OPENPGP
373 * gnutls_privkey_import_openpgp:
374 * @pkey: The private key
375 * @key: The private key to be imported
376 * @flags: should be zero
378 * This function will import the given private key to the abstract
379 * #gnutls_privkey_t structure.
381 * The #gnutls_openpgp_privkey_t object must not be deallocated
382 * during the lifetime of this structure. The subkey set as
383 * preferred will be used, or the master key otherwise.
385 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
386 * negative error value.
389 gnutls_privkey_import_openpgp (gnutls_privkey_t pkey,
390 gnutls_openpgp_privkey_t key,
391 unsigned int flags)
393 int ret, idx;
394 uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
396 ret = check_if_clean(pkey);
397 if (ret < 0)
399 gnutls_assert();
400 return ret;
403 pkey->key.openpgp = key;
404 pkey->type = GNUTLS_PRIVKEY_OPENPGP;
406 ret = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid);
407 if (ret == GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR)
409 pkey->pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm(key, NULL);
411 else
413 if (ret < 0)
414 return gnutls_assert_val(ret);
416 idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid);
418 pkey->pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, NULL);
421 pkey->flags = flags;
423 return 0;
425 #endif
428 * gnutls_privkey_sign_data:
429 * @signer: Holds the key
430 * @hash: should be a digest algorithm
431 * @flags: should be 0 for now
432 * @data: holds the data to be signed
433 * @signature: will contain the signature allocate with gnutls_malloc()
435 * This function will sign the given data using a signature algorithm
436 * supported by the private key. Signature algorithms are always used
437 * together with a hash functions. Different hash functions may be
438 * used for the RSA algorithm, but only SHA-1 for the DSA keys.
440 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
441 * negative error value.
443 * Since: 2.12.0
446 gnutls_privkey_sign_data (gnutls_privkey_t signer,
447 gnutls_digest_algorithm_t hash,
448 unsigned int flags,
449 const gnutls_datum_t * data,
450 gnutls_datum_t * signature)
452 int ret;
453 gnutls_datum_t digest;
455 ret = pk_hash_data (signer->pk_algorithm, hash, NULL, data, &digest);
456 if (ret < 0)
458 gnutls_assert ();
459 return ret;
462 ret = pk_prepare_hash (signer->pk_algorithm, hash, &digest);
463 if (ret < 0)
465 gnutls_assert ();
466 goto cleanup;
469 ret = _gnutls_privkey_sign_hash (signer, &digest, signature);
470 _gnutls_free_datum (&digest);
472 if (ret < 0)
474 gnutls_assert ();
475 return ret;
478 return 0;
480 cleanup:
481 _gnutls_free_datum (&digest);
482 return ret;
486 * gnutls_privkey_sign_hash:
487 * @signer: Holds the signer's key
488 * @hash_algo: The hash algorithm used
489 * @flags: zero for now
490 * @hash_data: holds the data to be signed
491 * @signature: will contain newly allocated signature
493 * This function will sign the given hashed data using a signature algorithm
494 * supported by the private key. Signature algorithms are always used
495 * together with a hash functions. Different hash functions may be
496 * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
498 * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine
499 * the hash algorithm.
501 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
502 * negative error value.
504 * Since: 2.12.0
507 gnutls_privkey_sign_hash (gnutls_privkey_t signer,
508 gnutls_digest_algorithm_t hash_algo,
509 unsigned int flags,
510 const gnutls_datum_t * hash_data,
511 gnutls_datum_t * signature)
513 int ret;
514 gnutls_datum_t digest;
516 digest.data = gnutls_malloc (hash_data->size);
517 if (digest.data == NULL)
519 gnutls_assert ();
520 return GNUTLS_E_MEMORY_ERROR;
522 digest.size = hash_data->size;
523 memcpy (digest.data, hash_data->data, digest.size);
525 ret = pk_prepare_hash (signer->pk_algorithm, hash_algo, &digest);
526 if (ret < 0)
528 gnutls_assert ();
529 goto cleanup;
532 ret = _gnutls_privkey_sign_hash (signer, &digest, signature);
533 if (ret < 0)
535 gnutls_assert ();
536 goto cleanup;
539 ret = 0;
541 cleanup:
542 _gnutls_free_datum (&digest);
543 return ret;
547 * _gnutls_privkey_sign_hash:
548 * @key: Holds the key
549 * @data: holds the data to be signed
550 * @signature: will contain the signature allocate with gnutls_malloc()
552 * This function will sign the given data using a signature algorithm
553 * supported by the private key.
555 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
556 * negative error value.
559 _gnutls_privkey_sign_hash (gnutls_privkey_t key,
560 const gnutls_datum_t * hash,
561 gnutls_datum_t * signature)
563 switch (key->type)
565 #ifdef ENABLE_OPENPGP
566 case GNUTLS_PRIVKEY_OPENPGP:
567 return gnutls_openpgp_privkey_sign_hash (key->key.openpgp,
568 hash, signature);
569 #endif
570 case GNUTLS_PRIVKEY_PKCS11:
571 return _gnutls_pkcs11_privkey_sign_hash (key->key.pkcs11,
572 hash, signature);
573 case GNUTLS_PRIVKEY_X509:
574 return _gnutls_soft_sign (key->key.x509->pk_algorithm,
575 key->key.x509->params,
576 key->key.x509->params_size, hash, signature);
577 default:
578 gnutls_assert ();
579 return GNUTLS_E_INVALID_REQUEST;
584 * gnutls_privkey_decrypt_data:
585 * @key: Holds the key
586 * @flags: zero for now
587 * @ciphertext: holds the data to be decrypted
588 * @plaintext: will contain the decrypted data, allocated with gnutls_malloc()
590 * This function will decrypt the given data using the algorithm
591 * supported by the private key.
593 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
594 * negative error value.
597 gnutls_privkey_decrypt_data (gnutls_privkey_t key,
598 unsigned int flags,
599 const gnutls_datum_t * ciphertext,
600 gnutls_datum_t * plaintext)
602 if (key->pk_algorithm != GNUTLS_PK_RSA)
604 gnutls_assert ();
605 return GNUTLS_E_INVALID_REQUEST;
608 switch (key->type)
610 #ifdef ENABLE_OPENPGP
611 case GNUTLS_PRIVKEY_OPENPGP:
612 return _gnutls_openpgp_privkey_decrypt_data (key->key.openpgp, flags,
613 ciphertext, plaintext);
614 #endif
615 case GNUTLS_PRIVKEY_X509:
616 return _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext,
617 key->key.x509->params,
618 key->key.x509->params_size, 2);
619 case GNUTLS_PRIVKEY_PKCS11:
620 return _gnutls_pkcs11_privkey_decrypt_data (key->key.pkcs11,
621 flags,
622 ciphertext, plaintext);
623 default:
624 gnutls_assert ();
625 return GNUTLS_E_INVALID_REQUEST;