1
/* pubkey.c - pubkey dispatcher
2
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4
* This file is part of GnuPG.
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.
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.
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
37
struct pubkey_table_s {
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 );
55
static struct pubkey_table_s pubkey_table[TABLE_SIZE];
56
static int disabled_algos[TABLE_SIZE];
61
dummy_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
62
{ log_bug("no generate() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
65
dummy_check_secret_key( int algo, MPI *skey )
66
{ log_bug("no check_secret_key() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
70
dummy_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
71
{ log_bug("no encrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
74
dummy_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
75
{ log_bug("no decrypt() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
78
dummy_sign( int algo, MPI *resarr, MPI data, MPI *skey )
79
{ log_bug("no sign() for %d\n", algo ); return G10ERR_PUBKEY_ALGO; }
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; }
88
dummy_get_nbits( int algo, MPI *pkey )
89
{ log_bug("no get_nbits() for %d\n", algo ); return 0; }
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.
98
setup_pubkey_table(void)
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 )
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 )
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 )
155
pubkey_table[i].algo = PUBKEY_ALGO_RSA;
156
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
157
&pubkey_table[i].npkey,
158
&pubkey_table[i].nskey,
159
&pubkey_table[i].nenc,
160
&pubkey_table[i].nsig,
161
&pubkey_table[i].use );
162
pubkey_table[i].generate = rsa_generate;
163
pubkey_table[i].check_secret_key = rsa_check_secret_key;
164
pubkey_table[i].encrypt = rsa_encrypt;
165
pubkey_table[i].decrypt = rsa_decrypt;
166
pubkey_table[i].sign = rsa_sign;
167
pubkey_table[i].verify = rsa_verify;
168
pubkey_table[i].get_nbits = rsa_get_nbits;
169
if( !pubkey_table[i].name )
172
pubkey_table[i].algo = PUBKEY_ALGO_RSA_E;
173
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
174
&pubkey_table[i].npkey,
175
&pubkey_table[i].nskey,
176
&pubkey_table[i].nenc,
177
&pubkey_table[i].nsig,
178
&pubkey_table[i].use );
179
pubkey_table[i].generate = rsa_generate;
180
pubkey_table[i].check_secret_key = rsa_check_secret_key;
181
pubkey_table[i].encrypt = rsa_encrypt;
182
pubkey_table[i].decrypt = rsa_decrypt;
183
pubkey_table[i].sign = dummy_sign;
184
pubkey_table[i].verify = dummy_verify;
185
pubkey_table[i].get_nbits = rsa_get_nbits;
186
if( !pubkey_table[i].name )
189
pubkey_table[i].algo = PUBKEY_ALGO_RSA_S;
190
pubkey_table[i].name = rsa_get_info( pubkey_table[i].algo,
191
&pubkey_table[i].npkey,
192
&pubkey_table[i].nskey,
193
&pubkey_table[i].nenc,
194
&pubkey_table[i].nsig,
195
&pubkey_table[i].use );
196
pubkey_table[i].generate = rsa_generate;
197
pubkey_table[i].check_secret_key = rsa_check_secret_key;
198
pubkey_table[i].encrypt = dummy_encrypt;
199
pubkey_table[i].decrypt = dummy_decrypt;
200
pubkey_table[i].sign = rsa_sign;
201
pubkey_table[i].verify = rsa_verify;
202
pubkey_table[i].get_nbits = rsa_get_nbits;
203
if( !pubkey_table[i].name )
207
for( ; i < TABLE_SIZE; i++ )
208
pubkey_table[i].name = NULL;
213
* Try to load all modules and return true if new modules are available
216
load_pubkey_modules(void)
218
static int initialized = 0;
221
setup_pubkey_table();
230
* Map a string to the pubkey algo
233
string_to_pubkey_algo( const char *string )
239
for(i=0; (s=pubkey_table[i].name); i++ )
240
if( !ascii_strcasecmp( s, string ) )
241
return pubkey_table[i].algo;
242
} while( load_pubkey_modules() );
248
* Map a pubkey algo to a string
251
pubkey_algo_to_string( int algo )
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() );
265
disable_pubkey_algo( int algo )
269
for(i=0; i < DIM(disabled_algos); i++ ) {
270
if( !disabled_algos[i] || disabled_algos[i] == algo ) {
271
disabled_algos[i] = algo;
275
log_fatal("can't disable pubkey algo %d: table full\n", algo );
280
check_pubkey_algo( int algo )
282
return check_pubkey_algo2( algo, 0 );
286
* a use of 0 means: don't care
289
check_pubkey_algo2( int algo, unsigned use )
294
for(i=0; pubkey_table[i].name; i++ )
295
if( pubkey_table[i].algo == algo ) {
296
if( (use & PUBKEY_USAGE_SIG)
297
&& !(pubkey_table[i].use & PUBKEY_USAGE_SIG) )
298
return G10ERR_WR_PUBKEY_ALGO;
299
if( (use & PUBKEY_USAGE_ENC)
300
&& !(pubkey_table[i].use & PUBKEY_USAGE_ENC) )
301
return G10ERR_WR_PUBKEY_ALGO;
303
for(i=0; i < DIM(disabled_algos); i++ ) {
304
if( disabled_algos[i] == algo )
305
return G10ERR_PUBKEY_ALGO;
309
} while( load_pubkey_modules() );
310
return G10ERR_PUBKEY_ALGO;
317
* Return the number of public key material numbers
320
pubkey_get_npkey( int algo )
324
for(i=0; pubkey_table[i].name; i++ )
325
if( pubkey_table[i].algo == algo )
326
return pubkey_table[i].npkey;
327
} while( load_pubkey_modules() );
332
* Return the number of secret key material numbers
335
pubkey_get_nskey( int algo )
339
for(i=0; pubkey_table[i].name; i++ )
340
if( pubkey_table[i].algo == algo )
341
return pubkey_table[i].nskey;
342
} while( load_pubkey_modules() );
343
if( is_RSA(algo) ) /* special hack, so that we are able to */
344
return 6; /* see the RSA keyids */
349
* Return the number of signature material numbers
352
pubkey_get_nsig( int algo )
356
for(i=0; pubkey_table[i].name; i++ )
357
if( pubkey_table[i].algo == algo )
358
return pubkey_table[i].nsig;
359
} while( load_pubkey_modules() );
360
if( is_RSA(algo) ) /* special hack, so that we are able to */
361
return 1; /* see the RSA keyids */
366
* Return the number of encryption material numbers
369
pubkey_get_nenc( int algo )
373
for(i=0; pubkey_table[i].name; i++ )
374
if( pubkey_table[i].algo == algo )
375
return pubkey_table[i].nenc;
376
} while( load_pubkey_modules() );
377
if( is_RSA(algo) ) /* special hack, so that we are able to */
378
return 1; /* see the RSA keyids */
383
* Get the number of nbits from the public key
386
pubkey_nbits( int algo, MPI *pkey )
391
for(i=0; pubkey_table[i].name; i++ )
392
if( pubkey_table[i].algo == algo )
393
return (*pubkey_table[i].get_nbits)( algo, pkey );
394
} while( load_pubkey_modules() );
395
if( is_RSA(algo) ) /* we always wanna see the length of a key :-) */
396
return mpi_get_nbits( pkey[0] );
402
pubkey_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
407
for(i=0; pubkey_table[i].name; i++ )
408
if( pubkey_table[i].algo == algo )
409
return (*pubkey_table[i].generate)( algo, nbits,
411
} while( load_pubkey_modules() );
412
return G10ERR_PUBKEY_ALGO;
417
pubkey_check_secret_key( int algo, MPI *skey )
422
for(i=0; pubkey_table[i].name; i++ )
423
if( pubkey_table[i].algo == algo )
424
return (*pubkey_table[i].check_secret_key)( algo, skey );
425
} while( load_pubkey_modules() );
426
return G10ERR_PUBKEY_ALGO;
431
* This is the interface to the public key encryption.
432
* Encrypt DATA with PKEY and put it into RESARR which
433
* should be an array of MPIs of size PUBKEY_MAX_NENC (or less if the
434
* algorithm allows this - check with pubkey_get_nenc() )
437
pubkey_encrypt( int algo, MPI *resarr, MPI data, MPI *pkey )
442
log_debug("pubkey_encrypt: algo=%d\n", algo );
443
for(i=0; i < pubkey_get_npkey(algo); i++ )
444
log_mpidump(" pkey:", pkey[i] );
445
log_mpidump(" data:", data );
449
for(i=0; pubkey_table[i].name; i++ )
450
if( pubkey_table[i].algo == algo ) {
451
rc = (*pubkey_table[i].encrypt)( algo, resarr, data, pkey );
454
} while( load_pubkey_modules() );
455
rc = G10ERR_PUBKEY_ALGO;
457
if( !rc && DBG_CIPHER ) {
458
for(i=0; i < pubkey_get_nenc(algo); i++ )
459
log_mpidump(" encr:", resarr[i] );
467
* This is the interface to the public key decryption.
468
* ALGO gives the algorithm to use and this implicitly determines
469
* the size of the arrays.
470
* result is a pointer to a mpi variable which will receive a
471
* newly allocated mpi or NULL in case of an error.
474
pubkey_decrypt( int algo, MPI *result, MPI *data, MPI *skey )
478
*result = NULL; /* so the caller can always do an mpi_free */
480
log_debug("pubkey_decrypt: algo=%d\n", algo );
481
for(i=0; i < pubkey_get_nskey(algo); i++ )
482
log_mpidump(" skey:", skey[i] );
483
for(i=0; i < pubkey_get_nenc(algo); i++ )
484
log_mpidump(" data:", data[i] );
488
for(i=0; pubkey_table[i].name; i++ )
489
if( pubkey_table[i].algo == algo ) {
490
rc = (*pubkey_table[i].decrypt)( algo, result, data, skey );
493
} while( load_pubkey_modules() );
494
rc = G10ERR_PUBKEY_ALGO;
496
if( !rc && DBG_CIPHER ) {
497
log_mpidump(" plain:", *result );
504
* This is the interface to the public key signing.
505
* Sign data with skey and put the result into resarr which
506
* should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
507
* algorithm allows this - check with pubkey_get_nsig() )
510
pubkey_sign( int algo, MPI *resarr, MPI data, MPI *skey )
515
log_debug("pubkey_sign: algo=%d\n", algo );
516
for(i=0; i < pubkey_get_nskey(algo); i++ )
517
log_mpidump(" skey:", skey[i] );
518
log_mpidump(" data:", data );
522
for(i=0; pubkey_table[i].name; i++ )
523
if( pubkey_table[i].algo == algo ) {
524
rc = (*pubkey_table[i].sign)( algo, resarr, data, skey );
527
} while( load_pubkey_modules() );
528
rc = G10ERR_PUBKEY_ALGO;
530
if( !rc && DBG_CIPHER ) {
531
for(i=0; i < pubkey_get_nsig(algo); i++ )
532
log_mpidump(" sig:", resarr[i] );
538
* Verify a public key signature.
539
* Return 0 if the signature is good
542
pubkey_verify( int algo, MPI hash, MPI *data, MPI *pkey,
543
int (*cmp)(void *, MPI), void *opaquev )
548
for(i=0; pubkey_table[i].name; i++ )
549
if( pubkey_table[i].algo == algo ) {
550
rc = (*pubkey_table[i].verify)( algo, hash, data, pkey,
554
} while( load_pubkey_modules() );
555
rc = G10ERR_PUBKEY_ALGO;