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