xref: /freebsd/crypto/libecc/src/examples/basic/fp_square_residue.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans  *  Copyright (C) 2017 - This file is part of libecc project
3*f0865ec9SKyle Evans  *
4*f0865ec9SKyle Evans  *  Authors:
5*f0865ec9SKyle Evans  *      Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans  *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans  *      Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8*f0865ec9SKyle Evans  *
9*f0865ec9SKyle Evans  *  Contributors:
10*f0865ec9SKyle Evans  *      Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11*f0865ec9SKyle Evans  *      Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12*f0865ec9SKyle Evans  *
13*f0865ec9SKyle Evans  *  This software is licensed under a dual BSD and GPL v2 license.
14*f0865ec9SKyle Evans  *  See LICENSE file at the root folder of the project.
15*f0865ec9SKyle Evans  */
16*f0865ec9SKyle Evans #include <libecc/libarith.h>
17*f0865ec9SKyle Evans 
18*f0865ec9SKyle Evans /* Declare our Miller-Rabin test implemented
19*f0865ec9SKyle Evans  * in another module.
20*f0865ec9SKyle Evans  */
21*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET int miller_rabin(nn_src_t n, const unsigned int t, int *check);
22*f0865ec9SKyle Evans 
23*f0865ec9SKyle Evans #ifdef FP_EXAMPLE
main(int argc,char * argv[])24*f0865ec9SKyle Evans int main(int argc, char *argv[])
25*f0865ec9SKyle Evans {
26*f0865ec9SKyle Evans 	nn p;
27*f0865ec9SKyle Evans 	fp x, x_sqrt1, x_sqrt2;
28*f0865ec9SKyle Evans 	fp_ctx ctx;
29*f0865ec9SKyle Evans 	int ret, ret_sqr, isone, check, cmp;
30*f0865ec9SKyle Evans 	x.magic = x_sqrt1.magic = x_sqrt2.magic = WORD(0);
31*f0865ec9SKyle Evans 	ctx.magic = WORD(0);
32*f0865ec9SKyle Evans 	FORCE_USED_VAR(argc);
33*f0865ec9SKyle Evans  	FORCE_USED_VAR(argv);
34*f0865ec9SKyle Evans 
35*f0865ec9SKyle Evans 	while (1) {
36*f0865ec9SKyle Evans 		/* Get a random prime p of maximum 521 bits */
37*f0865ec9SKyle Evans 		ret = nn_init(&p, 0); EG(ret, err);
38*f0865ec9SKyle Evans 		while (1) {
39*f0865ec9SKyle Evans 			/* x = random with max size ~= (NN_MAX_BIT_LEN / 3) bytes.
40*f0865ec9SKyle Evans 			 * This size limit is infered from the NN arithmetic primitives
41*f0865ec9SKyle Evans 			 * maximum working size. See nn.h for more information about this.
42*f0865ec9SKyle Evans 			 */
43*f0865ec9SKyle Evans 			ret = nn_get_random_maxlen
44*f0865ec9SKyle Evans 			    (&p, (u16)((NN_MAX_BIT_LEN / 3) / 8)); EG(ret, err);
45*f0865ec9SKyle Evans 
46*f0865ec9SKyle Evans 			/* p = 1 is a marginal prime we don't want to deal with */
47*f0865ec9SKyle Evans 			ret = nn_isone(&p, &isone); EG(ret, err);
48*f0865ec9SKyle Evans 			if(isone){
49*f0865ec9SKyle Evans 				continue;
50*f0865ec9SKyle Evans 			}
51*f0865ec9SKyle Evans 
52*f0865ec9SKyle Evans 			/* Check primality of p, and choose it if it is prime */
53*f0865ec9SKyle Evans 			ret = miller_rabin(&p, 100, &check); EG(ret, err);
54*f0865ec9SKyle Evans 			if(check == 1){
55*f0865ec9SKyle Evans 				break;
56*f0865ec9SKyle Evans 			}
57*f0865ec9SKyle Evans 		}
58*f0865ec9SKyle Evans 		nn_print("Prime p", &p);
59*f0865ec9SKyle Evans 		/* Initialize our Fp context from p */
60*f0865ec9SKyle Evans 		ret = fp_ctx_init_from_p(&ctx, &p); EG(ret, err);
61*f0865ec9SKyle Evans 		/* Initialize x and its square roots */
62*f0865ec9SKyle Evans 		ret = fp_init(&x, &ctx); EG(ret, err);
63*f0865ec9SKyle Evans 		ret = fp_init(&x_sqrt1, &ctx); EG(ret, err);
64*f0865ec9SKyle Evans 		ret = fp_init(&x_sqrt2, &ctx); EG(ret, err);
65*f0865ec9SKyle Evans 
66*f0865ec9SKyle Evans 		/* Get a random value in Fp */
67*f0865ec9SKyle Evans 		ret = fp_get_random(&x, &ctx); EG(ret, err);
68*f0865ec9SKyle Evans 		/* Compute its square in Fp */
69*f0865ec9SKyle Evans 		ext_printf("Random before squaring:\n");
70*f0865ec9SKyle Evans 		fp_print("x", &x);
71*f0865ec9SKyle Evans 		ext_printf("Random after squaring:\n");
72*f0865ec9SKyle Evans 		ret = fp_sqr(&x, &x); EG(ret, err);
73*f0865ec9SKyle Evans 		nn_print("x^2", &(x.fp_val));
74*f0865ec9SKyle Evans 
75*f0865ec9SKyle Evans 		ret_sqr = fp_sqrt(&x_sqrt1, &x_sqrt2, &x);
76*f0865ec9SKyle Evans 
77*f0865ec9SKyle Evans 		if (ret_sqr == 0) {
78*f0865ec9SKyle Evans 			/* Square roots found!, check them! */
79*f0865ec9SKyle Evans 			fp_print("sqrt1", &x_sqrt1);
80*f0865ec9SKyle Evans 			ret = fp_sqr(&x_sqrt1, &x_sqrt1); EG(ret, err);
81*f0865ec9SKyle Evans 			ret = fp_cmp(&x, &x_sqrt1, &cmp); EG(ret, err);
82*f0865ec9SKyle Evans 			if (cmp == 0) {
83*f0865ec9SKyle Evans 				ext_printf("First found square OK!\n");
84*f0865ec9SKyle Evans 			} else {
85*f0865ec9SKyle Evans 				ext_printf("First found square NOK: square "
86*f0865ec9SKyle Evans 					   "is not the expected value ...\n");
87*f0865ec9SKyle Evans 			}
88*f0865ec9SKyle Evans 			fp_print("sqrt2", &x_sqrt2);
89*f0865ec9SKyle Evans 			ret = fp_sqr(&x_sqrt2, &x_sqrt2); EG(ret, err);
90*f0865ec9SKyle Evans 			ret = fp_cmp(&x, &x_sqrt2, &cmp); EG(ret, err);
91*f0865ec9SKyle Evans 			if (cmp == 0) {
92*f0865ec9SKyle Evans 				ext_printf("Second found square OK!\n");
93*f0865ec9SKyle Evans 			} else {
94*f0865ec9SKyle Evans 				ext_printf("Second found square NOK: square "
95*f0865ec9SKyle Evans 					   "is not the expected value ...\n");
96*f0865ec9SKyle Evans 			}
97*f0865ec9SKyle Evans 
98*f0865ec9SKyle Evans 		} else {
99*f0865ec9SKyle Evans 			if (ret_sqr == -1) {
100*f0865ec9SKyle Evans 				/* This should not happen since we have forged our square */
101*f0865ec9SKyle Evans 				ext_printf("Value n has no square over Fp\n");
102*f0865ec9SKyle Evans 				ext_printf("(Note: this error can be due to "
103*f0865ec9SKyle Evans 					   "Miller-Rabin providing a false "
104*f0865ec9SKyle Evans 					   "positive prime ...)\n");
105*f0865ec9SKyle Evans 				ext_printf("(though this should happen with "
106*f0865ec9SKyle Evans 					   "negligible probability))\n");
107*f0865ec9SKyle Evans 				nn_print("Check primality of p =", &p);
108*f0865ec9SKyle Evans 				/* Get out of the main loop */
109*f0865ec9SKyle Evans 				break;
110*f0865ec9SKyle Evans 			} else {
111*f0865ec9SKyle Evans 				/* This should not happen since we have forged our square */
112*f0865ec9SKyle Evans 				ext_printf("Tonelli-Shanks algorithm unkown "
113*f0865ec9SKyle Evans 					   "error ...\n");
114*f0865ec9SKyle Evans 				ext_printf("(Note: this error can be due to "
115*f0865ec9SKyle Evans 					   "Miller-Rabin providing a false "
116*f0865ec9SKyle Evans 					   "positive prime ...)\n");
117*f0865ec9SKyle Evans 				ext_printf("(though this should happen with "
118*f0865ec9SKyle Evans 					   "negligible probability))\n");
119*f0865ec9SKyle Evans 				nn_print("Check primality of p =", &p);
120*f0865ec9SKyle Evans 				/* Get out of the main loop */
121*f0865ec9SKyle Evans 				break;
122*f0865ec9SKyle Evans 			}
123*f0865ec9SKyle Evans 		}
124*f0865ec9SKyle Evans 	}
125*f0865ec9SKyle Evans 
126*f0865ec9SKyle Evans 	return 0;
127*f0865ec9SKyle Evans err:
128*f0865ec9SKyle Evans 	ext_printf("Error: unkown error ...\n");
129*f0865ec9SKyle Evans 	return -1;
130*f0865ec9SKyle Evans }
131*f0865ec9SKyle Evans #endif
132