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