1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72: #include <stdio.h>
73: #include <stdlib.h>
74: #ifdef FLAT_INC
75: #include "e_os.h"
76: #else
77: #include "../e_os.h"
78: #endif
79: #include <string.h>
80: #include <time.h>
81:
82:
83: #ifdef OPENSSL_NO_EC
84: int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); return 0; }
85: #else
86:
87:
88: #include <openssl/ec.h>
89: #ifndef OPENSSL_NO_ENGINE
90: #include <openssl/engine.h>
91: #endif
92: #include <openssl/err.h>
93: #include <openssl/obj_mac.h>
94: #include <openssl/objects.h>
95: #include <openssl/rand.h>
96: #include <openssl/bn.h>
97:
98: #if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
99:
100: #pragma warning(disable:4959)
101: #endif
102:
103: #define ABORT do { \
104: fflush(stdout); \
105: fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \
106: ERR_print_errors_fp(stderr); \
107: EXIT(1); \
108: } while (0)
109:
110: void prime_field_tests(void);
111: void char2_field_tests(void);
112: void internal_curve_test(void);
113:
114: #define TIMING_BASE_PT 0
115: #define TIMING_RAND_PT 1
116: #define TIMING_SIMUL 2
117:
118: #if 0
119: static void timings(EC_GROUP *group, int type, BN_CTX *ctx)
120: {
121: clock_t clck;
122: int i, j;
123: BIGNUM *s;
124: BIGNUM *r[10], *r0[10];
125: EC_POINT *P;
126:
127: s = BN_new();
128: if (s == NULL) ABORT;
129:
130: fprintf(stdout, "Timings for %d-bit field, ", EC_GROUP_get_degree(group));
131: if (!EC_GROUP_get_order(group, s, ctx)) ABORT;
132: fprintf(stdout, "%d-bit scalars ", (int)BN_num_bits(s));
133: fflush(stdout);
134:
135: P = EC_POINT_new(group);
136: if (P == NULL) ABORT;
137: EC_POINT_copy(P, EC_GROUP_get0_generator(group));
138:
139: for (i = 0; i < 10; i++)
140: {
141: if ((r[i] = BN_new()) == NULL) ABORT;
142: if (!BN_pseudo_rand(r[i], BN_num_bits(s), 0, 0)) ABORT;
143: if (type != TIMING_BASE_PT)
144: {
145: if ((r0[i] = BN_new()) == NULL) ABORT;
146: if (!BN_pseudo_rand(r0[i], BN_num_bits(s), 0, 0)) ABORT;
147: }
148: }
149:
150: clck = clock();
151: for (i = 0; i < 10; i++)
152: {
153: for (j = 0; j < 10; j++)
154: {
155: if (!EC_POINT_mul(group, P, (type != TIMING_RAND_PT) ? r[i] : NULL,
156: (type != TIMING_BASE_PT) ? P : NULL, (type != TIMING_BASE_PT) ? r0[i] : NULL, ctx)) ABORT;
157: }
158: }
159: clck = clock() - clck;
160:
161: fprintf(stdout, "\n");
162:
163: #ifdef CLOCKS_PER_SEC
164:
165:
166:
167:
168: # define UNIT "s"
169: #else
170:
171:
172: # define UNIT "units"
173: # define CLOCKS_PER_SEC 1
174: #endif
175:
176: if (type == TIMING_BASE_PT) {
177: fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
178: "base point multiplications", (double)clck/CLOCKS_PER_SEC);
179: } else if (type == TIMING_RAND_PT) {
180: fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
181: "random point multiplications", (double)clck/CLOCKS_PER_SEC);
182: } else if (type == TIMING_SIMUL) {
183: fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
184: "s*P+t*Q operations", (double)clck/CLOCKS_PER_SEC);
185: }
186: fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j));
187:
188: EC_POINT_free(P);
189: BN_free(s);
190: for (i = 0; i < 10; i++)
191: {
192: BN_free(r[i]);
193: if (type != TIMING_BASE_PT) BN_free(r0[i]);
194: }
195: }
196: #endif
197:
198: void prime_field_tests()
199: {
200: BN_CTX *ctx = NULL;
201: BIGNUM *p, *a, *b;
202: EC_GROUP *group;
203: EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
204: EC_POINT *P, *Q, *R;
205: BIGNUM *x, *y, *z;
206: unsigned char buf[100];
207: size_t i, len;
208: int k;
209:
210: #if 1
211: ctx = BN_CTX_new();
212: if (!ctx) ABORT;
213: #endif
214:
215: p = BN_new();
216: a = BN_new();
217: b = BN_new();
218: if (!p || !a || !b) ABORT;
219:
220: if (!BN_hex2bn(&p, "17")) ABORT;
221: if (!BN_hex2bn(&a, "1")) ABORT;
222: if (!BN_hex2bn(&b, "1")) ABORT;
223:
224: group = EC_GROUP_new(EC_GFp_mont_method());
225:
226: if (!group) ABORT;
227:
228: if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
229:
230: {
231: EC_GROUP *tmp;
232: tmp = EC_GROUP_new(EC_GROUP_method_of(group));
233: if (!tmp) ABORT;
234: if (!EC_GROUP_copy(tmp, group)) ABORT;
235: EC_GROUP_free(group);
236: group = tmp;
237: }
238:
239: if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) ABORT;
240:
241: fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 = x^3 + a*x + b (mod 0x");
242: BN_print_fp(stdout, p);
243: fprintf(stdout, ")\n a = 0x");
244: BN_print_fp(stdout, a);
245: fprintf(stdout, "\n b = 0x");
246: BN_print_fp(stdout, b);
247: fprintf(stdout, "\n");
248:
249: P = EC_POINT_new(group);
250: Q = EC_POINT_new(group);
251: R = EC_POINT_new(group);
252: if (!P || !Q || !R) ABORT;
253:
254: if (!EC_POINT_set_to_infinity(group, P)) ABORT;
255: if (!EC_POINT_is_at_infinity(group, P)) ABORT;
256:
257: buf[0] = 0;
258: if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
259:
260: if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
261: if (!EC_POINT_is_at_infinity(group, P)) ABORT;
262:
263: x = BN_new();
264: y = BN_new();
265: z = BN_new();
266: if (!x || !y || !z) ABORT;
267:
268: if (!BN_hex2bn(&x, "D")) ABORT;
269: if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT;
270: if (!EC_POINT_is_on_curve(group, Q, ctx))
271: {
272: if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT;
273: fprintf(stderr, "Point is not on curve: x = 0x");
274: BN_print_fp(stderr, x);
275: fprintf(stderr, ", y = 0x");
276: BN_print_fp(stderr, y);
277: fprintf(stderr, "\n");
278: ABORT;
279: }
280:
281: fprintf(stdout, "A cyclic subgroup:\n");
282: k = 100;
283: do
284: {
285: if (k-- == 0) ABORT;
286:
287: if (EC_POINT_is_at_infinity(group, P))
288: fprintf(stdout, " point at infinity\n");
289: else
290: {
291: if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
292:
293: fprintf(stdout, " x = 0x");
294: BN_print_fp(stdout, x);
295: fprintf(stdout, ", y = 0x");
296: BN_print_fp(stdout, y);
297: fprintf(stdout, "\n");
298: }
299:
300: if (!EC_POINT_copy(R, P)) ABORT;
301: if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
302:
303: #if 0
304: {
305: EC_POINT *points[3];
306:
307: points[0] = R;
308: points[1] = Q;
309: points[2] = P;
310: if (!EC_POINTs_make_affine(group, 2, points, ctx)) ABORT;
311: }
312: #endif
313:
314: }
315: while (!EC_POINT_is_at_infinity(group, P));
316:
317: if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
318: if (!EC_POINT_is_at_infinity(group, P)) ABORT;
319:
320: len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
321: if (len == 0) ABORT;
322: if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
323: if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
324: fprintf(stdout, "Generator as octect string, compressed form:\n ");
325: for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
326:
327: len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
328: if (len == 0) ABORT;
329: if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
330: if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
331: fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n ");
332: for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
333:
334: len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
335: if (len == 0) ABORT;
336: if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
337: if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
338: fprintf(stdout, "\nGenerator as octect string, hybrid form:\n ");
339: for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
340:
341: if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
342: fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n X = 0x");
343: BN_print_fp(stdout, x);
344: fprintf(stdout, ", Y = 0x");
345: BN_print_fp(stdout, y);
346: fprintf(stdout, ", Z = 0x");
347: BN_print_fp(stdout, z);
348: fprintf(stdout, "\n");
349:
350: if (!EC_POINT_invert(group, P, ctx)) ABORT;
351: if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
352:
353:
354:
355:
356:
357: if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT;
358: if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
359: if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT;
360: if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT;
361: if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
362:
363: if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT;
364: if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
365: if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
366: if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
367: if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT;
368: if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
369:
370: if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
371: fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x");
372: BN_print_fp(stdout, x);
373: fprintf(stdout, "\n y = 0x");
374: BN_print_fp(stdout, y);
375: fprintf(stdout, "\n");
376:
377: if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
378: if (0 != BN_cmp(y, z)) ABORT;
379:
380: fprintf(stdout, "verify degree ...");
381: if (EC_GROUP_get_degree(group) != 160) ABORT;
382: fprintf(stdout, " ok\n");
383:
384: fprintf(stdout, "verify group order ...");
385: fflush(stdout);
386: if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
387: if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
388: if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
389: fprintf(stdout, ".");
390: fflush(stdout);
391: if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
392: if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
393: if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
394: fprintf(stdout, " ok\n");
395:
396: if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
397: if (!EC_GROUP_copy(P_160, group)) ABORT;
398:
399:
400:
401:
402: if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT;
403: if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
404: if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT;
405: if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT;
406: if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
407:
408: if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT;
409: if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
410: if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
411: if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT;
412: if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
413:
414: if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
415: fprintf(stdout, "\nNIST curve P-192 -- Generator:\n x = 0x");
416: BN_print_fp(stdout, x);
417: fprintf(stdout, "\n y = 0x");
418: BN_print_fp(stdout, y);
419: fprintf(stdout, "\n");
420:
421: if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT;
422: if (0 != BN_cmp(y, z)) ABORT;
423:
424: fprintf(stdout, "verify degree ...");
425: if (EC_GROUP_get_degree(group) != 192) ABORT;
426: fprintf(stdout, " ok\n");
427:
428: fprintf(stdout, "verify group order ...");
429: fflush(stdout);
430: if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
431: if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
432: if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
433: fprintf(stdout, ".");
434: fflush(stdout);
435: #if 0
436: if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
437: #endif
438: if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
439: if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
440: fprintf(stdout, " ok\n");
441:
442: if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
443: if (!EC_GROUP_copy(P_192, group)) ABORT;
444:
445:
446:
447:
448: if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT;
449: if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
450: if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT;
451: if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT;
452: if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
453:
454: if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT;
455: if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
456: if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
457: if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT;
458: if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
459:
460: if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
461: fprintf(stdout, "\nNIST curve P-224 -- Generator:\n x = 0x");
462: BN_print_fp(stdout, x);
463: fprintf(stdout, "\n y = 0x");
464: BN_print_fp(stdout, y);
465: fprintf(stdout, "\n");
466:
467: if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT;
468: if (0 != BN_cmp(y, z)) ABORT;
469:
470: fprintf(stdout, "verify degree ...");
471: if (EC_GROUP_get_degree(group) != 224) ABORT;
472: fprintf(stdout, " ok\n");
473:
474: fprintf(stdout, "verify group order ...");
475: fflush(stdout);
476: if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
477: if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
478: if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
479: fprintf(stdout, ".");
480: fflush(stdout);
481: #if 0
482: if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
483: #endif
484: if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
485: if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
486: fprintf(stdout, " ok\n");
487:
488: if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
489: if (!EC_GROUP_copy(P_224, group)) ABORT;
490:
491:
492:
493:
494: if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
495: if (1 != BN_is_prime_ex(p, BN_prime_checks,