Mercurial > dropbear
comparison dh.c @ 0:d7da3b1e1540 libtomcrypt
put back the 0.95 makefile which was inadvertently merged over
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 31 May 2004 18:21:40 +0000 |
parents | |
children | 5d99163f7e32 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d7da3b1e1540 |
---|---|
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
2 * | |
3 * LibTomCrypt is a library that provides various cryptographic | |
4 * algorithms in a highly modular and flexible manner. | |
5 * | |
6 * The library is free for all purposes without any express | |
7 * guarantee it works. | |
8 * | |
9 * Tom St Denis, [email protected], http://libtomcrypt.org | |
10 */ | |
11 #include "mycrypt.h" | |
12 | |
13 #ifdef MDH | |
14 | |
15 /* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ | |
16 static const struct { | |
17 int size; | |
18 char *name, *base, *prime; | |
19 } sets[] = { | |
20 #ifdef DH768 | |
21 { | |
22 96, | |
23 "DH-768", | |
24 "4", | |
25 "F///////////////////////////////////////////////////////////" | |
26 "////////////////////////////////////////////////////////////" | |
27 "//////m3wvV" | |
28 }, | |
29 #endif | |
30 #ifdef DH1024 | |
31 { | |
32 128, | |
33 "DH-1024", | |
34 "4", | |
35 "F///////////////////////////////////////////////////////////" | |
36 "////////////////////////////////////////////////////////////" | |
37 "////////////////////////////////////////////////m3C47" | |
38 }, | |
39 #endif | |
40 #ifdef DH1280 | |
41 { | |
42 160, | |
43 "DH-1280", | |
44 "4", | |
45 "F///////////////////////////////////////////////////////////" | |
46 "////////////////////////////////////////////////////////////" | |
47 "////////////////////////////////////////////////////////////" | |
48 "//////////////////////////////m4kSN" | |
49 }, | |
50 #endif | |
51 #ifdef DH1536 | |
52 { | |
53 192, | |
54 "DH-1536", | |
55 "4", | |
56 "F///////////////////////////////////////////////////////////" | |
57 "////////////////////////////////////////////////////////////" | |
58 "////////////////////////////////////////////////////////////" | |
59 "////////////////////////////////////////////////////////////" | |
60 "////////////m5uqd" | |
61 }, | |
62 #endif | |
63 #ifdef DH1792 | |
64 { | |
65 224, | |
66 "DH-1792", | |
67 "4", | |
68 "F///////////////////////////////////////////////////////////" | |
69 "////////////////////////////////////////////////////////////" | |
70 "////////////////////////////////////////////////////////////" | |
71 "////////////////////////////////////////////////////////////" | |
72 "//////////////////////////////////////////////////////mT/sd" | |
73 }, | |
74 #endif | |
75 #ifdef DH2048 | |
76 { | |
77 256, | |
78 "DH-2048", | |
79 "4", | |
80 "3///////////////////////////////////////////////////////////" | |
81 "////////////////////////////////////////////////////////////" | |
82 "////////////////////////////////////////////////////////////" | |
83 "////////////////////////////////////////////////////////////" | |
84 "////////////////////////////////////////////////////////////" | |
85 "/////////////////////////////////////////m8MPh" | |
86 }, | |
87 #endif | |
88 #ifdef DH2560 | |
89 { | |
90 320, | |
91 "DH-2560", | |
92 "4", | |
93 "3///////////////////////////////////////////////////////////" | |
94 "////////////////////////////////////////////////////////////" | |
95 "////////////////////////////////////////////////////////////" | |
96 "////////////////////////////////////////////////////////////" | |
97 "////////////////////////////////////////////////////////////" | |
98 "////////////////////////////////////////////////////////////" | |
99 "////////////////////////////////////////////////////////////" | |
100 "/////mKFpF" | |
101 }, | |
102 #endif | |
103 #ifdef DH3072 | |
104 { | |
105 384, | |
106 "DH-3072", | |
107 "4", | |
108 "3///////////////////////////////////////////////////////////" | |
109 "////////////////////////////////////////////////////////////" | |
110 "////////////////////////////////////////////////////////////" | |
111 "////////////////////////////////////////////////////////////" | |
112 "////////////////////////////////////////////////////////////" | |
113 "////////////////////////////////////////////////////////////" | |
114 "////////////////////////////////////////////////////////////" | |
115 "////////////////////////////////////////////////////////////" | |
116 "/////////////////////////////m32nN" | |
117 }, | |
118 #endif | |
119 #ifdef DH4096 | |
120 { | |
121 512, | |
122 "DH-4096", | |
123 "4", | |
124 "////////////////////////////////////////////////////////////" | |
125 "////////////////////////////////////////////////////////////" | |
126 "////////////////////////////////////////////////////////////" | |
127 "////////////////////////////////////////////////////////////" | |
128 "////////////////////////////////////////////////////////////" | |
129 "////////////////////////////////////////////////////////////" | |
130 "////////////////////////////////////////////////////////////" | |
131 "////////////////////////////////////////////////////////////" | |
132 "////////////////////////////////////////////////////////////" | |
133 "////////////////////////////////////////////////////////////" | |
134 "////////////////////////////////////////////////////////////" | |
135 "/////////////////////m8pOF" | |
136 }, | |
137 #endif | |
138 { | |
139 0, | |
140 NULL, | |
141 NULL, | |
142 NULL | |
143 } | |
144 }; | |
145 | |
146 static int is_valid_idx(int n) | |
147 { | |
148 int x; | |
149 | |
150 for (x = 0; sets[x].size; x++); | |
151 if ((n < 0) || (n >= x)) { | |
152 return 0; | |
153 } | |
154 return 1; | |
155 } | |
156 | |
157 int dh_test(void) | |
158 { | |
159 mp_int p, g, tmp; | |
160 int x, err, primality; | |
161 | |
162 if ((err = mp_init_multi(&p, &g, &tmp, NULL)) != MP_OKAY) { goto error; } | |
163 | |
164 for (x = 0; sets[x].size != 0; x++) { | |
165 #if 0 | |
166 printf("dh_test():testing size %d-bits\n", sets[x].size * 8); | |
167 #endif | |
168 if ((err = mp_read_radix(&g,(char *)sets[x].base, 64)) != MP_OKAY) { goto error; } | |
169 if ((err = mp_read_radix(&p,(char *)sets[x].prime, 64)) != MP_OKAY) { goto error; } | |
170 | |
171 /* ensure p is prime */ | |
172 if ((err = is_prime(&p, &primality)) != CRYPT_OK) { goto done; } | |
173 if (primality == 0) { | |
174 err = CRYPT_FAIL_TESTVECTOR; | |
175 goto done; | |
176 } | |
177 | |
178 if ((err = mp_sub_d(&p, 1, &tmp)) != MP_OKAY) { goto error; } | |
179 if ((err = mp_div_2(&tmp, &tmp)) != MP_OKAY) { goto error; } | |
180 | |
181 /* ensure (p-1)/2 is prime */ | |
182 if ((err = is_prime(&tmp, &primality)) != CRYPT_OK) { goto done; } | |
183 if (primality == 0) { | |
184 err = CRYPT_FAIL_TESTVECTOR; | |
185 goto done; | |
186 } | |
187 | |
188 /* now see if g^((p-1)/2) mod p is in fact 1 */ | |
189 if ((err = mp_exptmod(&g, &tmp, &p, &tmp)) != MP_OKAY) { goto error; } | |
190 if (mp_cmp_d(&tmp, 1)) { | |
191 err = CRYPT_FAIL_TESTVECTOR; | |
192 goto done; | |
193 } | |
194 } | |
195 err = CRYPT_OK; | |
196 goto done; | |
197 error: | |
198 err = mpi_to_ltc_error(err); | |
199 done: | |
200 mp_clear_multi(&tmp, &g, &p, NULL); | |
201 return err; | |
202 } | |
203 | |
204 void dh_sizes(int *low, int *high) | |
205 { | |
206 int x; | |
207 _ARGCHK(low != NULL); | |
208 _ARGCHK(high != NULL); | |
209 *low = INT_MAX; | |
210 *high = 0; | |
211 for (x = 0; sets[x].size != 0; x++) { | |
212 if (*low > sets[x].size) *low = sets[x].size; | |
213 if (*high < sets[x].size) *high = sets[x].size; | |
214 } | |
215 } | |
216 | |
217 int dh_get_size(dh_key *key) | |
218 { | |
219 _ARGCHK(key != NULL); | |
220 if (is_valid_idx(key->idx) == 1) { | |
221 return sets[key->idx].size; | |
222 } else { | |
223 return INT_MAX; /* large value that would cause dh_make_key() to fail */ | |
224 } | |
225 } | |
226 | |
227 int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key) | |
228 { | |
229 unsigned char buf[512]; | |
230 unsigned long x; | |
231 mp_int p, g; | |
232 int err; | |
233 | |
234 _ARGCHK(key != NULL); | |
235 | |
236 /* good prng? */ | |
237 if ((err = prng_is_valid(wprng)) != CRYPT_OK) { | |
238 return err; | |
239 } | |
240 | |
241 /* find key size */ | |
242 for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++); | |
243 #ifdef FAST_PK | |
244 keysize = MIN(sets[x].size, 32); | |
245 #else | |
246 keysize = sets[x].size; | |
247 #endif | |
248 | |
249 if (sets[x].size == 0) { | |
250 return CRYPT_INVALID_KEYSIZE; | |
251 } | |
252 key->idx = x; | |
253 | |
254 /* make up random string */ | |
255 if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) { | |
256 return CRYPT_ERROR_READPRNG; | |
257 } | |
258 | |
259 /* init parameters */ | |
260 if ((err = mp_init_multi(&g, &p, &key->x, &key->y, NULL)) != MP_OKAY) { | |
261 return mpi_to_ltc_error(err); | |
262 } | |
263 if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; } | |
264 if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; } | |
265 | |
266 /* load the x value */ | |
267 if ((err = mp_read_unsigned_bin(&key->x, buf, keysize)) != MP_OKAY) { goto error; } | |
268 if ((err = mp_exptmod(&g, &key->x, &p, &key->y)) != MP_OKAY) { goto error; } | |
269 key->type = PK_PRIVATE; | |
270 | |
271 if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; } | |
272 if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; } | |
273 | |
274 /* free up ram */ | |
275 err = CRYPT_OK; | |
276 goto done; | |
277 error: | |
278 err = mpi_to_ltc_error(err); | |
279 mp_clear_multi(&key->x, &key->y, NULL); | |
280 done: | |
281 mp_clear_multi(&p, &g, NULL); | |
282 zeromem(buf, sizeof(buf)); | |
283 return err; | |
284 } | |
285 | |
286 void dh_free(dh_key *key) | |
287 { | |
288 _ARGCHK(key != NULL); | |
289 mp_clear_multi(&key->x, &key->y, NULL); | |
290 } | |
291 | |
292 int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key) | |
293 { | |
294 unsigned long y, z; | |
295 int err; | |
296 | |
297 _ARGCHK(out != NULL); | |
298 _ARGCHK(outlen != NULL); | |
299 _ARGCHK(key != NULL); | |
300 | |
301 /* can we store the static header? */ | |
302 if (*outlen < (PACKET_SIZE + 2)) { | |
303 return CRYPT_BUFFER_OVERFLOW; | |
304 } | |
305 | |
306 if (type == PK_PRIVATE && key->type != PK_PRIVATE) { | |
307 return CRYPT_PK_NOT_PRIVATE; | |
308 } | |
309 | |
310 /* header */ | |
311 y = PACKET_SIZE; | |
312 | |
313 /* header */ | |
314 out[y++] = type; | |
315 out[y++] = (unsigned char)(sets[key->idx].size / 8); | |
316 | |
317 /* export y */ | |
318 OUTPUT_BIGNUM(&key->y, out, y, z); | |
319 | |
320 if (type == PK_PRIVATE) { | |
321 /* export x */ | |
322 OUTPUT_BIGNUM(&key->x, out, y, z); | |
323 } | |
324 | |
325 /* store header */ | |
326 packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_KEY); | |
327 | |
328 /* store len */ | |
329 *outlen = y; | |
330 return CRYPT_OK; | |
331 } | |
332 | |
333 int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) | |
334 { | |
335 unsigned long x, y, s; | |
336 int err; | |
337 | |
338 _ARGCHK(in != NULL); | |
339 _ARGCHK(key != NULL); | |
340 | |
341 /* make sure valid length */ | |
342 if ((2+PACKET_SIZE) > inlen) { | |
343 return CRYPT_INVALID_PACKET; | |
344 } | |
345 | |
346 /* check type byte */ | |
347 if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) { | |
348 return err; | |
349 } | |
350 | |
351 /* init */ | |
352 if ((err = mp_init_multi(&key->x, &key->y, NULL)) != MP_OKAY) { | |
353 return mpi_to_ltc_error(err); | |
354 } | |
355 | |
356 /* advance past packet header */ | |
357 y = PACKET_SIZE; | |
358 | |
359 /* key type, e.g. private, public */ | |
360 key->type = (int)in[y++]; | |
361 | |
362 /* key size in bytes */ | |
363 s = (unsigned long)in[y++] * 8; | |
364 | |
365 for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++); | |
366 if (sets[x].size == 0) { | |
367 err = CRYPT_INVALID_KEYSIZE; | |
368 goto error; | |
369 } | |
370 key->idx = (int)x; | |
371 | |
372 /* type check both values */ | |
373 if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) { | |
374 err = CRYPT_PK_TYPE_MISMATCH; | |
375 goto error; | |
376 } | |
377 | |
378 /* is the key idx valid? */ | |
379 if (is_valid_idx(key->idx) != 1) { | |
380 err = CRYPT_PK_TYPE_MISMATCH; | |
381 goto error; | |
382 } | |
383 | |
384 /* load public value g^x mod p*/ | |
385 INPUT_BIGNUM(&key->y, in, x, y, inlen); | |
386 | |
387 if (key->type == PK_PRIVATE) { | |
388 INPUT_BIGNUM(&key->x, in, x, y, inlen); | |
389 } | |
390 | |
391 /* eliminate private key if public */ | |
392 if (key->type == PK_PUBLIC) { | |
393 mp_clear(&key->x); | |
394 } | |
395 | |
396 return CRYPT_OK; | |
397 error: | |
398 mp_clear_multi(&key->y, &key->x, NULL); | |
399 return err; | |
400 } | |
401 | |
402 int dh_shared_secret(dh_key *private_key, dh_key *public_key, | |
403 unsigned char *out, unsigned long *outlen) | |
404 { | |
405 mp_int tmp, p; | |
406 unsigned long x; | |
407 int err; | |
408 | |
409 _ARGCHK(private_key != NULL); | |
410 _ARGCHK(public_key != NULL); | |
411 _ARGCHK(out != NULL); | |
412 _ARGCHK(outlen != NULL); | |
413 | |
414 /* types valid? */ | |
415 if (private_key->type != PK_PRIVATE) { | |
416 return CRYPT_PK_NOT_PRIVATE; | |
417 } | |
418 | |
419 /* same idx? */ | |
420 if (private_key->idx != public_key->idx) { | |
421 return CRYPT_PK_TYPE_MISMATCH; | |
422 } | |
423 | |
424 /* compute y^x mod p */ | |
425 if ((err = mp_init_multi(&tmp, &p, NULL)) != MP_OKAY) { | |
426 return mpi_to_ltc_error(err); | |
427 } | |
428 | |
429 if ((err = mp_read_radix(&p, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; } | |
430 if ((err = mp_exptmod(&public_key->y, &private_key->x, &p, &tmp)) != MP_OKAY) { goto error; } | |
431 | |
432 /* enough space for output? */ | |
433 x = (unsigned long)mp_unsigned_bin_size(&tmp); | |
434 if (*outlen < x) { | |
435 err = CRYPT_BUFFER_OVERFLOW; | |
436 goto done; | |
437 } | |
438 if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) { goto error; } | |
439 *outlen = x; | |
440 err = CRYPT_OK; | |
441 goto done; | |
442 error: | |
443 err = mpi_to_ltc_error(err); | |
444 done: | |
445 mp_clear_multi(&p, &tmp, NULL); | |
446 return err; | |
447 } | |
448 | |
449 #include "dh_sys.c" | |
450 | |
451 #endif | |
452 |