Added functions to export structures in an allocated buffer.
[gnutls.git] / lib / gnutls_pubkey.c
blob21bea55ed96d4472cd3037c5059146293a78e2be
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;
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
553 * X.509 structure.
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.
563 * Since: 3.1.3
566 gnutls_pubkey_export2 (gnutls_pubkey_t key,
567 gnutls_x509_crt_fmt_t format,
568 gnutls_datum_t * out)
570 int result;
571 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
573 if (key == NULL)
575 gnutls_assert ();
576 return GNUTLS_E_INVALID_REQUEST;
579 if ((result = asn1_create_element
580 (_gnutls_get_pkix (), "PKIX1.SubjectPublicKeyInfo", &spk))
581 != ASN1_SUCCESS)
583 gnutls_assert ();
584 return _gnutls_asn2err (result);
587 result =
588 _gnutls_x509_encode_and_copy_PKI_params (spk, "",
589 key->pk_algorithm,
590 &key->params);
591 if (result < 0)
593 gnutls_assert ();
594 goto cleanup;
597 result = _gnutls_x509_export_int_named2 (spk, "",
598 format, PK_PEM_HEADER, out);
599 if (result < 0)
601 gnutls_assert ();
602 goto cleanup;
605 result = 0;
607 cleanup:
608 asn1_delete_structure (&spk);
610 return result;
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,
628 * which is 20 bytes.
630 * Returns: In case of failure a negative error code will be
631 * returned, and 0 on success.
633 * Since: 2.12.0
636 gnutls_pubkey_get_key_id (gnutls_pubkey_t key, unsigned int flags,
637 unsigned char *output_data,
638 size_t * output_data_size)
640 int ret = 0;
642 if (key == NULL)
644 gnutls_assert ();
645 return GNUTLS_E_INVALID_REQUEST;
648 ret =
649 _gnutls_get_key_id (key->pk_algorithm, &key->params,
650 output_data, output_data_size);
651 if (ret < 0)
653 gnutls_assert ();
654 return ret;
657 return 0;
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.
672 * Since: 2.12.0
675 gnutls_pubkey_get_pk_rsa_raw (gnutls_pubkey_t key,
676 gnutls_datum_t * m, gnutls_datum_t * e)
678 int ret;
680 if (key == NULL)
682 gnutls_assert ();
683 return GNUTLS_E_INVALID_REQUEST;
686 if (key->pk_algorithm != GNUTLS_PK_RSA)
688 gnutls_assert ();
689 return GNUTLS_E_INVALID_REQUEST;
692 ret = _gnutls_mpi_dprint_lz (key->params.params[0], m);
693 if (ret < 0)
695 gnutls_assert ();
696 return ret;
699 ret = _gnutls_mpi_dprint_lz (key->params.params[1], e);
700 if (ret < 0)
702 gnutls_assert ();
703 _gnutls_free_datum (m);
704 return ret;
707 return 0;
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.
724 * Since: 2.12.0
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)
731 int ret;
733 if (key == NULL)
735 gnutls_assert ();
736 return GNUTLS_E_INVALID_REQUEST;
739 if (key->pk_algorithm != GNUTLS_PK_DSA)
741 gnutls_assert ();
742 return GNUTLS_E_INVALID_REQUEST;
745 /* P */
746 ret = _gnutls_mpi_dprint_lz (key->params.params[0], p);
747 if (ret < 0)
749 gnutls_assert ();
750 return ret;
753 /* Q */
754 ret = _gnutls_mpi_dprint_lz (key->params.params[1], q);
755 if (ret < 0)
757 gnutls_assert ();
758 _gnutls_free_datum (p);
759 return ret;
763 /* G */
764 ret = _gnutls_mpi_dprint_lz (key->params.params[2], g);
765 if (ret < 0)
767 gnutls_assert ();
768 _gnutls_free_datum (p);
769 _gnutls_free_datum (q);
770 return ret;
774 /* Y */
775 ret = _gnutls_mpi_dprint_lz (key->params.params[3], y);
776 if (ret < 0)
778 gnutls_assert ();
779 _gnutls_free_datum (p);
780 _gnutls_free_datum (g);
781 _gnutls_free_datum (q);
782 return ret;
785 return 0;
789 * gnutls_pubkey_get_pk_ecc_raw:
790 * @key: Holds the public key
791 * @curve: will hold the curve
792 * @x: will hold x
793 * @y: will hold y
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.
801 * Since: 3.0
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)
807 int ret;
809 if (key == NULL)
811 gnutls_assert ();
812 return GNUTLS_E_INVALID_REQUEST;
815 if (key->pk_algorithm != GNUTLS_PK_EC)
817 gnutls_assert ();
818 return GNUTLS_E_INVALID_REQUEST;
821 *curve = key->params.flags;
823 /* X */
824 ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_X], x);
825 if (ret < 0)
827 gnutls_assert ();
828 return ret;
831 /* Y */
832 ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_Y], y);
833 if (ret < 0)
835 gnutls_assert ();
836 _gnutls_free_datum (x);
837 return ret;
840 return 0;
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.
855 * Since: 3.0
857 int gnutls_pubkey_get_pk_ecc_x962 (gnutls_pubkey_t key, gnutls_datum_t* parameters,
858 gnutls_datum_t * ecpoint)
860 int ret;
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);
866 if (ret < 0)
867 return gnutls_assert_val(ret);
869 ret = _gnutls_x509_write_ecc_params(&key->params, parameters);
870 if (ret < 0)
872 _gnutls_free_datum(ecpoint);
873 return gnutls_assert_val(ret);
876 return 0;
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
889 * of "PUBLIC KEY".
891 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
892 * negative error value.
894 * Since: 2.12.0
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;
903 ASN1_TYPE spk;
905 if (key == NULL)
907 gnutls_assert ();
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 */
919 result =
920 _gnutls_fbase64_decode (PK_PEM_HEADER, data->data, data->size, &_data);
922 if (result < 0)
924 gnutls_assert ();
925 return result;
928 need_free = 1;
931 if ((result = asn1_create_element
932 (_gnutls_get_pkix (), "PKIX1.SubjectPublicKeyInfo", &spk))
933 != ASN1_SUCCESS)
935 gnutls_assert ();
936 result = _gnutls_asn2err (result);
937 goto cleanup;
940 result = asn1_der_decoding (&spk, _data.data, _data.size, NULL);
941 if (result != ASN1_SUCCESS)
943 gnutls_assert ();
944 result = _gnutls_asn2err (result);
945 goto cleanup;
948 result = _gnutls_get_asn_mpis (spk, "", &key->params);
949 if (result < 0)
951 gnutls_assert ();
952 goto cleanup;
955 /* this has already been called by get_asn_mpis() thus it cannot
956 * fail.
958 key->pk_algorithm = _gnutls_x509_get_pk_algorithm (spk, "", NULL);
959 key->bits = pubkey_to_bits(key->pk_algorithm, &key->params);
961 result = 0;
963 cleanup:
964 asn1_delete_structure (&spk);
966 if (need_free)
967 _gnutls_free_datum (&_data);
968 return result;
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.
982 * Since: 2.12.0
985 gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, gnutls_pubkey_t key)
987 int result;
989 if (crt == NULL)
991 gnutls_assert ();
992 return GNUTLS_E_INVALID_REQUEST;
995 result = _gnutls_x509_encode_and_copy_PKI_params (crt->cert,
996 "tbsCertificate.subjectPublicKeyInfo",
997 key->pk_algorithm,
998 &key->params);
1000 if (result < 0)
1002 gnutls_assert ();
1003 return result;
1006 if (key->key_usage)
1007 gnutls_x509_crt_set_key_usage (crt, key->key_usage);
1009 return 0;
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.
1023 * Since: 2.12.0
1026 gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, gnutls_pubkey_t key)
1028 int result;
1030 if (crq == NULL)
1032 gnutls_assert ();
1033 return GNUTLS_E_INVALID_REQUEST;
1036 result = _gnutls_x509_encode_and_copy_PKI_params
1037 (crq->crq,
1038 "certificationRequestInfo.subjectPKInfo",
1039 key->pk_algorithm, &key->params);
1041 if (result < 0)
1043 gnutls_assert ();
1044 return result;
1047 if (key->key_usage)
1048 gnutls_x509_crq_set_key_usage (crq, key->key_usage);
1050 return 0;
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.
1065 * Since: 2.12.0
1068 gnutls_pubkey_set_key_usage (gnutls_pubkey_t key, unsigned int usage)
1070 key->key_usage = usage;
1072 return 0;
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
1084 * structure.
1086 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1087 * negative error value.
1089 * Since: 2.12.0
1092 gnutls_pubkey_import_pkcs11_url (gnutls_pubkey_t key, const char *url,
1093 unsigned int flags)
1095 gnutls_pkcs11_obj_t pcrt;
1096 int ret;
1098 ret = gnutls_pkcs11_obj_init (&pcrt);
1099 if (ret < 0)
1101 gnutls_assert ();
1102 return ret;
1105 if (key->pin.cb)
1106 gnutls_pkcs11_obj_set_pin_function(pcrt, key->pin.cb, key->pin.data);
1108 ret = gnutls_pkcs11_obj_import_url (pcrt, url, flags);
1109 if (ret < 0)
1111 gnutls_assert ();
1112 goto cleanup;
1115 ret = gnutls_pubkey_import_pkcs11 (key, pcrt, 0);
1116 if (ret < 0)
1118 gnutls_assert ();
1119 goto cleanup;
1122 ret = 0;
1123 cleanup:
1125 gnutls_pkcs11_obj_deinit (pcrt);
1127 return ret;
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
1139 * as a public key.
1141 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1142 * negative error value.
1144 * Since: 3.1.0
1147 gnutls_pubkey_import_url (gnutls_pubkey_t key, const char *url,
1148 unsigned int flags)
1150 #ifdef ENABLE_PKCS11
1151 if (strstr(url, "pkcs11:") != NULL)
1152 return gnutls_pubkey_import_pkcs11_url(key, url, flags);
1153 #endif
1154 #ifdef HAVE_TROUSERS
1155 if (strstr(url, "tpmkey:") != NULL)
1156 return gnutls_pubkey_import_tpm_url(key, url, NULL, 0);
1157 #endif
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
1169 * gnutls_datum.
1171 * Returns: %GNUTLS_E_SUCCESS on success, or an negative error code.
1173 * Since: 2.12.0
1176 gnutls_pubkey_import_rsa_raw (gnutls_pubkey_t key,
1177 const gnutls_datum_t * m,
1178 const gnutls_datum_t * e)
1180 size_t siz = 0;
1182 if (key == NULL)
1184 gnutls_assert ();
1185 return GNUTLS_E_INVALID_REQUEST;
1188 gnutls_pk_params_init(&key->params);
1190 siz = m->size;
1191 if (_gnutls_mpi_scan_nz (&key->params.params[0], m->data, siz))
1193 gnutls_assert ();
1194 return GNUTLS_E_MPI_SCAN_FAILED;
1197 siz = e->size;
1198 if (_gnutls_mpi_scan_nz (&key->params.params[1], e->data, siz))
1200 gnutls_assert ();
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);
1209 return 0;
1213 * gnutls_pubkey_import_ecc_raw:
1214 * @key: The structure to store the parsed key
1215 * @curve: holds the curve
1216 * @x: holds the x
1217 * @y: holds the y
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.
1225 * Since: 3.0
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)
1233 int ret;
1235 if (key == NULL)
1237 gnutls_assert ();
1238 return GNUTLS_E_INVALID_REQUEST;
1241 key->params.flags = curve;
1243 ret = _gnutls_ecc_curve_fill_params(curve, &key->params);
1244 if (ret < 0)
1245 return gnutls_assert_val(ret);
1247 if (_gnutls_mpi_scan_nz (&key->params.params[ECC_X], x->data, x->size))
1249 gnutls_assert ();
1250 ret = GNUTLS_E_MPI_SCAN_FAILED;
1251 goto cleanup;
1253 key->params.params_nr++;
1255 if (_gnutls_mpi_scan_nz (&key->params.params[ECC_Y], y->data, y->size))
1257 gnutls_assert ();
1258 ret = GNUTLS_E_MPI_SCAN_FAILED;
1259 goto cleanup;
1261 key->params.params_nr++;
1262 key->pk_algorithm = GNUTLS_PK_EC;
1264 return 0;
1266 cleanup:
1267 gnutls_pk_params_release(&key->params);
1268 return ret;
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.
1283 * Since: 3.0
1286 gnutls_pubkey_import_ecc_x962 (gnutls_pubkey_t key,
1287 const gnutls_datum_t * parameters,
1288 const gnutls_datum_t * ecpoint)
1290 int ret;
1292 if (key == NULL)
1294 gnutls_assert ();
1295 return GNUTLS_E_INVALID_REQUEST;
1298 key->params.params_nr = 0;
1300 ret = _gnutls_x509_read_ecc_params(parameters->data, parameters->size,
1301 &key->params);
1302 if (ret < 0)
1304 gnutls_assert ();
1305 goto cleanup;
1308 ret = _gnutls_ecc_ansi_x963_import(ecpoint->data, ecpoint->size,
1309 &key->params.params[ECC_X], &key->params.params[ECC_Y]);
1310 if (ret < 0)
1312 gnutls_assert ();
1313 goto cleanup;
1315 key->params.params_nr+=2;
1316 key->pk_algorithm = GNUTLS_PK_EC;
1318 return 0;
1320 cleanup:
1321 gnutls_pk_params_release(&key->params);
1322 return ret;
1326 * gnutls_pubkey_import_dsa_raw:
1327 * @key: The structure to store the parsed key
1328 * @p: holds the p
1329 * @q: holds the q
1330 * @g: holds the g
1331 * @y: holds the y
1333 * This function will convert the given DSA raw parameters to the
1334 * native #gnutls_pubkey_t format. The output will be stored
1335 * in @key.
1337 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1338 * negative error value.
1340 * Since: 2.12.0
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)
1349 size_t siz = 0;
1351 if (key == NULL)
1353 gnutls_assert ();
1354 return GNUTLS_E_INVALID_REQUEST;
1357 gnutls_pk_params_init(&key->params);
1359 siz = p->size;
1360 if (_gnutls_mpi_scan_nz (&key->params.params[0], p->data, siz))
1362 gnutls_assert ();
1363 return GNUTLS_E_MPI_SCAN_FAILED;
1366 siz = q->size;
1367 if (_gnutls_mpi_scan_nz (&key->params.params[1], q->data, siz))
1369 gnutls_assert ();
1370 _gnutls_mpi_release (&key->params.params[0]);
1371 return GNUTLS_E_MPI_SCAN_FAILED;
1374 siz = g->size;
1375 if (_gnutls_mpi_scan_nz (&key->params.params[2], g->data, siz))
1377 gnutls_assert ();
1378 _gnutls_mpi_release (&key->params.params[1]);
1379 _gnutls_mpi_release (&key->params.params[0]);
1380 return GNUTLS_E_MPI_SCAN_FAILED;
1383 siz = y->size;
1384 if (_gnutls_mpi_scan_nz (&key->params.params[3], y->data, siz))
1386 gnutls_assert ();
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);
1397 return 0;
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.
1416 * Since: 2.12.0
1419 gnutls_pubkey_verify_data (gnutls_pubkey_t pubkey, unsigned int flags,
1420 const gnutls_datum_t * data,
1421 const gnutls_datum_t * signature)
1423 int ret;
1425 if (pubkey == NULL)
1427 gnutls_assert ();
1428 return GNUTLS_E_INVALID_REQUEST;
1431 ret = pubkey_verify_data( pubkey->pk_algorithm, GNUTLS_DIG_UNKNOWN, data, signature,
1432 &pubkey->params);
1433 if (ret < 0)
1435 gnutls_assert();
1438 return ret;
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.
1455 * Since: 3.0
1458 gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey,
1459 gnutls_sign_algorithm_t algo,
1460 unsigned int flags,
1461 const gnutls_datum_t * data,
1462 const gnutls_datum_t * signature)
1464 int ret;
1466 if (pubkey == NULL)
1468 gnutls_assert ();
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);
1474 if (ret < 0)
1476 gnutls_assert();
1479 return ret;
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.
1498 * Since: 2.12.0
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;
1506 int ret;
1508 ret = gnutls_pubkey_get_verify_algorithm (key, signature, &algo);
1509 if (ret < 0)
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.
1530 * Since: 3.0
1533 gnutls_pubkey_verify_hash2 (gnutls_pubkey_t key,
1534 gnutls_sign_algorithm_t algo,
1535 unsigned int flags,
1536 const gnutls_datum_t * hash,
1537 const gnutls_datum_t * signature)
1539 if (key == NULL)
1541 gnutls_assert ();
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);
1547 else
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
1562 * key.
1564 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1565 * negative error value.
1567 * Since: 3.0
1570 gnutls_pubkey_encrypt_data (gnutls_pubkey_t key, unsigned int flags,
1571 const gnutls_datum_t * plaintext,
1572 gnutls_datum_t * ciphertext)
1574 if (key == NULL)
1576 gnutls_assert ();
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.
1596 * Since: 2.12.0
1599 gnutls_pubkey_get_verify_algorithm (gnutls_pubkey_t key,
1600 const gnutls_datum_t * signature,
1601 gnutls_digest_algorithm_t * hash)
1603 if (key == NULL)
1605 gnutls_assert ();
1606 return GNUTLS_E_INVALID_REQUEST;
1609 return _gnutls_x509_verify_algorithm (hash, signature,
1610 key->pk_algorithm,
1611 &key->params);
1615 /* Checks whether the public key given is compatible with the
1616 * signature algorithm used. The session is only used for audit logging, and
1617 * it may be null.
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);
1659 return 0;
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)
1666 return 0;
1667 else
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
1686 static int
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)
1693 int ret;
1694 uint8_t md[MAX_HASH_SIZE], *cmp;
1695 unsigned int digest_size;
1696 gnutls_datum_t d, di;
1697 digest_hd_st hd;
1699 digest_size = _gnutls_hash_get_algo_len (hash);
1700 if (prehash)
1702 if (prehash->data == NULL || prehash->size != digest_size)
1703 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1705 cmp = prehash->data;
1707 else
1709 if (!text)
1711 gnutls_assert ();
1712 return GNUTLS_E_INVALID_REQUEST;
1715 ret = _gnutls_hash_init (&hd, hash);
1716 if (ret < 0)
1718 gnutls_assert ();
1719 return ret;
1722 _gnutls_hash (&hd, text->data, text->size);
1723 _gnutls_hash_deinit (&hd, md);
1725 cmp = md;
1728 d.data = cmp;
1729 d.size = digest_size;
1731 /* decrypted is a BER encoded data of type DigestInfo
1734 ret = encode_ber_digest_info (hash, &d, &di);
1735 if (ret < 0)
1736 return gnutls_assert_val(ret);
1738 ret = _gnutls_pk_verify (GNUTLS_PK_RSA, &di, signature, params);
1740 _gnutls_free_datum (&di);
1742 return ret;
1745 /* Hashes input data and verifies a signature.
1747 static int
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)
1764 gnutls_assert();
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);
1777 static int
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)
1784 int ret;
1785 uint8_t _digest[MAX_HASH_SIZE];
1786 gnutls_datum_t digest;
1787 digest_hd_st hd;
1789 if (algo == GNUTLS_DIG_UNKNOWN)
1790 algo = _gnutls_dsa_q_to_hash (pk, params, NULL);
1792 ret = _gnutls_hash_init (&hd, algo);
1793 if (ret < 0)
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)
1816 switch (pk)
1818 case GNUTLS_PK_RSA:
1820 if (_pkcs1_rsa_verify_sig
1821 (hash_algo, NULL, hash, signature, issuer_params) != 0)
1823 gnutls_assert ();
1824 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1827 return 1;
1828 break;
1830 case GNUTLS_PK_EC:
1831 case GNUTLS_PK_DSA:
1832 if (dsa_verify_hashed_data(pk, hash_algo, hash, signature, issuer_params) != 0)
1834 gnutls_assert ();
1835 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1838 return 1;
1839 break;
1840 default:
1841 gnutls_assert ();
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)
1858 switch (pk)
1860 case GNUTLS_PK_RSA:
1862 if (_pkcs1_rsa_verify_sig
1863 (hash_algo, data, NULL, signature, issuer_params) != 0)
1865 gnutls_assert ();
1866 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1869 return 1;
1870 break;
1872 case GNUTLS_PK_EC:
1873 case GNUTLS_PK_DSA:
1874 if (dsa_verify_data(pk, hash_algo, data, signature, issuer_params) != 0)
1876 gnutls_assert ();
1877 return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1880 return 1;
1881 break;
1882 default:
1883 gnutls_assert ();
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)
1893 int bits = 0;
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;
1900 if (bits <= 160)
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;
1925 else
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
1935 * @fn: the callback
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
1943 * to have effect.
1945 * Since: 3.1.0
1948 void gnutls_pubkey_set_pin_function (gnutls_pubkey_t key,
1949 gnutls_pin_callback_t fn, void *userdata)
1951 key->pin.cb = fn;
1952 key->pin.data = userdata;