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