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