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