1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003 X-Way Rights BV
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19
20 /*!\file dldp.c
21 * \brief Discrete Logarithm domain parameters.
22 * \author Bob Deblier <bob.deblier@telenet.be>
23 * \ingroup DL_m
24 */
25
26 #define BEECRYPT_DLL_EXPORT
27
28 #if HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include "beecrypt/dldp.h"
33 #include "beecrypt/mp.h"
34 #include "beecrypt/mpprime.h"
35
36 /*!\addtogroup DL_m
37 * \{
38 */
39 static int dldp_pgoqGenerator_w(dldp_p*, randomGeneratorContext*, mpw*);
40 static int dldp_pgonGenerator_w(dldp_p*, randomGeneratorContext*, mpw*);
41
dldp_pPrivate(const dldp_p * dp,randomGeneratorContext * rgc,mpnumber * x)42 int dldp_pPrivate(const dldp_p* dp, randomGeneratorContext* rgc, mpnumber* x)
43 {
44 /*
45 * Note: the private key is randomly selected to be smaller than q
46 *
47 * This is the variant of Diffie-Hellman as described in IEEE P1363
48 */
49
50 mpbnrnd(&dp->q, rgc, x);
51
52 return 0;
53 }
54
dldp_pPrivate_s(const dldp_p * dp,randomGeneratorContext * rgc,mpnumber * x,size_t xbits)55 int dldp_pPrivate_s(const dldp_p* dp, randomGeneratorContext* rgc, mpnumber* x, size_t xbits)
56 {
57 /*
58 * Note: the private key is randomly selected smaller than q with xbits < mpbits(q)
59 *
60 */
61
62 mpbnrnd(&dp->q, rgc, x);
63 mpntrbits(x, xbits);
64
65 return 0;
66 }
67
dldp_pPublic(const dldp_p * dp,const mpnumber * x,mpnumber * y)68 int dldp_pPublic(const dldp_p* dp, const mpnumber* x, mpnumber* y)
69 {
70 /*
71 * Public key y is computed as g^x mod p
72 */
73
74 mpbnpowmod(&dp->p, &dp->g, x, y);
75
76 return 0;
77 }
78
dldp_pPair(const dldp_p * dp,randomGeneratorContext * rgc,mpnumber * x,mpnumber * y)79 int dldp_pPair(const dldp_p* dp, randomGeneratorContext* rgc, mpnumber* x, mpnumber* y)
80 {
81 /*
82 * Combination of the two previous functions
83 */
84
85 mpbnrnd(&dp->q, rgc, x);
86 mpbnpowmod(&dp->p, &dp->g, x, y);
87
88 return 0;
89 }
90
dldp_pPair_s(const dldp_p * dp,randomGeneratorContext * rgc,mpnumber * x,mpnumber * y,size_t xbits)91 int dldp_pPair_s(const dldp_p* dp, randomGeneratorContext* rgc, mpnumber* x, mpnumber* y, size_t xbits)
92 {
93 mpbnrnd(&dp->q, rgc, x);
94 mpntrbits(x, xbits);
95 mpbnpowmod(&dp->p, &dp->g, x, y);
96
97 return 0;
98 }
99
dldp_pEqual(const dldp_p * a,const dldp_p * b)100 int dldp_pEqual(const dldp_p* a, const dldp_p* b)
101 {
102 return mpeqx(a->p.size, a->p.modl, b->p.size, b->p.modl) &&
103 mpeqx(a->q.size, a->q.modl, b->q.size, b->q.modl) &&
104 mpeqx(a->g.size, a->g.data, b->g.size, b->g.data);
105 }
106
107 /*
108 * needs to make workspace of 8*size+2
109 */
dldp_pValidate(const dldp_p * dp,randomGeneratorContext * rgc)110 int dldp_pValidate(const dldp_p* dp, randomGeneratorContext* rgc)
111 {
112 register size_t size = dp->p.size;
113
114 register mpw* temp = (mpw*) malloc((8*size+2) * sizeof(mpw));
115
116 if (temp)
117 {
118 /* check that p > 2 and p odd, then run miller-rabin test with t 50 */
119 if (mpeven(dp->p.size, dp->p.modl))
120 {
121 free(temp);
122 return 0;
123 }
124
125 if (mppmilrab_w(&dp->p, rgc, 50, temp) == 0)
126 {
127 free(temp);
128 return 0;
129 }
130
131 /* check that q > 2 and q odd, then run miller-rabin test with t 50 */
132 if (mpeven(dp->q.size, dp->q.modl))
133 {
134 free(temp);
135 return 0;
136 }
137
138 if (mppmilrab_w(&dp->q, rgc, 50, temp) == 0)
139 {
140 free(temp);
141 return 0;
142 }
143
144 free(temp);
145
146 /* check that 1 < g < p */
147 if (mpleone(dp->g.size, dp->g.data))
148 return 0;
149
150 if (mpgex(dp->g.size, dp->g.data, dp->p.size, dp->p.modl))
151 return 0;
152
153 return 1;
154 }
155 return -1;
156 }
157
dldp_pInit(dldp_p * dp)158 int dldp_pInit(dldp_p* dp)
159 {
160 mpbzero(&dp->p);
161 mpbzero(&dp->q);
162 mpnzero(&dp->g);
163 mpnzero(&dp->r);
164 mpbzero(&dp->n);
165
166 return 0;
167 }
168
dldp_pFree(dldp_p * dp)169 int dldp_pFree(dldp_p* dp)
170 {
171 mpbfree(&dp->p);
172 mpbfree(&dp->q);
173 mpnfree(&dp->g);
174 mpnfree(&dp->r);
175 mpbfree(&dp->n);
176
177 return 0;
178 }
179
dldp_pCopy(dldp_p * dst,const dldp_p * src)180 int dldp_pCopy(dldp_p* dst, const dldp_p* src)
181 {
182 mpbcopy(&dst->p, &src->p);
183 mpbcopy(&dst->q, &src->q);
184 mpncopy(&dst->r, &src->r);
185 mpncopy(&dst->g, &src->g);
186 mpbcopy(&dst->n, &src->n);
187
188 return 0;
189 }
190
dldp_pgoqMake(dldp_p * dp,randomGeneratorContext * rgc,size_t pbits,size_t qbits,int cofactor)191 int dldp_pgoqMake(dldp_p* dp, randomGeneratorContext* rgc, size_t pbits, size_t qbits, int cofactor)
192 {
193 /*
194 * Generate parameters as described by IEEE P1363, A.16.1
195 */
196 register size_t psize = MP_BITS_TO_WORDS(pbits + MP_WBITS - 1);
197 register mpw* temp = (mpw*) malloc((8*psize+2) * sizeof(mpw));
198
199 if (temp)
200 {
201 /* first generate q */
202 mpprnd_w(&dp->q, rgc, qbits, mpptrials(qbits), (const mpnumber*) 0, temp);
203
204 /* generate p with the appropriate congruences */
205 mpprndconone_w(&dp->p, rgc, pbits, mpptrials(pbits), &dp->q, (const mpnumber*) 0, &dp->r, cofactor, temp);
206
207 /* clear n */
208 mpbzero(&dp->n);
209
210 /* clear g */
211 mpnzero(&dp->g);
212
213 dldp_pgoqGenerator_w(dp, rgc, temp);
214
215 free(temp);
216
217 return 0;
218 }
219
220 return -1;
221 }
222
dldp_pgoqMakeSafe(dldp_p * dp,randomGeneratorContext * rgc,size_t bits)223 int dldp_pgoqMakeSafe(dldp_p* dp, randomGeneratorContext* rgc, size_t bits)
224 {
225 /*
226 * Generate parameters with a safe prime; p = 2q+1 i.e. r=2
227 *
228 */
229
230 register size_t size = MP_BITS_TO_WORDS(bits + MP_WBITS - 1);
231 register mpw* temp = (mpw*) malloc((8*size+2) * sizeof(mpw));
232
233 if (temp)
234 {
235 /* generate p */
236 mpprndsafe_w(&dp->p, rgc, bits, mpptrials(bits), temp);
237
238 /* set q */
239 mpcopy(size, temp, dp->p.modl);
240 mpdivtwo(size, temp);
241 mpbset(&dp->q, size, temp);
242
243 /* set r = 2 */
244 mpnsetw(&dp->r, 2);
245
246 /* clear n */
247 mpbzero(&dp->n);
248
249 dldp_pgoqGenerator_w(dp, rgc, temp);
250
251 free(temp);
252
253 return 0;
254 }
255 return -1;
256 }
257
dldp_pgoqGenerator_w(dldp_p * dp,randomGeneratorContext * rgc,mpw * wksp)258 int dldp_pgoqGenerator_w(dldp_p* dp, randomGeneratorContext* rgc, mpw* wksp)
259 {
260 /*
261 * Randomly determine a generator over the subgroup with order q
262 */
263
264 register size_t size = dp->p.size;
265
266 mpnfree(&dp->g);
267 mpnsize(&dp->g, size);
268
269 while (1)
270 {
271 /* get a random value h (stored into g) */
272 mpbrnd_w(&dp->p, rgc, dp->g.data, wksp);
273
274 /* first compute h^r mod p (stored in g) */
275 mpbpowmod_w(&dp->p, size, dp->g.data, dp->r.size, dp->r.data, dp->g.data, wksp);
276
277 if (mpisone(size, dp->g.data))
278 continue;
279
280 return 0;
281 }
282 return -1;
283 }
284
dldp_pgoqGenerator(dldp_p * dp,randomGeneratorContext * rgc)285 int dldp_pgoqGenerator(dldp_p* dp, randomGeneratorContext* rgc)
286 {
287 register size_t size = dp->p.size;
288 register mpw* temp = (mpw*) malloc((4*size+2)*sizeof(mpw));
289
290 if (temp)
291 {
292 dldp_pgoqGenerator_w(dp, rgc, temp);
293
294 free(temp);
295
296 return 0;
297 }
298 return -1;
299 }
300
dldp_pgoqValidate(const dldp_p * dp,randomGeneratorContext * rgc,int cofactor)301 int dldp_pgoqValidate(const dldp_p* dp, randomGeneratorContext* rgc, int cofactor)
302 {
303 register int rc = dldp_pValidate(dp, rgc);
304
305 if (rc <= 0)
306 return rc;
307
308 /* check that g^q mod p = 1 */
309
310 /* if r != 0, then check that qr+1 = p */
311
312 /* if cofactor, then check that q does not divide (r) */
313
314 return 1;
315 }
316
dldp_pgonMake(dldp_p * dp,randomGeneratorContext * rgc,size_t pbits,size_t qbits)317 int dldp_pgonMake(dldp_p* dp, randomGeneratorContext* rgc, size_t pbits, size_t qbits)
318 {
319 /*
320 * Generate parameters with a prime p such that p = qr+1, with q prime, and r = 2s, with s prime
321 */
322
323 register size_t psize = MP_BITS_TO_WORDS(pbits + MP_WBITS - 1);
324 register mpw* temp = (mpw*) malloc((8*psize+2) * sizeof(mpw));
325
326 if (temp)
327 {
328 /* generate q */
329 mpprnd_w(&dp->q, rgc, qbits, mpptrials(qbits), (const mpnumber*) 0, temp);
330
331 /* generate p with the appropriate congruences */
332 mpprndconone_w(&dp->p, rgc, pbits, mpptrials(pbits), &dp->q, (const mpnumber*) 0, &dp->r, 2, temp);
333
334 /* set n */
335 mpbsubone(&dp->p, temp);
336 mpbset(&dp->n, psize, temp);
337
338 dldp_pgonGenerator_w(dp, rgc, temp);
339
340 free(temp);
341
342 return 0;
343 }
344 return -1;
345 }
346
dldp_pgonMakeSafe(dldp_p * dp,randomGeneratorContext * rgc,size_t pbits)347 int dldp_pgonMakeSafe(dldp_p* dp, randomGeneratorContext* rgc, size_t pbits)
348 {
349 /*
350 * Generate parameters with a safe prime; i.e. p = 2q+1, where q is prime
351 */
352
353 register size_t psize = MP_BITS_TO_WORDS(pbits + MP_WBITS - 1);
354 register mpw* temp = (mpw*) malloc((8*psize+2) * sizeof(mpw));
355
356 if (temp)
357 {
358 /* generate safe p */
359 mpprndsafe_w(&dp->p, rgc, pbits, mpptrials(pbits), temp);
360
361 /* set n */
362 mpbsubone(&dp->p, temp);
363 mpbset(&dp->n, psize, temp);
364
365 /* set q */
366 mpdivtwo(psize, temp);
367 mpbset(&dp->q, psize, temp);
368
369 /* set r = 2 */
370 mpnsetw(&dp->r, 2);
371
372 dldp_pgonGenerator_w(dp, rgc, temp);
373
374 free(temp);
375
376 return 0;
377 }
378 return -1;
379 }
380
dldp_pgonGenerator_w(dldp_p * dp,randomGeneratorContext * rgc,mpw * wksp)381 int dldp_pgonGenerator_w(dldp_p* dp, randomGeneratorContext* rgc, mpw* wksp)
382 {
383 register size_t size = dp->p.size;
384
385 mpnfree(&dp->g);
386 mpnsize(&dp->g, size);
387
388 while (1)
389 {
390 mpbrnd_w(&dp->p, rgc, dp->g.data, wksp);
391
392 if (mpistwo(dp->r.size, dp->r.data))
393 {
394 /*
395 * A little math here: the only element in the group which has order 2 is (p-1);
396 * the two group elements raised to power two which result in 1 (mod p) are thus (p-1) and 1
397 *
398 * mpbrnd_w doesn't return 1 or (p-1), so the test where g^2 mod p = 1 can be safely skipped
399 */
400
401 /* check g^q mod p*/
402 mpbpowmod_w(&dp->p, size, dp->g.data, dp->q.size, dp->q.modl, wksp, wksp+size);
403 if (mpisone(size, wksp))
404 continue;
405 }
406 else
407 {
408 /* we can either compute g^r, g^2q and g^(qr/2) or
409 * we first compute s = r/2, and then compute g^2s, g^2q and g^qs
410 *
411 * hence we first compute t = g^s
412 * then compute t^2 mod p, and test if one
413 * then compute t^q mod p, and test if one
414 * then compute (g^q mod p)^2 mod p, and test if one
415 */
416
417 /* compute s = r/2 */
418 mpsetx(size, wksp, dp->r.size, dp->r.data);
419 mpdivtwo(size, wksp);
420
421 /* compute t = g^s mod p */
422 mpbpowmod_w(&dp->p, size, dp->g.data, size, wksp, wksp+size, wksp+2*size);
423 /* compute t^2 mod p = g^2s mod p = g^r mod p*/
424 mpbsqrmod_w(&dp->p, size, wksp+size, wksp+size, wksp+2*size);
425 if (mpisone(size, wksp+size))
426 continue;
427
428 /* compute t^q mod p = g^qs mod p */
429 mpbpowmod_w(&dp->p, size, wksp, dp->q.size, dp->q.modl, wksp+size, wksp+2*size);
430 if (mpisone(size, wksp+size))
431 continue;
432
433 /* compute g^2q mod p */
434 mpbpowmod_w(&dp->p, size, dp->g.data, dp->q.size, dp->q.modl, wksp, wksp+size);
435 mpbsqrmod_w(&dp->p, size, wksp, wksp+size, wksp+2*size);
436 if (mpisone(size, wksp+size))
437 continue;
438 }
439
440 return 0;
441 }
442
443 return -1;
444 }
445
dldp_pgonGenerator(dldp_p * dp,randomGeneratorContext * rgc)446 int dldp_pgonGenerator(dldp_p* dp, randomGeneratorContext* rgc)
447 {
448 register size_t psize = dp->p.size;
449 register mpw* temp = (mpw*) malloc((8*psize+2) * sizeof(mpw));
450
451 if (temp)
452 {
453 dldp_pgonGenerator_w(dp, rgc, temp);
454
455 free(temp);
456
457 return 0;
458 }
459 return -1;
460 }
461
dldp_pgonValidate(const dldp_p * dp,randomGeneratorContext * rgc)462 int dldp_pgonValidate(const dldp_p* dp, randomGeneratorContext* rgc)
463 {
464 return dldp_pValidate((const dldp_p*) dp, rgc);
465 }
466
467 /*!\}
468 */
469