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 <pakchois/pakchois.h>
25 #include <gnutls/pkcs11.h>
29 #include <gnutls_errors.h>
30 #include <gnutls_datum.h>
31 #include <pkcs11_int.h>
32 #include <gnutls/abstract.h>
33 #include <gnutls_pk.h>
35 #include <openpgp/openpgp_int.h>
36 #include <openpgp/gnutls_openpgp.h>
37 #include <gnutls_sig.h>
38 #include <abstract_int.h>
40 struct gnutls_privkey_st
42 gnutls_privkey_type_t type
;
43 gnutls_pk_algorithm_t pk_algorithm
;
47 gnutls_x509_privkey_t x509
;
48 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
);
94 case GNUTLS_PRIVKEY_PKCS11
:
95 return gnutls_pkcs11_privkey_get_pk_algorithm (key
->key
.pkcs11
, bits
);
96 case GNUTLS_PRIVKEY_X509
:
98 *bits
= _gnutls_mpi_get_nbits (key
->key
.x509
->params
[0]);
99 return gnutls_x509_privkey_get_pk_algorithm (key
->key
.x509
);
102 return GNUTLS_E_INVALID_REQUEST
;
108 privkey_to_pubkey (gnutls_pk_algorithm_t pk
,
109 const bigint_t
* params
, int params_size
,
110 bigint_t
* new_params
, int *new_params_size
)
117 if (*new_params_size
< RSA_PUBLIC_PARAMS
118 || params_size
< RSA_PRIVATE_PARAMS
)
121 return GNUTLS_E_INVALID_REQUEST
;
124 new_params
[0] = _gnutls_mpi_copy (params
[0]);
125 new_params
[1] = _gnutls_mpi_copy (params
[1]);
127 *new_params_size
= RSA_PUBLIC_PARAMS
;
129 if (new_params
[0] == NULL
|| new_params
[1] == NULL
)
132 ret
= GNUTLS_E_MEMORY_ERROR
;
138 if (*new_params_size
< DSA_PUBLIC_PARAMS
139 || params_size
< DSA_PRIVATE_PARAMS
)
142 return GNUTLS_E_INVALID_REQUEST
;
145 new_params
[0] = _gnutls_mpi_copy (params
[0]);
146 new_params
[1] = _gnutls_mpi_copy (params
[1]);
147 new_params
[2] = _gnutls_mpi_copy (params
[2]);
148 new_params
[3] = _gnutls_mpi_copy (params
[3]);
150 *new_params_size
= DSA_PUBLIC_PARAMS
;
152 if (new_params
[0] == NULL
|| new_params
[1] == NULL
||
153 new_params
[2] == NULL
|| new_params
[3] == NULL
)
156 ret
= GNUTLS_E_MEMORY_ERROR
;
163 return GNUTLS_E_INVALID_REQUEST
;
168 for (i
= 0; i
< *new_params_size
; i
++)
169 _gnutls_mpi_release (new_params
[i
]);
174 /* Returns the public key of the private key (if possible)
177 _gnutls_privkey_get_public_mpis (gnutls_privkey_t key
,
178 bigint_t
* params
, int *params_size
)
181 gnutls_pk_algorithm_t pk
= gnutls_privkey_get_pk_algorithm (key
, NULL
);
185 #ifdef ENABLE_OPENPGP
186 case GNUTLS_PRIVKEY_OPENPGP
:
188 bigint_t tmp_params
[MAX_PRIV_PARAMS_SIZE
];
189 int tmp_params_size
= MAX_PRIV_PARAMS_SIZE
;
191 gnutls_openpgp_keyid_t keyid
;
194 gnutls_openpgp_privkey_get_preferred_key_id (key
->key
.openpgp
,
198 KEYID_IMPORT (kid
, keyid
);
199 ret
= _gnutls_openpgp_privkey_get_mpis (key
->key
.openpgp
, kid
,
204 ret
= _gnutls_openpgp_privkey_get_mpis (key
->key
.openpgp
, NULL
,
214 ret
= privkey_to_pubkey (pk
,
215 tmp_params
, tmp_params_size
,
216 params
, params_size
);
218 for (i
= 0; i
< tmp_params_size
; i
++)
219 _gnutls_mpi_release (&tmp_params
[i
]);
225 case GNUTLS_PRIVKEY_X509
:
226 ret
= privkey_to_pubkey (pk
,
227 key
->key
.x509
->params
,
228 key
->key
.x509
->params_size
, params
,
233 return GNUTLS_E_INVALID_REQUEST
;
240 * gnutls_privkey_init:
241 * @key: The structure to be initialized
243 * This function will initialize an private key structure.
245 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
246 * negative error value.
249 gnutls_privkey_init (gnutls_privkey_t
* key
)
251 *key
= gnutls_calloc (1, sizeof (struct gnutls_privkey_st
));
255 return GNUTLS_E_MEMORY_ERROR
;
262 * gnutls_privkey_deinit:
263 * @key: The structure to be deinitialized
265 * This function will deinitialize a private key structure.
268 gnutls_privkey_deinit (gnutls_privkey_t key
)
270 if (key
->flags
& GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
)
273 #ifdef ENABLE_OPENPGP
274 case GNUTLS_PRIVKEY_OPENPGP
:
275 return gnutls_openpgp_privkey_deinit (key
->key
.openpgp
);
277 case GNUTLS_PRIVKEY_PKCS11
:
278 return gnutls_pkcs11_privkey_deinit (key
->key
.pkcs11
);
279 case GNUTLS_PRIVKEY_X509
:
280 return gnutls_x509_privkey_deinit (key
->key
.x509
);
285 /* will fail if the private key contains an actual key.
287 static int check_if_clean(gnutls_privkey_t key
)
290 return GNUTLS_E_INVALID_REQUEST
;
296 * gnutls_privkey_import_pkcs11:
297 * @pkey: The private key
298 * @key: The private key to be imported
299 * @flags: should be zero
301 * This function will import the given private key to the abstract
302 * #gnutls_privkey_t structure.
304 * The #gnutls_pkcs11_privkey_t object must not be deallocated
305 * during the lifetime of this structure.
307 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
308 * negative error value.
311 gnutls_privkey_import_pkcs11 (gnutls_privkey_t pkey
,
312 gnutls_pkcs11_privkey_t key
, unsigned int flags
)
316 ret
= check_if_clean(pkey
);
323 pkey
->key
.pkcs11
= key
;
324 pkey
->type
= GNUTLS_PRIVKEY_PKCS11
;
325 pkey
->pk_algorithm
= gnutls_pkcs11_privkey_get_pk_algorithm (key
, NULL
);
332 * gnutls_privkey_import_x509:
333 * @pkey: The private key
334 * @key: The private key to be imported
335 * @flags: should be zero
337 * This function will import the given private key to the abstract
338 * #gnutls_privkey_t structure.
340 * The #gnutls_x509_privkey_t object must not be deallocated
341 * during the lifetime of this structure.
343 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
344 * negative error value.
347 gnutls_privkey_import_x509 (gnutls_privkey_t pkey
,
348 gnutls_x509_privkey_t key
, unsigned int flags
)
352 ret
= check_if_clean(pkey
);
359 pkey
->key
.x509
= key
;
360 pkey
->type
= GNUTLS_PRIVKEY_X509
;
361 pkey
->pk_algorithm
= gnutls_x509_privkey_get_pk_algorithm (key
);
367 #ifdef ENABLE_OPENPGP
369 * gnutls_privkey_import_openpgp:
370 * @pkey: The private key
371 * @key: The private key to be imported
372 * @flags: should be zero
374 * This function will import the given private key to the abstract
375 * #gnutls_privkey_t structure.
377 * The #gnutls_openpgp_privkey_t object must not be deallocated
378 * during the lifetime of this structure.
380 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
381 * negative error value.
384 gnutls_privkey_import_openpgp (gnutls_privkey_t pkey
,
385 gnutls_openpgp_privkey_t key
,
390 ret
= check_if_clean(pkey
);
397 pkey
->key
.openpgp
= key
;
398 pkey
->type
= GNUTLS_PRIVKEY_OPENPGP
;
399 pkey
->pk_algorithm
= gnutls_openpgp_privkey_get_pk_algorithm (key
, NULL
);
407 * gnutls_privkey_sign_data2:
408 * @signer: Holds the key
409 * @digest: should be a digest algorithm
410 * @flags: should be 0 for now
411 * @data: holds the data to be signed
412 * @signature: will contain the signature allocate with gnutls_malloc()
414 * This function will sign the given data using a signature algorithm
415 * supported by the private key. Signature algorithms are always used
416 * together with a hash functions. Different hash functions may be
417 * used for the RSA algorithm, but only SHA-1 for the DSA keys.
419 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
420 * negative error value.
425 gnutls_privkey_sign_data (gnutls_privkey_t signer
,
426 gnutls_digest_algorithm_t hash
,
428 const gnutls_datum_t
* data
,
429 gnutls_datum_t
* signature
)
432 gnutls_datum_t digest
;
434 ret
= pk_hash_data (signer
->pk_algorithm
, hash
, NULL
, data
, &digest
);
441 ret
= pk_prepare_hash (signer
->pk_algorithm
, hash
, &digest
);
448 ret
= _gnutls_privkey_sign_hash (signer
, &digest
, signature
);
449 _gnutls_free_datum (&digest
);
460 _gnutls_free_datum (&digest
);
465 * gnutls_privkey_sign_hash:
466 * @signer: Holds the signer's key
467 * @hash_algo: The hash algorithm used
468 * @flags: zero for now
469 * @hash_data: holds the data to be signed
470 * @signature: will contain newly allocated signature
472 * This function will sign the given hashed data using a signature algorithm
473 * supported by the private key. Signature algorithms are always used
474 * together with a hash functions. Different hash functions may be
475 * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
477 * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine
478 * the hash algorithm.
480 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
481 * negative error value.
486 gnutls_privkey_sign_hash (gnutls_privkey_t signer
,
487 gnutls_digest_algorithm_t hash_algo
,
489 const gnutls_datum_t
* hash_data
,
490 gnutls_datum_t
* signature
)
493 gnutls_datum_t digest
;
495 digest
.data
= gnutls_malloc (hash_data
->size
);
496 if (digest
.data
== NULL
)
499 return GNUTLS_E_MEMORY_ERROR
;
501 digest
.size
= hash_data
->size
;
502 memcpy (digest
.data
, hash_data
->data
, digest
.size
);
504 ret
= pk_prepare_hash (signer
->pk_algorithm
, hash_algo
, &digest
);
511 ret
= _gnutls_privkey_sign_hash (signer
, &digest
, signature
);
521 _gnutls_free_datum (&digest
);
526 * _gnutls_privkey_sign_hash:
527 * @key: Holds the key
528 * @data: holds the data to be signed
529 * @signature: will contain the signature allocate with gnutls_malloc()
531 * This function will sign the given data using a signature algorithm
532 * supported by the private key.
534 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
535 * negative error value.
538 _gnutls_privkey_sign_hash (gnutls_privkey_t key
,
539 const gnutls_datum_t
* hash
,
540 gnutls_datum_t
* signature
)
544 #ifdef ENABLE_OPENPGP
545 case GNUTLS_PRIVKEY_OPENPGP
:
546 return gnutls_openpgp_privkey_sign_hash (key
->key
.openpgp
,
549 case GNUTLS_PRIVKEY_PKCS11
:
550 return _gnutls_pkcs11_privkey_sign_hash (key
->key
.pkcs11
,
552 case GNUTLS_PRIVKEY_X509
:
553 return _gnutls_soft_sign (key
->key
.x509
->pk_algorithm
,
554 key
->key
.x509
->params
,
555 key
->key
.x509
->params_size
, hash
, signature
);
558 return GNUTLS_E_INVALID_REQUEST
;
563 * gnutls_privkey_decrypt_data:
564 * @key: Holds the key
565 * @flags: zero for now
566 * @ciphertext: holds the data to be decrypted
567 * @plaintext: will contain the decrypted data, allocated with gnutls_malloc()
569 * This function will decrypt the given data using the algorithm
570 * supported by the private key.
572 * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
573 * negative error value.
576 gnutls_privkey_decrypt_data (gnutls_privkey_t key
,
578 const gnutls_datum_t
* ciphertext
,
579 gnutls_datum_t
* plaintext
)
581 if (key
->pk_algorithm
!= GNUTLS_PK_RSA
)
584 return GNUTLS_E_INVALID_REQUEST
;
589 #ifdef ENABLE_OPENPGP
590 case GNUTLS_PRIVKEY_OPENPGP
:
591 return _gnutls_openpgp_privkey_decrypt_data (key
->key
.openpgp
, flags
,
592 ciphertext
, plaintext
);
594 case GNUTLS_PRIVKEY_X509
:
595 return _gnutls_pkcs1_rsa_decrypt (plaintext
, ciphertext
,
596 key
->key
.x509
->params
,
597 key
->key
.x509
->params_size
, 2);
598 case GNUTLS_PRIVKEY_PKCS11
:
599 return _gnutls_pkcs11_privkey_decrypt_data (key
->key
.pkcs11
,
601 ciphertext
, plaintext
);
604 return GNUTLS_E_INVALID_REQUEST
;