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