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