xref: /third_party/openssl/crypto/ec/ecp_oct.c (revision e1051a39)
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#include <openssl/symhacks.h>
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_ci#include "ec_local.h"
21e1051a39Sopenharmony_ci
22e1051a39Sopenharmony_ciint ossl_ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
23e1051a39Sopenharmony_ci                                                  EC_POINT *point,
24e1051a39Sopenharmony_ci                                                  const BIGNUM *x_, int y_bit,
25e1051a39Sopenharmony_ci                                                  BN_CTX *ctx)
26e1051a39Sopenharmony_ci{
27e1051a39Sopenharmony_ci    BN_CTX *new_ctx = NULL;
28e1051a39Sopenharmony_ci    BIGNUM *tmp1, *tmp2, *x, *y;
29e1051a39Sopenharmony_ci    int ret = 0;
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_ci    if (ctx == NULL) {
32e1051a39Sopenharmony_ci        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
33e1051a39Sopenharmony_ci        if (ctx == NULL)
34e1051a39Sopenharmony_ci            return 0;
35e1051a39Sopenharmony_ci    }
36e1051a39Sopenharmony_ci
37e1051a39Sopenharmony_ci    y_bit = (y_bit != 0);
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
40e1051a39Sopenharmony_ci    tmp1 = BN_CTX_get(ctx);
41e1051a39Sopenharmony_ci    tmp2 = BN_CTX_get(ctx);
42e1051a39Sopenharmony_ci    x = BN_CTX_get(ctx);
43e1051a39Sopenharmony_ci    y = BN_CTX_get(ctx);
44e1051a39Sopenharmony_ci    if (y == NULL)
45e1051a39Sopenharmony_ci        goto err;
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_ci    /*-
48e1051a39Sopenharmony_ci     * Recover y.  We have a Weierstrass equation
49e1051a39Sopenharmony_ci     *     y^2 = x^3 + a*x + b,
50e1051a39Sopenharmony_ci     * so  y  is one of the square roots of  x^3 + a*x + b.
51e1051a39Sopenharmony_ci     */
52e1051a39Sopenharmony_ci
53e1051a39Sopenharmony_ci    /* tmp1 := x^3 */
54e1051a39Sopenharmony_ci    if (!BN_nnmod(x, x_, group->field, ctx))
55e1051a39Sopenharmony_ci        goto err;
56e1051a39Sopenharmony_ci    if (group->meth->field_decode == 0) {
57e1051a39Sopenharmony_ci        /* field_{sqr,mul} work on standard representation */
58e1051a39Sopenharmony_ci        if (!group->meth->field_sqr(group, tmp2, x_, ctx))
59e1051a39Sopenharmony_ci            goto err;
60e1051a39Sopenharmony_ci        if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx))
61e1051a39Sopenharmony_ci            goto err;
62e1051a39Sopenharmony_ci    } else {
63e1051a39Sopenharmony_ci        if (!BN_mod_sqr(tmp2, x_, group->field, ctx))
64e1051a39Sopenharmony_ci            goto err;
65e1051a39Sopenharmony_ci        if (!BN_mod_mul(tmp1, tmp2, x_, group->field, ctx))
66e1051a39Sopenharmony_ci            goto err;
67e1051a39Sopenharmony_ci    }
68e1051a39Sopenharmony_ci
69e1051a39Sopenharmony_ci    /* tmp1 := tmp1 + a*x */
70e1051a39Sopenharmony_ci    if (group->a_is_minus3) {
71e1051a39Sopenharmony_ci        if (!BN_mod_lshift1_quick(tmp2, x, group->field))
72e1051a39Sopenharmony_ci            goto err;
73e1051a39Sopenharmony_ci        if (!BN_mod_add_quick(tmp2, tmp2, x, group->field))
74e1051a39Sopenharmony_ci            goto err;
75e1051a39Sopenharmony_ci        if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, group->field))
76e1051a39Sopenharmony_ci            goto err;
77e1051a39Sopenharmony_ci    } else {
78e1051a39Sopenharmony_ci        if (group->meth->field_decode) {
79e1051a39Sopenharmony_ci            if (!group->meth->field_decode(group, tmp2, group->a, ctx))
80e1051a39Sopenharmony_ci                goto err;
81e1051a39Sopenharmony_ci            if (!BN_mod_mul(tmp2, tmp2, x, group->field, ctx))
82e1051a39Sopenharmony_ci                goto err;
83e1051a39Sopenharmony_ci        } else {
84e1051a39Sopenharmony_ci            /* field_mul works on standard representation */
85e1051a39Sopenharmony_ci            if (!group->meth->field_mul(group, tmp2, group->a, x, ctx))
86e1051a39Sopenharmony_ci                goto err;
87e1051a39Sopenharmony_ci        }
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci        if (!BN_mod_add_quick(tmp1, tmp1, tmp2, group->field))
90e1051a39Sopenharmony_ci            goto err;
91e1051a39Sopenharmony_ci    }
92e1051a39Sopenharmony_ci
93e1051a39Sopenharmony_ci    /* tmp1 := tmp1 + b */
94e1051a39Sopenharmony_ci    if (group->meth->field_decode) {
95e1051a39Sopenharmony_ci        if (!group->meth->field_decode(group, tmp2, group->b, ctx))
96e1051a39Sopenharmony_ci            goto err;
97e1051a39Sopenharmony_ci        if (!BN_mod_add_quick(tmp1, tmp1, tmp2, group->field))
98e1051a39Sopenharmony_ci            goto err;
99e1051a39Sopenharmony_ci    } else {
100e1051a39Sopenharmony_ci        if (!BN_mod_add_quick(tmp1, tmp1, group->b, group->field))
101e1051a39Sopenharmony_ci            goto err;
102e1051a39Sopenharmony_ci    }
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci    ERR_set_mark();
105e1051a39Sopenharmony_ci    if (!BN_mod_sqrt(y, tmp1, group->field, ctx)) {
106e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
107e1051a39Sopenharmony_ci        unsigned long err = ERR_peek_last_error();
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ci        if (ERR_GET_LIB(err) == ERR_LIB_BN
110e1051a39Sopenharmony_ci            && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
111e1051a39Sopenharmony_ci            ERR_pop_to_mark();
112e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT);
113e1051a39Sopenharmony_ci        } else
114e1051a39Sopenharmony_ci#endif
115e1051a39Sopenharmony_ci        {
116e1051a39Sopenharmony_ci            ERR_clear_last_mark();
117e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB);
118e1051a39Sopenharmony_ci        }
119e1051a39Sopenharmony_ci        goto err;
120e1051a39Sopenharmony_ci    }
121e1051a39Sopenharmony_ci    ERR_clear_last_mark();
122e1051a39Sopenharmony_ci
123e1051a39Sopenharmony_ci    if (y_bit != BN_is_odd(y)) {
124e1051a39Sopenharmony_ci        if (BN_is_zero(y)) {
125e1051a39Sopenharmony_ci            int kron;
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ci            kron = BN_kronecker(x, group->field, ctx);
128e1051a39Sopenharmony_ci            if (kron == -2)
129e1051a39Sopenharmony_ci                goto err;
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_ci            if (kron == 1)
132e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSION_BIT);
133e1051a39Sopenharmony_ci            else
134e1051a39Sopenharmony_ci                /*
135e1051a39Sopenharmony_ci                 * BN_mod_sqrt() should have caught this error (not a square)
136e1051a39Sopenharmony_ci                 */
137e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, EC_R_INVALID_COMPRESSED_POINT);
138e1051a39Sopenharmony_ci            goto err;
139e1051a39Sopenharmony_ci        }
140e1051a39Sopenharmony_ci        if (!BN_usub(y, group->field, y))
141e1051a39Sopenharmony_ci            goto err;
142e1051a39Sopenharmony_ci    }
143e1051a39Sopenharmony_ci    if (y_bit != BN_is_odd(y)) {
144e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
145e1051a39Sopenharmony_ci        goto err;
146e1051a39Sopenharmony_ci    }
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ci    if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
149e1051a39Sopenharmony_ci        goto err;
150e1051a39Sopenharmony_ci
151e1051a39Sopenharmony_ci    ret = 1;
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ci err:
154e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
155e1051a39Sopenharmony_ci    BN_CTX_free(new_ctx);
156e1051a39Sopenharmony_ci    return ret;
157e1051a39Sopenharmony_ci}
158e1051a39Sopenharmony_ci
159e1051a39Sopenharmony_cisize_t ossl_ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
160e1051a39Sopenharmony_ci                                    point_conversion_form_t form,
161e1051a39Sopenharmony_ci                                    unsigned char *buf, size_t len, BN_CTX *ctx)
162e1051a39Sopenharmony_ci{
163e1051a39Sopenharmony_ci    size_t ret;
164e1051a39Sopenharmony_ci    BN_CTX *new_ctx = NULL;
165e1051a39Sopenharmony_ci    int used_ctx = 0;
166e1051a39Sopenharmony_ci    BIGNUM *x, *y;
167e1051a39Sopenharmony_ci    size_t field_len, i, skip;
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    if ((form != POINT_CONVERSION_COMPRESSED)
170e1051a39Sopenharmony_ci        && (form != POINT_CONVERSION_UNCOMPRESSED)
171e1051a39Sopenharmony_ci        && (form != POINT_CONVERSION_HYBRID)) {
172e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM);
173e1051a39Sopenharmony_ci        goto err;
174e1051a39Sopenharmony_ci    }
175e1051a39Sopenharmony_ci
176e1051a39Sopenharmony_ci    if (EC_POINT_is_at_infinity(group, point)) {
177e1051a39Sopenharmony_ci        /* encodes to a single 0 octet */
178e1051a39Sopenharmony_ci        if (buf != NULL) {
179e1051a39Sopenharmony_ci            if (len < 1) {
180e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
181e1051a39Sopenharmony_ci                return 0;
182e1051a39Sopenharmony_ci            }
183e1051a39Sopenharmony_ci            buf[0] = 0;
184e1051a39Sopenharmony_ci        }
185e1051a39Sopenharmony_ci        return 1;
186e1051a39Sopenharmony_ci    }
187e1051a39Sopenharmony_ci
188e1051a39Sopenharmony_ci    /* ret := required output buffer length */
189e1051a39Sopenharmony_ci    field_len = BN_num_bytes(group->field);
190e1051a39Sopenharmony_ci    ret =
191e1051a39Sopenharmony_ci        (form ==
192e1051a39Sopenharmony_ci         POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
193e1051a39Sopenharmony_ci
194e1051a39Sopenharmony_ci    /* if 'buf' is NULL, just return required length */
195e1051a39Sopenharmony_ci    if (buf != NULL) {
196e1051a39Sopenharmony_ci        if (len < ret) {
197e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
198e1051a39Sopenharmony_ci            goto err;
199e1051a39Sopenharmony_ci        }
200e1051a39Sopenharmony_ci
201e1051a39Sopenharmony_ci        if (ctx == NULL) {
202e1051a39Sopenharmony_ci            ctx = new_ctx = BN_CTX_new_ex(group->libctx);
203e1051a39Sopenharmony_ci            if (ctx == NULL)
204e1051a39Sopenharmony_ci                return 0;
205e1051a39Sopenharmony_ci        }
206e1051a39Sopenharmony_ci
207e1051a39Sopenharmony_ci        BN_CTX_start(ctx);
208e1051a39Sopenharmony_ci        used_ctx = 1;
209e1051a39Sopenharmony_ci        x = BN_CTX_get(ctx);
210e1051a39Sopenharmony_ci        y = BN_CTX_get(ctx);
211e1051a39Sopenharmony_ci        if (y == NULL)
212e1051a39Sopenharmony_ci            goto err;
213e1051a39Sopenharmony_ci
214e1051a39Sopenharmony_ci        if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
215e1051a39Sopenharmony_ci            goto err;
216e1051a39Sopenharmony_ci
217e1051a39Sopenharmony_ci        if ((form == POINT_CONVERSION_COMPRESSED
218e1051a39Sopenharmony_ci             || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
219e1051a39Sopenharmony_ci            buf[0] = form + 1;
220e1051a39Sopenharmony_ci        else
221e1051a39Sopenharmony_ci            buf[0] = form;
222e1051a39Sopenharmony_ci
223e1051a39Sopenharmony_ci        i = 1;
224e1051a39Sopenharmony_ci
225e1051a39Sopenharmony_ci        skip = field_len - BN_num_bytes(x);
226e1051a39Sopenharmony_ci        if (skip > field_len) {
227e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
228e1051a39Sopenharmony_ci            goto err;
229e1051a39Sopenharmony_ci        }
230e1051a39Sopenharmony_ci        while (skip > 0) {
231e1051a39Sopenharmony_ci            buf[i++] = 0;
232e1051a39Sopenharmony_ci            skip--;
233e1051a39Sopenharmony_ci        }
234e1051a39Sopenharmony_ci        skip = BN_bn2bin(x, buf + i);
235e1051a39Sopenharmony_ci        i += skip;
236e1051a39Sopenharmony_ci        if (i != 1 + field_len) {
237e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
238e1051a39Sopenharmony_ci            goto err;
239e1051a39Sopenharmony_ci        }
240e1051a39Sopenharmony_ci
241e1051a39Sopenharmony_ci        if (form == POINT_CONVERSION_UNCOMPRESSED
242e1051a39Sopenharmony_ci            || form == POINT_CONVERSION_HYBRID) {
243e1051a39Sopenharmony_ci            skip = field_len - BN_num_bytes(y);
244e1051a39Sopenharmony_ci            if (skip > field_len) {
245e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
246e1051a39Sopenharmony_ci                goto err;
247e1051a39Sopenharmony_ci            }
248e1051a39Sopenharmony_ci            while (skip > 0) {
249e1051a39Sopenharmony_ci                buf[i++] = 0;
250e1051a39Sopenharmony_ci                skip--;
251e1051a39Sopenharmony_ci            }
252e1051a39Sopenharmony_ci            skip = BN_bn2bin(y, buf + i);
253e1051a39Sopenharmony_ci            i += skip;
254e1051a39Sopenharmony_ci        }
255e1051a39Sopenharmony_ci
256e1051a39Sopenharmony_ci        if (i != ret) {
257e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
258e1051a39Sopenharmony_ci            goto err;
259e1051a39Sopenharmony_ci        }
260e1051a39Sopenharmony_ci    }
261e1051a39Sopenharmony_ci
262e1051a39Sopenharmony_ci    if (used_ctx)
263e1051a39Sopenharmony_ci        BN_CTX_end(ctx);
264e1051a39Sopenharmony_ci    BN_CTX_free(new_ctx);
265e1051a39Sopenharmony_ci    return ret;
266e1051a39Sopenharmony_ci
267e1051a39Sopenharmony_ci err:
268e1051a39Sopenharmony_ci    if (used_ctx)
269e1051a39Sopenharmony_ci        BN_CTX_end(ctx);
270e1051a39Sopenharmony_ci    BN_CTX_free(new_ctx);
271e1051a39Sopenharmony_ci    return 0;
272e1051a39Sopenharmony_ci}
273e1051a39Sopenharmony_ci
274e1051a39Sopenharmony_ciint ossl_ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
275e1051a39Sopenharmony_ci                                 const unsigned char *buf, size_t len,
276e1051a39Sopenharmony_ci                                 BN_CTX *ctx)
277e1051a39Sopenharmony_ci{
278e1051a39Sopenharmony_ci    point_conversion_form_t form;
279e1051a39Sopenharmony_ci    int y_bit;
280e1051a39Sopenharmony_ci    BN_CTX *new_ctx = NULL;
281e1051a39Sopenharmony_ci    BIGNUM *x, *y;
282e1051a39Sopenharmony_ci    size_t field_len, enc_len;
283e1051a39Sopenharmony_ci    int ret = 0;
284e1051a39Sopenharmony_ci
285e1051a39Sopenharmony_ci    if (len == 0) {
286e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
287e1051a39Sopenharmony_ci        return 0;
288e1051a39Sopenharmony_ci    }
289e1051a39Sopenharmony_ci    form = buf[0];
290e1051a39Sopenharmony_ci    y_bit = form & 1;
291e1051a39Sopenharmony_ci    form = form & ~1U;
292e1051a39Sopenharmony_ci    if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
293e1051a39Sopenharmony_ci        && (form != POINT_CONVERSION_UNCOMPRESSED)
294e1051a39Sopenharmony_ci        && (form != POINT_CONVERSION_HYBRID)) {
295e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
296e1051a39Sopenharmony_ci        return 0;
297e1051a39Sopenharmony_ci    }
298e1051a39Sopenharmony_ci    if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
299e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
300e1051a39Sopenharmony_ci        return 0;
301e1051a39Sopenharmony_ci    }
302e1051a39Sopenharmony_ci
303e1051a39Sopenharmony_ci    if (form == 0) {
304e1051a39Sopenharmony_ci        if (len != 1) {
305e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
306e1051a39Sopenharmony_ci            return 0;
307e1051a39Sopenharmony_ci        }
308e1051a39Sopenharmony_ci
309e1051a39Sopenharmony_ci        return EC_POINT_set_to_infinity(group, point);
310e1051a39Sopenharmony_ci    }
311e1051a39Sopenharmony_ci
312e1051a39Sopenharmony_ci    field_len = BN_num_bytes(group->field);
313e1051a39Sopenharmony_ci    enc_len =
314e1051a39Sopenharmony_ci        (form ==
315e1051a39Sopenharmony_ci         POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
316e1051a39Sopenharmony_ci
317e1051a39Sopenharmony_ci    if (len != enc_len) {
318e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
319e1051a39Sopenharmony_ci        return 0;
320e1051a39Sopenharmony_ci    }
321e1051a39Sopenharmony_ci
322e1051a39Sopenharmony_ci    if (ctx == NULL) {
323e1051a39Sopenharmony_ci        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
324e1051a39Sopenharmony_ci        if (ctx == NULL)
325e1051a39Sopenharmony_ci            return 0;
326e1051a39Sopenharmony_ci    }
327e1051a39Sopenharmony_ci
328e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
329e1051a39Sopenharmony_ci    x = BN_CTX_get(ctx);
330e1051a39Sopenharmony_ci    y = BN_CTX_get(ctx);
331e1051a39Sopenharmony_ci    if (y == NULL)
332e1051a39Sopenharmony_ci        goto err;
333e1051a39Sopenharmony_ci
334e1051a39Sopenharmony_ci    if (!BN_bin2bn(buf + 1, field_len, x))
335e1051a39Sopenharmony_ci        goto err;
336e1051a39Sopenharmony_ci    if (BN_ucmp(x, group->field) >= 0) {
337e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
338e1051a39Sopenharmony_ci        goto err;
339e1051a39Sopenharmony_ci    }
340e1051a39Sopenharmony_ci
341e1051a39Sopenharmony_ci    if (form == POINT_CONVERSION_COMPRESSED) {
342e1051a39Sopenharmony_ci        if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx))
343e1051a39Sopenharmony_ci            goto err;
344e1051a39Sopenharmony_ci    } else {
345e1051a39Sopenharmony_ci        if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
346e1051a39Sopenharmony_ci            goto err;
347e1051a39Sopenharmony_ci        if (BN_ucmp(y, group->field) >= 0) {
348e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
349e1051a39Sopenharmony_ci            goto err;
350e1051a39Sopenharmony_ci        }
351e1051a39Sopenharmony_ci        if (form == POINT_CONVERSION_HYBRID) {
352e1051a39Sopenharmony_ci            if (y_bit != BN_is_odd(y)) {
353e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
354e1051a39Sopenharmony_ci                goto err;
355e1051a39Sopenharmony_ci            }
356e1051a39Sopenharmony_ci        }
357e1051a39Sopenharmony_ci
358e1051a39Sopenharmony_ci        /*
359e1051a39Sopenharmony_ci         * EC_POINT_set_affine_coordinates is responsible for checking that
360e1051a39Sopenharmony_ci         * the point is on the curve.
361e1051a39Sopenharmony_ci         */
362e1051a39Sopenharmony_ci        if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
363e1051a39Sopenharmony_ci            goto err;
364e1051a39Sopenharmony_ci    }
365e1051a39Sopenharmony_ci
366e1051a39Sopenharmony_ci    ret = 1;
367e1051a39Sopenharmony_ci
368e1051a39Sopenharmony_ci err:
369e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
370e1051a39Sopenharmony_ci    BN_CTX_free(new_ctx);
371e1051a39Sopenharmony_ci    return ret;
372e1051a39Sopenharmony_ci}
373