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