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