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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial