2
0

ec2_smpl.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. /*
  2. * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
  3. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  4. *
  5. * Licensed under the Apache License 2.0 (the "License"). You may not use
  6. * this file except in compliance with the License. You can obtain a copy
  7. * in the file LICENSE in the source distribution or at
  8. * https://www.openssl.org/source/license.html
  9. */
  10. /*
  11. * ECDSA low-level APIs are deprecated for public use, but still ok for
  12. * internal use.
  13. */
  14. #include "internal/deprecated.h"
  15. #include <openssl/err.h>
  16. #include "crypto/bn.h"
  17. #include "ec_local.h"
  18. #ifndef OPENSSL_NO_EC2M
  19. /*
  20. * Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
  21. * are handled by EC_GROUP_new.
  22. */
  23. int ossl_ec_GF2m_simple_group_init(EC_GROUP *group)
  24. {
  25. group->field = BN_new();
  26. group->a = BN_new();
  27. group->b = BN_new();
  28. if (group->field == NULL || group->a == NULL || group->b == NULL) {
  29. BN_free(group->field);
  30. BN_free(group->a);
  31. BN_free(group->b);
  32. return 0;
  33. }
  34. return 1;
  35. }
  36. /*
  37. * Free a GF(2^m)-based EC_GROUP structure. Note that all other members are
  38. * handled by EC_GROUP_free.
  39. */
  40. void ossl_ec_GF2m_simple_group_finish(EC_GROUP *group)
  41. {
  42. BN_free(group->field);
  43. BN_free(group->a);
  44. BN_free(group->b);
  45. }
  46. /*
  47. * Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other
  48. * members are handled by EC_GROUP_clear_free.
  49. */
  50. void ossl_ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
  51. {
  52. BN_clear_free(group->field);
  53. BN_clear_free(group->a);
  54. BN_clear_free(group->b);
  55. group->poly[0] = 0;
  56. group->poly[1] = 0;
  57. group->poly[2] = 0;
  58. group->poly[3] = 0;
  59. group->poly[4] = 0;
  60. group->poly[5] = -1;
  61. }
  62. /*
  63. * Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are
  64. * handled by EC_GROUP_copy.
  65. */
  66. int ossl_ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
  67. {
  68. if (!BN_copy(dest->field, src->field))
  69. return 0;
  70. if (!BN_copy(dest->a, src->a))
  71. return 0;
  72. if (!BN_copy(dest->b, src->b))
  73. return 0;
  74. dest->poly[0] = src->poly[0];
  75. dest->poly[1] = src->poly[1];
  76. dest->poly[2] = src->poly[2];
  77. dest->poly[3] = src->poly[3];
  78. dest->poly[4] = src->poly[4];
  79. dest->poly[5] = src->poly[5];
  80. if (bn_wexpand(dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
  81. NULL)
  82. return 0;
  83. if (bn_wexpand(dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
  84. NULL)
  85. return 0;
  86. bn_set_all_zero(dest->a);
  87. bn_set_all_zero(dest->b);
  88. return 1;
  89. }
  90. /* Set the curve parameters of an EC_GROUP structure. */
  91. int ossl_ec_GF2m_simple_group_set_curve(EC_GROUP *group,
  92. const BIGNUM *p, const BIGNUM *a,
  93. const BIGNUM *b, BN_CTX *ctx)
  94. {
  95. int ret = 0, i;
  96. /* group->field */
  97. if (!BN_copy(group->field, p))
  98. goto err;
  99. i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1;
  100. if ((i != 5) && (i != 3)) {
  101. ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD);
  102. goto err;
  103. }
  104. /* group->a */
  105. if (!BN_GF2m_mod_arr(group->a, a, group->poly))
  106. goto err;
  107. if (bn_wexpand(group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
  108. == NULL)
  109. goto err;
  110. bn_set_all_zero(group->a);
  111. /* group->b */
  112. if (!BN_GF2m_mod_arr(group->b, b, group->poly))
  113. goto err;
  114. if (bn_wexpand(group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
  115. == NULL)
  116. goto err;
  117. bn_set_all_zero(group->b);
  118. ret = 1;
  119. err:
  120. return ret;
  121. }
  122. /*
  123. * Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL
  124. * then there values will not be set but the method will return with success.
  125. */
  126. int ossl_ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
  127. BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
  128. {
  129. int ret = 0;
  130. if (p != NULL) {
  131. if (!BN_copy(p, group->field))
  132. return 0;
  133. }
  134. if (a != NULL) {
  135. if (!BN_copy(a, group->a))
  136. goto err;
  137. }
  138. if (b != NULL) {
  139. if (!BN_copy(b, group->b))
  140. goto err;
  141. }
  142. ret = 1;
  143. err:
  144. return ret;
  145. }
  146. /*
  147. * Gets the degree of the field. For a curve over GF(2^m) this is the value
  148. * m.
  149. */
  150. int ossl_ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
  151. {
  152. return BN_num_bits(group->field) - 1;
  153. }
  154. /*
  155. * Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an
  156. * elliptic curve <=> b != 0 (mod p)
  157. */
  158. int ossl_ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
  159. BN_CTX *ctx)
  160. {
  161. int ret = 0;
  162. BIGNUM *b;
  163. #ifndef FIPS_MODULE
  164. BN_CTX *new_ctx = NULL;
  165. if (ctx == NULL) {
  166. ctx = new_ctx = BN_CTX_new();
  167. if (ctx == NULL) {
  168. ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
  169. goto err;
  170. }
  171. }
  172. #endif
  173. BN_CTX_start(ctx);
  174. b = BN_CTX_get(ctx);
  175. if (b == NULL)
  176. goto err;
  177. if (!BN_GF2m_mod_arr(b, group->b, group->poly))
  178. goto err;
  179. /*
  180. * check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
  181. * curve <=> b != 0 (mod p)
  182. */
  183. if (BN_is_zero(b))
  184. goto err;
  185. ret = 1;
  186. err:
  187. BN_CTX_end(ctx);
  188. #ifndef FIPS_MODULE
  189. BN_CTX_free(new_ctx);
  190. #endif
  191. return ret;
  192. }
  193. /* Initializes an EC_POINT. */
  194. int ossl_ec_GF2m_simple_point_init(EC_POINT *point)
  195. {
  196. point->X = BN_new();
  197. point->Y = BN_new();
  198. point->Z = BN_new();
  199. if (point->X == NULL || point->Y == NULL || point->Z == NULL) {
  200. BN_free(point->X);
  201. BN_free(point->Y);
  202. BN_free(point->Z);
  203. return 0;
  204. }
  205. return 1;
  206. }
  207. /* Frees an EC_POINT. */
  208. void ossl_ec_GF2m_simple_point_finish(EC_POINT *point)
  209. {
  210. BN_free(point->X);
  211. BN_free(point->Y);
  212. BN_free(point->Z);
  213. }
  214. /* Clears and frees an EC_POINT. */
  215. void ossl_ec_GF2m_simple_point_clear_finish(EC_POINT *point)
  216. {
  217. BN_clear_free(point->X);
  218. BN_clear_free(point->Y);
  219. BN_clear_free(point->Z);
  220. point->Z_is_one = 0;
  221. }
  222. /*
  223. * Copy the contents of one EC_POINT into another. Assumes dest is
  224. * initialized.
  225. */
  226. int ossl_ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
  227. {
  228. if (!BN_copy(dest->X, src->X))
  229. return 0;
  230. if (!BN_copy(dest->Y, src->Y))
  231. return 0;
  232. if (!BN_copy(dest->Z, src->Z))
  233. return 0;
  234. dest->Z_is_one = src->Z_is_one;
  235. dest->curve_name = src->curve_name;
  236. return 1;
  237. }
  238. /*
  239. * Set an EC_POINT to the point at infinity. A point at infinity is
  240. * represented by having Z=0.
  241. */
  242. int ossl_ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
  243. EC_POINT *point)
  244. {
  245. point->Z_is_one = 0;
  246. BN_zero(point->Z);
  247. return 1;
  248. }
  249. /*
  250. * Set the coordinates of an EC_POINT using affine coordinates. Note that
  251. * the simple implementation only uses affine coordinates.
  252. */
  253. int ossl_ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
  254. EC_POINT *point,
  255. const BIGNUM *x,
  256. const BIGNUM *y,
  257. BN_CTX *ctx)
  258. {
  259. int ret = 0;
  260. if (x == NULL || y == NULL) {
  261. ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
  262. return 0;
  263. }
  264. if (!BN_copy(point->X, x))
  265. goto err;
  266. BN_set_negative(point->X, 0);
  267. if (!BN_copy(point->Y, y))
  268. goto err;
  269. BN_set_negative(point->Y, 0);
  270. if (!BN_copy(point->Z, BN_value_one()))
  271. goto err;
  272. BN_set_negative(point->Z, 0);
  273. point->Z_is_one = 1;
  274. ret = 1;
  275. err:
  276. return ret;
  277. }
  278. /*
  279. * Gets the affine coordinates of an EC_POINT. Note that the simple
  280. * implementation only uses affine coordinates.
  281. */
  282. int ossl_ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
  283. const EC_POINT *point,
  284. BIGNUM *x, BIGNUM *y,
  285. BN_CTX *ctx)
  286. {
  287. int ret = 0;
  288. if (EC_POINT_is_at_infinity(group, point)) {
  289. ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
  290. return 0;
  291. }
  292. if (BN_cmp(point->Z, BN_value_one())) {
  293. ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  294. return 0;
  295. }
  296. if (x != NULL) {
  297. if (!BN_copy(x, point->X))
  298. goto err;
  299. BN_set_negative(x, 0);
  300. }
  301. if (y != NULL) {
  302. if (!BN_copy(y, point->Y))
  303. goto err;
  304. BN_set_negative(y, 0);
  305. }
  306. ret = 1;
  307. err:
  308. return ret;
  309. }
  310. /*
  311. * Computes a + b and stores the result in r. r could be a or b, a could be
  312. * b. Uses algorithm A.10.2 of IEEE P1363.
  313. */
  314. int ossl_ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r,
  315. const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
  316. {
  317. BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
  318. int ret = 0;
  319. #ifndef FIPS_MODULE
  320. BN_CTX *new_ctx = NULL;
  321. #endif
  322. if (EC_POINT_is_at_infinity(group, a)) {
  323. if (!EC_POINT_copy(r, b))
  324. return 0;
  325. return 1;
  326. }
  327. if (EC_POINT_is_at_infinity(group, b)) {
  328. if (!EC_POINT_copy(r, a))
  329. return 0;
  330. return 1;
  331. }
  332. #ifndef FIPS_MODULE
  333. if (ctx == NULL) {
  334. ctx = new_ctx = BN_CTX_new();
  335. if (ctx == NULL)
  336. return 0;
  337. }
  338. #endif
  339. BN_CTX_start(ctx);
  340. x0 = BN_CTX_get(ctx);
  341. y0 = BN_CTX_get(ctx);
  342. x1 = BN_CTX_get(ctx);
  343. y1 = BN_CTX_get(ctx);
  344. x2 = BN_CTX_get(ctx);
  345. y2 = BN_CTX_get(ctx);
  346. s = BN_CTX_get(ctx);
  347. t = BN_CTX_get(ctx);
  348. if (t == NULL)
  349. goto err;
  350. if (a->Z_is_one) {
  351. if (!BN_copy(x0, a->X))
  352. goto err;
  353. if (!BN_copy(y0, a->Y))
  354. goto err;
  355. } else {
  356. if (!EC_POINT_get_affine_coordinates(group, a, x0, y0, ctx))
  357. goto err;
  358. }
  359. if (b->Z_is_one) {
  360. if (!BN_copy(x1, b->X))
  361. goto err;
  362. if (!BN_copy(y1, b->Y))
  363. goto err;
  364. } else {
  365. if (!EC_POINT_get_affine_coordinates(group, b, x1, y1, ctx))
  366. goto err;
  367. }
  368. if (BN_GF2m_cmp(x0, x1)) {
  369. if (!BN_GF2m_add(t, x0, x1))
  370. goto err;
  371. if (!BN_GF2m_add(s, y0, y1))
  372. goto err;
  373. if (!group->meth->field_div(group, s, s, t, ctx))
  374. goto err;
  375. if (!group->meth->field_sqr(group, x2, s, ctx))
  376. goto err;
  377. if (!BN_GF2m_add(x2, x2, group->a))
  378. goto err;
  379. if (!BN_GF2m_add(x2, x2, s))
  380. goto err;
  381. if (!BN_GF2m_add(x2, x2, t))
  382. goto err;
  383. } else {
  384. if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
  385. if (!EC_POINT_set_to_infinity(group, r))
  386. goto err;
  387. ret = 1;
  388. goto err;
  389. }
  390. if (!group->meth->field_div(group, s, y1, x1, ctx))
  391. goto err;
  392. if (!BN_GF2m_add(s, s, x1))
  393. goto err;
  394. if (!group->meth->field_sqr(group, x2, s, ctx))
  395. goto err;
  396. if (!BN_GF2m_add(x2, x2, s))
  397. goto err;
  398. if (!BN_GF2m_add(x2, x2, group->a))
  399. goto err;
  400. }
  401. if (!BN_GF2m_add(y2, x1, x2))
  402. goto err;
  403. if (!group->meth->field_mul(group, y2, y2, s, ctx))
  404. goto err;
  405. if (!BN_GF2m_add(y2, y2, x2))
  406. goto err;
  407. if (!BN_GF2m_add(y2, y2, y1))
  408. goto err;
  409. if (!EC_POINT_set_affine_coordinates(group, r, x2, y2, ctx))
  410. goto err;
  411. ret = 1;
  412. err:
  413. BN_CTX_end(ctx);
  414. #ifndef FIPS_MODULE
  415. BN_CTX_free(new_ctx);
  416. #endif
  417. return ret;
  418. }
  419. /*
  420. * Computes 2 * a and stores the result in r. r could be a. Uses algorithm
  421. * A.10.2 of IEEE P1363.
  422. */
  423. int ossl_ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r,
  424. const EC_POINT *a, BN_CTX *ctx)
  425. {
  426. return ossl_ec_GF2m_simple_add(group, r, a, a, ctx);
  427. }
  428. int ossl_ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point,
  429. BN_CTX *ctx)
  430. {
  431. if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
  432. /* point is its own inverse */
  433. return 1;
  434. if (group->meth->make_affine == NULL
  435. || !group->meth->make_affine(group, point, ctx))
  436. return 0;
  437. return BN_GF2m_add(point->Y, point->X, point->Y);
  438. }
  439. /* Indicates whether the given point is the point at infinity. */
  440. int ossl_ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
  441. const EC_POINT *point)
  442. {
  443. return BN_is_zero(point->Z);
  444. }
  445. /*-
  446. * Determines whether the given EC_POINT is an actual point on the curve defined
  447. * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
  448. * y^2 + x*y = x^3 + a*x^2 + b.
  449. */
  450. int ossl_ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
  451. BN_CTX *ctx)
  452. {
  453. int ret = -1;
  454. BIGNUM *lh, *y2;
  455. int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
  456. const BIGNUM *, BN_CTX *);
  457. int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
  458. #ifndef FIPS_MODULE
  459. BN_CTX *new_ctx = NULL;
  460. #endif
  461. if (EC_POINT_is_at_infinity(group, point))
  462. return 1;
  463. field_mul = group->meth->field_mul;
  464. field_sqr = group->meth->field_sqr;
  465. /* only support affine coordinates */
  466. if (!point->Z_is_one)
  467. return -1;
  468. #ifndef FIPS_MODULE
  469. if (ctx == NULL) {
  470. ctx = new_ctx = BN_CTX_new();
  471. if (ctx == NULL)
  472. return -1;
  473. }
  474. #endif
  475. BN_CTX_start(ctx);
  476. y2 = BN_CTX_get(ctx);
  477. lh = BN_CTX_get(ctx);
  478. if (lh == NULL)
  479. goto err;
  480. /*-
  481. * We have a curve defined by a Weierstrass equation
  482. * y^2 + x*y = x^3 + a*x^2 + b.
  483. * <=> x^3 + a*x^2 + x*y + b + y^2 = 0
  484. * <=> ((x + a) * x + y) * x + b + y^2 = 0
  485. */
  486. if (!BN_GF2m_add(lh, point->X, group->a))
  487. goto err;
  488. if (!field_mul(group, lh, lh, point->X, ctx))
  489. goto err;
  490. if (!BN_GF2m_add(lh, lh, point->Y))
  491. goto err;
  492. if (!field_mul(group, lh, lh, point->X, ctx))
  493. goto err;
  494. if (!BN_GF2m_add(lh, lh, group->b))
  495. goto err;
  496. if (!field_sqr(group, y2, point->Y, ctx))
  497. goto err;
  498. if (!BN_GF2m_add(lh, lh, y2))
  499. goto err;
  500. ret = BN_is_zero(lh);
  501. err:
  502. BN_CTX_end(ctx);
  503. #ifndef FIPS_MODULE
  504. BN_CTX_free(new_ctx);
  505. #endif
  506. return ret;
  507. }
  508. /*-
  509. * Indicates whether two points are equal.
  510. * Return values:
  511. * -1 error
  512. * 0 equal (in affine coordinates)
  513. * 1 not equal
  514. */
  515. int ossl_ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
  516. const EC_POINT *b, BN_CTX *ctx)
  517. {
  518. BIGNUM *aX, *aY, *bX, *bY;
  519. int ret = -1;
  520. #ifndef FIPS_MODULE
  521. BN_CTX *new_ctx = NULL;
  522. #endif
  523. if (EC_POINT_is_at_infinity(group, a)) {
  524. return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
  525. }
  526. if (EC_POINT_is_at_infinity(group, b))
  527. return 1;
  528. if (a->Z_is_one && b->Z_is_one) {
  529. return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
  530. }
  531. #ifndef FIPS_MODULE
  532. if (ctx == NULL) {
  533. ctx = new_ctx = BN_CTX_new();
  534. if (ctx == NULL)
  535. return -1;
  536. }
  537. #endif
  538. BN_CTX_start(ctx);
  539. aX = BN_CTX_get(ctx);
  540. aY = BN_CTX_get(ctx);
  541. bX = BN_CTX_get(ctx);
  542. bY = BN_CTX_get(ctx);
  543. if (bY == NULL)
  544. goto err;
  545. if (!EC_POINT_get_affine_coordinates(group, a, aX, aY, ctx))
  546. goto err;
  547. if (!EC_POINT_get_affine_coordinates(group, b, bX, bY, ctx))
  548. goto err;
  549. ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
  550. err:
  551. BN_CTX_end(ctx);
  552. #ifndef FIPS_MODULE
  553. BN_CTX_free(new_ctx);
  554. #endif
  555. return ret;
  556. }
  557. /* Forces the given EC_POINT to internally use affine coordinates. */
  558. int ossl_ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
  559. BN_CTX *ctx)
  560. {
  561. BIGNUM *x, *y;
  562. int ret = 0;
  563. #ifndef FIPS_MODULE
  564. BN_CTX *new_ctx = NULL;
  565. #endif
  566. if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
  567. return 1;
  568. #ifndef FIPS_MODULE
  569. if (ctx == NULL) {
  570. ctx = new_ctx = BN_CTX_new();
  571. if (ctx == NULL)
  572. return 0;
  573. }
  574. #endif
  575. BN_CTX_start(ctx);
  576. x = BN_CTX_get(ctx);
  577. y = BN_CTX_get(ctx);
  578. if (y == NULL)
  579. goto err;
  580. if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
  581. goto err;
  582. if (!BN_copy(point->X, x))
  583. goto err;
  584. if (!BN_copy(point->Y, y))
  585. goto err;
  586. if (!BN_one(point->Z))
  587. goto err;
  588. point->Z_is_one = 1;
  589. ret = 1;
  590. err:
  591. BN_CTX_end(ctx);
  592. #ifndef FIPS_MODULE
  593. BN_CTX_free(new_ctx);
  594. #endif
  595. return ret;
  596. }
  597. /*
  598. * Forces each of the EC_POINTs in the given array to use affine coordinates.
  599. */
  600. int ossl_ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
  601. EC_POINT *points[], BN_CTX *ctx)
  602. {
  603. size_t i;
  604. for (i = 0; i < num; i++) {
  605. if (!group->meth->make_affine(group, points[i], ctx))
  606. return 0;
  607. }
  608. return 1;
  609. }
  610. /* Wrapper to simple binary polynomial field multiplication implementation. */
  611. int ossl_ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
  612. const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
  613. {
  614. return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
  615. }
  616. /* Wrapper to simple binary polynomial field squaring implementation. */
  617. int ossl_ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
  618. const BIGNUM *a, BN_CTX *ctx)
  619. {
  620. return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
  621. }
  622. /* Wrapper to simple binary polynomial field division implementation. */
  623. int ossl_ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
  624. const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
  625. {
  626. return BN_GF2m_mod_div(r, a, b, group->field, ctx);
  627. }
  628. /*-
  629. * Lopez-Dahab ladder, pre step.
  630. * See e.g. "Guide to ECC" Alg 3.40.
  631. * Modified to blind s and r independently.
  632. * s:= p, r := 2p
  633. */
  634. static
  635. int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
  636. EC_POINT *r, EC_POINT *s,
  637. EC_POINT *p, BN_CTX *ctx)
  638. {
  639. /* if p is not affine, something is wrong */
  640. if (p->Z_is_one == 0)
  641. return 0;
  642. /* s blinding: make sure lambda (s->Z here) is not zero */
  643. do {
  644. if (!BN_priv_rand_ex(s->Z, BN_num_bits(group->field) - 1,
  645. BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) {
  646. ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
  647. return 0;
  648. }
  649. } while (BN_is_zero(s->Z));
  650. /* if field_encode defined convert between representations */
  651. if ((group->meth->field_encode != NULL
  652. && !group->meth->field_encode(group, s->Z, s->Z, ctx))
  653. || !group->meth->field_mul(group, s->X, p->X, s->Z, ctx))
  654. return 0;
  655. /* r blinding: make sure lambda (r->Y here for storage) is not zero */
  656. do {
  657. if (!BN_priv_rand_ex(r->Y, BN_num_bits(group->field) - 1,
  658. BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0, ctx)) {
  659. ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
  660. return 0;
  661. }
  662. } while (BN_is_zero(r->Y));
  663. if ((group->meth->field_encode != NULL
  664. && !group->meth->field_encode(group, r->Y, r->Y, ctx))
  665. || !group->meth->field_sqr(group, r->Z, p->X, ctx)
  666. || !group->meth->field_sqr(group, r->X, r->Z, ctx)
  667. || !BN_GF2m_add(r->X, r->X, group->b)
  668. || !group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx)
  669. || !group->meth->field_mul(group, r->X, r->X, r->Y, ctx))
  670. return 0;
  671. s->Z_is_one = 0;
  672. r->Z_is_one = 0;
  673. return 1;
  674. }
  675. /*-
  676. * Ladder step: differential addition-and-doubling, mixed Lopez-Dahab coords.
  677. * http://www.hyperelliptic.org/EFD/g12o/auto-code/shortw/xz/ladder/mladd-2003-s.op3
  678. * s := r + s, r := 2r
  679. */
  680. static
  681. int ec_GF2m_simple_ladder_step(const EC_GROUP *group,
  682. EC_POINT *r, EC_POINT *s,
  683. EC_POINT *p, BN_CTX *ctx)
  684. {
  685. if (!group->meth->field_mul(group, r->Y, r->Z, s->X, ctx)
  686. || !group->meth->field_mul(group, s->X, r->X, s->Z, ctx)
  687. || !group->meth->field_sqr(group, s->Y, r->Z, ctx)
  688. || !group->meth->field_sqr(group, r->Z, r->X, ctx)
  689. || !BN_GF2m_add(s->Z, r->Y, s->X)
  690. || !group->meth->field_sqr(group, s->Z, s->Z, ctx)
  691. || !group->meth->field_mul(group, s->X, r->Y, s->X, ctx)
  692. || !group->meth->field_mul(group, r->Y, s->Z, p->X, ctx)
  693. || !BN_GF2m_add(s->X, s->X, r->Y)
  694. || !group->meth->field_sqr(group, r->Y, r->Z, ctx)
  695. || !group->meth->field_mul(group, r->Z, r->Z, s->Y, ctx)
  696. || !group->meth->field_sqr(group, s->Y, s->Y, ctx)
  697. || !group->meth->field_mul(group, s->Y, s->Y, group->b, ctx)
  698. || !BN_GF2m_add(r->X, r->Y, s->Y))
  699. return 0;
  700. return 1;
  701. }
  702. /*-
  703. * Recover affine (x,y) result from Lopez-Dahab r and s, affine p.
  704. * See e.g. "Fast Multiplication on Elliptic Curves over GF(2**m)
  705. * without Precomputation" (Lopez and Dahab, CHES 1999),
  706. * Appendix Alg Mxy.
  707. */
  708. static
  709. int ec_GF2m_simple_ladder_post(const EC_GROUP *group,
  710. EC_POINT *r, EC_POINT *s,
  711. EC_POINT *p, BN_CTX *ctx)
  712. {
  713. int ret = 0;
  714. BIGNUM *t0, *t1, *t2 = NULL;
  715. if (BN_is_zero(r->Z))
  716. return EC_POINT_set_to_infinity(group, r);
  717. if (BN_is_zero(s->Z)) {
  718. if (!EC_POINT_copy(r, p)
  719. || !EC_POINT_invert(group, r, ctx)) {
  720. ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
  721. return 0;
  722. }
  723. return 1;
  724. }
  725. BN_CTX_start(ctx);
  726. t0 = BN_CTX_get(ctx);
  727. t1 = BN_CTX_get(ctx);
  728. t2 = BN_CTX_get(ctx);
  729. if (t2 == NULL) {
  730. ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
  731. goto err;
  732. }
  733. if (!group->meth->field_mul(group, t0, r->Z, s->Z, ctx)
  734. || !group->meth->field_mul(group, t1, p->X, r->Z, ctx)
  735. || !BN_GF2m_add(t1, r->X, t1)
  736. || !group->meth->field_mul(group, t2, p->X, s->Z, ctx)
  737. || !group->meth->field_mul(group, r->Z, r->X, t2, ctx)
  738. || !BN_GF2m_add(t2, t2, s->X)
  739. || !group->meth->field_mul(group, t1, t1, t2, ctx)
  740. || !group->meth->field_sqr(group, t2, p->X, ctx)
  741. || !BN_GF2m_add(t2, p->Y, t2)
  742. || !group->meth->field_mul(group, t2, t2, t0, ctx)
  743. || !BN_GF2m_add(t1, t2, t1)
  744. || !group->meth->field_mul(group, t2, p->X, t0, ctx)
  745. || !group->meth->field_inv(group, t2, t2, ctx)
  746. || !group->meth->field_mul(group, t1, t1, t2, ctx)
  747. || !group->meth->field_mul(group, r->X, r->Z, t2, ctx)
  748. || !BN_GF2m_add(t2, p->X, r->X)
  749. || !group->meth->field_mul(group, t2, t2, t1, ctx)
  750. || !BN_GF2m_add(r->Y, p->Y, t2)
  751. || !BN_one(r->Z))
  752. goto err;
  753. r->Z_is_one = 1;
  754. /* GF(2^m) field elements should always have BIGNUM::neg = 0 */
  755. BN_set_negative(r->X, 0);
  756. BN_set_negative(r->Y, 0);
  757. ret = 1;
  758. err:
  759. BN_CTX_end(ctx);
  760. return ret;
  761. }
  762. static
  763. int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r,
  764. const BIGNUM *scalar, size_t num,
  765. const EC_POINT *points[],
  766. const BIGNUM *scalars[],
  767. BN_CTX *ctx)
  768. {
  769. int ret = 0;
  770. EC_POINT *t = NULL;
  771. /*-
  772. * We limit use of the ladder only to the following cases:
  773. * - r := scalar * G
  774. * Fixed point mul: scalar != NULL && num == 0;
  775. * - r := scalars[0] * points[0]
  776. * Variable point mul: scalar == NULL && num == 1;
  777. * - r := scalar * G + scalars[0] * points[0]
  778. * used, e.g., in ECDSA verification: scalar != NULL && num == 1
  779. *
  780. * In any other case (num > 1) we use the default wNAF implementation.
  781. *
  782. * We also let the default implementation handle degenerate cases like group
  783. * order or cofactor set to 0.
  784. */
  785. if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor))
  786. return ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
  787. if (scalar != NULL && num == 0)
  788. /* Fixed point multiplication */
  789. return ossl_ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
  790. if (scalar == NULL && num == 1)
  791. /* Variable point multiplication */
  792. return ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
  793. /*-
  794. * Double point multiplication:
  795. * r := scalar * G + scalars[0] * points[0]
  796. */
  797. if ((t = EC_POINT_new(group)) == NULL) {
  798. ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
  799. return 0;
  800. }
  801. if (!ossl_ec_scalar_mul_ladder(group, t, scalar, NULL, ctx)
  802. || !ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx)
  803. || !EC_POINT_add(group, r, t, r, ctx))
  804. goto err;
  805. ret = 1;
  806. err:
  807. EC_POINT_free(t);
  808. return ret;
  809. }
  810. /*-
  811. * Computes the multiplicative inverse of a in GF(2^m), storing the result in r.
  812. * If a is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error.
  813. * SCA hardening is with blinding: BN_GF2m_mod_inv does that.
  814. */
  815. static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r,
  816. const BIGNUM *a, BN_CTX *ctx)
  817. {
  818. int ret;
  819. if (!(ret = BN_GF2m_mod_inv(r, a, group->field, ctx)))
  820. ERR_raise(ERR_LIB_EC, EC_R_CANNOT_INVERT);
  821. return ret;
  822. }
  823. const EC_METHOD *EC_GF2m_simple_method(void)
  824. {
  825. static const EC_METHOD ret = {
  826. EC_FLAGS_DEFAULT_OCT,
  827. NID_X9_62_characteristic_two_field,
  828. ossl_ec_GF2m_simple_group_init,
  829. ossl_ec_GF2m_simple_group_finish,
  830. ossl_ec_GF2m_simple_group_clear_finish,
  831. ossl_ec_GF2m_simple_group_copy,
  832. ossl_ec_GF2m_simple_group_set_curve,
  833. ossl_ec_GF2m_simple_group_get_curve,
  834. ossl_ec_GF2m_simple_group_get_degree,
  835. ossl_ec_group_simple_order_bits,
  836. ossl_ec_GF2m_simple_group_check_discriminant,
  837. ossl_ec_GF2m_simple_point_init,
  838. ossl_ec_GF2m_simple_point_finish,
  839. ossl_ec_GF2m_simple_point_clear_finish,
  840. ossl_ec_GF2m_simple_point_copy,
  841. ossl_ec_GF2m_simple_point_set_to_infinity,
  842. ossl_ec_GF2m_simple_point_set_affine_coordinates,
  843. ossl_ec_GF2m_simple_point_get_affine_coordinates,
  844. 0, /* point_set_compressed_coordinates */
  845. 0, /* point2oct */
  846. 0, /* oct2point */
  847. ossl_ec_GF2m_simple_add,
  848. ossl_ec_GF2m_simple_dbl,
  849. ossl_ec_GF2m_simple_invert,
  850. ossl_ec_GF2m_simple_is_at_infinity,
  851. ossl_ec_GF2m_simple_is_on_curve,
  852. ossl_ec_GF2m_simple_cmp,
  853. ossl_ec_GF2m_simple_make_affine,
  854. ossl_ec_GF2m_simple_points_make_affine,
  855. ec_GF2m_simple_points_mul,
  856. 0, /* precompute_mult */
  857. 0, /* have_precompute_mult */
  858. ossl_ec_GF2m_simple_field_mul,
  859. ossl_ec_GF2m_simple_field_sqr,
  860. ossl_ec_GF2m_simple_field_div,
  861. ec_GF2m_simple_field_inv,
  862. 0, /* field_encode */
  863. 0, /* field_decode */
  864. 0, /* field_set_to_one */
  865. ossl_ec_key_simple_priv2oct,
  866. ossl_ec_key_simple_oct2priv,
  867. 0, /* set private */
  868. ossl_ec_key_simple_generate_key,
  869. ossl_ec_key_simple_check_key,
  870. ossl_ec_key_simple_generate_public_key,
  871. 0, /* keycopy */
  872. 0, /* keyfinish */
  873. ossl_ecdh_simple_compute_key,
  874. ossl_ecdsa_simple_sign_setup,
  875. ossl_ecdsa_simple_sign_sig,
  876. ossl_ecdsa_simple_verify_sig,
  877. 0, /* field_inverse_mod_ord */
  878. 0, /* blind_coordinates */
  879. ec_GF2m_simple_ladder_pre,
  880. ec_GF2m_simple_ladder_step,
  881. ec_GF2m_simple_ladder_post
  882. };
  883. return &ret;
  884. }
  885. #endif