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