4def6f6992f0d87d8d904b50d053688af41b786f
[gnupg.git] / cipher / pubkey.c
1 /* pubkey.c  -  pubkey dispatcher
2  *      Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG 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  * GnuPG 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 "dynload.h"
34
35 /* FIXME: use set_lasterr() */
36
37 #define TABLE_SIZE 10
38
39 struct pubkey_table_s {
40     const char *name;
41     int algo;
42     int npkey;
43     int nskey;
44     int nenc;
45     int nsig;
46     int use;
47     int (*generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
48     int (*check_secret_key)( int algo, MPI *skey );
49     int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey );
50     int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey );
51     int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey );
52     int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey,
53                    int (*cmp)(void *, MPI), void *opaquev );
54     unsigned (*get_nbits)( int algo, MPI *pkey );
55 };
56
57 static struct pubkey_table_s pubkey_table[TABLE_SIZE];
58 static int disabled_algos[TABLE_SIZE];
59
60 static struct { const char* name; int algo;
61                 const char* common_elements;
62                 const char* public_elements;
63                 const char* secret_elements;
64 } algo_info_table[] = {
65         {  "dsa"            , PUBKEY_ALGO_DSA       , "pqgy", "", "x"    },
66         {  "rsa"            , PUBKEY_ALGO_RSA       , "ne",   "", "dpqu" },
67         {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "pgy",  "", "x"    },
68         {  "openpgp-dsa"    , PUBKEY_ALGO_DSA       , "pqgy", "", "x"    },
69         {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "pqgy", "", "x"    },
70         {  "openpgp-elg"    , PUBKEY_ALGO_ELGAMAL_E , "pgy",  "", "x"    },
71         {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "pgy",  "", "x"    },
72         {  NULL }};
73
74 static struct {
75     const char* name; int algo;
76     const char* elements;
77 } sig_info_table[] = {
78         {  "dsa"            , PUBKEY_ALGO_DSA       , "rs" },
79         {  "rsa"            , PUBKEY_ALGO_RSA       , "s"  },
80         {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "rs" },
81         {  "openpgp-dsa"    , PUBKEY_ALGO_DSA       , "rs" },
82         {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "s"  },
83         {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "rs" },
84         {  NULL }};
85
86 static struct {
87     const char* name; int algo;
88     const char* elements;
89 } enc_info_table[] = {
90         {  "elg"            , PUBKEY_ALGO_ELGAMAL   , "ab" },
91         {  "rsa"            , PUBKEY_ALGO_RSA       , "a"  },
92         {  "openpgp-rsa"    , PUBKEY_ALGO_RSA       , "a"  },
93         {  "openpgp-elg"    , PUBKEY_ALGO_ELGAMAL_E , "ab" },
94         {  "openpgp-elg-sig", PUBKEY_ALGO_ELGAMAL   , "ab" },
95         {  NULL }};
96
97
98 static int pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey );
99 static int pubkey_sign( int algo, MPI *resarr, MPI hash, MPI *skey );
100 static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
101                       int (*cmp)(void *, MPI), void *opaque );
102
103 static int
104 dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
105 { log_bug("no generate() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
106
107 static int
108 dummy_check_secret_key( int algo, MPI *skey )
109 { log_bug("no check_secret_key() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
110
111 static int
112 dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
113 { log_bug("no encrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
114
115 static int
116 dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
117 { log_bug("no decrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
118
119 static int
120 dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey )
121 { log_bug("no sign() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
122
123 static int
124 dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey,
125                 int (*cmp)(void *, MPI), void *opaquev )
126 { log_bug("no verify() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
127
128 static unsigned
129 dummy_get_nbits( int algo, MPI *pkey )
130 { log_bug("no get_nbits() for %d\n", algo ); return 0; }
131
132
133 /****************
134  * Put the static entries into the table.
135  * This is out constructor function which fill the table
136  * of algorithms with the one we have statically linked.
137  */
138 static void
139 setup_pubkey_table(void)
140 {
141     int i;
142
143     i = 0;
144     pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL;
145     pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
146                                          &pubkey_table[i].npkey,
147                                          &pubkey_table[i].nskey,
148                                          &pubkey_table[i].nenc,
149                                          &pubkey_table[i].nsig,
150                                          &pubkey_table[i].use );
151     pubkey_table[i].generate         = elg_generate;
152     pubkey_table[i].check_secret_key = elg_check_secret_key;
153     pubkey_table[i].encrypt          = elg_encrypt;
154     pubkey_table[i].decrypt          = elg_decrypt;
155     pubkey_table[i].sign             = elg_sign;
156     pubkey_table[i].verify           = elg_verify;
157     pubkey_table[i].get_nbits        = elg_get_nbits;
158     if( !pubkey_table[i].name )
159         BUG();
160     i++;
161     pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E;
162     pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
163                                          &pubkey_table[i].npkey,
164                                          &pubkey_table[i].nskey,
165                                          &pubkey_table[i].nenc,
166                                          &pubkey_table[i].nsig,
167                                          &pubkey_table[i].use );
168     pubkey_table[i].generate         = elg_generate;
169     pubkey_table[i].check_secret_key = elg_check_secret_key;
170     pubkey_table[i].encrypt          = elg_encrypt;
171     pubkey_table[i].decrypt          = elg_decrypt;
172     pubkey_table[i].sign             = elg_sign;
173     pubkey_table[i].verify           = elg_verify;
174     pubkey_table[i].get_nbits        = elg_get_nbits;
175     if( !pubkey_table[i].name )
176         BUG();
177     i++;
178     pubkey_table[i].algo = PUBKEY_ALGO_DSA;
179     pubkey_table[i].name = dsa_get_info( pubkey_table[i].algo,
180                                          &pubkey_table[i].npkey,
181                                          &pubkey_table[i].nskey,
182                                          &pubkey_table[i].nenc,
183                                          &pubkey_table[i].nsig,
184                                          &pubkey_table[i].use );
185     pubkey_table[i].generate         = dsa_generate;
186     pubkey_table[i].check_secret_key = dsa_check_secret_key;
187     pubkey_table[i].encrypt          = dummy_encrypt;
188     pubkey_table[i].decrypt          = dummy_decrypt;
189     pubkey_table[i].sign             = dsa_sign;
190     pubkey_table[i].verify           = dsa_verify;
191     pubkey_table[i].get_nbits        = dsa_get_nbits;
192     if( !pubkey_table[i].name )
193         BUG();
194     i++;
195
196     for( ; i < TABLE_SIZE; i++ )
197         pubkey_table[i].name = NULL;
198 }
199
200 static void
201 release_mpi_array( MPI *array )
202 {
203     for( ; *array; array++ ) {
204         mpi_free(*array);
205         *array = NULL;
206     }
207 }
208
209 /****************
210  * Try to load all modules and return true if new modules are available
211  */
212 static int
213 load_pubkey_modules(void)
214 {
215     static int initialized = 0;
216     static int done = 0;
217     void *context = NULL;
218     struct pubkey_table_s *ct;
219     int ct_idx;
220     int i;
221     const char *name;
222     int any = 0;
223
224
225     if( !initialized ) {
226         cipher_modules_constructor();
227         setup_pubkey_table();
228         initialized = 1;
229         return 1;
230     }
231     if( done )
232         return 0;
233     done = 1;
234     for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
235         if( !ct->name )
236             break;
237     }
238     if( ct_idx >= TABLE_SIZE-1 )
239         BUG(); /* table already full */
240     /* now load all extensions */
241     while( (name = enum_gnupgext_pubkeys( &context, &ct->algo,
242                                 &ct->npkey, &ct->nskey, &ct->nenc,
243                                 &ct->nsig,  &ct->use,
244                                 &ct->generate,
245                                 &ct->check_secret_key,
246                                 &ct->encrypt,
247                                 &ct->decrypt,
248                                 &ct->sign,
249                                 &ct->verify,
250                                 &ct->get_nbits )) ) {
251         for(i=0; pubkey_table[i].name; i++ )
252             if( pubkey_table[i].algo == ct->algo )
253                 break;
254         if( pubkey_table[i].name ) {
255             log_info("skipping pubkey %d: already loaded\n", ct->algo );
256             continue;
257         }
258
259         if( !ct->generate  )  ct->generate = dummy_generate;
260         if( !ct->check_secret_key )  ct->check_secret_key =
261                                                     dummy_check_secret_key;
262         if( !ct->encrypt   )  ct->encrypt  = dummy_encrypt;
263         if( !ct->decrypt   )  ct->decrypt  = dummy_decrypt;
264         if( !ct->sign      )  ct->sign     = dummy_sign;
265         if( !ct->verify    )  ct->verify   = dummy_verify;
266         if( !ct->get_nbits )  ct->get_nbits= dummy_get_nbits;
267         /* put it into the table */
268         if( g10_log_verbosity( 2 ) )
269             log_info("loaded pubkey %d (%s)\n", ct->algo, name);
270         ct->name = name;
271         ct_idx++;
272         ct++;
273         any = 1;
274         /* check whether there are more available table slots */
275         if( ct_idx >= TABLE_SIZE-1 ) {
276             log_info("pubkey table full; ignoring other extensions\n");
277             break;
278         }
279     }
280     enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL,
281                                NULL, NULL, NULL, NULL, NULL, NULL, NULL );
282     return any;
283 }
284
285
286 /****************
287  * Map a string to the pubkey algo
288  */
289 int
290 gcry_pk_map_name( const char *string )
291 {
292     int i;
293     const char *s;
294
295     do {
296         for(i=0; (s=pubkey_table[i].name); i++ )
297             if( !stricmp( s, string ) )
298                 return pubkey_table[i].algo;
299     } while( load_pubkey_modules() );
300     return 0;
301 }
302
303
304 /****************
305  * Map a pubkey algo to a string
306  */
307 const char *
308 gcry_pk_algo_name( int algo )
309 {
310     int i;
311
312     do {
313         for(i=0; pubkey_table[i].name; i++ )
314             if( pubkey_table[i].algo == algo )
315                 return pubkey_table[i].name;
316     } while( load_pubkey_modules() );
317     return NULL;
318 }
319
320
321 static void
322 disable_pubkey_algo( int algo )
323 {
324     int i;
325
326     for(i=0; i < DIM(disabled_algos); i++ ) {
327         if( !disabled_algos[i] || disabled_algos[i] == algo ) {
328             disabled_algos[i] = algo;
329             return;
330         }
331     }
332     log_fatal("can't disable pubkey algo %d: table full\n", algo );
333 }
334
335
336 /****************
337  * a use of 0 means: don't care
338  */
339 static int
340 check_pubkey_algo( int algo, unsigned use )
341 {
342     int i;
343
344     do {
345         for(i=0; pubkey_table[i].name; i++ )
346             if( pubkey_table[i].algo == algo ) {
347                 if( (use & GCRY_PK_USAGE_SIGN)
348                     && !(pubkey_table[i].use & GCRY_PK_USAGE_SIGN) )
349                     return GCRYERR_WRONG_PK_ALGO;
350                 if( (use & GCRY_PK_USAGE_ENCR)
351                     && !(pubkey_table[i].use & GCRY_PK_USAGE_ENCR) )
352                     return GCRYERR_WRONG_PK_ALGO;
353
354                 for(i=0; i < DIM(disabled_algos); i++ ) {
355                     if( disabled_algos[i] == algo )
356                         return GCRYERR_INV_PK_ALGO;
357                 }
358                 return 0; /* okay */
359             }
360     } while( load_pubkey_modules() );
361     return GCRYERR_INV_PK_ALGO;
362 }
363
364
365
366
367 /****************
368  * Return the number of public key material numbers
369  */
370 static int
371 pubkey_get_npkey( int algo )
372 {
373     int i;
374     do {
375         for(i=0; pubkey_table[i].name; i++ )
376             if( pubkey_table[i].algo == algo )
377                 return pubkey_table[i].npkey;
378     } while( load_pubkey_modules() );
379     if( is_RSA(algo) )    /* special hack, so that we are able to */
380         return 2;         /* see the RSA keyids */
381     return 0;
382 }
383
384 /****************
385  * Return the number of secret key material numbers
386  */
387 static int
388 pubkey_get_nskey( int algo )
389 {
390     int i;
391     do {
392         for(i=0; pubkey_table[i].name; i++ )
393             if( pubkey_table[i].algo == algo )
394                 return pubkey_table[i].nskey;
395     } while( load_pubkey_modules() );
396     if( is_RSA(algo) )    /* special hack, so that we are able to */
397         return 6;         /* see the RSA keyids */
398     return 0;
399 }
400
401 /****************
402  * Return the number of signature material numbers
403  */
404 static int
405 pubkey_get_nsig( int algo )
406 {
407     int i;
408     do {
409         for(i=0; pubkey_table[i].name; i++ )
410             if( pubkey_table[i].algo == algo )
411                 return pubkey_table[i].nsig;
412     } while( load_pubkey_modules() );
413     if( is_RSA(algo) )    /* special hack, so that we are able to */
414         return 1;         /* see the RSA keyids */
415     return 0;
416 }
417
418 /****************
419  * Return the number of encryption material numbers
420  */
421 static int
422 pubkey_get_nenc( int algo )
423 {
424     int i;
425     do {
426         for(i=0; pubkey_table[i].name; i++ )
427             if( pubkey_table[i].algo == algo )
428                 return pubkey_table[i].nenc;
429     } while( load_pubkey_modules() );
430     if( is_RSA(algo) )    /* special hack, so that we are able to */
431         return 1;         /* see the RSA keyids */
432     return 0;
433 }
434
435
436 static int
437 pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
438 {
439     int i;
440
441     do {
442         for(i=0; pubkey_table[i].name; i++ )
443             if( pubkey_table[i].algo == algo )
444                 return (*pubkey_table[i].generate)( algo, nbits,
445                                                     skey, retfactors );
446     } while( load_pubkey_modules() );
447     return GCRYERR_INV_PK_ALGO;
448 }
449
450
451 static int
452 pubkey_check_secret_key( int algo, MPI *skey )
453 {
454     int i;
455
456     do {
457         for(i=0; pubkey_table[i].name; i++ )
458             if( pubkey_table[i].algo == algo )
459                 return (*pubkey_table[i].check_secret_key)( algo, skey );
460     } while( load_pubkey_modules() );
461     return GCRYERR_INV_PK_ALGO;
462 }
463
464
465 /****************
466  * This is the interface to the public key encryption.
467  * Encrypt DATA with PKEY and put it into RESARR which
468  * should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
469  * algorithm allows this - check with pubkey_get_nenc() )
470  */
471 static int
472 pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
473 {
474     int i, rc;
475
476     if( DBG_CIPHER ) {
477         log_debug("pubkey_encrypt: algo=%d\n", algo );
478         for(i=0; i < pubkey_get_npkey(algo); i++ )
479             log_mpidump("  pkey:", pkey[i] );
480         log_mpidump("  data:", data );
481     }
482
483     do {
484         for(i=0; pubkey_table[i].name; i++ )
485             if( pubkey_table[i].algo == algo ) {
486                 rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey );
487                 goto ready;
488             }
489     } while( load_pubkey_modules() );
490     rc = GCRYERR_INV_PK_ALGO;
491   ready:
492     if( !rc && DBG_CIPHER ) {
493         for(i=0; i < pubkey_get_nenc(algo); i++ )
494             log_mpidump("  encr:", resarr[i] );
495     }
496     return rc;
497 }
498
499
500
501 /****************
502  * This is the interface to the public key decryption.
503  * ALGO gives the algorithm to use and this implicitly determines
504  * the size of the arrays.
505  * result is a pointer to a mpi variable which will receive a
506  * newly allocated mpi or NULL in case of an error.
507  */
508 static int
509 pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
510 {
511     int i, rc;
512
513     *result = NULL; /* so the caller can always do a mpi_free */
514     if( DBG_CIPHER ) {
515         log_debug("pubkey_decrypt: algo=%d\n", algo );
516         for(i=0; i < pubkey_get_nskey(algo); i++ )
517             log_mpidump("  skey:", skey[i] );
518         for(i=0; i < pubkey_get_nenc(algo); i++ )
519             log_mpidump("  data:", data[i] );
520     }
521
522     do {
523         for(i=0; pubkey_table[i].name; i++ )
524             if( pubkey_table[i].algo == algo ) {
525                 rc = (*pubkey_table[i].decrypt)( algo, result, data, skey );
526                 goto ready;
527             }
528     } while( load_pubkey_modules() );
529     rc = GCRYERR_INV_PK_ALGO;
530   ready:
531     if( !rc && DBG_CIPHER ) {
532         log_mpidump(" plain:", *result );
533     }
534     return rc;
535 }
536
537
538 /****************
539  * This is the interface to the public key signing.
540  * Sign data with skey and put the result into resarr which
541  * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
542  * algorithm allows this - check with pubkey_get_nsig() )
543  */
544 static int
545 pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
546 {
547     int i, rc;
548
549     if( DBG_CIPHER ) {
550         log_debug("pubkey_sign: algo=%d\n", algo );
551         for(i=0; i < pubkey_get_nskey(algo); i++ )
552             log_mpidump("  skey:", skey[i] );
553         log_mpidump("  data:", data );
554     }
555
556     do {
557         for(i=0; pubkey_table[i].name; i++ )
558             if( pubkey_table[i].algo == algo ) {
559                 rc = (*pubkey_table[i].sign)( algo, resarr, data, skey );
560                 goto ready;
561             }
562     } while( load_pubkey_modules() );
563     rc = GCRYERR_INV_PK_ALGO;
564   ready:
565     if( !rc && DBG_CIPHER ) {
566         for(i=0; i < pubkey_get_nsig(algo); i++ )
567             log_mpidump("   sig:", resarr[i] );
568     }
569     return rc;
570 }
571
572 /****************
573  * Verify a public key signature.
574  * Return 0 if the signature is good
575  */
576 static int
577 pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
578                     int (*cmp)(void *, MPI), void *opaquev )
579 {
580     int i, rc;
581
582     do {
583         for(i=0; pubkey_table[i].name; i++ )
584             if( pubkey_table[i].algo == algo ) {
585                 rc = (*pubkey_table[i].verify)( algo, hash, data, pkey,
586                                                             cmp, opaquev );
587                 goto ready;
588             }
589     } while( load_pubkey_modules() );
590     rc = GCRYERR_INV_PK_ALGO;
591   ready:
592     return rc;
593 }
594
595
596
597 /****************
598  * Convert a S-Exp with either a private or a public key to our
599  * internal format. Currently we do only support the following
600  * algorithms:
601  *    dsa
602  *    rsa
603  *    openpgp-dsa
604  *    openpgp-rsa
605  *    openpgp-elg
606  *    openpgp-elg-sig
607  * Provide a SE with the first element be either "private-key" or
608  * or "public-key". the followed by a list with its first element
609  * be one of the above algorithm identifiers and the following
610  * elements are pairs with parameter-id and value.
611  * NOTE: we look through the list to find a list beginning with
612  * "private-key" or "public-key" - the first one found is used.
613  *
614  * FIXME: Allow for encrypted secret keys here.
615  *
616  * Returns: A pointer to an allocated array of MPIs if the return value is
617  *          zero; the caller has to release this array.
618  *
619  * Example of a DSA public key:
620  *  (private-key
621  *    (dsa
622  *      (p <mpi>)
623  *      (g <mpi>)
624  *      (y <mpi>)
625  *      (x <mpi>)
626  *    )
627  *  )
628  * The <mpi> are expected to be in GCRYMPI_FMT_USG
629  */
630 static int
631 sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
632 {
633     GCRY_SEXP list, l2;
634     const char *name;
635     const char *s;
636     size_t n;
637     int i, idx;
638     int algo;
639     const char *elems1, *elems2;
640     GCRY_MPI *array;
641
642     /* check that the first element is valid */
643     list = gcry_sexp_find_token( sexp, want_private? "private-key"
644                                                     :"public-key", 0 );
645     if( !list )
646         return GCRYERR_INV_OBJ; /* Does not contain a public- or private-key object */
647     list = gcry_sexp_cdr( list );
648     if( !list )
649         return GCRYERR_NO_OBJ; /* no cdr for the key object */
650     name = gcry_sexp_car_data( list, &n );
651     if( !name )
652         return GCRYERR_INV_OBJ; /* invalid structure of object */
653     for(i=0; (s=algo_info_table[i].name); i++ ) {
654         if( strlen(s) == n && !memcmp( s, name, n ) )
655             break;
656     }
657     if( !s )
658         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
659     algo = algo_info_table[i].algo;
660     elems1 = algo_info_table[i].common_elements;
661     elems2 = want_private? algo_info_table[i].secret_elements
662                          : algo_info_table[i].public_elements;
663     array = g10_calloc( strlen(elems1)+strlen(elems2)+1, sizeof *array );
664     if( !array )
665         return GCRYERR_NO_MEM;
666
667     idx = 0;
668     for(s=elems1; *s; s++, idx++ ) {
669         l2 = gcry_sexp_find_token( list, s, 1 );
670         if( !l2 ) {
671             g10_free( array );
672             return GCRYERR_NO_OBJ; /* required parameter not found */
673         }
674         array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
675         if( !array[idx] ) {
676             g10_free( array );
677             return GCRYERR_INV_OBJ; /* required parameter is invalid */
678         }
679     }
680     for(s=elems2; *s; s++, idx++ ) {
681         l2 = gcry_sexp_find_token( list, s, 1 );
682         if( !l2 ) {
683             g10_free( array );
684             return GCRYERR_NO_OBJ; /* required parameter not found */
685         }
686         /* FIXME: put the MPI in secure memory when needed */
687         array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
688         if( !array[idx] ) {
689             g10_free( array );
690             return GCRYERR_INV_OBJ; /* required parameter is invalid */
691         }
692     }
693
694     *retarray = array;
695     *retalgo = algo;
696
697     return 0;
698 }
699
700 static int
701 sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
702 {
703     GCRY_SEXP list, l2;
704     const char *name;
705     const char *s;
706     size_t n;
707     int i, idx;
708     int algo;
709     const char *elems;
710     GCRY_MPI *array;
711
712     /* check that the first element is valid */
713     list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
714     if( !list )
715         return GCRYERR_INV_OBJ; /* Does not contain a signature value object */
716     list = gcry_sexp_cdr( list );
717     if( !list )
718         return GCRYERR_NO_OBJ; /* no cdr for the sig object */
719     name = gcry_sexp_car_data( list, &n );
720     if( !name )
721         return GCRYERR_INV_OBJ; /* invalid structure of object */
722     for(i=0; (s=sig_info_table[i].name); i++ ) {
723         if( strlen(s) == n && !memcmp( s, name, n ) )
724             break;
725     }
726     if( !s )
727         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
728     algo = sig_info_table[i].algo;
729     elems = sig_info_table[i].elements;
730     array = g10_calloc( (strlen(elems)+1) , sizeof *array );
731     if( !array )
732         return GCRYERR_NO_MEM;
733
734     idx = 0;
735     for(s=elems; *s; s++, idx++ ) {
736         l2 = gcry_sexp_find_token( list, s, 1 );
737         if( !l2 ) {
738             g10_free( array );
739             return GCRYERR_NO_OBJ; /* required parameter not found */
740         }
741         array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
742         if( !array[idx] ) {
743             g10_free( array );
744             return GCRYERR_INV_OBJ; /* required parameter is invalid */
745         }
746     }
747
748     *retarray = array;
749     *retalgo = algo;
750
751     return 0;
752 }
753
754
755 /****************
756  * Take sexp and return an array of MPI as used for our internal decrypt
757  * function.
758  */
759 static int
760 sexp_to_enc( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
761 {
762     GCRY_SEXP list, l2;
763     const char *name;
764     const char *s;
765     size_t n;
766     int i, idx;
767     int algo;
768     const char *elems;
769     GCRY_MPI *array;
770
771     /* check that the first element is valid */
772     list = gcry_sexp_find_token( sexp, "enc-val" , 0 );
773     if( !list )
774         return GCRYERR_INV_OBJ; /* Does not contain a encrypted value object */
775     list = gcry_sexp_cdr( list );
776     if( !list )
777         return GCRYERR_NO_OBJ; /* no cdr for the data object */
778     name = gcry_sexp_car_data( list, &n );
779     if( !name )
780         return GCRYERR_INV_OBJ; /* invalid structure of object */
781     for(i=0; (s=enc_info_table[i].name); i++ ) {
782         if( strlen(s) == n && !memcmp( s, name, n ) )
783             break;
784     }
785     if( !s )
786         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
787     algo = enc_info_table[i].algo;
788     elems = enc_info_table[i].elements;
789     array = g10_calloc( (strlen(elems)+1) , sizeof *array );
790     if( !array )
791         return GCRYERR_NO_MEM;
792
793     idx = 0;
794     for(s=elems; *s; s++, idx++ ) {
795         l2 = gcry_sexp_find_token( list, s, 1 );
796         if( !l2 ) {
797             g10_free( array );
798             return GCRYERR_NO_OBJ; /* required parameter not found */
799         }
800         array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
801         if( !array[idx] ) {
802             g10_free( array );
803             return GCRYERR_INV_OBJ; /* required parameter is invalid */
804         }
805     }
806
807     *retarray = array;
808     *retalgo = algo;
809
810     return 0;
811 }
812
813
814 /****************
815  * Do a PK encrypt operation
816  *
817  * Caller has to provide a public key as the SEXP pkey and data as a SEXP
818  * with just one MPI in it.  The function returns a a sexp which may
819  * be passed tp to pk_decrypt.
820  * Later versions of this functions may take more complex input data.
821  *
822  * Returns: 0 or an errorcode.
823  *
824  * s_data = (<mpi>)
825  * s_pkey = <key-as-defined-in-sexp_to_key>
826  * r_ciph = (enc-val
827  *            (<algo>
828  *              (<param_name1> <mpi>)
829  *              ...
830  *              (<param_namen> <mpi>)
831  *            ))
832  */
833 int
834 gcry_pk_encrypt( GCRY_SEXP *r_ciph, GCRY_SEXP s_data, GCRY_SEXP s_pkey )
835 {
836     MPI *pkey, data, *ciph;
837     const char *algo_name, *algo_elems;
838     GCRY_SEXP *s_elems;
839     int i, rc, algo;
840
841     /* get the key */
842     rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
843     if( rc ) {
844         return rc;
845     }
846
847     /* get the name and the required size of the return value */
848     for(i=0; (algo_name = enc_info_table[i].name); i++ ) {
849         if( enc_info_table[i].algo == algo )
850             break;
851     }
852     if( !algo_name ) {
853         release_mpi_array( pkey );
854         return GCRYERR_INV_PK_ALGO;
855     }
856     algo_elems = enc_info_table[i].elements;
857
858     /* get the stuff we want to encrypt */
859     data = gcry_sexp_car_mpi( s_data, 0 );
860     if( !data ) {
861         release_mpi_array( pkey );
862         return GCRYERR_INV_OBJ;
863     }
864
865     /* Now we can encrypt data to ciph */
866     ciph = g10_xcalloc( (strlen(algo_elems)+1) , sizeof *ciph );
867     rc = pubkey_encrypt( algo, ciph, data, pkey );
868     release_mpi_array( pkey );
869     mpi_free( data );
870     if( rc ) {
871         g10_free( ciph );
872         return rc;
873     }
874
875     /* We did it.  Now build the return list */
876     s_elems = g10_xcalloc( (strlen(algo_elems)+2), sizeof *s_elems );
877     s_elems[0] = SEXP_NEW( algo_name, 0 );
878     for(i=0; algo_elems[i]; i++ ) {
879         char tmp[2];
880         tmp[0] = algo_elems[i];
881         tmp[1] = 0;
882         s_elems[i+1] = gcry_sexp_new_name_mpi( tmp, ciph[i] );
883     }
884     release_mpi_array( ciph );
885     g10_free( ciph );
886
887     *r_ciph = SEXP_CONS( SEXP_NEW( "enc-val", 0 ),
888                          gcry_sexp_alist( s_elems ) );
889
890     g10_free( s_elems );
891     return 0;
892 }
893
894 /****************
895  * Do a PK decrypt operation
896  *
897  * Caller has to provide a secret key as the SEXP skey and data in a format
898  * as created by gcry_pk_encrypt.  Currently the function returns
899  * simply a MPI.  Later versions of this functions may return a more
900  * complex data structure.
901  *
902  * Returns: 0 or an errorcode.
903  *
904  * s_data = (enc-val
905  *            (<algo>
906  *              (<param_name1> <mpi>)
907  *              ...
908  *              (<param_namen> <mpi>)
909  *            ))
910  * s_skey = <key-as-defined-in-sexp_to_key>
911  * r_plain= (<mpi>)   FIXME: Return a more structered value
912  */
913 int
914 gcry_pk_decrypt( GCRY_SEXP *r_plain, GCRY_SEXP s_data, GCRY_SEXP s_skey )
915 {
916     MPI *skey, *data, plain;
917     int rc, algo, dataalgo;
918
919     rc = sexp_to_key( s_skey, 1, &skey, &algo );
920     if( rc ) {
921         return rc;
922     }
923     rc = sexp_to_enc( s_data, &data, &dataalgo );
924     if( rc ) {
925         release_mpi_array( skey );
926         return rc;
927     }
928     if( algo != dataalgo ) {
929         release_mpi_array( skey );
930         release_mpi_array( data );
931         return -1; /* fixme: add real errornumber - algo does not match */
932     }
933
934     rc = pubkey_decrypt( algo, &plain, data, skey );
935     if( rc ) {
936         release_mpi_array( skey );
937         release_mpi_array( data );
938         return -1; /* fixme: add real errornumber - decryption failed */
939     }
940
941     *r_plain = gcry_sexp_new_mpi( plain );
942     mpi_free( plain );
943     release_mpi_array( data );
944     release_mpi_array( skey );
945     return 0;
946 }
947
948
949
950 /****************
951  * Create a signature.
952  *
953  * Caller has to provide a secret key as the SEXP skey and data expressed
954  * as a SEXP list hash with only one element which should instantly be
955  * available as a MPI.  Later versions of this functions may provide padding
956  * and other things depending on data.
957  *
958  * Returns: 0 or an errorcode.
959  *          In case of 0 the function returns a new SEXP with the
960  *          signature value; the structure of this signature depends on the
961  *          other arguments but is always suitable to be passed to
962  *          gcry_pk_verify
963  *
964  * s_hash = (<mpi>)
965  * s_skey = <key-as-defined-in-sexp_to_key>
966  * r_sig  = (sig-val
967  *            (<algo>
968  *              (<param_name1> <mpi>)
969  *              ...
970  *              (<param_namen> <mpi>)
971  *            ))
972  */
973 int
974 gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
975 {
976     MPI *skey, hash;
977     MPI *result;
978     int i, algo, rc;
979     const char *algo_name, *algo_elems;
980     GCRY_SEXP *s_elems;
981
982     rc = sexp_to_key( s_skey, 1, &skey, &algo );
983     if( rc )
984         return rc;
985
986     /* get the name and the required size of the result array */
987     for(i=0; (algo_name = sig_info_table[i].name); i++ ) {
988         if( sig_info_table[i].algo == algo )
989             break;
990     }
991     if( !algo_name ) {
992         release_mpi_array( skey );
993         return -4; /* oops: unknown algorithm */
994     }
995     algo_elems = sig_info_table[i].elements;
996
997     /* get the stuff we want to sign */
998     hash = gcry_sexp_car_mpi( s_hash, 0 );
999     if( !hash ) {
1000         release_mpi_array( skey );
1001         return -1; /* fixme: get a real errorcode for this */
1002     }
1003     result = g10_xcalloc( (strlen(algo_elems)+1) , sizeof *result );
1004     rc = pubkey_sign( algo, result, hash, skey );
1005     release_mpi_array( skey );
1006     mpi_free( hash );
1007     if( rc ) {
1008         g10_free( result );
1009         return rc;
1010     }
1011
1012     s_elems = g10_xcalloc( (strlen(algo_elems)+2), sizeof *s_elems );
1013     s_elems[0] = SEXP_NEW( algo_name, 0 );
1014     for(i=0; algo_elems[i]; i++ ) {
1015         char tmp[2];
1016         tmp[0] = algo_elems[i];
1017         tmp[1] = 0;
1018         s_elems[i+1] = gcry_sexp_new_name_mpi( tmp, result[i] );
1019     }
1020     release_mpi_array( result );
1021     g10_free( result );
1022
1023     *r_sig = SEXP_CONS( SEXP_NEW( "sig-val", 0 ),
1024                         gcry_sexp_alist( s_elems ) );
1025
1026     g10_free( s_elems );
1027     return 0;
1028 }
1029
1030
1031 /****************
1032  * Verify a sgnature.  Caller has to supply the public key pkey,
1033  * the signature sig and his hashvalue data.  Public key has to be
1034  * a standard public key given as an S-Exp, sig is a S-Exp as returned
1035  * from gcry_pk_sign and data must be an S-Exp like the one in sign too.
1036  */
1037 int
1038 gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
1039 {
1040     MPI *pkey, hash, *sig;
1041     int algo, sigalgo;
1042     int rc;
1043
1044     rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
1045     if( rc )
1046         return rc;
1047     rc = sexp_to_sig( s_sig, &sig, &sigalgo );
1048     if( rc ) {
1049         release_mpi_array( pkey );
1050         return rc;
1051     }
1052     if( algo != sigalgo ) {
1053         release_mpi_array( pkey );
1054         release_mpi_array( sig );
1055         return -1; /* fixme: add real errornumber - algo does not match */
1056     }
1057
1058     hash = gcry_sexp_car_mpi( s_hash, 0 );
1059     if( !hash ) {
1060         release_mpi_array( pkey );
1061         release_mpi_array( sig );
1062         return -1; /* fixme: get a real errorcode for this */
1063     }
1064
1065     rc = pubkey_verify( algo, hash, sig, pkey, NULL, NULL );
1066     release_mpi_array( pkey );
1067     release_mpi_array( sig );
1068     mpi_free(hash);
1069
1070     return rc;
1071 }
1072
1073
1074 /****************
1075  * Test a key.  This may be used either for a public or a secret key
1076  * to see whether internal structre is valid.
1077  *
1078  * Returns: 0 or an errorcode.
1079  *
1080  * s_key = <key-as-defined-in-sexp_to_key>
1081  */
1082 int
1083 gcry_pk_testkey( GCRY_SEXP s_key )
1084 {
1085     MPI *key;
1086     int rc, algo;
1087
1088     /* Note we currently support only secret key checking */
1089     rc = sexp_to_key( s_key, 1, &key, &algo );
1090     if( rc ) {
1091         return rc;
1092     }
1093
1094     rc = pubkey_check_secret_key( algo, key );
1095     release_mpi_array( key );
1096     return rc;
1097 }
1098
1099
1100 /****************
1101  * Create a public key pair and return it in r_key.
1102  * How the key is created depends on s_parms:
1103  * (GNU
1104  *  (genkey
1105  *   (algo
1106  *     (parameter_name_1 ....)
1107  *      ....
1108  *     (parameter_name_n ....)
1109  * )))
1110  * The key is returned in a format depending on the
1111  * algorithm. Both, private and secret key are returned
1112  * and optionally some additional informatin.
1113  */
1114 int
1115 gcry_pk_genkey( GCRY_SEXP *r_key, GCRY_SEXP s_parms )
1116 {
1117     return GCRYERR_NOT_IMPL;
1118 }
1119
1120 /****************
1121  * Get the number of nbits from the public key
1122  * Hmmm: Should we have really this function or is it
1123  * better to have a more general function to retrieve
1124  * different propoerties of the key?
1125  */
1126 unsigned int
1127 gcry_pk_get_nbits( GCRY_SEXP key )
1128 {
1129     int rc, i, algo;
1130     MPI *keyarr;
1131     unsigned int nbits = 0;
1132
1133     rc = sexp_to_key( key, 0, &keyarr, &algo );
1134     if( rc == GCRYERR_INV_OBJ )
1135         rc = sexp_to_key( key, 0, &keyarr, &algo );
1136     if( rc )
1137         return 0;
1138
1139     do {
1140         for(i=0; pubkey_table[i].name; i++ )
1141             if( pubkey_table[i].algo == algo ) {
1142                 nbits = (*pubkey_table[i].get_nbits)( algo, keyarr );
1143                 goto leave;
1144             }
1145     } while( load_pubkey_modules() );
1146     if( is_RSA(algo) )  /* we always wanna see the length of a key :-) */
1147         nbits = mpi_get_nbits( keyarr[0] );
1148   leave:
1149     release_mpi_array( keyarr );
1150     return nbits;
1151 }
1152
1153
1154
1155 int
1156 gcry_pk_ctl( int cmd, void *buffer, size_t buflen)
1157 {
1158     switch( cmd ) {
1159       case GCRYCTL_DISABLE_ALGO:
1160         /* this one expects a buffer pointing to an
1161          * integer with the algo number.
1162          */
1163         if( !buffer || buflen != sizeof(int) )
1164             return set_lasterr( GCRYERR_INV_CIPHER_ALGO );
1165         disable_pubkey_algo( *(int*)buffer );
1166         break;
1167
1168       default:
1169         return set_lasterr( GCRYERR_INV_OP );
1170     }
1171     return 0;
1172 }
1173
1174
1175 /****************
1176  * Return information about the given algorithm
1177  * WHAT select the kind of information returned:
1178  *  GCRYCTL_TEST_ALGO:
1179  *      Returns 0 when the specified algorithm is available for use.
1180  *      Buffer must be NULL, nbytes  may have the address of a variable
1181  *      with the required usage of the algorithm. It may be 0 for don't
1182  *      care or a combination of the GCRY_PK_USAGE_xxx flags;
1183  *
1184  * On error the value -1 is returned and the error reason may be
1185  * retrieved by gcry_errno().
1186  * Note:  Because this function is in most caes used to return an
1187  * integer value, we can make it easier for the caller to just look at
1188  * the return value.  The caller will in all cases consult the value
1189  * and thereby detecting whether a error occured or not (i.e. while checking
1190  * the block size)
1191  */
1192 int
1193 gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes)
1194 {
1195     switch( what ) {
1196       case GCRYCTL_TEST_ALGO: {
1197             int use = nbytes? *nbytes: 0;
1198             if( buffer ) {
1199                 set_lasterr( GCRYERR_INV_ARG );
1200                 return -1;
1201             }
1202             if( check_pubkey_algo( algo, use ) ) {
1203                 set_lasterr( GCRYERR_INV_PK_ALGO );
1204                 return -1;
1205             }
1206         }
1207         break;
1208
1209       case GCRYCTL_GET_ALGO_NPKEY: return pubkey_get_npkey( algo );
1210       case GCRYCTL_GET_ALGO_NSKEY: return pubkey_get_nskey( algo );
1211       case GCRYCTL_GET_ALGO_NSIGN: return pubkey_get_nsig( algo );
1212       case GCRYCTL_GET_ALGO_NENCR: return pubkey_get_nenc( algo );
1213
1214       default:
1215         set_lasterr( GCRYERR_INV_OP );
1216         return -1;
1217     }
1218     return 0;
1219 }
1220
1221