2003-06-18 Moritz Schulte <moritz@g10code.com>
[libgcrypt.git] / cipher / pubkey.c
1 /* pubkey.c  -  pubkey dispatcher
2  * Copyright (C) 1998,1999,2000,2002,2003 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #include "g10lib.h"
29 #include "mpi.h"
30 #include "cipher.h"
31 #include "ath.h"
32
33 static gpg_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags);
34 static gpg_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t hash, gcry_mpi_t *skey);
35 static gpg_err_code_t pubkey_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
36                                      int (*cmp) (void *, gcry_mpi_t), void *opaque);
37
38 /* This is the list of the default public-key ciphers included in
39    libgcrypt.  */
40 static struct
41 {
42   gcry_pubkey_spec_t *pubkey;
43 } pubkey_table[] =
44   {
45 #if USE_RSA
46     { &pubkey_spec_rsa },
47 #endif
48 #if USE_ELGAMAL
49     { &pubkey_spec_elg },
50 #endif
51 #if USE_DSA
52     { &pubkey_spec_dsa },
53 #endif
54     { NULL },
55   };
56
57 /* List of registered ciphers.  */
58 static gcry_module_t *pubkeys_registered;
59
60 /* This is the lock protecting PUBKEYS_REGISTERED.  */
61 static ath_mutex_t pubkeys_registered_lock;
62
63 /* Flag to check wether the default pubkeys have already been
64    registered.  */
65 static int default_pubkeys_registered;
66
67 /* Convenient macro for registering the default digests.  */
68 #define REGISTER_DEFAULT_PUBKEYS                   \
69   do                                               \
70     {                                              \
71       ath_mutex_lock (&pubkeys_registered_lock);   \
72       if (! default_pubkeys_registered)            \
73         {                                          \
74           gcry_pubkey_register_default ();         \
75           default_pubkeys_registered = 1;          \
76         }                                          \
77       ath_mutex_unlock (&pubkeys_registered_lock); \
78     }                                              \
79   while (0)
80
81 /* These dummy functions are used in case a cipher implementation
82    refuses to provide it's own functions.  */
83
84 static gpg_err_code_t
85 dummy_generate (int id, unsigned int nbits, unsigned long dummy,
86                 gcry_mpi_t *skey, gcry_mpi_t **retfactors)
87 {
88   log_bug ("no generate() for %d\n", id);
89   return GPG_ERR_PUBKEY_ALGO;
90 }
91
92 static gpg_err_code_t
93 dummy_check_secret_key (int id, gcry_mpi_t *skey)
94 {
95   log_bug ("no check_secret_key() for %d\n", id);
96   return GPG_ERR_PUBKEY_ALGO;
97 }
98
99 static gpg_err_code_t
100 dummy_encrypt (int id, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, int flags)
101 {
102   log_bug ("no encrypt() for %d\n", id);
103   return GPG_ERR_PUBKEY_ALGO;
104 }
105
106 static gpg_err_code_t
107 dummy_decrypt (int id, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags)
108 {
109   log_bug ("no decrypt() for %d\n", id);
110   return GPG_ERR_PUBKEY_ALGO;
111 }
112
113 static gpg_err_code_t
114 dummy_sign (int id, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
115 {
116   log_bug ("no sign() for %d\n", id);
117   return GPG_ERR_PUBKEY_ALGO;
118 }
119
120 static gpg_err_code_t
121 dummy_verify (int id, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
122               int (*cmp) (void *, gcry_mpi_t), void *opaquev)
123 {
124   log_bug ("no verify() for %d\n", id);
125   return GPG_ERR_PUBKEY_ALGO;
126 }
127
128 static unsigned
129 dummy_get_nbits (int id, gcry_mpi_t *pkey)
130 {
131   log_bug ("no get_nbits() for %d\n", id);
132   return 0;
133 }
134
135 /* Internal function.  Register all the pubkeys included in
136    PUBKEY_TABLE.  Returns zero on success or an error code.  */
137 static void
138 gcry_pubkey_register_default (void)
139 {
140   gpg_err_code_t err = 0;
141   int i;
142   
143   for (i = 0; (! err) && pubkey_table[i].pubkey; i++)
144     {
145 #define pubkey_use_dummy(func)                       \
146       if (! pubkey_table[i].pubkey->func)            \
147         pubkey_table[i].pubkey->func = dummy_##func;
148
149       pubkey_use_dummy (generate);
150       pubkey_use_dummy (check_secret_key);
151       pubkey_use_dummy (encrypt);
152       pubkey_use_dummy (decrypt);
153       pubkey_use_dummy (sign);
154       pubkey_use_dummy (verify);
155       pubkey_use_dummy (get_nbits);
156
157       err = _gcry_module_add (&pubkeys_registered,
158                               pubkey_table[i].pubkey->id,
159                               (void *) pubkey_table[i].pubkey, NULL);
160     }
161
162   if (err)
163     BUG ();
164 }
165
166 /* Internal callback function.  Used via _gcry_module_lookup.  */
167 static int
168 gcry_pubkey_lookup_func_name (void *spec, void *data)
169 {
170   gcry_pubkey_spec_t *pubkey = (gcry_pubkey_spec_t *) spec;
171   char *name = (char *) data;
172   char **sexp_names = pubkey->sexp_names;
173   int ret = stricmp (name, pubkey->name);
174
175   while (ret && *sexp_names)
176     ret = stricmp (name, *sexp_names++);
177
178   return ! ret;
179 }
180
181 /* Internal function.  Lookup a pubkey entry by it's name.  */
182 static gcry_module_t *
183 gcry_pubkey_lookup_name (const char *name)
184 {
185   gcry_module_t *pubkey;
186
187   pubkey = _gcry_module_lookup (pubkeys_registered, (void *) name,
188                                 gcry_pubkey_lookup_func_name);
189
190   return pubkey;
191 }
192
193 /* Public function.  Register a provided PUBKEY.  Returns zero on
194    success, in which case the chosen pubkey ID has been stored in
195    PUBKEY, or an error code.  */
196 gpg_error_t
197 gcry_pubkey_register (gcry_pubkey_spec_t *pubkey, gcry_module_t **module)
198 {
199   gpg_err_code_t err = GPG_ERR_NO_ERROR;
200   gcry_module_t *mod;
201
202   ath_mutex_lock (&pubkeys_registered_lock);
203   err = _gcry_module_add (&pubkeys_registered, 0,
204                           (void *) pubkey, &mod);
205   ath_mutex_unlock (&pubkeys_registered_lock);
206
207   if (! err)
208     {
209       *module = mod;
210       pubkey->id = mod->id;
211     }
212
213   return err;
214 }
215
216 /* Public function.  Unregister the pubkey identified by ID, which
217    must have been registered with gcry_pubkey_register.  */
218 void
219 gcry_pubkey_unregister (gcry_module_t *module)
220 {
221   ath_mutex_lock (&pubkeys_registered_lock);
222   _gcry_module_release (module);
223   ath_mutex_unlock (&pubkeys_registered_lock);
224 }
225
226 static void
227 release_mpi_array (gcry_mpi_t *array)
228 {
229   for (; *array; array++)
230     {
231       mpi_free(*array);
232       *array = NULL;
233     }
234 }
235
236 /****************
237  * Map a string to the pubkey algo
238  */
239 int
240 gcry_pk_map_name (const char *string)
241 {
242   gcry_module_t *pubkey;
243   int id = 0;
244
245   REGISTER_DEFAULT_PUBKEYS;
246
247   ath_mutex_lock (&pubkeys_registered_lock);
248   pubkey = gcry_pubkey_lookup_name (string);
249   if (pubkey)
250     {
251       id = ((gcry_pubkey_spec_t *) pubkey->spec)->id;
252       _gcry_module_release (pubkey);
253     }
254   ath_mutex_unlock (&pubkeys_registered_lock);
255
256   return id;
257 }
258
259
260 /****************
261  * Map a pubkey algo to a string
262  */
263 const char *
264 gcry_pk_algo_name (int id)
265 {
266   const char *name = NULL;
267   gcry_module_t *pubkey;
268
269   REGISTER_DEFAULT_PUBKEYS;
270
271   ath_mutex_lock (&pubkeys_registered_lock);
272   pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
273   if (pubkey)
274     {
275       name = ((gcry_pubkey_spec_t *) pubkey->spec)->name;
276       _gcry_module_release (pubkey);
277     }
278   ath_mutex_unlock (&pubkeys_registered_lock);
279
280   return name;
281 }
282
283
284 static void
285 disable_pubkey_algo (int id)
286 {
287   gcry_module_t *pubkey;
288
289   ath_mutex_lock (&pubkeys_registered_lock);
290   pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
291   if (pubkey)
292     {
293       if (! (pubkey-> flags & FLAG_MODULE_DISABLED))
294         pubkey->flags |= FLAG_MODULE_DISABLED;
295       _gcry_module_release (pubkey);
296     }
297   ath_mutex_unlock (&pubkeys_registered_lock);
298 }
299
300
301 /****************
302  * a use of 0 means: don't care
303  */
304 static gpg_err_code_t
305 check_pubkey_algo (int id, unsigned use)
306 {
307   gpg_err_code_t err = GPG_ERR_NO_ERROR;
308   gcry_pubkey_spec_t *pubkey;
309   gcry_module_t *module;
310
311   REGISTER_DEFAULT_PUBKEYS;
312
313   ath_mutex_lock (&pubkeys_registered_lock);
314   module = _gcry_module_lookup_id (pubkeys_registered, id);
315   if (module)
316     {
317       pubkey = (gcry_pubkey_spec_t *) module->spec;
318
319       if (((use & GCRY_PK_USAGE_SIGN)
320            && (! (pubkey->use & GCRY_PK_USAGE_SIGN)))
321           || ((use & GCRY_PK_USAGE_ENCR)
322               && (! (pubkey->use & GCRY_PK_USAGE_ENCR))))
323         err = GPG_ERR_WRONG_PUBKEY_ALGO;
324       else if (module->flags & FLAG_MODULE_DISABLED)
325         err = GPG_ERR_PUBKEY_ALGO;
326       _gcry_module_release (module);
327     }
328   else
329     err = GPG_ERR_PUBKEY_ALGO;
330   ath_mutex_unlock (&pubkeys_registered_lock);
331
332   return err;
333 }
334
335
336 /****************
337  * Return the number of public key material numbers
338  */
339 static int
340 pubkey_get_npkey (int id)
341 {
342   gcry_module_t *pubkey;
343   int npkey = 0;
344
345   REGISTER_DEFAULT_PUBKEYS;
346
347   ath_mutex_lock (&pubkeys_registered_lock);
348   pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
349   if (pubkey)
350     {
351       npkey = strlen (((gcry_pubkey_spec_t *) pubkey->spec)->elements_pkey);
352       _gcry_module_release (pubkey);
353     }
354   ath_mutex_unlock (&pubkeys_registered_lock);
355
356   return npkey;
357 }
358
359 /****************
360  * Return the number of secret key material numbers
361  */
362 static int
363 pubkey_get_nskey (int id)
364 {
365   gcry_module_t *pubkey;
366   int nskey = 0;
367
368   REGISTER_DEFAULT_PUBKEYS;
369
370   ath_mutex_lock (&pubkeys_registered_lock);
371   pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
372   if (pubkey)
373     {
374       nskey = strlen (((gcry_pubkey_spec_t *) pubkey->spec)->elements_skey);
375       _gcry_module_release (pubkey);
376     }
377   ath_mutex_unlock (&pubkeys_registered_lock);
378
379   return nskey;
380 }
381
382 /****************
383  * Return the number of signature material numbers
384  */
385 static int
386 pubkey_get_nsig (int id)
387 {
388   gcry_module_t *pubkey;
389   int nsig = 0;
390
391   REGISTER_DEFAULT_PUBKEYS;
392
393   ath_mutex_lock (&pubkeys_registered_lock);
394   pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
395   if (pubkey)
396     {
397       nsig = strlen (((gcry_pubkey_spec_t *) pubkey->spec)->elements_sig);
398       _gcry_module_release (pubkey);
399     }
400   ath_mutex_unlock (&pubkeys_registered_lock);
401
402   return nsig;
403 }
404
405 /****************
406  * Return the number of encryption material numbers
407  */
408 static int
409 pubkey_get_nenc (int id)
410 {
411   gcry_module_t *pubkey;
412   int nenc = 0;
413
414   REGISTER_DEFAULT_PUBKEYS;
415
416   ath_mutex_lock (&pubkeys_registered_lock);
417   pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
418   if (pubkey)
419     {
420       nenc = strlen (((gcry_pubkey_spec_t *) pubkey->spec)->elements_enc);
421       _gcry_module_release (pubkey);
422     }
423   ath_mutex_unlock (&pubkeys_registered_lock);
424
425   return nenc;
426 }
427
428
429 static gpg_err_code_t
430 pubkey_generate (int id, unsigned int nbits, unsigned long use_e,
431                  gcry_mpi_t *skey, gcry_mpi_t **retfactors)
432 {
433   gpg_err_code_t err = GPG_ERR_PUBKEY_ALGO;
434   gcry_module_t *pubkey;
435
436   REGISTER_DEFAULT_PUBKEYS;
437
438   ath_mutex_lock (&pubkeys_registered_lock);
439   pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
440   if (pubkey)
441     {
442       err = (*((gcry_pubkey_spec_t *) pubkey->spec)->generate) (id, nbits, use_e, skey,
443                                                             retfactors);
444       _gcry_module_release (pubkey);
445     }
446   ath_mutex_unlock (&pubkeys_registered_lock);
447
448   return err;
449 }
450
451 static gpg_err_code_t
452 pubkey_check_secret_key (int id, gcry_mpi_t *skey)
453 {
454   gpg_err_code_t err = GPG_ERR_PUBKEY_ALGO;
455   gcry_module_t *pubkey;
456
457   REGISTER_DEFAULT_PUBKEYS;
458
459   ath_mutex_lock (&pubkeys_registered_lock);
460   pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
461   if (pubkey)
462     {
463       err = (*((gcry_pubkey_spec_t *) pubkey->spec)->check_secret_key) (id, skey);
464       _gcry_module_release (pubkey);
465     }
466   ath_mutex_unlock (&pubkeys_registered_lock);
467
468   return err;
469 }
470
471
472 /****************
473  * This is the interface to the public key encryption.  Encrypt DATA
474  * with PKEY and put it into RESARR which should be an array of MPIs
475  * of size PUBKEY_MAX_NENC (or less if the algorithm allows this -
476  * check with pubkey_get_nenc() )
477  */
478 static gpg_err_code_t
479 pubkey_encrypt (int id, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey,
480                 int flags)
481 {
482   gcry_pubkey_spec_t *pubkey;
483   gcry_module_t *module;
484   gpg_err_code_t rc;
485   int i;
486
487   if (DBG_CIPHER)
488     {
489       log_debug ("pubkey_encrypt: algo=%d\n", id);
490       for(i = 0; i < pubkey_get_npkey (id); i++)
491         log_mpidump ("  pkey:", pkey[i]);
492       log_mpidump ("  data:", data);
493     }
494
495   ath_mutex_lock (&pubkeys_registered_lock);
496   module = _gcry_module_lookup_id (pubkeys_registered, id);
497   if (module)
498     {
499       pubkey = (gcry_pubkey_spec_t *) module->spec;
500       rc = (*pubkey->encrypt) (id, resarr, data, pkey, flags);
501       _gcry_module_release (module);
502       goto ready;
503     }
504   rc = GPG_ERR_PUBKEY_ALGO;
505
506  ready:
507   ath_mutex_unlock (&pubkeys_registered_lock);
508
509   if (!rc && DBG_CIPHER)
510     {
511       for(i = 0; i < pubkey_get_nenc (id); i++)
512         log_mpidump("  encr:", resarr[i] );
513     }
514   return rc;
515 }
516
517
518 /****************
519  * This is the interface to the public key decryption.
520  * ALGO gives the algorithm to use and this implicitly determines
521  * the size of the arrays.
522  * result is a pointer to a mpi variable which will receive a
523  * newly allocated mpi or NULL in case of an error.
524  */
525 static gpg_err_code_t
526 pubkey_decrypt (int id, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey,
527                 int flags)
528 {
529   gcry_pubkey_spec_t *pubkey;
530   gcry_module_t *module;
531   gpg_err_code_t rc;
532   int i;
533
534   *result = NULL; /* so the caller can always do a mpi_free */
535   if (DBG_CIPHER)
536     {
537       log_debug ("pubkey_decrypt: algo=%d\n", id);
538       for(i = 0; i < pubkey_get_nskey (id); i++)
539         log_mpidump ("  skey:", skey[i]);
540       for(i = 0; i < pubkey_get_nenc (id); i++)
541         log_mpidump ("  data:", data[i]);
542     }
543
544   ath_mutex_lock (&pubkeys_registered_lock);
545   module = _gcry_module_lookup_id (pubkeys_registered, id);
546   if (module)
547     {
548       pubkey = (gcry_pubkey_spec_t *) module->spec;
549       rc = (*pubkey->decrypt) (id, result, data, skey, flags);
550       _gcry_module_release (module);
551       goto ready;
552     }
553
554   rc = GPG_ERR_PUBKEY_ALGO;
555   
556  ready:
557   ath_mutex_unlock (&pubkeys_registered_lock);
558
559   if (! rc && DBG_CIPHER)
560     log_mpidump (" plain:", *result);
561
562   return rc;
563 }
564
565
566 /****************
567  * This is the interface to the public key signing.
568  * Sign data with skey and put the result into resarr which
569  * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
570  * algorithm allows this - check with pubkey_get_nsig() )
571  */
572 static gpg_err_code_t
573 pubkey_sign (int id, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey)
574 {
575   gcry_pubkey_spec_t *pubkey;
576   gcry_module_t *module;
577   gpg_err_code_t rc;
578   int i;
579
580   if (DBG_CIPHER)
581     {
582       log_debug ("pubkey_sign: algo=%d\n", id);
583       for(i = 0; i < pubkey_get_nskey (id); i++)
584         log_mpidump ("  skey:", skey[i]);
585       log_mpidump("  data:", data );
586     }
587
588   ath_mutex_lock (&pubkeys_registered_lock);
589   module = _gcry_module_lookup_id (pubkeys_registered, id);
590   if (module)
591     {
592       pubkey = (gcry_pubkey_spec_t *) module->spec;
593       rc = (*pubkey->sign) (id, resarr, data, skey);
594       _gcry_module_release (module);
595       goto ready;
596     }
597
598   rc = GPG_ERR_PUBKEY_ALGO;
599
600  ready:
601   ath_mutex_unlock (&pubkeys_registered_lock);
602
603   if (! rc && DBG_CIPHER)
604     for (i = 0; i < pubkey_get_nsig (id); i++)
605       log_mpidump ("   sig:", resarr[i]);
606
607   return rc;
608 }
609
610 /****************
611  * Verify a public key signature.
612  * Return 0 if the signature is good
613  */
614 static gpg_err_code_t
615 pubkey_verify (int id, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
616                int (*cmp)(void *, gcry_mpi_t), void *opaquev)
617 {
618   gcry_pubkey_spec_t *pubkey;
619   gcry_module_t *module;
620   gpg_err_code_t rc;
621   int i;
622
623   if (DBG_CIPHER)
624     {
625       log_debug ("pubkey_verify: algo=%d\n", id);
626       for (i = 0; i < pubkey_get_npkey (id); i++)
627         log_mpidump ("  pkey:", pkey[i]);
628       for (i = 0; i < pubkey_get_nsig (id); i++)
629         log_mpidump ("   sig:", data[i]);
630       log_mpidump ("  hash:", hash);
631     }
632
633   ath_mutex_lock (&pubkeys_registered_lock);
634   module = _gcry_module_lookup_id (pubkeys_registered, id);
635   if (module)
636     {
637       pubkey = (gcry_pubkey_spec_t *) module->spec;
638       rc = (*pubkey->verify) (id, hash, data, pkey, cmp, opaquev);
639       _gcry_module_release (module);
640       goto ready;
641     }
642
643   rc = GPG_ERR_PUBKEY_ALGO;
644
645  ready:
646   ath_mutex_unlock (&pubkeys_registered_lock);
647   return rc;
648 }
649
650 /* Internal function.   */
651 static gpg_err_code_t
652 sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
653                        gcry_mpi_t *elements)
654 {
655   gpg_err_code_t err = GPG_ERR_NO_ERROR;
656   int i, index;
657   const char *name;
658   gcry_sexp_t list;
659
660   for (name = element_names, index = 0; *name && (! err); name++, index++)
661     {
662       list = gcry_sexp_find_token (key_sexp, name, 1);
663       if (! list)
664         err = GPG_ERR_NO_OBJ;
665       else
666         {
667           elements[index] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
668           gcry_sexp_release (list);
669           if (! elements[index])
670             err = GPG_ERR_INV_OBJ;
671         }
672     }
673
674   if (err)
675     for (i = 0; i < index; i++)
676       if (elements[i])
677         gcry_free (elements[i]);
678
679   return err;
680 }
681
682 /****************
683  * Convert a S-Exp with either a private or a public key to our
684  * internal format. Currently we do only support the following
685  * algorithms:
686  *    dsa
687  *    rsa
688  *    openpgp-dsa
689  *    openpgp-rsa
690  *    openpgp-elg
691  *    openpgp-elg-sig
692  * Provide a SE with the first element be either "private-key" or
693  * or "public-key". the followed by a list with its first element
694  * be one of the above algorithm identifiers and the following
695  * elements are pairs with parameter-id and value.
696  * NOTE: we look through the list to find a list beginning with
697  * "private-key" or "public-key" - the first one found is used.
698  *
699  * FIXME: Allow for encrypted secret keys here.
700  *
701  * Returns: A pointer to an allocated array of MPIs if the return value is
702  *          zero; the caller has to release this array.
703  *
704  * Example of a DSA public key:
705  *  (private-key
706  *    (dsa
707  *      (p <mpi>)
708  *      (g <mpi>)
709  *      (y <mpi>)
710  *      (x <mpi>)
711  *    )
712  *  )
713  * The <mpi> are expected to be in GCRYMPI_FMT_USG
714  */
715 static gpg_err_code_t
716 sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray,
717              gcry_module_t **retalgo)
718 {
719     gcry_sexp_t list, l2;
720     const char *name;
721     size_t n;
722     int algo;
723     const char *elems;
724     gcry_mpi_t *array;
725     gpg_err_code_t err = GPG_ERR_NO_ERROR;
726     gcry_module_t *module;
727     gcry_pubkey_spec_t *pubkey;
728
729     /* check that the first element is valid */
730     list = gcry_sexp_find_token( sexp, want_private? "private-key"
731                                                     :"public-key", 0 );
732     if( !list )
733         return GPG_ERR_INV_OBJ; /* Does not contain a public- or private-key object */
734     l2 = gcry_sexp_cadr( list );
735     gcry_sexp_release ( list );
736     list = l2;
737     name = gcry_sexp_nth_data( list, 0, &n );
738     if( !name ) {
739         gcry_sexp_release ( list );
740         return GPG_ERR_INV_OBJ; /* invalid structure of object */
741     }
742
743     {
744       char *name_terminated = gcry_xmalloc (n + 1);
745       strncpy (name_terminated, name, n);
746       name_terminated[n] = 0;
747
748       ath_mutex_lock (&pubkeys_registered_lock);
749       module = gcry_pubkey_lookup_name (name_terminated);
750       ath_mutex_unlock (&pubkeys_registered_lock);
751
752       free (name_terminated);
753     }
754
755     if (! module)
756       {
757         gcry_sexp_release (list);
758         return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
759       }
760     else
761       pubkey = (gcry_pubkey_spec_t *) module->spec;
762
763     algo = pubkey->id;
764     elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey;
765     array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
766     if (! array)
767       err = gpg_err_code_from_errno (errno);
768     if (! err)
769       err = sexp_elements_extract (list, elems, array);
770
771     if (list)
772       gcry_sexp_release (list);
773
774     if (err)
775       {
776         if (array)
777           gcry_free (array);
778
779         ath_mutex_lock (&pubkeys_registered_lock);
780         _gcry_module_release (module);
781         ath_mutex_unlock (&pubkeys_registered_lock);
782       }
783     else
784       {
785         *retarray = array;
786         *retalgo = module;
787       }
788
789     return err;
790 }
791
792 static gpg_err_code_t
793 sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray,
794              gcry_module_t **retalgo)
795 {
796     gcry_sexp_t list, l2;
797     const char *name;
798     size_t n;
799     int algo;
800     const char *elems;
801     gcry_mpi_t *array;
802     gpg_err_code_t err = GPG_ERR_NO_ERROR;
803     gcry_module_t *module;
804     gcry_pubkey_spec_t *pubkey;
805
806     /* check that the first element is valid */
807     list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
808     if( !list )
809         return GPG_ERR_INV_OBJ; /* Does not contain a signature value object */
810     l2 = gcry_sexp_cadr( list );
811     gcry_sexp_release ( list );
812     list = l2;
813     if( !list )
814         return GPG_ERR_NO_OBJ; /* no cadr for the sig object */
815     name = gcry_sexp_nth_data( list, 0, &n );
816     if( !name ) {
817         gcry_sexp_release ( list );
818         return GPG_ERR_INV_OBJ; /* invalid structure of object */
819     }
820
821     {
822       char *name_terminated = gcry_xmalloc (n + 1);
823       strncpy (name_terminated, name, n);
824       name_terminated[n] = 0;
825       
826       ath_mutex_lock (&pubkeys_registered_lock);
827       module = gcry_pubkey_lookup_name (name_terminated);
828       ath_mutex_unlock (&pubkeys_registered_lock);
829
830       free (name_terminated);
831     }
832
833     if (! module)
834       {
835         gcry_sexp_release (list);
836         return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
837       }
838     else
839       pubkey = (gcry_pubkey_spec_t *) module->spec;
840
841     algo = pubkey->id;
842     elems = pubkey->elements_sig;
843     array = gcry_calloc (strlen (elems) + 1 , sizeof (*array));
844     if (! array)
845       err = gpg_err_code_from_errno (errno);
846
847     if (! err)
848       err = sexp_elements_extract (list, elems, array);
849
850     if (list)
851       gcry_sexp_release (list);
852
853     if (err)
854       {
855         ath_mutex_lock (&pubkeys_registered_lock);
856         _gcry_module_release (module);
857         ath_mutex_unlock (&pubkeys_registered_lock);
858
859         if (array)
860           gcry_free (array);
861       }
862     else
863       {
864         *retarray = array;
865         *retalgo = module;
866       }
867
868     return err;
869 }
870
871
872 /****************
873  * Take sexp and return an array of MPI as used for our internal decrypt
874  * function.
875  * s_data = (enc-val
876  *           [(flags [pkcs1])
877  *            (<algo>
878  *              (<param_name1> <mpi>)
879  *              ...
880  *              (<param_namen> <mpi>)
881  *            ))
882  * RET_MODERN is set to true when at least an empty flags list has been found.
883  */
884 static gpg_err_code_t
885 sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t **retalgo,
886              int *ret_modern, int *ret_want_pkcs1, int *flags)
887 {
888   gcry_sexp_t list = NULL, l2 = NULL;
889   gcry_pubkey_spec_t *pubkey = NULL;
890   gcry_module_t *module = NULL;
891   const char *name;
892   size_t n;
893   int parsed_flags = 0;
894   const char *elems;
895   gcry_mpi_t *array = NULL;
896   gpg_err_code_t err = GPG_ERR_NO_ERROR;
897
898   *ret_want_pkcs1 = 0;
899   *ret_modern = 0;
900
901   /* check that the first element is valid */
902   list = gcry_sexp_find_token (sexp, "enc-val" , 0);
903   if (! list)
904     err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object */
905
906   if (! err)
907     {
908       l2 = gcry_sexp_nth (list, 1);
909       if (! l2)
910         err = GPG_ERR_NO_OBJ; /* no cdr for the data object */
911     }
912
913   if (! err)
914     {
915       /* Extract the name of the algorithm.  */
916       name = gcry_sexp_nth_data (l2, 0, &n);
917       if (! name)
918         err = GPG_ERR_INV_OBJ; /* invalid structure of object */
919     }
920
921   if ((! err) && (n == 5) && (! memcmp (name, "flags", 5)))
922     {
923       /* There is a flags element - process it */
924       const char *s;
925       int i;
926
927       *ret_modern = 1;
928       for (i = gcry_sexp_length (l2) - 1; i > 0 && (! err); i--)
929         {
930           s = gcry_sexp_nth_data (l2, i, &n);
931           if (! s)
932             ; /* not a data element - ignore */
933           else if (n == 3 && ! memcmp (s, "raw", 3))
934             ; /* just a dummy because it is the default */
935           else if (n == 5 && ! memcmp (s, "pkcs1", 5))
936             *ret_want_pkcs1 = 1;
937           else if (n == 11 && ! memcmp (s, "no-blinding", 11))
938             parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
939           else
940             err = GPG_ERR_INV_FLAG;
941         }
942     }
943
944   if (! err)
945     {
946       /* Get the next which has the actual data */
947       gcry_sexp_release (l2);
948       l2 = gcry_sexp_nth (list, 2);
949       if (! l2)
950         err = GPG_ERR_NO_OBJ; /* no cdr for the data object */
951     }
952
953   if (! err)
954     {
955       name = gcry_sexp_nth_data (l2, 0, &n);
956       if (! name)
957         err = GPG_ERR_INV_OBJ; /* invalid structure of object */
958       else
959         {
960           gcry_sexp_release (list);
961           list = l2;
962           l2 = NULL;
963         }
964     }
965
966   if (! err)
967     {
968       char *name_terminated = gcry_xmalloc (n + 1);
969       strncpy (name_terminated, name, n);
970       name_terminated[n] = 0;
971
972       ath_mutex_lock (&pubkeys_registered_lock);
973       module = gcry_pubkey_lookup_name (name_terminated);
974       ath_mutex_unlock (&pubkeys_registered_lock);
975
976       free (name_terminated);
977
978       if (! module)
979         err = GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
980       else
981         pubkey = (gcry_pubkey_spec_t *) module->spec;
982     }
983
984   if (! err)
985     {
986       elems = pubkey->elements_enc;
987       array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
988       if (! array)
989         err = gpg_err_code_from_errno (errno);
990     }
991
992   if (! err)
993     err = sexp_elements_extract (list, elems, array);
994
995   if (list)
996     gcry_sexp_release (list);
997   if (l2)
998     gcry_sexp_release (l2);
999
1000   if (err)
1001     {
1002       ath_mutex_lock (&pubkeys_registered_lock);
1003       _gcry_module_release (module);
1004       ath_mutex_unlock (&pubkeys_registered_lock);
1005       if (array)
1006         gcry_free (array);
1007     }
1008   else
1009     {
1010       *retarray = array;
1011       *retalgo = module;
1012       *flags = parsed_flags;
1013     }
1014
1015   return err;
1016 }
1017
1018 /* Take the hash value and convert into an MPI, suitable for for
1019    passing to the low level functions.  We currently support the
1020    old style way of passing just a MPI and the modern interface which
1021    allows to pass flags so that we can choose between raw and pkcs1
1022    padding - may be more padding options later. 
1023
1024    (<mpi>)
1025    or
1026    (data
1027     [(flags [pkcs1])]
1028     [(hash <algo> <value>)]
1029     [(value <text>)]
1030    )
1031    
1032    Either the VALUE or the HASH element must be present for use
1033    with signatures.  VALUE is used for encryption.
1034
1035    NBITS is the length of the key in bits. 
1036
1037 */
1038 static gpg_err_code_t
1039 sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi,
1040                   int for_encryption, int *flags)
1041 {
1042   gpg_err_code_t rc = 0;
1043   gcry_sexp_t ldata, lhash, lvalue;
1044   int i;
1045   size_t n;
1046   const char *s;
1047   int is_raw = 0, is_pkcs1 = 0, unknown_flag=0; 
1048   int parsed_flags = 0, dummy_flags;
1049
1050   if (! flags)
1051     flags = &dummy_flags;
1052   
1053   *ret_mpi = NULL;
1054   ldata = gcry_sexp_find_token (input, "data", 0);
1055   if (!ldata)
1056     { /* assume old style */
1057       *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0);
1058       return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
1059     }
1060
1061   /* see whether there is a flags object */
1062   {
1063     gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0);
1064     if (lflags)
1065       { /* parse the flags list. */
1066         for (i=gcry_sexp_length (lflags)-1; i > 0; i--)
1067           {
1068             s = gcry_sexp_nth_data (lflags, i, &n);
1069             if (!s)
1070               ; /* not a data element*/
1071             else if ( n == 3 && !memcmp (s, "raw", 3))
1072               is_raw = 1;
1073             else if ( n == 5 && !memcmp (s, "pkcs1", 5))
1074               is_pkcs1 = 1;
1075             else if (n == 11 && ! memcmp (s, "no-blinding", 11))
1076               parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
1077             else
1078               unknown_flag = 1;
1079           }
1080         gcry_sexp_release (lflags);
1081       }
1082   }
1083
1084   if (!is_pkcs1 && !is_raw)
1085     is_raw = 1; /* default to raw */
1086
1087   /* Get HASH or MPI */
1088   lhash = gcry_sexp_find_token (ldata, "hash", 0);
1089   lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0);
1090
1091   if (!(!lhash ^ !lvalue))
1092     rc = GPG_ERR_INV_OBJ; /* none or both given */
1093   else if (unknown_flag)
1094     rc = GPG_ERR_INV_FLAG;
1095   else if (is_raw && is_pkcs1 && !for_encryption)
1096     rc = GPG_ERR_CONFLICT;
1097   else if (is_raw && lvalue)
1098     {
1099       *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, 0);
1100       if (!*ret_mpi)
1101         rc = GPG_ERR_INV_OBJ;
1102     }
1103   else if (is_pkcs1 && lvalue && for_encryption)
1104     { /* create pkcs#1 block type 2 padding */
1105       unsigned char *frame = NULL;
1106       size_t nframe = (nbits+7) / 8;
1107       const void * value;
1108       size_t valuelen;
1109       unsigned char *p;
1110
1111       if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
1112         rc = GPG_ERR_INV_OBJ;
1113       else if (valuelen + 7 > nframe || !nframe)
1114         {
1115           /* Can't encode a VALUELEN value in a NFRAME bytes frame. */
1116           rc = GPG_ERR_TOO_SHORT; /* the key is too short */
1117         }
1118       else if ( !(frame = gcry_malloc_secure (nframe)))
1119         rc = gpg_err_code_from_errno (errno);
1120       else
1121         {
1122           n = 0;
1123           frame[n++] = 0;
1124           frame[n++] = 2; /* block type */
1125           i = nframe - 3 - valuelen;
1126           assert (i > 0);
1127           p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
1128           /* replace zero bytes by new values*/
1129           for (;;)
1130             {
1131               int j, k;
1132               unsigned char *pp;
1133               
1134               /* count the zero bytes */
1135               for (j=k=0; j < i; j++)
1136                 {
1137                   if (!p[j])
1138                     k++;
1139                 }
1140               if (!k)
1141                 break; /* okay: no (more) zero bytes */
1142               
1143               k += k/128; /* better get some more */
1144               pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
1145               for (j=0; j < i && k; j++)
1146                 {
1147                   if (!p[j])
1148                     p[j] = pp[--k];
1149                 }
1150               gcry_free (pp);
1151             }
1152           memcpy (frame+n, p, i);
1153           n += i;
1154           gcry_free (p);
1155           
1156           frame[n++] = 0;
1157           memcpy (frame+n, value, valuelen);
1158           n += valuelen;
1159           assert (n == nframe);
1160
1161           /* FIXME, error checking?  */
1162           gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, &nframe);
1163         }
1164
1165       gcry_free(frame);
1166     }
1167   else if (is_pkcs1 && lhash && !for_encryption)
1168     { /* create pkcs#1 block type 1 padding */
1169       if (gcry_sexp_length (lhash) != 3)
1170         rc = GPG_ERR_INV_OBJ;
1171       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
1172         rc = GPG_ERR_INV_OBJ;
1173       else
1174         {
1175           static struct { const char *name; int algo; } hashnames[] = 
1176           { { "sha1",   GCRY_MD_SHA1 },
1177             { "md5",    GCRY_MD_MD5 },
1178             { "rmd160", GCRY_MD_RMD160 },
1179             { "sha256", GCRY_MD_SHA256 },
1180             { "sha384", GCRY_MD_SHA384 },
1181             { "sha512", GCRY_MD_SHA512 },
1182             { "md2",    GCRY_MD_MD2 },
1183             { "md4",    GCRY_MD_MD4 },
1184             { "tiger",  GCRY_MD_TIGER },
1185             { "haval",  GCRY_MD_HAVAL },
1186             { NULL }
1187           };
1188           int algo;
1189           byte asn[100];
1190           byte *frame = NULL;
1191           size_t nframe = (nbits+7) / 8;
1192           const void * value;
1193           size_t valuelen;
1194           size_t asnlen, dlen;
1195             
1196           for (i=0; hashnames[i].name; i++)
1197             {
1198               if ( strlen (hashnames[i].name) == n
1199                    && !memcmp (hashnames[i].name, s, n))
1200                 break;
1201             }
1202
1203           algo = hashnames[i].algo;
1204           asnlen = DIM(asn);
1205           dlen = gcry_md_get_algo_dlen (algo);
1206
1207           if (!hashnames[i].name)
1208             rc = GPG_ERR_DIGEST_ALGO;
1209           else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
1210                     || !valuelen )
1211             rc = GPG_ERR_INV_OBJ;
1212           else if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
1213             rc = GPG_ERR_NOT_IMPLEMENTED; /* we don't have all of the above algos */
1214           else if ( valuelen != dlen )
1215             {
1216               /* hash value does not match the length of digest for
1217                  the given algo */
1218               rc = GPG_ERR_CONFLICT;
1219             }
1220           else if( !dlen || dlen + asnlen + 4 > nframe)
1221             {
1222               /* can't encode an DLEN byte digest MD into a NFRAME byte frame */
1223               rc = GPG_ERR_TOO_SHORT;
1224             }
1225           else if ( !(frame = gcry_malloc (nframe)) )
1226             rc = gpg_err_code_from_errno (errno);
1227           else
1228             { /* assemble the pkcs#1 block type 1 */
1229               n = 0;
1230               frame[n++] = 0;
1231               frame[n++] = 1; /* block type */
1232               i = nframe - valuelen - asnlen - 3 ;
1233               assert (i > 1);
1234               memset (frame+n, 0xff, i );
1235               n += i;
1236               frame[n++] = 0;
1237               memcpy (frame+n, asn, asnlen);
1238               n += asnlen;
1239               memcpy (frame+n, value, valuelen );
1240               n += valuelen;
1241               assert (n == nframe);
1242       
1243               /* convert it into an MPI, FIXME: error checking?  */
1244               gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, &nframe);
1245             }
1246           
1247           gcry_free (frame);
1248         }
1249     }
1250   else
1251     rc = GPG_ERR_CONFLICT;
1252    
1253   gcry_sexp_release (ldata);
1254   gcry_sexp_release (lhash);
1255   gcry_sexp_release (lvalue);
1256
1257   if (! rc)
1258     *flags = parsed_flags;
1259
1260   return rc;
1261 }
1262
1263
1264 /*
1265    Do a PK encrypt operation
1266   
1267    Caller has to provide a public key as the SEXP pkey and data as a
1268    SEXP with just one MPI in it. Alternativly S_DATA might be a
1269    complex S-Expression, similar to the one used for signature
1270    verification.  This provides a flag which allows to handle PKCS#1
1271    block type 2 padding.  The function returns a a sexp which may be
1272    passed to to pk_decrypt.
1273   
1274    Returns: 0 or an errorcode.
1275   
1276    s_data = See comment for sexp_data_to_mpi
1277    s_pkey = <key-as-defined-in-sexp_to_key>
1278    r_ciph = (enc-val
1279                (<algo>
1280                  (<param_name1> <mpi>)
1281                  ...
1282                  (<param_namen> <mpi>)
1283                ))
1284
1285 */
1286 gpg_error_t
1287 gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
1288 {
1289   gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL;
1290   const char *algo_name, *algo_elems;
1291   int flags;
1292   gpg_err_code_t rc;
1293   gcry_pubkey_spec_t *pubkey = NULL;
1294   gcry_module_t *module = NULL;
1295
1296   REGISTER_DEFAULT_PUBKEYS;
1297
1298   *r_ciph = NULL;
1299   /* get the key */
1300   rc = sexp_to_key (s_pkey, 0, &pkey, &module);
1301   if (! rc)
1302     {
1303       assert (module);
1304       pubkey = (gcry_pubkey_spec_t *) module->spec;
1305       algo_name = pubkey->name;
1306       algo_elems = pubkey->elements_enc;
1307       
1308       /* get the stuff we want to encrypt */
1309       rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1,
1310                              &flags);
1311     }
1312
1313   if (! rc)
1314     {
1315       /* Now we can encrypt data to ciph */
1316       ciph = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*ciph));
1317       rc = pubkey_encrypt (pubkey->id, ciph, data, pkey, flags);
1318       mpi_free (data);
1319     }
1320
1321   /* We did it.  Now build the return list */
1322   if (! rc)
1323     {
1324       char *string, *p;
1325       int i;
1326       size_t nelem = strlen (algo_elems);
1327       size_t needed = 19 + strlen (algo_name) + (nelem * 5);
1328
1329       if (flags & PUBKEY_FLAG_NO_BLINDING)
1330         needed += 12;
1331
1332       /* Build the string.  */
1333       string = p = gcry_xmalloc (needed);
1334       p = stpcpy ( p, "(enc-val(flags" );
1335       if (flags & PUBKEY_FLAG_NO_BLINDING)
1336         p = stpcpy (p, " no-blinding");
1337       p = stpcpy (p, ")(");
1338       p = stpcpy ( p, algo_name );
1339       for(i=0; algo_elems[i]; i++ ) {
1340         *p++ = '(';
1341         *p++ = algo_elems[i];
1342         p = stpcpy ( p, "%m)" );
1343       }
1344       strcpy ( p, "))" );
1345
1346       /* and now the ugly part:  we don't have a function to
1347        * pass an array to a format string, so we have to do it this way :-(
1348        */
1349
1350       {
1351         int i;
1352         void **arg_list = malloc (sizeof (void *) * nelem);
1353         if (arg_list)
1354           {
1355             for (i = 0; i < nelem; i++)
1356               arg_list[i] = &ciph[i];
1357
1358             rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list);
1359
1360             free (arg_list);
1361           }
1362         else
1363           rc = gpg_err_code_from_errno (errno);
1364       }
1365
1366       if (rc)
1367         BUG ();
1368       gcry_free (string);
1369     }
1370
1371   if (ciph)
1372     {
1373       release_mpi_array (ciph);
1374       gcry_free (ciph);
1375     }
1376
1377   if (module)
1378     {
1379       ath_mutex_lock (&pubkeys_registered_lock);
1380       _gcry_module_release (module);
1381       ath_mutex_unlock (&pubkeys_registered_lock);
1382     }
1383
1384   return gpg_error (rc);
1385 }
1386
1387 /****************
1388  * Do a PK decrypt operation
1389  *
1390  * Caller has to provide a secret key as the SEXP skey and data in a
1391  * format as created by gcry_pk_encrypt.  For historic reasons the
1392  * function returns simply an MPI as an S-expression part; this is
1393  * deprecated and the new method should be used which returns a real
1394  * S-expressionl this is selected by adding at least an empty flags
1395  * list to S_DATA.
1396  * 
1397  * Returns: 0 or an errorcode.
1398  *
1399  * s_data = (enc-val
1400  *            [(flags)]
1401  *            (<algo>
1402  *              (<param_name1> <mpi>)
1403  *              ...
1404  *              (<param_namen> <mpi>)
1405  *            ))
1406  * s_skey = <key-as-defined-in-sexp_to_key>
1407  * r_plain= Either an incomplete S-expression without the parentheses
1408  *          or if the flags list is used (even if empty) a real S-expression:
1409  *          (value PLAIN).  */
1410 gpg_error_t
1411 gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
1412 {
1413   gcry_mpi_t *skey = NULL, *data = NULL, plain = NULL;
1414   int modern, want_pkcs1, flags;
1415   gpg_err_code_t rc;
1416   gcry_module_t *module_enc = NULL, *module_key = NULL;
1417   gcry_pubkey_spec_t *pubkey = NULL;
1418
1419   REGISTER_DEFAULT_PUBKEYS;
1420
1421   *r_plain = NULL;
1422   rc = sexp_to_key (s_skey, 1, &skey, &module_key);
1423
1424   if (! rc)
1425     rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &want_pkcs1, &flags);
1426
1427   if (! rc)
1428     {
1429       if (((gcry_pubkey_spec_t *) module_key->spec)->id
1430           != ((gcry_pubkey_spec_t *) module_enc->spec)->id)
1431         rc = GPG_ERR_CONFLICT; /* key algo does not match data algo */
1432       else
1433         pubkey = (gcry_pubkey_spec_t *) module_key->spec;
1434     }
1435
1436   if (! rc)
1437     rc = pubkey_decrypt (pubkey->id, &plain, data, skey, flags);
1438
1439   if (! rc)
1440     {
1441       if (! modern)
1442         {
1443           if (gcry_sexp_build (r_plain, NULL, "%m", plain))
1444             BUG ();
1445         }
1446       else
1447         {
1448           if (gcry_sexp_build (r_plain, NULL, "(value %m)", plain))
1449             BUG ();
1450         }
1451     }
1452
1453   if (skey)
1454     {
1455       release_mpi_array (skey);
1456       gcry_free (skey);
1457     }
1458
1459   if (plain)
1460     mpi_free (plain);
1461
1462   if (data)
1463     {
1464       release_mpi_array (data);
1465       gcry_free (data);
1466     }
1467
1468   if (module_key || module_enc)
1469     {
1470       ath_mutex_lock (&pubkeys_registered_lock);
1471       if (module_key)
1472         _gcry_module_release (module_key);
1473       if (module_enc)
1474         _gcry_module_release (module_enc);
1475       ath_mutex_unlock (&pubkeys_registered_lock);
1476     }
1477
1478   return gpg_error (rc);
1479 }
1480
1481
1482
1483 /****************
1484  * Create a signature.
1485  *
1486  * Caller has to provide a secret key as the SEXP skey and data
1487  * expressed as a SEXP list hash with only one element which should
1488  * instantly be available as a MPI. Alternatively the structure given
1489  * below may be used for S_HASH, it provides the abiliy to pass flags
1490  * to the operation; the only flag defined by now is "pkcs1" which
1491  * does PKCS#1 block type 1 style padding.
1492  *
1493  * Returns: 0 or an errorcode.
1494  *          In case of 0 the function returns a new SEXP with the
1495  *          signature value; the structure of this signature depends on the
1496  *          other arguments but is always suitable to be passed to
1497  *          gcry_pk_verify
1498  *
1499  * s_hash = See comment for sexp_data_to_mpi
1500  *             
1501  * s_skey = <key-as-defined-in-sexp_to_key>
1502  * r_sig  = (sig-val
1503  *            (<algo>
1504  *              (<param_name1> <mpi>)
1505  *              ...
1506  *              (<param_namen> <mpi>)
1507  * )) */
1508 gpg_error_t
1509 gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
1510 {
1511   gcry_mpi_t *skey = NULL, hash = NULL, *result = NULL;
1512   gcry_pubkey_spec_t *pubkey = NULL;
1513   gcry_module_t *module = NULL;
1514   const char *key_algo_name, *algo_name, *algo_elems;
1515   int i;
1516   gpg_err_code_t rc;
1517
1518
1519   REGISTER_DEFAULT_PUBKEYS;
1520
1521   *r_sig = NULL;
1522   rc = sexp_to_key (s_skey, 1, &skey, &module);
1523
1524   if (! rc)
1525     {
1526       assert (module);
1527       pubkey = (gcry_pubkey_spec_t *) module->spec;
1528       algo_name = key_algo_name = pubkey->name;
1529
1530       algo_elems = pubkey->elements_sig;
1531
1532       /* get the stuff we want to sign */
1533       /* Note that pk_get_nbits does also work on a private key */
1534       rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey), &hash, 0, NULL);
1535     }
1536
1537   if (! rc)
1538     {
1539       result = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*result));
1540       rc = pubkey_sign (pubkey->id, result, hash, skey);
1541     }
1542
1543   if (! rc)
1544     {
1545       char *string, *p;
1546       size_t nelem, needed = strlen (algo_name) + 20;
1547
1548       nelem = strlen (algo_elems);
1549
1550       /* count elements, so that we can allocate enough space */
1551       needed += 10 * nelem;
1552
1553       /* build the string */
1554       string = p = gcry_xmalloc (needed);
1555       p = stpcpy (p, "(sig-val(");
1556       p = stpcpy (p, algo_name);
1557       for(i = 0; algo_elems[i]; i++)
1558         {
1559           *p++ = '(';
1560           *p++ = algo_elems[i];
1561           p = stpcpy (p, "%m)");
1562         }
1563       strcpy (p, "))");
1564
1565       {
1566         int i;
1567         void **arg_list = malloc (sizeof (void *) * nelem);
1568         if (arg_list)
1569           {
1570             for (i = 0; i < nelem; i++)
1571               arg_list[i] = &result[i];
1572
1573             rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list);
1574
1575             free (arg_list);
1576           }
1577         else
1578           rc = gpg_err_code_from_errno (errno);
1579       }
1580
1581       if (rc)
1582         BUG ();
1583       gcry_free (string);
1584     }
1585
1586   if (skey)
1587     {
1588       release_mpi_array (skey);
1589       gcry_free (skey);
1590     }
1591
1592   if (hash)
1593     mpi_free (hash);
1594
1595   if (result)
1596     gcry_free (result);
1597
1598   return gpg_error (rc);
1599 }
1600
1601
1602 /****************
1603  * Verify a signature.  Caller has to supply the public key pkey, the
1604  * signature sig and his hashvalue data.  Public key has to be a
1605  * standard public key given as an S-Exp, sig is a S-Exp as returned
1606  * from gcry_pk_sign and data must be an S-Exp like the one in sign
1607  * too.
1608  */
1609 gpg_error_t
1610 gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
1611 {
1612   gcry_module_t *module_key = NULL, *module_sig = NULL;
1613   gcry_mpi_t *pkey = NULL, hash = NULL, *sig = NULL;
1614   gpg_err_code_t rc;
1615
1616   REGISTER_DEFAULT_PUBKEYS;
1617  
1618   rc = sexp_to_key (s_pkey, 0, &pkey, &module_key);
1619   if (! rc)
1620     rc = sexp_to_sig (s_sig, &sig, &module_sig);
1621
1622   if ((! rc)
1623       && (((gcry_pubkey_spec_t *) module_key->spec)->id
1624           != ((gcry_pubkey_spec_t *) module_sig->spec)->id))
1625     rc = GPG_ERR_CONFLICT;
1626
1627   if (! rc)
1628     rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0);
1629
1630   if (! rc)
1631     rc = pubkey_verify (((gcry_pubkey_spec_t *) module_key->spec)->id,
1632                         hash, sig, pkey, NULL, NULL);
1633
1634   if (pkey)
1635     {
1636       release_mpi_array (pkey);
1637       gcry_free (pkey);
1638     }
1639   if (sig)
1640     {
1641       release_mpi_array (sig);
1642       gcry_free (sig);
1643     }
1644   if (hash)
1645     mpi_free (hash);
1646
1647   if (module_key || module_sig)
1648     {
1649       ath_mutex_lock (&pubkeys_registered_lock);
1650       if (module_key)
1651         _gcry_module_release (module_key);
1652       if (module_sig)
1653         _gcry_module_release (module_sig);
1654       ath_mutex_unlock (&pubkeys_registered_lock);
1655     }
1656
1657   return gpg_error (rc);
1658 }
1659
1660
1661 /****************
1662  * Test a key.  This may be used either for a public or a secret key
1663  * to see whether internal structre is valid.
1664  *
1665  * Returns: 0 or an errorcode.
1666  *
1667  * s_key = <key-as-defined-in-sexp_to_key>
1668  */
1669 gpg_error_t
1670 gcry_pk_testkey (gcry_sexp_t s_key)
1671 {
1672   gcry_module_t *module = NULL;
1673   gcry_mpi_t *key = NULL;
1674   gpg_err_code_t rc;
1675   
1676   REGISTER_DEFAULT_PUBKEYS;
1677
1678   /* Note we currently support only secret key checking */
1679   rc = sexp_to_key (s_key, 1, &key, &module);
1680   if (! rc)
1681     {
1682       rc = pubkey_check_secret_key (((gcry_pubkey_spec_t *) module->spec)->id, key);
1683       release_mpi_array (key);
1684       gcry_free (key);
1685     }
1686   return gpg_error (rc);
1687 }
1688
1689
1690 /****************
1691  * Create a public key pair and return it in r_key.
1692  * How the key is created depends on s_parms:
1693  * (genkey
1694  *  (algo
1695  *    (parameter_name_1 ....)
1696  *     ....
1697  *    (parameter_name_n ....)
1698  * ))
1699  * The key is returned in a format depending on the
1700  * algorithm. Both, private and secret keys are returned
1701  * and optionally some additional informatin.
1702  * For elgamal we return this structure:
1703  * (key-data
1704  *  (public-key
1705  *    (elg
1706  *      (p <mpi>)
1707  *      (g <mpi>)
1708  *      (y <mpi>)
1709  *    )
1710  *  )
1711  *  (private-key
1712  *    (elg
1713  *      (p <mpi>)
1714  *      (g <mpi>)
1715  *      (y <mpi>)
1716  *      (x <mpi>)
1717  *    )
1718  *  )
1719  *  (misc-key-info
1720  *     (pm1-factors n1 n2 ... nn)
1721  *  )
1722  * )
1723  */
1724 gpg_error_t
1725 gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
1726 {
1727   gcry_pubkey_spec_t *pubkey = NULL;
1728   gcry_module_t *module = NULL;
1729   gcry_sexp_t list = NULL, l2 = NULL;
1730   const char *name;
1731   size_t n;
1732   gpg_err_code_t rc = GPG_ERR_NO_ERROR;
1733   int i;
1734   const char *algo_name = NULL;
1735   int algo;
1736   const char *sec_elems = NULL, *pub_elems = NULL;
1737   gcry_mpi_t skey[10] = { NULL }, *factors = NULL;
1738   unsigned int nbits = 0;
1739   unsigned long use_e = 0;
1740
1741   REGISTER_DEFAULT_PUBKEYS;
1742
1743   *r_key = NULL;
1744   list = gcry_sexp_find_token (s_parms, "genkey", 0);
1745   if (! list)
1746     rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data */
1747
1748   if (! rc)
1749     {
1750       l2 = gcry_sexp_cadr (list);
1751       gcry_sexp_release (list);
1752       list = l2;
1753       l2 = NULL;
1754       if (! list)
1755         rc = GPG_ERR_NO_OBJ; /* no cdr for the genkey */
1756     }
1757
1758   if (! rc)
1759     {
1760       name = gcry_sexp_nth_data (list, 0, &n);
1761       if (! name)
1762         rc = GPG_ERR_INV_OBJ; /* algo string missing */
1763     }
1764
1765   if (! rc)
1766     {
1767       char *name_terminated = gcry_xmalloc (n + 1);
1768       strncpy (name_terminated, name, n);
1769       name_terminated[n] = 0;
1770
1771       ath_mutex_lock (&pubkeys_registered_lock);
1772       module = gcry_pubkey_lookup_name (name_terminated);
1773       ath_mutex_unlock (&pubkeys_registered_lock);
1774
1775       free (name_terminated);
1776
1777       if (! module)
1778         rc = GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
1779       else
1780         {
1781           pubkey = (gcry_pubkey_spec_t *) module->spec;
1782           algo = pubkey->id;
1783           algo_name = pubkey->name;
1784           pub_elems = pubkey->elements_pkey;
1785           sec_elems = pubkey->elements_skey;
1786         }
1787     }
1788
1789   if (! rc)
1790     {
1791       l2 = gcry_sexp_find_token (list, "rsa-use-e", 0);
1792       if (l2)
1793         {
1794           char buf[50];
1795
1796           name = gcry_sexp_nth_data (l2, 1, &n);
1797           if ((! name) || (n >= DIM (buf) - 1))
1798             rc = GPG_ERR_INV_OBJ; /* no value or value too large */
1799           else
1800             {
1801               memcpy (buf, name, n);
1802               buf[n] = 0;
1803               use_e = strtoul (buf, NULL, 0);
1804             }
1805           gcry_sexp_release (l2);
1806           l2 = NULL;
1807         }
1808       else
1809         use_e = 65537; /* not given, use the value generated by old versions. */
1810     }
1811
1812   if (! rc)
1813     {
1814       l2 = gcry_sexp_find_token (list, "nbits", 0);
1815       gcry_sexp_release (list);
1816       list = l2;
1817       l2 = NULL;
1818       if (! list)
1819         rc = GPG_ERR_NO_OBJ; /* no nbits parameter */
1820       else
1821         {
1822           name = gcry_sexp_nth_data (list, 1, &n);
1823           if (! name)
1824             rc = GPG_ERR_INV_OBJ; /* nbits without a cdr */
1825           else
1826             {
1827               char *p = gcry_xmalloc (n + 1);
1828               memcpy (p, name, n);
1829               p[n] = 0;
1830               nbits = (unsigned int) strtol (p, NULL, 0);
1831               gcry_free (p);
1832             }
1833         }
1834     }
1835
1836   if (! rc)
1837     rc = pubkey_generate (pubkey->id, nbits, use_e, skey, &factors);
1838
1839   if (! rc)
1840     {
1841       char *string, *p;
1842       size_t nelem=0, nelem_cp = 0, needed=0;
1843       gcry_mpi_t mpis[30];
1844
1845       nelem = strlen (pub_elems) + strlen (sec_elems);
1846       for (i = 0; factors[i]; i++)
1847         nelem++;
1848       nelem_cp = nelem;
1849
1850       needed += nelem * 10;
1851       needed += 2 * strlen (algo_name) + 300;
1852       if (nelem > DIM (mpis))
1853         BUG ();
1854
1855       /* build the string */
1856       nelem = 0;
1857       string = p = gcry_xmalloc (needed);
1858       p = stpcpy (p, "(key-data");
1859       p = stpcpy (p, "(public-key(");
1860       p = stpcpy (p, algo_name);
1861       for(i = 0; pub_elems[i]; i++)
1862         {
1863           *p++ = '(';
1864           *p++ = pub_elems[i];
1865           p = stpcpy (p, "%m)");
1866           mpis[nelem++] = skey[i];
1867         }
1868       p = stpcpy (p, "))");
1869       p = stpcpy (p, "(private-key(");
1870       p = stpcpy (p, algo_name);
1871       for (i = 0; sec_elems[i]; i++)
1872         {
1873           *p++ = '(';
1874           *p++ = sec_elems[i];
1875           p = stpcpy (p, "%m)");
1876           mpis[nelem++] = skey[i];
1877         }
1878       p = stpcpy (p, "))");
1879
1880       /* Very ugly hack to make release_mpi_array() work FIXME */
1881       skey[i] = NULL;
1882
1883       p = stpcpy (p, "(misc-key-info(pm1-factors");
1884       for(i = 0; factors[i]; i++)
1885         {
1886           p = stpcpy (p, "%m");
1887           mpis[nelem++] = factors[i];
1888         }
1889       strcpy (p, ")))");
1890
1891       while (nelem < DIM (mpis))
1892         mpis[nelem++] = NULL;
1893
1894       {
1895         int elem_n = strlen (pub_elems) + strlen (sec_elems), i;
1896         void **arg_list = malloc (sizeof (void *) * nelem_cp);
1897         if (arg_list)
1898           {
1899             for (i = 0; i < elem_n; i++)
1900               arg_list[i] = &mpis[i];
1901             for (; i < nelem_cp; i++)
1902               arg_list[i] = &factors[i - elem_n];
1903
1904             rc = gcry_sexp_build_array (r_key, NULL, string, arg_list);
1905
1906             free (arg_list);
1907           }
1908         else
1909           rc = gpg_err_code_from_errno (errno);
1910       }
1911
1912       if (rc)
1913         BUG ();
1914       assert (DIM (mpis) == 30);        /* ? */
1915       gcry_free (string);
1916     }
1917
1918   release_mpi_array (skey);
1919   /* no free:  skey is a static array */
1920
1921   if (factors)
1922     {
1923       release_mpi_array ( factors );
1924       gcry_free (factors);
1925     }
1926
1927   if (l2)
1928     gcry_sexp_release (l2);
1929   if (list)
1930     gcry_sexp_release (list);
1931
1932   if (module)
1933     {
1934       ath_mutex_lock (&pubkeys_registered_lock);
1935       _gcry_module_release (module);
1936       ath_mutex_unlock (&pubkeys_registered_lock);
1937     }
1938
1939   return gpg_error (rc);
1940 }
1941
1942 /****************
1943  * Get the number of nbits from the public key
1944  * Hmmm: Should we have really this function or is it
1945  * better to have a more general function to retrieve
1946  * different propoerties of the key?
1947  */
1948 unsigned int
1949 gcry_pk_get_nbits (gcry_sexp_t key)
1950 {
1951   gcry_module_t *module = NULL;
1952   gcry_pubkey_spec_t *pubkey;
1953   gcry_mpi_t *keyarr = NULL;
1954   unsigned int nbits = 0;
1955   gpg_err_code_t rc;
1956
1957   REGISTER_DEFAULT_PUBKEYS;
1958
1959   rc = sexp_to_key (key, 0, &keyarr, &module);
1960   if (rc == GPG_ERR_INV_OBJ)
1961     rc = sexp_to_key (key, 1, &keyarr, &module);
1962   if (rc)
1963     return 0;
1964   else
1965     {
1966       pubkey = (gcry_pubkey_spec_t *) module->spec;
1967       nbits = (*pubkey->get_nbits) (pubkey->id, keyarr);
1968
1969       ath_mutex_lock (&pubkeys_registered_lock);
1970       _gcry_module_release (module);
1971       ath_mutex_unlock (&pubkeys_registered_lock);
1972     }
1973
1974   release_mpi_array (keyarr);
1975   gcry_free (keyarr);
1976
1977   return nbits;
1978 }
1979
1980
1981 /* Return the so called KEYGRIP which is the SHA-1 hash of the public
1982    key parameters expressed in a way depended on the algorithm.
1983
1984    ARRAY must either be 20 bytes long or NULL; in the latter case a
1985    newly allocated array of that size is returned, otherwise ARRAY or
1986    NULL is returned to indicate an error which is most likely an
1987    unknown algorithm.  The function accepts public or secret keys. */
1988 unsigned char *
1989 gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
1990 {
1991   gcry_sexp_t list = NULL, l2 = NULL;
1992   gcry_pubkey_spec_t *pubkey = NULL;
1993   gcry_module_t *module = NULL;
1994   const char *s, *name;
1995   size_t n;
1996   int idx;
1997   int is_rsa;
1998   const char *elems;
1999   gcry_md_hd_t md = NULL;
2000
2001   REGISTER_DEFAULT_PUBKEYS;
2002
2003   /* check that the first element is valid */
2004   list = gcry_sexp_find_token (key, "public-key", 0);
2005   if (! list)
2006     list = gcry_sexp_find_token (key, "private-key", 0);
2007   if (! list)
2008     list = gcry_sexp_find_token (key, "protected-private-key", 0);
2009   if (! list)
2010     return NULL; /* no public- or private-key object */
2011
2012   l2 = gcry_sexp_cadr (list);
2013   gcry_sexp_release (list);
2014   list = l2;
2015   l2 = NULL;
2016
2017   name = gcry_sexp_nth_data (list, 0, &n);
2018   if (! name)
2019     goto fail; /* invalid structure of object */
2020
2021   
2022   {
2023     char *name_terminated = gcry_xmalloc (n + 1);
2024     strncpy (name_terminated, name, n);
2025     name_terminated[n] = 0;
2026
2027     ath_mutex_lock (&pubkeys_registered_lock);
2028     module = gcry_pubkey_lookup_name (name_terminated);
2029     ath_mutex_unlock (&pubkeys_registered_lock);
2030
2031     free (name_terminated);
2032   }
2033
2034   if (! module)
2035     goto fail; /* unknown algorithm */
2036   else
2037     pubkey = (gcry_pubkey_spec_t *) module->spec;
2038
2039   /* FIXME, special handling should be implemented by the algorithms,
2040      not by the libgcrypt core.  */
2041   is_rsa = pubkey->id == GCRY_PK_RSA;
2042   elems = pubkey->elements_grip;
2043   if (! elems)
2044     goto fail; /* no grip parameter */
2045     
2046   if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
2047     goto fail;
2048
2049   for (idx = 0, s = elems; *s; s++, idx++)
2050     {
2051       const char *data;
2052       size_t datalen;
2053
2054       l2 = gcry_sexp_find_token (list, s, 1);
2055       if (! l2)
2056         goto fail;
2057       data = gcry_sexp_nth_data (l2, 1, &datalen);
2058       if (! data)
2059         goto fail;
2060       if (!is_rsa)
2061         {
2062           char buf[30];
2063
2064           sprintf (buf, "(1:%c%u:", *s, (unsigned int)datalen);
2065           gcry_md_write (md, buf, strlen (buf));
2066         }
2067       /* pkcs-15 says that for RSA only the modulus should be hashed -
2068          however, it is not clear wether this is meant to has the raw
2069          bytes assuming this is an unsigned integer or whether the DER
2070          required 0 should be prefixed. We hash th raw bytes.  For
2071          non-RSA we hash S-expressions. */
2072       gcry_md_write (md, data, datalen);
2073       gcry_sexp_release (l2);
2074       if (!is_rsa)
2075         gcry_md_write (md, ")", 1);
2076     }
2077
2078   if (!array)
2079     {
2080       array = gcry_malloc (20);
2081       if (! array)
2082         goto fail;
2083     }
2084   memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20);
2085   gcry_md_close (md);
2086   gcry_sexp_release (list);
2087    return array;
2088
2089  fail:
2090   if (l2)
2091     gcry_sexp_release (l2);
2092   if (md)
2093     gcry_md_close (md);
2094   gcry_sexp_release (list);
2095   return NULL;
2096 }
2097
2098
2099 gpg_error_t
2100 gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
2101 {
2102   gpg_err_code_t err = GPG_ERR_NO_ERROR;
2103
2104   REGISTER_DEFAULT_PUBKEYS;
2105
2106   switch (cmd)
2107     {
2108     case GCRYCTL_DISABLE_ALGO:
2109       /* this one expects a buffer pointing to an integer with the
2110        * algo number.
2111        */
2112       if ((! buffer) || (buflen != sizeof (int)))
2113         err = GPG_ERR_CIPHER_ALGO;  /* FIXME?  */
2114       else
2115         disable_pubkey_algo (*((int *) buffer));
2116       break;
2117
2118     default:
2119       err = GPG_ERR_INV_OP;
2120     }
2121
2122   return gpg_error (err);
2123 }
2124
2125
2126 /****************
2127  * Return information about the given algorithm
2128  * WHAT select the kind of information returned:
2129  *  GCRYCTL_TEST_ALGO:
2130  *      Returns 0 when the specified algorithm is available for use.
2131  *      Buffer must be NULL, nbytes  may have the address of a variable
2132  *      with the required usage of the algorithm. It may be 0 for don't
2133  *      care or a combination of the GCRY_PK_USAGE_xxx flags;
2134  *  GCRYCTL_GET_ALGO_USAGE:
2135  *      Return the usage glafs for the give algo.  An invalid alog
2136  *      does return 0.  Disabled algos are ignored here becuase we
2137  *      only want to know whether the algo is at all capable of
2138  *      the usage.
2139  *
2140  * Note:  Because this function is in most cases used to return an
2141  * integer value, we can make it easier for the caller to just look at
2142  * the return value.  The caller will in all cases consult the value
2143  * and thereby detecting whether a error occured or not (i.e. while checking
2144  * the block size)
2145  */
2146 gpg_error_t
2147 gcry_pk_algo_info (int id, int what, void *buffer, size_t *nbytes)
2148 {
2149   gpg_err_code_t err = GPG_ERR_NO_ERROR;
2150
2151   switch (what)
2152     {
2153     case GCRYCTL_TEST_ALGO:
2154       {
2155         int use = nbytes ? *nbytes : 0;
2156         if (buffer)
2157           err = GPG_ERR_INV_ARG;
2158         else if (check_pubkey_algo (id, use))
2159           err = GPG_ERR_PUBKEY_ALGO;
2160         break;
2161       }
2162
2163     case GCRYCTL_GET_ALGO_USAGE:
2164       {
2165         gcry_module_t *pubkey;
2166         int use = 0;
2167
2168         REGISTER_DEFAULT_PUBKEYS;
2169
2170         ath_mutex_lock (&pubkeys_registered_lock);
2171         pubkey = _gcry_module_lookup_id (pubkeys_registered, id);
2172         if (pubkey)
2173           {
2174             use = ((gcry_pubkey_spec_t *) pubkey->spec)->use;
2175             _gcry_module_release (pubkey);
2176           }
2177         ath_mutex_unlock (&pubkeys_registered_lock);
2178
2179         /* FIXME? */
2180         *nbytes = use;
2181       }
2182
2183     case GCRYCTL_GET_ALGO_NPKEY:
2184       {
2185         /* FIXME?  */
2186         int npkey = pubkey_get_npkey (id);
2187         *nbytes = npkey;
2188         break;
2189       }
2190     case GCRYCTL_GET_ALGO_NSKEY:
2191       {
2192         /* FIXME?  */
2193         int nskey = pubkey_get_nskey (id);
2194         *nbytes = nskey;
2195         break;
2196       }
2197     case GCRYCTL_GET_ALGO_NSIGN:
2198       {
2199         /* FIXME?  */
2200         int nsign = pubkey_get_nsig (id);
2201         *nbytes = nsign;
2202         break;
2203       }
2204     case GCRYCTL_GET_ALGO_NENCR:
2205       {
2206         /* FIXME?  */
2207         int nencr = pubkey_get_nenc (id);
2208         *nbytes = nencr;
2209         break;
2210       }
2211
2212     default:
2213       err = GPG_ERR_INV_OP;
2214     }
2215
2216   return gpg_error (err);
2217 }
2218
2219 gpg_err_code_t
2220 _gcry_pk_init (void)
2221 {
2222   gpg_err_code_t err = GPG_ERR_NO_ERROR;
2223
2224   REGISTER_DEFAULT_PUBKEYS;
2225
2226   return err;
2227 }