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