2 * GnuTLS public key support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * The GnuTLS is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>
21 #include <gnutls_int.h>
22 #include <gnutls/pkcs11.h>
25 #include <gnutls_errors.h>
26 #include <gnutls_datum.h>
27 #include <pkcs11_int.h>
28 #include <gnutls/abstract.h>
29 #include <gnutls_sig.h>
30 #include <gnutls_pk.h>
32 #include <openpgp/openpgp_int.h>
33 #include <gnutls_num.h>
34 #include <x509/common.h>
36 #include <abstract_int.h>
37 #include <gnutls_ecc.h>
39 #define PK_PEM_HEADER "PUBLIC KEY"
41 #define OPENPGP_KEY_PRIMARY 2
42 #define OPENPGP_KEY_SUBKEY 1
45 int pubkey_to_bits(gnutls_pk_algorithm_t pk
, gnutls_pk_params_st
* params
)
50 return _gnutls_mpi_get_nbits(params
->params
[0]);
52 return _gnutls_mpi_get_nbits(params
->params
[3]);
54 return gnutls_ecc_curve_get_size(params
->flags
)*8;
61 * gnutls_pubkey_get_pk_algorithm:
62 * @key: should contain a #gnutls_pubkey_t structure
63 * @bits: If set will return the number of bits of the parameters (may be NULL)
65 * This function will return the public key algorithm of a public
66 * key and if possible will return a number of bits that indicates
67 * the security parameter of the key.
69 * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
70 * success, or a negative error code on error.
75 gnutls_pubkey_get_pk_algorithm (gnutls_pubkey_t key
, unsigned int *bits
)
80 return key
->pk_algorithm
;
84 * gnutls_pubkey_get_key_usage:
85 * @key: should contain a #gnutls_pubkey_t structure
86 * @usage: If set will return the number of bits of the parameters (may be NULL)
88 * This function will return the key usage of the public key.
90 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
91 * negative error value.
96 gnutls_pubkey_get_key_usage (gnutls_pubkey_t key
, unsigned int *usage
)
99 *usage
= key
->key_usage
;
105 * gnutls_pubkey_init:
106 * @key: The structure to be initialized
108 * This function will initialize an public key structure.
110 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
111 * negative error value.
116 gnutls_pubkey_init (gnutls_pubkey_t
* key
)
118 *key
= gnutls_calloc (1, sizeof (struct gnutls_pubkey_st
));
122 return GNUTLS_E_MEMORY_ERROR
;
129 * gnutls_pubkey_deinit:
130 * @key: The structure to be deinitialized
132 * This function will deinitialize a public key structure.
137 gnutls_pubkey_deinit (gnutls_pubkey_t key
)
141 gnutls_pk_params_release (&key
->params
);
146 * gnutls_pubkey_import_x509:
147 * @key: The public key
148 * @crt: The certificate to be imported
149 * @flags: should be zero
151 * This function will import the given public key to the abstract
152 * #gnutls_pubkey_t structure.
154 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
155 * negative error value.
160 gnutls_pubkey_import_x509 (gnutls_pubkey_t key
, gnutls_x509_crt_t crt
,
165 key
->pk_algorithm
= gnutls_x509_crt_get_pk_algorithm (crt
, &key
->bits
);
167 ret
= gnutls_x509_crt_get_key_usage (crt
, &key
->key_usage
, NULL
);
171 ret
= _gnutls_x509_crt_get_mpis (crt
, &key
->params
);
182 * gnutls_pubkey_import_privkey:
183 * @key: The public key
184 * @pkey: The private key
185 * @usage: GNUTLS_KEY_* key usage flags.
186 * @flags: should be zero
188 * Imports the public key from a private. This function will import
189 * the given public key to the abstract #gnutls_pubkey_t structure.
191 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
192 * negative error value.
197 gnutls_pubkey_import_privkey (gnutls_pubkey_t key
, gnutls_privkey_t pkey
,
198 unsigned int usage
, unsigned int flags
)
200 key
->pk_algorithm
= gnutls_privkey_get_pk_algorithm (pkey
, &key
->bits
);
202 key
->key_usage
= usage
;
204 return _gnutls_privkey_get_public_mpis (pkey
, &key
->params
);
208 * gnutls_pubkey_get_preferred_hash_algorithm:
209 * @key: Holds the certificate
210 * @hash: The result of the call with the hash algorithm used for signature
211 * @mand: If non zero it means that the algorithm MUST use this hash. May be NULL.
213 * This function will read the certifcate and return the appropriate digest
214 * algorithm to use for signing with this certificate. Some certificates (i.e.
215 * DSA might not be able to sign without the preferred algorithm).
217 * Returns: the 0 if the hash algorithm is found. A negative error code is
223 gnutls_pubkey_get_preferred_hash_algorithm (gnutls_pubkey_t key
,
224 gnutls_digest_algorithm_t
*
225 hash
, unsigned int *mand
)
232 return GNUTLS_E_INVALID_REQUEST
;
235 ret
= _gnutls_pk_get_hash_algorithm (key
->pk_algorithm
,
245 * gnutls_pubkey_import_pkcs11:
246 * @key: The public key
247 * @obj: The parameters to be imported
248 * @flags: should be zero
250 * Imports a public key from a pkcs11 key. This function will import
251 * the given public key to the abstract #gnutls_pubkey_t structure.
253 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
254 * negative error value.
259 gnutls_pubkey_import_pkcs11 (gnutls_pubkey_t key
,
260 gnutls_pkcs11_obj_t obj
, unsigned int flags
)
264 type
= gnutls_pkcs11_obj_get_type (obj
);
265 if (type
!= GNUTLS_PKCS11_OBJ_PUBKEY
&& type
!= GNUTLS_PKCS11_OBJ_X509_CRT
)
268 return GNUTLS_E_INVALID_REQUEST
;
271 if (type
== GNUTLS_PKCS11_OBJ_X509_CRT
)
273 gnutls_x509_crt_t xcrt
;
275 ret
= gnutls_x509_crt_init (&xcrt
);
282 ret
= gnutls_x509_crt_import_pkcs11 (xcrt
, obj
);
289 ret
= gnutls_pubkey_import_x509 (key
, xcrt
, 0);
296 gnutls_x509_crt_get_key_usage(xcrt
, &key
->key_usage
, NULL
);
300 gnutls_x509_crt_deinit(xcrt
);
304 key
->key_usage
= obj
->key_usage
;
306 switch (obj
->pk_algorithm
)
309 ret
= gnutls_pubkey_import_rsa_raw (key
, &obj
->pubkey
[0],
313 ret
= gnutls_pubkey_import_dsa_raw (key
, &obj
->pubkey
[0],
315 &obj
->pubkey
[2], &obj
->pubkey
[3]);
318 ret
= gnutls_pubkey_import_ecc_x962 (key
, &obj
->pubkey
[0],
323 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
335 #endif /* ENABLE_PKCS11 */
337 #ifdef ENABLE_OPENPGP
340 * gnutls_pubkey_import_openpgp:
341 * @key: The public key
342 * @crt: The certificate to be imported
343 * @flags: should be zero
345 * Imports a public key from an openpgp key. This function will import
346 * the given public key to the abstract #gnutls_pubkey_t
347 * structure. The subkey set as preferred will be imported or the
348 * master key otherwise.
350 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
351 * negative error value.
356 gnutls_pubkey_import_openpgp (gnutls_pubkey_t key
,
357 gnutls_openpgp_crt_t crt
,
363 uint8_t keyid
[GNUTLS_OPENPGP_KEYID_SIZE
];
365 ret
= gnutls_openpgp_crt_get_preferred_key_id (crt
, keyid
);
366 if (ret
== GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR
)
368 key
->pk_algorithm
= gnutls_openpgp_crt_get_pk_algorithm (crt
, &key
->bits
);
369 key
->openpgp_key_id_set
= OPENPGP_KEY_PRIMARY
;
371 ret
= gnutls_openpgp_crt_get_key_id(crt
, key
->openpgp_key_id
);
373 return gnutls_assert_val(ret
);
375 ret
= gnutls_openpgp_crt_get_key_usage (crt
, &key
->key_usage
);
388 key
->openpgp_key_id_set
= OPENPGP_KEY_SUBKEY
;
390 KEYID_IMPORT (kid32
, keyid
);
393 idx
= gnutls_openpgp_crt_get_subkey_idx (crt
, keyid
);
395 ret
= gnutls_openpgp_crt_get_subkey_id(crt
, idx
, key
->openpgp_key_id
);
397 return gnutls_assert_val(ret
);
399 ret
= gnutls_openpgp_crt_get_subkey_usage (crt
, idx
, &key
->key_usage
);
403 key
->pk_algorithm
= gnutls_openpgp_crt_get_subkey_pk_algorithm (crt
, idx
, NULL
);
407 _gnutls_openpgp_crt_get_mpis (crt
, k
, &key
->params
);
409 return gnutls_assert_val(ret
);
415 * gnutls_pubkey_get_openpgp_key_id:
416 * @key: Holds the public key
417 * @flags: should be 0 for now
418 * @output_data: will contain the key ID
419 * @output_data_size: holds the size of output_data (and will be
420 * replaced by the actual size of parameters)
421 * @subkey: Will be non zero if the key ID corresponds to a subkey
423 * This function will return a unique ID the depends on the public
424 * key parameters. This ID can be used in checking whether a
425 * certificate corresponds to the given public key.
427 * If the buffer provided is not long enough to hold the output, then
428 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
429 * be returned. The output will normally be a SHA-1 hash output,
432 * Returns: In case of failure a negative error code will be
433 * returned, and 0 on success.
438 gnutls_pubkey_get_openpgp_key_id (gnutls_pubkey_t key
, unsigned int flags
,
439 unsigned char *output_data
,
440 size_t * output_data_size
,
441 unsigned int *subkey
)
446 return GNUTLS_E_INVALID_REQUEST
;
449 if (*output_data_size
< sizeof(key
->openpgp_key_id
))
451 *output_data_size
= sizeof(key
->openpgp_key_id
);
452 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER
);
455 if (key
->openpgp_key_id_set
== 0)
456 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
458 if (key
->openpgp_key_id_set
== OPENPGP_KEY_SUBKEY
)
459 if (subkey
) *subkey
= 1;
463 memcpy(output_data
, key
->openpgp_key_id
, sizeof(key
->openpgp_key_id
));
465 *output_data_size
= sizeof(key
->openpgp_key_id
);
473 * gnutls_pubkey_export:
474 * @key: Holds the certificate
475 * @format: the format of output params. One of PEM or DER.
476 * @output_data: will contain a certificate PEM or DER encoded
477 * @output_data_size: holds the size of output_data (and will be
478 * replaced by the actual size of parameters)
480 * This function will export the public key to DER or PEM format.
481 * The contents of the exported data is the SubjectPublicKeyInfo
484 * If the buffer provided is not long enough to hold the output, then
485 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
488 * If the structure is PEM encoded, it will have a header
489 * of "BEGIN CERTIFICATE".
491 * Returns: In case of failure a negative error code will be
492 * returned, and 0 on success.
497 gnutls_pubkey_export (gnutls_pubkey_t key
,
498 gnutls_x509_crt_fmt_t format
, void *output_data
,
499 size_t * output_data_size
)
502 ASN1_TYPE spk
= ASN1_TYPE_EMPTY
;
507 return GNUTLS_E_INVALID_REQUEST
;
510 if ((result
= asn1_create_element
511 (_gnutls_get_pkix (), "PKIX1.SubjectPublicKeyInfo", &spk
))
515 return _gnutls_asn2err (result
);
519 _gnutls_x509_encode_and_copy_PKI_params (spk
, "",
528 result
= _gnutls_x509_export_int_named (spk
, "",
529 format
, PK_PEM_HEADER
,
530 output_data
, output_data_size
);
540 asn1_delete_structure (&spk
);
546 * gnutls_pubkey_export2:
547 * @key: Holds the certificate
548 * @format: the format of output params. One of PEM or DER.
549 * @out: will contain a certificate PEM or DER encoded
551 * This function will export the public key to DER or PEM format.
552 * The contents of the exported data is the SubjectPublicKeyInfo
555 * The output buffer will be allocated using gnutls_malloc().
557 * If the structure is PEM encoded, it will have a header
558 * of "BEGIN CERTIFICATE".
560 * Returns: In case of failure a negative error code will be
561 * returned, and 0 on success.
566 gnutls_pubkey_export2 (gnutls_pubkey_t key
,
567 gnutls_x509_crt_fmt_t format
,
568 gnutls_datum_t
* out
)
571 ASN1_TYPE spk
= ASN1_TYPE_EMPTY
;
576 return GNUTLS_E_INVALID_REQUEST
;
579 if ((result
= asn1_create_element
580 (_gnutls_get_pkix (), "PKIX1.SubjectPublicKeyInfo", &spk
))
584 return _gnutls_asn2err (result
);
588 _gnutls_x509_encode_and_copy_PKI_params (spk
, "",
597 result
= _gnutls_x509_export_int_named2 (spk
, "",
598 format
, PK_PEM_HEADER
, out
);
608 asn1_delete_structure (&spk
);
614 * gnutls_pubkey_get_key_id:
615 * @key: Holds the public key
616 * @flags: should be 0 for now
617 * @output_data: will contain the key ID
618 * @output_data_size: holds the size of output_data (and will be
619 * replaced by the actual size of parameters)
621 * This function will return a unique ID the depends on the public
622 * key parameters. This ID can be used in checking whether a
623 * certificate corresponds to the given public key.
625 * If the buffer provided is not long enough to hold the output, then
626 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
627 * be returned. The output will normally be a SHA-1 hash output,
630 * Returns: In case of failure a negative error code will be
631 * returned, and 0 on success.
636 gnutls_pubkey_get_key_id (gnutls_pubkey_t key
, unsigned int flags
,
637 unsigned char *output_data
,
638 size_t * output_data_size
)
645 return GNUTLS_E_INVALID_REQUEST
;
649 _gnutls_get_key_id (key
->pk_algorithm
, &key
->params
,
650 output_data
, output_data_size
);
661 * gnutls_pubkey_get_pk_rsa_raw:
662 * @key: Holds the certificate
663 * @m: will hold the modulus
664 * @e: will hold the public exponent
666 * This function will export the RSA public key's parameters found in
667 * the given structure. The new parameters will be allocated using
668 * gnutls_malloc() and will be stored in the appropriate datum.
670 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
675 gnutls_pubkey_get_pk_rsa_raw (gnutls_pubkey_t key
,
676 gnutls_datum_t
* m
, gnutls_datum_t
* e
)
683 return GNUTLS_E_INVALID_REQUEST
;
686 if (key
->pk_algorithm
!= GNUTLS_PK_RSA
)
689 return GNUTLS_E_INVALID_REQUEST
;
692 ret
= _gnutls_mpi_dprint_lz (key
->params
.params
[0], m
);
699 ret
= _gnutls_mpi_dprint_lz (key
->params
.params
[1], e
);
703 _gnutls_free_datum (m
);
711 * gnutls_pubkey_get_pk_dsa_raw:
712 * @key: Holds the public key
713 * @p: will hold the p
714 * @q: will hold the q
715 * @g: will hold the g
716 * @y: will hold the y
718 * This function will export the DSA public key's parameters found in
719 * the given certificate. The new parameters will be allocated using
720 * gnutls_malloc() and will be stored in the appropriate datum.
722 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
727 gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key
,
728 gnutls_datum_t
* p
, gnutls_datum_t
* q
,
729 gnutls_datum_t
* g
, gnutls_datum_t
* y
)
736 return GNUTLS_E_INVALID_REQUEST
;
739 if (key
->pk_algorithm
!= GNUTLS_PK_DSA
)
742 return GNUTLS_E_INVALID_REQUEST
;
746 ret
= _gnutls_mpi_dprint_lz (key
->params
.params
[0], p
);
754 ret
= _gnutls_mpi_dprint_lz (key
->params
.params
[1], q
);
758 _gnutls_free_datum (p
);
764 ret
= _gnutls_mpi_dprint_lz (key
->params
.params
[2], g
);
768 _gnutls_free_datum (p
);
769 _gnutls_free_datum (q
);
775 ret
= _gnutls_mpi_dprint_lz (key
->params
.params
[3], y
);
779 _gnutls_free_datum (p
);
780 _gnutls_free_datum (g
);
781 _gnutls_free_datum (q
);
789 * gnutls_pubkey_get_pk_ecc_raw:
790 * @key: Holds the public key
791 * @curve: will hold the curve
795 * This function will export the ECC public key's parameters found in
796 * the given certificate. The new parameters will be allocated using
797 * gnutls_malloc() and will be stored in the appropriate datum.
799 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
804 gnutls_pubkey_get_pk_ecc_raw (gnutls_pubkey_t key
, gnutls_ecc_curve_t
*curve
,
805 gnutls_datum_t
* x
, gnutls_datum_t
* y
)
812 return GNUTLS_E_INVALID_REQUEST
;
815 if (key
->pk_algorithm
!= GNUTLS_PK_EC
)
818 return GNUTLS_E_INVALID_REQUEST
;
821 *curve
= key
->params
.flags
;
824 ret
= _gnutls_mpi_dprint_lz (key
->params
.params
[ECC_X
], x
);
832 ret
= _gnutls_mpi_dprint_lz (key
->params
.params
[ECC_Y
], y
);
836 _gnutls_free_datum (x
);
844 * gnutls_pubkey_get_pk_ecc_x962:
845 * @key: Holds the public key
846 * @parameters: DER encoding of an ANSI X9.62 parameters
847 * @ecpoint: DER encoding of ANSI X9.62 ECPoint
849 * This function will export the ECC public key's parameters found in
850 * the given certificate. The new parameters will be allocated using
851 * gnutls_malloc() and will be stored in the appropriate datum.
853 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
857 int gnutls_pubkey_get_pk_ecc_x962 (gnutls_pubkey_t key
, gnutls_datum_t
* parameters
,
858 gnutls_datum_t
* ecpoint
)
862 if (key
== NULL
|| key
->pk_algorithm
!= GNUTLS_PK_EC
)
863 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
865 ret
= _gnutls_x509_write_ecc_pubkey(&key
->params
, ecpoint
);
867 return gnutls_assert_val(ret
);
869 ret
= _gnutls_x509_write_ecc_params(&key
->params
, parameters
);
872 _gnutls_free_datum(ecpoint
);
873 return gnutls_assert_val(ret
);
880 * gnutls_pubkey_import:
881 * @key: The structure to store the parsed public key.
882 * @data: The DER or PEM encoded certificate.
883 * @format: One of DER or PEM
885 * This function will import the provided public key in
886 * a SubjectPublicKeyInfo X.509 structure to a native
887 * %gnutls_pubkey_t structure. The output will be stored
888 * in @key. If the public key is PEM encoded it should have a header
891 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
892 * negative error value.
897 gnutls_pubkey_import (gnutls_pubkey_t key
,
898 const gnutls_datum_t
* data
,
899 gnutls_x509_crt_fmt_t format
)
901 int result
= 0, need_free
= 0;
902 gnutls_datum_t _data
;
908 return GNUTLS_E_INVALID_REQUEST
;
911 _data
.data
= data
->data
;
912 _data
.size
= data
->size
;
914 /* If the Certificate is in PEM format then decode it
916 if (format
== GNUTLS_X509_FMT_PEM
)
918 /* Try the first header */
920 _gnutls_fbase64_decode (PK_PEM_HEADER
, data
->data
, data
->size
, &_data
);
931 if ((result
= asn1_create_element
932 (_gnutls_get_pkix (), "PKIX1.SubjectPublicKeyInfo", &spk
))
936 result
= _gnutls_asn2err (result
);
940 result
= asn1_der_decoding (&spk
, _data
.data
, _data
.size
, NULL
);
941 if (result
!= ASN1_SUCCESS
)
944 result
= _gnutls_asn2err (result
);
948 result
= _gnutls_get_asn_mpis (spk
, "", &key
->params
);
955 /* this has already been called by get_asn_mpis() thus it cannot
958 key
->pk_algorithm
= _gnutls_x509_get_pk_algorithm (spk
, "", NULL
);
959 key
->bits
= pubkey_to_bits(key
->pk_algorithm
, &key
->params
);
964 asn1_delete_structure (&spk
);
967 _gnutls_free_datum (&_data
);
972 * gnutls_x509_crt_set_pubkey:
973 * @crt: should contain a #gnutls_x509_crt_t structure
974 * @key: holds a public key
976 * This function will set the public parameters from the given public
977 * key to the request.
979 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
980 * negative error value.
985 gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt
, gnutls_pubkey_t key
)
992 return GNUTLS_E_INVALID_REQUEST
;
995 result
= _gnutls_x509_encode_and_copy_PKI_params (crt
->cert
,
996 "tbsCertificate.subjectPublicKeyInfo",
1007 gnutls_x509_crt_set_key_usage (crt
, key
->key_usage
);
1013 * gnutls_x509_crq_set_pubkey:
1014 * @crq: should contain a #gnutls_x509_crq_t structure
1015 * @key: holds a public key
1017 * This function will set the public parameters from the given public
1018 * key to the request.
1020 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1021 * negative error value.
1026 gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq
, gnutls_pubkey_t key
)
1033 return GNUTLS_E_INVALID_REQUEST
;
1036 result
= _gnutls_x509_encode_and_copy_PKI_params
1038 "certificationRequestInfo.subjectPKInfo",
1039 key
->pk_algorithm
, &key
->params
);
1048 gnutls_x509_crq_set_key_usage (crq
, key
->key_usage
);
1054 * gnutls_pubkey_set_key_usage:
1055 * @key: a certificate of type #gnutls_x509_crt_t
1056 * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
1058 * This function will set the key usage flags of the public key. This
1059 * is only useful if the key is to be exported to a certificate or
1060 * certificate request.
1062 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1063 * negative error value.
1068 gnutls_pubkey_set_key_usage (gnutls_pubkey_t key
, unsigned int usage
)
1070 key
->key_usage
= usage
;
1075 #ifdef ENABLE_PKCS11
1078 * gnutls_pubkey_import_pkcs11_url:
1079 * @key: A key of type #gnutls_pubkey_t
1080 * @url: A PKCS 11 url
1081 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1083 * This function will import a PKCS 11 certificate to a #gnutls_pubkey_t
1086 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1087 * negative error value.
1092 gnutls_pubkey_import_pkcs11_url (gnutls_pubkey_t key
, const char *url
,
1095 gnutls_pkcs11_obj_t pcrt
;
1098 ret
= gnutls_pkcs11_obj_init (&pcrt
);
1106 gnutls_pkcs11_obj_set_pin_function(pcrt
, key
->pin
.cb
, key
->pin
.data
);
1108 ret
= gnutls_pkcs11_obj_import_url (pcrt
, url
, flags
);
1115 ret
= gnutls_pubkey_import_pkcs11 (key
, pcrt
, 0);
1125 gnutls_pkcs11_obj_deinit (pcrt
);
1130 #endif /* ENABLE_PKCS11 */
1133 * gnutls_pubkey_import_url:
1134 * @key: A key of type #gnutls_pubkey_t
1135 * @url: A PKCS 11 url
1136 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1138 * This function will import a PKCS11 certificate or a TPM key
1141 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1142 * negative error value.
1147 gnutls_pubkey_import_url (gnutls_pubkey_t key
, const char *url
,
1150 #ifdef ENABLE_PKCS11
1151 if (strstr(url
, "pkcs11:") != NULL
)
1152 return gnutls_pubkey_import_pkcs11_url(key
, url
, flags
);
1154 #ifdef HAVE_TROUSERS
1155 if (strstr(url
, "tpmkey:") != NULL
)
1156 return gnutls_pubkey_import_tpm_url(key
, url
, NULL
, 0);
1158 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
1162 * gnutls_pubkey_import_rsa_raw:
1163 * @key: Is a structure will hold the parameters
1164 * @m: holds the modulus
1165 * @e: holds the public exponent
1167 * This function will replace the parameters in the given structure.
1168 * The new parameters should be stored in the appropriate
1171 * Returns: %GNUTLS_E_SUCCESS on success, or an negative error code.
1176 gnutls_pubkey_import_rsa_raw (gnutls_pubkey_t key
,
1177 const gnutls_datum_t
* m
,
1178 const gnutls_datum_t
* e
)
1185 return GNUTLS_E_INVALID_REQUEST
;
1188 gnutls_pk_params_init(&key
->params
);
1191 if (_gnutls_mpi_scan_nz (&key
->params
.params
[0], m
->data
, siz
))
1194 return GNUTLS_E_MPI_SCAN_FAILED
;
1198 if (_gnutls_mpi_scan_nz (&key
->params
.params
[1], e
->data
, siz
))
1201 _gnutls_mpi_release (&key
->params
.params
[0]);
1202 return GNUTLS_E_MPI_SCAN_FAILED
;
1205 key
->params
.params_nr
= RSA_PUBLIC_PARAMS
;
1206 key
->pk_algorithm
= GNUTLS_PK_RSA
;
1207 key
->bits
= pubkey_to_bits(GNUTLS_PK_RSA
, &key
->params
);
1213 * gnutls_pubkey_import_ecc_raw:
1214 * @key: The structure to store the parsed key
1215 * @curve: holds the curve
1219 * This function will convert the given elliptic curve parameters to a
1220 * #gnutls_pubkey_t. The output will be stored in @key.
1222 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1223 * negative error value.
1228 gnutls_pubkey_import_ecc_raw (gnutls_pubkey_t key
,
1229 gnutls_ecc_curve_t curve
,
1230 const gnutls_datum_t
* x
,
1231 const gnutls_datum_t
* y
)
1238 return GNUTLS_E_INVALID_REQUEST
;
1241 key
->params
.flags
= curve
;
1243 ret
= _gnutls_ecc_curve_fill_params(curve
, &key
->params
);
1245 return gnutls_assert_val(ret
);
1247 if (_gnutls_mpi_scan_nz (&key
->params
.params
[ECC_X
], x
->data
, x
->size
))
1250 ret
= GNUTLS_E_MPI_SCAN_FAILED
;
1253 key
->params
.params_nr
++;
1255 if (_gnutls_mpi_scan_nz (&key
->params
.params
[ECC_Y
], y
->data
, y
->size
))
1258 ret
= GNUTLS_E_MPI_SCAN_FAILED
;
1261 key
->params
.params_nr
++;
1262 key
->pk_algorithm
= GNUTLS_PK_EC
;
1267 gnutls_pk_params_release(&key
->params
);
1272 * gnutls_pubkey_import_ecc_x962:
1273 * @key: The structure to store the parsed key
1274 * @parameters: DER encoding of an ANSI X9.62 parameters
1275 * @ecpoint: DER encoding of ANSI X9.62 ECPoint
1277 * This function will convert the given elliptic curve parameters to a
1278 * #gnutls_pubkey_t. The output will be stored in @key.
1280 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1281 * negative error value.
1286 gnutls_pubkey_import_ecc_x962 (gnutls_pubkey_t key
,
1287 const gnutls_datum_t
* parameters
,
1288 const gnutls_datum_t
* ecpoint
)
1295 return GNUTLS_E_INVALID_REQUEST
;
1298 key
->params
.params_nr
= 0;
1300 ret
= _gnutls_x509_read_ecc_params(parameters
->data
, parameters
->size
,
1308 ret
= _gnutls_ecc_ansi_x963_import(ecpoint
->data
, ecpoint
->size
,
1309 &key
->params
.params
[ECC_X
], &key
->params
.params
[ECC_Y
]);
1315 key
->params
.params_nr
+=2;
1316 key
->pk_algorithm
= GNUTLS_PK_EC
;
1321 gnutls_pk_params_release(&key
->params
);
1326 * gnutls_pubkey_import_dsa_raw:
1327 * @key: The structure to store the parsed key
1333 * This function will convert the given DSA raw parameters to the
1334 * native #gnutls_pubkey_t format. The output will be stored
1337 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1338 * negative error value.
1343 gnutls_pubkey_import_dsa_raw (gnutls_pubkey_t key
,
1344 const gnutls_datum_t
* p
,
1345 const gnutls_datum_t
* q
,
1346 const gnutls_datum_t
* g
,
1347 const gnutls_datum_t
* y
)
1354 return GNUTLS_E_INVALID_REQUEST
;
1357 gnutls_pk_params_init(&key
->params
);
1360 if (_gnutls_mpi_scan_nz (&key
->params
.params
[0], p
->data
, siz
))
1363 return GNUTLS_E_MPI_SCAN_FAILED
;
1367 if (_gnutls_mpi_scan_nz (&key
->params
.params
[1], q
->data
, siz
))
1370 _gnutls_mpi_release (&key
->params
.params
[0]);
1371 return GNUTLS_E_MPI_SCAN_FAILED
;
1375 if (_gnutls_mpi_scan_nz (&key
->params
.params
[2], g
->data
, siz
))
1378 _gnutls_mpi_release (&key
->params
.params
[1]);
1379 _gnutls_mpi_release (&key
->params
.params
[0]);
1380 return GNUTLS_E_MPI_SCAN_FAILED
;
1384 if (_gnutls_mpi_scan_nz (&key
->params
.params
[3], y
->data
, siz
))
1387 _gnutls_mpi_release (&key
->params
.params
[2]);
1388 _gnutls_mpi_release (&key
->params
.params
[1]);
1389 _gnutls_mpi_release (&key
->params
.params
[0]);
1390 return GNUTLS_E_MPI_SCAN_FAILED
;
1393 key
->params
.params_nr
= DSA_PUBLIC_PARAMS
;
1394 key
->pk_algorithm
= GNUTLS_PK_DSA
;
1395 key
->bits
= pubkey_to_bits(GNUTLS_PK_DSA
, &key
->params
);
1402 * gnutls_pubkey_verify_data:
1403 * @pubkey: Holds the public key
1404 * @flags: should be 0 for now
1405 * @data: holds the signed data
1406 * @signature: contains the signature
1408 * This function will verify the given signed data, using the
1409 * parameters from the certificate.
1411 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1412 * is returned, and zero or positive code on success.
1414 * Deprecated. Use gnutls_pubkey_verify_data2() instead of this function.
1419 gnutls_pubkey_verify_data (gnutls_pubkey_t pubkey
, unsigned int flags
,
1420 const gnutls_datum_t
* data
,
1421 const gnutls_datum_t
* signature
)
1428 return GNUTLS_E_INVALID_REQUEST
;
1431 ret
= pubkey_verify_data( pubkey
->pk_algorithm
, GNUTLS_DIG_UNKNOWN
, data
, signature
,
1442 * gnutls_pubkey_verify_data2:
1443 * @pubkey: Holds the public key
1444 * @algo: The signature algorithm used
1445 * @flags: should be 0 for now
1446 * @data: holds the signed data
1447 * @signature: contains the signature
1449 * This function will verify the given signed data, using the
1450 * parameters from the certificate.
1452 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1453 * is returned, and zero or positive code on success.
1458 gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey
,
1459 gnutls_sign_algorithm_t algo
,
1461 const gnutls_datum_t
* data
,
1462 const gnutls_datum_t
* signature
)
1469 return GNUTLS_E_INVALID_REQUEST
;
1472 ret
= pubkey_verify_data( pubkey
->pk_algorithm
, gnutls_sign_get_hash_algorithm(algo
),
1473 data
, signature
, &pubkey
->params
);
1484 * gnutls_pubkey_verify_hash:
1485 * @key: Holds the public key
1486 * @flags: should be 0 for now
1487 * @hash: holds the hash digest to be verified
1488 * @signature: contains the signature
1490 * This function will verify the given signed digest, using the
1491 * parameters from the public key.
1493 * Deprecated. Use gnutls_pubkey_verify_hash2() instead of this function.
1495 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1496 * is returned, and zero or positive code on success.
1501 gnutls_pubkey_verify_hash (gnutls_pubkey_t key
, unsigned int flags
,
1502 const gnutls_datum_t
* hash
,
1503 const gnutls_datum_t
* signature
)
1505 gnutls_digest_algorithm_t algo
;
1508 ret
= gnutls_pubkey_get_verify_algorithm (key
, signature
, &algo
);
1510 return gnutls_assert_val(ret
);
1512 return gnutls_pubkey_verify_hash2(key
, gnutls_pk_to_sign(key
->pk_algorithm
, algo
),
1513 flags
, hash
, signature
);
1517 * gnutls_pubkey_verify_hash2:
1518 * @key: Holds the public key
1519 * @algo: The signature algorithm used
1520 * @flags: should be 0 for now
1521 * @hash: holds the hash digest to be verified
1522 * @signature: contains the signature
1524 * This function will verify the given signed digest, using the
1525 * parameters from the public key.
1527 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1528 * is returned, and zero or positive code on success.
1533 gnutls_pubkey_verify_hash2 (gnutls_pubkey_t key
,
1534 gnutls_sign_algorithm_t algo
,
1536 const gnutls_datum_t
* hash
,
1537 const gnutls_datum_t
* signature
)
1542 return GNUTLS_E_INVALID_REQUEST
;
1545 if (flags
& GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA
)
1546 return _gnutls_pk_verify (GNUTLS_PK_RSA
, hash
, signature
, &key
->params
);
1549 return pubkey_verify_hashed_data (key
->pk_algorithm
, gnutls_sign_get_hash_algorithm(algo
),
1550 hash
, signature
, &key
->params
);
1555 * gnutls_pubkey_encrypt_data:
1556 * @key: Holds the public key
1557 * @flags: should be 0 for now
1558 * @plaintext: The data to be encrypted
1559 * @ciphertext: contains the encrypted data
1561 * This function will encrypt the given data, using the public
1564 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1565 * negative error value.
1570 gnutls_pubkey_encrypt_data (gnutls_pubkey_t key
, unsigned int flags
,
1571 const gnutls_datum_t
* plaintext
,
1572 gnutls_datum_t
* ciphertext
)
1577 return GNUTLS_E_INVALID_REQUEST
;
1580 return _gnutls_pk_encrypt (key
->pk_algorithm
, ciphertext
,
1581 plaintext
, &key
->params
);
1585 * gnutls_pubkey_get_verify_algorithm:
1586 * @key: Holds the certificate
1587 * @signature: contains the signature
1588 * @hash: The result of the call with the hash algorithm used for signature
1590 * This function will read the certifcate and the signed data to
1591 * determine the hash algorithm used to generate the signature.
1593 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1594 * negative error value.
1599 gnutls_pubkey_get_verify_algorithm (gnutls_pubkey_t key
,
1600 const gnutls_datum_t
* signature
,
1601 gnutls_digest_algorithm_t
* hash
)
1606 return GNUTLS_E_INVALID_REQUEST
;
1609 return _gnutls_x509_verify_algorithm (hash
, signature
,
1615 /* Checks whether the public key given is compatible with the
1616 * signature algorithm used. The session is only used for audit logging, and
1619 int _gnutls_pubkey_compatible_with_sig(gnutls_session_t session
,
1620 gnutls_pubkey_t pubkey
,
1621 gnutls_protocol_t ver
,
1622 gnutls_sign_algorithm_t sign
)
1624 unsigned int hash_size
;
1625 unsigned int hash_algo
;
1626 unsigned int sig_hash_size
;
1628 if (pubkey
->pk_algorithm
== GNUTLS_PK_DSA
)
1630 hash_algo
= _gnutls_dsa_q_to_hash (pubkey
->pk_algorithm
, &pubkey
->params
, &hash_size
);
1632 /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
1633 if (!_gnutls_version_has_selectable_sighash (ver
))
1635 if (hash_algo
!= GNUTLS_DIG_SHA1
)
1636 return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL
);
1638 else if (sign
!= GNUTLS_SIGN_UNKNOWN
)
1640 sig_hash_size
= _gnutls_hash_get_algo_len(gnutls_sign_get_hash_algorithm(sign
));
1641 if (sig_hash_size
< hash_size
)
1642 _gnutls_audit_log(session
, "The hash size used in signature (%u) is less than the expected (%u)\n", sig_hash_size
, hash_size
);
1646 else if (pubkey
->pk_algorithm
== GNUTLS_PK_EC
)
1648 if (_gnutls_version_has_selectable_sighash (ver
) && sign
!= GNUTLS_SIGN_UNKNOWN
)
1650 _gnutls_dsa_q_to_hash (pubkey
->pk_algorithm
, &pubkey
->params
, &hash_size
);
1651 sig_hash_size
= _gnutls_hash_get_algo_len(gnutls_sign_get_hash_algorithm(sign
));
1653 if (sig_hash_size
< hash_size
)
1654 _gnutls_audit_log(session
, "The hash size used in signature (%u) is less than the expected (%u)\n", sig_hash_size
, hash_size
);
1662 /* Returns zero if the public key has more than 512 bits */
1663 int _gnutls_pubkey_is_over_rsa_512(gnutls_pubkey_t pubkey
)
1665 if (pubkey
->pk_algorithm
== GNUTLS_PK_RSA
&& _gnutls_mpi_get_nbits (pubkey
->params
.params
[0]) > 512)
1668 return GNUTLS_E_INVALID_REQUEST
; /* doesn't matter */
1672 /* Returns the public key.
1675 _gnutls_pubkey_get_mpis (gnutls_pubkey_t key
,
1676 gnutls_pk_params_st
* params
)
1678 return _gnutls_pk_params_copy(params
, &key
->params
);
1681 /* if hash==MD5 then we do RSA-MD5
1682 * if hash==SHA then we do RSA-SHA
1683 * params[0] is modulus
1684 * params[1] is public key
1687 _pkcs1_rsa_verify_sig (gnutls_digest_algorithm_t hash
,
1688 const gnutls_datum_t
* text
,
1689 const gnutls_datum_t
* prehash
,
1690 const gnutls_datum_t
* signature
,
1691 gnutls_pk_params_st
* params
)
1694 uint8_t md
[MAX_HASH_SIZE
], *cmp
;
1695 unsigned int digest_size
;
1696 gnutls_datum_t d
, di
;
1699 digest_size
= _gnutls_hash_get_algo_len (hash
);
1702 if (prehash
->data
== NULL
|| prehash
->size
!= digest_size
)
1703 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
1705 cmp
= prehash
->data
;
1712 return GNUTLS_E_INVALID_REQUEST
;
1715 ret
= _gnutls_hash_init (&hd
, hash
);
1722 _gnutls_hash (&hd
, text
->data
, text
->size
);
1723 _gnutls_hash_deinit (&hd
, md
);
1729 d
.size
= digest_size
;
1731 /* decrypted is a BER encoded data of type DigestInfo
1734 ret
= encode_ber_digest_info (hash
, &d
, &di
);
1736 return gnutls_assert_val(ret
);
1738 ret
= _gnutls_pk_verify (GNUTLS_PK_RSA
, &di
, signature
, params
);
1740 _gnutls_free_datum (&di
);
1745 /* Hashes input data and verifies a signature.
1748 dsa_verify_hashed_data (gnutls_pk_algorithm_t pk
,
1749 gnutls_digest_algorithm_t algo
,
1750 const gnutls_datum_t
* hash
,
1751 const gnutls_datum_t
* signature
,
1752 gnutls_pk_params_st
* params
)
1754 gnutls_datum_t digest
;
1755 unsigned int hash_len
;
1757 if (algo
== GNUTLS_DIG_UNKNOWN
)
1758 algo
= _gnutls_dsa_q_to_hash (pk
, params
, &hash_len
);
1759 else hash_len
= _gnutls_hash_get_algo_len(algo
);
1761 /* SHA1 or better allowed */
1762 if (!hash
->data
|| hash
->size
< hash_len
)
1765 _gnutls_debug_log("Hash size (%d) does not correspond to hash %s(%d) or better.\n", (int)hash
->size
, gnutls_mac_get_name(algo
), hash_len
);
1767 if (hash
->size
!= 20) /* SHA1 is allowed */
1768 return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED
);
1771 digest
.data
= hash
->data
;
1772 digest
.size
= hash
->size
;
1774 return _gnutls_pk_verify (pk
, &digest
, signature
, params
);
1778 dsa_verify_data (gnutls_pk_algorithm_t pk
,
1779 gnutls_digest_algorithm_t algo
,
1780 const gnutls_datum_t
* data
,
1781 const gnutls_datum_t
* signature
,
1782 gnutls_pk_params_st
* params
)
1785 uint8_t _digest
[MAX_HASH_SIZE
];
1786 gnutls_datum_t digest
;
1789 if (algo
== GNUTLS_DIG_UNKNOWN
)
1790 algo
= _gnutls_dsa_q_to_hash (pk
, params
, NULL
);
1792 ret
= _gnutls_hash_init (&hd
, algo
);
1794 return gnutls_assert_val(ret
);
1796 _gnutls_hash (&hd
, data
->data
, data
->size
);
1797 _gnutls_hash_deinit (&hd
, _digest
);
1799 digest
.data
= _digest
;
1800 digest
.size
= _gnutls_hash_get_algo_len(algo
);
1802 return _gnutls_pk_verify (pk
, &digest
, signature
, params
);
1805 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if
1806 * not verified, or 1 otherwise.
1809 pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk
,
1810 gnutls_digest_algorithm_t hash_algo
,
1811 const gnutls_datum_t
* hash
,
1812 const gnutls_datum_t
* signature
,
1813 gnutls_pk_params_st
* issuer_params
)
1820 if (_pkcs1_rsa_verify_sig
1821 (hash_algo
, NULL
, hash
, signature
, issuer_params
) != 0)
1824 return GNUTLS_E_PK_SIG_VERIFY_FAILED
;
1832 if (dsa_verify_hashed_data(pk
, hash_algo
, hash
, signature
, issuer_params
) != 0)
1835 return GNUTLS_E_PK_SIG_VERIFY_FAILED
;
1842 return GNUTLS_E_INTERNAL_ERROR
;
1847 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if
1848 * not verified, or 1 otherwise.
1851 pubkey_verify_data (gnutls_pk_algorithm_t pk
,
1852 gnutls_digest_algorithm_t hash_algo
,
1853 const gnutls_datum_t
* data
,
1854 const gnutls_datum_t
* signature
,
1855 gnutls_pk_params_st
* issuer_params
)
1862 if (_pkcs1_rsa_verify_sig
1863 (hash_algo
, data
, NULL
, signature
, issuer_params
) != 0)
1866 return GNUTLS_E_PK_SIG_VERIFY_FAILED
;
1874 if (dsa_verify_data(pk
, hash_algo
, data
, signature
, issuer_params
) != 0)
1877 return GNUTLS_E_PK_SIG_VERIFY_FAILED
;
1884 return GNUTLS_E_INTERNAL_ERROR
;
1889 gnutls_digest_algorithm_t
1890 _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo
, const gnutls_pk_params_st
* params
,
1891 unsigned int* hash_len
)
1895 if (algo
== GNUTLS_PK_DSA
)
1896 bits
= _gnutls_mpi_get_nbits (params
->params
[1]);
1897 else if (algo
== GNUTLS_PK_EC
)
1898 bits
= gnutls_ecc_curve_get_size(params
->flags
)*8;
1902 if (hash_len
) *hash_len
= 20;
1903 return GNUTLS_DIG_SHA1
;
1905 else if (bits
<= 192)
1907 if (hash_len
) *hash_len
= 24;
1908 return GNUTLS_DIG_SHA256
;
1910 else if (bits
<= 224)
1912 if (hash_len
) *hash_len
= 28;
1913 return GNUTLS_DIG_SHA256
;
1915 else if (bits
<= 256)
1917 if (hash_len
) *hash_len
= 32;
1918 return GNUTLS_DIG_SHA256
;
1920 else if (bits
<= 384)
1922 if (hash_len
) *hash_len
= 48;
1923 return GNUTLS_DIG_SHA384
;
1927 if (hash_len
) *hash_len
= 64;
1928 return GNUTLS_DIG_SHA512
;
1933 * gnutls_pubkey_set_pin_function:
1934 * @key: A key of type #gnutls_pubkey_t
1936 * @userdata: data associated with the callback
1938 * This function will set a callback function to be used when
1939 * required to access the object. This function overrides any other
1940 * global PIN functions.
1942 * Note that this function must be called right after initialization
1948 void gnutls_pubkey_set_pin_function (gnutls_pubkey_t key
,
1949 gnutls_pin_callback_t fn
, void *userdata
)
1952 key
->pin
.data
= userdata
;