Add ARMv8/CE acceleration for AES-XTS
[libgcrypt.git] / cipher / pubkey.c
1 /* pubkey.c  -  pubkey dispatcher
2  * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
3  *               2007, 2008, 2011 Free Software Foundation, Inc.
4  * Copyright (C) 2013 g10 Code GmbH
5  *
6  * This file is part of Libgcrypt.
7  *
8  * Libgcrypt is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser general Public License as
10  * published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * Libgcrypt is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include "g10lib.h"
29 #include "mpi.h"
30 #include "cipher.h"
31 #include "context.h"
32 #include "pubkey-internal.h"
33
34
35 /* This is the list of the public-key algorithms included in
36    Libgcrypt.  */
37 static gcry_pk_spec_t *pubkey_list[] =
38   {
39 #if USE_ECC
40     &_gcry_pubkey_spec_ecc,
41 #endif
42 #if USE_RSA
43     &_gcry_pubkey_spec_rsa,
44 #endif
45 #if USE_DSA
46     &_gcry_pubkey_spec_dsa,
47 #endif
48 #if USE_ELGAMAL
49     &_gcry_pubkey_spec_elg,
50 #endif
51     NULL
52   };
53
54
55 static int
56 map_algo (int algo)
57 {
58  switch (algo)
59    {
60    case GCRY_PK_RSA_E: return GCRY_PK_RSA;
61    case GCRY_PK_RSA_S: return GCRY_PK_RSA;
62    case GCRY_PK_ELG_E: return GCRY_PK_ELG;
63    case GCRY_PK_ECDSA: return GCRY_PK_ECC;
64    case GCRY_PK_ECDH:  return GCRY_PK_ECC;
65    default:            return algo;
66    }
67 }
68
69
70 /* Return the spec structure for the public key algorithm ALGO.  For
71    an unknown algorithm NULL is returned.  */
72 static gcry_pk_spec_t *
73 spec_from_algo (int algo)
74 {
75   int idx;
76   gcry_pk_spec_t *spec;
77
78   algo = map_algo (algo);
79
80   for (idx = 0; (spec = pubkey_list[idx]); idx++)
81     if (algo == spec->algo)
82       return spec;
83   return NULL;
84 }
85
86
87 /* Return the spec structure for the public key algorithm with NAME.
88    For an unknown name NULL is returned.  */
89 static gcry_pk_spec_t *
90 spec_from_name (const char *name)
91 {
92   gcry_pk_spec_t *spec;
93   int idx;
94   const char **aliases;
95
96   for (idx=0; (spec = pubkey_list[idx]); idx++)
97     {
98       if (!stricmp (name, spec->name))
99         return spec;
100       for (aliases = spec->aliases; *aliases; aliases++)
101         if (!stricmp (name, *aliases))
102           return spec;
103     }
104
105   return NULL;
106 }
107
108
109
110 /* Given the s-expression SEXP with the first element be either
111  * "private-key" or "public-key" return the spec structure for it.  We
112  * look through the list to find a list beginning with "private-key"
113  * or "public-key" - the first one found is used.  If WANT_PRIVATE is
114  * set the function will only succeed if a private key has been given.
115  * On success the spec is stored at R_SPEC.  On error NULL is stored
116  * at R_SPEC and an error code returned.  If R_PARMS is not NULL and
117  * the function returns success, the parameter list below
118  * "private-key" or "public-key" is stored there and the caller must
119  * call gcry_sexp_release on it.
120  */
121 static gcry_err_code_t
122 spec_from_sexp (gcry_sexp_t sexp, int want_private,
123                 gcry_pk_spec_t **r_spec, gcry_sexp_t *r_parms)
124 {
125   gcry_sexp_t list, l2;
126   char *name;
127   gcry_pk_spec_t *spec;
128
129   *r_spec = NULL;
130   if (r_parms)
131     *r_parms = NULL;
132
133   /* Check that the first element is valid.  If we are looking for a
134      public key but a private key was supplied, we allow the use of
135      the private key anyway.  The rationale for this is that the
136      private key is a superset of the public key.  */
137   list = sexp_find_token (sexp, want_private? "private-key":"public-key", 0);
138   if (!list && !want_private)
139     list = sexp_find_token (sexp, "private-key", 0);
140   if (!list)
141     return GPG_ERR_INV_OBJ; /* Does not contain a key object.  */
142
143   l2 = sexp_cadr (list);
144   sexp_release (list);
145   list = l2;
146   name = sexp_nth_string (list, 0);
147   if (!name)
148     {
149       sexp_release ( list );
150       return GPG_ERR_INV_OBJ;      /* Invalid structure of object. */
151     }
152   spec = spec_from_name (name);
153   xfree (name);
154   if (!spec)
155     {
156       sexp_release (list);
157       return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
158     }
159   *r_spec = spec;
160   if (r_parms)
161     *r_parms = list;
162   else
163     sexp_release (list);
164   return 0;
165 }
166
167
168
169 /* Disable the use of the algorithm ALGO.  This is not thread safe and
170    should thus be called early.  */
171 static void
172 disable_pubkey_algo (int algo)
173 {
174   gcry_pk_spec_t *spec = spec_from_algo (algo);
175
176   if (spec)
177     spec->flags.disabled = 1;
178 }
179
180
181 \f
182 /*
183  * Map a string to the pubkey algo
184  */
185 int
186 _gcry_pk_map_name (const char *string)
187 {
188   gcry_pk_spec_t *spec;
189
190   if (!string)
191     return 0;
192   spec = spec_from_name (string);
193   if (!spec)
194     return 0;
195   if (spec->flags.disabled)
196     return 0;
197   return spec->algo;
198 }
199
200
201 /* Map the public key algorithm whose ID is contained in ALGORITHM to
202    a string representation of the algorithm name.  For unknown
203    algorithm IDs this functions returns "?". */
204 const char *
205 _gcry_pk_algo_name (int algo)
206 {
207   gcry_pk_spec_t *spec;
208
209   spec = spec_from_algo (algo);
210   if (spec)
211     return spec->name;
212   return "?";
213 }
214
215
216 /****************
217  * A USE of 0 means: don't care.
218  */
219 static gcry_err_code_t
220 check_pubkey_algo (int algo, unsigned use)
221 {
222   gcry_err_code_t err = 0;
223   gcry_pk_spec_t *spec;
224
225   spec = spec_from_algo (algo);
226   if (spec)
227     {
228       if (((use & GCRY_PK_USAGE_SIGN)
229            && (! (spec->use & GCRY_PK_USAGE_SIGN)))
230           || ((use & GCRY_PK_USAGE_ENCR)
231               && (! (spec->use & GCRY_PK_USAGE_ENCR))))
232         err = GPG_ERR_WRONG_PUBKEY_ALGO;
233     }
234   else
235     err = GPG_ERR_PUBKEY_ALGO;
236
237   return err;
238 }
239
240
241 /****************
242  * Return the number of public key material numbers
243  */
244 static int
245 pubkey_get_npkey (int algo)
246 {
247   gcry_pk_spec_t *spec = spec_from_algo (algo);
248
249   return spec? strlen (spec->elements_pkey) : 0;
250 }
251
252
253 /****************
254  * Return the number of secret key material numbers
255  */
256 static int
257 pubkey_get_nskey (int algo)
258 {
259   gcry_pk_spec_t *spec = spec_from_algo (algo);
260
261   return spec? strlen (spec->elements_skey) : 0;
262 }
263
264
265 /****************
266  * Return the number of signature material numbers
267  */
268 static int
269 pubkey_get_nsig (int algo)
270 {
271   gcry_pk_spec_t *spec = spec_from_algo (algo);
272
273   return spec? strlen (spec->elements_sig) : 0;
274 }
275
276 /****************
277  * Return the number of encryption material numbers
278  */
279 static int
280 pubkey_get_nenc (int algo)
281 {
282   gcry_pk_spec_t *spec = spec_from_algo (algo);
283
284   return spec? strlen (spec->elements_enc) : 0;
285 }
286
287
288 \f
289 /*
290    Do a PK encrypt operation
291
292    Caller has to provide a public key as the SEXP pkey and data as a
293    SEXP with just one MPI in it. Alternatively S_DATA might be a
294    complex S-Expression, similar to the one used for signature
295    verification.  This provides a flag which allows to handle PKCS#1
296    block type 2 padding.  The function returns a sexp which may be
297    passed to to pk_decrypt.
298
299    Returns: 0 or an errorcode.
300
301    s_data = See comment for _gcry_pk_util_data_to_mpi
302    s_pkey = <key-as-defined-in-sexp_to_key>
303    r_ciph = (enc-val
304                (<algo>
305                  (<param_name1> <mpi>)
306                  ...
307                  (<param_namen> <mpi>)
308                ))
309
310 */
311 gcry_err_code_t
312 _gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
313 {
314   gcry_err_code_t rc;
315   gcry_pk_spec_t *spec;
316   gcry_sexp_t keyparms;
317
318   *r_ciph = NULL;
319
320   rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
321   if (rc)
322     goto leave;
323
324   if (spec->encrypt)
325     rc = spec->encrypt (r_ciph, s_data, keyparms);
326   else
327     rc = GPG_ERR_NOT_IMPLEMENTED;
328
329  leave:
330   sexp_release (keyparms);
331   return rc;
332 }
333
334
335 /*
336    Do a PK decrypt operation
337
338    Caller has to provide a secret key as the SEXP skey and data in a
339    format as created by gcry_pk_encrypt.  For historic reasons the
340    function returns simply an MPI as an S-expression part; this is
341    deprecated and the new method should be used which returns a real
342    S-expressionl this is selected by adding at least an empty flags
343    list to S_DATA.
344
345    Returns: 0 or an errorcode.
346
347    s_data = (enc-val
348               [(flags [raw, pkcs1, oaep])]
349               (<algo>
350                 (<param_name1> <mpi>)
351                 ...
352                 (<param_namen> <mpi>)
353               ))
354    s_skey = <key-as-defined-in-sexp_to_key>
355    r_plain= Either an incomplete S-expression without the parentheses
356             or if the flags list is used (even if empty) a real S-expression:
357             (value PLAIN).  In raw mode (or no flags given) the returned value
358             is to be interpreted as a signed MPI, thus it may have an extra
359             leading zero octet even if not included in the original data.
360             With pkcs1 or oaep decoding enabled the returned value is a
361             verbatim octet string.
362  */
363 gcry_err_code_t
364 _gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
365 {
366   gcry_err_code_t rc;
367   gcry_pk_spec_t *spec;
368   gcry_sexp_t keyparms;
369
370   *r_plain = NULL;
371
372   rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
373   if (rc)
374     goto leave;
375
376   if (spec->decrypt)
377     rc = spec->decrypt (r_plain, s_data, keyparms);
378   else
379     rc = GPG_ERR_NOT_IMPLEMENTED;
380
381  leave:
382   sexp_release (keyparms);
383   return rc;
384 }
385
386
387
388 /*
389    Create a signature.
390
391    Caller has to provide a secret key as the SEXP skey and data
392    expressed as a SEXP list hash with only one element which should
393    instantly be available as a MPI. Alternatively the structure given
394    below may be used for S_HASH, it provides the abiliy to pass flags
395    to the operation; the flags defined by now are "pkcs1" which does
396    PKCS#1 block type 1 style padding and "pss" for PSS encoding.
397
398    Returns: 0 or an errorcode.
399             In case of 0 the function returns a new SEXP with the
400             signature value; the structure of this signature depends on the
401             other arguments but is always suitable to be passed to
402             gcry_pk_verify
403
404    s_hash = See comment for _gcry-pk_util_data_to_mpi
405
406    s_skey = <key-as-defined-in-sexp_to_key>
407    r_sig  = (sig-val
408               (<algo>
409                 (<param_name1> <mpi>)
410                 ...
411                 (<param_namen> <mpi>))
412              [(hash algo)])
413
414   Note that (hash algo) in R_SIG is not used.
415 */
416 gcry_err_code_t
417 _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
418 {
419   gcry_err_code_t rc;
420   gcry_pk_spec_t *spec;
421   gcry_sexp_t keyparms;
422
423   *r_sig = NULL;
424
425   rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
426   if (rc)
427     goto leave;
428
429   if (spec->sign)
430     rc = spec->sign (r_sig, s_hash, keyparms);
431   else
432     rc = GPG_ERR_NOT_IMPLEMENTED;
433
434  leave:
435   sexp_release (keyparms);
436   return rc;
437 }
438
439
440 /*
441    Verify a signature.
442
443    Caller has to supply the public key pkey, the signature sig and his
444    hashvalue data.  Public key has to be a standard public key given
445    as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data
446    must be an S-Exp like the one in sign too.  */
447 gcry_err_code_t
448 _gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
449 {
450   gcry_err_code_t rc;
451   gcry_pk_spec_t *spec;
452   gcry_sexp_t keyparms;
453
454   rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
455   if (rc)
456     goto leave;
457
458   if (spec->verify)
459     rc = spec->verify (s_sig, s_hash, keyparms);
460   else
461     rc = GPG_ERR_NOT_IMPLEMENTED;
462
463  leave:
464   sexp_release (keyparms);
465   return rc;
466 }
467
468
469 /*
470    Test a key.
471
472    This may be used either for a public or a secret key to see whether
473    the internal structure is okay.
474
475    Returns: 0 or an errorcode.
476
477    NOTE: We currently support only secret key checking. */
478 gcry_err_code_t
479 _gcry_pk_testkey (gcry_sexp_t s_key)
480 {
481   gcry_err_code_t rc;
482   gcry_pk_spec_t *spec;
483   gcry_sexp_t keyparms;
484
485   rc = spec_from_sexp (s_key, 1, &spec, &keyparms);
486   if (rc)
487     goto leave;
488
489   if (spec->check_secret_key)
490     rc = spec->check_secret_key (keyparms);
491   else
492     rc = GPG_ERR_NOT_IMPLEMENTED;
493
494  leave:
495   sexp_release (keyparms);
496   return rc;
497 }
498
499
500 /*
501   Create a public key pair and return it in r_key.
502   How the key is created depends on s_parms:
503   (genkey
504    (algo
505      (parameter_name_1 ....)
506       ....
507      (parameter_name_n ....)
508   ))
509   The key is returned in a format depending on the
510   algorithm. Both, private and secret keys are returned
511   and optionally some additional informatin.
512   For elgamal we return this structure:
513   (key-data
514    (public-key
515      (elg
516         (p <mpi>)
517         (g <mpi>)
518         (y <mpi>)
519      )
520    )
521    (private-key
522      (elg
523         (p <mpi>)
524         (g <mpi>)
525         (y <mpi>)
526         (x <mpi>)
527      )
528    )
529    (misc-key-info
530       (pm1-factors n1 n2 ... nn)
531    ))
532  */
533 gcry_err_code_t
534 _gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
535 {
536   gcry_pk_spec_t *spec = NULL;
537   gcry_sexp_t list = NULL;
538   gcry_sexp_t l2 = NULL;
539   char *name = NULL;
540   gcry_err_code_t rc;
541
542   *r_key = NULL;
543
544   list = sexp_find_token (s_parms, "genkey", 0);
545   if (!list)
546     {
547       rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */
548       goto leave;
549     }
550
551   l2 = sexp_cadr (list);
552   sexp_release (list);
553   list = l2;
554   l2 = NULL;
555   if (! list)
556     {
557       rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */
558       goto leave;
559     }
560
561   name = _gcry_sexp_nth_string (list, 0);
562   if (!name)
563     {
564       rc = GPG_ERR_INV_OBJ; /* Algo string missing.  */
565       goto leave;
566     }
567
568   spec = spec_from_name (name);
569   xfree (name);
570   name = NULL;
571   if (!spec)
572     {
573       rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm.  */
574       goto leave;
575     }
576
577   if (spec->generate)
578     rc = spec->generate (list, r_key);
579   else
580     rc = GPG_ERR_NOT_IMPLEMENTED;
581
582  leave:
583   sexp_release (list);
584   xfree (name);
585   sexp_release (l2);
586
587   return rc;
588 }
589
590
591 /*
592    Get the number of nbits from the public key.
593
594    Hmmm: Should we have really this function or is it better to have a
595    more general function to retrieve different properties of the key?  */
596 unsigned int
597 _gcry_pk_get_nbits (gcry_sexp_t key)
598 {
599   gcry_pk_spec_t *spec;
600   gcry_sexp_t parms;
601   unsigned int nbits;
602
603   /* Parsing KEY might be considered too much overhead.  For example
604      for RSA we would only need to look at P and stop parsing right
605      away.  However, with ECC things are more complicate in that only
606      a curve name might be specified.  Thus we need to tear the sexp
607      apart. */
608
609   if (spec_from_sexp (key, 0, &spec, &parms))
610     return 0; /* Error - 0 is a suitable indication for that.  */
611
612   nbits = spec->get_nbits (parms);
613   sexp_release (parms);
614   return nbits;
615 }
616
617
618 /* Return the so called KEYGRIP which is the SHA-1 hash of the public
619    key parameters expressed in a way depending on the algorithm.
620
621    ARRAY must either be 20 bytes long or NULL; in the latter case a
622    newly allocated array of that size is returned, otherwise ARRAY or
623    NULL is returned to indicate an error which is most likely an
624    unknown algorithm.  The function accepts public or secret keys. */
625 unsigned char *
626 _gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
627 {
628   gcry_sexp_t list = NULL;
629   gcry_sexp_t l2 = NULL;
630   gcry_pk_spec_t *spec = NULL;
631   const char *s;
632   char *name = NULL;
633   int idx;
634   const char *elems;
635   gcry_md_hd_t md = NULL;
636   int okay = 0;
637
638   /* Check that the first element is valid. */
639   list = sexp_find_token (key, "public-key", 0);
640   if (! list)
641     list = sexp_find_token (key, "private-key", 0);
642   if (! list)
643     list = sexp_find_token (key, "protected-private-key", 0);
644   if (! list)
645     list = sexp_find_token (key, "shadowed-private-key", 0);
646   if (! list)
647     return NULL; /* No public- or private-key object. */
648
649   l2 = sexp_cadr (list);
650   sexp_release (list);
651   list = l2;
652   l2 = NULL;
653
654   name = _gcry_sexp_nth_string (list, 0);
655   if (!name)
656     goto fail; /* Invalid structure of object. */
657
658   spec = spec_from_name (name);
659   if (!spec)
660     goto fail; /* Unknown algorithm.  */
661
662   elems = spec->elements_grip;
663   if (!elems)
664     goto fail; /* No grip parameter.  */
665
666   if (_gcry_md_open (&md, GCRY_MD_SHA1, 0))
667     goto fail;
668
669   if (spec->comp_keygrip)
670     {
671       /* Module specific method to compute a keygrip.  */
672       if (spec->comp_keygrip (md, list))
673         goto fail;
674     }
675   else
676     {
677       /* Generic method to compute a keygrip.  */
678       for (idx = 0, s = elems; *s; s++, idx++)
679         {
680           const char *data;
681           size_t datalen;
682           char buf[30];
683
684           l2 = sexp_find_token (list, s, 1);
685           if (! l2)
686             goto fail;
687           data = sexp_nth_data (l2, 1, &datalen);
688           if (! data)
689             goto fail;
690
691           snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
692           _gcry_md_write (md, buf, strlen (buf));
693           _gcry_md_write (md, data, datalen);
694           sexp_release (l2);
695           l2 = NULL;
696           _gcry_md_write (md, ")", 1);
697         }
698     }
699
700   if (!array)
701     {
702       array = xtrymalloc (20);
703       if (! array)
704         goto fail;
705     }
706
707   memcpy (array, _gcry_md_read (md, GCRY_MD_SHA1), 20);
708   okay = 1;
709
710  fail:
711   xfree (name);
712   sexp_release (l2);
713   _gcry_md_close (md);
714   sexp_release (list);
715   return okay? array : NULL;
716 }
717
718
719 \f
720 const char *
721 _gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
722 {
723   const char *result = NULL;
724   gcry_pk_spec_t *spec;
725   gcry_sexp_t keyparms = NULL;
726
727   if (r_nbits)
728     *r_nbits = 0;
729
730   if (key)
731     {
732       iterator = 0;
733
734       if (spec_from_sexp (key, 0, &spec, &keyparms))
735         return NULL;
736     }
737   else
738     {
739       spec = spec_from_name ("ecc");
740       if (!spec)
741         return NULL;
742     }
743
744   if (spec->get_curve)
745     result = spec->get_curve (keyparms, iterator, r_nbits);
746
747   sexp_release (keyparms);
748   return result;
749 }
750
751
752 \f
753 gcry_sexp_t
754 _gcry_pk_get_param (int algo, const char *name)
755 {
756   gcry_sexp_t result = NULL;
757   gcry_pk_spec_t *spec = NULL;
758
759   algo = map_algo (algo);
760
761   if (algo != GCRY_PK_ECC)
762     return NULL;
763
764   spec = spec_from_name ("ecc");
765   if (spec)
766     {
767       if (spec && spec->get_curve_param)
768         result = spec->get_curve_param (name);
769     }
770   return result;
771 }
772
773
774 \f
775 gcry_err_code_t
776 _gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
777 {
778   gcry_err_code_t rc = 0;
779
780   switch (cmd)
781     {
782     case GCRYCTL_DISABLE_ALGO:
783       /* This one expects a buffer pointing to an integer with the
784          algo number.  */
785       if ((! buffer) || (buflen != sizeof (int)))
786         rc = GPG_ERR_INV_ARG;
787       else
788         disable_pubkey_algo (*((int *) buffer));
789       break;
790
791     default:
792       rc = GPG_ERR_INV_OP;
793     }
794
795   return rc;
796 }
797
798
799 /* Return information about the given algorithm
800
801    WHAT selects the kind of information returned:
802
803     GCRYCTL_TEST_ALGO:
804         Returns 0 when the specified algorithm is available for use.
805         Buffer must be NULL, nbytes  may have the address of a variable
806         with the required usage of the algorithm. It may be 0 for don't
807         care or a combination of the GCRY_PK_USAGE_xxx flags;
808
809     GCRYCTL_GET_ALGO_USAGE:
810         Return the usage flags for the given algo.  An invalid algo
811         returns 0.  Disabled algos are ignored here because we
812         only want to know whether the algo is at all capable of
813         the usage.
814
815    Note: Because this function is in most cases used to return an
816    integer value, we can make it easier for the caller to just look at
817    the return value.  The caller will in all cases consult the value
818    and thereby detecting whether a error occurred or not (i.e. while
819    checking the block size) */
820 gcry_err_code_t
821 _gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
822 {
823   gcry_err_code_t rc = 0;
824
825   switch (what)
826     {
827     case GCRYCTL_TEST_ALGO:
828       {
829         int use = nbytes ? *nbytes : 0;
830         if (buffer)
831           rc = GPG_ERR_INV_ARG;
832         else if (check_pubkey_algo (algorithm, use))
833           rc = GPG_ERR_PUBKEY_ALGO;
834         break;
835       }
836
837     case GCRYCTL_GET_ALGO_USAGE:
838       {
839         gcry_pk_spec_t *spec;
840
841         spec = spec_from_algo (algorithm);
842         *nbytes = spec? spec->use : 0;
843         break;
844       }
845
846     case GCRYCTL_GET_ALGO_NPKEY:
847       {
848         /* FIXME?  */
849         int npkey = pubkey_get_npkey (algorithm);
850         *nbytes = npkey;
851         break;
852       }
853     case GCRYCTL_GET_ALGO_NSKEY:
854       {
855         /* FIXME?  */
856         int nskey = pubkey_get_nskey (algorithm);
857         *nbytes = nskey;
858         break;
859       }
860     case GCRYCTL_GET_ALGO_NSIGN:
861       {
862         /* FIXME?  */
863         int nsign = pubkey_get_nsig (algorithm);
864         *nbytes = nsign;
865         break;
866       }
867     case GCRYCTL_GET_ALGO_NENCR:
868       {
869         /* FIXME?  */
870         int nencr = pubkey_get_nenc (algorithm);
871         *nbytes = nencr;
872         break;
873       }
874
875     default:
876       rc = GPG_ERR_INV_OP;
877     }
878
879   return rc;
880 }
881
882
883 /* Return an S-expression representing the context CTX.  Depending on
884    the state of that context, the S-expression may either be a public
885    key, a private key or any other object used with public key
886    operations.  On success a new S-expression is stored at R_SEXP and
887    0 is returned, on error NULL is store there and an error code is
888    returned.  MODE is either 0 or one of the GCRY_PK_GET_xxx values.
889
890    As of now it only support certain ECC operations because a context
891    object is right now only defined for ECC.  Over time this function
892    will be extended to cover more algorithms.  Note also that the name
893    of the function is gcry_pubkey_xxx and not gcry_pk_xxx.  The idea
894    is that we will eventually provide variants of the existing
895    gcry_pk_xxx functions which will take a context parameter.   */
896 gcry_err_code_t
897 _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
898 {
899   mpi_ec_t ec;
900
901   if (!r_sexp)
902     return GPG_ERR_INV_VALUE;
903   *r_sexp = NULL;
904   switch (mode)
905     {
906     case 0:
907     case GCRY_PK_GET_PUBKEY:
908     case GCRY_PK_GET_SECKEY:
909       break;
910     default:
911       return GPG_ERR_INV_VALUE;
912     }
913   if (!ctx)
914     return GPG_ERR_NO_CRYPT_CTX;
915
916   ec = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_EC);
917   if (ec)
918     return _gcry_pk_ecc_get_sexp (r_sexp, mode, ec);
919
920   return GPG_ERR_WRONG_CRYPT_CTX;
921 }
922
923
924 \f
925 /* Explicitly initialize this module.  */
926 gcry_err_code_t
927 _gcry_pk_init (void)
928 {
929   if (fips_mode())
930     {
931       /* disable algorithms that are disallowed in fips */
932       int idx;
933       gcry_pk_spec_t *spec;
934
935       for (idx = 0; (spec = pubkey_list[idx]); idx++)
936         if (!spec->flags.fips)
937           spec->flags.disabled = 1;
938     }
939
940   return 0;
941 }
942
943
944 /* Run the selftests for pubkey algorithm ALGO with optional reporting
945    function REPORT.  */
946 gpg_error_t
947 _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
948 {
949   gcry_err_code_t ec;
950   gcry_pk_spec_t *spec;
951
952   algo = map_algo (algo);
953   spec = spec_from_algo (algo);
954   if (spec && !spec->flags.disabled && spec->selftest)
955     ec = spec->selftest (algo, extended, report);
956   else
957     {
958       ec = GPG_ERR_PUBKEY_ALGO;
959       /* Fixme: We need to change the report function to allow passing
960          of an encryption mode (e.g. pkcs1, ecdsa, or ecdh).  */
961       if (report)
962         report ("pubkey", algo, "module",
963                 spec && !spec->flags.disabled?
964                 "no selftest available" :
965                 spec? "algorithm disabled" :
966                 "algorithm not found");
967     }
968
969   return gpg_error (ec);
970 }