Diffstat (limited to 'pwmanager/libcrypt/cipher/elgamal.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | pwmanager/libcrypt/cipher/elgamal.c | 682 |
1 files changed, 682 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/elgamal.c b/pwmanager/libcrypt/cipher/elgamal.c new file mode 100644 index 0000000..e62b1e5 --- a/dev/null +++ b/pwmanager/libcrypt/cipher/elgamal.c | |||
@@ -0,0 +1,682 @@ | |||
1 | /* Elgamal.c - ElGamal Public Key encryption | ||
2 | * Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of Libgcrypt. | ||
5 | * | ||
6 | * Libgcrypt is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Lesser general Public License as | ||
8 | * published by the Free Software Foundation; either version 2.1 of | ||
9 | * the License, or (at your option) any later version. | ||
10 | * | ||
11 | * Libgcrypt 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 Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License 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 | * For a description of the algorithm, see: | ||
21 | * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. | ||
22 | * ISBN 0-471-11709-9. Pages 476 ff. | ||
23 | */ | ||
24 | |||
25 | #include <config.h> | ||
26 | #include <stdio.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <string.h> | ||
29 | #include "g10lib.h" | ||
30 | #include "mpi.h" | ||
31 | #include "cipher.h" | ||
32 | |||
33 | typedef struct | ||
34 | { | ||
35 | gcry_mpi_t p; /* prime */ | ||
36 | gcry_mpi_t g; /* group generator */ | ||
37 | gcry_mpi_t y; /* g^x mod p */ | ||
38 | } ELG_public_key; | ||
39 | |||
40 | |||
41 | typedef struct | ||
42 | { | ||
43 | gcry_mpi_t p; /* prime */ | ||
44 | gcry_mpi_t g; /* group generator */ | ||
45 | gcry_mpi_t y; /* g^x mod p */ | ||
46 | gcry_mpi_t x; /* secret exponent */ | ||
47 | } ELG_secret_key; | ||
48 | |||
49 | |||
50 | static void test_keys (ELG_secret_key *sk, unsigned nbits); | ||
51 | static gcry_mpi_t gen_k (gcry_mpi_t p, int small_k); | ||
52 | static void generate (ELG_secret_key *sk, unsigned nbits, gcry_mpi_t **factors); | ||
53 | static int check_secret_key (ELG_secret_key *sk); | ||
54 | static void do_encrypt (gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, | ||
55 | ELG_public_key *pkey); | ||
56 | static void decrypt (gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, | ||
57 | ELG_secret_key *skey); | ||
58 | static void sign (gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, | ||
59 | ELG_secret_key *skey); | ||
60 | static int verify (gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, | ||
61 | ELG_public_key *pkey); | ||
62 | |||
63 | |||
64 | static void (*progress_cb) (void *, const char *, int, int, int); | ||
65 | static void *progress_cb_data; | ||
66 | |||
67 | void | ||
68 | _gcry_register_pk_elg_progress (void (*cb) (void *, const char *, | ||
69 | int, int, int), | ||
70 | void *cb_data) | ||
71 | { | ||
72 | progress_cb = cb; | ||
73 | progress_cb_data = cb_data; | ||
74 | } | ||
75 | |||
76 | |||
77 | static void | ||
78 | progress (int c) | ||
79 | { | ||
80 | if (progress_cb) | ||
81 | progress_cb (progress_cb_data, "pk_elg", c, 0, 0); | ||
82 | } | ||
83 | |||
84 | |||
85 | /**************** | ||
86 | * Michael Wiener's table on subgroup sizes to match field sizes | ||
87 | * (floating around somewhere - Fixme: need a reference) | ||
88 | */ | ||
89 | static unsigned int | ||
90 | wiener_map( unsigned int n ) | ||
91 | { | ||
92 | static struct { unsigned int p_n, q_n; } t[] = | ||
93 | { /* p q attack cost */ | ||
94 | { 512, 119 },/* 9 x 10^17 */ | ||
95 | { 768, 145 },/* 6 x 10^21 */ | ||
96 | { 1024, 165 },/* 7 x 10^24 */ | ||
97 | { 1280, 183 },/* 3 x 10^27 */ | ||
98 | { 1536, 198 },/* 7 x 10^29 */ | ||
99 | { 1792, 212 },/* 9 x 10^31 */ | ||
100 | { 2048, 225 },/* 8 x 10^33 */ | ||
101 | { 2304, 237 },/* 5 x 10^35 */ | ||
102 | { 2560, 249 },/* 3 x 10^37 */ | ||
103 | { 2816, 259 },/* 1 x 10^39 */ | ||
104 | { 3072, 269 },/* 3 x 10^40 */ | ||
105 | { 3328, 279 },/* 8 x 10^41 */ | ||
106 | { 3584, 288 },/* 2 x 10^43 */ | ||
107 | { 3840, 296 },/* 4 x 10^44 */ | ||
108 | { 4096, 305 },/* 7 x 10^45 */ | ||
109 | { 4352, 313 },/* 1 x 10^47 */ | ||
110 | { 4608, 320 },/* 2 x 10^48 */ | ||
111 | { 4864, 328 },/* 2 x 10^49 */ | ||
112 | { 5120, 335 },/* 3 x 10^50 */ | ||
113 | { 0, 0 } | ||
114 | }; | ||
115 | int i; | ||
116 | |||
117 | for(i=0; t[i].p_n; i++ ) | ||
118 | { | ||
119 | if( n <= t[i].p_n ) | ||
120 | return t[i].q_n; | ||
121 | } | ||
122 | /* Not in table - use an arbitrary high number. */ | ||
123 | return n / 8 + 200; | ||
124 | } | ||
125 | |||
126 | static void | ||
127 | test_keys( ELG_secret_key *sk, unsigned nbits ) | ||
128 | { | ||
129 | ELG_public_key pk; | ||
130 | gcry_mpi_t test = gcry_mpi_new ( 0 ); | ||
131 | gcry_mpi_t out1_a = gcry_mpi_new ( nbits ); | ||
132 | gcry_mpi_t out1_b = gcry_mpi_new ( nbits ); | ||
133 | gcry_mpi_t out2 = gcry_mpi_new ( nbits ); | ||
134 | |||
135 | pk.p = sk->p; | ||
136 | pk.g = sk->g; | ||
137 | pk.y = sk->y; | ||
138 | |||
139 | gcry_mpi_randomize( test, nbits, GCRY_WEAK_RANDOM ); | ||
140 | |||
141 | do_encrypt( out1_a, out1_b, test, &pk ); | ||
142 | decrypt( out2, out1_a, out1_b, sk ); | ||
143 | if( mpi_cmp( test, out2 ) ) | ||
144 | log_fatal("ElGamal operation: encrypt, decrypt failed\n"); | ||
145 | |||
146 | sign( out1_a, out1_b, test, sk ); | ||
147 | if( !verify( out1_a, out1_b, test, &pk ) ) | ||
148 | log_fatal("ElGamal operation: sign, verify failed\n"); | ||
149 | |||
150 | gcry_mpi_release ( test ); | ||
151 | gcry_mpi_release ( out1_a ); | ||
152 | gcry_mpi_release ( out1_b ); | ||
153 | gcry_mpi_release ( out2 ); | ||
154 | } | ||
155 | |||
156 | |||
157 | /**************** | ||
158 | * Generate a random secret exponent k from prime p, so that k is | ||
159 | * relatively prime to p-1. With SMALL_K set, k will be selected for | ||
160 | * better encryption performance - this must never be used signing! | ||
161 | */ | ||
162 | static gcry_mpi_t | ||
163 | gen_k( gcry_mpi_t p, int small_k ) | ||
164 | { | ||
165 | gcry_mpi_t k = mpi_alloc_secure( 0 ); | ||
166 | gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(p) ); | ||
167 | gcry_mpi_t p_1 = mpi_copy(p); | ||
168 | unsigned int orig_nbits = mpi_get_nbits(p); | ||
169 | unsigned int nbits, nbytes; | ||
170 | char *rndbuf = NULL; | ||
171 | |||
172 | if (small_k) | ||
173 | { | ||
174 | /* Using a k much lesser than p is sufficient for encryption and | ||
175 | * it greatly improves the encryption performance. We use | ||
176 | * Wiener's table and add a large safety margin. */ | ||
177 | nbits = wiener_map( orig_nbits ) * 3 / 2; | ||
178 | if( nbits >= orig_nbits ) | ||
179 | BUG(); | ||
180 | } | ||
181 | else | ||
182 | nbits = orig_nbits; | ||
183 | |||
184 | |||
185 | nbytes = (nbits+7)/8; | ||
186 | if( DBG_CIPHER ) | ||
187 | log_debug("choosing a random k "); | ||
188 | mpi_sub_ui( p_1, p, 1); | ||
189 | for(;;) | ||
190 | { | ||
191 | if( !rndbuf || nbits < 32 ) | ||
192 | { | ||
193 | gcry_free(rndbuf); | ||
194 | rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM ); | ||
195 | } | ||
196 | else | ||
197 | { | ||
198 | /* Change only some of the higher bits. We could improve | ||
199 | this by directly requesting more memory at the first call | ||
200 | to get_random_bytes() and use this the here maybe it is | ||
201 | easier to do this directly in random.c Anyway, it is | ||
202 | highly inlikely that we will ever reach this code. */ | ||
203 | char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM ); | ||
204 | memcpy( rndbuf, pp, 4 ); | ||
205 | gcry_free(pp); | ||
206 | } | ||
207 | _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); | ||
208 | |||
209 | for(;;) | ||
210 | { | ||
211 | if( !(mpi_cmp( k, p_1 ) < 0) ) /* check: k < (p-1) */ | ||
212 | { | ||
213 | if( DBG_CIPHER ) | ||
214 | progress('+'); | ||
215 | break; /* no */ | ||
216 | } | ||
217 | if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */ | ||
218 | { | ||
219 | if( DBG_CIPHER ) | ||
220 | progress('-'); | ||
221 | break; /* no */ | ||
222 | } | ||
223 | if (gcry_mpi_gcd( temp, k, p_1 )) | ||
224 | goto found; /* okay, k is relative prime to (p-1) */ | ||
225 | mpi_add_ui( k, k, 1 ); | ||
226 | if( DBG_CIPHER ) | ||
227 | progress('.'); | ||
228 | } | ||
229 | } | ||
230 | found: | ||
231 | gcry_free(rndbuf); | ||
232 | if( DBG_CIPHER ) | ||
233 | progress('\n'); | ||
234 | mpi_free(p_1); | ||
235 | mpi_free(temp); | ||
236 | |||
237 | return k; | ||
238 | } | ||
239 | |||
240 | /**************** | ||
241 | * Generate a key pair with a key of size NBITS | ||
242 | * Returns: 2 structures filles with all needed values | ||
243 | * and an array with n-1 factors of (p-1) | ||
244 | */ | ||
245 | static void | ||
246 | generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) | ||
247 | { | ||
248 | gcry_mpi_t p; /* the prime */ | ||
249 | gcry_mpi_t p_min1; | ||
250 | gcry_mpi_t g; | ||
251 | gcry_mpi_t x; /* the secret exponent */ | ||
252 | gcry_mpi_t y; | ||
253 | gcry_mpi_t temp; | ||
254 | unsigned int qbits; | ||
255 | unsigned int xbits; | ||
256 | byte *rndbuf; | ||
257 | |||
258 | p_min1 = gcry_mpi_new ( nbits ); | ||
259 | temp = gcry_mpi_new( nbits ); | ||
260 | qbits = wiener_map( nbits ); | ||
261 | if( qbits & 1 ) /* better have a even one */ | ||
262 | qbits++; | ||
263 | g = mpi_alloc(1); | ||
264 | p = _gcry_generate_elg_prime( 0, nbits, qbits, g, ret_factors ); | ||
265 | mpi_sub_ui(p_min1, p, 1); | ||
266 | |||
267 | |||
268 | /* Select a random number which has these properties: | ||
269 | * 0 < x < p-1 | ||
270 | * This must be a very good random number because this is the | ||
271 | * secret part. The prime is public and may be shared anyway, | ||
272 | * so a random generator level of 1 is used for the prime. | ||
273 | * | ||
274 | * I don't see a reason to have a x of about the same size | ||
275 | * as the p. It should be sufficient to have one about the size | ||
276 | * of q or the later used k plus a large safety margin. Decryption | ||
277 | * will be much faster with such an x. | ||
278 | */ | ||
279 | xbits = qbits * 3 / 2; | ||
280 | if( xbits >= nbits ) | ||
281 | BUG(); | ||
282 | x = gcry_mpi_snew ( xbits ); | ||
283 | if( DBG_CIPHER ) | ||
284 | log_debug("choosing a random x of size %u", xbits ); | ||
285 | rndbuf = NULL; | ||
286 | do | ||
287 | { | ||
288 | if( DBG_CIPHER ) | ||
289 | progress('.'); | ||
290 | if( rndbuf ) | ||
291 | { /* Change only some of the higher bits */ | ||
292 | if( xbits < 16 ) /* should never happen ... */ | ||
293 | { | ||
294 | gcry_free(rndbuf); | ||
295 | rndbuf = gcry_random_bytes_secure( (xbits+7)/8, | ||
296 | GCRY_VERY_STRONG_RANDOM ); | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | char *r = gcry_random_bytes_secure( 2, | ||
301 | GCRY_VERY_STRONG_RANDOM ); | ||
302 | memcpy(rndbuf, r, 2 ); | ||
303 | gcry_free(r); | ||
304 | } | ||
305 | } | ||
306 | else | ||
307 | { | ||
308 | rndbuf = gcry_random_bytes_secure( (xbits+7)/8, | ||
309 | GCRY_VERY_STRONG_RANDOM ); | ||
310 | } | ||
311 | _gcry_mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); | ||
312 | mpi_clear_highbit( x, xbits+1 ); | ||
313 | } | ||
314 | while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); | ||
315 | gcry_free(rndbuf); | ||
316 | |||
317 | y = gcry_mpi_new (nbits); | ||
318 | gcry_mpi_powm( y, g, x, p ); | ||
319 | |||
320 | if( DBG_CIPHER ) | ||
321 | { | ||
322 | progress('\n'); | ||
323 | log_mpidump("elg p= ", p ); | ||
324 | log_mpidump("elg g= ", g ); | ||
325 | log_mpidump("elg y= ", y ); | ||
326 | log_mpidump("elg x= ", x ); | ||
327 | } | ||
328 | |||
329 | /* Copy the stuff to the key structures */ | ||
330 | sk->p = p; | ||
331 | sk->g = g; | ||
332 | sk->y = y; | ||
333 | sk->x = x; | ||
334 | |||
335 | /* Now we can test our keys (this should never fail!) */ | ||
336 | test_keys( sk, nbits - 64 ); | ||
337 | |||
338 | gcry_mpi_release ( p_min1 ); | ||
339 | gcry_mpi_release ( temp ); | ||
340 | } | ||
341 | |||
342 | |||
343 | /**************** | ||
344 | * Test whether the secret key is valid. | ||
345 | * Returns: if this is a valid key. | ||
346 | */ | ||
347 | static int | ||
348 | check_secret_key( ELG_secret_key *sk ) | ||
349 | { | ||
350 | int rc; | ||
351 | gcry_mpi_t y = mpi_alloc( mpi_get_nlimbs(sk->y) ); | ||
352 | |||
353 | gcry_mpi_powm( y, sk->g, sk->x, sk->p ); | ||
354 | rc = !mpi_cmp( y, sk->y ); | ||
355 | mpi_free( y ); | ||
356 | return rc; | ||
357 | } | ||
358 | |||
359 | |||
360 | static void | ||
361 | do_encrypt(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey ) | ||
362 | { | ||
363 | gcry_mpi_t k; | ||
364 | |||
365 | /* Note: maybe we should change the interface, so that it | ||
366 | * is possible to check that input is < p and return an | ||
367 | * error code. | ||
368 | */ | ||
369 | |||
370 | k = gen_k( pkey->p, 1 ); | ||
371 | gcry_mpi_powm( a, pkey->g, k, pkey->p ); | ||
372 | /* b = (y^k * input) mod p | ||
373 | * = ((y^k mod p) * (input mod p)) mod p | ||
374 | * and because input is < p | ||
375 | * = ((y^k mod p) * input) mod p | ||
376 | */ | ||
377 | gcry_mpi_powm( b, pkey->y, k, pkey->p ); | ||
378 | gcry_mpi_mulm( b, b, input, pkey->p ); | ||
379 | #if 0 | ||
380 | if( DBG_CIPHER ) | ||
381 | { | ||
382 | log_mpidump("elg encrypted y= ", pkey->y); | ||
383 | log_mpidump("elg encrypted p= ", pkey->p); | ||
384 | log_mpidump("elg encrypted k= ", k); | ||
385 | log_mpidump("elg encrypted M= ", input); | ||
386 | log_mpidump("elg encrypted a= ", a); | ||
387 | log_mpidump("elg encrypted b= ", b); | ||
388 | } | ||
389 | #endif | ||
390 | mpi_free(k); | ||
391 | } | ||
392 | |||
393 | |||
394 | |||
395 | |||
396 | static void | ||
397 | decrypt(gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey ) | ||
398 | { | ||
399 | gcry_mpi_t t1 = mpi_alloc_secure( mpi_get_nlimbs( skey->p ) ); | ||
400 | |||
401 | /* output = b/(a^x) mod p */ | ||
402 | gcry_mpi_powm( t1, a, skey->x, skey->p ); | ||
403 | mpi_invm( t1, t1, skey->p ); | ||
404 | mpi_mulm( output, b, t1, skey->p ); | ||
405 | #if 0 | ||
406 | if( DBG_CIPHER ) | ||
407 | { | ||
408 | log_mpidump("elg decrypted x= ", skey->x); | ||
409 | log_mpidump("elg decrypted p= ", skey->p); | ||
410 | log_mpidump("elg decrypted a= ", a); | ||
411 | log_mpidump("elg decrypted b= ", b); | ||
412 | log_mpidump("elg decrypted M= ", output); | ||
413 | } | ||
414 | #endif | ||
415 | mpi_free(t1); | ||
416 | } | ||
417 | |||
418 | |||
419 | /**************** | ||
420 | * Make an Elgamal signature out of INPUT | ||
421 | */ | ||
422 | |||
423 | static void | ||
424 | sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey ) | ||
425 | { | ||
426 | gcry_mpi_t k; | ||
427 | gcry_mpi_t t = mpi_alloc( mpi_get_nlimbs(a) ); | ||
428 | gcry_mpi_t inv = mpi_alloc( mpi_get_nlimbs(a) ); | ||
429 | gcry_mpi_t p_1 = mpi_copy(skey->p); | ||
430 | |||
431 | /* | ||
432 | * b = (t * inv) mod (p-1) | ||
433 | * b = (t * inv(k,(p-1),(p-1)) mod (p-1) | ||
434 | * b = (((M-x*a) mod (p-1)) * inv(k,(p-1),(p-1))) mod (p-1) | ||
435 | * | ||
436 | */ | ||
437 | mpi_sub_ui(p_1, p_1, 1); | ||
438 | k = gen_k( skey->p, 0 /* no small K ! */ ); | ||
439 | gcry_mpi_powm( a, skey->g, k, skey->p ); | ||
440 | mpi_mul(t, skey->x, a ); | ||
441 | mpi_subm(t, input, t, p_1 ); | ||
442 | mpi_invm(inv, k, p_1 ); | ||
443 | mpi_mulm(b, t, inv, p_1 ); | ||
444 | |||
445 | #if 0 | ||
446 | if( DBG_CIPHER ) | ||
447 | { | ||
448 | log_mpidump("elg sign p= ", skey->p); | ||
449 | log_mpidump("elg sign g= ", skey->g); | ||
450 | log_mpidump("elg sign y= ", skey->y); | ||
451 | log_mpidump("elg sign x= ", skey->x); | ||
452 | log_mpidump("elg sign k= ", k); | ||
453 | log_mpidump("elg sign M= ", input); | ||
454 | log_mpidump("elg sign a= ", a); | ||
455 | log_mpidump("elg sign b= ", b); | ||
456 | } | ||
457 | #endif | ||
458 | mpi_free(k); | ||
459 | mpi_free(t); | ||
460 | mpi_free(inv); | ||
461 | mpi_free(p_1); | ||
462 | } | ||
463 | |||
464 | |||
465 | /**************** | ||
466 | * Returns true if the signature composed of A and B is valid. | ||
467 | */ | ||
468 | static int | ||
469 | verify(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey ) | ||
470 | { | ||
471 | int rc; | ||
472 | gcry_mpi_t t1; | ||
473 | gcry_mpi_t t2; | ||
474 | gcry_mpi_t base[4]; | ||
475 | gcry_mpi_t ex[4]; | ||
476 | |||
477 | if( !(mpi_cmp_ui( a, 0 ) > 0 && mpi_cmp( a, pkey->p ) < 0) ) | ||
478 | return 0; /* assertion0 < a < p failed */ | ||
479 | |||
480 | t1 = mpi_alloc( mpi_get_nlimbs(a) ); | ||
481 | t2 = mpi_alloc( mpi_get_nlimbs(a) ); | ||
482 | |||
483 | #if 0 | ||
484 | /* t1 = (y^a mod p) * (a^b mod p) mod p */ | ||
485 | gcry_mpi_powm( t1, pkey->y, a, pkey->p ); | ||
486 | gcry_mpi_powm( t2, a, b, pkey->p ); | ||
487 | mpi_mulm( t1, t1, t2, pkey->p ); | ||
488 | |||
489 | /* t2 = g ^ input mod p */ | ||
490 | gcry_mpi_powm( t2, pkey->g, input, pkey->p ); | ||
491 | |||
492 | rc = !mpi_cmp( t1, t2 ); | ||
493 | #elif 0 | ||
494 | /* t1 = (y^a mod p) * (a^b mod p) mod p */ | ||
495 | base[0] = pkey->y; ex[0] = a; | ||
496 | base[1] = a; ex[1] = b; | ||
497 | base[2] = NULL; ex[2] = NULL; | ||
498 | mpi_mulpowm( t1, base, ex, pkey->p ); | ||
499 | |||
500 | /* t2 = g ^ input mod p */ | ||
501 | gcry_mpi_powm( t2, pkey->g, input, pkey->p ); | ||
502 | |||
503 | rc = !mpi_cmp( t1, t2 ); | ||
504 | #else | ||
505 | /* t1 = g ^ - input * y ^ a * a ^ b mod p */ | ||
506 | mpi_invm(t2, pkey->g, pkey->p ); | ||
507 | base[0] = t2 ; ex[0] = input; | ||
508 | base[1] = pkey->y; ex[1] = a; | ||
509 | base[2] = a; ex[2] = b; | ||
510 | base[3] = NULL; ex[3] = NULL; | ||
511 | mpi_mulpowm( t1, base, ex, pkey->p ); | ||
512 | rc = !mpi_cmp_ui( t1, 1 ); | ||
513 | |||
514 | #endif | ||
515 | |||
516 | mpi_free(t1); | ||
517 | mpi_free(t2); | ||
518 | return rc; | ||
519 | } | ||
520 | |||
521 | /********************************************* | ||
522 | ************** interface ****************** | ||
523 | *********************************************/ | ||
524 | |||
525 | gcry_err_code_t | ||
526 | _gcry_elg_generate (int algo, unsigned nbits, unsigned long dummy, | ||
527 | gcry_mpi_t *skey, gcry_mpi_t **retfactors) | ||
528 | { | ||
529 | ELG_secret_key sk; | ||
530 | |||
531 | generate (&sk, nbits, retfactors); | ||
532 | skey[0] = sk.p; | ||
533 | skey[1] = sk.g; | ||
534 | skey[2] = sk.y; | ||
535 | skey[3] = sk.x; | ||
536 | |||
537 | return GPG_ERR_NO_ERROR; | ||
538 | } | ||
539 | |||
540 | |||
541 | gcry_err_code_t | ||
542 | _gcry_elg_check_secret_key (int algo, gcry_mpi_t *skey) | ||
543 | { | ||
544 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
545 | ELG_secret_key sk; | ||
546 | |||
547 | if ((! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3])) | ||
548 | err = GPG_ERR_BAD_MPI; | ||
549 | else | ||
550 | { | ||
551 | sk.p = skey[0]; | ||
552 | sk.g = skey[1]; | ||
553 | sk.y = skey[2]; | ||
554 | sk.x = skey[3]; | ||
555 | |||
556 | if (! check_secret_key (&sk)) | ||
557 | err = GPG_ERR_BAD_SECKEY; | ||
558 | } | ||
559 | |||
560 | return err; | ||
561 | } | ||
562 | |||
563 | |||
564 | gcry_err_code_t | ||
565 | _gcry_elg_encrypt (int algo, gcry_mpi_t *resarr, | ||
566 | gcry_mpi_t data, gcry_mpi_t *pkey, int flags) | ||
567 | { | ||
568 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
569 | ELG_public_key pk; | ||
570 | |||
571 | if ((! data) || (! pkey[0]) || (! pkey[1]) || (! pkey[2])) | ||
572 | err = GPG_ERR_BAD_MPI; | ||
573 | else | ||
574 | { | ||
575 | pk.p = pkey[0]; | ||
576 | pk.g = pkey[1]; | ||
577 | pk.y = pkey[2]; | ||
578 | resarr[0] = mpi_alloc (mpi_get_nlimbs (pk.p)); | ||
579 | resarr[1] = mpi_alloc (mpi_get_nlimbs (pk.p)); | ||
580 | do_encrypt (resarr[0], resarr[1], data, &pk); | ||
581 | } | ||
582 | return err; | ||
583 | } | ||
584 | |||
585 | |||
586 | gcry_err_code_t | ||
587 | _gcry_elg_decrypt (int algo, gcry_mpi_t *result, | ||
588 | gcry_mpi_t *data, gcry_mpi_t *skey, int flags) | ||
589 | { | ||
590 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
591 | ELG_secret_key sk; | ||
592 | |||
593 | if ((! data[0]) || (! data[1]) | ||
594 | || (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3])) | ||
595 | err = GPG_ERR_BAD_MPI; | ||
596 | else | ||
597 | { | ||
598 | sk.p = skey[0]; | ||
599 | sk.g = skey[1]; | ||
600 | sk.y = skey[2]; | ||
601 | sk.x = skey[3]; | ||
602 | *result = mpi_alloc_secure (mpi_get_nlimbs (sk.p)); | ||
603 | decrypt (*result, data[0], data[1], &sk); | ||
604 | } | ||
605 | return err; | ||
606 | } | ||
607 | |||
608 | |||
609 | gcry_err_code_t | ||
610 | _gcry_elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) | ||
611 | { | ||
612 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
613 | ELG_secret_key sk; | ||
614 | |||
615 | if ((! data) | ||
616 | || (! skey[0]) || (! skey[1]) || (! skey[2]) || (! skey[3])) | ||
617 | err = GPG_ERR_BAD_MPI; | ||
618 | else | ||
619 | { | ||
620 | sk.p = skey[0]; | ||
621 | sk.g = skey[1]; | ||
622 | sk.y = skey[2]; | ||
623 | sk.x = skey[3]; | ||
624 | resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.p)); | ||
625 | resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p)); | ||
626 | sign (resarr[0], resarr[1], data, &sk); | ||
627 | } | ||
628 | |||
629 | return err; | ||
630 | } | ||
631 | |||
632 | gcry_err_code_t | ||
633 | _gcry_elg_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, | ||
634 | int (*cmp) (void *, gcry_mpi_t), void *opaquev) | ||
635 | { | ||
636 | gcry_err_code_t err = GPG_ERR_NO_ERROR; | ||
637 | ELG_public_key pk; | ||
638 | |||
639 | if ((! data[0]) || (! data[1]) || (! hash) | ||
640 | || (! pkey[0]) || (! pkey[1]) || (! pkey[2])) | ||
641 | err = GPG_ERR_BAD_MPI; | ||
642 | else | ||
643 | { | ||
644 | pk.p = pkey[0]; | ||
645 | pk.g = pkey[1]; | ||
646 | pk.y = pkey[2]; | ||
647 | if (! verify (data[0], data[1], hash, &pk)) | ||
648 | err = GPG_ERR_BAD_SIGNATURE; | ||
649 | } | ||
650 | |||
651 | return err; | ||
652 | } | ||
653 | |||
654 | |||
655 | unsigned int | ||
656 | _gcry_elg_get_nbits (int algo, gcry_mpi_t *pkey) | ||
657 | { | ||
658 | return mpi_get_nbits (pkey[0]); | ||
659 | } | ||
660 | |||
661 | static char *elg_names[] = | ||
662 | { | ||
663 | "elg", | ||
664 | "openpgp-elg", | ||
665 | "openpgp-elg-sig", | ||
666 | NULL, | ||
667 | }; | ||
668 | |||
669 | |||
670 | gcry_pk_spec_t _gcry_pubkey_spec_elg = | ||
671 | { | ||
672 | "ELG", elg_names, | ||
673 | "pgy", "pgyx", "ab", "rs", "pgy", | ||
674 | GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR, | ||
675 | _gcry_elg_generate, | ||
676 | _gcry_elg_check_secret_key, | ||
677 | _gcry_elg_encrypt, | ||
678 | _gcry_elg_decrypt, | ||
679 | _gcry_elg_sign, | ||
680 | _gcry_elg_verify, | ||
681 | _gcry_elg_get_nbits, | ||
682 | }; | ||