Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

417 рядки
12 KiB

  1. /* Originally written by Bodo Moeller for the OpenSSL project.
  2. * ====================================================================
  3. * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in
  14. * the documentation and/or other materials provided with the
  15. * distribution.
  16. *
  17. * 3. All advertising materials mentioning features or use of this
  18. * software must display the following acknowledgment:
  19. * "This product includes software developed by the OpenSSL Project
  20. * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  21. *
  22. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  23. * endorse or promote products derived from this software without
  24. * prior written permission. For written permission, please contact
  25. * openssl-core@openssl.org.
  26. *
  27. * 5. Products derived from this software may not be called "OpenSSL"
  28. * nor may "OpenSSL" appear in their names without prior written
  29. * permission of the OpenSSL Project.
  30. *
  31. * 6. Redistributions of any form whatsoever must retain the following
  32. * acknowledgment:
  33. * "This product includes software developed by the OpenSSL Project
  34. * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  35. *
  36. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  37. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  38. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  39. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  42. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  43. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  44. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  45. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  46. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  47. * OF THE POSSIBILITY OF SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This product includes cryptographic software written by Eric Young
  51. * (eay@cryptsoft.com). This product includes software written by Tim
  52. * Hudson (tjh@cryptsoft.com).
  53. *
  54. */
  55. /* ====================================================================
  56. * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  57. *
  58. * Portions of the attached software ("Contribution") are developed by
  59. * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
  60. *
  61. * The Contribution is licensed pursuant to the OpenSSL open source
  62. * license provided above.
  63. *
  64. * The elliptic curve binary polynomial software is originally written by
  65. * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
  66. * Laboratories. */
  67. #include <openssl/ec.h>
  68. #include <openssl/bn.h>
  69. #include <openssl/bytestring.h>
  70. #include <openssl/err.h>
  71. #include "internal.h"
  72. static size_t ec_GFp_simple_point2oct(const EC_GROUP *group,
  73. const EC_POINT *point,
  74. point_conversion_form_t form,
  75. uint8_t *buf, size_t len, BN_CTX *ctx) {
  76. size_t ret;
  77. BN_CTX *new_ctx = NULL;
  78. int used_ctx = 0;
  79. BIGNUM *x, *y;
  80. size_t field_len, i;
  81. if ((form != POINT_CONVERSION_COMPRESSED) &&
  82. (form != POINT_CONVERSION_UNCOMPRESSED)) {
  83. OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
  84. goto err;
  85. }
  86. if (EC_POINT_is_at_infinity(group, point)) {
  87. OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
  88. goto err;
  89. }
  90. /* ret := required output buffer length */
  91. field_len = BN_num_bytes(&group->field);
  92. ret =
  93. (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
  94. /* if 'buf' is NULL, just return required length */
  95. if (buf != NULL) {
  96. if (len < ret) {
  97. OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
  98. goto err;
  99. }
  100. if (ctx == NULL) {
  101. ctx = new_ctx = BN_CTX_new();
  102. if (ctx == NULL) {
  103. goto err;
  104. }
  105. }
  106. BN_CTX_start(ctx);
  107. used_ctx = 1;
  108. x = BN_CTX_get(ctx);
  109. y = BN_CTX_get(ctx);
  110. if (y == NULL) {
  111. goto err;
  112. }
  113. if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) {
  114. goto err;
  115. }
  116. if ((form == POINT_CONVERSION_COMPRESSED) &&
  117. BN_is_odd(y)) {
  118. buf[0] = form + 1;
  119. } else {
  120. buf[0] = form;
  121. }
  122. i = 1;
  123. if (!BN_bn2bin_padded(buf + i, field_len, x)) {
  124. OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
  125. goto err;
  126. }
  127. i += field_len;
  128. if (form == POINT_CONVERSION_UNCOMPRESSED) {
  129. if (!BN_bn2bin_padded(buf + i, field_len, y)) {
  130. OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
  131. goto err;
  132. }
  133. i += field_len;
  134. }
  135. if (i != ret) {
  136. OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
  137. goto err;
  138. }
  139. }
  140. if (used_ctx) {
  141. BN_CTX_end(ctx);
  142. }
  143. BN_CTX_free(new_ctx);
  144. return ret;
  145. err:
  146. if (used_ctx) {
  147. BN_CTX_end(ctx);
  148. }
  149. BN_CTX_free(new_ctx);
  150. return 0;
  151. }
  152. static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
  153. const uint8_t *buf, size_t len,
  154. BN_CTX *ctx) {
  155. point_conversion_form_t form;
  156. int y_bit;
  157. BN_CTX *new_ctx = NULL;
  158. BIGNUM *x, *y;
  159. size_t field_len, enc_len;
  160. int ret = 0;
  161. if (len == 0) {
  162. OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
  163. return 0;
  164. }
  165. form = buf[0];
  166. y_bit = form & 1;
  167. form = form & ~1U;
  168. if ((form != POINT_CONVERSION_COMPRESSED &&
  169. form != POINT_CONVERSION_UNCOMPRESSED) ||
  170. (form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) {
  171. OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
  172. return 0;
  173. }
  174. field_len = BN_num_bytes(&group->field);
  175. enc_len =
  176. (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
  177. if (len != enc_len) {
  178. OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
  179. return 0;
  180. }
  181. if (ctx == NULL) {
  182. ctx = new_ctx = BN_CTX_new();
  183. if (ctx == NULL) {
  184. return 0;
  185. }
  186. }
  187. BN_CTX_start(ctx);
  188. x = BN_CTX_get(ctx);
  189. y = BN_CTX_get(ctx);
  190. if (x == NULL || y == NULL) {
  191. goto err;
  192. }
  193. if (!BN_bin2bn(buf + 1, field_len, x)) {
  194. goto err;
  195. }
  196. if (BN_ucmp(x, &group->field) >= 0) {
  197. OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
  198. goto err;
  199. }
  200. if (form == POINT_CONVERSION_COMPRESSED) {
  201. if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) {
  202. goto err;
  203. }
  204. } else {
  205. if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) {
  206. goto err;
  207. }
  208. if (BN_ucmp(y, &group->field) >= 0) {
  209. OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
  210. goto err;
  211. }
  212. if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
  213. goto err;
  214. }
  215. }
  216. ret = 1;
  217. err:
  218. BN_CTX_end(ctx);
  219. BN_CTX_free(new_ctx);
  220. return ret;
  221. }
  222. int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
  223. const uint8_t *buf, size_t len, BN_CTX *ctx) {
  224. if (group->meth != point->meth) {
  225. OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
  226. return 0;
  227. }
  228. return ec_GFp_simple_oct2point(group, point, buf, len, ctx);
  229. }
  230. size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
  231. point_conversion_form_t form, uint8_t *buf,
  232. size_t len, BN_CTX *ctx) {
  233. if (group->meth != point->meth) {
  234. OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
  235. return 0;
  236. }
  237. return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
  238. }
  239. int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point,
  240. point_conversion_form_t form, BN_CTX *ctx) {
  241. size_t len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx);
  242. if (len == 0) {
  243. return 0;
  244. }
  245. uint8_t *p;
  246. return CBB_add_space(out, &p, len) &&
  247. EC_POINT_point2oct(group, point, form, p, len, ctx) == len;
  248. }
  249. int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
  250. EC_POINT *point, const BIGNUM *x,
  251. int y_bit, BN_CTX *ctx) {
  252. if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) {
  253. OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT);
  254. return 0;
  255. }
  256. BN_CTX *new_ctx = NULL;
  257. BIGNUM *tmp1, *tmp2, *y;
  258. int ret = 0;
  259. ERR_clear_error();
  260. if (ctx == NULL) {
  261. ctx = new_ctx = BN_CTX_new();
  262. if (ctx == NULL) {
  263. return 0;
  264. }
  265. }
  266. y_bit = (y_bit != 0);
  267. BN_CTX_start(ctx);
  268. tmp1 = BN_CTX_get(ctx);
  269. tmp2 = BN_CTX_get(ctx);
  270. y = BN_CTX_get(ctx);
  271. if (y == NULL) {
  272. goto err;
  273. }
  274. /* Recover y. We have a Weierstrass equation
  275. * y^2 = x^3 + a*x + b,
  276. * so y is one of the square roots of x^3 + a*x + b. */
  277. /* tmp1 := x^3 */
  278. if (group->meth->field_decode == 0) {
  279. /* field_{sqr,mul} work on standard representation */
  280. if (!group->meth->field_sqr(group, tmp2, x, ctx) ||
  281. !group->meth->field_mul(group, tmp1, tmp2, x, ctx)) {
  282. goto err;
  283. }
  284. } else {
  285. if (!BN_mod_sqr(tmp2, x, &group->field, ctx) ||
  286. !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) {
  287. goto err;
  288. }
  289. }
  290. /* tmp1 := tmp1 + a*x */
  291. if (group->a_is_minus3) {
  292. if (!BN_mod_lshift1_quick(tmp2, x, &group->field) ||
  293. !BN_mod_add_quick(tmp2, tmp2, x, &group->field) ||
  294. !BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) {
  295. goto err;
  296. }
  297. } else {
  298. if (group->meth->field_decode) {
  299. if (!group->meth->field_decode(group, tmp2, &group->a, ctx) ||
  300. !BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) {
  301. goto err;
  302. }
  303. } else {
  304. /* field_mul works on standard representation */
  305. if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) {
  306. goto err;
  307. }
  308. }
  309. if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) {
  310. goto err;
  311. }
  312. }
  313. /* tmp1 := tmp1 + b */
  314. if (group->meth->field_decode) {
  315. if (!group->meth->field_decode(group, tmp2, &group->b, ctx) ||
  316. !BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) {
  317. goto err;
  318. }
  319. } else {
  320. if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) {
  321. goto err;
  322. }
  323. }
  324. if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) {
  325. unsigned long err = ERR_peek_last_error();
  326. if (ERR_GET_LIB(err) == ERR_LIB_BN &&
  327. ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
  328. ERR_clear_error();
  329. OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT);
  330. } else {
  331. OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
  332. }
  333. goto err;
  334. }
  335. if (y_bit != BN_is_odd(y)) {
  336. if (BN_is_zero(y)) {
  337. OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
  338. goto err;
  339. }
  340. if (!BN_usub(y, &group->field, y)) {
  341. goto err;
  342. }
  343. }
  344. if (y_bit != BN_is_odd(y)) {
  345. OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
  346. goto err;
  347. }
  348. if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
  349. goto err;
  350. }
  351. ret = 1;
  352. err:
  353. BN_CTX_end(ctx);
  354. BN_CTX_free(new_ctx);
  355. return ret;
  356. }
  357. int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
  358. EC_POINT *point, const BIGNUM *x,
  359. int y_bit, BN_CTX *ctx) {
  360. if (group->meth != point->meth) {
  361. OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
  362. return 0;
  363. }
  364. return ec_GFp_simple_set_compressed_coordinates(group, point, x, y_bit, ctx);
  365. }