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