documented fix
[gnutls.git] / lib / gnutls_pubkey.c
blobc1455628268f4a272fd59f1ab317b40fe745e865
1 /*
2 * GnuTLS public key support
3 * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4 *
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>
23 #include <stdio.h>
24 #include <string.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>
31 #include <x509_int.h>
32 #include <openpgp/openpgp_int.h>
33 #include <gnutls_num.h>
34 #include <x509/common.h>
35 #include <x509_b64.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)
47 switch(pk)
49 case GNUTLS_PK_RSA:
50 return _gnutls_mpi_get_nbits(params->params[0]);
51 case GNUTLS_PK_DSA:
52 return _gnutls_mpi_get_nbits(params->params[3]);
53 case GNUTLS_PK_EC:
54 return gnutls_ecc_curve_get_size(params->flags)*8;
55 default:
56 return 0;
60 /**
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.
72 * Since: 2.12.0
73 **/
74 int
75 gnutls_pubkey_get_pk_algorithm (gnutls_pubkey_t key, unsigned int *bits)
77 if (bits)
78 *bits = key->bits;
80 return key->pk_algorithm;
83 /**
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.
93 * Since: 2.12.0
94 **/
95 int
96 gnutls_pubkey_get_key_usage (gnutls_pubkey_t key, unsigned int *usage)
98 if (usage)
99 *usage = key->key_usage;
101 return 0;
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.
113 * Since: 2.12.0
116 gnutls_pubkey_init (gnutls_pubkey_t * key)
118 *key = gnutls_calloc (1, sizeof (struct gnutls_pubkey_st));
119 if (*key == NULL)
121 gnutls_assert ();
122 return GNUTLS_E_MEMORY_ERROR;
125 return 0;
129 * gnutls_pubkey_deinit:
130 * @key: The structure to be deinitialized
132 * This function will deinitialize a public key structure.
134 * Since: 2.12.0
136 void
137 gnutls_pubkey_deinit (gnutls_pubkey_t key)
139 if (!key)
140 return;
141 gnutls_pk_params_release (&key->params);
142 gnutls_free (key);
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.
157 * Since: 2.12.0
160 gnutls_pubkey_import_x509 (gnutls_pubkey_t key, gnutls_x509_crt_t crt,
161 unsigned int flags)
163 int ret;
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);
168 if (ret < 0)
169 key->key_usage = 0;
171 ret = _gnutls_x509_crt_get_mpis (crt, &key->params);
172 if (ret < 0)
174 gnutls_assert ();
175 return ret;
178 return 0;
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.
194 * Since: 2.12.0
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
218 * returned on error.
220 * Since: 2.12.0
223 gnutls_pubkey_get_preferred_hash_algorithm (gnutls_pubkey_t key,
224 gnutls_digest_algorithm_t *
225 hash, unsigned int *mand)
227 int ret;
229 if (key == NULL)
231 gnutls_assert ();
232 return GNUTLS_E_INVALID_REQUEST;
235 ret = _gnutls_pk_get_hash_algorithm (key->pk_algorithm,
236 &key->params,
237 hash, mand);
239 return ret;
242 #ifdef ENABLE_PKCS11
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.
256 * Since: 2.12.0
259 gnutls_pubkey_import_pkcs11 (gnutls_pubkey_t key,
260 gnutls_pkcs11_obj_t obj, unsigned int flags)
262 int ret, type;
264 type = gnutls_pkcs11_obj_get_type (obj);
265 if (type != GNUTLS_PKCS11_OBJ_PUBKEY && type != GNUTLS_PKCS11_OBJ_X509_CRT)
267 gnutls_assert ();
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);
276 if (ret < 0)
278 gnutls_assert()
279 return ret;
282 ret = gnutls_x509_crt_import_pkcs11 (xcrt, obj);
283 if (ret < 0)
285 gnutls_assert();
286 goto cleanup_crt;
289 ret = gnutls_pubkey_import_x509 (key, xcrt, 0);
290 if (ret < 0)
292 gnutls_assert();
293 goto cleanup_crt;
296 gnutls_x509_crt_get_key_usage(xcrt, &key->key_usage, NULL);
298 ret = 0;
299 cleanup_crt:
300 gnutls_x509_crt_deinit(xcrt);
301 return ret;
304 key->key_usage = obj->key_usage;
306 switch (obj->pk_algorithm)
308 case GNUTLS_PK_RSA:
309 ret = gnutls_pubkey_import_rsa_raw (key, &obj->pubkey[0],
310 &obj->pubkey[1]);
311 break;
312 case GNUTLS_PK_DSA:
313 ret = gnutls_pubkey_import_dsa_raw (key, &obj->pubkey[0],
314 &obj->pubkey[1],
315 &obj->pubkey[2], &obj->pubkey[3]);
316 break;
317 case GNUTLS_PK_EC:
318 ret = gnutls_pubkey_import_ecc_x962 (key, &obj->pubkey[0],
319 &obj->pubkey[1]);
320 break;
321 default:
322 gnutls_assert ();
323 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
326 if (ret < 0)
328 gnutls_assert ();
329 return ret;
332 return 0;
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.
353 * Since: 2.12.0
356 gnutls_pubkey_import_openpgp (gnutls_pubkey_t key,
357 gnutls_openpgp_crt_t crt,
358 unsigned int flags)
360 int ret, idx;
361 uint32_t kid32[2];
362 uint32_t *k;
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);
372 if (ret < 0)
373 return gnutls_assert_val(ret);
375 ret = gnutls_openpgp_crt_get_key_usage (crt, &key->key_usage);
376 if (ret < 0)
377 key->key_usage = 0;
379 k = NULL;
381 else
383 if (ret < 0)
385 gnutls_assert ();
386 return ret;
388 key->openpgp_key_id_set = OPENPGP_KEY_SUBKEY;
390 KEYID_IMPORT (kid32, keyid);
391 k = kid32;
393 idx = gnutls_openpgp_crt_get_subkey_idx (crt, keyid);
395 ret = gnutls_openpgp_crt_get_subkey_id(crt, idx, key->openpgp_key_id);
396 if (ret < 0)
397 return gnutls_assert_val(ret);
399 ret = gnutls_openpgp_crt_get_subkey_usage (crt, idx, &key->key_usage);
400 if (ret < 0)
401 key->key_usage = 0;
403 key->pk_algorithm = gnutls_openpgp_crt_get_subkey_pk_algorithm (crt, idx, NULL);
406 ret =
407 _gnutls_openpgp_crt_get_mpis (crt, k, &key->params);
408 if (ret < 0)
409 return gnutls_assert_val(ret);
411 return 0;
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,
430 * which is 20 bytes.
432 * Returns: In case of failure a negative error code will be
433 * returned, and 0 on success.
435 * Since: 3.0
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)
443 if (key == NULL)
445 gnutls_assert ();
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;
461 if (output_data)
463 memcpy(output_data, key->openpgp_key_id, sizeof(key->openpgp_key_id));
465 *output_data_size = sizeof(key->openpgp_key_id);
467 return 0;
470 #endif
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
482 * X.509 structure.
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
486 * be returned.
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.
494 * Since: 2.12.0
497 gnutls_pubkey_export (gnutls_pubkey_t key,
498 gnutls_x509_crt_fmt_t format, void *output_data,
499 size_t * output_data_size)
501 int result;
502 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
504 if (key == NULL)
506 gnutls_assert ();
507 return GNUTLS_E_INVALID_REQUEST;
510 if ((result = asn1_create_element
511 (_gnutls_get_pkix (), "PKIX1.SubjectPublicKeyInfo", &spk))
512 != ASN1_SUCCESS)
514 gnutls_assert ();
515 return _gnutls_asn2err (result);
518 result =
519 _gnutls_x509_encode_and_copy_PKI_params (spk, "",
520 key->pk_algorithm,
521 &key->params);
522 if (result < 0)
524 gnutls_assert ();
525 goto cleanup;
528 result = _gnutls_x509_export_int_named (spk, "",
529 format, PK_PEM_HEADER,
530 output_data, output_data_size);
531 if (result < 0)
533 gnutls_assert ();
534 goto cleanup;
537 result = 0;
539 cleanup:
540 asn1_delete_structure (&spk);
542 return result;
547 * gnutls_pubkey_get_key_id:
548 * @key: Holds the public key
549 * @flags: should be 0 for now
550 * @output_data: will contain the key ID
551 * @output_data_size: holds the size of output_data (and will be
552 * replaced by the actual size of parameters)
554 * This function will return a unique ID the depends on the public
555 * key parameters. This ID can be used in checking whether a
556 * certificate corresponds to the given public key.
558 * If the buffer provided is not long enough to hold the output, then
559 * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
560 * be returned. The output will normally be a SHA-1 hash output,
561 * which is 20 bytes.
563 * Returns: In case of failure a negative error code will be
564 * returned, and 0 on success.
566 * Since: 2.12.0
569 gnutls_pubkey_get_key_id (gnutls_pubkey_t key, unsigned int flags,
570 unsigned char *output_data,
571 size_t * output_data_size)
573 int ret = 0;
575 if (key == NULL)
577 gnutls_assert ();
578 return GNUTLS_E_INVALID_REQUEST;
581 ret =
582 _gnutls_get_key_id (key->pk_algorithm, &key->params,
583 output_data, output_data_size);
584 if (ret < 0)
586 gnutls_assert ();
587 return ret;
590 return 0;
594 * gnutls_pubkey_get_pk_rsa_raw:
595 * @key: Holds the certificate
596 * @m: will hold the modulus
597 * @e: will hold the public exponent
599 * This function will export the RSA public key's parameters found in
600 * the given structure. The new parameters will be allocated using
601 * gnutls_malloc() and will be stored in the appropriate datum.
603 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
605 * Since: 2.12.0
608 gnutls_pubkey_get_pk_rsa_raw (gnutls_pubkey_t key,
609 gnutls_datum_t * m, gnutls_datum_t * e)
611 int ret;
613 if (key == NULL)
615 gnutls_assert ();
616 return GNUTLS_E_INVALID_REQUEST;
619 if (key->pk_algorithm != GNUTLS_PK_RSA)
621 gnutls_assert ();
622 return GNUTLS_E_INVALID_REQUEST;
625 ret = _gnutls_mpi_dprint_lz (key->params.params[0], m);
626 if (ret < 0)
628 gnutls_assert ();
629 return ret;
632 ret = _gnutls_mpi_dprint_lz (key->params.params[1], e);
633 if (ret < 0)
635 gnutls_assert ();
636 _gnutls_free_datum (m);
637 return ret;
640 return 0;
644 * gnutls_pubkey_get_pk_dsa_raw:
645 * @key: Holds the public key
646 * @p: will hold the p
647 * @q: will hold the q
648 * @g: will hold the g
649 * @y: will hold the y
651 * This function will export the DSA public key's parameters found in
652 * the given certificate. The new parameters will be allocated using
653 * gnutls_malloc() and will be stored in the appropriate datum.
655 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
657 * Since: 2.12.0
660 gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t key,
661 gnutls_datum_t * p, gnutls_datum_t * q,
662 gnutls_datum_t * g, gnutls_datum_t * y)
664 int ret;
666 if (key == NULL)
668 gnutls_assert ();
669 return GNUTLS_E_INVALID_REQUEST;
672 if (key->pk_algorithm != GNUTLS_PK_DSA)
674 gnutls_assert ();
675 return GNUTLS_E_INVALID_REQUEST;
678 /* P */
679 ret = _gnutls_mpi_dprint_lz (key->params.params[0], p);
680 if (ret < 0)
682 gnutls_assert ();
683 return ret;
686 /* Q */
687 ret = _gnutls_mpi_dprint_lz (key->params.params[1], q);
688 if (ret < 0)
690 gnutls_assert ();
691 _gnutls_free_datum (p);
692 return ret;
696 /* G */
697 ret = _gnutls_mpi_dprint_lz (key->params.params[2], g);
698 if (ret < 0)
700 gnutls_assert ();
701 _gnutls_free_datum (p);
702 _gnutls_free_datum (q);
703 return ret;
707 /* Y */
708 ret = _gnutls_mpi_dprint_lz (key->params.params[3], y);
709 if (ret < 0)
711 gnutls_assert ();
712 _gnutls_free_datum (p);
713 _gnutls_free_datum (g);
714 _gnutls_free_datum (q);
715 return ret;
718 return 0;
722 * gnutls_pubkey_get_pk_ecc_raw:
723 * @key: Holds the public key
724 * @curve: will hold the curve
725 * @x: will hold x
726 * @y: will hold y
728 * This function will export the ECC public key's parameters found in
729 * the given certificate. The new parameters will be allocated using
730 * gnutls_malloc() and will be stored in the appropriate datum.
732 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
734 * Since: 3.0
737 gnutls_pubkey_get_pk_ecc_raw (gnutls_pubkey_t key, gnutls_ecc_curve_t *curve,
738 gnutls_datum_t * x, gnutls_datum_t * y)
740 int ret;
742 if (key == NULL)
744 gnutls_assert ();
745 return GNUTLS_E_INVALID_REQUEST;
748 if (key->pk_algorithm != GNUTLS_PK_EC)
750 gnutls_assert ();
751 return GNUTLS_E_INVALID_REQUEST;
754 *curve = key->params.flags;
756 /* X */
757 ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_X], x);
758 if (ret < 0)
760 gnutls_assert ();
761 return ret;
764 /* Y */
765 ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_Y], y);
766 if (ret < 0)
768 gnutls_assert ();
769 _gnutls_free_datum (x);
770 return ret;
773 return 0;
777 * gnutls_pubkey_get_pk_ecc_x962:
778 * @key: Holds the public key
779 * @parameters: DER encoding of an ANSI X9.62 parameters
780 * @ecpoint: DER encoding of ANSI X9.62 ECPoint
782 * This function will export the ECC public key's parameters found in
783 * the given certificate. The new parameters will be allocated using
784 * gnutls_malloc() and will be stored in the appropriate datum.
786 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
788 * Since: 3.0
790 int gnutls_pubkey_get_pk_ecc_x962 (gnutls_pubkey_t key, gnutls_datum_t* parameters,
791 gnutls_datum_t * ecpoint)
793 int ret;
795 if (key == NULL || key->pk_algorithm != GNUTLS_PK_EC)
796 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
798 ret = _gnutls_x509_write_ecc_pubkey(&key->params, ecpoint);
799 if (ret < 0)
800 return gnutls_assert_val(ret);
802 ret = _gnutls_x509_write_ecc_params(&key->params, parameters);
803 if (ret < 0)
805 _gnutls_free_datum(ecpoint);
806 return gnutls_assert_val(ret);
809 return 0;
813 * gnutls_pubkey_import:
814 * @key: The structure to store the parsed public key.
815 * @data: The DER or PEM encoded certificate.
816 * @format: One of DER or PEM
818 * This function will import the provided public key in
819 * a SubjectPublicKeyInfo X.509 structure to a native
820 * %gnutls_pubkey_t structure. The output will be stored
821 * in @key. If the public key is PEM encoded it should have a header
822 * of "PUBLIC KEY".
824 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
825 * negative error value.
827 * Since: 2.12.0
830 gnutls_pubkey_import (gnutls_pubkey_t key,
831 const gnutls_datum_t * data,
832 gnutls_x509_crt_fmt_t format)
834 int result = 0, need_free = 0;
835 gnutls_datum_t _data;
836 ASN1_TYPE spk;
838 if (key == NULL)
840 gnutls_assert ();
841 return GNUTLS_E_INVALID_REQUEST;
844 _data.data = data->data;
845 _data.size = data->size;
847 /* If the Certificate is in PEM format then decode it
849 if (format == GNUTLS_X509_FMT_PEM)
851 /* Try the first header */
852 result =
853 _gnutls_fbase64_decode (PK_PEM_HEADER, data->data, data->size, &_data);
855 if (result < 0)
857 gnutls_assert ();
858 return result;
861 need_free = 1;
864 if ((result = asn1_create_element
865 (_gnutls_get_pkix (), "PKIX1.SubjectPublicKeyInfo", &spk))
866 != ASN1_SUCCESS)
868 gnutls_assert ();
869 result = _gnutls_asn2err (result);
870 goto cleanup;
873 result = asn1_der_decoding (&spk, _data.data, _data.size, NULL);
874 if (result != ASN1_SUCCESS)
876 gnutls_assert ();
877 result = _gnutls_asn2err (result);
878 goto cleanup;
881 result = _gnutls_get_asn_mpis (spk, "", &key->params);
882 if (result < 0)
884 gnutls_assert ();
885 goto cleanup;
888 /* this has already been called by get_asn_mpis() thus it cannot
889 * fail.
891 key->pk_algorithm = _gnutls_x509_get_pk_algorithm (spk, "", NULL);
892 key->bits = pubkey_to_bits(key->pk_algorithm, &key->params);
894 result = 0;
896 cleanup:
897 asn1_delete_structure (&spk);
899 if (need_free)
900 _gnutls_free_datum (&_data);
901 return result;
905 * gnutls_x509_crt_set_pubkey:
906 * @crt: should contain a #gnutls_x509_crt_t structure
907 * @key: holds a public key
909 * This function will set the public parameters from the given public
910 * key to the request.
912 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
913 * negative error value.
915 * Since: 2.12.0
918 gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, gnutls_pubkey_t key)
920 int result;
922 if (crt == NULL)
924 gnutls_assert ();
925 return GNUTLS_E_INVALID_REQUEST;
928 result = _gnutls_x509_encode_and_copy_PKI_params (crt->cert,
929 "tbsCertificate.subjectPublicKeyInfo",
930 key->pk_algorithm,
931 &key->params);
933 if (result < 0)
935 gnutls_assert ();
936 return result;
939 if (key->key_usage)
940 gnutls_x509_crt_set_key_usage (crt, key->key_usage);
942 return 0;
946 * gnutls_x509_crq_set_pubkey:
947 * @crq: should contain a #gnutls_x509_crq_t structure
948 * @key: holds a public key
950 * This function will set the public parameters from the given public
951 * key to the request.
953 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
954 * negative error value.
956 * Since: 2.12.0
959 gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, gnutls_pubkey_t key)
961 int result;
963 if (crq == NULL)
965 gnutls_assert ();
966 return GNUTLS_E_INVALID_REQUEST;
969 result = _gnutls_x509_encode_and_copy_PKI_params
970 (crq->crq,
971 "certificationRequestInfo.subjectPKInfo",
972 key->pk_algorithm, &key->params);
974 if (result < 0)
976 gnutls_assert ();
977 return result;
980 if (key->key_usage)
981 gnutls_x509_crq_set_key_usage (crq, key->key_usage);
983 return 0;
987 * gnutls_pubkey_set_key_usage:
988 * @key: a certificate of type #gnutls_x509_crt_t
989 * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
991 * This function will set the key usage flags of the public key. This
992 * is only useful if the key is to be exported to a certificate or
993 * certificate request.
995 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
996 * negative error value.
998 * Since: 2.12.0
1001 gnutls_pubkey_set_key_usage (gnutls_pubkey_t key, unsigned int usage)
1003 key->key_usage = usage;
1005 return 0;
1008 #ifdef ENABLE_PKCS11
1011 * gnutls_pubkey_import_pkcs11_url:
1012 * @key: A key of type #gnutls_pubkey_t
1013 * @url: A PKCS 11 url
1014 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1016 * This function will import a PKCS 11 certificate to a #gnutls_pubkey_t
1017 * structure.
1019 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1020 * negative error value.
1022 * Since: 2.12.0
1025 gnutls_pubkey_import_pkcs11_url (gnutls_pubkey_t key, const char *url,
1026 unsigned int flags)
1028 gnutls_pkcs11_obj_t pcrt;
1029 int ret;
1031 ret = gnutls_pkcs11_obj_init (&pcrt);
1032 if (ret < 0)
1034 gnutls_assert ();
1035 return ret;
1038 if (key->pin.cb)
1039 gnutls_pkcs11_obj_set_pin_function(pcrt, key->pin.cb, key->pin.data);
1041 ret = gnutls_pkcs11_obj_import_url (pcrt, url, flags);
1042 if (ret < 0)
1044 gnutls_assert ();
1045 goto cleanup;
1048 ret = gnutls_pubkey_import_pkcs11 (key, pcrt, 0);
1049 if (ret < 0)
1051 gnutls_assert ();
1052 goto cleanup;
1055 ret = 0;
1056 cleanup:
1058 gnutls_pkcs11_obj_deinit (pcrt);
1060 return ret;
1063 #endif /* ENABLE_PKCS11 */
1066 * gnutls_pubkey_import_url:
1067 * @key: A key of type #gnutls_pubkey_t
1068 * @url: A PKCS 11 url
1069 * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1071 * This function will import a PKCS11 certificate or a TPM key
1072 * as a public key.
1074 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1075 * negative error value.
1077 * Since: 3.1.0
1080 gnutls_pubkey_import_url (gnutls_pubkey_t key, const char *url,
1081 unsigned int flags)
1083 #ifdef ENABLE_PKCS11
1084 if (strstr(url, "pkcs11:") != NULL)
1085 return gnutls_pubkey_import_pkcs11_url(key, url, flags);
1086 #endif
1087 #ifdef HAVE_TROUSERS
1088 if (strstr(url, "tpmkey:") != NULL)
1089 return gnutls_pubkey_import_tpm_url(key, url, NULL, 0);
1090 #endif
1091 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1095 * gnutls_pubkey_import_rsa_raw:
1096 * @key: Is a structure will hold the parameters
1097 * @m: holds the modulus
1098 * @e: holds the public exponent
1100 * This function will replace the parameters in the given structure.
1101 * The new parameters should be stored in the appropriate
1102 * gnutls_datum.
1104 * Returns: %GNUTLS_E_SUCCESS on success, or an negative error code.
1106 * Since: 2.12.0
1109 gnutls_pubkey_import_rsa_raw (gnutls_pubkey_t key,
1110 const gnutls_datum_t * m,
1111 const gnutls_datum_t * e)
1113 size_t siz = 0;
1115 if (key == NULL)
1117 gnutls_assert ();
1118 return GNUTLS_E_INVALID_REQUEST;
1121 gnutls_pk_params_init(&key->params);
1123 siz = m->size;
1124 if (_gnutls_mpi_scan_nz (&key->params.params[0], m->data, siz))
1126 gnutls_assert ();
1127 return GNUTLS_E_MPI_SCAN_FAILED;
1130 siz = e->size;
1131 if (_gnutls_mpi_scan_nz (&key->params.params[1], e->data, siz))
1133 gnutls_assert ();
1134 _gnutls_mpi_release (&key->params.params[0]);
1135 return GNUTLS_E_MPI_SCAN_FAILED;
1138 key->params.params_nr = RSA_PUBLIC_PARAMS;
1139 key->pk_algorithm = GNUTLS_PK_RSA;
1140 key->bits = pubkey_to_bits(GNUTLS_PK_RSA, &key->params);
1142 return 0;
1146 * gnutls_pubkey_import_ecc_raw:
1147 * @key: The structure to store the parsed key
1148 * @curve: holds the curve
1149 * @x: holds the x
1150 * @y: holds the y
1152 * This function will convert the given elliptic curve parameters to a
1153 * #gnutls_pubkey_t. The output will be stored in @key.
1155 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1156 * negative error value.
1158 * Since: 3.0
1161 gnutls_pubkey_import_ecc_raw (gnutls_pubkey_t key,
1162 gnutls_ecc_curve_t curve,
1163 const gnutls_datum_t * x,
1164 const gnutls_datum_t * y)
1166 int ret;
1168 if (key == NULL)
1170 gnutls_assert ();
1171 return GNUTLS_E_INVALID_REQUEST;
1174 key->params.flags = curve;
1176 ret = _gnutls_ecc_curve_fill_params(curve, &key->params);
1177 if (ret < 0)
1178 return gnutls_assert_val(ret);
1180 if (_gnutls_mpi_scan_nz (&key->params.params[ECC_X], x->data, x->size))
1182 gnutls_assert ();
1183 ret = GNUTLS_E_MPI_SCAN_FAILED;
1184 goto cleanup;
1186 key->params.params_nr++;
1188 if (_gnutls_mpi_scan_nz (&key->params.params[ECC_Y], y->data, y->size))
1190 gnutls_assert ();
1191 ret = GNUTLS_E_MPI_SCAN_FAILED;
1192 goto cleanup;
1194 key->params.params_nr++;
1195 key->pk_algorithm = GNUTLS_PK_EC;
1197 return 0;
1199 cleanup:
1200 gnutls_pk_params_release(&key->params);
1201 return ret;
1205 * gnutls_pubkey_import_ecc_x962:
1206 * @key: The structure to store the parsed key
1207 * @parameters: DER encoding of an ANSI X9.62 parameters
1208 * @ecpoint: DER encoding of ANSI X9.62 ECPoint
1210 * This function will convert the given elliptic curve parameters to a
1211 * #gnutls_pubkey_t. The output will be stored in @key.
1213 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1214 * negative error value.
1216 * Since: 3.0
1219 gnutls_pubkey_import_ecc_x962 (gnutls_pubkey_t key,
1220 const gnutls_datum_t * parameters,
1221 const gnutls_datum_t * ecpoint)
1223 int ret;
1225 if (key == NULL)
1227 gnutls_assert ();
1228 return GNUTLS_E_INVALID_REQUEST;
1231 key->params.params_nr = 0;
1233 ret = _gnutls_x509_read_ecc_params(parameters->data, parameters->size,
1234 &key->params);
1235 if (ret < 0)
1237 gnutls_assert ();
1238 goto cleanup;
1241 ret = _gnutls_ecc_ansi_x963_import(ecpoint->data, ecpoint->size,
1242 &key->params.params[ECC_X], &key->params.params[ECC_Y]);
1243 if (ret < 0)
1245 gnutls_assert ();
1246 goto cleanup;
1248 key->params.params_nr+=2;
1249 key->pk_algorithm = GNUTLS_PK_EC;
1251 return 0;
1253 cleanup:
1254 gnutls_pk_params_release(&key->params);
1255 return ret;
1259 * gnutls_pubkey_import_dsa_raw:
1260 * @key: The structure to store the parsed key
1261 * @p: holds the p
1262 * @q: holds the q
1263 * @g: holds the g
1264 * @y: holds the y
1266 * This function will convert the given DSA raw parameters to the
1267 * native #gnutls_pubkey_t format. The output will be stored
1268 * in @key.
1270 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1271 * negative error value.
1273 * Since: 2.12.0
1276 gnutls_pubkey_import_dsa_raw (gnutls_pubkey_t key,
1277 const gnutls_datum_t * p,
1278 const gnutls_datum_t * q,
1279 const gnutls_datum_t * g,
1280 const gnutls_datum_t * y)
1282 size_t siz = 0;
1284 if (key == NULL)
1286 gnutls_assert ();
1287 return GNUTLS_E_INVALID_REQUEST;
1290 gnutls_pk_params_init(&key->params);
1292 siz = p->size;
1293 if (_gnutls_mpi_scan_nz (&key->params.params[0], p->data, siz))
1295 gnutls_assert ();
1296 return GNUTLS_E_MPI_SCAN_FAILED;
1299 siz = q->size;
1300 if (_gnutls_mpi_scan_nz (&key->params.params[1], q->data, siz))
1302 gnutls_assert ();
1303 _gnutls_mpi_release (&key->params.params[0]);
1304 return GNUTLS_E_MPI_SCAN_FAILED;
1307 siz = g->size;
1308 if (_gnutls_mpi_scan_nz (&key->params.params[2], g->data, siz))
1310 gnutls_assert ();
1311 _gnutls_mpi_release (&key->params.params[1]);
1312 _gnutls_mpi_release (&key->params.params[0]);
1313 return GNUTLS_E_MPI_SCAN_FAILED;
1316 siz = y->size;
1317 if (_gnutls_mpi_scan_nz (&key->params.params[3], y->data, siz))
1319 gnutls_assert ();
1320 _gnutls_mpi_release (&key->params.params[2]);
1321 _gnutls_mpi_release (&key->params.params[1]);
1322 _gnutls_mpi_release (&key->params.params[0]);
1323 return GNUTLS_E_MPI_SCAN_FAILED;
1326 key->params.params_nr = DSA_PUBLIC_PARAMS;
1327 key->pk_algorithm = GNUTLS_PK_DSA;
1328 key->bits = pubkey_to_bits(GNUTLS_PK_DSA, &key->params);
1330 return 0;
1335 * gnutls_pubkey_verify_data:
1336 * @pubkey: Holds the public key
1337 * @flags: should be 0 for now
1338 * @data: holds the signed data
1339 * @signature: contains the signature
1341 * This function will verify the given signed data, using the
1342 * parameters from the certificate.
1344 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1345 * is returned, and zero or positive code on success.
1347 * Deprecated. Use gnutls_pubkey_verify_data2() instead of this function.
1349 * Since: 2.12.0
1352 gnutls_pubkey_verify_data (gnutls_pubkey_t pubkey, unsigned int flags,
1353 const gnutls_datum_t * data,
1354 const gnutls_datum_t * signature)
1356 int ret;
1358 if (pubkey == NULL)
1360 gnutls_assert ();
1361 return GNUTLS_E_INVALID_REQUEST;
1364 ret = pubkey_verify_data( pubkey->pk_algorithm, GNUTLS_DIG_UNKNOWN, data, signature,
1365 &pubkey->params);
1366 if (ret < 0)
1368 gnutls_assert();
1371 return ret;
1375 * gnutls_pubkey_verify_data2:
1376 * @pubkey: Holds the public key
1377 * @algo: The signature algorithm used
1378 * @flags: should be 0 for now
1379 * @data: holds the signed data
1380 * @signature: contains the signature
1382 * This function will verify the given signed data, using the
1383 * parameters from the certificate.
1385 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1386 * is returned, and zero or positive code on success.
1388 * Since: 3.0
1391 gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey,
1392 gnutls_sign_algorithm_t algo,
1393 unsigned int flags,
1394 const gnutls_datum_t * data,
1395 const gnutls_datum_t * signature)
1397 int ret;
1399 if (pubkey == NULL)
1401 gnutls_assert ();
1402 return GNUTLS_E_INVALID_REQUEST;
1405 ret = pubkey_verify_data( pubkey->pk_algorithm, gnutls_sign_get_hash_algorithm(algo),
1406 data, signature, &pubkey->params);
1407 if (ret < 0)
1409 gnutls_assert();
1412 return ret;
1417 * gnutls_pubkey_verify_hash:
1418 * @key: Holds the public key
1419 * @flags: should be 0 for now
1420 * @hash: holds the hash digest to be verified
1421 * @signature: contains the signature
1423 * This function will verify the given signed digest, using the
1424 * parameters from the public key.
1426 * Deprecated. Use gnutls_pubkey_verify_hash2() instead of this function.
1428 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1429 * is returned, and zero or positive code on success.
1431 * Since: 2.12.0
1434 gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags,
1435 const gnutls_datum_t * hash,
1436 const gnutls_datum_t * signature)
1438 gnutls_digest_algorithm_t algo;
1439 int ret;
1441 ret = gnutls_pubkey_get_verify_algorithm (key, signature, &algo);
1442 if (ret < 0)
1443 return gnutls_assert_val(ret);
1445 return gnutls_pubkey_verify_hash2(key, gnutls_pk_to_sign(key->pk_algorithm, algo),
1446 flags, hash, signature);
1450 * gnutls_pubkey_verify_hash2:
1451 * @key: Holds the public key
1452 * @algo: The signature algorithm used
1453 * @flags: should be 0 for now
1454 * @hash: holds the hash digest to be verified
1455 * @signature: contains the signature
1457 * This function will verify the given signed digest, using the
1458 * parameters from the public key.
1460 * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED
1461 * is returned, and zero or positive code on success.
1463 * Since: 3.0
1466 gnutls_pubkey_verify_hash2 (gnutls_pubkey_t key,
1467 gnutls_sign_algorithm_t algo,
1468 unsigned int flags,
1469 const gnutls_datum_t * hash,
1470 const gnutls_datum_t * signature)
1472 if (key == NULL)
1474 gnutls_assert ();
1475 return GNUTLS_E_INVALID_REQUEST;
1478 if (flags & GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA)
1479 return _gnutls_pk_verify (GNUTLS_PK_RSA, hash, signature, &key->params);
1480 else
1482 return pubkey_verify_hashed_data (key->pk_algorithm, gnutls_sign_get_hash_algorithm(algo),
1483 hash, signature, &key->params);
1488 * gnutls_pubkey_encrypt_data:
1489 * @key: Holds the public key
1490 * @flags: should be 0 for now
1491 * @plaintext: The data to be encrypted
1492 * @ciphertext: contains the encrypted data
1494 * This function will encrypt the given data, using the public
1495 * key.
1497 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1498 * negative error value.
1500 * Since: 3.0
1503 gnutls_pubkey_encrypt_data (gnutls_pubkey_t key, unsigned int flags,
1504 const gnutls_datum_t * plaintext,
1505 gnutls_datum_t * ciphertext)
1507 if (key == NULL)
1509 gnutls_assert ();
1510 return GNUTLS_E_INVALID_REQUEST;
1513 return _gnutls_pk_encrypt (key->pk_algorithm, ciphertext,
1514 plaintext, &key->params);
1518 * gnutls_pubkey_get_verify_algorithm:
1519 * @key: Holds the certificate
1520 * @signature: contains the signature
1521 * @hash: The result of the call with the hash algorithm used for signature
1523 * This function will read the certifcate and the signed data to
1524 * determine the hash algorithm used to generate the signature.
1526 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1527 * negative error value.
1529 * Since: 2.12.0
1532 gnutls_pubkey_get_verify_algorithm (gnutls_pubkey_t key,
1533 const gnutls_datum_t * signature,
1534 gnutls_digest_algorithm_t * hash)
1536 if (key == NULL)
1538 gnutls_assert ();
1539 return GNUTLS_E_INVALID_REQUEST;
1542 return _gnutls_x509_verify_algorithm (hash, signature,
1543 key->pk_algorithm,
1544 &key->params);
1548 /* Checks whether the public key given is compatible with the
1549 * signature algorithm used. The session is only used for audit logging, and
1550 * it may be null.
1552 int _gnutls_pubkey_compatible_with_sig(gnutls_session_t session,
1553 gnutls_pubkey_t pubkey,
1554 gnutls_protocol_t ver,
1555 gnutls_sign_algorithm_t sign)
1557 unsigned int hash_size;
1558 unsigned int hash_algo;
1559 unsigned int sig_hash_size;
1561 if (pubkey->pk_algorithm == GNUTLS_PK_DSA)
1563 hash_algo = _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, &pubkey->params, &hash_size);
1565 /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
1566 if (!_gnutls_version_has_selectable_sighash (ver))
1568 if (hash_algo != GNUTLS_DIG_SHA1)
1569 return gnutls_assert_val(GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
1571 else if (sign != GNUTLS_SIGN_UNKNOWN)
1573 sig_hash_size = _gnutls_hash_get_algo_len(gnutls_sign_get_hash_algorithm(sign));
1574 if (sig_hash_size < hash_size)
1575 _gnutls_audit_log(session, "The hash size used in signature (%u) is less than the expected (%u)\n", sig_hash_size, hash_size);
1579 else if (pubkey->pk_algorithm == GNUTLS_PK_EC)
1581 if (_gnutls_version_has_selectable_sighash (ver) && sign != GNUTLS_SIGN_UNKNOWN)
1583 _gnutls_dsa_q_to_hash (pubkey->pk_algorithm, &pubkey->params, &hash_size);
1584 sig_hash_size = _gnutls_hash_get_algo_len(gnutls_sign_get_hash_algorithm(sign));
1586 if (sig_hash_size < hash_size)
1587 _gnutls_audit_log(session, "The hash size used in signature (%u) is less than the expected (%u)\n", sig_hash_size, hash_size);
1592 return 0;
1595 /* Returns zero if the public key has more than 512 bits */
1596 int _gnutls_pubkey_is_over_rsa_512(gnutls_pubkey_t pubkey)
1598 if (pubkey->pk_algorithm == GNUTLS_PK_RSA && _gnutls_mpi_get_nbits (pubkey->params.params[0]) > 512)
1599 return 0;
1600 else
1601 return GNUTLS_E_INVALID_REQUEST; /* doesn't matter */
1605 /* Returns the public key.
1608 _gnutls_pubkey_get_mpis (gnutls_pubkey_t key,
1609 gnutls_pk_params_st * params)
1611 return _gnutls_pk_params_copy(params, &key->params);
1614 /* if hash==MD5 then we do RSA-MD5
1615 * if hash==SHA then we do RSA-SHA
1616 * params[0] is modulus
1617 * params[1] is public key
1619 static int
1620 _pkcs1_rsa_verify_sig (gnutls_digest_algorithm_t hash,
1621 const gnutls_datum_t * text,
1622 const gnutls_datum_t * prehash,
1623 const gnutls_datum_t * signature,
1624 gnutls_pk_params_st * params)
1626 int ret;
1627 uint8_t md[MAX_HASH_SIZE], *cmp;
1628 unsigned int digest_size;
1629 gnutls_datum_t d, di;
1630 digest_hd_st hd;
1632 digest_size = _gnutls_hash_get_algo_len (hash);
1633 if (prehash)
1635 if (prehash->data == NULL || prehash->size != digest_size)
1636 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1638 cmp = prehash->data;
1640 else
1642 if (!text)
1644 gnutls_assert ();
1645 return GNUTLS_E_INVALID_REQUEST;
1648 ret = _gnutls_hash_init (&hd, hash);
1649 if (ret < 0)
1651 gnutls_assert ();
1652 return ret;
1655 _gnutls_hash (&hd, text->data, text->size);
1656 _gnutls_hash_deinit (&hd, md);
1658 cmp = md;
1661 d.data = cmp;
1662 d.size = digest_size;
1664 /* decrypted is a BER encoded data of type DigestInfo
1667 ret = encode_ber_digest_info (hash, &d, &di);
1668 if (ret < 0)
1669 return gnutls_assert_val(ret);
1671 ret = _gnutls_pk_verify (GNUTLS_PK_RSA, &di, signature, params);
1673 _gnutls_free_datum (&di);
1675 return ret;
1678 /* Hashes input data and verifies a signature.
1680 static int
1681 dsa_verify_hashed_data (gnutls_pk_algorithm_t pk,
1682 gnutls_digest_algorithm_t algo,
1683 const gnutls_datum_t * hash,
1684 const gnutls_datum_t * signature,
1685 gnutls_pk_params_st* params)
1687 gnutls_datum_t digest;
1688 unsigned int hash_len;
1690 if (algo == GNUTLS_DIG_UNKNOWN)
1691 algo = _gnutls_dsa_q_to_hash (pk, params, &hash_len);
1692 else hash_len = _gnutls_hash_get_algo_len(algo);
1694 /* SHA1 or better allowed */
1695 if (!hash->data || hash->size < hash_len)
1697 gnutls_assert();
1698 _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);
1700 if (hash->size != 20) /* SHA1 is allowed */
1701 return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
1704 digest.data = hash->data;
1705 digest.size = hash->size;
1707 return _gnutls_pk_verify (pk, &digest, signature, params);
1710 static int
1711 dsa_verify_data (gnutls_pk_algorithm_t pk,
1712 gnutls_digest_algorithm_t algo,
1713 const gnutls_datum_t * data,
1714 const gnutls_datum_t * signature,
1715 gnutls_pk_params_st* params)
1717 int ret;
1718 uint8_t _digest[MAX_HASH_SIZE];
1719 gnutls_datum_t digest;
1720 digest_hd_st hd;
1722 if (algo == GNUTLS_DIG_UNKNOWN)
1723 algo = _gnutls_dsa_q_to_hash (pk, params, NULL);
1725 ret = _gnutls_hash_init (&hd, algo);
1726 if (ret < 0)
1727 return gnutls_assert_val(ret);
1729 _gnutls_hash (&hd, data->data, data->size);
1730 _gnutls_hash_deinit (&hd, _digest);
1732 digest.data = _digest;
1733 digest.size = _gnutls_hash_get_algo_len(algo);
1735 return _gnutls_pk_verify (pk, &digest, signature, params);
1738 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if
1739 * not verified, or 1 otherwise.
1742 pubkey_verify_hashed_data (gnutls_pk_algorithm_t pk,
1743 gnutls_digest_algorithm_t hash_algo,
1744 const gnutls_datum_t * hash,
1745 const gnutls_datum_t * signature,
1746 gnutls_pk_params_st * issuer_params)
1749 switch (pk)
1751 case GNUTLS_PK_RSA:
1753 if (_pkcs1_rsa_verify_sig
1754 (hash_algo, NULL, hash, signature, issuer_params) != 0)
1756 gnutls_assert ();
1757 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1760 return 1;
1761 break;
1763 case GNUTLS_PK_EC:
1764 case GNUTLS_PK_DSA:
1765 if (dsa_verify_hashed_data(pk, hash_algo, hash, signature, issuer_params) != 0)
1767 gnutls_assert ();
1768 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1771 return 1;
1772 break;
1773 default:
1774 gnutls_assert ();
1775 return GNUTLS_E_INTERNAL_ERROR;
1780 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if
1781 * not verified, or 1 otherwise.
1784 pubkey_verify_data (gnutls_pk_algorithm_t pk,
1785 gnutls_digest_algorithm_t hash_algo,
1786 const gnutls_datum_t * data,
1787 const gnutls_datum_t * signature,
1788 gnutls_pk_params_st * issuer_params)
1791 switch (pk)
1793 case GNUTLS_PK_RSA:
1795 if (_pkcs1_rsa_verify_sig
1796 (hash_algo, data, NULL, signature, issuer_params) != 0)
1798 gnutls_assert ();
1799 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1802 return 1;
1803 break;
1805 case GNUTLS_PK_EC:
1806 case GNUTLS_PK_DSA:
1807 if (dsa_verify_data(pk, hash_algo, data, signature, issuer_params) != 0)
1809 gnutls_assert ();
1810 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1813 return 1;
1814 break;
1815 default:
1816 gnutls_assert ();
1817 return GNUTLS_E_INTERNAL_ERROR;
1822 gnutls_digest_algorithm_t
1823 _gnutls_dsa_q_to_hash (gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params,
1824 unsigned int* hash_len)
1826 int bits = 0;
1828 if (algo == GNUTLS_PK_DSA)
1829 bits = _gnutls_mpi_get_nbits (params->params[1]);
1830 else if (algo == GNUTLS_PK_EC)
1831 bits = gnutls_ecc_curve_get_size(params->flags)*8;
1833 if (bits <= 160)
1835 if (hash_len) *hash_len = 20;
1836 return GNUTLS_DIG_SHA1;
1838 else if (bits <= 192)
1840 if (hash_len) *hash_len = 24;
1841 return GNUTLS_DIG_SHA256;
1843 else if (bits <= 224)
1845 if (hash_len) *hash_len = 28;
1846 return GNUTLS_DIG_SHA256;
1848 else if (bits <= 256)
1850 if (hash_len) *hash_len = 32;
1851 return GNUTLS_DIG_SHA256;
1853 else if (bits <= 384)
1855 if (hash_len) *hash_len = 48;
1856 return GNUTLS_DIG_SHA384;
1858 else
1860 if (hash_len) *hash_len = 64;
1861 return GNUTLS_DIG_SHA512;
1866 * gnutls_pubkey_set_pin_function:
1867 * @key: A key of type #gnutls_pubkey_t
1868 * @fn: the callback
1869 * @userdata: data associated with the callback
1871 * This function will set a callback function to be used when
1872 * required to access the object. This function overrides any other
1873 * global PIN functions.
1875 * Note that this function must be called right after initialization
1876 * to have effect.
1878 * Since: 3.1.0
1881 void gnutls_pubkey_set_pin_function (gnutls_pubkey_t key,
1882 gnutls_pin_callback_t fn, void *userdata)
1884 key->pin.cb = fn;
1885 key->pin.data = userdata;