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
743 /****************
744  * Convert a S-Exp with either a private or a public key to our
745  * internal format. Currently we do only support the following
746  * algorithms:
747  *    dsa
748  *    rsa
749  *    openpgp-dsa
750  *    openpgp-rsa
751  *    openpgp-elg
752  *    openpgp-elg-sig
753  * Provide a SE with the first element be either "private-key" or
754  * or "public-key". the followed by a list with its first element
755  * be one of the above algorithm identifiers and the following
756  * elements are pairs with parameter-id and value.
757  * NOTE: we look through the list to find a list beginning with
758  * "private-key" or "public-key" - the first one found is used.
759  *
760  * FIXME: Allow for encrypted secret keys here.
761  *
762  * Returns: A pointer to an allocated array of MPIs if the return value is
763  *          zero; the caller has to release this array.
764  *
765  * Example of a DSA public key:
766  *  (private-key
767  *    (dsa
768  *      (p <mpi>)
769  *      (g <mpi>)
770  *      (y <mpi>)
771  *      (x <mpi>)
772  *    )
773  *  )
774  * The <mpi> are expected to be in GCRYMPI_FMT_USG
775  */
776 static int
777 sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray,
778              int *retalgo, int *r_algotblidx)
779 {
780     GCRY_SEXP list, l2;
781     const char *name;
782     const char *s;
783     size_t n;
784     int i, idx;
785     int algo;
786     const char *elems1, *elems2;
787     GCRY_MPI *array;
788
789     /* check that the first element is valid */
790     list = gcry_sexp_find_token( sexp, want_private? "private-key"
791                                                     :"public-key", 0 );
792     if( !list )
793         return GCRYERR_INV_OBJ; /* Does not contain a public- or private-key object */
794     l2 = gcry_sexp_cadr( list );
795     gcry_sexp_release ( list );
796     list = l2;
797     name = gcry_sexp_nth_data( list, 0, &n );
798     if( !name ) {
799         gcry_sexp_release ( list );
800         return GCRYERR_INV_OBJ; /* invalid structure of object */
801     }
802     for(i=0; (s=algo_info_table[i].name); i++ ) {
803         if( strlen(s) == n && !memcmp( s, name, n ) )
804             break;
805     }
806     if( !s ) {
807         gcry_sexp_release ( list );
808         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
809     }
810     if (r_algotblidx)
811       *r_algotblidx = i;
812     algo = algo_info_table[i].algo;
813     elems1 = algo_info_table[i].common_elements;
814     elems2 = want_private? algo_info_table[i].secret_elements
815                          : algo_info_table[i].public_elements;
816     array = gcry_calloc( strlen(elems1)+strlen(elems2)+1, sizeof *array );
817     if( !array ) {
818         gcry_sexp_release ( list );
819         return GCRYERR_NO_MEM;
820     }
821
822     idx = 0;
823     for(s=elems1; *s; s++, idx++ ) {
824         l2 = gcry_sexp_find_token( list, s, 1 );
825         if( !l2 ) {
826             for(i=0; i<idx; i++)
827                 gcry_free( array[i] );
828             gcry_free( array );
829             gcry_sexp_release ( list );
830             return GCRYERR_NO_OBJ; /* required parameter not found */
831         }
832         array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
833         gcry_sexp_release ( l2 );
834         if( !array[idx] ) {
835             for(i=0; i<idx; i++)
836                 gcry_free( array[i] );
837             gcry_free( array );
838             gcry_sexp_release ( list );
839             return GCRYERR_INV_OBJ; /* required parameter is invalid */
840         }
841     }
842     for(s=elems2; *s; s++, idx++ ) {
843         l2 = gcry_sexp_find_token( list, s, 1 );
844         if( !l2 ) {
845             for(i=0; i<idx; i++)
846                 gcry_free( array[i] );
847             gcry_free( array );
848             gcry_sexp_release ( list );
849             return GCRYERR_NO_OBJ; /* required parameter not found */
850         }
851         array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
852         gcry_sexp_release ( l2 );
853         if( !array[idx] ) {
854             for(i=0; i<idx; i++)
855                 gcry_free( array[i] );
856             gcry_free( array );
857             gcry_sexp_release ( list );
858             return GCRYERR_INV_OBJ; /* required parameter is invalid */
859         }
860     }
861
862     gcry_sexp_release ( list );
863     *retarray = array;
864     *retalgo = algo;
865
866     return 0;
867 }
868
869 static int
870 sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
871 {
872     GCRY_SEXP list, l2;
873     const char *name;
874     const char *s;
875     size_t n;
876     int i, idx;
877     int algo;
878     const char *elems;
879     GCRY_MPI *array;
880
881     /* check that the first element is valid */
882     list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
883     if( !list )
884         return GCRYERR_INV_OBJ; /* Does not contain a signature value object */
885     l2 = gcry_sexp_cadr( list );
886     gcry_sexp_release ( list );
887     list = l2;
888     if( !list )
889         return GCRYERR_NO_OBJ; /* no cadr for the sig object */
890     name = gcry_sexp_nth_data( list, 0, &n );
891     if( !name ) {
892         gcry_sexp_release ( list );
893         return GCRYERR_INV_OBJ; /* invalid structure of object */
894     }
895     for(i=0; (s=sig_info_table[i].name); i++ ) {
896         if( strlen(s) == n && !memcmp( s, name, n ) )
897             break;
898     }
899     if( !s ) {
900         gcry_sexp_release ( list );
901         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
902     }
903     algo = sig_info_table[i].algo;
904     elems = sig_info_table[i].elements;
905     array = gcry_calloc( (strlen(elems)+1) , sizeof *array );
906     if( !array ) {
907         gcry_sexp_release ( list );
908         return GCRYERR_NO_MEM;
909     }
910
911     idx = 0;
912     for(s=elems; *s; s++, idx++ ) {
913         l2 = gcry_sexp_find_token( list, s, 1 );
914         if( !l2 ) {
915             gcry_free( array );
916             gcry_sexp_release ( list );
917             return GCRYERR_NO_OBJ; /* required parameter not found */
918         }
919         array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
920         gcry_sexp_release ( l2 );
921         if( !array[idx] ) {
922             gcry_free( array );
923             gcry_sexp_release ( list );
924             return GCRYERR_INV_OBJ; /* required parameter is invalid */
925         }
926     }
927
928     gcry_sexp_release ( list );
929     *retarray = array;
930     *retalgo = algo;
931
932     return 0;
933 }
934
935
936 /****************
937  * Take sexp and return an array of MPI as used for our internal decrypt
938  * function.
939  * s_data = (enc-val
940  *           [(flags [pkcs1])
941  *            (<algo>
942  *              (<param_name1> <mpi>)
943  *              ...
944  *              (<param_namen> <mpi>)
945  *            ))
946  * RET_MODERN is set to true when at least an empty flags list has been found.
947  */
948 static int
949 sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo,
950              int *ret_modern, int *ret_want_pkcs1,
951              int *flags)
952 {
953     GCRY_SEXP list, l2;
954     const char *name;
955     const char *s;
956     size_t n;
957     int i, idx;
958     int algo;
959     int parsed_flags = 0;
960     const char *elems;
961     GCRY_MPI *array;
962
963     *ret_want_pkcs1 = 0;
964     *ret_modern = 0;
965     /* check that the first element is valid */
966     list = gcry_sexp_find_token( sexp, "enc-val" , 0 );
967     if( !list )
968         return GCRYERR_INV_OBJ; /* Does not contain a encrypted value object */
969     l2 = gcry_sexp_nth (list, 1);
970     if (!l2 ) {
971         gcry_sexp_release (list);
972         return GCRYERR_NO_OBJ; /* no cdr for the data object */
973     }
974     name = gcry_sexp_nth_data (l2, 0, &n);
975     if (!name) {
976         gcry_sexp_release (l2);
977         gcry_sexp_release (list);
978         return GCRYERR_INV_OBJ; /* invalid structure of object */
979     }
980     if ( n == 5 && !memcmp (name, "flags", 5)) {
981       /* There is a flags element - process it */
982       const char *s;
983
984       *ret_modern = 1;
985       for (i=gcry_sexp_length (l2)-1; i > 0; i--)
986         {
987           s = gcry_sexp_nth_data (l2, i, &n);
988           if (!s)
989             ; /* not a data element - ignore */
990           else if ( n == 3 && !memcmp (s, "raw", 3))
991             ; /* just a dummy because it is the default */
992           else if ( n == 5 && !memcmp (s, "pkcs1", 5))
993             *ret_want_pkcs1 = 1;
994           else if ( n == 11 && !memcmp (s, "no-blinding", 11))
995             parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
996           else
997             {
998               gcry_sexp_release (l2);
999               gcry_sexp_release (list);
1000               return GCRYERR_INV_FLAG;
1001             }
1002         }
1003       
1004       /* Get the next which has the actual data */
1005       gcry_sexp_release (l2);
1006       l2 = gcry_sexp_nth (list, 2);
1007       if (!l2 ) {
1008         gcry_sexp_release (list);
1009         return GCRYERR_NO_OBJ; /* no cdr for the data object */
1010       }
1011       name = gcry_sexp_nth_data (l2, 0, &n);
1012       if (!name) {
1013         gcry_sexp_release (l2);
1014         gcry_sexp_release (list);
1015         return GCRYERR_INV_OBJ; /* invalid structure of object */
1016       }
1017     }
1018     gcry_sexp_release (list);
1019     list = l2; l2 = NULL;
1020     
1021     for(i=0; (s=enc_info_table[i].name); i++ ) {
1022         if( strlen(s) == n && !memcmp( s, name, n ) )
1023             break;
1024     }
1025     if( !s ) {
1026         gcry_sexp_release (list);
1027         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
1028     }
1029
1030     algo = enc_info_table[i].algo;
1031     elems = enc_info_table[i].elements;
1032     array = gcry_calloc( (strlen(elems)+1) , sizeof *array );
1033     if( !array ) {
1034         gcry_sexp_release ( list );
1035         return GCRYERR_NO_MEM;
1036     }
1037
1038     idx = 0;
1039     for(s=elems; *s; s++, idx++ ) {
1040         l2 = gcry_sexp_find_token( list, s, 1 );
1041         if( !l2 ) {
1042             gcry_free( array );
1043             gcry_sexp_release ( list );
1044             return GCRYERR_NO_OBJ; /* required parameter not found */
1045         }
1046         array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
1047         gcry_sexp_release ( l2 );
1048         if( !array[idx] ) {
1049             gcry_free( array );
1050             gcry_sexp_release ( list );
1051             return GCRYERR_INV_OBJ; /* required parameter is invalid */
1052         }
1053     }
1054
1055     gcry_sexp_release ( list );
1056     *retarray = array;
1057     *retalgo = algo;
1058
1059     *flags = parsed_flags;
1060
1061     return 0;
1062 }
1063
1064 /* Take the hash value and convert into an MPI, suitable for for
1065    passing to the low level functions.  We currently support the
1066    old style way of passing just a MPI and the modern interface which
1067    allows to pass flags so that we can choose between raw and pkcs1
1068    padding - may be more padding options later. 
1069
1070    (<mpi>)
1071    or
1072    (data
1073     [(flags [pkcs1])]
1074     [(hash <algo> <value>)]
1075     [(value <text>)]
1076    )
1077    
1078    Either the VALUE or the HASH element must be present for use
1079    with signatures.  VALUE is used for encryption.
1080
1081    NBITS is the length of the key in bits. 
1082
1083 */
1084 static int 
1085 sexp_data_to_mpi (GcrySexp input, unsigned int nbits, GcryMPI *ret_mpi,
1086                   int for_encryption, int *flags)
1087 {
1088   int rc = 0;
1089   GcrySexp ldata, lhash, lvalue;
1090   int i;
1091   size_t n;
1092   const char *s;
1093   int is_raw = 0, is_pkcs1 = 0, unknown_flag=0; 
1094   int parsed_flags = 0, dummy_flags;
1095
1096   if (! flags)
1097     flags = &dummy_flags;
1098   
1099   *ret_mpi = NULL;
1100   ldata = gcry_sexp_find_token (input, "data", 0);
1101   if (!ldata)
1102     { /* assume old style */
1103       *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0);
1104       return *ret_mpi? 0 : GCRYERR_INV_OBJ;
1105     }
1106
1107   /* see whether there is a flags object */
1108   {
1109     GcrySexp lflags = gcry_sexp_find_token (ldata, "flags", 0);
1110     if (lflags)
1111       { /* parse the flags list. */
1112         for (i=gcry_sexp_length (lflags)-1; i > 0; i--)
1113           {
1114             s = gcry_sexp_nth_data (lflags, i, &n);
1115             if (!s)
1116               ; /* not a data element*/
1117             else if ( n == 3 && !memcmp (s, "raw", 3))
1118               is_raw = 1;
1119             else if ( n == 5 && !memcmp (s, "pkcs1", 5))
1120               is_pkcs1 = 1;
1121             else if (n == 11 && ! memcmp (s, "no-blinding", 11))
1122               parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
1123             else
1124               unknown_flag = 1;
1125           }
1126         gcry_sexp_release (lflags);
1127       }
1128   }
1129
1130   if (!is_pkcs1 && !is_raw)
1131     is_raw = 1; /* default to raw */
1132
1133   /* Get HASH or MPI */
1134   lhash = gcry_sexp_find_token (ldata, "hash", 0);
1135   lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0);
1136
1137   if (!(!lhash ^ !lvalue))
1138     rc = GCRYERR_INV_OBJ; /* none or both given */
1139   else if (unknown_flag)
1140     rc = GCRYERR_INV_FLAG;
1141   else if (is_raw && is_pkcs1 && !for_encryption)
1142     rc = GCRYERR_CONFLICT;
1143   else if (is_raw && lvalue)
1144     {
1145       *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, 0);
1146       if (!*ret_mpi)
1147         rc = GCRYERR_INV_OBJ;
1148     }
1149   else if (is_pkcs1 && lvalue && for_encryption)
1150     { /* create pkcs#1 block type 2 padding */
1151       unsigned char *frame = NULL;
1152       size_t nframe = (nbits+7) / 8;
1153       const void * value;
1154       size_t valuelen;
1155       unsigned char *p;
1156
1157       if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
1158         rc = GCRYERR_INV_OBJ;
1159       else if (valuelen + 7 > nframe || !nframe)
1160         {
1161           /* Can't encode a VALUELEN value in a NFRAME bytes frame. */
1162           rc = GCRYERR_TOO_SHORT; /* the key is too short */
1163         }
1164       else if ( !(frame = gcry_malloc_secure (nframe)))
1165         rc = GCRYERR_NO_MEM;
1166       else
1167         {
1168           n = 0;
1169           frame[n++] = 0;
1170           frame[n++] = 2; /* block type */
1171           i = nframe - 3 - valuelen;
1172           assert (i > 0);
1173           p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
1174           /* replace zero bytes by new values*/
1175           for (;;)
1176             {
1177               int j, k;
1178               unsigned char *pp;
1179               
1180               /* count the zero bytes */
1181               for (j=k=0; j < i; j++)
1182                 {
1183                   if (!p[j])
1184                     k++;
1185                 }
1186               if (!k)
1187                 break; /* okay: no (more) zero bytes */
1188               
1189               k += k/128; /* better get some more */
1190               pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
1191               for (j=0; j < i && k; j++)
1192                 {
1193                   if (!p[j])
1194                     p[j] = pp[--k];
1195                 }
1196               gcry_free (pp);
1197             }
1198           memcpy (frame+n, p, i);
1199           n += i;
1200           gcry_free (p);
1201           
1202           frame[n++] = 0;
1203           memcpy (frame+n, value, valuelen);
1204           n += valuelen;
1205           assert (n == nframe);
1206
1207           gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, &nframe);
1208         }
1209
1210       gcry_free(frame);
1211     }
1212   else if (is_pkcs1 && lhash && !for_encryption)
1213     { /* create pkcs#1 block type 1 padding */
1214       if (gcry_sexp_length (lhash) != 3)
1215         rc = GCRYERR_INV_OBJ;
1216       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
1217         rc = GCRYERR_INV_OBJ;
1218       else
1219         {
1220           static struct { const char *name; int algo; } hashnames[] = 
1221           { { "sha1",   GCRY_MD_SHA1 },
1222             { "md5",    GCRY_MD_MD5 },
1223             { "rmd160", GCRY_MD_RMD160 },
1224             { "sha256", GCRY_MD_SHA256 },
1225             { "sha384", GCRY_MD_SHA384 },
1226             { "sha512", GCRY_MD_SHA512 },
1227             { "md2",    GCRY_MD_MD2 },
1228             { "md4",    GCRY_MD_MD4 },
1229             { "tiger",  GCRY_MD_TIGER },
1230             { "haval",  GCRY_MD_HAVAL },
1231             { NULL }
1232           };
1233           int algo;
1234           byte asn[100];
1235           byte *frame = NULL;
1236           size_t nframe = (nbits+7) / 8;
1237           const void * value;
1238           size_t valuelen;
1239           size_t asnlen, dlen;
1240             
1241           for (i=0; hashnames[i].name; i++)
1242             {
1243               if ( strlen (hashnames[i].name) == n
1244                    && !memcmp (hashnames[i].name, s, n))
1245                 break;
1246             }
1247
1248           algo = hashnames[i].algo;
1249           asnlen = DIM(asn);
1250           dlen = gcry_md_get_algo_dlen (algo);
1251
1252           if (!hashnames[i].name)
1253             rc = GCRYERR_INV_MD_ALGO;
1254           else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
1255                     || !valuelen )
1256             rc = GCRYERR_INV_OBJ;
1257           else if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
1258             rc = GCRYERR_NOT_IMPL; /* we don't have all of the above algos */
1259           else if ( valuelen != dlen )
1260             {
1261               /* hash value does not match the length of digest for
1262                  the given algo */
1263               rc = GCRYERR_CONFLICT;
1264             }
1265           else if( !dlen || dlen + asnlen + 4 > nframe)
1266             {
1267               /* can't encode an DLEN byte digest MD into a NFRAME byte frame */
1268               rc = GCRYERR_TOO_SHORT;
1269             }
1270           else if ( !(frame = gcry_malloc (nframe)) )
1271             rc = GCRYERR_NO_MEM;
1272           else
1273             { /* assemble the pkcs#1 block type 1 */
1274               n = 0;
1275               frame[n++] = 0;
1276               frame[n++] = 1; /* block type */
1277               i = nframe - valuelen - asnlen - 3 ;
1278               assert (i > 1);
1279               memset (frame+n, 0xff, i );
1280               n += i;
1281               frame[n++] = 0;
1282               memcpy (frame+n, asn, asnlen);
1283               n += asnlen;
1284               memcpy (frame+n, value, valuelen );
1285               n += valuelen;
1286               assert (n == nframe);
1287       
1288               /* convert it into an MPI */
1289               gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, &nframe);
1290             }
1291           
1292           gcry_free (frame);
1293         }
1294     }
1295   else
1296     rc = GCRYERR_CONFLICT;
1297    
1298   gcry_sexp_release (ldata);
1299   gcry_sexp_release (lhash);
1300   gcry_sexp_release (lvalue);
1301
1302   if (! rc)
1303     *flags = parsed_flags;
1304
1305   return rc;
1306 }
1307
1308
1309 /*
1310    Do a PK encrypt operation
1311   
1312    Caller has to provide a public key as the SEXP pkey and data as a
1313    SEXP with just one MPI in it. Alternativly S_DATA might be a
1314    complex S-Expression, similar to the one used for signature
1315    verification.  This provides a flag which allows to handle PKCS#1
1316    block type 2 padding.  The function returns a a sexp which may be
1317    passed to to pk_decrypt.
1318   
1319    Returns: 0 or an errorcode.
1320   
1321    s_data = See comment for sexp_data_to_mpi
1322    s_pkey = <key-as-defined-in-sexp_to_key>
1323    r_ciph = (enc-val
1324                (<algo>
1325                  (<param_name1> <mpi>)
1326                  ...
1327                  (<param_namen> <mpi>)
1328                ))
1329
1330 */
1331 int
1332 gcry_pk_encrypt (GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey)
1333 {
1334     MPI *pkey, data, *ciph;
1335     const char *key_algo_name, *algo_name, *algo_elems;
1336     int i, rc, algo, flags;
1337     
1338     *r_ciph = NULL;
1339     /* get the key */
1340     rc = sexp_to_key( s_pkey, 0, &pkey, &algo, &i);
1341     if( rc ) 
1342         return rc;
1343     key_algo_name = algo_info_table[i].name;
1344     assert (key_algo_name);
1345
1346     /* get the name and the required size of the return value */
1347     for(i=0; (algo_name = enc_info_table[i].name); i++ ) {
1348         if( enc_info_table[i].algo == algo )
1349             break;
1350     }
1351     /* get the name and the required size of the result array.  We
1352        compare using the algorithm name and not the algo number - this way
1353        we get the correct name for the return value */
1354     for(i=0; (algo_name = enc_info_table[i].name); i++ ) {
1355         if( !strcmp (algo_name, key_algo_name) )
1356             break;
1357     }
1358     if( !algo_name ) {
1359         release_mpi_array( pkey );
1360         gcry_free (pkey);
1361         return GCRYERR_INV_PK_ALGO;
1362     }
1363     algo_elems = enc_info_table[i].elements;
1364
1365     /* get the stuff we want to encrypt */
1366     rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1,
1367                            &flags);
1368     if (rc) {
1369         release_mpi_array( pkey );
1370         gcry_free (pkey);
1371         return GCRYERR_INV_OBJ;
1372     }
1373
1374     /* Now we can encrypt data to ciph */
1375     ciph = gcry_xcalloc( (strlen(algo_elems)+1) , sizeof *ciph );
1376     rc = pubkey_encrypt( algo, ciph, data, pkey, flags );
1377     release_mpi_array( pkey );
1378     gcry_free (pkey); pkey = NULL;
1379     mpi_free( data );
1380     if( rc ) {
1381         release_mpi_array( ciph );
1382         gcry_free( ciph );
1383         return rc;
1384     }
1385
1386     /* We did it.  Now build the return list */
1387     {
1388         char *string, *p;
1389         size_t nelem, needed= strlen(algo_name) + 30;
1390
1391         /* FIXME, this calculation needs to be cleaned up.
1392            -moritz  */
1393
1394         /* count elements, so that we can allocate enough space */
1395         for(nelem=0; algo_elems[nelem]; nelem++ )
1396             needed += 10; /* 6 + a safety margin */
1397         /* build the string */
1398         string = p = gcry_xmalloc ( needed );
1399         p = stpcpy ( p, "(enc-val(flags " );
1400         if (flags & PUBKEY_FLAG_NO_BLINDING)
1401           p = stpcpy (p, "no-blinding");
1402         p = stpcpy (p, ")(");
1403         p = stpcpy ( p, algo_name );
1404         for(i=0; algo_elems[i]; i++ ) {
1405             *p++ = '(';
1406             *p++ = algo_elems[i];
1407             p = stpcpy ( p, "%m)" );
1408         }
1409         strcpy ( p, "))" );
1410         /* and now the ugly part:  we don't have a function to
1411          * pass an array to a format string, so we have to do it this way :-(
1412          */
1413         switch ( nelem ) {
1414           case 1: rc = gcry_sexp_build ( r_ciph, NULL, string,
1415                      ciph[0]
1416                   ); break;
1417           case 2: rc = gcry_sexp_build ( r_ciph, NULL, string,
1418                      ciph[0], ciph[1]
1419                   ); break;
1420           case 3: rc = gcry_sexp_build ( r_ciph, NULL, string,
1421                      ciph[0], ciph[1], ciph[2]
1422                   ); break;
1423           case 4: rc = gcry_sexp_build ( r_ciph, NULL, string,
1424                      ciph[0], ciph[1], ciph[2], ciph[3]
1425                   ); break;
1426           case 5: rc = gcry_sexp_build ( r_ciph, NULL, string,
1427                      ciph[0], ciph[1], ciph[2], ciph[3], ciph[4]
1428                   ); break;
1429           case 6: rc = gcry_sexp_build ( r_ciph, NULL, string,
1430                      ciph[0], ciph[1], ciph[2], ciph[3], ciph[4], ciph[5]
1431                   ); break;
1432           default: BUG ();
1433         }
1434         if ( rc )
1435             BUG ();
1436         gcry_free ( string );
1437     }
1438     release_mpi_array( ciph );
1439     gcry_free( ciph );
1440
1441
1442     return 0;
1443 }
1444
1445 /****************
1446  * Do a PK decrypt operation
1447  *
1448  * Caller has to provide a secret key as the SEXP skey and data in a
1449  * format as created by gcry_pk_encrypt.  For historic reasons the
1450  * function returns simply an MPI as an S-expression part; this is
1451  * deprecated and the new method should be used which returns a real
1452  * S-expressionl this is selected by adding at least an empt flags
1453  * list to S_DATA.
1454  * 
1455  * Returns: 0 or an errorcode.
1456  *
1457  * s_data = (enc-val
1458  *            [(flags)]
1459  *            (<algo>
1460  *              (<param_name1> <mpi>)
1461  *              ...
1462  *              (<param_namen> <mpi>)
1463  *            ))
1464  * s_skey = <key-as-defined-in-sexp_to_key>
1465  * r_plain= Either an incomplete S-expression without the parentheses
1466  *          or if the flags list is used (even if empty) a real S-expression:
1467  *          (value PLAIN).  */
1468 int
1469 gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey )
1470 {
1471     MPI *skey, *data, plain;
1472     int rc, algo, dataalgo, modern, want_pkcs1, flags;
1473     
1474     *r_plain = NULL;
1475     rc = sexp_to_key( s_skey, 1, &skey, &algo, NULL );
1476     if( rc ) {
1477         return rc;
1478     }
1479     rc = sexp_to_enc( s_data, &data, &dataalgo, &modern, &want_pkcs1,
1480                       &flags );
1481     if( rc ) {
1482         release_mpi_array( skey );
1483         gcry_free (skey);
1484         return rc;
1485     }
1486     if( algo != dataalgo ) {
1487         release_mpi_array( skey );
1488         gcry_free (skey);
1489         release_mpi_array( data );
1490         gcry_free (data);
1491         return GCRYERR_CONFLICT; /* key algo does not match data algo */
1492     }
1493
1494     rc = pubkey_decrypt( algo, &plain, data, skey, flags );
1495     if( rc ) {
1496         release_mpi_array( skey );
1497         gcry_free (skey);
1498         release_mpi_array( data );
1499         gcry_free (data);
1500         return GCRYERR_GENERAL; /* decryption failed */
1501     }
1502
1503     if (!modern) {
1504       if ( gcry_sexp_build( r_plain, NULL, "%m", plain ) )
1505         BUG ();
1506     }
1507     else {
1508       if ( gcry_sexp_build( r_plain, NULL, "(value %m)", plain ) )
1509         BUG ();
1510     }
1511       
1512
1513     mpi_free( plain );
1514     release_mpi_array( data );
1515     gcry_free (data);
1516     release_mpi_array( skey );
1517     gcry_free (skey);
1518     return 0;
1519 }
1520
1521
1522
1523 /****************
1524  * Create a signature.
1525  *
1526  * Caller has to provide a secret key as the SEXP skey and data
1527  * expressed as a SEXP list hash with only one element which should
1528  * instantly be available as a MPI. Alternatively the structure given
1529  * below may be used for S_HASH, it provides the abiliy to pass flags
1530  * to the operation; the only flag defined by now is "pkcs1" which
1531  * does PKCS#1 block type 1 style padding.
1532  *
1533  * Returns: 0 or an errorcode.
1534  *          In case of 0 the function returns a new SEXP with the
1535  *          signature value; the structure of this signature depends on the
1536  *          other arguments but is always suitable to be passed to
1537  *          gcry_pk_verify
1538  *
1539  * s_hash = See comment for sexp_data_to_mpi
1540  *             
1541  * s_skey = <key-as-defined-in-sexp_to_key>
1542  * r_sig  = (sig-val
1543  *            (<algo>
1544  *              (<param_name1> <mpi>)
1545  *              ...
1546  *              (<param_namen> <mpi>)
1547  * )) */
1548 int
1549 gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
1550 {
1551     MPI *skey, hash;
1552     MPI *result;
1553     int i, algo, rc;
1554     const char *key_algo_name, *algo_name, *algo_elems;
1555
1556     *r_sig = NULL;
1557     rc = sexp_to_key( s_skey, 1, &skey, &algo, &i);
1558     if( rc )
1559         return rc;
1560     key_algo_name = algo_info_table[i].name;
1561     assert (key_algo_name);
1562
1563     /* get the name and the required size of the result array.  We
1564        compare using the algorithm name and not the algo number - this way
1565        we get the correct name for the return value */
1566     for(i=0; (algo_name = sig_info_table[i].name); i++ ) {
1567         if( !strcmp (algo_name, key_algo_name) )
1568             break;
1569     }
1570     if( !algo_name ) {
1571         release_mpi_array( skey );
1572         gcry_free (skey);
1573         return -4; /* oops: unknown algorithm */
1574     }
1575     assert (sig_info_table[i].algo == algo);
1576     algo_elems = sig_info_table[i].elements;
1577
1578     /* get the stuff we want to sign */
1579     /* Note that pk_get_nbits does also work on a private key */
1580     rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey), &hash, 0, NULL);
1581     if (rc) {
1582         release_mpi_array( skey );
1583         gcry_free (skey);
1584         return rc; 
1585     }
1586     result = gcry_xcalloc( (strlen(algo_elems)+1) , sizeof *result );
1587     rc = pubkey_sign( algo, result, hash, skey );
1588     release_mpi_array( skey );
1589     gcry_free (skey); skey = NULL;
1590     mpi_free( hash );
1591     if( rc ) {
1592         gcry_free( result );
1593         return rc;
1594     }
1595
1596     {
1597         char *string, *p;
1598         size_t nelem, needed= strlen(algo_name) + 20;
1599
1600         /* count elements, so that we can allocate enough space */
1601         for(nelem=0; algo_elems[nelem]; nelem++ )
1602             needed += 10; /* 6 + a safety margin */
1603         /* build the string */
1604         string = p = gcry_xmalloc ( needed );
1605         p = stpcpy ( p, "(sig-val(" );
1606         p = stpcpy ( p, algo_name );
1607         for(i=0; algo_elems[i]; i++ ) {
1608             *p++ = '(';
1609             *p++ = algo_elems[i];
1610             p = stpcpy ( p, "%m)" );
1611         }
1612         strcpy ( p, "))" );
1613         /* and now the ugly part:  we don't have a function to
1614          * pass an array to a format string, so we have to do it this way :-(
1615          */
1616         switch ( nelem ) {
1617           case 1: rc = gcry_sexp_build ( r_sig, NULL, string,
1618                      result[0]
1619                   ); break;
1620           case 2: rc = gcry_sexp_build ( r_sig, NULL, string,
1621                      result[0], result[1]
1622                   ); break;
1623           case 3: rc = gcry_sexp_build ( r_sig, NULL, string,
1624                      result[0], result[1], result[2]
1625                   ); break;
1626           case 4: rc = gcry_sexp_build ( r_sig, NULL, string,
1627                      result[0], result[1], result[2], result[3]
1628                   ); break;
1629           case 5: rc = gcry_sexp_build ( r_sig, NULL, string,
1630                      result[0], result[1], result[2], result[3], result[4]
1631                   ); break;
1632           case 6: rc = gcry_sexp_build ( r_sig, NULL, string,
1633                      result[0], result[1], result[2], result[3], result[4], result[5]
1634                   ); break;
1635           default: BUG ();
1636         }
1637         if ( rc )
1638             BUG ();
1639         gcry_free ( string );
1640     }
1641     release_mpi_array( result );
1642     gcry_free( result );
1643
1644     return 0;
1645 }
1646
1647
1648 /****************
1649  * Verify a sgnature.  Caller has to supply the public key pkey,
1650  * the signature sig and his hashvalue data.  Public key has to be
1651  * a standard public key given as an S-Exp, sig is a S-Exp as returned
1652  * from gcry_pk_sign and data must be an S-Exp like the one in sign too.
1653  */
1654 int
1655 gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
1656 {
1657     MPI *pkey, hash, *sig;
1658     int algo, sigalgo;
1659     int rc;
1660
1661     rc = sexp_to_key( s_pkey, 0, &pkey, &algo, NULL );
1662     if( rc )
1663         return rc;
1664     rc = sexp_to_sig( s_sig, &sig, &sigalgo );
1665     if( rc ) {
1666         release_mpi_array( pkey );
1667         gcry_free (pkey);
1668         return rc;
1669     }
1670     if( algo != sigalgo ) {
1671         release_mpi_array( pkey );
1672         gcry_free (pkey);
1673         release_mpi_array( sig );
1674         gcry_free (sig);
1675         return GCRYERR_CONFLICT; /* algo does not match */
1676     }
1677
1678     rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0);
1679     if (rc) {
1680         release_mpi_array( pkey );
1681         gcry_free (pkey);
1682         release_mpi_array( sig );
1683         gcry_free (sig);
1684         return rc; 
1685     }
1686
1687     rc = pubkey_verify( algo, hash, sig, pkey, NULL, NULL );
1688     release_mpi_array( pkey );
1689     gcry_free (pkey);
1690     release_mpi_array( sig );
1691     gcry_free (sig);
1692     mpi_free(hash);
1693
1694     return rc;
1695 }
1696
1697
1698 /****************
1699  * Test a key.  This may be used either for a public or a secret key
1700  * to see whether internal structre is valid.
1701  *
1702  * Returns: 0 or an errorcode.
1703  *
1704  * s_key = <key-as-defined-in-sexp_to_key>
1705  */
1706 int
1707 gcry_pk_testkey( GCRY_SEXP s_key )
1708 {
1709     MPI *key;
1710     int rc, algo;
1711
1712     /* Note we currently support only secret key checking */
1713     rc = sexp_to_key( s_key, 1, &key, &algo, NULL );
1714     if( rc ) {
1715         return rc;
1716     }
1717
1718     rc = pubkey_check_secret_key( algo, key );
1719     release_mpi_array( key );
1720     gcry_free (key);
1721     return rc;
1722 }
1723
1724
1725 /****************
1726  * Create a public key pair and return it in r_key.
1727  * How the key is created depends on s_parms:
1728  * (genkey
1729  *  (algo
1730  *    (parameter_name_1 ....)
1731  *     ....
1732  *    (parameter_name_n ....)
1733  * ))
1734  * The key is returned in a format depending on the
1735  * algorithm. Both, private and secret keys are returned
1736  * and optionally some additional informatin.
1737  * For elgamal we return this structure:
1738  * (key-data
1739  *  (public-key
1740  *    (elg
1741  *      (p <mpi>)
1742  *      (g <mpi>)
1743  *      (y <mpi>)
1744  *    )
1745  *  )
1746  *  (private-key
1747  *    (elg
1748  *      (p <mpi>)
1749  *      (g <mpi>)
1750  *      (y <mpi>)
1751  *      (x <mpi>)
1752  *    )
1753  *  )
1754  *  (misc-key-info
1755  *     (pm1-factors n1 n2 ... nn)
1756  *  )
1757  * )
1758  */
1759 int
1760 gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
1761 {
1762     GCRY_SEXP list, l2;
1763     const char *name;
1764     const char *s, *s2;
1765     size_t n;
1766     int rc, i;
1767     const char *algo_name;
1768     int algo;
1769     char sec_elems[20], pub_elems[20];
1770     GCRY_MPI skey[10], *factors;
1771     unsigned int nbits;
1772     unsigned long use_e;
1773
1774     *r_key = NULL;
1775     list = gcry_sexp_find_token( s_parms, "genkey", 0 );
1776     if( !list )
1777         return GCRYERR_INV_OBJ; /* Does not contain genkey data */
1778     l2 = gcry_sexp_cadr( list );
1779     gcry_sexp_release ( list );
1780     list = l2;
1781     if( !list )
1782         return GCRYERR_NO_OBJ; /* no cdr for the genkey */
1783     name = gcry_sexp_nth_data( list, 0, &n );
1784     if( !name ) {
1785         gcry_sexp_release ( list );
1786         return GCRYERR_INV_OBJ; /* algo string missing */
1787     }
1788     for(i=0; (s=algo_info_table[i].name); i++ ) {
1789         if( strlen(s) == n && !memcmp( s, name, n ) )
1790             break;
1791     }
1792     if( !s ) {
1793         gcry_sexp_release ( list );
1794         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
1795     }
1796
1797     algo = algo_info_table[i].algo;
1798     algo_name = algo_info_table[i].name;
1799     
1800     s = algo_info_table[i].common_elements;
1801     s2 = algo_info_table[i].public_elements;
1802     if( strlen( s ) + strlen( s2 ) > DIM( pub_elems ) )
1803         return GCRYERR_INTERNAL; /* check bound failed */
1804     strcpy( pub_elems, s );
1805     strcat( pub_elems, s2 );
1806
1807     s = algo_info_table[i].common_elements;
1808     s2 = algo_info_table[i].secret_elements;
1809     if( strlen( s ) + strlen( s2 ) > DIM( sec_elems ) )
1810         return GCRYERR_INTERNAL; /* check bound failed */
1811     strcpy( sec_elems, s );
1812     strcat( sec_elems, s2 );
1813
1814     l2 = gcry_sexp_find_token (list, "rsa-use-e", 0);
1815     if (l2)
1816       {
1817         char buf[50];
1818
1819         name = gcry_sexp_nth_data (l2, 1, &n);
1820         if (!name || n >= DIM (buf)-1 )
1821            {
1822              gcry_sexp_release (l2);
1823              gcry_sexp_release (list);
1824              return GCRYERR_INV_OBJ; /* no value or value too large */
1825            }
1826         
1827         memcpy (buf, name, n);
1828         buf[n] = 0;
1829         use_e = strtoul (buf, NULL, 0);
1830         gcry_sexp_release (l2);
1831       }
1832     else
1833       use_e = 65537; /* not given, use the value generated by old versions. */
1834
1835     l2 = gcry_sexp_find_token( list, "nbits", 0 );
1836     gcry_sexp_release ( list );
1837     list = l2;
1838     if( !list )
1839         return GCRYERR_NO_OBJ; /* no nbits parameter */
1840     name = gcry_sexp_nth_data( list, 1, &n );
1841     if( !name ) {
1842         gcry_sexp_release ( list );
1843         return GCRYERR_INV_OBJ; /* nbits without a cdr */
1844     }
1845     {
1846         char *p = gcry_xmalloc(n+1);
1847         memcpy(p, name, n );
1848         p[n] = 0;
1849         nbits = (unsigned int)strtol( p, NULL, 0 );
1850         gcry_free( p );
1851     }
1852     gcry_sexp_release ( list );
1853
1854     rc = pubkey_generate( algo, nbits, use_e, skey, &factors );
1855     if( rc ) {
1856         return rc;
1857     }
1858
1859     {
1860         char *string, *p;
1861         size_t nelem=0, needed=0;
1862         GCRY_MPI mpis[30];
1863
1864
1865         /* count elements, so that we can allocate enough space */
1866         for(i=0; pub_elems[i]; i++, nelem++ )
1867             needed += 10; /* 6 + a safety margin */
1868         for(i=0; sec_elems[i]; i++, nelem++ )
1869             needed += 10; /* 6 + a safety margin */
1870         for(i=0; factors[i]; i++, nelem++ )
1871             needed += 10; /* 6 + a safety margin */
1872         needed += 2* strlen(algo_name) +  300;
1873         if ( nelem > DIM(mpis) )
1874             BUG ();
1875
1876         /* build the string */
1877         nelem = 0;
1878         string = p = gcry_xmalloc ( needed );
1879         p = stpcpy ( p, "(key-data" );
1880
1881         p = stpcpy ( p, "(public-key(" );
1882         p = stpcpy ( p, algo_name );
1883         for(i=0; pub_elems[i]; i++ ) {
1884             *p++ = '(';
1885             *p++ = pub_elems[i];
1886             p = stpcpy ( p, "%m)" );
1887             mpis[nelem++] = skey[i];
1888         }
1889         p = stpcpy ( p, "))" );
1890
1891         p = stpcpy ( p, "(private-key(" );
1892         p = stpcpy ( p, algo_name );
1893         for(i=0; sec_elems[i]; i++ ) {
1894             *p++ = '(';
1895             *p++ = sec_elems[i];
1896             p = stpcpy ( p, "%m)" );
1897             mpis[nelem++] = skey[i];
1898         }
1899         p = stpcpy ( p, "))" );
1900         /* Very ugly hack to make release_mpi_array() work FIXME */
1901         skey[i] = NULL;
1902
1903         p = stpcpy ( p, "(misc-key-info(pm1-factors" );
1904         for(i=0; factors[i]; i++ ) {
1905             p = stpcpy ( p, "%m" );
1906             mpis[nelem++] = factors[i];
1907         }
1908         strcpy ( p, ")))" );
1909
1910         while ( nelem < DIM(mpis) )
1911             mpis[nelem++] = NULL;
1912
1913         /* and now the ugly part:  we don't have a function to
1914          * pass an array to a format string, so we have just pass everything
1915          * we have. which normally should be no problem as only those
1916          * with a corresponding %m are used
1917          */
1918         if ( gcry_sexp_build ( r_key, NULL, string,
1919                    mpis[0], mpis[1], mpis[2], mpis[3], mpis[4], mpis[5],
1920                    mpis[6], mpis[7], mpis[8], mpis[9], mpis[10], mpis[11],
1921                    mpis[12], mpis[13], mpis[14], mpis[15], mpis[16], mpis[17],
1922                    mpis[18], mpis[19], mpis[20], mpis[21], mpis[22], mpis[23],
1923                    mpis[24], mpis[25], mpis[26], mpis[27], mpis[28], mpis[29]
1924                   ) )
1925             BUG ();
1926         assert ( DIM(mpis) == 30 );
1927         gcry_free ( string );
1928     }
1929     release_mpi_array ( skey );
1930     /* no free:  skey is a static array */
1931     release_mpi_array ( factors );
1932     gcry_free (factors);
1933
1934     return 0;
1935 }
1936
1937 /****************
1938  * Get the number of nbits from the public key
1939  * Hmmm: Should we have really this function or is it
1940  * better to have a more general function to retrieve
1941  * different propoerties of the key?
1942  */
1943 unsigned int
1944 gcry_pk_get_nbits (GCRY_SEXP key)
1945 {
1946   GcryPubkeySpec *pubkey;
1947   GcryModule *module;
1948   int rc, id;
1949   MPI *keyarr;
1950   unsigned int nbits = 0;
1951
1952   rc = sexp_to_key (key, 0, &keyarr, &id, NULL);
1953   if (rc == GCRYERR_INV_OBJ)
1954     rc = sexp_to_key (key, 1, &keyarr, &id, NULL);
1955   if (rc)
1956     return 0;
1957
1958   REGISTER_DEFAULT_PUBKEYS;
1959
1960   ath_mutex_lock (&pubkeys_registered_lock);
1961   module = gcry_pubkey_lookup_id (id);
1962   if (module)
1963     {
1964       pubkey = (GcryPubkeySpec *) module->spec;
1965       nbits = (*pubkey->get_nbits) (id, keyarr);
1966       _gcry_module_release (module);
1967       goto leave;
1968     }
1969
1970   if (is_RSA (id))      /* we always wanna see the length of a key :-) */
1971     nbits = mpi_get_nbits (keyarr[0]);
1972
1973  leave:
1974   ath_mutex_unlock (&pubkeys_registered_lock);
1975
1976   release_mpi_array (keyarr);
1977   gcry_free (keyarr);
1978   return nbits;
1979 }
1980
1981
1982 /* Return the so called KEYGRIP which is the SHA-1 hash of the public
1983    key parameters expressed in a way depended on the algorithm.
1984
1985    ARRAY must either be 20 bytes long or NULL; in the latter case a
1986    newly allocated array of that size is returned, otherwise ARRAY or
1987    NULL is returned to indicate an error which is most likely an
1988    unknown algorithm.  The function accepts public or secret keys. */
1989 unsigned char *
1990 gcry_pk_get_keygrip (GCRY_SEXP key, unsigned char *array)
1991 {
1992   GCRY_SEXP list=NULL, l2;
1993   const char *s, *name;
1994   size_t n;
1995   int i, idx;
1996   int is_rsa;
1997   const char *elems;
1998   GCRY_MD_HD md = NULL;
1999
2000   /* check that the first element is valid */
2001   list = gcry_sexp_find_token (key, "public-key", 0);
2002   if (!list)
2003     list = gcry_sexp_find_token (key, "private-key", 0);
2004   if (!list)
2005     list = gcry_sexp_find_token (key, "protected-private-key", 0);
2006   if (!list)
2007     return NULL; /* no public- or private-key object */
2008
2009   l2 = gcry_sexp_cadr (list);
2010   gcry_sexp_release (list);
2011   list = l2;
2012
2013   name = gcry_sexp_nth_data( list, 0, &n );
2014   if (!name)
2015     goto fail; /* invalid structure of object */
2016
2017   for (i=0; (s=algo_info_table[i].name); i++ ) 
2018     {
2019       if (strlen(s) == n && !memcmp (s, name, n))
2020         break;
2021     }
2022   
2023   if(!s)
2024     goto fail; /* unknown algorithm */
2025
2026   is_rsa = algo_info_table[i].algo == GCRY_PK_RSA;
2027   elems = algo_info_table[i].grip_elements;
2028   if (!elems)
2029     goto fail; /* no grip parameter */
2030     
2031   md = gcry_md_open (GCRY_MD_SHA1, 0);
2032   if (!md)
2033     goto fail;
2034
2035   idx = 0;
2036   for (s=elems; *s; s++, idx++)
2037     {
2038       const char *data;
2039       size_t datalen;
2040
2041       l2 = gcry_sexp_find_token (list, s, 1);
2042       if (!l2)
2043         goto fail;
2044       data = gcry_sexp_nth_data (l2, 1, &datalen);
2045       gcry_sexp_release (l2);
2046       if (!data)
2047         goto fail;
2048       if (!is_rsa)
2049         {
2050           char buf[30];
2051
2052           sprintf (buf, "(1:%c%u:", *s, (unsigned int)datalen);
2053           gcry_md_write (md, buf, strlen (buf));
2054         }
2055       /* pkcs-15 says that for RSA only the modulus should be hashed -
2056          however, it is not clear wether this is meant to has the raw
2057          bytes assuming this is an unsigned integer or whether the DER
2058          required 0 should be prefixed. We hash th raw bytes.  For
2059          non-RSA we hash S-expressions. */
2060       gcry_md_write (md, data, datalen);
2061       if (!is_rsa)
2062         gcry_md_write (md, ")", 1);
2063     }
2064   
2065   if (!array)
2066     {
2067       array = gcry_malloc (20);
2068       if (!array)
2069         goto fail;
2070     }
2071   memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20);
2072   gcry_md_close (md);
2073   gcry_sexp_release (list);
2074   return array;
2075
2076  fail:
2077   gcry_md_close (md);
2078   gcry_sexp_release (list);
2079   return NULL;
2080 }
2081
2082
2083
2084 int
2085 gcry_pk_ctl( int cmd, void *buffer, size_t buflen)
2086 {
2087     switch( cmd ) {
2088       case GCRYCTL_DISABLE_ALGO:
2089         /* this one expects a buffer pointing to an
2090          * integer with the algo number.
2091          */
2092         if( !buffer || buflen != sizeof(int) )
2093             return set_lasterr( GCRYERR_INV_CIPHER_ALGO );
2094         disable_pubkey_algo( *(int*)buffer );
2095         break;
2096
2097       default:
2098         return set_lasterr( GCRYERR_INV_OP );
2099     }
2100     return 0;
2101 }
2102
2103
2104 /****************
2105  * Return information about the given algorithm
2106  * WHAT select the kind of information returned:
2107  *  GCRYCTL_TEST_ALGO:
2108  *      Returns 0 when the specified algorithm is available for use.
2109  *      Buffer must be NULL, nbytes  may have the address of a variable
2110  *      with the required usage of the algorithm. It may be 0 for don't
2111  *      care or a combination of the GCRY_PK_USAGE_xxx flags;
2112  *  GCRYCTL_GET_ALGO_USAGE:
2113  *      Return the usage glafs for the give algo.  An invalid alog
2114  *      does return 0.  Disabled algos are ignored here becuase we
2115  *      only want to know whether the algo is at all capable of
2116  *      the usage.
2117  *
2118  * On error the value -1 is returned and the error reason may be
2119  * retrieved by gcry_errno().
2120  * Note:  Because this function is in most cases used to return an
2121  * integer value, we can make it easier for the caller to just look at
2122  * the return value.  The caller will in all cases consult the value
2123  * and thereby detecting whether a error occured or not (i.e. while checking
2124  * the block size)
2125  */
2126 int
2127 gcry_pk_algo_info (int id, int what, void *buffer, size_t *nbytes)
2128 {
2129   switch (what)
2130     {
2131     case GCRYCTL_TEST_ALGO:
2132       {
2133         int use = nbytes ? *nbytes: 0;
2134         if (buffer)
2135           {
2136             set_lasterr( GCRYERR_INV_ARG );
2137             return -1;
2138           }
2139         if (check_pubkey_algo (id, use))
2140           {
2141             set_lasterr( GCRYERR_INV_PK_ALGO );
2142             return -1;
2143           }
2144       }
2145       break;
2146
2147     case GCRYCTL_GET_ALGO_USAGE:
2148       {
2149         GcryModule *pubkey;
2150         int use = 0;
2151
2152         REGISTER_DEFAULT_PUBKEYS;
2153
2154         ath_mutex_lock (&pubkeys_registered_lock);
2155         pubkey = gcry_pubkey_lookup_id (id);
2156         if (pubkey)
2157           {
2158             use = ((GcryPubkeySpec *) pubkey->spec)->use;
2159             _gcry_module_release (pubkey);
2160           }
2161         ath_mutex_unlock (&pubkeys_registered_lock);
2162         return use;
2163       }
2164
2165     case GCRYCTL_GET_ALGO_NPKEY:
2166       return pubkey_get_npkey (id);
2167     case GCRYCTL_GET_ALGO_NSKEY:
2168       return pubkey_get_nskey (id);
2169     case GCRYCTL_GET_ALGO_NSIGN:
2170       return pubkey_get_nsig (id);
2171     case GCRYCTL_GET_ALGO_NENCR:
2172       return pubkey_get_nenc (id);
2173
2174     default:
2175       set_lasterr (GCRYERR_INV_OP);
2176       return -1;
2177     }
2178
2179   return 0;
2180 }