See ChangeLog: Mon Jan 24 13:04:28 CET 2000 Werner Koch
[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_sign( int algo, MPI *resarr, MPI hash, MPI *skey );
99 static int pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
100                       int (*cmp)(void *, MPI), void *opaque );
101
102 static int
103 dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
104 { log_bug("no generate() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
105
106 static int
107 dummy_check_secret_key( int algo, MPI *skey )
108 { log_bug("no check_secret_key() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
109
110 static int
111 dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
112 { log_bug("no encrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
113
114 static int
115 dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
116 { log_bug("no decrypt() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
117
118 static int
119 dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey )
120 { log_bug("no sign() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
121
122 static int
123 dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey,
124                 int (*cmp)(void *, MPI), void *opaquev )
125 { log_bug("no verify() for %d\n", algo ); return GCRYERR_INV_PK_ALGO; }
126
127 static unsigned
128 dummy_get_nbits( int algo, MPI *pkey )
129 { log_bug("no get_nbits() for %d\n", algo ); return 0; }
130
131
132 /****************
133  * Put the static entries into the table.
134  * This is out constructor function which fill the table
135  * of algorithms with the one we have statically linked.
136  */
137 static void
138 setup_pubkey_table(void)
139 {
140     int i;
141
142     i = 0;
143     pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL;
144     pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
145                                          &pubkey_table[i].npkey,
146                                          &pubkey_table[i].nskey,
147                                          &pubkey_table[i].nenc,
148                                          &pubkey_table[i].nsig,
149                                          &pubkey_table[i].use );
150     pubkey_table[i].generate         = elg_generate;
151     pubkey_table[i].check_secret_key = elg_check_secret_key;
152     pubkey_table[i].encrypt          = elg_encrypt;
153     pubkey_table[i].decrypt          = elg_decrypt;
154     pubkey_table[i].sign             = elg_sign;
155     pubkey_table[i].verify           = elg_verify;
156     pubkey_table[i].get_nbits        = elg_get_nbits;
157     if( !pubkey_table[i].name )
158         BUG();
159     i++;
160     pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E;
161     pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
162                                          &pubkey_table[i].npkey,
163                                          &pubkey_table[i].nskey,
164                                          &pubkey_table[i].nenc,
165                                          &pubkey_table[i].nsig,
166                                          &pubkey_table[i].use );
167     pubkey_table[i].generate         = elg_generate;
168     pubkey_table[i].check_secret_key = elg_check_secret_key;
169     pubkey_table[i].encrypt          = elg_encrypt;
170     pubkey_table[i].decrypt          = elg_decrypt;
171     pubkey_table[i].sign             = elg_sign;
172     pubkey_table[i].verify           = elg_verify;
173     pubkey_table[i].get_nbits        = elg_get_nbits;
174     if( !pubkey_table[i].name )
175         BUG();
176     i++;
177     pubkey_table[i].algo = PUBKEY_ALGO_DSA;
178     pubkey_table[i].name = dsa_get_info( pubkey_table[i].algo,
179                                          &pubkey_table[i].npkey,
180                                          &pubkey_table[i].nskey,
181                                          &pubkey_table[i].nenc,
182                                          &pubkey_table[i].nsig,
183                                          &pubkey_table[i].use );
184     pubkey_table[i].generate         = dsa_generate;
185     pubkey_table[i].check_secret_key = dsa_check_secret_key;
186     pubkey_table[i].encrypt          = dummy_encrypt;
187     pubkey_table[i].decrypt          = dummy_decrypt;
188     pubkey_table[i].sign             = dsa_sign;
189     pubkey_table[i].verify           = dsa_verify;
190     pubkey_table[i].get_nbits        = dsa_get_nbits;
191     if( !pubkey_table[i].name )
192         BUG();
193     i++;
194
195     for( ; i < TABLE_SIZE; i++ )
196         pubkey_table[i].name = NULL;
197 }
198
199 static void
200 release_mpi_array( MPI *array )
201 {
202     for( ; *array; array++ ) {
203         mpi_free(*array);
204         *array = NULL;
205     }
206 }
207
208 /****************
209  * Try to load all modules and return true if new modules are available
210  */
211 static int
212 load_pubkey_modules(void)
213 {
214     static int initialized = 0;
215     static int done = 0;
216     void *context = NULL;
217     struct pubkey_table_s *ct;
218     int ct_idx;
219     int i;
220     const char *name;
221     int any = 0;
222
223
224     if( !initialized ) {
225         cipher_modules_constructor();
226         setup_pubkey_table();
227         initialized = 1;
228         return 1;
229     }
230     if( done )
231         return 0;
232     done = 1;
233     for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
234         if( !ct->name )
235             break;
236     }
237     if( ct_idx >= TABLE_SIZE-1 )
238         BUG(); /* table already full */
239     /* now load all extensions */
240     while( (name = enum_gnupgext_pubkeys( &context, &ct->algo,
241                                 &ct->npkey, &ct->nskey, &ct->nenc,
242                                 &ct->nsig,  &ct->use,
243                                 &ct->generate,
244                                 &ct->check_secret_key,
245                                 &ct->encrypt,
246                                 &ct->decrypt,
247                                 &ct->sign,
248                                 &ct->verify,
249                                 &ct->get_nbits )) ) {
250         for(i=0; pubkey_table[i].name; i++ )
251             if( pubkey_table[i].algo == ct->algo )
252                 break;
253         if( pubkey_table[i].name ) {
254             log_info("skipping pubkey %d: already loaded\n", ct->algo );
255             continue;
256         }
257
258         if( !ct->generate  )  ct->generate = dummy_generate;
259         if( !ct->check_secret_key )  ct->check_secret_key =
260                                                     dummy_check_secret_key;
261         if( !ct->encrypt   )  ct->encrypt  = dummy_encrypt;
262         if( !ct->decrypt   )  ct->decrypt  = dummy_decrypt;
263         if( !ct->sign      )  ct->sign     = dummy_sign;
264         if( !ct->verify    )  ct->verify   = dummy_verify;
265         if( !ct->get_nbits )  ct->get_nbits= dummy_get_nbits;
266         /* put it into the table */
267         if( g10_log_verbosity( 2 ) )
268             log_info("loaded pubkey %d (%s)\n", ct->algo, name);
269         ct->name = name;
270         ct_idx++;
271         ct++;
272         any = 1;
273         /* check whether there are more available table slots */
274         if( ct_idx >= TABLE_SIZE-1 ) {
275             log_info("pubkey table full; ignoring other extensions\n");
276             break;
277         }
278     }
279     enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL,
280                                NULL, NULL, NULL, NULL, NULL, NULL, NULL );
281     return any;
282 }
283
284
285 /****************
286  * Map a string to the pubkey algo
287  */
288 int
289 gcry_pk_map_name( const char *string )
290 {
291     int i;
292     const char *s;
293
294     do {
295         for(i=0; (s=pubkey_table[i].name); i++ )
296             if( !stricmp( s, string ) )
297                 return pubkey_table[i].algo;
298     } while( load_pubkey_modules() );
299     return 0;
300 }
301
302
303 /****************
304  * Map a pubkey algo to a string
305  */
306 const char *
307 gcry_pk_algo_name( int algo )
308 {
309     int i;
310
311     do {
312         for(i=0; pubkey_table[i].name; i++ )
313             if( pubkey_table[i].algo == algo )
314                 return pubkey_table[i].name;
315     } while( load_pubkey_modules() );
316     return NULL;
317 }
318
319
320 static void
321 disable_pubkey_algo( int algo )
322 {
323     int i;
324
325     for(i=0; i < DIM(disabled_algos); i++ ) {
326         if( !disabled_algos[i] || disabled_algos[i] == algo ) {
327             disabled_algos[i] = algo;
328             return;
329         }
330     }
331     log_fatal("can't disable pubkey algo %d: table full\n", algo );
332 }
333
334
335 /****************
336  * a use of 0 means: don't care
337  */
338 static int
339 check_pubkey_algo( int algo, unsigned use )
340 {
341     int i;
342
343     do {
344         for(i=0; pubkey_table[i].name; i++ )
345             if( pubkey_table[i].algo == algo ) {
346                 if( (use & GCRY_PK_USAGE_SIGN)
347                     && !(pubkey_table[i].use & GCRY_PK_USAGE_SIGN) )
348                     return GCRYERR_WRONG_PK_ALGO;
349                 if( (use & GCRY_PK_USAGE_ENCR)
350                     && !(pubkey_table[i].use & GCRY_PK_USAGE_ENCR) )
351                     return GCRYERR_WRONG_PK_ALGO;
352
353                 for(i=0; i < DIM(disabled_algos); i++ ) {
354                     if( disabled_algos[i] == algo )
355                         return GCRYERR_INV_PK_ALGO;
356                 }
357                 return 0; /* okay */
358             }
359     } while( load_pubkey_modules() );
360     return GCRYERR_INV_PK_ALGO;
361 }
362
363
364
365
366 /****************
367  * Return the number of public key material numbers
368  */
369 static int
370 pubkey_get_npkey( int algo )
371 {
372     int i;
373     do {
374         for(i=0; pubkey_table[i].name; i++ )
375             if( pubkey_table[i].algo == algo )
376                 return pubkey_table[i].npkey;
377     } while( load_pubkey_modules() );
378     if( is_RSA(algo) )    /* special hack, so that we are able to */
379         return 2;         /* see the RSA keyids */
380     return 0;
381 }
382
383 /****************
384  * Return the number of secret key material numbers
385  */
386 static int
387 pubkey_get_nskey( int algo )
388 {
389     int i;
390     do {
391         for(i=0; pubkey_table[i].name; i++ )
392             if( pubkey_table[i].algo == algo )
393                 return pubkey_table[i].nskey;
394     } while( load_pubkey_modules() );
395     if( is_RSA(algo) )    /* special hack, so that we are able to */
396         return 6;         /* see the RSA keyids */
397     return 0;
398 }
399
400 /****************
401  * Return the number of signature material numbers
402  */
403 static int
404 pubkey_get_nsig( int algo )
405 {
406     int i;
407     do {
408         for(i=0; pubkey_table[i].name; i++ )
409             if( pubkey_table[i].algo == algo )
410                 return pubkey_table[i].nsig;
411     } while( load_pubkey_modules() );
412     if( is_RSA(algo) )    /* special hack, so that we are able to */
413         return 1;         /* see the RSA keyids */
414     return 0;
415 }
416
417 /****************
418  * Return the number of encryption material numbers
419  */
420 static int
421 pubkey_get_nenc( int algo )
422 {
423     int i;
424     do {
425         for(i=0; pubkey_table[i].name; i++ )
426             if( pubkey_table[i].algo == algo )
427                 return pubkey_table[i].nenc;
428     } while( load_pubkey_modules() );
429     if( is_RSA(algo) )    /* special hack, so that we are able to */
430         return 1;         /* see the RSA keyids */
431     return 0;
432 }
433
434
435 int
436 pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
437 {
438     int i;
439
440     do {
441         for(i=0; pubkey_table[i].name; i++ )
442             if( pubkey_table[i].algo == algo )
443                 return (*pubkey_table[i].generate)( algo, nbits,
444                                                     skey, retfactors );
445     } while( load_pubkey_modules() );
446     return GCRYERR_INV_PK_ALGO;
447 }
448
449
450 int
451 pubkey_check_secret_key( int algo, MPI *skey )
452 {
453     int i;
454
455     do {
456         for(i=0; pubkey_table[i].name; i++ )
457             if( pubkey_table[i].algo == algo )
458                 return (*pubkey_table[i].check_secret_key)( algo, skey );
459     } while( load_pubkey_modules() );
460     return GCRYERR_INV_PK_ALGO;
461 }
462
463
464 /****************
465  * This is the interface to the public key encryption.
466  * Encrypt DATA with PKEY and put it into RESARR which
467  * should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
468  * algorithm allows this - check with pubkey_get_nenc() )
469  */
470 int
471 pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
472 {
473     int i, rc;
474
475     if( DBG_CIPHER ) {
476         log_debug("pubkey_encrypt: algo=%d\n", algo );
477         for(i=0; i < pubkey_get_npkey(algo); i++ )
478             log_mpidump("  pkey:", pkey[i] );
479         log_mpidump("  data:", data );
480     }
481
482     do {
483         for(i=0; pubkey_table[i].name; i++ )
484             if( pubkey_table[i].algo == algo ) {
485                 rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey );
486                 goto ready;
487             }
488     } while( load_pubkey_modules() );
489     rc = GCRYERR_INV_PK_ALGO;
490   ready:
491     if( !rc && DBG_CIPHER ) {
492         for(i=0; i < pubkey_get_nenc(algo); i++ )
493             log_mpidump("  encr:", resarr[i] );
494     }
495     return rc;
496 }
497
498
499
500 /****************
501  * This is the interface to the public key decryption.
502  * ALGO gives the algorithm to use and this implicitly determines
503  * the size of the arrays.
504  * result is a pointer to a mpi variable which will receive a
505  * newly allocated mpi or NULL in case of an error.
506  */
507 int
508 pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
509 {
510     int i, rc;
511
512     *result = NULL; /* so the caller can always do an mpi_free */
513     if( DBG_CIPHER ) {
514         log_debug("pubkey_decrypt: algo=%d\n", algo );
515         for(i=0; i < pubkey_get_nskey(algo); i++ )
516             log_mpidump("  skey:", skey[i] );
517         for(i=0; i < pubkey_get_nenc(algo); i++ )
518             log_mpidump("  data:", data[i] );
519     }
520
521     do {
522         for(i=0; pubkey_table[i].name; i++ )
523             if( pubkey_table[i].algo == algo ) {
524                 rc = (*pubkey_table[i].decrypt)( algo, result, data, skey );
525                 goto ready;
526             }
527     } while( load_pubkey_modules() );
528     rc = GCRYERR_INV_PK_ALGO;
529   ready:
530     if( !rc && DBG_CIPHER ) {
531         log_mpidump(" plain:", *result );
532     }
533     return rc;
534 }
535
536
537 /****************
538  * This is the interface to the public key signing.
539  * Sign data with skey and put the result into resarr which
540  * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
541  * algorithm allows this - check with pubkey_get_nsig() )
542  */
543 static int
544 pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
545 {
546     int i, rc;
547
548     if( DBG_CIPHER ) {
549         log_debug("pubkey_sign: algo=%d\n", algo );
550         for(i=0; i < pubkey_get_nskey(algo); i++ )
551             log_mpidump("  skey:", skey[i] );
552         log_mpidump("  data:", data );
553     }
554
555     do {
556         for(i=0; pubkey_table[i].name; i++ )
557             if( pubkey_table[i].algo == algo ) {
558                 rc = (*pubkey_table[i].sign)( algo, resarr, data, skey );
559                 goto ready;
560             }
561     } while( load_pubkey_modules() );
562     rc = GCRYERR_INV_PK_ALGO;
563   ready:
564     if( !rc && DBG_CIPHER ) {
565         for(i=0; i < pubkey_get_nsig(algo); i++ )
566             log_mpidump("   sig:", resarr[i] );
567     }
568     return rc;
569 }
570
571 /****************
572  * Verify a public key signature.
573  * Return 0 if the signature is good
574  */
575 static int
576 pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
577                     int (*cmp)(void *, MPI), void *opaquev )
578 {
579     int i, rc;
580
581     do {
582         for(i=0; pubkey_table[i].name; i++ )
583             if( pubkey_table[i].algo == algo ) {
584                 rc = (*pubkey_table[i].verify)( algo, hash, data, pkey,
585                                                             cmp, opaquev );
586                 goto ready;
587             }
588     } while( load_pubkey_modules() );
589     rc = GCRYERR_INV_PK_ALGO;
590   ready:
591     return rc;
592 }
593
594
595
596 /****************
597  * Convert a S-Exp with either a private or a public key to our
598  * internal format. Currently we do only support the following
599  * algorithms:
600  *    dsa
601  *    rsa
602  *    openpgp-dsa
603  *    openpgp-rsa
604  *    openpgp-elg
605  *    openpgp-elg-sig
606  * Provide a SE with the first element be either "private-key" or
607  * or "public-key". the followed by a list with its first element
608  * be one of the above algorithm identifiers and the following
609  * elements are pairs with parameter-id and value.
610  * NOTE: we look through the list to find a list beginning with
611  * "private-key" or "public-key" - the first one found is used.
612  *
613  * FIXME: Allow for encrypted secret keys here.
614  *
615  * Returns: A pointer to an allocated array of MPIs if the return value is
616  *          zero; the caller has to release this array.
617  *
618  * Example of a DSA public key:
619  *  (private-key
620  *    (dsa
621  *      (p <mpi>)
622  *      (g <mpi>)
623  *      (y <mpi>)
624  *      (x <mpi>)
625  *    )
626  *  )
627  * The <mpi> are expected to be in GCRYMPI_FMT_USG
628  */
629 static int
630 sexp_to_key( GCRY_SEXP sexp, int want_private, MPI **retarray, int *retalgo)
631 {
632     GCRY_SEXP list, l2;
633     const char *name;
634     const char *s;
635     size_t n;
636     int i, idx;
637     int algo;
638     const char *elems1, *elems2;
639     GCRY_MPI *array;
640
641     /* check that the first element is valid */
642     list = gcry_sexp_find_token( sexp, want_private? "private-key"
643                                                     :"public-key", 0 );
644     if( !list )
645         return GCRYERR_INV_OBJ; /* Does not contain a public- or private-key object */
646     list = gcry_sexp_cdr( list );
647     if( !list )
648         return GCRYERR_NO_OBJ; /* no cdr for the key object */
649     name = gcry_sexp_car_data( list, &n );
650     if( !name )
651         return GCRYERR_INV_OBJ; /* invalid structure of object */
652     for(i=0; (s=algo_info_table[i].name); i++ ) {
653         if( strlen(s) == n && !memcmp( s, name, n ) )
654             break;
655     }
656     if( !s )
657         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
658     algo = algo_info_table[i].algo;
659     elems1 = algo_info_table[i].common_elements;
660     elems2 = want_private? algo_info_table[i].secret_elements
661                          : algo_info_table[i].public_elements;
662     array = g10_calloc( strlen(elems1)+strlen(elems2)+1, sizeof *array );
663     if( !array )
664         return GCRYERR_NO_MEM;
665
666     idx = 0;
667     for(s=elems1; *s; s++, idx++ ) {
668         l2 = gcry_sexp_find_token( list, s, 1 );
669         if( !l2 ) {
670             g10_free( array );
671             return GCRYERR_NO_OBJ; /* required parameter not found */
672         }
673         array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
674         if( !array[idx] ) {
675             g10_free( array );
676             return GCRYERR_INV_OBJ; /* required parameter is invalid */
677         }
678     }
679     for(s=elems2; *s; s++, idx++ ) {
680         l2 = gcry_sexp_find_token( list, s, 1 );
681         if( !l2 ) {
682             g10_free( array );
683             return GCRYERR_NO_OBJ; /* required parameter not found */
684         }
685         /* FIXME: put the MPI in secure memory when needed */
686         array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
687         if( !array[idx] ) {
688             g10_free( array );
689             return GCRYERR_INV_OBJ; /* required parameter is invalid */
690         }
691     }
692
693     *retarray = array;
694     *retalgo = algo;
695
696     return 0;
697 }
698
699 static int
700 sexp_to_sig( GCRY_SEXP sexp, MPI **retarray, int *retalgo)
701 {
702     GCRY_SEXP list, l2;
703     const char *name;
704     const char *s;
705     size_t n;
706     int i, idx;
707     int algo;
708     const char *elems;
709     GCRY_MPI *array;
710
711     /* check that the first element is valid */
712     list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
713     if( !list )
714         return GCRYERR_INV_OBJ; /* Does not contain a signature value object */
715     list = gcry_sexp_cdr( list );
716     if( !list )
717         return GCRYERR_NO_OBJ; /* no cdr for the sig object */
718     name = gcry_sexp_car_data( list, &n );
719     if( !name )
720         return GCRYERR_INV_OBJ; /* invalid structure of object */
721     for(i=0; (s=sig_info_table[i].name); i++ ) {
722         if( strlen(s) == n && !memcmp( s, name, n ) )
723             break;
724     }
725     if( !s )
726         return GCRYERR_INV_PK_ALGO; /* unknown algorithm */
727     algo = sig_info_table[i].algo;
728     elems = sig_info_table[i].elements;
729     array = g10_calloc( (strlen(elems)+1) , sizeof *array );
730     if( !array )
731         return GCRYERR_NO_MEM;
732
733     idx = 0;
734     for(s=elems; *s; s++, idx++ ) {
735         l2 = gcry_sexp_find_token( list, s, 1 );
736         if( !l2 ) {
737             g10_free( array );
738             return GCRYERR_NO_OBJ; /* required parameter not found */
739         }
740         array[idx] = gcry_sexp_cdr_mpi( l2, GCRYMPI_FMT_USG );
741         if( !array[idx] ) {
742             g10_free( array );
743             return GCRYERR_INV_OBJ; /* required parameter is invalid */
744         }
745     }
746
747     *retarray = array;
748     *retalgo = algo;
749
750     return 0;
751 }
752
753
754
755
756
757 int
758 gcry_pk_encrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP pkey )
759 {
760         /* ... */
761     return 0;
762 }
763
764 int
765 gcry_pk_decrypt( GCRY_SEXP *result, GCRY_SEXP data, GCRY_SEXP skey )
766 {
767         /* ... */
768     return 0;
769 }
770
771
772
773 /****************
774  * Create a signature.
775  *
776  * Caller has to provide a secret key as the SEXP skey and data expressed
777  * as a SEXP list hash with only one element which should instantly be
778  * available as a MPI.  Later versions of this functions may provide padding
779  * and other things depending on data.
780  *
781  * Returns: 0 or an errorcode.
782  *          In case of 0 the function returns a new SEXP with the
783  *          signature value; the structure of this signature depends on the
784  *          other arguments but is always suitable to be passed to
785  *          gcry_pk_verify
786  *
787  * s_hash = (<mpi>)
788  * s_skey = <key-as-defined-in-sexp_to_key>
789  * r_sig  = (sig-val
790  *            (<algo>
791  *              (<param_name1> <mpi>)
792  *              ...
793  *              (<param_namen> <mpi>)
794  *            ))
795  */
796 int
797 gcry_pk_sign( GCRY_SEXP *r_sig, GCRY_SEXP s_hash, GCRY_SEXP s_skey )
798 {
799     MPI *skey, hash;
800     MPI *result;
801     int i, algo, rc;
802     const char *algo_name, *algo_elems;
803     GCRY_SEXP s;
804
805     rc = sexp_to_key( s_skey, 1, &skey, &algo );
806     if( rc )
807         return rc;
808
809     /* get the name and the required size of the result array */
810     for(i=0; (algo_name = sig_info_table[i].name); i++ ) {
811         if( sig_info_table[i].algo == algo )
812             break;
813     }
814     if( !algo_name ) {
815         release_mpi_array( skey );
816         return -4; /* oops: unknown algorithm */
817     }
818     algo_elems = sig_info_table[i].elements;
819
820     /* get the stuff we want to sign */
821     hash = gcry_sexp_car_mpi( s_hash, 0 );
822     if( !hash ) {
823         release_mpi_array( skey );
824         return -1; /* fixme: get a real errorcode for this */
825     }
826     result = g10_xcalloc( (strlen(algo_elems)+1) , sizeof *result );
827     rc = pubkey_sign( algo, result, hash, skey );
828     release_mpi_array( skey );
829     mpi_free( hash );
830     if( rc ) {
831         g10_free( result );
832         return rc;
833     }
834
835     s = SEXP_NEW( algo_name, 0 );
836     for(i=0; algo_elems[i]; i++ ) {
837         char tmp[2];
838         tmp[0] = algo_elems[i];
839         tmp[1] = 0;
840         s = gcry_sexp_append( s, gcry_sexp_new_name_mpi( tmp, result[i] ) );
841     }
842     g10_free( result );
843     *r_sig = SEXP_CONS( SEXP_NEW( "sig-val", 0 ), s );
844     gcry_sexp_dump( *r_sig );
845     return 0;
846 }
847
848
849 /****************
850  * Verify a sgnature.  Caller has to supply the public key pkey,
851  * the signature sig and his hashvalue data.  Public key has to be
852  * a standard public key given as an S-Exp, sig is a S-Exp as returned
853  * from gcry_pk_sign and data must be an S-Exp like the one in sign too.
854  */
855 int
856 gcry_pk_verify( GCRY_SEXP s_sig, GCRY_SEXP s_hash, GCRY_SEXP s_pkey )
857 {
858     MPI *pkey, hash, *sig;
859     int algo, sigalgo;
860     int rc;
861
862     rc = sexp_to_key( s_pkey, 0, &pkey, &algo );
863     if( rc )
864         return rc;
865     rc = sexp_to_sig( s_sig, &sig, &sigalgo );
866     if( rc ) {
867         release_mpi_array( pkey );
868         return rc;
869     }
870     if( algo != sigalgo ) {
871         release_mpi_array( pkey );
872         release_mpi_array( sig );
873         return -1; /* fixme: add real errornumber - algo does not match */
874     }
875
876     hash = gcry_sexp_car_mpi( s_hash, 0 );
877     if( !hash ) {
878         release_mpi_array( pkey );
879         release_mpi_array( sig );
880         return -1; /* fixme: get a real errorcode for this */
881     }
882
883     rc = pubkey_verify( algo, hash, sig, pkey, NULL, NULL );
884     release_mpi_array( pkey );
885     release_mpi_array( sig );
886     mpi_free(hash);
887
888     return rc;
889 }
890
891
892 /****************
893  * Get the number of nbits from the public key
894  * Hmmm: Should we have really this function or is it
895  * better to have a more general function to retrieve
896  * different propoerties of the key?
897  */
898 unsigned int
899 gcry_pk_get_nbits( GCRY_SEXP key )
900 {
901     int rc, i, algo;
902     MPI *keyarr;
903     unsigned int nbits = 0;
904
905     rc = sexp_to_key( key, 0, &keyarr, &algo );
906     if( rc == GCRYERR_INV_OBJ )
907         rc = sexp_to_key( key, 0, &keyarr, &algo );
908     if( rc )
909         return 0;
910
911     do {
912         for(i=0; pubkey_table[i].name; i++ )
913             if( pubkey_table[i].algo == algo ) {
914                 nbits = (*pubkey_table[i].get_nbits)( algo, keyarr );
915                 goto leave;
916             }
917     } while( load_pubkey_modules() );
918     if( is_RSA(algo) )  /* we always wanna see the length of a key :-) */
919         nbits = mpi_get_nbits( keyarr[0] );
920   leave:
921     release_mpi_array( keyarr );
922     return nbits;
923 }
924
925
926
927 int
928 gcry_pk_ctl( int cmd, void *buffer, size_t buflen)
929 {
930     switch( cmd ) {
931       case GCRYCTL_DISABLE_ALGO:
932         /* this one expects a buffer pointing to an
933          * integer with the algo number.
934          */
935         if( !buffer || buflen != sizeof(int) )
936             return set_lasterr( GCRYERR_INV_CIPHER_ALGO );
937         disable_pubkey_algo( *(int*)buffer );
938         break;
939
940       default:
941         return set_lasterr( GCRYERR_INV_OP );
942     }
943     return 0;
944 }
945
946
947 /****************
948  * Return information about the given algorithm
949  * WHAT select the kind of information returned:
950  *  GCRYCTL_TEST_ALGO:
951  *      Returns 0 when the specified algorithm is available for use.
952  *      Buffer must be NULL, nbytes  may have the address of a variable
953  *      with the required usage of the algorithm. It may be 0 for don't
954  *      care or a combination of the GCRY_PK_USAGE_xxx flags;
955  *
956  * On error the value -1 is returned and the error reason may be
957  * retrieved by gcry_errno().
958  * Note:  Because this function is in most caes used to return an
959  * integer value, we can make it easier for the caller to just look at
960  * the return value.  The caller will in all cases consult the value
961  * and thereby detecting whether a error occured or not (i.e. while checking
962  * the block size)
963  */
964 int
965 gcry_pk_algo_info( int algo, int what, void *buffer, size_t *nbytes)
966 {
967     switch( what ) {
968       case GCRYCTL_TEST_ALGO: {
969             int use = nbytes? *nbytes: 0;
970             if( buffer ) {
971                 set_lasterr( GCRYERR_INV_ARG );
972                 return -1;
973             }
974             if( check_pubkey_algo( algo, use ) ) {
975                 set_lasterr( GCRYERR_INV_PK_ALGO );
976                 return -1;
977             }
978         }
979         break;
980
981       case GCRYCTL_GET_ALGO_NPKEY: return pubkey_get_npkey( algo );
982       case GCRYCTL_GET_ALGO_NSKEY: return pubkey_get_nskey( algo );
983       case GCRYCTL_GET_ALGO_NSIGN: return pubkey_get_nsig( algo );
984       case GCRYCTL_GET_ALGO_NENCR: return pubkey_get_nenc( algo );
985
986       default:
987         set_lasterr( GCRYERR_INV_OP );
988         return -1;
989     }
990     return 0;
991 }
992
993