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