1/* Originally written by Bodo Moeller for the OpenSSL project.
2 * ====================================================================
3 * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in
14 *    the documentation and/or other materials provided with the
15 *    distribution.
16 *
17 * 3. All advertising materials mentioning features or use of this
18 *    software must display the following acknowledgment:
19 *    "This product includes software developed by the OpenSSL Project
20 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21 *
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 *    endorse or promote products derived from this software without
24 *    prior written permission. For written permission, please contact
25 *    openssl-core@openssl.org.
26 *
27 * 5. Products derived from this software may not be called "OpenSSL"
28 *    nor may "OpenSSL" appear in their names without prior written
29 *    permission of the OpenSSL Project.
30 *
31 * 6. Redistributions of any form whatsoever must retain the following
32 *    acknowledgment:
33 *    "This product includes software developed by the OpenSSL Project
34 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This product includes cryptographic software written by Eric Young
51 * (eay@cryptsoft.com).  This product includes software written by Tim
52 * Hudson (tjh@cryptsoft.com).
53 *
54 */
55/* ====================================================================
56 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
57 *
58 * Portions of the attached software ("Contribution") are developed by
59 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
60 *
61 * The Contribution is licensed pursuant to the OpenSSL open source
62 * license provided above.
63 *
64 * The elliptic curve binary polynomial software is originally written by
65 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
66 * Laboratories. */
67
68#include <openssl/ec.h>
69
70#include <openssl/bn.h>
71#include <openssl/err.h>
72#include <openssl/mem.h>
73#include <openssl/obj.h>
74
75#include "internal.h"
76
77
78static const struct curve_data P224 = {
79    "NIST P-224",
80    28,
81    1,
82    {/* p */
83     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
84     0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85     0x00, 0x00, 0x00, 0x01,
86     /* a */
87     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
88     0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89     0xFF, 0xFF, 0xFF, 0xFE,
90     /* b */
91     0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
92     0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
93     0x23, 0x55, 0xFF, 0xB4,
94     /* x */
95     0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
96     0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
97     0x11, 0x5C, 0x1D, 0x21,
98     /* y */
99     0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
100     0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
101     0x85, 0x00, 0x7e, 0x34,
102     /* order */
103     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104     0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
105     0x5C, 0x5C, 0x2A, 0x3D,
106    }};
107
108static const struct curve_data P256 = {
109    "NIST P-256",
110    32,
111    1,
112    {/* p */
113     0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
114     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
115     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116     /* a */
117     0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
118     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
119     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
120     /* b */
121     0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
122     0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
123     0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,
124     /* x */
125     0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
126     0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
127     0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
128     /* y */
129     0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
130     0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
131     0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
132     /* order */
133     0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
134     0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
135     0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}};
136
137static const struct curve_data P384 = {
138    "NIST P-384",
139    48,
140    1,
141    {/* p */
142     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
143     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
144     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
145     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
146     /* a */
147     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
148     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
149     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
150     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC,
151     /* b */
152     0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
153     0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
154     0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
155     0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF,
156     /* x */
157     0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
158     0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
159     0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
160     0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
161     /* y */
162     0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
163     0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
164     0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
165     0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f,
166     /* order */
167     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
168     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
169     0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
170     0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73}};
171
172static const struct curve_data P521 = {
173    "NIST P-521",
174    66,
175    1,
176    {/* p */
177     0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
178     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
179     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
180     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
181     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
182     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
183     /* a */
184     0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
185     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
186     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
187     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
188     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
189     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
190     /* b */
191     0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
192     0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
193     0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
194     0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
195     0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
196     0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
197     /* x */
198     0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
199     0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
200     0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
201     0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
202     0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
203     0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
204     /* y */
205     0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
206     0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
207     0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
208     0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
209     0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
210     0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
211     /* order */
212     0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
213     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
214     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
215     0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
216     0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
217     0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09}};
218
219const struct built_in_curve OPENSSL_built_in_curves[] = {
220  {NID_secp224r1, &P224, 0},
221  {NID_X9_62_prime256v1, &P256, 0},
222  {NID_secp384r1, &P384, 0},
223  {NID_secp521r1, &P521, 0},
224  {NID_undef, 0, 0},
225};
226
227EC_GROUP *ec_group_new(const EC_METHOD *meth) {
228  EC_GROUP *ret;
229
230  if (meth == NULL) {
231    OPENSSL_PUT_ERROR(EC, ec_group_new, EC_R_SLOT_FULL);
232    return NULL;
233  }
234
235  if (meth->group_init == 0) {
236    OPENSSL_PUT_ERROR(EC, ec_group_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
237    return NULL;
238  }
239
240  ret = OPENSSL_malloc(sizeof(EC_GROUP));
241  if (ret == NULL) {
242    OPENSSL_PUT_ERROR(EC, ec_group_new, ERR_R_MALLOC_FAILURE);
243    return NULL;
244  }
245  memset(ret, 0, sizeof(EC_GROUP));
246
247  ret->meth = meth;
248  BN_init(&ret->order);
249  BN_init(&ret->cofactor);
250  ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
251
252  if (!meth->group_init(ret)) {
253    OPENSSL_free(ret);
254    return NULL;
255  }
256
257  return ret;
258}
259
260static EC_GROUP *ec_group_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
261                                        const BIGNUM *b, BN_CTX *ctx) {
262  const EC_METHOD *meth = EC_GFp_mont_method();
263  EC_GROUP *ret;
264
265  ret = ec_group_new(meth);
266  if (ret == NULL) {
267    return NULL;
268  }
269
270  if (ret->meth->group_set_curve == 0) {
271    OPENSSL_PUT_ERROR(EC, ec_group_new_curve_GFp,
272                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
273    return 0;
274  }
275  if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
276    EC_GROUP_free(ret);
277    return NULL;
278  }
279  return ret;
280}
281
282static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
283  EC_GROUP *group = NULL;
284  EC_POINT *P = NULL;
285  BN_CTX *ctx = NULL;
286  BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = NULL;
287  int ok = 0;
288  unsigned param_len;
289  const EC_METHOD *meth;
290  const struct curve_data *data;
291  const uint8_t *params;
292
293  if ((ctx = BN_CTX_new()) == NULL) {
294    OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_MALLOC_FAILURE);
295    goto err;
296  }
297
298  data = curve->data;
299  param_len = data->param_len;
300  params = data->data;
301
302  if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
303      !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
304      !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
305    OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
306    goto err;
307  }
308
309  if (curve->method != 0) {
310    meth = curve->method();
311    if (((group = ec_group_new(meth)) == NULL) ||
312        (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
313      OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
314      goto err;
315    }
316  } else {
317    if ((group = ec_group_new_curve_GFp(p, a, b, ctx)) == NULL) {
318      OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
319      goto err;
320    }
321  }
322
323  if ((P = EC_POINT_new(group)) == NULL) {
324    OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
325    goto err;
326  }
327
328  if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
329      !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
330    OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
331    goto err;
332  }
333
334  if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
335    OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
336    goto err;
337  }
338  if (!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) ||
339      !BN_set_word(x, (BN_ULONG)data->cofactor)) {
340    OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
341    goto err;
342  }
343
344  group->generator = P;
345  P = NULL;
346  if (!BN_copy(&group->order, order) ||
347      !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) {
348    OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
349    goto err;
350  }
351
352  ok = 1;
353
354err:
355  if (!ok) {
356    EC_GROUP_free(group);
357    group = NULL;
358  }
359  if (P)
360    EC_POINT_free(P);
361  if (ctx)
362    BN_CTX_free(ctx);
363  if (p)
364    BN_free(p);
365  if (a)
366    BN_free(a);
367  if (b)
368    BN_free(b);
369  if (order)
370    BN_free(order);
371  if (x)
372    BN_free(x);
373  if (y)
374    BN_free(y);
375  return group;
376}
377
378EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
379  unsigned i;
380  const struct built_in_curve *curve;
381  EC_GROUP *ret = NULL;
382
383  for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
384    curve = &OPENSSL_built_in_curves[i];
385    if (curve->nid == nid) {
386      ret = ec_group_new_from_data(curve);
387      break;
388    }
389  }
390
391  if (ret == NULL) {
392    OPENSSL_PUT_ERROR(EC, EC_GROUP_new_by_curve_name, EC_R_UNKNOWN_GROUP);
393    return NULL;
394  }
395
396  ret->curve_name = nid;
397  return ret;
398}
399
400void EC_GROUP_free(EC_GROUP *group) {
401  if (!group) {
402    return;
403  }
404
405  if (group->meth->group_finish != 0) {
406    group->meth->group_finish(group);
407  }
408
409  ec_pre_comp_free(group->pre_comp);
410
411  if (group->generator != NULL) {
412    EC_POINT_free(group->generator);
413  }
414  BN_free(&group->order);
415  BN_free(&group->cofactor);
416
417  OPENSSL_free(group);
418}
419
420int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) {
421  if (dest->meth->group_copy == 0) {
422    OPENSSL_PUT_ERROR(EC, EC_GROUP_copy, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
423    return 0;
424  }
425  if (dest->meth != src->meth) {
426    OPENSSL_PUT_ERROR(EC, EC_GROUP_copy, EC_R_INCOMPATIBLE_OBJECTS);
427    return 0;
428  }
429  if (dest == src) {
430    return 1;
431  }
432
433  ec_pre_comp_free(dest->pre_comp);
434  dest->pre_comp = ec_pre_comp_dup(src->pre_comp);
435
436  if (src->generator != NULL) {
437    if (dest->generator == NULL) {
438      dest->generator = EC_POINT_new(dest);
439      if (dest->generator == NULL) {
440        return 0;
441      }
442    }
443    if (!EC_POINT_copy(dest->generator, src->generator)) {
444      return 0;
445    }
446  } else {
447    /* src->generator == NULL */
448    if (dest->generator != NULL) {
449      EC_POINT_clear_free(dest->generator);
450      dest->generator = NULL;
451    }
452  }
453
454  if (!BN_copy(&dest->order, &src->order) ||
455      !BN_copy(&dest->cofactor, &src->cofactor)) {
456    return 0;
457  }
458
459  dest->curve_name = src->curve_name;
460  dest->asn1_form = src->asn1_form;
461
462  return dest->meth->group_copy(dest, src);
463}
464
465EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
466  EC_GROUP *t = NULL;
467  int ok = 0;
468
469  if (a == NULL) {
470    return NULL;
471  }
472
473  t = ec_group_new(a->meth);
474  if (t == NULL) {
475    return NULL;
476  }
477  if (!EC_GROUP_copy(t, a)) {
478    goto err;
479  }
480
481  ok = 1;
482
483err:
484  if (!ok) {
485    if (t) {
486      EC_GROUP_free(t);
487    }
488    return NULL;
489  } else {
490    return t;
491  }
492}
493
494int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b) {
495  if (a->curve_name == NID_undef || b->curve_name == NID_undef) {
496    return 0;
497  }
498  return a->curve_name == b->curve_name;
499}
500
501const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
502  return group->generator;
503}
504
505int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
506  if (!BN_copy(order, &group->order)) {
507    return 0;
508  }
509
510  return !BN_is_zero(order);
511}
512
513int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
514                          BN_CTX *ctx) {
515  if (!BN_copy(cofactor, &group->cofactor)) {
516    return 0;
517  }
518
519  return !BN_is_zero(&group->cofactor);
520}
521
522int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
523                           BIGNUM *out_b, BN_CTX *ctx) {
524  if (group->meth->group_get_curve == 0) {
525    OPENSSL_PUT_ERROR(EC, EC_GROUP_get_curve_GFp,
526                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
527    return 0;
528  }
529  return group->meth->group_get_curve(group, out_p, out_a, out_b, ctx);
530}
531
532int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
533
534int EC_GROUP_get_degree(const EC_GROUP *group) {
535  if (group->meth->group_get_degree == 0) {
536    OPENSSL_PUT_ERROR(EC, EC_GROUP_get_degree,
537                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
538    return 0;
539  }
540  return group->meth->group_get_degree(group);
541}
542
543void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
544                                        point_conversion_form_t form) {
545  group->asn1_form = form;
546}
547
548int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
549  if (group->meth->mul == 0) {
550    /* use default */
551    return ec_wNAF_precompute_mult(group, ctx);
552  }
553
554  if (group->meth->precompute_mult != 0) {
555    return group->meth->precompute_mult(group, ctx);
556  }
557
558  return 1; /* nothing to do, so report success */
559}
560
561int EC_GROUP_have_precompute_mult(const EC_GROUP *group) {
562  if (group->meth->mul == 0) {
563    /* use default */
564    return ec_wNAF_have_precompute_mult(group);
565  }
566
567  if (group->meth->have_precompute_mult != 0) {
568    return group->meth->have_precompute_mult(group);
569  }
570
571  return 0; /* cannot tell whether precomputation has been performed */
572}
573
574EC_POINT *EC_POINT_new(const EC_GROUP *group) {
575  EC_POINT *ret;
576
577  if (group == NULL) {
578    OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_PASSED_NULL_PARAMETER);
579    return NULL;
580  }
581  if (group->meth->point_init == 0) {
582    OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
583    return NULL;
584  }
585
586  ret = OPENSSL_malloc(sizeof *ret);
587  if (ret == NULL) {
588    OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_MALLOC_FAILURE);
589    return NULL;
590  }
591
592  ret->meth = group->meth;
593
594  if (!ret->meth->point_init(ret)) {
595    OPENSSL_free(ret);
596    return NULL;
597  }
598
599  return ret;
600}
601
602void EC_POINT_free(EC_POINT *point) {
603  if (!point) {
604    return;
605  }
606
607  if (point->meth->point_finish != 0) {
608    point->meth->point_finish(point);
609  }
610  OPENSSL_free(point);
611}
612
613void EC_POINT_clear_free(EC_POINT *point) {
614  if (!point) {
615    return;
616  }
617
618  if (point->meth->point_clear_finish != 0) {
619    point->meth->point_clear_finish(point);
620  } else if (point->meth->point_finish != 0) {
621    point->meth->point_finish(point);
622  }
623  OPENSSL_cleanse(point, sizeof *point);
624  OPENSSL_free(point);
625}
626
627int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
628  if (dest->meth->point_copy == 0) {
629    OPENSSL_PUT_ERROR(EC, EC_POINT_copy, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
630    return 0;
631  }
632  if (dest->meth != src->meth) {
633    OPENSSL_PUT_ERROR(EC, EC_POINT_copy, EC_R_INCOMPATIBLE_OBJECTS);
634    return 0;
635  }
636  if (dest == src) {
637    return 1;
638  }
639  return dest->meth->point_copy(dest, src);
640}
641
642EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
643  EC_POINT *t;
644  int r;
645
646  if (a == NULL) {
647    return NULL;
648  }
649
650  t = EC_POINT_new(group);
651  if (t == NULL) {
652    OPENSSL_PUT_ERROR(EC, EC_POINT_dup, ERR_R_MALLOC_FAILURE);
653    return NULL;
654  }
655  r = EC_POINT_copy(t, a);
656  if (!r) {
657    EC_POINT_free(t);
658    return NULL;
659  } else {
660    return t;
661  }
662}
663
664int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
665  if (group->meth->point_set_to_infinity == 0) {
666    OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity,
667                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
668    return 0;
669  }
670  if (group->meth != point->meth) {
671    OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity, EC_R_INCOMPATIBLE_OBJECTS);
672    return 0;
673  }
674  return group->meth->point_set_to_infinity(group, point);
675}
676
677int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
678  if (group->meth->is_at_infinity == 0) {
679    OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity,
680                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
681    return 0;
682  }
683  if (group->meth != point->meth) {
684    OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity, EC_R_INCOMPATIBLE_OBJECTS);
685    return 0;
686  }
687  return group->meth->is_at_infinity(group, point);
688}
689
690int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
691                         BN_CTX *ctx) {
692  if (group->meth->is_on_curve == 0) {
693    OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve,
694                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
695    return 0;
696  }
697  if (group->meth != point->meth) {
698    OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve, EC_R_INCOMPATIBLE_OBJECTS);
699    return 0;
700  }
701  return group->meth->is_on_curve(group, point, ctx);
702}
703
704int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
705                 BN_CTX *ctx) {
706  if (group->meth->point_cmp == 0) {
707    OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
708    return -1;
709  }
710  if ((group->meth != a->meth) || (a->meth != b->meth)) {
711    OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, EC_R_INCOMPATIBLE_OBJECTS);
712    return -1;
713  }
714  return group->meth->point_cmp(group, a, b, ctx);
715}
716
717int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
718  if (group->meth->make_affine == 0) {
719    OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine,
720                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
721    return 0;
722  }
723  if (group->meth != point->meth) {
724    OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
725    return 0;
726  }
727  return group->meth->make_affine(group, point, ctx);
728}
729
730int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
731                          BN_CTX *ctx) {
732  size_t i;
733
734  if (group->meth->points_make_affine == 0) {
735    OPENSSL_PUT_ERROR(EC, EC_POINTs_make_affine,
736                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
737    return 0;
738  }
739  for (i = 0; i < num; i++) {
740    if (group->meth != points[i]->meth) {
741      OPENSSL_PUT_ERROR(EC, EC_POINTs_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
742      return 0;
743    }
744  }
745  return group->meth->points_make_affine(group, num, points, ctx);
746}
747
748int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
749                                        const EC_POINT *point, BIGNUM *x,
750                                        BIGNUM *y, BN_CTX *ctx) {
751  if (group->meth->point_get_affine_coordinates == 0) {
752    OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
753                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
754    return 0;
755  }
756  if (group->meth != point->meth) {
757    OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
758                      EC_R_INCOMPATIBLE_OBJECTS);
759    return 0;
760  }
761  return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
762}
763
764int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
765                                        const BIGNUM *x, const BIGNUM *y,
766                                        BN_CTX *ctx) {
767  if (group->meth->point_set_affine_coordinates == 0) {
768    OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
769                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
770    return 0;
771  }
772  if (group->meth != point->meth) {
773    OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
774                      EC_R_INCOMPATIBLE_OBJECTS);
775    return 0;
776  }
777  return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
778}
779
780int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
781                 const EC_POINT *b, BN_CTX *ctx) {
782  if (group->meth->add == 0) {
783    OPENSSL_PUT_ERROR(EC, EC_POINT_add, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
784    return 0;
785  }
786  if ((group->meth != r->meth) || (r->meth != a->meth) ||
787      (a->meth != b->meth)) {
788    OPENSSL_PUT_ERROR(EC, EC_POINT_add, EC_R_INCOMPATIBLE_OBJECTS);
789    return 0;
790  }
791  return group->meth->add(group, r, a, b, ctx);
792}
793
794
795int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
796                 BN_CTX *ctx) {
797  if (group->meth->dbl == 0) {
798    OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
799    return 0;
800  }
801  if ((group->meth != r->meth) || (r->meth != a->meth)) {
802    OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, EC_R_INCOMPATIBLE_OBJECTS);
803    return 0;
804  }
805  return group->meth->dbl(group, r, a, ctx);
806}
807
808
809int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
810  if (group->meth->invert == 0) {
811    OPENSSL_PUT_ERROR(EC, EC_POINT_invert, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
812    return 0;
813  }
814  if (group->meth != a->meth) {
815    OPENSSL_PUT_ERROR(EC, EC_POINT_invert, EC_R_INCOMPATIBLE_OBJECTS);
816    return 0;
817  }
818  return group->meth->invert(group, a, ctx);
819}
820
821int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
822                 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) {
823  /* just a convenient interface to EC_POINTs_mul() */
824
825  const EC_POINT *points[1];
826  const BIGNUM *scalars[1];
827
828  points[0] = point;
829  scalars[0] = p_scalar;
830
831  return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL),
832                       points, scalars, ctx);
833}
834
835int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
836                  size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
837                  BN_CTX *ctx) {
838  if (group->meth->mul == 0) {
839    /* use default. Warning, not constant-time. */
840    return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
841  }
842
843  return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
844}
845
846int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
847                                             const BIGNUM *x, const BIGNUM *y,
848                                             const BIGNUM *z, BN_CTX *ctx) {
849  if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
850    OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
851                      ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
852    return 0;
853  }
854  if (group->meth != point->meth) {
855    OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
856                      EC_R_INCOMPATIBLE_OBJECTS);
857    return 0;
858  }
859  return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y,
860                                                            z, ctx);
861}
862