ec2_smpl.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. /* crypto/ec/ec2_smpl.c */
  2. /* ====================================================================
  3. * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  4. *
  5. * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
  6. * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
  7. * to the OpenSSL project.
  8. *
  9. * The ECC Code is licensed pursuant to the OpenSSL open source
  10. * license provided below.
  11. *
  12. * The software is originally written by Sheueling Chang Shantz and
  13. * Douglas Stebila of Sun Microsystems Laboratories.
  14. *
  15. */
  16. /* ====================================================================
  17. * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
  18. *
  19. * Redistribution and use in source and binary forms, with or without
  20. * modification, are permitted provided that the following conditions
  21. * are met:
  22. *
  23. * 1. Redistributions of source code must retain the above copyright
  24. * notice, this list of conditions and the following disclaimer.
  25. *
  26. * 2. Redistributions in binary form must reproduce the above copyright
  27. * notice, this list of conditions and the following disclaimer in
  28. * the documentation and/or other materials provided with the
  29. * distribution.
  30. *
  31. * 3. All advertising materials mentioning features or use of this
  32. * software must display the following acknowledgment:
  33. * "This product includes software developed by the OpenSSL Project
  34. * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  35. *
  36. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  37. * endorse or promote products derived from this software without
  38. * prior written permission. For written permission, please contact
  39. * openssl-core@openssl.org.
  40. *
  41. * 5. Products derived from this software may not be called "OpenSSL"
  42. * nor may "OpenSSL" appear in their names without prior written
  43. * permission of the OpenSSL Project.
  44. *
  45. * 6. Redistributions of any form whatsoever must retain the following
  46. * acknowledgment:
  47. * "This product includes software developed by the OpenSSL Project
  48. * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  49. *
  50. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  51. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  52. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  53. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  54. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  55. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  56. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  57. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  58. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  59. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  60. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  61. * OF THE POSSIBILITY OF SUCH DAMAGE.
  62. * ====================================================================
  63. *
  64. * This product includes cryptographic software written by Eric Young
  65. * (eay@cryptsoft.com). This product includes software written by Tim
  66. * Hudson (tjh@cryptsoft.com).
  67. *
  68. */
  69. #include <openssl/err.h>
  70. #include "ec_lcl.h"
  71. const EC_METHOD *EC_GF2m_simple_method(void)
  72. {
  73. static const EC_METHOD ret = {
  74. NID_X9_62_characteristic_two_field,
  75. ec_GF2m_simple_group_init,
  76. ec_GF2m_simple_group_finish,
  77. ec_GF2m_simple_group_clear_finish,
  78. ec_GF2m_simple_group_copy,
  79. ec_GF2m_simple_group_set_curve,
  80. ec_GF2m_simple_group_get_curve,
  81. ec_GF2m_simple_group_get_degree,
  82. ec_GF2m_simple_group_check_discriminant,
  83. ec_GF2m_simple_point_init,
  84. ec_GF2m_simple_point_finish,
  85. ec_GF2m_simple_point_clear_finish,
  86. ec_GF2m_simple_point_copy,
  87. ec_GF2m_simple_point_set_to_infinity,
  88. 0 /* set_Jprojective_coordinates_GFp */,
  89. 0 /* get_Jprojective_coordinates_GFp */,
  90. ec_GF2m_simple_point_set_affine_coordinates,
  91. ec_GF2m_simple_point_get_affine_coordinates,
  92. ec_GF2m_simple_set_compressed_coordinates,
  93. ec_GF2m_simple_point2oct,
  94. ec_GF2m_simple_oct2point,
  95. ec_GF2m_simple_add,
  96. ec_GF2m_simple_dbl,
  97. ec_GF2m_simple_invert,
  98. ec_GF2m_simple_is_at_infinity,
  99. ec_GF2m_simple_is_on_curve,
  100. ec_GF2m_simple_cmp,
  101. ec_GF2m_simple_make_affine,
  102. ec_GF2m_simple_points_make_affine,
  103. /* the following three method functions are defined in ec2_mult.c */
  104. ec_GF2m_simple_mul,
  105. ec_GF2m_precompute_mult,
  106. ec_GF2m_have_precompute_mult,
  107. ec_GF2m_simple_field_mul,
  108. ec_GF2m_simple_field_sqr,
  109. ec_GF2m_simple_field_div,
  110. 0 /* field_encode */,
  111. 0 /* field_decode */,
  112. 0 /* field_set_to_one */ };
  113. return &ret;
  114. }
  115. /* Initialize a GF(2^m)-based EC_GROUP structure.
  116. * Note that all other members are handled by EC_GROUP_new.
  117. */
  118. int ec_GF2m_simple_group_init(EC_GROUP *group)
  119. {
  120. BN_init(&group->field);
  121. BN_init(&group->a);
  122. BN_init(&group->b);
  123. return 1;
  124. }
  125. /* Free a GF(2^m)-based EC_GROUP structure.
  126. * Note that all other members are handled by EC_GROUP_free.
  127. */
  128. void ec_GF2m_simple_group_finish(EC_GROUP *group)
  129. {
  130. BN_free(&group->field);
  131. BN_free(&group->a);
  132. BN_free(&group->b);
  133. }
  134. /* Clear and free a GF(2^m)-based EC_GROUP structure.
  135. * Note that all other members are handled by EC_GROUP_clear_free.
  136. */
  137. void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
  138. {
  139. BN_clear_free(&group->field);
  140. BN_clear_free(&group->a);
  141. BN_clear_free(&group->b);
  142. group->poly[0] = 0;
  143. group->poly[1] = 0;
  144. group->poly[2] = 0;
  145. group->poly[3] = 0;
  146. group->poly[4] = 0;
  147. }
  148. /* Copy a GF(2^m)-based EC_GROUP structure.
  149. * Note that all other members are handled by EC_GROUP_copy.
  150. */
  151. int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
  152. {
  153. int i;
  154. if (!BN_copy(&dest->field, &src->field)) return 0;
  155. if (!BN_copy(&dest->a, &src->a)) return 0;
  156. if (!BN_copy(&dest->b, &src->b)) return 0;
  157. dest->poly[0] = src->poly[0];
  158. dest->poly[1] = src->poly[1];
  159. dest->poly[2] = src->poly[2];
  160. dest->poly[3] = src->poly[3];
  161. dest->poly[4] = src->poly[4];
  162. bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2);
  163. bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2);
  164. for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0;
  165. for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0;
  166. return 1;
  167. }
  168. /* Set the curve parameters of an EC_GROUP structure. */
  169. int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
  170. const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
  171. {
  172. int ret = 0, i;
  173. /* group->field */
  174. if (!BN_copy(&group->field, p)) goto err;
  175. i = BN_GF2m_poly2arr(&group->field, group->poly, 5);
  176. if ((i != 5) && (i != 3))
  177. {
  178. ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
  179. goto err;
  180. }
  181. /* group->a */
  182. if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err;
  183. bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2);
  184. for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0;
  185. /* group->b */
  186. if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err;
  187. bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2);
  188. for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0;
  189. ret = 1;
  190. err:
  191. return ret;
  192. }
  193. /* Get the curve parameters of an EC_GROUP structure.
  194. * If p, a, or b are NULL then there values will not be set but the method will return with success.
  195. */
  196. int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
  197. {
  198. int ret = 0;
  199. if (p != NULL)
  200. {
  201. if (!BN_copy(p, &group->field)) return 0;
  202. }
  203. if (a != NULL)
  204. {
  205. if (!BN_copy(a, &group->a)) goto err;
  206. }
  207. if (b != NULL)
  208. {
  209. if (!BN_copy(b, &group->b)) goto err;
  210. }
  211. ret = 1;
  212. err:
  213. return ret;
  214. }
  215. /* Gets the degree of the field. For a curve over GF(2^m) this is the value m. */
  216. int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
  217. {
  218. return BN_num_bits(&group->field)-1;
  219. }
  220. /* Checks the discriminant of the curve.
  221. * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
  222. */
  223. int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
  224. {
  225. int ret = 0;
  226. BIGNUM *b;
  227. BN_CTX *new_ctx = NULL;
  228. if (ctx == NULL)
  229. {
  230. ctx = new_ctx = BN_CTX_new();
  231. if (ctx == NULL)
  232. {
  233. ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
  234. goto err;
  235. }
  236. }
  237. BN_CTX_start(ctx);
  238. b = BN_CTX_get(ctx);
  239. if (b == NULL) goto err;
  240. if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err;
  241. /* check the discriminant:
  242. * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
  243. */
  244. if (BN_is_zero(b)) goto err;
  245. ret = 1;
  246. err:
  247. if (ctx != NULL)
  248. BN_CTX_end(ctx);
  249. if (new_ctx != NULL)
  250. BN_CTX_free(new_ctx);
  251. return ret;
  252. }
  253. /* Initializes an EC_POINT. */
  254. int ec_GF2m_simple_point_init(EC_POINT *point)
  255. {
  256. BN_init(&point->X);
  257. BN_init(&point->Y);
  258. BN_init(&point->Z);
  259. return 1;
  260. }
  261. /* Frees an EC_POINT. */
  262. void ec_GF2m_simple_point_finish(EC_POINT *point)
  263. {
  264. BN_free(&point->X);
  265. BN_free(&point->Y);
  266. BN_free(&point->Z);
  267. }
  268. /* Clears and frees an EC_POINT. */
  269. void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
  270. {
  271. BN_clear_free(&point->X);
  272. BN_clear_free(&point->Y);
  273. BN_clear_free(&point->Z);
  274. point->Z_is_one = 0;
  275. }
  276. /* Copy the contents of one EC_POINT into another. Assumes dest is initialized. */
  277. int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
  278. {
  279. if (!BN_copy(&dest->X, &src->X)) return 0;
  280. if (!BN_copy(&dest->Y, &src->Y)) return 0;
  281. if (!BN_copy(&dest->Z, &src->Z)) return 0;
  282. dest->Z_is_one = src->Z_is_one;
  283. return 1;
  284. }
  285. /* Set an EC_POINT to the point at infinity.
  286. * A point at infinity is represented by having Z=0.
  287. */
  288. int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
  289. {
  290. point->Z_is_one = 0;
  291. BN_zero(&point->Z);
  292. return 1;
  293. }
  294. /* Set the coordinates of an EC_POINT using affine coordinates.
  295. * Note that the simple implementation only uses affine coordinates.
  296. */
  297. int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
  298. const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
  299. {
  300. int ret = 0;
  301. if (x == NULL || y == NULL)
  302. {
  303. ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
  304. return 0;
  305. }
  306. if (!BN_copy(&point->X, x)) goto err;
  307. BN_set_negative(&point->X, 0);
  308. if (!BN_copy(&point->Y, y)) goto err;
  309. BN_set_negative(&point->Y, 0);
  310. if (!BN_copy(&point->Z, BN_value_one())) goto err;
  311. BN_set_negative(&point->Z, 0);
  312. point->Z_is_one = 1;
  313. ret = 1;
  314. err:
  315. return ret;
  316. }
  317. /* Gets the affine coordinates of an EC_POINT.
  318. * Note that the simple implementation only uses affine coordinates.
  319. */
  320. int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
  321. BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
  322. {
  323. int ret = 0;
  324. if (EC_POINT_is_at_infinity(group, point))
  325. {
  326. ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
  327. return 0;
  328. }
  329. if (BN_cmp(&point->Z, BN_value_one()))
  330. {
  331. ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
  332. return 0;
  333. }
  334. if (x != NULL)
  335. {
  336. if (!BN_copy(x, &point->X)) goto err;
  337. BN_set_negative(x, 0);
  338. }
  339. if (y != NULL)
  340. {
  341. if (!BN_copy(y, &point->Y)) goto err;
  342. BN_set_negative(y, 0);
  343. }
  344. ret = 1;
  345. err:
  346. return ret;
  347. }
  348. /* Calculates and sets the affine coordinates of an EC_POINT from the given
  349. * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
  350. * Note that the simple implementation only uses affine coordinates.
  351. *
  352. * The method is from the following publication:
  353. *
  354. * Harper, Menezes, Vanstone:
  355. * "Public-Key Cryptosystems with Very Small Key Lengths",
  356. * EUROCRYPT '92, Springer-Verlag LNCS 658,
  357. * published February 1993
  358. *
  359. * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
  360. * the same method, but claim no priority date earlier than July 29, 1994
  361. * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
  362. */
  363. int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
  364. const BIGNUM *x_, int y_bit, BN_CTX *ctx)
  365. {
  366. BN_CTX *new_ctx = NULL;
  367. BIGNUM *tmp, *x, *y, *z;
  368. int ret = 0, z0;
  369. /* clear error queue */
  370. ERR_clear_error();
  371. if (ctx == NULL)
  372. {
  373. ctx = new_ctx = BN_CTX_new();
  374. if (ctx == NULL)
  375. return 0;
  376. }
  377. y_bit = (y_bit != 0) ? 1 : 0;
  378. BN_CTX_start(ctx);
  379. tmp = BN_CTX_get(ctx);
  380. x = BN_CTX_get(ctx);
  381. y = BN_CTX_get(ctx);
  382. z = BN_CTX_get(ctx);
  383. if (z == NULL) goto err;
  384. if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
  385. if (BN_is_zero(x))
  386. {
  387. if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
  388. }
  389. else
  390. {
  391. if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
  392. if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
  393. if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
  394. if (!BN_GF2m_add(tmp, x, tmp)) goto err;
  395. if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
  396. {
  397. unsigned long err = ERR_peek_last_error();
  398. if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
  399. {
  400. ERR_clear_error();
  401. ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
  402. }
  403. else
  404. ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
  405. goto err;
  406. }
  407. z0 = (BN_is_odd(z)) ? 1 : 0;
  408. if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
  409. if (z0 != y_bit)
  410. {
  411. if (!BN_GF2m_add(y, y, x)) goto err;
  412. }
  413. }
  414. if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
  415. ret = 1;
  416. err:
  417. BN_CTX_end(ctx);
  418. if (new_ctx != NULL)
  419. BN_CTX_free(new_ctx);
  420. return ret;
  421. }
  422. /* Converts an EC_POINT to an octet string.
  423. * If buf is NULL, the encoded length will be returned.
  424. * If the length len of buf is smaller than required an error will be returned.
  425. */
  426. size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
  427. unsigned char *buf, size_t len, BN_CTX *ctx)
  428. {
  429. size_t ret;
  430. BN_CTX *new_ctx = NULL;
  431. int used_ctx = 0;
  432. BIGNUM *x, *y, *yxi;
  433. size_t field_len, i, skip;
  434. if ((form != POINT_CONVERSION_COMPRESSED)
  435. && (form != POINT_CONVERSION_UNCOMPRESSED)
  436. && (form != POINT_CONVERSION_HYBRID))
  437. {
  438. ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
  439. goto err;
  440. }
  441. if (EC_POINT_is_at_infinity(group, point))
  442. {
  443. /* encodes to a single 0 octet */
  444. if (buf != NULL)
  445. {
  446. if (len < 1)
  447. {
  448. ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
  449. return 0;
  450. }
  451. buf[0] = 0;
  452. }
  453. return 1;
  454. }
  455. /* ret := required output buffer length */
  456. field_len = (EC_GROUP_get_degree(group) + 7) / 8;
  457. ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
  458. /* if 'buf' is NULL, just return required length */
  459. if (buf != NULL)
  460. {
  461. if (len < ret)
  462. {
  463. ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
  464. goto err;
  465. }
  466. if (ctx == NULL)
  467. {
  468. ctx = new_ctx = BN_CTX_new();
  469. if (ctx == NULL)
  470. return 0;
  471. }
  472. BN_CTX_start(ctx);
  473. used_ctx = 1;
  474. x = BN_CTX_get(ctx);
  475. y = BN_CTX_get(ctx);
  476. yxi = BN_CTX_get(ctx);
  477. if (yxi == NULL) goto err;
  478. if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
  479. buf[0] = form;
  480. if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
  481. {
  482. if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
  483. if (BN_is_odd(yxi)) buf[0]++;
  484. }
  485. i = 1;
  486. skip = field_len - BN_num_bytes(x);
  487. if (skip > field_len)
  488. {
  489. ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
  490. goto err;
  491. }
  492. while (skip > 0)
  493. {
  494. buf[i++] = 0;
  495. skip--;
  496. }
  497. skip = BN_bn2bin(x, buf + i);
  498. i += skip;
  499. if (i != 1 + field_len)
  500. {
  501. ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
  502. goto err;
  503. }
  504. if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
  505. {
  506. skip = field_len - BN_num_bytes(y);
  507. if (skip > field_len)
  508. {
  509. ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
  510. goto err;
  511. }
  512. while (skip > 0)
  513. {
  514. buf[i++] = 0;
  515. skip--;
  516. }
  517. skip = BN_bn2bin(y, buf + i);
  518. i += skip;
  519. }
  520. if (i != ret)
  521. {
  522. ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
  523. goto err;
  524. }
  525. }
  526. if (used_ctx)
  527. BN_CTX_end(ctx);
  528. if (new_ctx != NULL)
  529. BN_CTX_free(new_ctx);
  530. return ret;
  531. err:
  532. if (used_ctx)
  533. BN_CTX_end(ctx);
  534. if (new_ctx != NULL)
  535. BN_CTX_free(new_ctx);
  536. return 0;
  537. }
  538. /* Converts an octet string representation to an EC_POINT.
  539. * Note that the simple implementation only uses affine coordinates.
  540. */
  541. int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
  542. const unsigned char *buf, size_t len, BN_CTX *ctx)
  543. {
  544. point_conversion_form_t form;
  545. int y_bit;
  546. BN_CTX *new_ctx = NULL;
  547. BIGNUM *x, *y, *yxi;
  548. size_t field_len, enc_len;
  549. int ret = 0;
  550. if (len == 0)
  551. {
  552. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
  553. return 0;
  554. }
  555. form = buf[0];
  556. y_bit = form & 1;
  557. form = form & ~1U;
  558. if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
  559. && (form != POINT_CONVERSION_UNCOMPRESSED)
  560. && (form != POINT_CONVERSION_HYBRID))
  561. {
  562. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
  563. return 0;
  564. }
  565. if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
  566. {
  567. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
  568. return 0;
  569. }
  570. if (form == 0)
  571. {
  572. if (len != 1)
  573. {
  574. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
  575. return 0;
  576. }
  577. return EC_POINT_set_to_infinity(group, point);
  578. }
  579. field_len = (EC_GROUP_get_degree(group) + 7) / 8;
  580. enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
  581. if (len != enc_len)
  582. {
  583. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
  584. return 0;
  585. }
  586. if (ctx == NULL)
  587. {
  588. ctx = new_ctx = BN_CTX_new();
  589. if (ctx == NULL)
  590. return 0;
  591. }
  592. BN_CTX_start(ctx);
  593. x = BN_CTX_get(ctx);
  594. y = BN_CTX_get(ctx);
  595. yxi = BN_CTX_get(ctx);
  596. if (yxi == NULL) goto err;
  597. if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
  598. if (BN_ucmp(x, &group->field) >= 0)
  599. {
  600. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
  601. goto err;
  602. }
  603. if (form == POINT_CONVERSION_COMPRESSED)
  604. {
  605. if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
  606. }
  607. else
  608. {
  609. if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
  610. if (BN_ucmp(y, &group->field) >= 0)
  611. {
  612. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
  613. goto err;
  614. }
  615. if (form == POINT_CONVERSION_HYBRID)
  616. {
  617. if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
  618. if (y_bit != BN_is_odd(yxi))
  619. {
  620. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
  621. goto err;
  622. }
  623. }
  624. if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
  625. }
  626. if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
  627. {
  628. ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
  629. goto err;
  630. }
  631. ret = 1;
  632. err:
  633. BN_CTX_end(ctx);
  634. if (new_ctx != NULL)
  635. BN_CTX_free(new_ctx);
  636. return ret;
  637. }
  638. /* Computes a + b and stores the result in r. r could be a or b, a could be b.
  639. * Uses algorithm A.10.2 of IEEE P1363.
  640. */
  641. int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
  642. {
  643. BN_CTX *new_ctx = NULL;
  644. BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
  645. int ret = 0;
  646. if (EC_POINT_is_at_infinity(group, a))
  647. {
  648. if (!EC_POINT_copy(r, b)) return 0;
  649. return 1;
  650. }
  651. if (EC_POINT_is_at_infinity(group, b))
  652. {
  653. if (!EC_POINT_copy(r, a)) return 0;
  654. return 1;
  655. }
  656. if (ctx == NULL)
  657. {
  658. ctx = new_ctx = BN_CTX_new();
  659. if (ctx == NULL)
  660. return 0;
  661. }
  662. BN_CTX_start(ctx);
  663. x0 = BN_CTX_get(ctx);
  664. y0 = BN_CTX_get(ctx);
  665. x1 = BN_CTX_get(ctx);
  666. y1 = BN_CTX_get(ctx);
  667. x2 = BN_CTX_get(ctx);
  668. y2 = BN_CTX_get(ctx);
  669. s = BN_CTX_get(ctx);
  670. t = BN_CTX_get(ctx);
  671. if (t == NULL) goto err;
  672. if (a->Z_is_one)
  673. {
  674. if (!BN_copy(x0, &a->X)) goto err;
  675. if (!BN_copy(y0, &a->Y)) goto err;
  676. }
  677. else
  678. {
  679. if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
  680. }
  681. if (b->Z_is_one)
  682. {
  683. if (!BN_copy(x1, &b->X)) goto err;
  684. if (!BN_copy(y1, &b->Y)) goto err;
  685. }
  686. else
  687. {
  688. if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
  689. }
  690. if (BN_GF2m_cmp(x0, x1))
  691. {
  692. if (!BN_GF2m_add(t, x0, x1)) goto err;
  693. if (!BN_GF2m_add(s, y0, y1)) goto err;
  694. if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
  695. if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
  696. if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
  697. if (!BN_GF2m_add(x2, x2, s)) goto err;
  698. if (!BN_GF2m_add(x2, x2, t)) goto err;
  699. }
  700. else
  701. {
  702. if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
  703. {
  704. if (!EC_POINT_set_to_infinity(group, r)) goto err;
  705. ret = 1;
  706. goto err;
  707. }
  708. if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
  709. if (!BN_GF2m_add(s, s, x1)) goto err;
  710. if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
  711. if (!BN_GF2m_add(x2, x2, s)) goto err;
  712. if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
  713. }
  714. if (!BN_GF2m_add(y2, x1, x2)) goto err;
  715. if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
  716. if (!BN_GF2m_add(y2, y2, x2)) goto err;
  717. if (!BN_GF2m_add(y2, y2, y1)) goto err;
  718. if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;
  719. ret = 1;
  720. err:
  721. BN_CTX_end(ctx);
  722. if (new_ctx != NULL)
  723. BN_CTX_free(new_ctx);
  724. return ret;
  725. }
  726. /* Computes 2 * a and stores the result in r. r could be a.
  727. * Uses algorithm A.10.2 of IEEE P1363.
  728. */
  729. int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
  730. {
  731. return ec_GF2m_simple_add(group, r, a, a, ctx);
  732. }
  733. int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
  734. {
  735. if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
  736. /* point is its own inverse */
  737. return 1;
  738. if (!EC_POINT_make_affine(group, point, ctx)) return 0;
  739. return BN_GF2m_add(&point->Y, &point->X, &point->Y);
  740. }
  741. /* Indicates whether the given point is the point at infinity. */
  742. int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
  743. {
  744. return BN_is_zero(&point->Z);
  745. }
  746. /* Determines whether the given EC_POINT is an actual point on the curve defined
  747. * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
  748. * y^2 + x*y = x^3 + a*x^2 + b.
  749. */
  750. int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
  751. {
  752. int ret = -1;
  753. BN_CTX *new_ctx = NULL;
  754. BIGNUM *lh, *y2;
  755. int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
  756. int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
  757. if (EC_POINT_is_at_infinity(group, point))
  758. return 1;
  759. field_mul = group->meth->field_mul;
  760. field_sqr = group->meth->field_sqr;
  761. /* only support affine coordinates */
  762. if (!point->Z_is_one) goto err;
  763. if (ctx == NULL)
  764. {
  765. ctx = new_ctx = BN_CTX_new();
  766. if (ctx == NULL)
  767. return -1;
  768. }
  769. BN_CTX_start(ctx);
  770. y2 = BN_CTX_get(ctx);
  771. lh = BN_CTX_get(ctx);
  772. if (lh == NULL) goto err;
  773. /* We have a curve defined by a Weierstrass equation
  774. * y^2 + x*y = x^3 + a*x^2 + b.
  775. * <=> x^3 + a*x^2 + x*y + b + y^2 = 0
  776. * <=> ((x + a) * x + y ) * x + b + y^2 = 0
  777. */
  778. if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
  779. if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
  780. if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
  781. if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
  782. if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
  783. if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
  784. if (!BN_GF2m_add(lh, lh, y2)) goto err;
  785. ret = BN_is_zero(lh);
  786. err:
  787. if (ctx) BN_CTX_end(ctx);
  788. if (new_ctx) BN_CTX_free(new_ctx);
  789. return ret;
  790. }
  791. /* Indicates whether two points are equal.
  792. * Return values:
  793. * -1 error
  794. * 0 equal (in affine coordinates)
  795. * 1 not equal
  796. */
  797. int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
  798. {
  799. BIGNUM *aX, *aY, *bX, *bY;
  800. BN_CTX *new_ctx = NULL;
  801. int ret = -1;
  802. if (EC_POINT_is_at_infinity(group, a))
  803. {
  804. return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
  805. }
  806. if (a->Z_is_one && b->Z_is_one)
  807. {
  808. return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
  809. }
  810. if (ctx == NULL)
  811. {
  812. ctx = new_ctx = BN_CTX_new();
  813. if (ctx == NULL)
  814. return -1;
  815. }
  816. BN_CTX_start(ctx);
  817. aX = BN_CTX_get(ctx);
  818. aY = BN_CTX_get(ctx);
  819. bX = BN_CTX_get(ctx);
  820. bY = BN_CTX_get(ctx);
  821. if (bY == NULL) goto err;
  822. if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err;
  823. if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err;
  824. ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
  825. err:
  826. if (ctx) BN_CTX_end(ctx);
  827. if (new_ctx) BN_CTX_free(new_ctx);
  828. return ret;
  829. }
  830. /* Forces the given EC_POINT to internally use affine coordinates. */
  831. int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
  832. {
  833. BN_CTX *new_ctx = NULL;
  834. BIGNUM *x, *y;
  835. int ret = 0;
  836. if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
  837. return 1;
  838. if (ctx == NULL)
  839. {
  840. ctx = new_ctx = BN_CTX_new();
  841. if (ctx == NULL)
  842. return 0;
  843. }
  844. BN_CTX_start(ctx);
  845. x = BN_CTX_get(ctx);
  846. y = BN_CTX_get(ctx);
  847. if (y == NULL) goto err;
  848. if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
  849. if (!BN_copy(&point->X, x)) goto err;
  850. if (!BN_copy(&point->Y, y)) goto err;
  851. if (!BN_one(&point->Z)) goto err;
  852. ret = 1;
  853. err:
  854. if (ctx) BN_CTX_end(ctx);
  855. if (new_ctx) BN_CTX_free(new_ctx);
  856. return ret;
  857. }
  858. /* Forces each of the EC_POINTs in the given array to use affine coordinates. */
  859. int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
  860. {
  861. size_t i;
  862. for (i = 0; i < num; i++)
  863. {
  864. if (!group->meth->make_affine(group, points[i], ctx)) return 0;
  865. }
  866. return 1;
  867. }
  868. /* Wrapper to simple binary polynomial field multiplication implementation. */
  869. int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
  870. {
  871. return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
  872. }
  873. /* Wrapper to simple binary polynomial field squaring implementation. */
  874. int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
  875. {
  876. return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
  877. }
  878. /* Wrapper to simple binary polynomial field division implementation. */
  879. int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
  880. {
  881. return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
  882. }