ea00080f5ef544170885b48dec0f6123b0502bd1
[libgcrypt.git] / cipher / pubkey.c
1 /* pubkey.c  -  pubkey dispatcher
2  *      Copyright (C) 1998, 1999, 2000 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 General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * 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 nbits, MPI *skey, MPI **retfactors );
49     int (*check_secret_key)( int algo, MPI *skey );
50     int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey );
51     int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey );
52     int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey );
53     int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey,
54                    int (*cmp)(void *, MPI), void *opaquev );
55     unsigned (*get_nbits)( int algo, MPI *pkey );
56 };
57
58 static struct pubkey_table_s pubkey_table[TABLE_SIZE];
59 static int disabled_algos[TABLE_SIZE];
60
61 static struct { const char* name; int algo;
62                 const char* common_elements;
63                 const char* public_elements;
64                 const char* secret_elements;
65 } algo_info_table[] = {
66         {  "dsa"            , PUBKEY_ALGO_DSA       , "pqgy", "", "x"    },
67         {  "rsa"            , PUBKEY_ALGO_RSA       , "ne",   "", "dpqu" },
68         {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "pgy",  "", "x"    },
69         {  "openpgp-dsa"    , PUBKEY_ALGO_DSA       , "pqgy", "", "x"    },
70         {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "pqgy", "", "x"    },
71         {  "openpgp-elg"    , PUBKEY_ALGO_ELGAMAL_E , "pgy",  "", "x"    },
72         {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "pgy",  "", "x"    },
73         {  NULL }};
74
75 static struct {
76     const char* name; int algo;
77     const char* elements;
78 } sig_info_table[] = {
79         {  "dsa"            , PUBKEY_ALGO_DSA       , "rs" },
80         {  "rsa"            , PUBKEY_ALGO_RSA       , "s"  },
81         {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "rs" },
82         {  "openpgp-dsa"    , PUBKEY_ALGO_DSA       , "rs" },
83         {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "s"  },
84         {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "rs" },
85         {  NULL }};
86
87 static struct {
88     const char* name; int algo;
89     const char* elements;
90 } enc_info_table[] = {
91         {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "ab" },
92         {  "rsa"            , PUBKEY_ALGO_RSA       , "a"  },
93         {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "a"  },
94         {  "openpgp-elg"    , PUBKEY_ALGO_ELGAMAL_E , "ab" },
95         {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "ab" },
96         {  NULL }};
97
98
99 static int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
100 static int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey );
101 static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
102                       int (*cmp)(void *, MPI), void *opaque );
103
104 static int
105 dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
106 { log_bug("no generate() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
107
108 static int
109 dummy_check_secret_key( int algo, MPI *skey )
110 { log_bug("no check_secret_key() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
111
112 static int
113 dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
114 { log_bug("no encrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
115
116 static int
117 dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
118 { log_bug("no decrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
119
120 static int
121 dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey )
122 { log_bug("no sign() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
123
124 static int
125 dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey,
126                 int (*cmp)(void *, MPI), void *opaquev )
127 { log_bug("no verify() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
128
129 static unsigned
130 dummy_get_nbits( int algo, MPI *pkey )
131 { log_bug("no get_nbits() for %d\n", algo ); return 0; }
132
133
134 /****************
135  * Put the static entries into the table.
136  * This is out constructor function which fill the table
137  * of algorithms with the one we have statically linked.
138  */
139 static void
140 setup_pubkey_table(void)
141 {
142     int i;
143
144     i = 0;
145     pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL;
146     pubkey_table[i].name = _gcry_elg_get_info( pubkey_table[i].algo,
147                                          &pubkey_table[i].npkey,
148                                          &pubkey_table[i].nskey,
149                                          &pubkey_table[i].nenc,
150                                          &pubkey_table[i].nsig,
151                                          &pubkey_table[i].use );
152     pubkey_table[i].generate         = _gcry_elg_generate;
153     pubkey_table[i].check_secret_key = _gcry_elg_check_secret_key;
154     pubkey_table[i].encrypt          = _gcry_elg_encrypt;
155     pubkey_table[i].decrypt          = _gcry_elg_decrypt;
156     pubkey_table[i].sign             = _gcry_elg_sign;
157     pubkey_table[i].verify           = _gcry_elg_verify;
158     pubkey_table[i].get_nbits        = _gcry_elg_get_nbits;
159     if( !pubkey_table[i].name )
160         BUG();
161     i++;
162     pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E;
163     pubkey_table[i].name = _gcry_elg_get_info( pubkey_table[i].algo,
164                                          &pubkey_table[i].npkey,
165                                          &pubkey_table[i].nskey,
166                                          &pubkey_table[i].nenc,
167                                          &pubkey_table[i].nsig,
168                                          &pubkey_table[i].use );
169     pubkey_table[i].generate         = _gcry_elg_generate;
170     pubkey_table[i].check_secret_key = _gcry_elg_check_secret_key;
171     pubkey_table[i].encrypt          = _gcry_elg_encrypt;
172     pubkey_table[i].decrypt          = _gcry_elg_decrypt;
173     pubkey_table[i].sign             = _gcry_elg_sign;
174     pubkey_table[i].verify           = _gcry_elg_verify;
175     pubkey_table[i].get_nbits        = _gcry_elg_get_nbits;
176     if( !pubkey_table[i].name )
177         BUG();
178     i++;
179     pubkey_table[i].algo = PUBKEY_ALGO_DSA;
180     pubkey_table[i].name = _gcry_dsa_get_info( pubkey_table[i].algo,
181                                          &pubkey_table[i].npkey,
182                                          &pubkey_table[i].nskey,
183                                          &pubkey_table[i].nenc,
184                                          &pubkey_table[i].nsig,
185                                          &pubkey_table[i].use );
186     pubkey_table[i].generate         = _gcry_dsa_generate;
187     pubkey_table[i].check_secret_key = _gcry_dsa_check_secret_key;
188     pubkey_table[i].encrypt          = dummy_encrypt;
189     pubkey_table[i].decrypt          = dummy_decrypt;
190     pubkey_table[i].sign             = _gcry_dsa_sign;
191     pubkey_table[i].verify           = _gcry_dsa_verify;
192     pubkey_table[i].get_nbits        = _gcry_dsa_get_nbits;
193     if( !pubkey_table[i].name )
194         BUG();
195     i++;
196
197     pubkey_table[i].algo = PUBKEY_ALGO_RSA;
198     pubkey_table[i].name = _gcry_rsa_get_info( pubkey_table[i].algo,
199                                          &pubkey_table[i].npkey,
200                                          &pubkey_table[i].nskey,
201                                          &pubkey_table[i].nenc,
202                                          &pubkey_table[i].nsig,
203                                          &pubkey_table[i].use );
204     pubkey_table[i].generate         = _gcry_rsa_generate;
205     pubkey_table[i].check_secret_key = _gcry_rsa_check_secret_key;
206     pubkey_table[i].encrypt          = _gcry_rsa_encrypt;
207     pubkey_table[i].decrypt          = _gcry_rsa_decrypt;
208     pubkey_table[i].sign             = _gcry_rsa_sign;
209     pubkey_table[i].verify           = _gcry_rsa_verify;
210     pubkey_table[i].get_nbits        = _gcry_rsa_get_nbits;
211     if( !pubkey_table[i].name )
212         BUG();
213     i++;
214     pubkey_table[i].algo = PUBKEY_ALGO_RSA_E;
215     pubkey_table[i].name = _gcry_rsa_get_info( pubkey_table[i].algo,
216                                          &pubkey_table[i].npkey,
217                                          &pubkey_table[i].nskey,
218                                          &pubkey_table[i].nenc,
219                                          &pubkey_table[i].nsig,
220                                          &pubkey_table[i].use );
221     pubkey_table[i].generate         = _gcry_rsa_generate;
222     pubkey_table[i].check_secret_key = _gcry_rsa_check_secret_key;
223     pubkey_table[i].encrypt          = _gcry_rsa_encrypt;
224     pubkey_table[i].decrypt          = _gcry_rsa_decrypt;
225     pubkey_table[i].sign             = dummy_sign;
226     pubkey_table[i].verify           = dummy_verify;
227     pubkey_table[i].get_nbits        = _gcry_rsa_get_nbits;
228     if( !pubkey_table[i].name )
229         BUG();
230     i++;
231     pubkey_table[i].algo = PUBKEY_ALGO_RSA_S;
232     pubkey_table[i].name = _gcry_rsa_get_info( pubkey_table[i].algo,
233                                          &pubkey_table[i].npkey,
234                                          &pubkey_table[i].nskey,
235                                          &pubkey_table[i].nenc,
236                                          &pubkey_table[i].nsig,
237                                          &pubkey_table[i].use );
238     pubkey_table[i].generate         = _gcry_rsa_generate;
239     pubkey_table[i].check_secret_key = _gcry_rsa_check_secret_key;
240     pubkey_table[i].encrypt          = dummy_encrypt;
241     pubkey_table[i].decrypt          = dummy_decrypt;
242     pubkey_table[i].sign             = _gcry_rsa_sign;
243     pubkey_table[i].verify           = _gcry_rsa_verify;
244     pubkey_table[i].get_nbits        = _gcry_rsa_get_nbits;
245     if( !pubkey_table[i].name )
246         BUG();
247     i++;
248
249     for( ; i < TABLE_SIZE; i++ )
250         pubkey_table[i].name = NULL;
251 }
252
253 static void
254 release_mpi_array( MPI *array )
255 {
256     for( ; *array; array++ ) {
257         mpi_free(*array);
258         *array = NULL;
259     }
260 }
261
262 /****************
263  * Try to load all modules and return true if new modules are available
264  */
265 static int
266 load_pubkey_modules(void)
267 {
268     static int initialized = 0;
269     static int done = 0;
270     void *context = NULL;
271     struct pubkey_table_s *ct;
272     int ct_idx;
273     int i;
274     const char *name;
275     int any = 0;
276
277
278     if( !initialized ) {
279         _gcry_cipher_modules_constructor();
280         setup_pubkey_table();
281         initialized = 1;
282         return 1;
283     }
284     if( done )
285         return 0;
286     done = 1;
287     for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
288         if( !ct->name )
289             break;
290     }
291     if( ct_idx >= TABLE_SIZE-1 )
292         BUG(); /* table already full */
293     /* now load all extensions */
294     while( (name = _gcry_enum_gnupgext_pubkeys( &context, &ct->algo,
295                                 &ct->npkey, &ct->nskey, &ct->nenc,
296                                 &ct->nsig,  &ct->use,
297                                 &ct->generate,
298                                 &ct->check_secret_key,
299                                 &ct->encrypt,
300                                 &ct->decrypt,
301                                 &ct->sign,
302                                 &ct->verify,
303                                 &ct->get_nbits )) ) {
304         for(i=0; pubkey_table[i].name; i++ )
305             if( pubkey_table[i].algo == ct->algo )
306                 break;
307         if( pubkey_table[i].name ) {
308             log_info("skipping pubkey %d: already loaded\n", ct->algo );
309             continue;
310         }
311
312         if( !ct->generate  )  ct->generate = dummy_generate;
313         if( !ct->check_secret_key )  ct->check_secret_key =
314                                                     dummy_check_secret_key;
315         if( !ct->encrypt   )  ct->encrypt  = dummy_encrypt;
316         if( !ct->decrypt   )  ct->decrypt  = dummy_decrypt;
317         if( !ct->sign      )  ct->sign     = dummy_sign;
318         if( !ct->verify    )  ct->verify   = dummy_verify;
319         if( !ct->get_nbits )  ct->get_nbits= dummy_get_nbits;
320         /* put it into the table */
321         if( _gcry_log_verbosity( 2 ) )
322             log_info("loaded pubkey %d (%s)\n", ct->algo, name);
323         ct->name = name;
324         ct_idx++;
325         ct++;
326         any = 1;
327         /* check whether there are more available table slots */
328         if( ct_idx >= TABLE_SIZE-1 ) {
329             log_info("pubkey table full; ignoring other extensions\n");
330             break;
331         }
332     }
333     _gcry_enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL,
334                                NULL, NULL, NULL, NULL, NULL, NULL, NULL );
335     return any;
336 }
337
338
339 /****************
340  * Map a string to the pubkey algo
341  */
342 int
343 gcry_pk_map_name( const char *string )
344 {
345     int i;
346     const char *s;
347
348     do {
349         for(i=0; (s=pubkey_table[i].name); i++ )
350             if( !stricmp( s, string ) )
351                 return pubkey_table[i].algo;
352     } while( load_pubkey_modules() );
353     return 0;
354 }
355
356
357 /****************
358  * Map a pubkey algo to a string
359  */
360 const char *
361 gcry_pk_algo_name( int algo )
362 {
363     int i;
364
365     do {
366         for(i=0; pubkey_table[i].name; i++ )
367             if( pubkey_table[i].algo == algo )
368                 return pubkey_table[i].name;
369     } while( load_pubkey_modules() );
370     return NULL;
371 }
372
373
374 static void
375 disable_pubkey_algo( int algo )
376 {
377     int i;
378
379     for(i=0; i < DIM(disabled_algos); i++ ) {
380         if( !disabled_algos[i] || disabled_algos[i] == algo ) {
381             disabled_algos[i] = algo;
382             return;
383         }
384     }
385     log_fatal("can't disable pubkey algo %d: table full\n", algo );
386 }
387
388
389 /****************
390  * a use of 0 means: don't care
391  */
392 static int
393 check_pubkey_algo( int algo, unsigned use )
394 {
395     int i;
396
397     do {
398         for(i=0; pubkey_table[i].name; i++ )
399             if( pubkey_table[i].algo == algo ) {
400                 if( (use & GCRY_PK_USAGE_SIGN)
401                     && !(pubkey_table[i].use & GCRY_PK_USAGE_SIGN) )
402                     return GCRYERR_WRONG_PK_ALGO;
403                 if( (use & GCRY_PK_USAGE_ENCR)
404                     && !(pubkey_table[i].use & GCRY_PK_USAGE_ENCR) )
405                     return GCRYERR_WRONG_PK_ALGO;
406
407                 for(i=0; i < DIM(disabled_algos); i++ ) {
408                     if( disabled_algos[i] == algo )
409                         return GCRYERR_INV_PK_ALGO;
410                 }
411                 return 0; /* okay */
412             }
413     } while( load_pubkey_modules() );
414     return GCRYERR_INV_PK_ALGO;
415 }
416
417
418
419
420 /****************
421  * Return the number of public key material numbers
422  */
423 static int
424 pubkey_get_npkey( int algo )
425 {
426     int i;
427     do {
428         for(i=0; pubkey_table[i].name; i++ )
429             if( pubkey_table[i].algo == algo )
430                 return pubkey_table[i].npkey;
431     } while( load_pubkey_modules() );
432     return 0;
433 }
434
435 /****************
436  * Return the number of secret key material numbers
437  */
438 static int
439 pubkey_get_nskey( int algo )
440 {
441     int i;
442     do {
443         for(i=0; pubkey_table[i].name; i++ )
444             if( pubkey_table[i].algo == algo )
445                 return pubkey_table[i].nskey;
446     } while( load_pubkey_modules() );
447     return 0;
448 }
449
450 /****************
451  * Return the number of signature material numbers
452  */
453 static int
454 pubkey_get_nsig( int algo )
455 {
456     int i;
457     do {
458         for(i=0; pubkey_table[i].name; i++ )
459             if( pubkey_table[i].algo == algo )
460                 return pubkey_table[i].nsig;
461     } while( load_pubkey_modules() );
462     return 0;
463 }
464
465 /****************
466  * Return the number of encryption material numbers
467  */
468 static int
469 pubkey_get_nenc( int algo )
470 {
471     int i;
472     do {
473         for(i=0; pubkey_table[i].name; i++ )
474             if( pubkey_table[i].algo == algo )
475                 return pubkey_table[i].nenc;
476     } while( load_pubkey_modules() );
477     return 0;
478 }
479
480
481 static int
482 pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
483 {
484     int i;
485
486     do {
487         for(i=0; pubkey_table[i].name; i++ )
488             if( pubkey_table[i].algo == algo )
489                 return (*pubkey_table[i].generate)( algo, nbits,
490                                                     skey, retfactors );
491     } while( load_pubkey_modules() );
492     return GCRYERR_INV_PK_ALGO;
493 }
494
495
496 static int
497 pubkey_check_secret_key( int algo, MPI *skey )
498 {
499     int i;
500
501     do {
502         for(i=0; pubkey_table[i].name; i++ )
503             if( pubkey_table[i].algo == algo )
504                 return (*pubkey_table[i].check_secret_key)( algo, skey );
505     } while( load_pubkey_modules() );
506     return GCRYERR_INV_PK_ALGO;
507 }
508
509
510 /****************
511  * This is the interface to the public key encryption.
512  * Encrypt DATA with PKEY and put it into RESARR which
513  * should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
514  * algorithm allows this - check with pubkey_get_nenc() )
515  */
516 static int
517 pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
518 {
519     int i, rc;
520
521     if( DBG_CIPHER ) {
522         log_debug("pubkey_encrypt: algo=%d\n", algo );
523         for(i=0; i < pubkey_get_npkey(algo); i++ )
524             log_mpidump("  pkey:", pkey[i] );
525         log_mpidump("  data:", data );
526     }
527
528     do {
529         for(i=0; pubkey_table[i].name; i++ )
530             if( pubkey_table[i].algo == algo ) {
531                 rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey );
532                 goto ready;
533             }
534     } while( load_pubkey_modules() );
535     rc = GCRYERR_INV_PK_ALGO;
536   ready:
537     if( !rc && DBG_CIPHER ) {
538         for(i=0; i < pubkey_get_nenc(algo); i++ )
539             log_mpidump("  encr:", resarr[i] );
540     }
541     return rc;
542 }
543
544
545
546 /****************
547  * This is the interface to the public key decryption.
548  * ALGO gives the algorithm to use and this implicitly determines
549  * the size of the arrays.
550  * result is a pointer to a mpi variable which will receive a
551  * newly allocated mpi or NULL in case of an error.
552  */
553 static int
554 pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
555 {
556     int i, rc;
557
558     *result = NULL; /* so the caller can always do a mpi_free */
559     if( DBG_CIPHER ) {
560         log_debug("pubkey_decrypt: algo=%d\n", algo );
561         for(i=0; i < pubkey_get_nskey(algo); i++ )
562             log_mpidump("  skey:", skey[i] );
563         for(i=0; i < pubkey_get_nenc(algo); i++ )
564             log_mpidump("  data:", data[i] );
565     }
566
567     do {
568         for(i=0; pubkey_table[i].name; i++ )
569             if( pubkey_table[i].algo == algo ) {
570                 rc = (*pubkey_table[i].decrypt)( algo, result, data, skey );
571                 goto ready;
572             }
573     } while( load_pubkey_modules() );
574     rc = GCRYERR_INV_PK_ALGO;
575   ready:
576     if( !rc && DBG_CIPHER ) {
577         log_mpidump(" plain:", *result );
578     }
579     return rc;
580 }
581
582
583 /****************
584  * This is the interface to the public key signing.
585  * Sign data with skey and put the result into resarr which
586  * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
587  * algorithm allows this - check with pubkey_get_nsig() )
588  */
589 static int
590 pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
591 {
592     int i, rc;
593
594     if( DBG_CIPHER ) {
595         log_debug("pubkey_sign: algo=%d\n", algo );
596         for(i=0; i < pubkey_get_nskey(algo); i++ )
597             log_mpidump("  skey:", skey[i] );
598         log_mpidump("  data:", data );
599     }
600
601     do {
602         for(i=0; pubkey_table[i].name; i++ )
603             if( pubkey_table[i].algo == algo ) {
604                 rc = (*pubkey_table[i].sign)( algo, resarr, data, skey );
605                 goto ready;
606             }
607     } while( load_pubkey_modules() );
608     rc = GCRYERR_INV_PK_ALGO;
609   ready:
610     if( !rc && DBG_CIPHER ) {
611         for(i=0; i < pubkey_get_nsig(algo); i++ )
612             log_mpidump("   sig:", resarr[i] );
613     }
614     return rc;
615 }
616
617 /****************
618  * Verify a public key signature.
619  * Return 0 if the signature is good
620  */
621 static int
622 pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
623                     int (*cmp)(void *, MPI), void *opaquev )
624 {
625     int i, rc;
626
627     do {
628         for(i=0; pubkey_table[i].name; i++ )
629             if( pubkey_table[i].algo == algo ) {
630                 rc = (*pubkey_table[i].verify)( algo, hash, data, pkey,
631                                                             cmp, opaquev );
632                 goto ready;
633             }
634     } while( load_pubkey_modules() );
635     rc = GCRYERR_INV_PK_ALGO;
636   ready:
637     return rc;
638 }
639
640
641
642 /****************
643  * Convert a S-Exp with either a private or a public key to our
644  * internal format. Currently we do only support the following
645  * algorithms:
646  *    dsa
647  *    rsa
648  *    openpgp-dsa
649  *    openpgp-rsa
650  *    openpgp-elg
651  *    openpgp-elg-sig
652  * Provide a SE with the first element be either "private-key" or
653  * or "public-key". the followed by a list with its first element
654  * be one of the above algorithm identifiers and the following
655  * elements are pairs with parameter-id and value.
656  * NOTE: we look through the list to find a list beginning with
657  * "private-key" or "public-key" - the first one found is used.
658  *
659  * FIXME: Allow for encrypted secret keys here.
660  *
661  * Returns: A pointer to an allocated array of MPIs if the return value is
662  *          zero; the caller has to release this array.
663  *
664  * Example of a DSA public key:
665  *  (private-key
666  *    (dsa
667  *      (p <mpi>)
668  *      (g <mpi>)
669  *      (y <mpi>)
670  *      (x <mpi>)
671  *    )
672  *  )
673  * The <mpi> are expected to be in GCRYMPI_FMT_USG
674  */
675 static int
676 sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
677 {
678     GCRY_SEXP list, l2;
679     const char *name;
680     const char *s;
681     size_t n;
682     int i, idx;
683     int algo;
684     const char *elems1, *elems2;
685     GCRY_MPI *array;
686
687     /* check that the first element is valid */
688     list = gcry_sexp_find_token( sexp, want_private? "private-key"
689                                                     :"public-key", 0 );
690     if( !list )
691         return GCRYERR_INV_OBJ; /* Does not contain a public- or private-key object */
692     l2 = gcry_sexp_cadr( list );
693     gcry_sexp_release ( list );
694     list = l2;
695     name = gcry_sexp_nth_data( list, 0, &n );
696     if( !name ) {
697         gcry_sexp_release ( list );
698         return GCRYERR_INV_OBJ; /* invalid structure of object */
699     }
700     for(i=0; (s=algo_info_table[i].name); i++ ) {
701         if( strlen(s) == n && !memcmp( s, name, n ) )
702             break;
703     }
704     if( !s ) {
705         gcry_sexp_release ( list );
706         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
707     }
708     algo = algo_info_table[i].algo;
709     elems1 = algo_info_table[i].common_elements;
710     elems2 = want_private? algo_info_table[i].secret_elements
711                          : algo_info_table[i].public_elements;
712     array = gcry_calloc( strlen(elems1)+strlen(elems2)+1, sizeof *array );
713     if( !array ) {
714         gcry_sexp_release ( list );
715         return GCRYERR_NO_MEM;
716     }
717
718     idx = 0;
719     for(s=elems1; *s; s++, idx++ ) {
720         l2 = gcry_sexp_find_token( list, s, 1 );
721         if( !l2 ) {
722             for(i=0; i<idx; i++)
723                 gcry_free( array[i] );
724             gcry_free( array );
725             gcry_sexp_release ( list );
726             return GCRYERR_NO_OBJ; /* required parameter not found */
727         }
728         array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
729         gcry_sexp_release ( l2 );
730         if( !array[idx] ) {
731             for(i=0; i<idx; i++)
732                 gcry_free( array[i] );
733             gcry_free( array );
734             gcry_sexp_release ( list );
735             return GCRYERR_INV_OBJ; /* required parameter is invalid */
736         }
737     }
738     for(s=elems2; *s; s++, idx++ ) {
739         l2 = gcry_sexp_find_token( list, s, 1 );
740         if( !l2 ) {
741             for(i=0; i<idx; i++)
742                 gcry_free( array[i] );
743             gcry_free( array );
744             gcry_sexp_release ( list );
745             return GCRYERR_NO_OBJ; /* required parameter not found */
746         }
747         array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
748         gcry_sexp_release ( l2 );
749         if( !array[idx] ) {
750             for(i=0; i<idx; i++)
751                 gcry_free( array[i] );
752             gcry_free( array );
753             gcry_sexp_release ( list );
754             return GCRYERR_INV_OBJ; /* required parameter is invalid */
755         }
756     }
757
758     gcry_sexp_release ( list );
759     *retarray = array;
760     *retalgo = algo;
761
762     return 0;
763 }
764
765 static int
766 sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
767 {
768     GCRY_SEXP list, l2;
769     const char *name;
770     const char *s;
771     size_t n;
772     int i, idx;
773     int algo;
774     const char *elems;
775     GCRY_MPI *array;
776
777     /* check that the first element is valid */
778     list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
779     if( !list )
780         return GCRYERR_INV_OBJ; /* Does not contain a signature value object */
781     l2 = gcry_sexp_cadr( list );
782     gcry_sexp_release ( list );
783     list = l2;
784     if( !list )
785         return GCRYERR_NO_OBJ; /* no cadr for the sig object */
786     name = gcry_sexp_nth_data( list, 0, &n );
787     if( !name ) {
788         gcry_sexp_release ( list );
789         return GCRYERR_INV_OBJ; /* invalid structure of object */
790     }
791     for(i=0; (s=sig_info_table[i].name); i++ ) {
792         if( strlen(s) == n && !memcmp( s, name, n ) )
793             break;
794     }
795     if( !s ) {
796         gcry_sexp_release ( list );
797         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
798     }
799     algo = sig_info_table[i].algo;
800     elems = sig_info_table[i].elements;
801     array = gcry_calloc( (strlen(elems)+1) , sizeof *array );
802     if( !array ) {
803         gcry_sexp_release ( list );
804         return GCRYERR_NO_MEM;
805     }
806
807     idx = 0;
808     for(s=elems; *s; s++, idx++ ) {
809         l2 = gcry_sexp_find_token( list, s, 1 );
810         if( !l2 ) {
811             gcry_free( array );
812             gcry_sexp_release ( list );
813             return GCRYERR_NO_OBJ; /* required parameter not found */
814         }
815         array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
816         gcry_sexp_release ( l2 );
817         if( !array[idx] ) {
818             gcry_free( array );
819             gcry_sexp_release ( list );
820             return GCRYERR_INV_OBJ; /* required parameter is invalid */
821         }
822     }
823
824     gcry_sexp_release ( list );
825     *retarray = array;
826     *retalgo = algo;
827
828     return 0;
829 }
830
831
832 /****************
833  * Take sexp and return an array of MPI as used for our internal decrypt
834  * function.
835  */
836 static int
837 sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
838 {
839     GCRY_SEXP list, l2;
840     const char *name;
841     const char *s;
842     size_t n;
843     int i, idx;
844     int algo;
845     const char *elems;
846     GCRY_MPI *array;
847
848     /* check that the first element is valid */
849     list = gcry_sexp_find_token( sexp, "enc-val" , 0 );
850     if( !list )
851         return GCRYERR_INV_OBJ; /* Does not contain a encrypted value object */
852     l2 = gcry_sexp_cadr( list );
853     gcry_sexp_release ( list );
854     list = l2;
855     if( !list ) {
856         gcry_sexp_release ( list );
857         return GCRYERR_NO_OBJ; /* no cdr for the data object */
858     }
859     name = gcry_sexp_nth_data( list, 0, &n );
860     if( !name ) {
861         gcry_sexp_release ( list );
862         return GCRYERR_INV_OBJ; /* invalid structure of object */
863     }
864     for(i=0; (s=enc_info_table[i].name); i++ ) {
865         if( strlen(s) == n && !memcmp( s, name, n ) )
866             break;
867     }
868     if( !s ) {
869         gcry_sexp_release ( list );
870         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
871     }
872
873     algo = enc_info_table[i].algo;
874     elems = enc_info_table[i].elements;
875     array = gcry_calloc( (strlen(elems)+1) , sizeof *array );
876     if( !array ) {
877         gcry_sexp_release ( list );
878         return GCRYERR_NO_MEM;
879     }
880
881     idx = 0;
882     for(s=elems; *s; s++, idx++ ) {
883         l2 = gcry_sexp_find_token( list, s, 1 );
884         if( !l2 ) {
885             gcry_free( array );
886             gcry_sexp_release ( list );
887             return GCRYERR_NO_OBJ; /* required parameter not found */
888         }
889         array[idx] = gcry_sexp_nth_mpi( l2, 1, GCRYMPI_FMT_USG );
890         gcry_sexp_release ( l2 );
891         if( !array[idx] ) {
892             gcry_free( array );
893             gcry_sexp_release ( list );
894             return GCRYERR_INV_OBJ; /* required parameter is invalid */
895         }
896     }
897
898     gcry_sexp_release ( list );
899     *retarray = array;
900     *retalgo = algo;
901
902     return 0;
903 }
904
905
906 /****************
907  * Do a PK encrypt operation
908  *
909  * Caller has to provide a public key as the SEXP pkey and data as a SEXP
910  * with just one MPI in it.  The function returns a a sexp which may
911  * be passed to to pk_decrypt.
912  * Later versions of this functions may take more complex input data, for 
913  * example s_data could have a control tag which allows us to to PKCS-1
914  * encoding directly here.
915  *
916  * Returns: 0 or an errorcode.
917  *
918  * s_data = (<mpi>)
919  * s_pkey = <key-as-defined-in-sexp_to_key>
920  * r_ciph = (enc-val
921  *            (<algo>
922  *              (<param_name1> <mpi>)
923  *              ...
924  *              (<param_namen> <mpi>)
925  *            ))
926  */
927 int
928 gcry_pk_encrypt( GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey )
929 {
930     MPI *pkey, data, *ciph;
931     const char *algo_name, *algo_elems;
932     int i, rc, algo;
933
934     /* get the key */
935     rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
936     if( rc ) {
937         return rc;
938     }
939
940     /* get the name and the required size of the return value */
941     for(i=0; (algo_name = enc_info_table[i].name); i++ ) {
942         if( enc_info_table[i].algo == algo )
943             break;
944     }
945     if( !algo_name ) {
946         release_mpi_array( pkey );
947         return GCRYERR_INV_PK_ALGO;
948     }
949     algo_elems = enc_info_table[i].elements;
950
951     /* get the stuff we want to encrypt */
952     data = gcry_sexp_nth_mpi( s_data, 0, 0 );
953     if( !data ) {
954         release_mpi_array( pkey );
955         return GCRYERR_INV_OBJ;
956     }
957
958     /* Now we can encrypt data to ciph */
959     ciph = gcry_xcalloc( (strlen(algo_elems)+1) , sizeof *ciph );
960     rc = pubkey_encrypt( algo, ciph, data, pkey );
961     release_mpi_array( pkey );
962     mpi_free( data );
963     if( rc ) {
964         release_mpi_array( ciph );
965         gcry_free( ciph );
966         return rc;
967     }
968
969     /* We did it.  Now build the return list */
970     {
971         char *string, *p;
972         size_t nelem, needed= strlen(algo_name) + 20;
973
974         /* count elements, so that we can allocate enough space */
975         for(nelem=0; algo_elems[nelem]; nelem++ )
976             needed += 10; /* 6 + a safety margin */
977         /* build the string */
978         string = p = gcry_xmalloc ( needed );
979         p = stpcpy ( p, "(enc-val(" );
980         p = stpcpy ( p, algo_name );
981         for(i=0; algo_elems[i]; i++ ) {
982             *p++ = '(';
983             *p++ = algo_elems[i];
984             p = stpcpy ( p, "%m)" );
985         }
986         strcpy ( p, "))" );
987         /* and now the ugly part:  we don't have a function to
988          * pass an array to a format string, so we have to do it this way :-(
989          */
990         switch ( nelem ) {
991           case 1: rc = gcry_sexp_build ( r_ciph, NULL, string,
992                      ciph[0]
993                   ); break;
994           case 2: rc = gcry_sexp_build ( r_ciph, NULL, string,
995                      ciph[0], ciph[1]
996                   ); break;
997           case 3: rc = gcry_sexp_build ( r_ciph, NULL, string,
998                      ciph[0], ciph[1], ciph[2]
999                   ); break;
1000           case 4: rc = gcry_sexp_build ( r_ciph, NULL, string,
1001                      ciph[0], ciph[1], ciph[2], ciph[3]
1002                   ); break;
1003           case 5: rc = gcry_sexp_build ( r_ciph, NULL, string,
1004                      ciph[0], ciph[1], ciph[2], ciph[3], ciph[4]
1005                   ); break;
1006           case 6: rc = gcry_sexp_build ( r_ciph, NULL, string,
1007                      ciph[0], ciph[1], ciph[2], ciph[3], ciph[4], ciph[5]
1008                   ); break;
1009           default: BUG ();
1010         }
1011         if ( rc )
1012             BUG ();
1013         gcry_free ( string );
1014     }
1015     release_mpi_array( ciph );
1016     gcry_free( ciph );
1017
1018
1019     return 0;
1020 }
1021
1022 /****************
1023  * Do a PK decrypt operation
1024  *
1025  * Caller has to provide a secret key as the SEXP skey and data in a format
1026  * as created by gcry_pk_encrypt.  Currently the function returns
1027  * simply a MPI.  Later versions of this functions may return a more
1028  * complex data structure.
1029  *
1030  * Returns: 0 or an errorcode.
1031  *
1032  * s_data = (enc-val
1033  *            (<algo>
1034  *              (<param_name1> <mpi>)
1035  *              ...
1036  *              (<param_namen> <mpi>)
1037  *            ))
1038  * s_skey = <key-as-defined-in-sexp_to_key>
1039  * r_plain= (<mpi>)   FIXME: Return a more structered value
1040  */
1041 int
1042 gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey )
1043 {
1044     MPI *skey, *data, plain;
1045     int rc, algo, dataalgo;
1046
1047     rc = sexp_to_key( s_skey, 1, &skey, &algo );
1048     if( rc ) {
1049         return rc;
1050     }
1051     rc = sexp_to_enc( s_data, &data, &dataalgo );
1052     if( rc ) {
1053         release_mpi_array( skey );
1054         return rc;
1055     }
1056     if( algo != dataalgo ) {
1057         release_mpi_array( skey );
1058         release_mpi_array( data );
1059         return -1; /* fixme: add real errornumber - algo does not match */
1060     }
1061
1062     rc = pubkey_decrypt( algo, &plain, data, skey );
1063     if( rc ) {
1064         release_mpi_array( skey );
1065         release_mpi_array( data );
1066         return -1; /* fixme: add real errornumber - decryption failed */
1067     }
1068
1069     if ( gcry_sexp_build( r_plain, NULL, "%m", plain ) )
1070         BUG ();
1071
1072     mpi_free( plain );
1073     release_mpi_array( data );
1074     release_mpi_array( skey );
1075     return 0;
1076 }
1077
1078
1079
1080 /****************
1081  * Create a signature.
1082  *
1083  * Caller has to provide a secret key as the SEXP skey and data expressed
1084  * as a SEXP list hash with only one element which should instantly be
1085  * available as a MPI.  Later versions of this functions may provide padding
1086  * and other things depending on data.
1087  *
1088  * Returns: 0 or an errorcode.
1089  *          In case of 0 the function returns a new SEXP with the
1090  *          signature value; the structure of this signature depends on the
1091  *          other arguments but is always suitable to be passed to
1092  *          gcry_pk_verify
1093  *
1094  * s_hash = (<mpi>)
1095  * s_skey = <key-as-defined-in-sexp_to_key>
1096  * r_sig  = (sig-val
1097  *            (<algo>
1098  *              (<param_name1> <mpi>)
1099  *              ...
1100  *              (<param_namen> <mpi>)
1101  *            ))
1102  */
1103 int
1104 gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
1105 {
1106     MPI *skey, hash;
1107     MPI *result;
1108     int i, algo, rc;
1109     const char *algo_name, *algo_elems;
1110
1111     rc = sexp_to_key( s_skey, 1, &skey, &algo );
1112     if( rc )
1113         return rc;
1114
1115     /* get the name and the required size of the result array */
1116     for(i=0; (algo_name = sig_info_table[i].name); i++ ) {
1117         if( sig_info_table[i].algo == algo )
1118             break;
1119     }
1120     if( !algo_name ) {
1121         release_mpi_array( skey );
1122         return -4; /* oops: unknown algorithm */
1123     }
1124     algo_elems = sig_info_table[i].elements;
1125
1126     /* get the stuff we want to sign */
1127     hash = gcry_sexp_nth_mpi( s_hash, 0, 0 );
1128     if( !hash ) {
1129         release_mpi_array( skey );
1130         return -1; /* fixme: get a real errorcode for this */
1131     }
1132     result = gcry_xcalloc( (strlen(algo_elems)+1) , sizeof *result );
1133     rc = pubkey_sign( algo, result, hash, skey );
1134     release_mpi_array( skey );
1135     mpi_free( hash );
1136     if( rc ) {
1137         gcry_free( result );
1138         return rc;
1139     }
1140
1141     {
1142         char *string, *p;
1143         size_t nelem, needed= strlen(algo_name) + 20;
1144
1145         /* count elements, so that we can allocate enough space */
1146         for(nelem=0; algo_elems[nelem]; nelem++ )
1147             needed += 10; /* 6 + a safety margin */
1148         /* build the string */
1149         string = p = gcry_xmalloc ( needed );
1150         p = stpcpy ( p, "(sig-val(" );
1151         p = stpcpy ( p, algo_name );
1152         for(i=0; algo_elems[i]; i++ ) {
1153             *p++ = '(';
1154             *p++ = algo_elems[i];
1155             p = stpcpy ( p, "%m)" );
1156         }
1157         strcpy ( p, "))" );
1158         /* and now the ugly part:  we don't have a function to
1159          * pass an array to a format string, so we have to do it this way :-(
1160          */
1161         switch ( nelem ) {
1162           case 1: rc = gcry_sexp_build ( r_sig, NULL, string,
1163                      result[0]
1164                   ); break;
1165           case 2: rc = gcry_sexp_build ( r_sig, NULL, string,
1166                      result[0], result[1]
1167                   ); break;
1168           case 3: rc = gcry_sexp_build ( r_sig, NULL, string,
1169                      result[0], result[1], result[2]
1170                   ); break;
1171           case 4: rc = gcry_sexp_build ( r_sig, NULL, string,
1172                      result[0], result[1], result[2], result[3]
1173                   ); break;
1174           case 5: rc = gcry_sexp_build ( r_sig, NULL, string,
1175                      result[0], result[1], result[2], result[3], result[4]
1176                   ); break;
1177           case 6: rc = gcry_sexp_build ( r_sig, NULL, string,
1178                      result[0], result[1], result[2], result[3], result[4], result[5]
1179                   ); break;
1180           default: BUG ();
1181         }
1182         if ( rc )
1183             BUG ();
1184         gcry_free ( string );
1185     }
1186     release_mpi_array( result );
1187     gcry_free( result );
1188
1189     return 0;
1190 }
1191
1192
1193 /****************
1194  * Verify a sgnature.  Caller has to supply the public key pkey,
1195  * the signature sig and his hashvalue data.  Public key has to be
1196  * a standard public key given as an S-Exp, sig is a S-Exp as returned
1197  * from gcry_pk_sign and data must be an S-Exp like the one in sign too.
1198  */
1199 int
1200 gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
1201 {
1202     MPI *pkey, hash, *sig;
1203     int algo, sigalgo;
1204     int rc;
1205
1206     rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
1207     if( rc )
1208         return rc;
1209     rc = sexp_to_sig( s_sig, &sig, &sigalgo );
1210     if( rc ) {
1211         release_mpi_array( pkey );
1212         return rc;
1213     }
1214     if( algo != sigalgo ) {
1215         release_mpi_array( pkey );
1216         release_mpi_array( sig );
1217         return -1; /* fixme: add real errornumber - algo does not match */
1218     }
1219
1220     hash = gcry_sexp_nth_mpi( s_hash, 0, 0 );
1221     if( !hash ) {
1222         release_mpi_array( pkey );
1223         release_mpi_array( sig );
1224         return -1; /* fixme: get a real errorcode for this */
1225     }
1226
1227     rc = pubkey_verify( algo, hash, sig, pkey, NULL, NULL );
1228     release_mpi_array( pkey );
1229     release_mpi_array( sig );
1230     mpi_free(hash);
1231
1232     return rc;
1233 }
1234
1235
1236 /****************
1237  * Test a key.  This may be used either for a public or a secret key
1238  * to see whether internal structre is valid.
1239  *
1240  * Returns: 0 or an errorcode.
1241  *
1242  * s_key = <key-as-defined-in-sexp_to_key>
1243  */
1244 int
1245 gcry_pk_testkey( GCRY_SEXP s_key )
1246 {
1247     MPI *key;
1248     int rc, algo;
1249
1250     /* Note we currently support only secret key checking */
1251     rc = sexp_to_key( s_key, 1, &key, &algo );
1252     if( rc ) {
1253         return rc;
1254     }
1255
1256     rc = pubkey_check_secret_key( algo, key );
1257     release_mpi_array( key );
1258     return rc;
1259 }
1260
1261
1262 /****************
1263  * Create a public key pair and return it in r_key.
1264  * How the key is created depends on s_parms:
1265  * (genkey
1266  *  (algo
1267  *    (parameter_name_1 ....)
1268  *     ....
1269  *    (parameter_name_n ....)
1270  * ))
1271  * The key is returned in a format depending on the
1272  * algorithm. Both, private and secret keys are returned
1273  * and optionally some additional informatin.
1274  * For elgamal we return this structure:
1275  * (key-data
1276  *  (public-key
1277  *    (elg
1278  *      (p <mpi>)
1279  *      (g <mpi>)
1280  *      (y <mpi>)
1281  *    )
1282  *  )
1283  *  (private-key
1284  *    (elg
1285  *      (p <mpi>)
1286  *      (g <mpi>)
1287  *      (y <mpi>)
1288  *      (x <mpi>)
1289  *    )
1290  *  )
1291  *  (misc-key-info
1292  *     (pm1-factors n1 n2 ... nn)
1293  *  )
1294  * )
1295  */
1296 int
1297 gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
1298 {
1299     GCRY_SEXP list, l2;
1300     const char *name;
1301     const char *s;
1302     size_t n;
1303     int rc, i;
1304     const char *algo_name;
1305     int algo;
1306     char sec_elems[20], pub_elems[20];  /* fixme: check bounds */
1307     GCRY_MPI skey[10], *factors;
1308     unsigned int nbits;
1309
1310     list = gcry_sexp_find_token( s_parms, "genkey", 0 );
1311     if( !list )
1312         return GCRYERR_INV_OBJ; /* Does not contain genkey data */
1313     l2 = gcry_sexp_cadr( list );
1314     gcry_sexp_release ( list );
1315     list = l2;
1316     if( !list )
1317         return GCRYERR_NO_OBJ; /* no cdr for the genkey */
1318     name = gcry_sexp_nth_data( list, 0, &n );
1319     if( !name ) {
1320         gcry_sexp_release ( list );
1321         return GCRYERR_INV_OBJ; /* algo string missing */
1322     }
1323     for(i=0; (s=algo_info_table[i].name); i++ ) {
1324         if( strlen(s) == n && !memcmp( s, name, n ) )
1325             break;
1326     }
1327     if( !s ) {
1328         gcry_sexp_release ( list );
1329         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
1330     }
1331
1332     algo = algo_info_table[i].algo;
1333     algo_name = algo_info_table[i].name;
1334     strcpy( pub_elems, algo_info_table[i].common_elements );
1335     strcat( pub_elems, algo_info_table[i].public_elements );
1336     strcpy( sec_elems, algo_info_table[i].common_elements );
1337     strcat( sec_elems, algo_info_table[i].secret_elements );
1338
1339     l2 = gcry_sexp_find_token( list, "nbits", 0 );
1340     gcry_sexp_release ( list );
1341     list = l2;
1342     if( !list )
1343         return GCRYERR_NO_OBJ; /* no nbits parameter */
1344     name = gcry_sexp_nth_data( list, 1, &n );
1345     if( !name ) {
1346         gcry_sexp_release ( list );
1347         return GCRYERR_INV_OBJ; /* nbits without a cdr */
1348     }
1349     {
1350         char *p = gcry_xmalloc(n+1);
1351         memcpy(p, name, n );
1352         p[n] = 0;
1353         nbits = (unsigned int)strtol( p, NULL, 0 );
1354         gcry_free( p );
1355     }
1356     gcry_sexp_release ( list );
1357
1358     rc = pubkey_generate( algo, nbits, skey, &factors );
1359     if( rc ) {
1360         return rc;
1361     }
1362
1363     {
1364         char *string, *p;
1365         size_t nelem=0, needed=0;
1366         GCRY_MPI mpis[30];
1367
1368
1369         /* count elements, so that we can allocate enough space */
1370         for(i=0; pub_elems[i]; i++, nelem++ )
1371             needed += 10; /* 6 + a safety margin */
1372         for(i=0; sec_elems[i]; i++, nelem++ )
1373             needed += 10; /* 6 + a safety margin */
1374         for(i=0; factors[i]; i++, nelem++ )
1375             needed += 10; /* 6 + a safety margin */
1376         needed += 2* strlen(algo_name) +  300;
1377         if ( nelem > DIM(mpis) )
1378             BUG ();
1379
1380         /* build the string */
1381         nelem = 0;
1382         string = p = gcry_xmalloc ( needed );
1383         p = stpcpy ( p, "(key-data" );
1384
1385         p = stpcpy ( p, "(public-key(" );
1386         p = stpcpy ( p, algo_name );
1387         for(i=0; pub_elems[i]; i++ ) {
1388             *p++ = '(';
1389             *p++ = pub_elems[i];
1390             p = stpcpy ( p, "%m)" );
1391             mpis[nelem++] = skey[i];
1392         }
1393         p = stpcpy ( p, "))" );
1394
1395         p = stpcpy ( p, "(private-key(" );
1396         p = stpcpy ( p, algo_name );
1397         for(i=0; sec_elems[i]; i++ ) {
1398             *p++ = '(';
1399             *p++ = sec_elems[i];
1400             p = stpcpy ( p, "%m)" );
1401             mpis[nelem++] = skey[i];
1402         }
1403         p = stpcpy ( p, "))" );
1404         /* Very ugly hack to make release_mpi_array() work FIXME */
1405         skey[i] = NULL;
1406
1407         p = stpcpy ( p, "(misc-key-info(pm1-factors" );
1408         for(i=0; factors[i]; i++ ) {
1409             p = stpcpy ( p, "%m" );
1410             mpis[nelem++] = factors[i];
1411         }
1412         strcpy ( p, ")))" );
1413
1414         while ( nelem < DIM(mpis) )
1415             mpis[nelem++] = NULL;
1416
1417         /* and now the ugly part:  we don't have a function to
1418          * pass an array to a format string, so we have just pass everything
1419          * we have. which normally should be no problem as only those
1420          * with a corresponding %m are used
1421          */
1422         if ( gcry_sexp_build ( r_key, NULL, string,
1423                    mpis[0], mpis[1], mpis[2], mpis[3], mpis[4], mpis[5],
1424                    mpis[6], mpis[7], mpis[8], mpis[9], mpis[10], mpis[11],
1425                    mpis[12], mpis[13], mpis[14], mpis[15], mpis[16], mpis[17],
1426                    mpis[18], mpis[19], mpis[20], mpis[21], mpis[22], mpis[23],
1427                    mpis[24], mpis[25], mpis[26], mpis[27], mpis[28], mpis[29]
1428                   ) )
1429             BUG ();
1430         assert ( DIM(mpis) == 30 );
1431         gcry_free ( string );
1432     }
1433     release_mpi_array ( skey );
1434     release_mpi_array ( factors );
1435
1436     return 0;
1437 }
1438
1439 /****************
1440  * Get the number of nbits from the public key
1441  * Hmmm: Should we have really this function or is it
1442  * better to have a more general function to retrieve
1443  * different propoerties of the key?
1444  */
1445 unsigned int
1446 gcry_pk_get_nbits( GCRY_SEXP key )
1447 {
1448     int rc, i, algo;
1449     MPI *keyarr;
1450     unsigned int nbits = 0;
1451
1452     rc = sexp_to_key( key, 0, &keyarr, &algo );
1453     if( rc == GCRYERR_INV_OBJ )
1454         rc = sexp_to_key( key, 0, &keyarr, &algo );
1455     if( rc )
1456         return 0;
1457
1458     do {
1459         for(i=0; pubkey_table[i].name; i++ )
1460             if( pubkey_table[i].algo == algo ) {
1461                 nbits = (*pubkey_table[i].get_nbits)( algo, keyarr );
1462                 goto leave;
1463             }
1464     } while( load_pubkey_modules() );
1465     if( is_RSA(algo) )  /* we always wanna see the length of a key :-) */
1466         nbits = mpi_get_nbits( keyarr[0] );
1467   leave:
1468     release_mpi_array( keyarr );
1469     return nbits;
1470 }
1471
1472
1473
1474 int
1475 gcry_pk_ctl( int cmd, void *buffer, size_t buflen)
1476 {
1477     switch( cmd ) {
1478       case GCRYCTL_DISABLE_ALGO:
1479         /* this one expects a buffer pointing to an
1480          * integer with the algo number.
1481          */
1482         if( !buffer || buflen != sizeof(int) )
1483             return set_lasterr( GCRYERR_INV_CIPHER_ALGO );
1484         disable_pubkey_algo( *(int*)buffer );
1485         break;
1486
1487       default:
1488         return set_lasterr( GCRYERR_INV_OP );
1489     }
1490     return 0;
1491 }
1492
1493
1494 /****************
1495  * Return information about the given algorithm
1496  * WHAT select the kind of information returned:
1497  *  GCRYCTL_TEST_ALGO:
1498  *      Returns 0 when the specified algorithm is available for use.
1499  *      Buffer must be NULL, nbytes  may have the address of a variable
1500  *      with the required usage of the algorithm. It may be 0 for don't
1501  *      care or a combination of the GCRY_PK_USAGE_xxx flags;
1502  *  GCRYCTL_GET_ALGO_USAGE:
1503  *      Return the usage glafs for the give algo.  An invalid alog
1504  *      does return 0.  Disabled algos are ignored here becuase we
1505  *      only want to know whether the algo is at all capable of
1506  *      the usage.
1507  *
1508  * On error the value -1 is returned and the error reason may be
1509  * retrieved by gcry_errno().
1510  * Note:  Because this function is in most caes used to return an
1511  * integer value, we can make it easier for the caller to just look at
1512  * the return value.  The caller will in all cases consult the value
1513  * and thereby detecting whether a error occured or not (i.e. while checking
1514  * the block size)
1515  */
1516 int
1517 gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes)
1518 {
1519     switch( what ) {
1520       case GCRYCTL_TEST_ALGO: {
1521             int use = nbytes? *nbytes: 0;
1522             if( buffer ) {
1523                 set_lasterr( GCRYERR_INV_ARG );
1524                 return -1;
1525             }
1526             if( check_pubkey_algo( algo, use ) ) {
1527                 set_lasterr( GCRYERR_INV_PK_ALGO );
1528                 return -1;
1529             }
1530         }
1531         break;
1532
1533       case GCRYCTL_GET_ALGO_USAGE: 
1534           do {
1535               int i;
1536               for(i=0; pubkey_table[i].name; i++ )
1537                   if( pubkey_table[i].algo == algo ) 
1538                       return pubkey_table[i].use;
1539           } while( load_pubkey_modules() );
1540           return 0;
1541          
1542       case GCRYCTL_GET_ALGO_NPKEY: return pubkey_get_npkey( algo );
1543       case GCRYCTL_GET_ALGO_NSKEY: return pubkey_get_nskey( algo );
1544       case GCRYCTL_GET_ALGO_NSIGN: return pubkey_get_nsig( algo );
1545       case GCRYCTL_GET_ALGO_NENCR: return pubkey_get_nenc( algo );
1546
1547       default:
1548         set_lasterr( GCRYERR_INV_OP );
1549         return -1;
1550     }
1551     return 0;
1552 }
1553
1554