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