comparison dh.c @ 3:7faae8f46238 libtomcrypt-orig

Branch renaming
author Matt Johnston <matt@ucc.asn.au>
date Mon, 31 May 2004 18:25:41 +0000
parents
children 5d99163f7e32
comparison
equal deleted inserted replaced
-1:000000000000 3:7faae8f46238
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