See ChangeLog: Mon Jul 26 09:34:46 CEST 1999 Werner Koch
[gnupg.git] / cipher / pubkey.c
1 /* pubkey.c  -  pubkey dispatcher
2  *      Copyright (C) 1998 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 #include "util.h"
28 #include "errors.h"
29 #include "mpi.h"
30 #include "cipher.h"
31 #include "elgamal.h"
32 #include "dsa.h"
33 #include "dynload.h"
34
35
36 #define TABLE_SIZE 10
37
38 struct pubkey_table_s {
39     const char *name;
40     int algo;
41     int npkey;
42     int nskey;
43     int nenc;
44     int nsig;
45     int use;
46     int (*generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors );
47     int (*check_secret_key)( int algo, MPI *skey );
48     int (*encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey );
49     int (*decrypt)( int algo, MPI *result, MPI *data, MPI *skey );
50     int (*sign)( int algo, MPI *resarr, MPI data, MPI *skey );
51     int (*verify)( int algo, MPI hash, MPI *data, MPI *pkey,
52                    int (*cmp)(void *, MPI), void *opaquev );
53     unsigned (*get_nbits)( int algo, MPI *pkey );
54 };
55
56 static struct pubkey_table_s pubkey_table[TABLE_SIZE];
57 static int disabled_algos[TABLE_SIZE];
58
59
60 static int
61 dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
62 { log_bug("no generate() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
63
64 static int
65 dummy_check_secret_key( int algo, MPI *skey )
66 { log_bug("no check_secret_key() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
67
68 static int
69 dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
70 { log_bug("no encrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
71
72 static int
73 dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
74 { log_bug("no decrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
75
76 static int
77 dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey )
78 { log_bug("no sign() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
79
80 static int
81 dummy_verify( int algo, MPI hash, MPI *data, MPI *pkey,
82                 int (*cmp)(void *, MPI), void *opaquev )
83 { log_bug("no verify() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
84
85 static unsigned
86 dummy_get_nbits( int algo, MPI *pkey )
87 { log_bug("no get_nbits() for %d\n", algo ); return 0; }
88
89
90 /****************
91  * Put the static entries into the table.
92  * This is out constructor function which fill the table
93  * of algorithms with the one we have statically linked.
94  */
95 static void
96 setup_pubkey_table(void)
97 {
98     int i;
99
100     i = 0;
101     pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL;
102     pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
103                                          &pubkey_table[i].npkey,
104                                          &pubkey_table[i].nskey,
105                                          &pubkey_table[i].nenc,
106                                          &pubkey_table[i].nsig,
107                                          &pubkey_table[i].use );
108     pubkey_table[i].generate         = elg_generate;
109     pubkey_table[i].check_secret_key = elg_check_secret_key;
110     pubkey_table[i].encrypt          = elg_encrypt;
111     pubkey_table[i].decrypt          = elg_decrypt;
112     pubkey_table[i].sign             = elg_sign;
113     pubkey_table[i].verify           = elg_verify;
114     pubkey_table[i].get_nbits        = elg_get_nbits;
115     if( !pubkey_table[i].name )
116         BUG();
117     i++;
118     pubkey_table[i].algo = PUBKEY_ALGO_ELGAMAL_E;
119     pubkey_table[i].name = elg_get_info( pubkey_table[i].algo,
120                                          &pubkey_table[i].npkey,
121                                          &pubkey_table[i].nskey,
122                                          &pubkey_table[i].nenc,
123                                          &pubkey_table[i].nsig,
124                                          &pubkey_table[i].use );
125     pubkey_table[i].generate         = elg_generate;
126     pubkey_table[i].check_secret_key = elg_check_secret_key;
127     pubkey_table[i].encrypt          = elg_encrypt;
128     pubkey_table[i].decrypt          = elg_decrypt;
129     pubkey_table[i].sign             = elg_sign;
130     pubkey_table[i].verify           = elg_verify;
131     pubkey_table[i].get_nbits        = elg_get_nbits;
132     if( !pubkey_table[i].name )
133         BUG();
134     i++;
135     pubkey_table[i].algo = PUBKEY_ALGO_DSA;
136     pubkey_table[i].name = dsa_get_info( pubkey_table[i].algo,
137                                          &pubkey_table[i].npkey,
138                                          &pubkey_table[i].nskey,
139                                          &pubkey_table[i].nenc,
140                                          &pubkey_table[i].nsig,
141                                          &pubkey_table[i].use );
142     pubkey_table[i].generate         = dsa_generate;
143     pubkey_table[i].check_secret_key = dsa_check_secret_key;
144     pubkey_table[i].encrypt          = dummy_encrypt;
145     pubkey_table[i].decrypt          = dummy_decrypt;
146     pubkey_table[i].sign             = dsa_sign;
147     pubkey_table[i].verify           = dsa_verify;
148     pubkey_table[i].get_nbits        = dsa_get_nbits;
149     if( !pubkey_table[i].name )
150         BUG();
151     i++;
152
153     for( ; i < TABLE_SIZE; i++ )
154         pubkey_table[i].name = NULL;
155 }
156
157
158 /****************
159  * Try to load all modules and return true if new modules are available
160  */
161 static int
162 load_pubkey_modules(void)
163 {
164     static int initialized = 0;
165     static int done = 0;
166     void *context = NULL;
167     struct pubkey_table_s *ct;
168     int ct_idx;
169     int i;
170     const char *name;
171     int any = 0;
172
173
174     if( !initialized ) {
175         cipher_modules_constructor();
176         setup_pubkey_table();
177         initialized = 1;
178         return 1;
179     }
180     if( done )
181         return 0;
182     done = 1;
183     for(ct_idx=0, ct = pubkey_table; ct_idx < TABLE_SIZE; ct_idx++,ct++ ) {
184         if( !ct->name )
185             break;
186     }
187     if( ct_idx >= TABLE_SIZE-1 )
188         BUG(); /* table already full */
189     /* now load all extensions */
190     while( (name = enum_gnupgext_pubkeys( &context, &ct->algo,
191                                 &ct->npkey, &ct->nskey, &ct->nenc,
192                                 &ct->nsig,  &ct->use,
193                                 &ct->generate,
194                                 &ct->check_secret_key,
195                                 &ct->encrypt,
196                                 &ct->decrypt,
197                                 &ct->sign,
198                                 &ct->verify,
199                                 &ct->get_nbits )) ) {
200         for(i=0; pubkey_table[i].name; i++ )
201             if( pubkey_table[i].algo == ct->algo )
202                 break;
203         if( pubkey_table[i].name ) {
204             log_info("skipping pubkey %d: already loaded\n", ct->algo );
205             continue;
206         }
207
208         if( !ct->generate  )  ct->generate = dummy_generate;
209         if( !ct->check_secret_key )  ct->check_secret_key =
210                                                     dummy_check_secret_key;
211         if( !ct->encrypt   )  ct->encrypt  = dummy_encrypt;
212         if( !ct->decrypt   )  ct->decrypt  = dummy_decrypt;
213         if( !ct->sign      )  ct->sign     = dummy_sign;
214         if( !ct->verify    )  ct->verify   = dummy_verify;
215         if( !ct->get_nbits )  ct->get_nbits= dummy_get_nbits;
216         /* put it into the table */
217         if( g10_opt_verbose > 1 )
218             log_info("loaded pubkey %d (%s)\n", ct->algo, name);
219         ct->name = name;
220         ct_idx++;
221         ct++;
222         any = 1;
223         /* check whether there are more available table slots */
224         if( ct_idx >= TABLE_SIZE-1 ) {
225             log_info("pubkey table full; ignoring other extensions\n");
226             break;
227         }
228     }
229     enum_gnupgext_pubkeys( &context, NULL, NULL, NULL, NULL, NULL, NULL,
230                                NULL, NULL, NULL, NULL, NULL, NULL, NULL );
231     return any;
232 }
233
234
235 /****************
236  * Map a string to the pubkey algo
237  */
238 int
239 string_to_pubkey_algo( const char *string )
240 {
241     int i;
242     const char *s;
243
244     do {
245         for(i=0; (s=pubkey_table[i].name); i++ )
246             if( !stricmp( s, string ) )
247                 return pubkey_table[i].algo;
248     } while( load_pubkey_modules() );
249     return 0;
250 }
251
252
253 /****************
254  * Map a pubkey algo to a string
255  */
256 const char *
257 pubkey_algo_to_string( int algo )
258 {
259     int i;
260
261     do {
262         for(i=0; pubkey_table[i].name; i++ )
263             if( pubkey_table[i].algo == algo )
264                 return pubkey_table[i].name;
265     } while( load_pubkey_modules() );
266     return NULL;
267 }
268
269
270 void
271 disable_pubkey_algo( int algo )
272 {
273     int i;
274
275     for(i=0; i < DIM(disabled_algos); i++ ) {
276         if( !disabled_algos[i] || disabled_algos[i] == algo ) {
277             disabled_algos[i] = algo;
278             return;
279         }
280     }
281     log_fatal("can't disable pubkey algo %d: table full\n", algo );
282 }
283
284
285 int
286 check_pubkey_algo( int algo )
287 {
288     return check_pubkey_algo2( algo, 0 );
289 }
290
291 /****************
292  * a use of 0 means: don't care
293  */
294 int
295 check_pubkey_algo2( int algo, unsigned use )
296 {
297     int i;
298
299     do {
300         for(i=0; pubkey_table[i].name; i++ )
301             if( pubkey_table[i].algo == algo ) {
302                 if( (use & PUBKEY_USAGE_SIG)
303                     && !(pubkey_table[i].use & PUBKEY_USAGE_SIG) )
304                     return G10ERR_WR_PUBKEY_ALGO;
305                 if( (use & PUBKEY_USAGE_ENC)
306                     && !(pubkey_table[i].use & PUBKEY_USAGE_ENC) )
307                     return G10ERR_WR_PUBKEY_ALGO;
308
309                 for(i=0; i < DIM(disabled_algos); i++ ) {
310                     if( disabled_algos[i] == algo )
311                         return G10ERR_PUBKEY_ALGO;
312                 }
313                 return 0; /* okay */
314             }
315     } while( load_pubkey_modules() );
316     return G10ERR_PUBKEY_ALGO;
317 }
318
319
320
321
322 /****************
323  * Return the number of public key material numbers
324  */
325 int
326 pubkey_get_npkey( int algo )
327 {
328     int i;
329     do {
330         for(i=0; pubkey_table[i].name; i++ )
331             if( pubkey_table[i].algo == algo )
332                 return pubkey_table[i].npkey;
333     } while( load_pubkey_modules() );
334     if( is_RSA(algo) )    /* special hack, so that we are able to */
335         return 2;         /* see the RSA keyids */
336     return 0;
337 }
338
339 /****************
340  * Return the number of secret key material numbers
341  */
342 int
343 pubkey_get_nskey( int algo )
344 {
345     int i;
346     do {
347         for(i=0; pubkey_table[i].name; i++ )
348             if( pubkey_table[i].algo == algo )
349                 return pubkey_table[i].nskey;
350     } while( load_pubkey_modules() );
351     if( is_RSA(algo) )    /* special hack, so that we are able to */
352         return 6;         /* see the RSA keyids */
353     return 0;
354 }
355
356 /****************
357  * Return the number of signature material numbers
358  */
359 int
360 pubkey_get_nsig( int algo )
361 {
362     int i;
363     do {
364         for(i=0; pubkey_table[i].name; i++ )
365             if( pubkey_table[i].algo == algo )
366                 return pubkey_table[i].nsig;
367     } while( load_pubkey_modules() );
368     if( is_RSA(algo) )    /* special hack, so that we are able to */
369         return 1;         /* see the RSA keyids */
370     return 0;
371 }
372
373 /****************
374  * Return the number of encryption material numbers
375  */
376 int
377 pubkey_get_nenc( int algo )
378 {
379     int i;
380     do {
381         for(i=0; pubkey_table[i].name; i++ )
382             if( pubkey_table[i].algo == algo )
383                 return pubkey_table[i].nenc;
384     } while( load_pubkey_modules() );
385     if( is_RSA(algo) )    /* special hack, so that we are able to */
386         return 1;         /* see the RSA keyids */
387     return 0;
388 }
389
390 /****************
391  * Get the number of nbits from the public key
392  */
393 unsigned
394 pubkey_nbits( int algo, MPI *pkey )
395 {
396     int i;
397
398     do {
399         for(i=0; pubkey_table[i].name; i++ )
400             if( pubkey_table[i].algo == algo )
401                 return (*pubkey_table[i].get_nbits)( algo, pkey );
402     } while( load_pubkey_modules() );
403     if( is_RSA(algo) )  /* we always wanna see the length of a key :-) */
404         return mpi_get_nbits( pkey[0] );
405     return 0;
406 }
407
408
409 int
410 pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
411 {
412     int i;
413
414     do {
415         for(i=0; pubkey_table[i].name; i++ )
416             if( pubkey_table[i].algo == algo )
417                 return (*pubkey_table[i].generate)( algo, nbits,
418                                                     skey, retfactors );
419     } while( load_pubkey_modules() );
420     return G10ERR_PUBKEY_ALGO;
421 }
422
423
424 int
425 pubkey_check_secret_key( int algo, MPI *skey )
426 {
427     int i;
428
429     do {
430         for(i=0; pubkey_table[i].name; i++ )
431             if( pubkey_table[i].algo == algo )
432                 return (*pubkey_table[i].check_secret_key)( algo, skey );
433     } while( load_pubkey_modules() );
434     return G10ERR_PUBKEY_ALGO;
435 }
436
437
438 /****************
439  * This is the interface to the public key encryption.
440  * Encrypt DATA with PKEY and put it into RESARR which
441  * should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
442  * algorithm allows this - check with pubkey_get_nenc() )
443  */
444 int
445 pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
446 {
447     int i, rc;
448
449     if( DBG_CIPHER ) {
450         log_debug("pubkey_encrypt: algo=%d\n", algo );
451         for(i=0; i < pubkey_get_npkey(algo); i++ )
452             log_mpidump("  pkey:", pkey[i] );
453         log_mpidump("  data:", data );
454     }
455
456     do {
457         for(i=0; pubkey_table[i].name; i++ )
458             if( pubkey_table[i].algo == algo ) {
459                 rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey );
460                 goto ready;
461             }
462     } while( load_pubkey_modules() );
463     rc = G10ERR_PUBKEY_ALGO;
464   ready:
465     if( !rc && DBG_CIPHER ) {
466         for(i=0; i < pubkey_get_nenc(algo); i++ )
467             log_mpidump("  encr:", resarr[i] );
468     }
469     return rc;
470 }
471
472
473
474 /****************
475  * This is the interface to the public key decryption.
476  * ALGO gives the algorithm to use and this implicitly determines
477  * the size of the arrays.
478  * result is a pointer to a mpi variable which will receive a
479  * newly allocated mpi or NULL in case of an error.
480  */
481 int
482 pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
483 {
484     int i, rc;
485
486     *result = NULL; /* so the caller can always do an mpi_free */
487     if( DBG_CIPHER ) {
488         log_debug("pubkey_decrypt: algo=%d\n", algo );
489         for(i=0; i < pubkey_get_nskey(algo); i++ )
490             log_mpidump("  skey:", skey[i] );
491         for(i=0; i < pubkey_get_nenc(algo); i++ )
492             log_mpidump("  data:", data[i] );
493     }
494
495     do {
496         for(i=0; pubkey_table[i].name; i++ )
497             if( pubkey_table[i].algo == algo ) {
498                 rc = (*pubkey_table[i].decrypt)( algo, result, data, skey );
499                 goto ready;
500             }
501     } while( load_pubkey_modules() );
502     rc = G10ERR_PUBKEY_ALGO;
503   ready:
504     if( !rc && DBG_CIPHER ) {
505         log_mpidump(" plain:", *result );
506     }
507     return rc;
508 }
509
510
511 /****************
512  * This is the interface to the public key signing.
513  * Sign data with skey and put the result into resarr which
514  * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
515  * algorithm allows this - check with pubkey_get_nsig() )
516  */
517 int
518 pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
519 {
520     int i, rc;
521
522     if( DBG_CIPHER ) {
523         log_debug("pubkey_sign: algo=%d\n", algo );
524         for(i=0; i < pubkey_get_nskey(algo); i++ )
525             log_mpidump("  skey:", skey[i] );
526         log_mpidump("  data:", data );
527     }
528
529     do {
530         for(i=0; pubkey_table[i].name; i++ )
531             if( pubkey_table[i].algo == algo ) {
532                 rc = (*pubkey_table[i].sign)( algo, resarr, data, skey );
533                 goto ready;
534             }
535     } while( load_pubkey_modules() );
536     rc = G10ERR_PUBKEY_ALGO;
537   ready:
538     if( !rc && DBG_CIPHER ) {
539         for(i=0; i < pubkey_get_nsig(algo); i++ )
540             log_mpidump("   sig:", resarr[i] );
541     }
542     return rc;
543 }
544
545 /****************
546  * Verify a public key signature.
547  * Return 0 if the signature is good
548  */
549 int
550 pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
551                     int (*cmp)(void *, MPI), void *opaquev )
552 {
553     int i, rc;
554
555     do {
556         for(i=0; pubkey_table[i].name; i++ )
557             if( pubkey_table[i].algo == algo ) {
558                 rc = (*pubkey_table[i].verify)( algo, hash, data, pkey,
559                                                             cmp, opaquev );
560                 goto ready;
561             }
562     } while( load_pubkey_modules() );
563     rc = G10ERR_PUBKEY_ALGO;
564   ready:
565     return rc;
566 }
567