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