2 * GnuTLS PKCS#11 support
3 * Copyright (C) 2010 Free Software Foundation
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,
23 #include <gnutls_int.h>
24 #include <gnutls/pkcs11.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>
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
;
45 gnutls_x509_privkey_t x509
;
47 gnutls_pkcs11_privkey_t pkcs11
;
50 gnutls_openpgp_privkey_t openpgp
;
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.
68 gnutls_privkey_get_type (gnutls_privkey_t key
)
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.
86 gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key
, unsigned int *bits
)
91 case GNUTLS_PRIVKEY_OPENPGP
:
92 return gnutls_openpgp_privkey_get_pk_algorithm (key
->key
.openpgp
, bits
);
95 case GNUTLS_PRIVKEY_PKCS11
:
96 return gnutls_pkcs11_privkey_get_pk_algorithm (key
->key
.pkcs11
, bits
);
98 case GNUTLS_PRIVKEY_X509
:
100 *bits
= _gnutls_mpi_get_nbits (key
->key
.x509
->params
[0]);
101 return gnutls_x509_privkey_get_pk_algorithm (key
->key
.x509
);
104 return GNUTLS_E_INVALID_REQUEST
;
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
)
119 if (*new_params_size
< RSA_PUBLIC_PARAMS
120 || params_size
< RSA_PRIVATE_PARAMS
)
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
)
134 ret
= GNUTLS_E_MEMORY_ERROR
;
140 if (*new_params_size
< DSA_PUBLIC_PARAMS
141 || params_size
< DSA_PRIVATE_PARAMS
)
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
)
158 ret
= GNUTLS_E_MEMORY_ERROR
;
165 return GNUTLS_E_INVALID_REQUEST
;
170 for (i
= 0; i
< *new_params_size
; i
++)
171 _gnutls_mpi_release (new_params
[i
]);
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
)
183 gnutls_pk_algorithm_t pk
= gnutls_privkey_get_pk_algorithm (key
, NULL
);
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
;
193 uint8_t keyid
[GNUTLS_OPENPGP_KEYID_SIZE
];
196 gnutls_openpgp_privkey_get_preferred_key_id (key
->key
.openpgp
,
200 KEYID_IMPORT (kid
, keyid
);
201 ret
= _gnutls_openpgp_privkey_get_mpis (key
->key
.openpgp
, kid
,
206 ret
= _gnutls_openpgp_privkey_get_mpis (key
->key
.openpgp
, NULL
,
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
]);
227 case GNUTLS_PRIVKEY_X509
:
228 ret
= privkey_to_pubkey (pk
,
229 key
->key
.x509
->params
,
230 key
->key
.x509
->params_size
, params
,
235 return GNUTLS_E_INVALID_REQUEST
;
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
));
257 return GNUTLS_E_MEMORY_ERROR
;
264 * gnutls_privkey_deinit:
265 * @key: The structure to be deinitialized
267 * This function will deinitialize a private key structure.
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
)
277 #ifdef ENABLE_OPENPGP
278 case GNUTLS_PRIVKEY_OPENPGP
:
279 gnutls_openpgp_privkey_deinit (key
->key
.openpgp
);
283 case GNUTLS_PRIVKEY_PKCS11
:
284 gnutls_pkcs11_privkey_deinit (key
->key
.pkcs11
);
287 case GNUTLS_PRIVKEY_X509
:
288 gnutls_x509_privkey_deinit (key
->key
.x509
);
294 /* will fail if the private key contains an actual key.
296 static int check_if_clean(gnutls_privkey_t key
)
299 return GNUTLS_E_INVALID_REQUEST
;
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
)
327 ret
= check_if_clean(pkey
);
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
);
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
)
368 ret
= check_if_clean(pkey
);
375 if (flags
& GNUTLS_PRIVKEY_IMPORT_COPY
)
377 ret
= gnutls_x509_privkey_init(&pkey
->key
.x509
);
379 return gnutls_assert_val(ret
);
381 ret
= gnutls_x509_privkey_cpy(pkey
->key
.x509
, key
);
384 gnutls_x509_privkey_deinit(pkey
->key
.x509
);
385 return gnutls_assert_val(ret
);
389 pkey
->key
.x509
= key
;
391 pkey
->type
= GNUTLS_PRIVKEY_X509
;
392 pkey
->pk_algorithm
= gnutls_x509_privkey_get_pk_algorithm (key
);
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
,
421 uint8_t keyid
[GNUTLS_OPENPGP_KEYID_SIZE
];
423 ret
= check_if_clean(pkey
);
430 if (flags
& GNUTLS_PRIVKEY_IMPORT_COPY
)
432 ret
= gnutls_openpgp_privkey_init(&pkey
->key
.openpgp
);
434 return gnutls_assert_val(ret
);
436 ret
= _gnutls_openpgp_privkey_cpy(pkey
->key
.openpgp
, key
);
439 gnutls_openpgp_privkey_deinit(pkey
->key
.openpgp
);
440 return gnutls_assert_val(ret
);
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
);
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
);
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.
488 gnutls_privkey_sign_data (gnutls_privkey_t signer
,
489 gnutls_digest_algorithm_t hash
,
491 const gnutls_datum_t
* data
,
492 gnutls_datum_t
* signature
)
495 gnutls_datum_t digest
;
497 ret
= pk_hash_data (signer
->pk_algorithm
, hash
, NULL
, data
, &digest
);
504 ret
= pk_prepare_hash (signer
->pk_algorithm
, hash
, &digest
);
511 ret
= _gnutls_privkey_sign_hash (signer
, &digest
, signature
);
512 _gnutls_free_datum (&digest
);
523 _gnutls_free_datum (&digest
);
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.
549 gnutls_privkey_sign_hash (gnutls_privkey_t signer
,
550 gnutls_digest_algorithm_t hash_algo
,
552 const gnutls_datum_t
* hash_data
,
553 gnutls_datum_t
* signature
)
556 gnutls_datum_t digest
;
558 digest
.data
= gnutls_malloc (hash_data
->size
);
559 if (digest
.data
== NULL
)
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
);
574 ret
= _gnutls_privkey_sign_hash (signer
, &digest
, signature
);
584 _gnutls_free_datum (&digest
);
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
)
607 #ifdef ENABLE_OPENPGP
608 case GNUTLS_PRIVKEY_OPENPGP
:
609 return gnutls_openpgp_privkey_sign_hash (key
->key
.openpgp
,
613 case GNUTLS_PRIVKEY_PKCS11
:
614 return _gnutls_pkcs11_privkey_sign_hash (key
->key
.pkcs11
,
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
);
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
,
643 const gnutls_datum_t
* ciphertext
,
644 gnutls_datum_t
* plaintext
)
646 if (key
->pk_algorithm
!= GNUTLS_PK_RSA
)
649 return GNUTLS_E_INVALID_REQUEST
;
654 #ifdef ENABLE_OPENPGP
655 case GNUTLS_PRIVKEY_OPENPGP
:
656 return _gnutls_openpgp_privkey_decrypt_data (key
->key
.openpgp
, flags
,
657 ciphertext
, plaintext
);
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);
664 case GNUTLS_PRIVKEY_PKCS11
:
665 return _gnutls_pkcs11_privkey_decrypt_data (key
->key
.pkcs11
,
667 ciphertext
, plaintext
);
671 return GNUTLS_E_INVALID_REQUEST
;