PageRenderTime 48ms CodeModel.GetById 12ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/freebl/ecl/tests/ecp_test.c

http://github.com/zpao/v8monkey
C | 460 lines | 362 code | 29 blank | 69 comment | 77 complexity | 0174fcd280e98e5ee1f899b83a697d1d MD5 | raw file
  1/* 
  2 * ***** BEGIN LICENSE BLOCK *****
  3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4 *
  5 * The contents of this file are subject to the Mozilla Public License Version
  6 * 1.1 (the "License"); you may not use this file except in compliance with
  7 * the License. You may obtain a copy of the License at
  8 * http://www.mozilla.org/MPL/
  9 *
 10 * Software distributed under the License is distributed on an "AS IS" basis,
 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 12 * for the specific language governing rights and limitations under the
 13 * License.
 14 *
 15 * The Original Code is the elliptic curve math library for prime field curves.
 16 *
 17 * The Initial Developer of the Original Code is
 18 * Sun Microsystems, Inc.
 19 * Portions created by the Initial Developer are Copyright (C) 2003
 20 * the Initial Developer. All Rights Reserved.
 21 *
 22 * Contributor(s):
 23 *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
 24 *
 25 * Alternatively, the contents of this file may be used under the terms of
 26 * either the GNU General Public License Version 2 or later (the "GPL"), or
 27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 28 * in which case the provisions of the GPL or the LGPL are applicable instead
 29 * of those above. If you wish to allow use of your version of this file only
 30 * under the terms of either the GPL or the LGPL, and not to allow others to
 31 * use your version of this file under the terms of the MPL, indicate your
 32 * decision by deleting the provisions above and replace them with the notice
 33 * and other provisions required by the GPL or the LGPL. If you do not delete
 34 * the provisions above, a recipient may use your version of this file under
 35 * the terms of any one of the MPL, the GPL or the LGPL.
 36 *
 37 * ***** END LICENSE BLOCK ***** */
 38
 39#include "mpi.h"
 40#include "mplogic.h"
 41#include "mpprime.h"
 42#include "ecl.h"
 43#include "ecl-curve.h"
 44#include "ecp.h"
 45#include <stdio.h>
 46#include <strings.h>
 47#include <assert.h>
 48
 49#include <time.h>
 50#include <sys/time.h>
 51#include <sys/resource.h>
 52
 53/* Time k repetitions of operation op. */
 54#define M_TimeOperation(op, k) { \
 55	double dStart, dNow, dUserTime; \
 56	struct rusage ru; \
 57	int i; \
 58	getrusage(RUSAGE_SELF, &ru); \
 59	dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
 60	for (i = 0; i < k; i++) { \
 61		{ op; } \
 62	}; \
 63	getrusage(RUSAGE_SELF, &ru); \
 64	dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
 65	dUserTime = dNow-dStart; \
 66	if (dUserTime) printf("    %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
 67}
 68
 69/* Test curve using generic field arithmetic. */
 70#define ECTEST_GENERIC_GFP(name_c, name) \
 71	printf("Testing %s using generic implementation...\n", name_c); \
 72	params = EC_GetNamedCurveParams(name); \
 73	if (params == NULL) { \
 74			printf("  Error: could not construct params.\n"); \
 75			res = MP_NO; \
 76			goto CLEANUP; \
 77	} \
 78	ECGroup_free(group); \
 79	group = ECGroup_fromHex(params); \
 80	if (group == NULL) { \
 81		printf("  Error: could not construct group.\n"); \
 82		res = MP_NO; \
 83		goto CLEANUP; \
 84	} \
 85	MP_CHECKOK( ectest_curve_GFp(group, ectestPrint, ectestTime, 1) ); \
 86	printf("... okay.\n");
 87
 88/* Test curve using specific field arithmetic. */
 89#define ECTEST_NAMED_GFP(name_c, name) \
 90	printf("Testing %s using specific implementation...\n", name_c); \
 91	ECGroup_free(group); \
 92	group = ECGroup_fromName(name); \
 93	if (group == NULL) { \
 94		printf("  Warning: could not construct group.\n"); \
 95		printf("... failed; continuing with remaining tests.\n"); \
 96	} else { \
 97		MP_CHECKOK( ectest_curve_GFp(group, ectestPrint, ectestTime, 0) ); \
 98		printf("... okay.\n"); \
 99	}
100
101/* Performs basic tests of elliptic curve cryptography over prime fields.
102 * If tests fail, then it prints an error message, aborts, and returns an
103 * error code. Otherwise, returns 0. */
104int
105ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
106				 int generic)
107{
108
109	mp_int one, order_1, gx, gy, rx, ry, n;
110	int size;
111	mp_err res;
112	char s[1000];
113
114	/* initialize values */
115	MP_CHECKOK(mp_init(&one));
116	MP_CHECKOK(mp_init(&order_1));
117	MP_CHECKOK(mp_init(&gx));
118	MP_CHECKOK(mp_init(&gy));
119	MP_CHECKOK(mp_init(&rx));
120	MP_CHECKOK(mp_init(&ry));
121	MP_CHECKOK(mp_init(&n));
122
123	MP_CHECKOK(mp_set_int(&one, 1));
124	MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
125
126	/* encode base point */
127	if (group->meth->field_dec) {
128		MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
129		MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
130	} else {
131		MP_CHECKOK(mp_copy(&group->genx, &gx));
132		MP_CHECKOK(mp_copy(&group->geny, &gy));
133	}
134	if (ectestPrint) {
135		/* output base point */
136		printf("  base point P:\n");
137		MP_CHECKOK(mp_toradix(&gx, s, 16));
138		printf("    %s\n", s);
139		MP_CHECKOK(mp_toradix(&gy, s, 16));
140		printf("    %s\n", s);
141		if (group->meth->field_enc) {
142			printf("  base point P (encoded):\n");
143			MP_CHECKOK(mp_toradix(&group->genx, s, 16));
144			printf("    %s\n", s);
145			MP_CHECKOK(mp_toradix(&group->geny, s, 16));
146			printf("    %s\n", s);
147		}
148	}
149
150#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
151	/* multiply base point by order - 1 and check for negative of base
152	 * point */
153	MP_CHECKOK(ec_GFp_pt_mul_aff
154			   (&order_1, &group->genx, &group->geny, &rx, &ry, group));
155	if (ectestPrint) {
156		printf("  (order-1)*P (affine):\n");
157		MP_CHECKOK(mp_toradix(&rx, s, 16));
158		printf("    %s\n", s);
159		MP_CHECKOK(mp_toradix(&ry, s, 16));
160		printf("    %s\n", s);
161	}
162	MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
163	if ((mp_cmp(&rx, &group->genx) != 0)
164		|| (mp_cmp(&ry, &group->geny) != 0)) {
165		printf("  Error: invalid result (expected (- base point)).\n");
166		res = MP_NO;
167		goto CLEANUP;
168	}
169#endif
170
171#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
172	/* multiply base point by order - 1 and check for negative of base
173	 * point */
174	MP_CHECKOK(ec_GFp_pt_mul_jac
175			   (&order_1, &group->genx, &group->geny, &rx, &ry, group));
176	if (ectestPrint) {
177		printf("  (order-1)*P (jacobian):\n");
178		MP_CHECKOK(mp_toradix(&rx, s, 16));
179		printf("    %s\n", s);
180		MP_CHECKOK(mp_toradix(&ry, s, 16));
181		printf("    %s\n", s);
182	}
183	MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
184	if ((mp_cmp(&rx, &group->genx) != 0)
185		|| (mp_cmp(&ry, &group->geny) != 0)) {
186		printf("  Error: invalid result (expected (- base point)).\n");
187		res = MP_NO;
188		goto CLEANUP;
189	}
190#endif
191
192	/* multiply base point by order - 1 and check for negative of base
193	 * point */
194	MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
195	if (ectestPrint) {
196		printf("  (order-1)*P (ECPoint_mul):\n");
197		MP_CHECKOK(mp_toradix(&rx, s, 16));
198		printf("    %s\n", s);
199		MP_CHECKOK(mp_toradix(&ry, s, 16));
200		printf("    %s\n", s);
201	}
202	MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
203	if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
204		printf("  Error: invalid result (expected (- base point)).\n");
205		res = MP_NO;
206		goto CLEANUP;
207	}
208
209	/* multiply base point by order - 1 and check for negative of base
210	 * point */
211	MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
212	if (ectestPrint) {
213		printf("  (order-1)*P (ECPoint_mul):\n");
214		MP_CHECKOK(mp_toradix(&rx, s, 16));
215		printf("    %s\n", s);
216		MP_CHECKOK(mp_toradix(&ry, s, 16));
217		printf("    %s\n", s);
218	}
219	MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
220	if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
221		printf("  Error: invalid result (expected (- base point)).\n");
222		res = MP_NO;
223		goto CLEANUP;
224	}
225
226#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
227	/* multiply base point by order and check for point at infinity */
228	MP_CHECKOK(ec_GFp_pt_mul_aff
229			   (&group->order, &group->genx, &group->geny, &rx, &ry,
230				group));
231	if (ectestPrint) {
232		printf("  (order)*P (affine):\n");
233		MP_CHECKOK(mp_toradix(&rx, s, 16));
234		printf("    %s\n", s);
235		MP_CHECKOK(mp_toradix(&ry, s, 16));
236		printf("    %s\n", s);
237	}
238	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
239		printf("  Error: invalid result (expected point at infinity).\n");
240		res = MP_NO;
241		goto CLEANUP;
242	}
243#endif
244
245#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
246	/* multiply base point by order and check for point at infinity */
247	MP_CHECKOK(ec_GFp_pt_mul_jac
248			   (&group->order, &group->genx, &group->geny, &rx, &ry,
249				group));
250	if (ectestPrint) {
251		printf("  (order)*P (jacobian):\n");
252		MP_CHECKOK(mp_toradix(&rx, s, 16));
253		printf("    %s\n", s);
254		MP_CHECKOK(mp_toradix(&ry, s, 16));
255		printf("    %s\n", s);
256	}
257	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
258		printf("  Error: invalid result (expected point at infinity).\n");
259		res = MP_NO;
260		goto CLEANUP;
261	}
262#endif
263
264	/* multiply base point by order and check for point at infinity */
265	MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
266	if (ectestPrint) {
267		printf("  (order)*P (ECPoint_mul):\n");
268		MP_CHECKOK(mp_toradix(&rx, s, 16));
269		printf("    %s\n", s);
270		MP_CHECKOK(mp_toradix(&ry, s, 16));
271		printf("    %s\n", s);
272	}
273	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
274		printf("  Error: invalid result (expected point at infinity).\n");
275		res = MP_NO;
276		goto CLEANUP;
277	}
278
279	/* multiply base point by order and check for point at infinity */
280	MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
281	if (ectestPrint) {
282		printf("  (order)*P (ECPoint_mul):\n");
283		MP_CHECKOK(mp_toradix(&rx, s, 16));
284		printf("    %s\n", s);
285		MP_CHECKOK(mp_toradix(&ry, s, 16));
286		printf("    %s\n", s);
287	}
288	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
289		printf("  Error: invalid result (expected point at infinity).\n");
290		res = MP_NO;
291		goto CLEANUP;
292	}
293
294	/* check that (order-1)P + (order-1)P + P == (order-1)P */
295	MP_CHECKOK(ECPoints_mul
296			   (group, &order_1, &order_1, &gx, &gy, &rx, &ry));
297	MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
298	if (ectestPrint) {
299		printf
300			("  (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
301		MP_CHECKOK(mp_toradix(&rx, s, 16));
302		printf("    %s\n", s);
303		MP_CHECKOK(mp_toradix(&ry, s, 16));
304		printf("    %s\n", s);
305	}
306	MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
307	if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
308		printf("  Error: invalid result (expected (- base point)).\n");
309		res = MP_NO;
310		goto CLEANUP;
311	}
312
313	/* test validate_point function */
314	if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
315		printf("  Error: validate point on base point failed.\n");
316		res = MP_NO;
317		goto CLEANUP;
318	}
319	MP_CHECKOK(mp_add_d(&gy, 1, &ry));
320	if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
321		printf("  Error: validate point on invalid point passed.\n");
322		res = MP_NO;
323		goto CLEANUP;
324	}
325
326	if (ectestTime) {
327		/* compute random scalar */
328		size = mpl_significant_bits(&group->meth->irr);
329		if (size < MP_OKAY) {
330			goto CLEANUP;
331		}
332		MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
333		MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
334		/* timed test */
335		if (generic) {
336#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
337			M_TimeOperation(MP_CHECKOK
338							(ec_GFp_pt_mul_aff
339							 (&n, &group->genx, &group->geny, &rx, &ry,
340							  group)), 100);
341#endif
342			M_TimeOperation(MP_CHECKOK
343							(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
344							100);
345			M_TimeOperation(MP_CHECKOK
346							(ECPoints_mul
347							 (group, &n, &n, &gx, &gy, &rx, &ry)), 100);
348		} else {
349			M_TimeOperation(MP_CHECKOK
350							(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
351							100);
352			M_TimeOperation(MP_CHECKOK
353							(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
354							100);
355			M_TimeOperation(MP_CHECKOK
356							(ECPoints_mul
357							 (group, &n, &n, &gx, &gy, &rx, &ry)), 100);
358		}
359	}
360
361  CLEANUP:
362	mp_clear(&one);
363	mp_clear(&order_1);
364	mp_clear(&gx);
365	mp_clear(&gy);
366	mp_clear(&rx);
367	mp_clear(&ry);
368	mp_clear(&n);
369	if (res != MP_OKAY) {
370		printf("  Error: exiting with error value %i\n", res);
371	}
372	return res;
373}
374
375/* Prints help information. */
376void
377printUsage()
378{
379	printf("Usage: ecp_test [--print] [--time]\n");
380	printf
381		("	--print     Print out results of each point arithmetic test.\n");
382	printf
383		("	--time      Benchmark point operations and print results.\n");
384}
385
386/* Performs tests of elliptic curve cryptography over prime fields If
387 * tests fail, then it prints an error message, aborts, and returns an
388 * error code. Otherwise, returns 0. */
389int
390main(int argv, char **argc)
391{
392
393	int ectestTime = 0;
394	int ectestPrint = 0;
395	int i;
396	ECGroup *group = NULL;
397	ECCurveParams *params = NULL;
398	mp_err res;
399
400	/* read command-line arguments */
401	for (i = 1; i < argv; i++) {
402		if ((strcasecmp(argc[i], "time") == 0)
403			|| (strcasecmp(argc[i], "-time") == 0)
404			|| (strcasecmp(argc[i], "--time") == 0)) {
405			ectestTime = 1;
406		} else if ((strcasecmp(argc[i], "print") == 0)
407				   || (strcasecmp(argc[i], "-print") == 0)
408				   || (strcasecmp(argc[i], "--print") == 0)) {
409			ectestPrint = 1;
410		} else {
411			printUsage();
412			return 0;
413		}
414	}
415
416	/* generic arithmetic tests */
417	ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
418
419	/* specific arithmetic tests */
420	ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
421	ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
422	ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
423	ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
424	ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
425	ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
426	ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
427	ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
428	ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
429	ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
430	ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
431	ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
432	ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
433	ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
434	ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
435	ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
436	ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
437	ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
438	ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
439	ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
440	ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
441	ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
442	ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
443	ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
444	ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
445	ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
446	ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
447	ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6);
448	ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7);
449	ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
450	ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
451	ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
452
453  CLEANUP:
454	EC_FreeCurveParams(params);
455	ECGroup_free(group);
456	if (res != MP_OKAY) {
457		printf("Error: exiting with error value %i\n", res);
458	}
459	return res;
460}