gnutls_pubkey_t: allow the import of another parameter set without a leak
[gnutls:gnutls.git] / lib / gnutls_pubkey.c
1 /*
2  * GnuTLS public key support
3  * Copyright (C) 2010-2012 Free Software Foundation, Inc.
4  * 
5  * Author: Nikos Mavrogiannopoulos
6  *
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 2.1 of
10  * the License, or (at your option) any later version.
11  *
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.
16  *
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/>
19  */
20
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 <fips.h>
38 #include "urls.h"
39 #include <gnutls_ecc.h>
40
41
42 #define OPENPGP_KEY_PRIMARY 2
43 #define OPENPGP_KEY_SUBKEY 1
44
45
46 int pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st * params)
47 {
48         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;
57         }
58 }
59
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)
64  *
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.
68  *
69  * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
70  *   success, or a negative error code on error.
71  *
72  * Since: 2.12.0
73  **/
74 int gnutls_pubkey_get_pk_algorithm(gnutls_pubkey_t key, unsigned int *bits)
75 {
76         if (bits)
77                 *bits = key->bits;
78
79         return key->pk_algorithm;
80 }
81
82 /**
83  * gnutls_pubkey_get_key_usage:
84  * @key: should contain a #gnutls_pubkey_t structure
85  * @usage: If set will return the number of bits of the parameters (may be NULL)
86  *
87  * This function will return the key usage of the public key.
88  *
89  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
90  *   negative error value.
91  *
92  * Since: 2.12.0
93  **/
94 int gnutls_pubkey_get_key_usage(gnutls_pubkey_t key, unsigned int *usage)
95 {
96         if (usage)
97                 *usage = key->key_usage;
98
99         return 0;
100 }
101
102 /**
103  * gnutls_pubkey_init:
104  * @key: The structure to be initialized
105  *
106  * This function will initialize an public key structure.
107  *
108  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
109  *   negative error value.
110  *
111  * Since: 2.12.0
112  **/
113 int gnutls_pubkey_init(gnutls_pubkey_t * key)
114 {
115         FAIL_IF_LIB_ERROR;
116
117         *key = gnutls_calloc(1, sizeof(struct gnutls_pubkey_st));
118         if (*key == NULL) {
119                 gnutls_assert();
120                 return GNUTLS_E_MEMORY_ERROR;
121         }
122
123         return 0;
124 }
125
126 /**
127  * gnutls_pubkey_deinit:
128  * @key: The structure to be deinitialized
129  *
130  * This function will deinitialize a public key structure.
131  *
132  * Since: 2.12.0
133  **/
134 void gnutls_pubkey_deinit(gnutls_pubkey_t key)
135 {
136         if (!key)
137                 return;
138         gnutls_pk_params_release(&key->params);
139         gnutls_free(key);
140 }
141
142 /**
143  * gnutls_pubkey_import_x509:
144  * @key: The public key
145  * @crt: The certificate to be imported
146  * @flags: should be zero
147  *
148  * This function will import the given public key to the abstract
149  * #gnutls_pubkey_t structure.
150  *
151  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
152  *   negative error value.
153  *
154  * Since: 2.12.0
155  **/
156 int
157 gnutls_pubkey_import_x509(gnutls_pubkey_t key, gnutls_x509_crt_t crt,
158                           unsigned int flags)
159 {
160         int ret;
161
162         gnutls_pk_params_release(&key->params);
163         /* params initialized in _gnutls_x509_crt_get_mpis */
164
165         key->pk_algorithm =
166             gnutls_x509_crt_get_pk_algorithm(crt, &key->bits);
167
168         ret = gnutls_x509_crt_get_key_usage(crt, &key->key_usage, NULL);
169         if (ret < 0)
170                 key->key_usage = 0;
171
172         ret = _gnutls_x509_crt_get_mpis(crt, &key->params);
173         if (ret < 0) {
174                 gnutls_assert();
175                 return ret;
176         }
177
178         return 0;
179 }
180
181 /**
182  * gnutls_pubkey_import_x509_crq:
183  * @key: The public key
184  * @crq: The certificate to be imported
185  * @flags: should be zero
186  *
187  * This function will import the given public key to the abstract
188  * #gnutls_pubkey_t structure.
189  *
190  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
191  *   negative error value.
192  *
193  * Since: 3.1.5
194  **/
195 int
196 gnutls_pubkey_import_x509_crq(gnutls_pubkey_t key, gnutls_x509_crq_t crq,
197                               unsigned int flags)
198 {
199         int ret;
200
201         gnutls_pk_params_release(&key->params);
202         /* params initialized in _gnutls_x509_crq_get_mpis */
203
204         key->pk_algorithm =
205             gnutls_x509_crq_get_pk_algorithm(crq, &key->bits);
206
207         ret = gnutls_x509_crq_get_key_usage(crq, &key->key_usage, NULL);
208         if (ret < 0)
209                 key->key_usage = 0;
210
211         ret = _gnutls_x509_crq_get_mpis(crq, &key->params);
212         if (ret < 0) {
213                 gnutls_assert();
214                 return ret;
215         }
216
217         return 0;
218 }
219
220 /**
221  * gnutls_pubkey_import_privkey:
222  * @key: The public key
223  * @pkey: The private key
224  * @usage: GNUTLS_KEY_* key usage flags.
225  * @flags: should be zero
226  *
227  * Imports the public key from a private.  This function will import
228  * the given public key to the abstract #gnutls_pubkey_t structure.
229  *
230  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
231  *   negative error value.
232  *
233  * Since: 2.12.0
234  **/
235 int
236 gnutls_pubkey_import_privkey(gnutls_pubkey_t key, gnutls_privkey_t pkey,
237                              unsigned int usage, unsigned int flags)
238 {
239         gnutls_pk_params_release(&key->params);
240         gnutls_pk_params_init(&key->params);
241
242         key->pk_algorithm =
243             gnutls_privkey_get_pk_algorithm(pkey, &key->bits);
244
245         key->key_usage = usage;
246
247         return _gnutls_privkey_get_public_mpis(pkey, &key->params);
248 }
249
250 /**
251  * gnutls_pubkey_get_preferred_hash_algorithm:
252  * @key: Holds the certificate
253  * @hash: The result of the call with the hash algorithm used for signature
254  * @mand: If non zero it means that the algorithm MUST use this hash. May be NULL.
255  *
256  * This function will read the certifcate and return the appropriate digest
257  * algorithm to use for signing with this certificate. Some certificates (i.e.
258  * DSA might not be able to sign without the preferred algorithm).
259  *
260  * To get the signature algorithm instead of just the hash use gnutls_pk_to_sign()
261  * with the algorithm of the certificate/key and the provided @hash.
262  *
263  * Returns: the 0 if the hash algorithm is found. A negative error code is
264  * returned on error.
265  *
266  * Since: 2.12.0
267  **/
268 int
269 gnutls_pubkey_get_preferred_hash_algorithm(gnutls_pubkey_t key,
270                                            gnutls_digest_algorithm_t *
271                                            hash, unsigned int *mand)
272 {
273         int ret;
274
275         if (key == NULL) {
276                 gnutls_assert();
277                 return GNUTLS_E_INVALID_REQUEST;
278         }
279
280         ret = _gnutls_pk_get_hash_algorithm(key->pk_algorithm,
281                                             &key->params, hash, mand);
282
283         return ret;
284 }
285
286 #ifdef ENABLE_PKCS11
287
288 /**
289  * gnutls_pubkey_import_pkcs11:
290  * @key: The public key
291  * @obj: The parameters to be imported
292  * @flags: should be zero
293  *
294  * Imports a public key from a pkcs11 key. This function will import
295  * the given public key to the abstract #gnutls_pubkey_t structure.
296  *
297  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
298  *   negative error value.
299  *
300  * Since: 2.12.0
301  **/
302 int
303 gnutls_pubkey_import_pkcs11(gnutls_pubkey_t key,
304                             gnutls_pkcs11_obj_t obj, unsigned int flags)
305 {
306         int ret, type;
307
308         type = gnutls_pkcs11_obj_get_type(obj);
309         if (type != GNUTLS_PKCS11_OBJ_PUBKEY
310             && type != GNUTLS_PKCS11_OBJ_X509_CRT) {
311                 gnutls_assert();
312                 return GNUTLS_E_INVALID_REQUEST;
313         }
314
315         if (type == GNUTLS_PKCS11_OBJ_X509_CRT) {
316                 gnutls_x509_crt_t xcrt;
317
318                 ret = gnutls_x509_crt_init(&xcrt);
319                 if (ret < 0) {
320                         gnutls_assert()
321                             return ret;
322                 }
323
324                 ret = gnutls_x509_crt_import_pkcs11(xcrt, obj);
325                 if (ret < 0) {
326                         gnutls_assert();
327                         goto cleanup_crt;
328                 }
329
330                 ret = gnutls_pubkey_import_x509(key, xcrt, 0);
331                 if (ret < 0) {
332                         gnutls_assert();
333                         goto cleanup_crt;
334                 }
335
336                 gnutls_x509_crt_get_key_usage(xcrt, &key->key_usage, NULL);
337
338                 ret = 0;
339               cleanup_crt:
340                 gnutls_x509_crt_deinit(xcrt);
341                 return ret;
342         }
343
344         key->key_usage = obj->key_usage;
345
346         switch (obj->pk_algorithm) {
347         case GNUTLS_PK_RSA:
348                 ret = gnutls_pubkey_import_rsa_raw(key, &obj->pubkey[0],
349                                                    &obj->pubkey[1]);
350                 break;
351         case GNUTLS_PK_DSA:
352                 ret = gnutls_pubkey_import_dsa_raw(key, &obj->pubkey[0],
353                                                    &obj->pubkey[1],
354                                                    &obj->pubkey[2],
355                                                    &obj->pubkey[3]);
356                 break;
357         case GNUTLS_PK_EC:
358                 ret = gnutls_pubkey_import_ecc_x962(key, &obj->pubkey[0],
359                                                     &obj->pubkey[1]);
360                 break;
361         default:
362                 gnutls_assert();
363                 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
364         }
365
366         if (ret < 0) {
367                 gnutls_assert();
368                 return ret;
369         }
370
371         return 0;
372 }
373
374 #endif                          /* ENABLE_PKCS11 */
375
376 #ifdef ENABLE_OPENPGP
377
378 /**
379  * gnutls_pubkey_import_openpgp:
380  * @key: The public key
381  * @crt: The certificate to be imported
382  * @flags: should be zero
383  *
384  * Imports a public key from an openpgp key. This function will import
385  * the given public key to the abstract #gnutls_pubkey_t
386  * structure. The subkey set as preferred will be imported or the
387  * master key otherwise.
388  *
389  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
390  *   negative error value.
391  *
392  * Since: 2.12.0
393  **/
394 int
395 gnutls_pubkey_import_openpgp(gnutls_pubkey_t key,
396                              gnutls_openpgp_crt_t crt, unsigned int flags)
397 {
398         int ret, idx;
399         uint32_t kid32[2];
400         uint32_t *k;
401         uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
402         size_t len;
403
404         len = sizeof(key->openpgp_key_fpr);
405         ret =
406             gnutls_openpgp_crt_get_fingerprint(crt, key->openpgp_key_fpr,
407                                                &len);
408         if (ret < 0)
409                 return gnutls_assert_val(ret);
410         key->openpgp_key_fpr_set = 1;
411
412         ret = gnutls_openpgp_crt_get_preferred_key_id(crt, keyid);
413         if (ret == GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR) {
414                 key->pk_algorithm =
415                     gnutls_openpgp_crt_get_pk_algorithm(crt, &key->bits);
416                 key->openpgp_key_id_set = OPENPGP_KEY_PRIMARY;
417
418                 ret =
419                     gnutls_openpgp_crt_get_key_id(crt,
420                                                   key->openpgp_key_id);
421                 if (ret < 0)
422                         return gnutls_assert_val(ret);
423
424                 ret =
425                     gnutls_openpgp_crt_get_key_usage(crt, &key->key_usage);
426                 if (ret < 0)
427                         key->key_usage = 0;
428
429                 k = NULL;
430         } else {
431                 if (ret < 0) {
432                         gnutls_assert();
433                         return ret;
434                 }
435                 key->openpgp_key_id_set = OPENPGP_KEY_SUBKEY;
436
437                 KEYID_IMPORT(kid32, keyid);
438                 k = kid32;
439
440                 idx = gnutls_openpgp_crt_get_subkey_idx(crt, keyid);
441
442                 ret =
443                     gnutls_openpgp_crt_get_subkey_id(crt, idx,
444                                                      key->openpgp_key_id);
445                 if (ret < 0)
446                         return gnutls_assert_val(ret);
447
448                 ret =
449                     gnutls_openpgp_crt_get_subkey_usage(crt, idx,
450                                                         &key->key_usage);
451                 if (ret < 0)
452                         key->key_usage = 0;
453
454                 key->pk_algorithm =
455                     gnutls_openpgp_crt_get_subkey_pk_algorithm(crt, idx,
456                                                                NULL);
457         }
458
459         ret = _gnutls_openpgp_crt_get_mpis(crt, k, &key->params);
460         if (ret < 0)
461                 return gnutls_assert_val(ret);
462
463         return 0;
464 }
465
466 /**
467  * gnutls_pubkey_get_openpgp_key_id:
468  * @key: Holds the public key
469  * @flags: should be 0 or %GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT
470  * @output_data: will contain the key ID
471  * @output_data_size: holds the size of output_data (and will be
472  *   replaced by the actual size of parameters)
473  * @subkey: Will be non zero if the key ID corresponds to a subkey
474  *
475  * This function returns the OpenPGP key ID of the corresponding key.
476  * The key is a unique ID that depends on the public
477  * key parameters. 
478  *
479  * If the flag %GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT is specified
480  * this function returns the fingerprint of the master key.
481  *
482  * If the buffer provided is not long enough to hold the output, then
483  * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
484  * be returned.  The output is %GNUTLS_OPENPGP_KEYID_SIZE bytes long.
485  *
486  * Returns: In case of failure a negative error code will be
487  *   returned, and 0 on success.
488  *
489  * Since: 3.0
490  **/
491 int
492 gnutls_pubkey_get_openpgp_key_id(gnutls_pubkey_t key, unsigned int flags,
493                                  unsigned char *output_data,
494                                  size_t * output_data_size,
495                                  unsigned int *subkey)
496 {
497         if (key == NULL) {
498                 gnutls_assert();
499                 return GNUTLS_E_INVALID_REQUEST;
500         }
501
502         if (flags & GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT) {
503                 if (*output_data_size < sizeof(key->openpgp_key_fpr)) {
504                         *output_data_size = sizeof(key->openpgp_key_fpr);
505                         return
506                             gnutls_assert_val
507                             (GNUTLS_E_SHORT_MEMORY_BUFFER);
508                 }
509
510                 if (key->openpgp_key_fpr_set == 0)
511                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
512
513                 if (output_data)
514                         memcpy(output_data, key->openpgp_key_fpr,
515                                sizeof(key->openpgp_key_fpr));
516                 *output_data_size = sizeof(key->openpgp_key_fpr);
517
518                 return 0;
519         }
520
521         if (*output_data_size < sizeof(key->openpgp_key_id)) {
522                 *output_data_size = sizeof(key->openpgp_key_id);
523                 return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
524         }
525
526         if (key->openpgp_key_id_set == 0)
527                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
528
529         if (subkey) {
530                 if (key->openpgp_key_id_set == OPENPGP_KEY_SUBKEY)
531                         *subkey = 1;
532                 else
533                         *subkey = 0;
534         }
535
536         if (output_data) {
537                 memcpy(output_data, key->openpgp_key_id,
538                        sizeof(key->openpgp_key_id));
539         }
540         *output_data_size = sizeof(key->openpgp_key_id);
541
542         return 0;
543 }
544
545 /**
546  * gnutls_pubkey_import_openpgp_raw:
547  * @pkey: The public key
548  * @data: The public key data to be imported
549  * @format: The format of the public key
550  * @keyid: The key id to use (optional)
551  * @flags: Should be zero
552  *
553  * This function will import the given public key to the abstract
554  * #gnutls_pubkey_t structure. 
555  *
556  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
557  *   negative error value.
558  *
559  * Since: 3.1.3
560  **/
561 int gnutls_pubkey_import_openpgp_raw(gnutls_pubkey_t pkey,
562                                      const gnutls_datum_t * data,
563                                      gnutls_openpgp_crt_fmt_t format,
564                                      const gnutls_openpgp_keyid_t keyid,
565                                      unsigned int flags)
566 {
567         gnutls_openpgp_crt_t xpriv;
568         int ret;
569
570         ret = gnutls_openpgp_crt_init(&xpriv);
571         if (ret < 0)
572                 return gnutls_assert_val(ret);
573
574         ret = gnutls_openpgp_crt_import(xpriv, data, format);
575         if (ret < 0) {
576                 gnutls_assert();
577                 goto cleanup;
578         }
579
580         if (keyid) {
581                 ret =
582                     gnutls_openpgp_crt_set_preferred_key_id(xpriv, keyid);
583                 if (ret < 0) {
584                         gnutls_assert();
585                         goto cleanup;
586                 }
587         }
588
589         ret = gnutls_pubkey_import_openpgp(pkey, xpriv, flags);
590         if (ret < 0) {
591                 gnutls_assert();
592                 goto cleanup;
593         }
594
595         ret = 0;
596
597       cleanup:
598         gnutls_openpgp_crt_deinit(xpriv);
599
600         return ret;
601 }
602
603 #endif
604
605 /**
606  * gnutls_pubkey_export:
607  * @key: Holds the certificate
608  * @format: the format of output params. One of PEM or DER.
609  * @output_data: will contain a certificate PEM or DER encoded
610  * @output_data_size: holds the size of output_data (and will be
611  *   replaced by the actual size of parameters)
612  *
613  * This function will export the public key to DER or PEM format.
614  * The contents of the exported data is the SubjectPublicKeyInfo
615  * X.509 structure.
616  *
617  * If the buffer provided is not long enough to hold the output, then
618  * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
619  * be returned.
620  *
621  * If the structure is PEM encoded, it will have a header
622  * of "BEGIN CERTIFICATE".
623  *
624  * Returns: In case of failure a negative error code will be
625  *   returned, and 0 on success.
626  *
627  * Since: 2.12.0
628  **/
629 int
630 gnutls_pubkey_export(gnutls_pubkey_t key,
631                      gnutls_x509_crt_fmt_t format, void *output_data,
632                      size_t * output_data_size)
633 {
634         int result;
635         ASN1_TYPE spk = ASN1_TYPE_EMPTY;
636
637         if (key == NULL) {
638                 gnutls_assert();
639                 return GNUTLS_E_INVALID_REQUEST;
640         }
641
642         if ((result = asn1_create_element
643              (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
644             != ASN1_SUCCESS) {
645                 gnutls_assert();
646                 return _gnutls_asn2err(result);
647         }
648
649         result =
650             _gnutls_x509_encode_and_copy_PKI_params(spk, "",
651                                                     key->pk_algorithm,
652                                                     &key->params);
653         if (result < 0) {
654                 gnutls_assert();
655                 goto cleanup;
656         }
657
658         result = _gnutls_x509_export_int_named(spk, "",
659                                                format, PEM_PK,
660                                                output_data,
661                                                output_data_size);
662         if (result < 0) {
663                 gnutls_assert();
664                 goto cleanup;
665         }
666
667         result = 0;
668
669       cleanup:
670         asn1_delete_structure(&spk);
671
672         return result;
673 }
674
675 /**
676  * gnutls_pubkey_export2:
677  * @key: Holds the certificate
678  * @format: the format of output params. One of PEM or DER.
679  * @out: will contain a certificate PEM or DER encoded
680  *
681  * This function will export the public key to DER or PEM format.
682  * The contents of the exported data is the SubjectPublicKeyInfo
683  * X.509 structure.
684  *
685  * The output buffer will be allocated using gnutls_malloc().
686  *
687  * If the structure is PEM encoded, it will have a header
688  * of "BEGIN CERTIFICATE".
689  *
690  * Returns: In case of failure a negative error code will be
691  *   returned, and 0 on success.
692  *
693  * Since: 3.1.3
694  **/
695 int
696 gnutls_pubkey_export2(gnutls_pubkey_t key,
697                       gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
698 {
699         int result;
700         ASN1_TYPE spk = ASN1_TYPE_EMPTY;
701
702         if (key == NULL) {
703                 gnutls_assert();
704                 return GNUTLS_E_INVALID_REQUEST;
705         }
706
707         if ((result = asn1_create_element
708              (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
709             != ASN1_SUCCESS) {
710                 gnutls_assert();
711                 return _gnutls_asn2err(result);
712         }
713
714         result =
715             _gnutls_x509_encode_and_copy_PKI_params(spk, "",
716                                                     key->pk_algorithm,
717                                                     &key->params);
718         if (result < 0) {
719                 gnutls_assert();
720                 goto cleanup;
721         }
722
723         result = _gnutls_x509_export_int_named2(spk, "",
724                                                 format, PEM_PK,
725                                                 out);
726         if (result < 0) {
727                 gnutls_assert();
728                 goto cleanup;
729         }
730
731         result = 0;
732
733       cleanup:
734         asn1_delete_structure(&spk);
735
736         return result;
737 }
738
739 /**
740  * gnutls_pubkey_get_key_id:
741  * @key: Holds the public key
742  * @flags: should be 0 for now
743  * @output_data: will contain the key ID
744  * @output_data_size: holds the size of output_data (and will be
745  *   replaced by the actual size of parameters)
746  *
747  * This function will return a unique ID that depends on the public
748  * key parameters. This ID can be used in checking whether a
749  * certificate corresponds to the given public key.
750  *
751  * If the buffer provided is not long enough to hold the output, then
752  * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
753  * be returned.  The output will normally be a SHA-1 hash output,
754  * which is 20 bytes.
755  *
756  * Returns: In case of failure a negative error code will be
757  *   returned, and 0 on success.
758  *
759  * Since: 2.12.0
760  **/
761 int
762 gnutls_pubkey_get_key_id(gnutls_pubkey_t key, unsigned int flags,
763                          unsigned char *output_data,
764                          size_t * output_data_size)
765 {
766         int ret = 0;
767
768         if (key == NULL) {
769                 gnutls_assert();
770                 return GNUTLS_E_INVALID_REQUEST;
771         }
772
773         ret =
774             _gnutls_get_key_id(key->pk_algorithm, &key->params,
775                                output_data, output_data_size);
776         if (ret < 0) {
777                 gnutls_assert();
778                 return ret;
779         }
780
781         return 0;
782 }
783
784 /**
785  * gnutls_pubkey_export_rsa_raw:
786  * @key: Holds the certificate
787  * @m: will hold the modulus
788  * @e: will hold the public exponent
789  *
790  * This function will export the RSA public key's parameters found in
791  * the given structure.  The new parameters will be allocated using
792  * gnutls_malloc() and will be stored in the appropriate datum.
793  *
794  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
795  *
796  * Since: 3.3.0
797  **/
798 int
799 gnutls_pubkey_export_rsa_raw(gnutls_pubkey_t key,
800                              gnutls_datum_t * m, gnutls_datum_t * e)
801 {
802         int ret;
803
804         if (key == NULL) {
805                 gnutls_assert();
806                 return GNUTLS_E_INVALID_REQUEST;
807         }
808
809         if (key->pk_algorithm != GNUTLS_PK_RSA) {
810                 gnutls_assert();
811                 return GNUTLS_E_INVALID_REQUEST;
812         }
813
814         ret = _gnutls_mpi_dprint_lz(key->params.params[0], m);
815         if (ret < 0) {
816                 gnutls_assert();
817                 return ret;
818         }
819
820         ret = _gnutls_mpi_dprint_lz(key->params.params[1], e);
821         if (ret < 0) {
822                 gnutls_assert();
823                 _gnutls_free_datum(m);
824                 return ret;
825         }
826
827         return 0;
828 }
829
830
831 /**
832  * gnutls_pubkey_export_dsa_raw:
833  * @key: Holds the public key
834  * @p: will hold the p
835  * @q: will hold the q
836  * @g: will hold the g
837  * @y: will hold the y
838  *
839  * This function will export the DSA public key's parameters found in
840  * the given certificate.  The new parameters will be allocated using
841  * gnutls_malloc() and will be stored in the appropriate datum.
842  *
843  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
844  *
845  * Since: 3.3.0
846  **/
847 int
848 gnutls_pubkey_export_dsa_raw(gnutls_pubkey_t key,
849                              gnutls_datum_t * p, gnutls_datum_t * q,
850                              gnutls_datum_t * g, gnutls_datum_t * y)
851 {
852         int ret;
853
854         if (key == NULL) {
855                 gnutls_assert();
856                 return GNUTLS_E_INVALID_REQUEST;
857         }
858
859         if (key->pk_algorithm != GNUTLS_PK_DSA) {
860                 gnutls_assert();
861                 return GNUTLS_E_INVALID_REQUEST;
862         }
863
864         /* P */
865         ret = _gnutls_mpi_dprint_lz(key->params.params[0], p);
866         if (ret < 0) {
867                 gnutls_assert();
868                 return ret;
869         }
870
871         /* Q */
872         ret = _gnutls_mpi_dprint_lz(key->params.params[1], q);
873         if (ret < 0) {
874                 gnutls_assert();
875                 _gnutls_free_datum(p);
876                 return ret;
877         }
878
879
880         /* G */
881         ret = _gnutls_mpi_dprint_lz(key->params.params[2], g);
882         if (ret < 0) {
883                 gnutls_assert();
884                 _gnutls_free_datum(p);
885                 _gnutls_free_datum(q);
886                 return ret;
887         }
888
889
890         /* Y */
891         ret = _gnutls_mpi_dprint_lz(key->params.params[3], y);
892         if (ret < 0) {
893                 gnutls_assert();
894                 _gnutls_free_datum(p);
895                 _gnutls_free_datum(g);
896                 _gnutls_free_datum(q);
897                 return ret;
898         }
899
900         return 0;
901 }
902
903 /**
904  * gnutls_pubkey_export_ecc_raw:
905  * @key: Holds the public key
906  * @curve: will hold the curve
907  * @x: will hold x
908  * @y: will hold y
909  *
910  * This function will export the ECC public key's parameters found in
911  * the given certificate.  The new parameters will be allocated using
912  * gnutls_malloc() and will be stored in the appropriate datum.
913  *
914  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
915  *
916  * Since: 3.0
917  **/
918 int
919 gnutls_pubkey_export_ecc_raw(gnutls_pubkey_t key,
920                              gnutls_ecc_curve_t * curve,
921                              gnutls_datum_t * x, gnutls_datum_t * y)
922 {
923         int ret;
924
925         if (key == NULL) {
926                 gnutls_assert();
927                 return GNUTLS_E_INVALID_REQUEST;
928         }
929
930         if (key->pk_algorithm != GNUTLS_PK_EC) {
931                 gnutls_assert();
932                 return GNUTLS_E_INVALID_REQUEST;
933         }
934
935         *curve = key->params.flags;
936
937         /* X */
938         ret = _gnutls_mpi_dprint_lz(key->params.params[ECC_X], x);
939         if (ret < 0) {
940                 gnutls_assert();
941                 return ret;
942         }
943
944         /* Y */
945         ret = _gnutls_mpi_dprint_lz(key->params.params[ECC_Y], y);
946         if (ret < 0) {
947                 gnutls_assert();
948                 _gnutls_free_datum(x);
949                 return ret;
950         }
951
952         return 0;
953 }
954
955 /**
956  * gnutls_pubkey_export_ecc_x962:
957  * @key: Holds the public key
958  * @parameters: DER encoding of an ANSI X9.62 parameters
959  * @ecpoint: DER encoding of ANSI X9.62 ECPoint
960  *
961  * This function will export the ECC public key's parameters found in
962  * the given certificate.  The new parameters will be allocated using
963  * gnutls_malloc() and will be stored in the appropriate datum.
964  *
965  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
966  *
967  * Since: 3.3.0
968  **/
969 int gnutls_pubkey_export_ecc_x962(gnutls_pubkey_t key,
970                                   gnutls_datum_t * parameters,
971                                   gnutls_datum_t * ecpoint)
972 {
973         int ret;
974         gnutls_datum_t raw_point = {NULL,0};
975
976         if (key == NULL || key->pk_algorithm != GNUTLS_PK_EC)
977                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
978
979         ret = _gnutls_x509_write_ecc_pubkey(&key->params, &raw_point);
980         if (ret < 0)
981                 return gnutls_assert_val(ret);
982
983         ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
984                                          raw_point.data, raw_point.size, ecpoint);
985         if (ret < 0) {
986                 gnutls_assert();
987                 goto cleanup;
988         }
989
990         ret = _gnutls_x509_write_ecc_params(key->params.flags, parameters);
991         if (ret < 0) {
992                 _gnutls_free_datum(ecpoint);
993                 gnutls_assert();
994                 goto cleanup;
995         }
996
997         ret = 0;
998  cleanup:
999         gnutls_free(raw_point.data);
1000         return ret;
1001 }
1002
1003 /**
1004  * gnutls_pubkey_import:
1005  * @key: The structure to store the parsed public key. 
1006  * @data: The DER or PEM encoded certificate. 
1007  * @format: One of DER or PEM 
1008  * 
1009  * This function will import the provided public key in
1010  * a SubjectPublicKeyInfo X.509 structure to a native
1011  * %gnutls_pubkey_t structure. The output will be stored 
1012  * in @key. If the public key is PEM encoded it should have a header 
1013  * of "PUBLIC KEY". 
1014  * 
1015  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1016  * negative error value.
1017  *
1018  * Since: 2.12.0
1019  **/
1020 int
1021 gnutls_pubkey_import(gnutls_pubkey_t key,
1022                      const gnutls_datum_t * data,
1023                      gnutls_x509_crt_fmt_t format)
1024 {
1025         int result = 0, need_free = 0;
1026         gnutls_datum_t _data;
1027         ASN1_TYPE spk;
1028
1029         if (key == NULL) {
1030                 gnutls_assert();
1031                 return GNUTLS_E_INVALID_REQUEST;
1032         }
1033
1034         _data.data = data->data;
1035         _data.size = data->size;
1036
1037         /* If the Certificate is in PEM format then decode it
1038          */
1039         if (format == GNUTLS_X509_FMT_PEM) {
1040                 /* Try the first header */
1041                 result =
1042                     _gnutls_fbase64_decode(PEM_PK, data->data,
1043                                            data->size, &_data);
1044
1045                 if (result < 0) {
1046                         gnutls_assert();
1047                         return result;
1048                 }
1049
1050                 need_free = 1;
1051         }
1052
1053         if ((result = asn1_create_element
1054              (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk))
1055             != ASN1_SUCCESS) {
1056                 gnutls_assert();
1057                 result = _gnutls_asn2err(result);
1058                 goto cleanup;
1059         }
1060
1061         result = asn1_der_decoding(&spk, _data.data, _data.size, NULL);
1062         if (result != ASN1_SUCCESS) {
1063                 gnutls_assert();
1064                 result = _gnutls_asn2err(result);
1065                 goto cleanup;
1066         }
1067
1068         result = _gnutls_get_asn_mpis(spk, "", &key->params);
1069         if (result < 0) {
1070                 gnutls_assert();
1071                 goto cleanup;
1072         }
1073
1074         /* this has already been called by get_asn_mpis() thus it cannot
1075          * fail.
1076          */
1077         key->pk_algorithm = _gnutls_x509_get_pk_algorithm(spk, "", NULL);
1078         key->bits = pubkey_to_bits(key->pk_algorithm, &key->params);
1079
1080         result = 0;
1081
1082       cleanup:
1083         asn1_delete_structure(&spk);
1084
1085         if (need_free)
1086                 _gnutls_free_datum(&_data);
1087         return result;
1088 }
1089
1090 /**
1091  * gnutls_x509_crt_set_pubkey:
1092  * @crt: should contain a #gnutls_x509_crt_t structure
1093  * @key: holds a public key
1094  *
1095  * This function will set the public parameters from the given public
1096  * key to the request.
1097  *
1098  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1099  *   negative error value.
1100  *
1101  * Since: 2.12.0
1102  **/
1103 int gnutls_x509_crt_set_pubkey(gnutls_x509_crt_t crt, gnutls_pubkey_t key)
1104 {
1105         int result;
1106
1107         if (crt == NULL) {
1108                 gnutls_assert();
1109                 return GNUTLS_E_INVALID_REQUEST;
1110         }
1111
1112         result = _gnutls_x509_encode_and_copy_PKI_params(crt->cert,
1113                                                          "tbsCertificate.subjectPublicKeyInfo",
1114                                                          key->pk_algorithm,
1115                                                          &key->params);
1116
1117         if (result < 0) {
1118                 gnutls_assert();
1119                 return result;
1120         }
1121
1122         if (key->key_usage)
1123                 gnutls_x509_crt_set_key_usage(crt, key->key_usage);
1124
1125         return 0;
1126 }
1127
1128 /**
1129  * gnutls_x509_crq_set_pubkey:
1130  * @crq: should contain a #gnutls_x509_crq_t structure
1131  * @key: holds a public key
1132  *
1133  * This function will set the public parameters from the given public
1134  * key to the request.
1135  *
1136  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1137  *   negative error value.
1138  *
1139  * Since: 2.12.0
1140  **/
1141 int gnutls_x509_crq_set_pubkey(gnutls_x509_crq_t crq, gnutls_pubkey_t key)
1142 {
1143         int result;
1144
1145         if (crq == NULL) {
1146                 gnutls_assert();
1147                 return GNUTLS_E_INVALID_REQUEST;
1148         }
1149
1150         result = _gnutls_x509_encode_and_copy_PKI_params
1151             (crq->crq,
1152              "certificationRequestInfo.subjectPKInfo",
1153              key->pk_algorithm, &key->params);
1154
1155         if (result < 0) {
1156                 gnutls_assert();
1157                 return result;
1158         }
1159
1160         if (key->key_usage)
1161                 gnutls_x509_crq_set_key_usage(crq, key->key_usage);
1162
1163         return 0;
1164 }
1165
1166 /**
1167  * gnutls_pubkey_set_key_usage:
1168  * @key: a certificate of type #gnutls_x509_crt_t
1169  * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
1170  *
1171  * This function will set the key usage flags of the public key. This
1172  * is only useful if the key is to be exported to a certificate or
1173  * certificate request.
1174  *
1175  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1176  *   negative error value.
1177  *
1178  * Since: 2.12.0
1179  **/
1180 int gnutls_pubkey_set_key_usage(gnutls_pubkey_t key, unsigned int usage)
1181 {
1182         key->key_usage = usage;
1183
1184         return 0;
1185 }
1186
1187 #ifdef ENABLE_PKCS11
1188
1189 /**
1190  * gnutls_pubkey_import_pkcs11_url:
1191  * @key: A key of type #gnutls_pubkey_t
1192  * @url: A PKCS 11 url
1193  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1194  *
1195  * This function will import a PKCS 11 certificate to a #gnutls_pubkey_t
1196  * structure.
1197  *
1198  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1199  *   negative error value.
1200  *
1201  * Since: 2.12.0
1202  **/
1203 int
1204 gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key, const char *url,
1205                                 unsigned int flags)
1206 {
1207         gnutls_pkcs11_obj_t pcrt;
1208         int ret;
1209
1210         ret = gnutls_pkcs11_obj_init(&pcrt);
1211         if (ret < 0) {
1212                 gnutls_assert();
1213                 return ret;
1214         }
1215
1216         if (key->pin.cb)
1217                 gnutls_pkcs11_obj_set_pin_function(pcrt, key->pin.cb,
1218                                                    key->pin.data);
1219
1220         ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags);
1221         if (ret < 0) {
1222                 gnutls_assert();
1223                 goto cleanup;
1224         }
1225
1226         ret = gnutls_pubkey_import_pkcs11(key, pcrt, 0);
1227         if (ret < 0) {
1228                 gnutls_assert();
1229                 goto cleanup;
1230         }
1231
1232         ret = 0;
1233       cleanup:
1234
1235         gnutls_pkcs11_obj_deinit(pcrt);
1236
1237         return ret;
1238 }
1239
1240 #endif                          /* ENABLE_PKCS11 */
1241
1242 /**
1243  * gnutls_pubkey_import_url:
1244  * @key: A key of type #gnutls_pubkey_t
1245  * @url: A PKCS 11 url
1246  * @flags: One of GNUTLS_PKCS11_OBJ_* flags
1247  *
1248  * This function will import a public key from the provided URL.
1249  *
1250  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1251  *   negative error value.
1252  *
1253  * Since: 3.1.0
1254  **/
1255 int
1256 gnutls_pubkey_import_url(gnutls_pubkey_t key, const char *url,
1257                          unsigned int flags)
1258 {
1259         unsigned i;
1260
1261         if (strncmp(url, PKCS11_URL, PKCS11_URL_SIZE) == 0)
1262 #ifdef ENABLE_PKCS11
1263                 return gnutls_pubkey_import_pkcs11_url(key, url, flags);
1264 #else
1265                 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1266 #endif
1267
1268         if (strncmp(url, TPMKEY_URL, TPMKEY_URL_SIZE) == 0)
1269 #ifdef HAVE_TROUSERS
1270                 return gnutls_pubkey_import_tpm_url(key, url, NULL, 0);
1271 #else
1272                 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1273 #endif
1274
1275         for (i=0;i<_gnutls_custom_urls_size;i++) {
1276                 if (strncmp(url, _gnutls_custom_urls[i].name, _gnutls_custom_urls[i].name_size) == 0) {
1277                         if (_gnutls_custom_urls[i].import_pubkey)
1278                                 return _gnutls_custom_urls[i].import_pubkey(key, url, flags);
1279                 }
1280         }
1281
1282         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1283 }
1284
1285 /**
1286  * gnutls_pubkey_import_rsa_raw:
1287  * @key: Is a structure will hold the parameters
1288  * @m: holds the modulus
1289  * @e: holds the public exponent
1290  *
1291  * This function will replace the parameters in the given structure.
1292  * The new parameters should be stored in the appropriate
1293  * gnutls_datum.
1294  *
1295  * Returns: %GNUTLS_E_SUCCESS on success, or an negative error code.
1296  *
1297  * Since: 2.12.0
1298  **/
1299 int
1300 gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key,
1301                              const gnutls_datum_t * m,
1302                              const gnutls_datum_t * e)
1303 {
1304         size_t siz = 0;
1305
1306         if (key == NULL) {
1307                 gnutls_assert();
1308                 return GNUTLS_E_INVALID_REQUEST;
1309         }
1310
1311         gnutls_pk_params_release(&key->params);
1312         gnutls_pk_params_init(&key->params);
1313
1314         siz = m->size;
1315         if (_gnutls_mpi_init_scan_nz(&key->params.params[0], m->data, siz)) {
1316                 gnutls_assert();
1317                 return GNUTLS_E_MPI_SCAN_FAILED;
1318         }
1319
1320         siz = e->size;
1321         if (_gnutls_mpi_init_scan_nz(&key->params.params[1], e->data, siz)) {
1322                 gnutls_assert();
1323                 _gnutls_mpi_release(&key->params.params[0]);
1324                 return GNUTLS_E_MPI_SCAN_FAILED;
1325         }
1326
1327         key->params.params_nr = RSA_PUBLIC_PARAMS;
1328         key->pk_algorithm = GNUTLS_PK_RSA;
1329         key->bits = pubkey_to_bits(GNUTLS_PK_RSA, &key->params);
1330
1331         return 0;
1332 }
1333
1334 /**
1335  * gnutls_pubkey_import_ecc_raw:
1336  * @key: The structure to store the parsed key
1337  * @curve: holds the curve
1338  * @x: holds the x
1339  * @y: holds the y
1340  *
1341  * This function will convert the given elliptic curve parameters to a
1342  * #gnutls_pubkey_t.  The output will be stored in @key.
1343  *
1344  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1345  *   negative error value.
1346  *
1347  * Since: 3.0
1348  **/
1349 int
1350 gnutls_pubkey_import_ecc_raw(gnutls_pubkey_t key,
1351                              gnutls_ecc_curve_t curve,
1352                              const gnutls_datum_t * x,
1353                              const gnutls_datum_t * y)
1354 {
1355         int ret;
1356
1357         if (key == NULL) {
1358                 gnutls_assert();
1359                 return GNUTLS_E_INVALID_REQUEST;
1360         }
1361
1362         gnutls_pk_params_release(&key->params);
1363         gnutls_pk_params_init(&key->params);
1364
1365         key->params.flags = curve;
1366
1367         if (_gnutls_mpi_init_scan_nz
1368             (&key->params.params[ECC_X], x->data, x->size)) {
1369                 gnutls_assert();
1370                 ret = GNUTLS_E_MPI_SCAN_FAILED;
1371                 goto cleanup;
1372         }
1373         key->params.params_nr++;
1374
1375         if (_gnutls_mpi_init_scan_nz
1376             (&key->params.params[ECC_Y], y->data, y->size)) {
1377                 gnutls_assert();
1378                 ret = GNUTLS_E_MPI_SCAN_FAILED;
1379                 goto cleanup;
1380         }
1381         key->params.params_nr++;
1382         key->pk_algorithm = GNUTLS_PK_EC;
1383
1384         return 0;
1385
1386       cleanup:
1387         gnutls_pk_params_release(&key->params);
1388         return ret;
1389 }
1390
1391 /**
1392  * gnutls_pubkey_import_ecc_x962:
1393  * @key: The structure to store the parsed key
1394  * @parameters: DER encoding of an ANSI X9.62 parameters
1395  * @ecpoint: DER encoding of ANSI X9.62 ECPoint
1396  *
1397  * This function will convert the given elliptic curve parameters to a
1398  * #gnutls_pubkey_t.  The output will be stored in @key.
1399  *
1400  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1401  *   negative error value.
1402  *
1403  * Since: 3.0
1404  **/
1405 int
1406 gnutls_pubkey_import_ecc_x962(gnutls_pubkey_t key,
1407                               const gnutls_datum_t * parameters,
1408                               const gnutls_datum_t * ecpoint)
1409 {
1410         int ret;
1411         gnutls_datum_t raw_point = {NULL,0};
1412
1413         if (key == NULL) {
1414                 gnutls_assert();
1415                 return GNUTLS_E_INVALID_REQUEST;
1416         }
1417
1418         gnutls_pk_params_release(&key->params);
1419         gnutls_pk_params_init(&key->params);
1420
1421         key->params.params_nr = 0;
1422
1423         ret =
1424             _gnutls_x509_read_ecc_params(parameters->data,
1425                                          parameters->size, &key->params.flags);
1426         if (ret < 0) {
1427                 gnutls_assert();
1428                 goto cleanup;
1429         }
1430
1431         ret = _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
1432                                          ecpoint->data, ecpoint->size, &raw_point);
1433         if (ret < 0) {
1434                 gnutls_assert();
1435                 goto cleanup;
1436         }
1437
1438         ret = _gnutls_ecc_ansi_x963_import(raw_point.data, raw_point.size,
1439                                            &key->params.params[ECC_X],
1440                                            &key->params.params[ECC_Y]);
1441         if (ret < 0) {
1442                 gnutls_assert();
1443                 goto cleanup;
1444         }
1445         key->params.params_nr += 2;
1446         key->pk_algorithm = GNUTLS_PK_EC;
1447
1448         gnutls_free(raw_point.data);
1449         return 0;
1450
1451       cleanup:
1452         gnutls_pk_params_release(&key->params);
1453         gnutls_free(raw_point.data);
1454         return ret;
1455 }
1456
1457 /**
1458  * gnutls_pubkey_import_dsa_raw:
1459  * @key: The structure to store the parsed key
1460  * @p: holds the p
1461  * @q: holds the q
1462  * @g: holds the g
1463  * @y: holds the y
1464  *
1465  * This function will convert the given DSA raw parameters to the
1466  * native #gnutls_pubkey_t format.  The output will be stored
1467  * in @key.
1468  *
1469  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1470  *   negative error value.
1471  *
1472  * Since: 2.12.0
1473  **/
1474 int
1475 gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key,
1476                              const gnutls_datum_t * p,
1477                              const gnutls_datum_t * q,
1478                              const gnutls_datum_t * g,
1479                              const gnutls_datum_t * y)
1480 {
1481         size_t siz = 0;
1482
1483         if (key == NULL) {
1484                 gnutls_assert();
1485                 return GNUTLS_E_INVALID_REQUEST;
1486         }
1487
1488         gnutls_pk_params_release(&key->params);
1489         gnutls_pk_params_init(&key->params);
1490
1491         siz = p->size;
1492         if (_gnutls_mpi_init_scan_nz(&key->params.params[0], p->data, siz)) {
1493                 gnutls_assert();
1494                 return GNUTLS_E_MPI_SCAN_FAILED;
1495         }
1496
1497         siz = q->size;
1498         if (_gnutls_mpi_init_scan_nz(&key->params.params[1], q->data, siz)) {
1499                 gnutls_assert();
1500                 _gnutls_mpi_release(&key->params.params[0]);
1501                 return GNUTLS_E_MPI_SCAN_FAILED;
1502         }
1503
1504         siz = g->size;
1505         if (_gnutls_mpi_init_scan_nz(&key->params.params[2], g->data, siz)) {
1506                 gnutls_assert();
1507                 _gnutls_mpi_release(&key->params.params[1]);
1508                 _gnutls_mpi_release(&key->params.params[0]);
1509                 return GNUTLS_E_MPI_SCAN_FAILED;
1510         }
1511
1512         siz = y->size;
1513         if (_gnutls_mpi_init_scan_nz(&key->params.params[3], y->data, siz)) {
1514                 gnutls_assert();
1515                 _gnutls_mpi_release(&key->params.params[2]);
1516                 _gnutls_mpi_release(&key->params.params[1]);
1517                 _gnutls_mpi_release(&key->params.params[0]);
1518                 return GNUTLS_E_MPI_SCAN_FAILED;
1519         }
1520
1521         key->params.params_nr = DSA_PUBLIC_PARAMS;
1522         key->pk_algorithm = GNUTLS_PK_DSA;
1523         key->bits = pubkey_to_bits(GNUTLS_PK_DSA, &key->params);
1524
1525         return 0;
1526
1527 }
1528
1529 /**
1530  * gnutls_pubkey_verify_data:
1531  * @pubkey: Holds the public key
1532  * @flags: Zero or one of %gnutls_pubkey_flags_t
1533  * @data: holds the signed data
1534  * @signature: contains the signature
1535  *
1536  * This function will verify the given signed data, using the
1537  * parameters from the certificate.
1538  *
1539  * Deprecated. This function cannot be easily used securely. 
1540  * Use gnutls_pubkey_verify_data2() instead.
1541  *
1542  * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED 
1543  * is returned, and zero or positive code on success. 
1544  *
1545  * Since: 2.12.0
1546  **/
1547 int
1548 gnutls_pubkey_verify_data(gnutls_pubkey_t pubkey, unsigned int flags,
1549                           const gnutls_datum_t * data,
1550                           const gnutls_datum_t * signature)
1551 {
1552         int ret;
1553         gnutls_digest_algorithm_t hash;
1554
1555         if (pubkey == NULL) {
1556                 gnutls_assert();
1557                 return GNUTLS_E_INVALID_REQUEST;
1558         }
1559
1560         if (flags & GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA)
1561                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1562
1563         ret = gnutls_pubkey_get_verify_algorithm(pubkey, signature, &hash);
1564         if (ret < 0)
1565                 return gnutls_assert_val(ret);
1566
1567         ret = pubkey_verify_data(pubkey->pk_algorithm, hash_to_entry(hash),
1568                                  data, signature, &pubkey->params);
1569         if (ret < 0) {
1570                 gnutls_assert();
1571         }
1572
1573         return ret;
1574 }
1575
1576 /**
1577  * gnutls_pubkey_verify_data2:
1578  * @pubkey: Holds the public key
1579  * @algo: The signature algorithm used
1580  * @flags: Zero or one of %gnutls_pubkey_flags_t
1581  * @data: holds the signed data
1582  * @signature: contains the signature
1583  *
1584  * This function will verify the given signed data, using the
1585  * parameters from the certificate.
1586  *
1587  * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED 
1588  * is returned, and zero or positive code on success.
1589  *
1590  * Since: 3.0
1591  **/
1592 int
1593 gnutls_pubkey_verify_data2(gnutls_pubkey_t pubkey,
1594                            gnutls_sign_algorithm_t algo,
1595                            unsigned int flags,
1596                            const gnutls_datum_t * data,
1597                            const gnutls_datum_t * signature)
1598 {
1599         int ret;
1600         const mac_entry_st *me;
1601
1602         if (pubkey == NULL) {
1603                 gnutls_assert();
1604                 return GNUTLS_E_INVALID_REQUEST;
1605         }
1606
1607         if (flags & GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA)
1608                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1609
1610         me = hash_to_entry(gnutls_sign_get_hash_algorithm(algo));
1611         if (me == NULL)
1612                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1613
1614         ret = pubkey_verify_data(pubkey->pk_algorithm, me,
1615                                  data, signature, &pubkey->params);
1616         if (ret < 0) {
1617                 gnutls_assert();
1618         }
1619
1620         return ret;
1621 }
1622
1623
1624 /**
1625  * gnutls_pubkey_verify_hash:
1626  * @key: Holds the public key
1627  * @flags: Zero or one of %gnutls_pubkey_flags_t
1628  * @hash: holds the hash digest to be verified
1629  * @signature: contains the signature
1630  *
1631  * This function will verify the given signed digest, using the
1632  * parameters from the public key. 
1633  *
1634  * Deprecated. This function cannot be easily used securely. 
1635  * Use gnutls_pubkey_verify_hash2() instead.
1636  *
1637  * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED 
1638  * is returned, and zero or positive code on success.
1639  *
1640  * Since: 2.12.0
1641  **/
1642 int
1643 gnutls_pubkey_verify_hash(gnutls_pubkey_t key, unsigned int flags,
1644                           const gnutls_datum_t * hash,
1645                           const gnutls_datum_t * signature)
1646 {
1647         gnutls_digest_algorithm_t algo;
1648         int ret;
1649
1650         ret = gnutls_pubkey_get_verify_algorithm(key, signature, &algo);
1651         if (ret < 0)
1652                 return gnutls_assert_val(ret);
1653
1654         return gnutls_pubkey_verify_hash2(key,
1655                                           gnutls_pk_to_sign(key->
1656                                                             pk_algorithm,
1657                                                             algo), flags,
1658                                           hash, signature);
1659 }
1660
1661 /**
1662  * gnutls_pubkey_verify_hash2:
1663  * @key: Holds the public key
1664  * @algo: The signature algorithm used
1665  * @flags: Zero or one of %gnutls_pubkey_flags_t
1666  * @hash: holds the hash digest to be verified
1667  * @signature: contains the signature
1668  *
1669  * This function will verify the given signed digest, using the
1670  * parameters from the public key. Note that unlike gnutls_privkey_sign_hash(),
1671  * this function accepts a signature algorithm instead of a digest algorithm.
1672  * You can use gnutls_pk_to_sign() to get the appropriate value.
1673  *
1674  * Returns: In case of a verification failure %GNUTLS_E_PK_SIG_VERIFY_FAILED 
1675  * is returned, and zero or positive code on success.
1676  *
1677  * Since: 3.0
1678  **/
1679 int
1680 gnutls_pubkey_verify_hash2(gnutls_pubkey_t key,
1681                            gnutls_sign_algorithm_t algo,
1682                            unsigned int flags,
1683                            const gnutls_datum_t * hash,
1684                            const gnutls_datum_t * signature)
1685 {
1686         const mac_entry_st *me;
1687
1688         if (key == NULL) {
1689                 gnutls_assert();
1690                 return GNUTLS_E_INVALID_REQUEST;
1691         }
1692
1693         if (flags & GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA) {
1694                 return _gnutls_pk_verify(GNUTLS_PK_RSA, hash, signature,
1695                                          &key->params);
1696         } else {
1697                 me = hash_to_entry(gnutls_sign_get_hash_algorithm(algo));
1698                 return pubkey_verify_hashed_data(key->pk_algorithm, me,
1699                                                  hash, signature,
1700                                                  &key->params);
1701         }
1702 }
1703
1704 /**
1705  * gnutls_pubkey_encrypt_data:
1706  * @key: Holds the public key
1707  * @flags: should be 0 for now
1708  * @plaintext: The data to be encrypted
1709  * @ciphertext: contains the encrypted data
1710  *
1711  * This function will encrypt the given data, using the public
1712  * key.
1713  *
1714  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1715  *   negative error value.
1716  *
1717  * Since: 3.0
1718  **/
1719 int
1720 gnutls_pubkey_encrypt_data(gnutls_pubkey_t key, unsigned int flags,
1721                            const gnutls_datum_t * plaintext,
1722                            gnutls_datum_t * ciphertext)
1723 {
1724         if (key == NULL) {
1725                 gnutls_assert();
1726                 return GNUTLS_E_INVALID_REQUEST;
1727         }
1728
1729         return _gnutls_pk_encrypt(key->pk_algorithm, ciphertext,
1730                                   plaintext, &key->params);
1731 }
1732
1733 /**
1734  * gnutls_pubkey_get_verify_algorithm:
1735  * @key: Holds the certificate
1736  * @signature: contains the signature
1737  * @hash: The result of the call with the hash algorithm used for signature
1738  *
1739  * This function will read the certifcate and the signed data to
1740  * determine the hash algorithm used to generate the signature.
1741  *
1742  * This function is only for informative purposes, as it does not
1743  * return a cryptographically binding result. Modifications to the signature
1744  * may cause this function to return an incorrect result.
1745  *
1746  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1747  *   negative error value.
1748  *
1749  * Since: 2.12.0
1750  **/
1751 int
1752 gnutls_pubkey_get_verify_algorithm(gnutls_pubkey_t key,
1753                                    const gnutls_datum_t * signature,
1754                                    gnutls_digest_algorithm_t * hash)
1755 {
1756         if (key == NULL) {
1757                 gnutls_assert();
1758                 return GNUTLS_E_INVALID_REQUEST;
1759         }
1760
1761         return _gnutls_x509_verify_algorithm(hash, signature,
1762                                              key->pk_algorithm,
1763                                              &key->params);
1764
1765 }
1766
1767 /* Checks whether the public key given is compatible with the
1768  * signature algorithm used. The session is only used for audit logging, and
1769  * it may be null.
1770  */
1771 int _gnutls_pubkey_compatible_with_sig(gnutls_session_t session,
1772                                        gnutls_pubkey_t pubkey,
1773                                        const version_entry_st * ver,
1774                                        gnutls_sign_algorithm_t sign)
1775 {
1776         unsigned int hash_size = 0;
1777         unsigned int sig_hash_size;
1778         const mac_entry_st *me;
1779
1780         if (pubkey->pk_algorithm == GNUTLS_PK_DSA) {
1781                 me = _gnutls_dsa_q_to_hash(pubkey->pk_algorithm,
1782                                            &pubkey->params, &hash_size);
1783
1784                 /* DSA keys over 1024 bits cannot be used with TLS 1.x, x<2 */
1785                 if (!_gnutls_version_has_selectable_sighash(ver)) {
1786                         if (me->id != GNUTLS_MAC_SHA1)
1787                                 return
1788                                     gnutls_assert_val
1789                                     (GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL);
1790                 } else if (sign != GNUTLS_SIGN_UNKNOWN) {
1791                         me = hash_to_entry(gnutls_sign_get_hash_algorithm
1792                                           (sign));
1793                         sig_hash_size = _gnutls_hash_get_algo_len(me);
1794                         if (sig_hash_size < hash_size)
1795                                 _gnutls_audit_log(session,
1796                                                   "The hash size used in signature (%u) is less than the expected (%u)\n",
1797                                                   sig_hash_size,
1798                                                   hash_size);
1799                 }
1800
1801         } else if (pubkey->pk_algorithm == GNUTLS_PK_EC) {
1802                 if (_gnutls_version_has_selectable_sighash(ver)
1803                     && sign != GNUTLS_SIGN_UNKNOWN) {
1804                         _gnutls_dsa_q_to_hash(pubkey->pk_algorithm,
1805                                                    &pubkey->params,
1806                                                    &hash_size);
1807
1808                         me = hash_to_entry(gnutls_sign_get_hash_algorithm
1809                                           (sign));
1810                         sig_hash_size = _gnutls_hash_get_algo_len(me);
1811
1812                         if (sig_hash_size < hash_size)
1813                                 _gnutls_audit_log(session,
1814                                                   "The hash size used in signature (%u) is less than the expected (%u)\n",
1815                                                   sig_hash_size,
1816                                                   hash_size);
1817                 }
1818
1819         }
1820
1821         return 0;
1822 }
1823
1824 /* Returns the public key. 
1825  */
1826 int
1827 _gnutls_pubkey_get_mpis(gnutls_pubkey_t key, gnutls_pk_params_st * params)
1828 {
1829         return _gnutls_pk_params_copy(params, &key->params);
1830 }
1831
1832 /* if hash==MD5 then we do RSA-MD5
1833  * if hash==SHA then we do RSA-SHA
1834  * params[0] is modulus
1835  * params[1] is public key
1836  */
1837 static int
1838 _pkcs1_rsa_verify_sig(const mac_entry_st * me,
1839                       const gnutls_datum_t * text,
1840                       const gnutls_datum_t * prehash,
1841                       const gnutls_datum_t * signature,
1842                       gnutls_pk_params_st * params)
1843 {
1844         int ret;
1845         uint8_t md[MAX_HASH_SIZE], *cmp;
1846         unsigned int digest_size;
1847         gnutls_datum_t d, di;
1848
1849         digest_size = _gnutls_hash_get_algo_len(me);
1850         if (prehash) {
1851                 if (prehash->data == NULL || prehash->size != digest_size)
1852                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1853
1854                 cmp = prehash->data;
1855         } else {
1856                 if (!text) {
1857                         gnutls_assert();
1858                         return GNUTLS_E_INVALID_REQUEST;
1859                 }
1860
1861                 ret = _gnutls_hash_fast(me->id, text->data, text->size, md);
1862                 if (ret < 0) {
1863                         gnutls_assert();
1864                         return ret;
1865                 }
1866
1867                 cmp = md;
1868         }
1869
1870         d.data = cmp;
1871         d.size = digest_size;
1872
1873         /* decrypted is a BER encoded data of type DigestInfo
1874          */
1875         ret = encode_ber_digest_info(me, &d, &di);
1876         if (ret < 0)
1877                 return gnutls_assert_val(ret);
1878
1879         ret = _gnutls_pk_verify(GNUTLS_PK_RSA, &di, signature, params);
1880         _gnutls_free_datum(&di);
1881
1882         return ret;
1883 }
1884
1885 /* Hashes input data and verifies a signature.
1886  */
1887 static int
1888 dsa_verify_hashed_data(gnutls_pk_algorithm_t pk,
1889                        const mac_entry_st * algo,
1890                        const gnutls_datum_t * hash,
1891                        const gnutls_datum_t * signature,
1892                        gnutls_pk_params_st * params)
1893 {
1894         gnutls_datum_t digest;
1895         unsigned int hash_len;
1896
1897         if (algo == NULL)
1898                 algo = _gnutls_dsa_q_to_hash(pk, params, &hash_len);
1899         else
1900                 hash_len = _gnutls_hash_get_algo_len(algo);
1901
1902         /* SHA1 or better allowed */
1903         if (!hash->data || hash->size < hash_len) {
1904                 gnutls_assert();
1905                 _gnutls_debug_log
1906                     ("Hash size (%d) does not correspond to hash %s(%d) or better.\n",
1907                      (int) hash->size, _gnutls_mac_get_name(algo),
1908                      hash_len);
1909
1910                 if (hash->size != 20)   /* SHA1 is allowed */
1911                         return
1912                             gnutls_assert_val
1913                             (GNUTLS_E_PK_SIG_VERIFY_FAILED);
1914         }
1915
1916         digest.data = hash->data;
1917         digest.size = hash->size;
1918
1919         return _gnutls_pk_verify(pk, &digest, signature, params);
1920 }
1921
1922 static int
1923 dsa_verify_data(gnutls_pk_algorithm_t pk,
1924                 const mac_entry_st * algo,
1925                 const gnutls_datum_t * data,
1926                 const gnutls_datum_t * signature,
1927                 gnutls_pk_params_st * params)
1928 {
1929         int ret;
1930         uint8_t _digest[MAX_HASH_SIZE];
1931         gnutls_datum_t digest;
1932
1933         if (algo == NULL)
1934                 algo = _gnutls_dsa_q_to_hash(pk, params, NULL);
1935
1936         ret = _gnutls_hash_fast(algo->id, data->data, data->size, _digest);
1937         if (ret < 0)
1938                 return gnutls_assert_val(ret);
1939
1940         digest.data = _digest;
1941         digest.size = _gnutls_hash_get_algo_len(algo);
1942
1943         return _gnutls_pk_verify(pk, &digest, signature, params);
1944 }
1945
1946 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if 
1947  * not verified, or 1 otherwise.
1948  */
1949 int
1950 pubkey_verify_hashed_data(gnutls_pk_algorithm_t pk,
1951                           const mac_entry_st * hash_algo,
1952                           const gnutls_datum_t * hash,
1953                           const gnutls_datum_t * signature,
1954                           gnutls_pk_params_st * issuer_params)
1955 {
1956
1957         switch (pk) {
1958         case GNUTLS_PK_RSA:
1959
1960                 if (_pkcs1_rsa_verify_sig
1961                     (hash_algo, NULL, hash, signature, issuer_params) != 0)
1962                 {
1963                         gnutls_assert();
1964                         return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1965                 }
1966
1967                 return 1;
1968                 break;
1969
1970         case GNUTLS_PK_EC:
1971         case GNUTLS_PK_DSA:
1972                 if (dsa_verify_hashed_data
1973                     (pk, hash_algo, hash, signature, issuer_params) != 0) {
1974                         gnutls_assert();
1975                         return GNUTLS_E_PK_SIG_VERIFY_FAILED;
1976                 }
1977
1978                 return 1;
1979                 break;
1980         default:
1981                 gnutls_assert();
1982                 return GNUTLS_E_INTERNAL_ERROR;
1983
1984         }
1985 }
1986
1987 /* Verifies the signature data, and returns GNUTLS_E_PK_SIG_VERIFY_FAILED if 
1988  * not verified, or 1 otherwise.
1989  */
1990 int
1991 pubkey_verify_data(gnutls_pk_algorithm_t pk,
1992                    const mac_entry_st * me,
1993                    const gnutls_datum_t * data,
1994                    const gnutls_datum_t * signature,
1995                    gnutls_pk_params_st * issuer_params)
1996 {
1997
1998         switch (pk) {
1999         case GNUTLS_PK_RSA:
2000
2001                 if (_pkcs1_rsa_verify_sig
2002                     (me, data, NULL, signature, issuer_params) != 0) {
2003                         gnutls_assert();
2004                         return GNUTLS_E_PK_SIG_VERIFY_FAILED;
2005                 }
2006
2007                 return 1;
2008                 break;
2009
2010         case GNUTLS_PK_EC:
2011         case GNUTLS_PK_DSA:
2012                 if (dsa_verify_data(pk, me, data, signature, issuer_params)
2013                     != 0) {
2014                         gnutls_assert();
2015                         return GNUTLS_E_PK_SIG_VERIFY_FAILED;
2016                 }
2017
2018                 return 1;
2019                 break;
2020         default:
2021                 gnutls_assert();
2022                 return GNUTLS_E_INTERNAL_ERROR;
2023
2024         }
2025 }
2026
2027 const mac_entry_st *_gnutls_dsa_q_to_hash(gnutls_pk_algorithm_t algo,
2028                                           const gnutls_pk_params_st *
2029                                           params, unsigned int *hash_len)
2030 {
2031         int bits = 0;
2032         int ret;
2033
2034         if (algo == GNUTLS_PK_DSA)
2035                 bits = _gnutls_mpi_get_nbits(params->params[1]);
2036         else if (algo == GNUTLS_PK_EC)
2037                 bits = gnutls_ecc_curve_get_size(params->flags) * 8;
2038
2039         if (bits <= 160) {
2040                 if (hash_len)
2041                         *hash_len = 20;
2042                 ret = GNUTLS_DIG_SHA1;
2043         } else if (bits <= 192) {
2044                 if (hash_len)
2045                         *hash_len = 24;
2046                 ret = GNUTLS_DIG_SHA256;
2047         } else if (bits <= 224) {
2048                 if (hash_len)
2049                         *hash_len = 28;
2050                 ret = GNUTLS_DIG_SHA256;
2051         } else if (bits <= 256) {
2052                 if (hash_len)
2053                         *hash_len = 32;
2054                 ret = GNUTLS_DIG_SHA256;
2055         } else if (bits <= 384) {
2056                 if (hash_len)
2057                         *hash_len = 48;
2058                 ret = GNUTLS_DIG_SHA384;
2059         } else {
2060                 if (hash_len)
2061                         *hash_len = 64;
2062                 ret = GNUTLS_DIG_SHA512;
2063         }
2064
2065         return mac_to_entry(ret);
2066 }
2067
2068 /**
2069  * gnutls_pubkey_set_pin_function:
2070  * @key: A key of type #gnutls_pubkey_t
2071  * @fn: the callback
2072  * @userdata: data associated with the callback
2073  *
2074  * This function will set a callback function to be used when
2075  * required to access the object. This function overrides any other
2076  * global PIN functions.
2077  *
2078  * Note that this function must be called right after initialization
2079  * to have effect.
2080  *
2081  * Since: 3.1.0
2082  *
2083  **/
2084 void gnutls_pubkey_set_pin_function(gnutls_pubkey_t key,
2085                                     gnutls_pin_callback_t fn,
2086                                     void *userdata)
2087 {
2088         key->pin.cb = fn;
2089         key->pin.data = userdata;
2090 }
2091
2092 /**
2093  * gnutls_pubkey_import_x509_raw:
2094  * @pkey: The public key
2095  * @data: The public key data to be imported
2096  * @format: The format of the public key
2097  * @flags: should be zero
2098  *
2099  * This function will import the given public key to the abstract
2100  * #gnutls_pubkey_t structure. 
2101  *
2102  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2103  *   negative error value.
2104  *
2105  * Since: 3.1.3
2106  **/
2107 int gnutls_pubkey_import_x509_raw(gnutls_pubkey_t pkey,
2108                                   const gnutls_datum_t * data,
2109                                   gnutls_x509_crt_fmt_t format,
2110                                   unsigned int flags)
2111 {
2112         gnutls_x509_crt_t xpriv;
2113         int ret;
2114
2115         ret = gnutls_x509_crt_init(&xpriv);
2116         if (ret < 0)
2117                 return gnutls_assert_val(ret);
2118
2119         ret = gnutls_x509_crt_import(xpriv, data, format);
2120         if (ret < 0) {
2121                 gnutls_assert();
2122                 goto cleanup;
2123         }
2124
2125         ret = gnutls_pubkey_import_x509(pkey, xpriv, flags);
2126         if (ret < 0) {
2127                 gnutls_assert();
2128                 goto cleanup;
2129         }
2130
2131         return 0;
2132
2133       cleanup:
2134         gnutls_x509_crt_deinit(xpriv);
2135
2136         return ret;
2137 }
2138
2139 /**
2140  * gnutls_pubkey_verify_params:
2141  * @key: should contain a #gnutls_pubkey_t structure
2142  *
2143  * This function will verify the private key parameters.
2144  *
2145  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2146  *   negative error value.
2147  *
2148  * Since: 3.3.0
2149  **/
2150 int gnutls_pubkey_verify_params(gnutls_pubkey_t key)
2151 {
2152         int ret;
2153
2154         ret = _gnutls_pk_verify_pub_params(key->pk_algorithm, &key->params);
2155         if (ret < 0) {
2156                 gnutls_assert();
2157                 return ret;
2158         }
2159
2160         return 0;
2161 }