1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 4e1051a39Sopenharmony_ci * 5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 6e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 9e1051a39Sopenharmony_ci */ 10e1051a39Sopenharmony_ci 11e1051a39Sopenharmony_ci/* 12e1051a39Sopenharmony_ci * ECDSA low level APIs are deprecated for public use, but still ok for 13e1051a39Sopenharmony_ci * internal use. 14e1051a39Sopenharmony_ci */ 15e1051a39Sopenharmony_ci#include "internal/deprecated.h" 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#include <openssl/err.h> 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_ci#include "ec_local.h" 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC2M 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_ci/*- 24e1051a39Sopenharmony_ci * Calculates and sets the affine coordinates of an EC_POINT from the given 25e1051a39Sopenharmony_ci * compressed coordinates. Uses algorithm 2.3.4 of SEC 1. 26e1051a39Sopenharmony_ci * Note that the simple implementation only uses affine coordinates. 27e1051a39Sopenharmony_ci * 28e1051a39Sopenharmony_ci * The method is from the following publication: 29e1051a39Sopenharmony_ci * 30e1051a39Sopenharmony_ci * Harper, Menezes, Vanstone: 31e1051a39Sopenharmony_ci * "Public-Key Cryptosystems with Very Small Key Lengths", 32e1051a39Sopenharmony_ci * EUROCRYPT '92, Springer-Verlag LNCS 658, 33e1051a39Sopenharmony_ci * published February 1993 34e1051a39Sopenharmony_ci * 35e1051a39Sopenharmony_ci * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe 36e1051a39Sopenharmony_ci * the same method, but claim no priority date earlier than July 29, 1994 37e1051a39Sopenharmony_ci * (and additionally fail to cite the EUROCRYPT '92 publication as prior art). 38e1051a39Sopenharmony_ci */ 39e1051a39Sopenharmony_ciint ossl_ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, 40e1051a39Sopenharmony_ci EC_POINT *point, 41e1051a39Sopenharmony_ci const BIGNUM *x_, int y_bit, 42e1051a39Sopenharmony_ci BN_CTX *ctx) 43e1051a39Sopenharmony_ci{ 44e1051a39Sopenharmony_ci BIGNUM *tmp, *x, *y, *z; 45e1051a39Sopenharmony_ci int ret = 0, z0; 46e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 47e1051a39Sopenharmony_ci BN_CTX *new_ctx = NULL; 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_ci if (ctx == NULL) { 50e1051a39Sopenharmony_ci ctx = new_ctx = BN_CTX_new(); 51e1051a39Sopenharmony_ci if (ctx == NULL) 52e1051a39Sopenharmony_ci return 0; 53e1051a39Sopenharmony_ci } 54e1051a39Sopenharmony_ci#endif 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci y_bit = (y_bit != 0) ? 1 : 0; 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci BN_CTX_start(ctx); 59e1051a39Sopenharmony_ci tmp = BN_CTX_get(ctx); 60e1051a39Sopenharmony_ci x = BN_CTX_get(ctx); 61e1051a39Sopenharmony_ci y = BN_CTX_get(ctx); 62e1051a39Sopenharmony_ci z = BN_CTX_get(ctx); 63e1051a39Sopenharmony_ci if (z == NULL) 64e1051a39Sopenharmony_ci goto err; 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ci if (!BN_GF2m_mod_arr(x, x_, group->poly)) 67e1051a39Sopenharmony_ci goto err; 68e1051a39Sopenharmony_ci if (BN_is_zero(x)) { 69e1051a39Sopenharmony_ci if (!BN_GF2m_mod_sqrt_arr(y, group->b, group->poly, ctx)) 70e1051a39Sopenharmony_ci goto err; 71e1051a39Sopenharmony_ci } else { 72e1051a39Sopenharmony_ci if (!group->meth->field_sqr(group, tmp, x, ctx)) 73e1051a39Sopenharmony_ci goto err; 74e1051a39Sopenharmony_ci if (!group->meth->field_div(group, tmp, group->b, tmp, ctx)) 75e1051a39Sopenharmony_ci goto err; 76e1051a39Sopenharmony_ci if (!BN_GF2m_add(tmp, group->a, tmp)) 77e1051a39Sopenharmony_ci goto err; 78e1051a39Sopenharmony_ci if (!BN_GF2m_add(tmp, x, tmp)) 79e1051a39Sopenharmony_ci goto err; 80e1051a39Sopenharmony_ci ERR_set_mark(); 81e1051a39Sopenharmony_ci if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) { 82e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 83e1051a39Sopenharmony_ci unsigned long err = ERR_peek_last_error(); 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ci if (ERR_GET_LIB(err) == ERR_LIB_BN 86e1051a39Sopenharmony_ci && ERR_GET_REASON(err) == BN_R_NO_SOLUTION) { 87e1051a39Sopenharmony_ci ERR_pop_to_mark(); 88e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT); 89e1051a39Sopenharmony_ci } else 90e1051a39Sopenharmony_ci#endif 91e1051a39Sopenharmony_ci { 92e1051a39Sopenharmony_ci ERR_clear_last_mark(); 93e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 94e1051a39Sopenharmony_ci } 95e1051a39Sopenharmony_ci goto err; 96e1051a39Sopenharmony_ci } 97e1051a39Sopenharmony_ci ERR_clear_last_mark(); 98e1051a39Sopenharmony_ci z0 = (BN_is_odd(z)) ? 1 : 0; 99e1051a39Sopenharmony_ci if (!group->meth->field_mul(group, y, x, z, ctx)) 100e1051a39Sopenharmony_ci goto err; 101e1051a39Sopenharmony_ci if (z0 != y_bit) { 102e1051a39Sopenharmony_ci if (!BN_GF2m_add(y, y, x)) 103e1051a39Sopenharmony_ci goto err; 104e1051a39Sopenharmony_ci } 105e1051a39Sopenharmony_ci } 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) 108e1051a39Sopenharmony_ci goto err; 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci ret = 1; 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci err: 113e1051a39Sopenharmony_ci BN_CTX_end(ctx); 114e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 115e1051a39Sopenharmony_ci BN_CTX_free(new_ctx); 116e1051a39Sopenharmony_ci#endif 117e1051a39Sopenharmony_ci return ret; 118e1051a39Sopenharmony_ci} 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci/* 121e1051a39Sopenharmony_ci * Converts an EC_POINT to an octet string. If buf is NULL, the encoded 122e1051a39Sopenharmony_ci * length will be returned. If the length len of buf is smaller than required 123e1051a39Sopenharmony_ci * an error will be returned. 124e1051a39Sopenharmony_ci */ 125e1051a39Sopenharmony_cisize_t ossl_ec_GF2m_simple_point2oct(const EC_GROUP *group, 126e1051a39Sopenharmony_ci const EC_POINT *point, 127e1051a39Sopenharmony_ci point_conversion_form_t form, 128e1051a39Sopenharmony_ci unsigned char *buf, size_t len, BN_CTX *ctx) 129e1051a39Sopenharmony_ci{ 130e1051a39Sopenharmony_ci size_t ret; 131e1051a39Sopenharmony_ci int used_ctx = 0; 132e1051a39Sopenharmony_ci BIGNUM *x, *y, *yxi; 133e1051a39Sopenharmony_ci size_t field_len, i, skip; 134e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 135e1051a39Sopenharmony_ci BN_CTX *new_ctx = NULL; 136e1051a39Sopenharmony_ci#endif 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci if ((form != POINT_CONVERSION_COMPRESSED) 139e1051a39Sopenharmony_ci && (form != POINT_CONVERSION_UNCOMPRESSED) 140e1051a39Sopenharmony_ci && (form != POINT_CONVERSION_HYBRID)) { 141e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM); 142e1051a39Sopenharmony_ci goto err; 143e1051a39Sopenharmony_ci } 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci if (EC_POINT_is_at_infinity(group, point)) { 146e1051a39Sopenharmony_ci /* encodes to a single 0 octet */ 147e1051a39Sopenharmony_ci if (buf != NULL) { 148e1051a39Sopenharmony_ci if (len < 1) { 149e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); 150e1051a39Sopenharmony_ci return 0; 151e1051a39Sopenharmony_ci } 152e1051a39Sopenharmony_ci buf[0] = 0; 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci return 1; 155e1051a39Sopenharmony_ci } 156e1051a39Sopenharmony_ci 157e1051a39Sopenharmony_ci /* ret := required output buffer length */ 158e1051a39Sopenharmony_ci field_len = (EC_GROUP_get_degree(group) + 7) / 8; 159e1051a39Sopenharmony_ci ret = 160e1051a39Sopenharmony_ci (form == 161e1051a39Sopenharmony_ci POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; 162e1051a39Sopenharmony_ci 163e1051a39Sopenharmony_ci /* if 'buf' is NULL, just return required length */ 164e1051a39Sopenharmony_ci if (buf != NULL) { 165e1051a39Sopenharmony_ci if (len < ret) { 166e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); 167e1051a39Sopenharmony_ci goto err; 168e1051a39Sopenharmony_ci } 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 171e1051a39Sopenharmony_ci if (ctx == NULL) { 172e1051a39Sopenharmony_ci ctx = new_ctx = BN_CTX_new(); 173e1051a39Sopenharmony_ci if (ctx == NULL) 174e1051a39Sopenharmony_ci return 0; 175e1051a39Sopenharmony_ci } 176e1051a39Sopenharmony_ci#endif 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci BN_CTX_start(ctx); 179e1051a39Sopenharmony_ci used_ctx = 1; 180e1051a39Sopenharmony_ci x = BN_CTX_get(ctx); 181e1051a39Sopenharmony_ci y = BN_CTX_get(ctx); 182e1051a39Sopenharmony_ci yxi = BN_CTX_get(ctx); 183e1051a39Sopenharmony_ci if (yxi == NULL) 184e1051a39Sopenharmony_ci goto err; 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx)) 187e1051a39Sopenharmony_ci goto err; 188e1051a39Sopenharmony_ci 189e1051a39Sopenharmony_ci buf[0] = form; 190e1051a39Sopenharmony_ci if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) { 191e1051a39Sopenharmony_ci if (!group->meth->field_div(group, yxi, y, x, ctx)) 192e1051a39Sopenharmony_ci goto err; 193e1051a39Sopenharmony_ci if (BN_is_odd(yxi)) 194e1051a39Sopenharmony_ci buf[0]++; 195e1051a39Sopenharmony_ci } 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_ci i = 1; 198e1051a39Sopenharmony_ci 199e1051a39Sopenharmony_ci skip = field_len - BN_num_bytes(x); 200e1051a39Sopenharmony_ci if (skip > field_len) { 201e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 202e1051a39Sopenharmony_ci goto err; 203e1051a39Sopenharmony_ci } 204e1051a39Sopenharmony_ci while (skip > 0) { 205e1051a39Sopenharmony_ci buf[i++] = 0; 206e1051a39Sopenharmony_ci skip--; 207e1051a39Sopenharmony_ci } 208e1051a39Sopenharmony_ci skip = BN_bn2bin(x, buf + i); 209e1051a39Sopenharmony_ci i += skip; 210e1051a39Sopenharmony_ci if (i != 1 + field_len) { 211e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 212e1051a39Sopenharmony_ci goto err; 213e1051a39Sopenharmony_ci } 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_ci if (form == POINT_CONVERSION_UNCOMPRESSED 216e1051a39Sopenharmony_ci || form == POINT_CONVERSION_HYBRID) { 217e1051a39Sopenharmony_ci skip = field_len - BN_num_bytes(y); 218e1051a39Sopenharmony_ci if (skip > field_len) { 219e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 220e1051a39Sopenharmony_ci goto err; 221e1051a39Sopenharmony_ci } 222e1051a39Sopenharmony_ci while (skip > 0) { 223e1051a39Sopenharmony_ci buf[i++] = 0; 224e1051a39Sopenharmony_ci skip--; 225e1051a39Sopenharmony_ci } 226e1051a39Sopenharmony_ci skip = BN_bn2bin(y, buf + i); 227e1051a39Sopenharmony_ci i += skip; 228e1051a39Sopenharmony_ci } 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci if (i != ret) { 231e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 232e1051a39Sopenharmony_ci goto err; 233e1051a39Sopenharmony_ci } 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ci if (used_ctx) 237e1051a39Sopenharmony_ci BN_CTX_end(ctx); 238e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 239e1051a39Sopenharmony_ci BN_CTX_free(new_ctx); 240e1051a39Sopenharmony_ci#endif 241e1051a39Sopenharmony_ci return ret; 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci err: 244e1051a39Sopenharmony_ci if (used_ctx) 245e1051a39Sopenharmony_ci BN_CTX_end(ctx); 246e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 247e1051a39Sopenharmony_ci BN_CTX_free(new_ctx); 248e1051a39Sopenharmony_ci#endif 249e1051a39Sopenharmony_ci return 0; 250e1051a39Sopenharmony_ci} 251e1051a39Sopenharmony_ci 252e1051a39Sopenharmony_ci/* 253e1051a39Sopenharmony_ci * Converts an octet string representation to an EC_POINT. Note that the 254e1051a39Sopenharmony_ci * simple implementation only uses affine coordinates. 255e1051a39Sopenharmony_ci */ 256e1051a39Sopenharmony_ciint ossl_ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, 257e1051a39Sopenharmony_ci const unsigned char *buf, size_t len, 258e1051a39Sopenharmony_ci BN_CTX *ctx) 259e1051a39Sopenharmony_ci{ 260e1051a39Sopenharmony_ci point_conversion_form_t form; 261e1051a39Sopenharmony_ci int y_bit, m; 262e1051a39Sopenharmony_ci BIGNUM *x, *y, *yxi; 263e1051a39Sopenharmony_ci size_t field_len, enc_len; 264e1051a39Sopenharmony_ci int ret = 0; 265e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 266e1051a39Sopenharmony_ci BN_CTX *new_ctx = NULL; 267e1051a39Sopenharmony_ci#endif 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci if (len == 0) { 270e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL); 271e1051a39Sopenharmony_ci return 0; 272e1051a39Sopenharmony_ci } 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci /* 275e1051a39Sopenharmony_ci * The first octet is the point converison octet PC, see X9.62, page 4 276e1051a39Sopenharmony_ci * and section 4.4.2. It must be: 277e1051a39Sopenharmony_ci * 0x00 for the point at infinity 278e1051a39Sopenharmony_ci * 0x02 or 0x03 for compressed form 279e1051a39Sopenharmony_ci * 0x04 for uncompressed form 280e1051a39Sopenharmony_ci * 0x06 or 0x07 for hybrid form. 281e1051a39Sopenharmony_ci * For compressed or hybrid forms, we store the last bit of buf[0] as 282e1051a39Sopenharmony_ci * y_bit and clear it from buf[0] so as to obtain a POINT_CONVERSION_*. 283e1051a39Sopenharmony_ci * We error if buf[0] contains any but the above values. 284e1051a39Sopenharmony_ci */ 285e1051a39Sopenharmony_ci y_bit = buf[0] & 1; 286e1051a39Sopenharmony_ci form = buf[0] & ~1U; 287e1051a39Sopenharmony_ci 288e1051a39Sopenharmony_ci if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED) 289e1051a39Sopenharmony_ci && (form != POINT_CONVERSION_UNCOMPRESSED) 290e1051a39Sopenharmony_ci && (form != POINT_CONVERSION_HYBRID)) { 291e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 292e1051a39Sopenharmony_ci return 0; 293e1051a39Sopenharmony_ci } 294e1051a39Sopenharmony_ci if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) { 295e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 296e1051a39Sopenharmony_ci return 0; 297e1051a39Sopenharmony_ci } 298e1051a39Sopenharmony_ci 299e1051a39Sopenharmony_ci /* The point at infinity is represented by a single zero octet. */ 300e1051a39Sopenharmony_ci if (form == 0) { 301e1051a39Sopenharmony_ci if (len != 1) { 302e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 303e1051a39Sopenharmony_ci return 0; 304e1051a39Sopenharmony_ci } 305e1051a39Sopenharmony_ci 306e1051a39Sopenharmony_ci return EC_POINT_set_to_infinity(group, point); 307e1051a39Sopenharmony_ci } 308e1051a39Sopenharmony_ci 309e1051a39Sopenharmony_ci m = EC_GROUP_get_degree(group); 310e1051a39Sopenharmony_ci field_len = (m + 7) / 8; 311e1051a39Sopenharmony_ci enc_len = 312e1051a39Sopenharmony_ci (form == 313e1051a39Sopenharmony_ci POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; 314e1051a39Sopenharmony_ci 315e1051a39Sopenharmony_ci if (len != enc_len) { 316e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 317e1051a39Sopenharmony_ci return 0; 318e1051a39Sopenharmony_ci } 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 321e1051a39Sopenharmony_ci if (ctx == NULL) { 322e1051a39Sopenharmony_ci ctx = new_ctx = BN_CTX_new(); 323e1051a39Sopenharmony_ci if (ctx == NULL) 324e1051a39Sopenharmony_ci return 0; 325e1051a39Sopenharmony_ci } 326e1051a39Sopenharmony_ci#endif 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_ci BN_CTX_start(ctx); 329e1051a39Sopenharmony_ci x = BN_CTX_get(ctx); 330e1051a39Sopenharmony_ci y = BN_CTX_get(ctx); 331e1051a39Sopenharmony_ci yxi = BN_CTX_get(ctx); 332e1051a39Sopenharmony_ci if (yxi == NULL) 333e1051a39Sopenharmony_ci goto err; 334e1051a39Sopenharmony_ci 335e1051a39Sopenharmony_ci if (!BN_bin2bn(buf + 1, field_len, x)) 336e1051a39Sopenharmony_ci goto err; 337e1051a39Sopenharmony_ci if (BN_num_bits(x) > m) { 338e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 339e1051a39Sopenharmony_ci goto err; 340e1051a39Sopenharmony_ci } 341e1051a39Sopenharmony_ci 342e1051a39Sopenharmony_ci if (form == POINT_CONVERSION_COMPRESSED) { 343e1051a39Sopenharmony_ci if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx)) 344e1051a39Sopenharmony_ci goto err; 345e1051a39Sopenharmony_ci } else { 346e1051a39Sopenharmony_ci if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) 347e1051a39Sopenharmony_ci goto err; 348e1051a39Sopenharmony_ci if (BN_num_bits(y) > m) { 349e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 350e1051a39Sopenharmony_ci goto err; 351e1051a39Sopenharmony_ci } 352e1051a39Sopenharmony_ci if (form == POINT_CONVERSION_HYBRID) { 353e1051a39Sopenharmony_ci /* 354e1051a39Sopenharmony_ci * Check that the form in the encoding was set correctly 355e1051a39Sopenharmony_ci * according to X9.62 4.4.2.a, 4(c), see also first paragraph 356e1051a39Sopenharmony_ci * of X9.62, 4.4.1.b. 357e1051a39Sopenharmony_ci */ 358e1051a39Sopenharmony_ci if (BN_is_zero(x)) { 359e1051a39Sopenharmony_ci if (y_bit != 0) { 360e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 361e1051a39Sopenharmony_ci goto err; 362e1051a39Sopenharmony_ci } 363e1051a39Sopenharmony_ci } else { 364e1051a39Sopenharmony_ci if (!group->meth->field_div(group, yxi, y, x, ctx)) 365e1051a39Sopenharmony_ci goto err; 366e1051a39Sopenharmony_ci if (y_bit != BN_is_odd(yxi)) { 367e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 368e1051a39Sopenharmony_ci goto err; 369e1051a39Sopenharmony_ci } 370e1051a39Sopenharmony_ci } 371e1051a39Sopenharmony_ci } 372e1051a39Sopenharmony_ci 373e1051a39Sopenharmony_ci /* 374e1051a39Sopenharmony_ci * EC_POINT_set_affine_coordinates is responsible for checking that 375e1051a39Sopenharmony_ci * the point is on the curve. 376e1051a39Sopenharmony_ci */ 377e1051a39Sopenharmony_ci if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx)) 378e1051a39Sopenharmony_ci goto err; 379e1051a39Sopenharmony_ci } 380e1051a39Sopenharmony_ci 381e1051a39Sopenharmony_ci ret = 1; 382e1051a39Sopenharmony_ci 383e1051a39Sopenharmony_ci err: 384e1051a39Sopenharmony_ci BN_CTX_end(ctx); 385e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 386e1051a39Sopenharmony_ci BN_CTX_free(new_ctx); 387e1051a39Sopenharmony_ci#endif 388e1051a39Sopenharmony_ci return ret; 389e1051a39Sopenharmony_ci} 390e1051a39Sopenharmony_ci#endif 391