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 <assert.h>
71#include <string.h>
72
73#include <openssl/bn.h>
74#include <openssl/err.h>
75#include <openssl/mem.h>
76#include <openssl/nid.h>
77
78#include "internal.h"
79#include "../../internal.h"
80#include "../bn/internal.h"
81#include "../delocate.h"
82
83
84static void ec_point_free(EC_POINT *point, int free_group);
85
86static const uint8_t kP224Params[6 * 28] = {
87 // p
88 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x01,
91 // a
92 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
93 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
94 0xFF, 0xFF, 0xFF, 0xFE,
95 // b
96 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
97 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
98 0x23, 0x55, 0xFF, 0xB4,
99 // x
100 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
101 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
102 0x11, 0x5C, 0x1D, 0x21,
103 // y
104 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
105 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
106 0x85, 0x00, 0x7e, 0x34,
107 // order
108 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
109 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
110 0x5C, 0x5C, 0x2A, 0x3D,
111};
112
113static const uint8_t kP256Params[6 * 32] = {
114 // p
115 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
117 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
118 // a
119 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
121 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
122 // b
123 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
124 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
125 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,
126 // x
127 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
128 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
129 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
130 // y
131 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
132 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
133 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
134 // order
135 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
136 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
137 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51,
138};
139
140static const uint8_t kP384Params[6 * 48] = {
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};
172
173static const uint8_t kP521Params[6 * 66] = {
174 // p
175 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
176 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
177 0xFF, 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,
181 // a
182 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
183 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
184 0xFF, 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, 0xFC,
188 // b
189 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
190 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
191 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
192 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
193 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
194 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
195 // x
196 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
197 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
198 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
199 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
200 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
201 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
202 // y
203 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
204 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
205 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
206 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
207 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
208 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
209 // order
210 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
211 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
212 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
213 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
214 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
215 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09,
216};
217
218DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) {
219 // 1.3.132.0.35
220 static const uint8_t kOIDP521[] = {0x2b, 0x81, 0x04, 0x00, 0x23};
221 out->curves[0].nid = NID_secp521r1;
222 out->curves[0].oid = kOIDP521;
223 out->curves[0].oid_len = sizeof(kOIDP521);
224 out->curves[0].comment = "NIST P-521";
225 out->curves[0].param_len = 66;
226 out->curves[0].params = kP521Params;
227 out->curves[0].method = EC_GFp_mont_method();
228
229 // 1.3.132.0.34
230 static const uint8_t kOIDP384[] = {0x2b, 0x81, 0x04, 0x00, 0x22};
231 out->curves[1].nid = NID_secp384r1;
232 out->curves[1].oid = kOIDP384;
233 out->curves[1].oid_len = sizeof(kOIDP384);
234 out->curves[1].comment = "NIST P-384";
235 out->curves[1].param_len = 48;
236 out->curves[1].params = kP384Params;
237 out->curves[1].method = EC_GFp_mont_method();
238
239 // 1.2.840.10045.3.1.7
240 static const uint8_t kOIDP256[] = {0x2a, 0x86, 0x48, 0xce,
241 0x3d, 0x03, 0x01, 0x07};
242 out->curves[2].nid = NID_X9_62_prime256v1;
243 out->curves[2].oid = kOIDP256;
244 out->curves[2].oid_len = sizeof(kOIDP256);
245 out->curves[2].comment = "NIST P-256";
246 out->curves[2].param_len = 32;
247 out->curves[2].params = kP256Params;
248 out->curves[2].method =
249#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
250 !defined(OPENSSL_SMALL)
251 EC_GFp_nistz256_method();
252#else
253 EC_GFp_nistp256_method();
254#endif
255
256 // 1.3.132.0.33
257 static const uint8_t kOIDP224[] = {0x2b, 0x81, 0x04, 0x00, 0x21};
258 out->curves[3].nid = NID_secp224r1;
259 out->curves[3].oid = kOIDP224;
260 out->curves[3].oid_len = sizeof(kOIDP224);
261 out->curves[3].comment = "NIST P-224";
262 out->curves[3].param_len = 28;
263 out->curves[3].params = kP224Params;
264 out->curves[3].method =
265#if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL)
266 EC_GFp_nistp224_method();
267#else
268 EC_GFp_mont_method();
269#endif
270}
271
272EC_GROUP *ec_group_new(const EC_METHOD *meth) {
273 EC_GROUP *ret;
274
275 if (meth == NULL) {
276 OPENSSL_PUT_ERROR(EC, EC_R_SLOT_FULL);
277 return NULL;
278 }
279
280 if (meth->group_init == 0) {
281 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
282 return NULL;
283 }
284
285 ret = OPENSSL_malloc(sizeof(EC_GROUP));
286 if (ret == NULL) {
287 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
288 return NULL;
289 }
290 OPENSSL_memset(ret, 0, sizeof(EC_GROUP));
291
292 ret->references = 1;
293 ret->meth = meth;
294 BN_init(&ret->order);
295
296 if (!meth->group_init(ret)) {
297 OPENSSL_free(ret);
298 return NULL;
299 }
300
301 return ret;
302}
303
304static void ec_group_set0_generator(EC_GROUP *group, EC_POINT *generator) {
305 assert(group->generator == NULL);
306 assert(group == generator->group);
307
308 // Avoid a reference cycle. |group->generator| does not maintain an owning
309 // pointer to |group|.
310 group->generator = generator;
311 int is_zero = CRYPTO_refcount_dec_and_test_zero(&group->references);
312
313 assert(!is_zero);
314 (void)is_zero;
315}
316
317EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
318 const BIGNUM *b, BN_CTX *ctx) {
319 if (BN_num_bytes(p) > EC_MAX_BYTES) {
320 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
321 return NULL;
322 }
323
324 EC_GROUP *ret = ec_group_new(EC_GFp_mont_method());
325 if (ret == NULL) {
326 return NULL;
327 }
328
329 if (ret->meth->group_set_curve == NULL) {
330 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
331 EC_GROUP_free(ret);
332 return NULL;
333 }
334 if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
335 EC_GROUP_free(ret);
336 return NULL;
337 }
338 return ret;
339}
340
341int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
342 const BIGNUM *order, const BIGNUM *cofactor) {
343 if (group->curve_name != NID_undef || group->generator != NULL ||
344 generator->group != group) {
345 // |EC_GROUP_set_generator| may only be used with |EC_GROUP|s returned by
346 // |EC_GROUP_new_curve_GFp| and may only used once on each group.
347 // |generator| must have been created from |EC_GROUP_new_curve_GFp|, not a
348 // copy, so that |generator->group->generator| is set correctly.
349 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
350 return 0;
351 }
352
353 if (BN_num_bytes(order) > EC_MAX_BYTES) {
354 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
355 return 0;
356 }
357
358 // Require a cofactor of one for custom curves, which implies prime order.
359 if (!BN_is_one(cofactor)) {
360 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COFACTOR);
361 return 0;
362 }
363
364 // Require that p < 2×order. This simplifies some ECDSA operations.
365 //
366 // Note any curve which did not satisfy this must have been invalid or use a
367 // tiny prime (less than 17). See the proof in |field_element_to_scalar| in
368 // the ECDSA implementation.
369 int ret = 0;
370 EC_POINT *copy = NULL;
371 BIGNUM *tmp = BN_new();
372 if (tmp == NULL ||
373 !BN_lshift1(tmp, order)) {
374 goto err;
375 }
376 if (BN_cmp(tmp, &group->field) <= 0) {
377 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
378 goto err;
379 }
380
381 copy = EC_POINT_new(group);
382 if (copy == NULL ||
383 !EC_POINT_copy(copy, generator) ||
384 !BN_copy(&group->order, order)) {
385 goto err;
386 }
387 // Store the order in minimal form, so it can be used with |BN_ULONG| arrays.
388 bn_set_minimal_width(&group->order);
389
390 BN_MONT_CTX_free(group->order_mont);
391 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
392 if (group->order_mont == NULL) {
393 goto err;
394 }
395
396 group->field_greater_than_order = BN_cmp(&group->field, &group->order) > 0;
397 if (group->field_greater_than_order) {
398 if (!BN_sub(tmp, &group->field, &group->order) ||
399 !bn_copy_words(group->field_minus_order.words, group->field.width,
400 tmp)) {
401 goto err;
402 }
403 }
404
405 ec_group_set0_generator(group, copy);
406 copy = NULL;
407 ret = 1;
408
409err:
410 EC_POINT_free(copy);
411 BN_free(tmp);
412 return ret;
413}
414
415static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
416 EC_GROUP *group = NULL;
417 EC_POINT *P = NULL;
418 BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
419 int ok = 0;
420
421 BN_CTX *ctx = BN_CTX_new();
422 if (ctx == NULL) {
423 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
424 goto err;
425 }
426
427 const unsigned param_len = curve->param_len;
428 const uint8_t *params = curve->params;
429
430 if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
431 !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
432 !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
433 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
434 goto err;
435 }
436
437 group = ec_group_new(curve->method);
438 if (group == NULL ||
439 !group->meth->group_set_curve(group, p, a, b, ctx)) {
440 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
441 goto err;
442 }
443
444 if ((P = EC_POINT_new(group)) == NULL) {
445 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
446 goto err;
447 }
448
449 if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
450 !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
451 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
452 goto err;
453 }
454
455 if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
456 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
457 goto err;
458 }
459 if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order)) {
460 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
461 goto err;
462 }
463
464 group->field_greater_than_order = BN_cmp(&group->field, &group->order) > 0;
465 if (group->field_greater_than_order) {
466 if (!BN_sub(p, &group->field, &group->order) ||
467 !bn_copy_words(group->field_minus_order.words, group->field.width, p)) {
468 goto err;
469 }
470 }
471
472 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx);
473 if (group->order_mont == NULL) {
474 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
475 goto err;
476 }
477
478 ec_group_set0_generator(group, P);
479 P = NULL;
480 ok = 1;
481
482err:
483 if (!ok) {
484 EC_GROUP_free(group);
485 group = NULL;
486 }
487 EC_POINT_free(P);
488 BN_CTX_free(ctx);
489 BN_free(p);
490 BN_free(a);
491 BN_free(b);
492 BN_free(x);
493 BN_free(y);
494 return group;
495}
496
497// Built-in groups are allocated lazily and static once allocated.
498// TODO(davidben): Make these actually static. https://crbug.com/boringssl/20.
499struct built_in_groups_st {
500 EC_GROUP *groups[OPENSSL_NUM_BUILT_IN_CURVES];
501};
502DEFINE_BSS_GET(struct built_in_groups_st, built_in_groups)
503DEFINE_STATIC_MUTEX(built_in_groups_lock)
504
505EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
506 struct built_in_groups_st *groups = built_in_groups_bss_get();
507 EC_GROUP **group_ptr = NULL;
508 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
509 const struct built_in_curve *curve = NULL;
510 for (size_t i = 0; i < OPENSSL_NUM_BUILT_IN_CURVES; i++) {
511 if (curves->curves[i].nid == nid) {
512 curve = &curves->curves[i];
513 group_ptr = &groups->groups[i];
514 break;
515 }
516 }
517
518 if (curve == NULL) {
519 OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
520 return NULL;
521 }
522
523 CRYPTO_STATIC_MUTEX_lock_read(built_in_groups_lock_bss_get());
524 EC_GROUP *ret = *group_ptr;
525 CRYPTO_STATIC_MUTEX_unlock_read(built_in_groups_lock_bss_get());
526 if (ret != NULL) {
527 return ret;
528 }
529
530 ret = ec_group_new_from_data(curve);
531 if (ret == NULL) {
532 return NULL;
533 }
534
535 EC_GROUP *to_free = NULL;
536 CRYPTO_STATIC_MUTEX_lock_write(built_in_groups_lock_bss_get());
537 if (*group_ptr == NULL) {
538 *group_ptr = ret;
539 // Filling in |ret->curve_name| makes |EC_GROUP_free| and |EC_GROUP_dup|
540 // into no-ops. At this point, |ret| is considered static.
541 ret->curve_name = nid;
542 } else {
543 to_free = ret;
544 ret = *group_ptr;
545 }
546 CRYPTO_STATIC_MUTEX_unlock_write(built_in_groups_lock_bss_get());
547
548 EC_GROUP_free(to_free);
549 return ret;
550}
551
552void EC_GROUP_free(EC_GROUP *group) {
553 if (group == NULL ||
554 // Built-in curves are static.
555 group->curve_name != NID_undef ||
556 !CRYPTO_refcount_dec_and_test_zero(&group->references)) {
557 return;
558 }
559
560 if (group->meth->group_finish != NULL) {
561 group->meth->group_finish(group);
562 }
563
564 ec_point_free(group->generator, 0 /* don't free group */);
565 BN_free(&group->order);
566 BN_MONT_CTX_free(group->order_mont);
567
568 OPENSSL_free(group);
569}
570
571EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
572 if (a == NULL ||
573 // Built-in curves are static.
574 a->curve_name != NID_undef) {
575 return (EC_GROUP *)a;
576 }
577
578 // Groups are logically immutable (but for |EC_GROUP_set_generator| which must
579 // be called early on), so we simply take a reference.
580 EC_GROUP *group = (EC_GROUP *)a;
581 CRYPTO_refcount_inc(&group->references);
582 return group;
583}
584
585int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
586 // Note this function returns 0 if equal and non-zero otherwise.
587 if (a == b) {
588 return 0;
589 }
590 if (a->curve_name != b->curve_name) {
591 return 1;
592 }
593 if (a->curve_name != NID_undef) {
594 // Built-in curves may be compared by curve name alone.
595 return 0;
596 }
597
598 // |a| and |b| are both custom curves. We compare the entire curve
599 // structure. If |a| or |b| is incomplete (due to legacy OpenSSL mistakes,
600 // custom curve construction is sadly done in two parts) but otherwise not the
601 // same object, we consider them always unequal.
602 return a->meth != b->meth ||
603 a->generator == NULL ||
604 b->generator == NULL ||
605 BN_cmp(&a->order, &b->order) != 0 ||
606 BN_cmp(&a->field, &b->field) != 0 ||
607 !ec_felem_equal(a, &a->a, &b->a) ||
608 !ec_felem_equal(a, &a->b, &b->b) ||
609 ec_GFp_simple_cmp(a, &a->generator->raw, &b->generator->raw) != 0;
610}
611
612const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
613 return group->generator;
614}
615
616const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
617 assert(!BN_is_zero(&group->order));
618 return &group->order;
619}
620
621int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
622 if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) {
623 return 0;
624 }
625 return 1;
626}
627
628int EC_GROUP_order_bits(const EC_GROUP *group) {
629 return BN_num_bits(&group->order);
630}
631
632int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
633 BN_CTX *ctx) {
634 // All |EC_GROUP|s have cofactor 1.
635 return BN_set_word(cofactor, 1);
636}
637
638int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
639 BIGNUM *out_b, BN_CTX *ctx) {
640 return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b);
641}
642
643int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
644
645unsigned EC_GROUP_get_degree(const EC_GROUP *group) {
646 return BN_num_bits(&group->field);
647}
648
649const char *EC_curve_nid2nist(int nid) {
650 switch (nid) {
651 case NID_secp224r1:
652 return "P-224";
653 case NID_X9_62_prime256v1:
654 return "P-256";
655 case NID_secp384r1:
656 return "P-384";
657 case NID_secp521r1:
658 return "P-521";
659 }
660 return NULL;
661}
662
663int EC_curve_nist2nid(const char *name) {
664 if (strcmp(name, "P-224") == 0) {
665 return NID_secp224r1;
666 }
667 if (strcmp(name, "P-256") == 0) {
668 return NID_X9_62_prime256v1;
669 }
670 if (strcmp(name, "P-384") == 0) {
671 return NID_secp384r1;
672 }
673 if (strcmp(name, "P-521") == 0) {
674 return NID_secp521r1;
675 }
676 return NID_undef;
677}
678
679EC_POINT *EC_POINT_new(const EC_GROUP *group) {
680 if (group == NULL) {
681 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
682 return NULL;
683 }
684
685 EC_POINT *ret = OPENSSL_malloc(sizeof *ret);
686 if (ret == NULL) {
687 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
688 return NULL;
689 }
690
691 ret->group = EC_GROUP_dup(group);
692 ec_GFp_simple_point_init(&ret->raw);
693 return ret;
694}
695
696static void ec_point_free(EC_POINT *point, int free_group) {
697 if (!point) {
698 return;
699 }
700 if (free_group) {
701 EC_GROUP_free(point->group);
702 }
703 OPENSSL_free(point);
704}
705
706void EC_POINT_free(EC_POINT *point) {
707 ec_point_free(point, 1 /* free group */);
708}
709
710void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
711
712int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
713 if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) {
714 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
715 return 0;
716 }
717 if (dest == src) {
718 return 1;
719 }
720 ec_GFp_simple_point_copy(&dest->raw, &src->raw);
721 return 1;
722}
723
724EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
725 if (a == NULL) {
726 return NULL;
727 }
728
729 EC_POINT *ret = EC_POINT_new(group);
730 if (ret == NULL ||
731 !EC_POINT_copy(ret, a)) {
732 EC_POINT_free(ret);
733 return NULL;
734 }
735
736 return ret;
737}
738
739int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
740 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
741 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
742 return 0;
743 }
744 ec_GFp_simple_point_set_to_infinity(group, &point->raw);
745 return 1;
746}
747
748int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
749 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
750 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
751 return 0;
752 }
753 return ec_GFp_simple_is_at_infinity(group, &point->raw);
754}
755
756int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
757 BN_CTX *ctx) {
758 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
759 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
760 return 0;
761 }
762 return ec_GFp_simple_is_on_curve(group, &point->raw);
763}
764
765int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
766 BN_CTX *ctx) {
767 if (EC_GROUP_cmp(group, a->group, NULL) != 0 ||
768 EC_GROUP_cmp(group, b->group, NULL) != 0) {
769 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
770 return -1;
771 }
772 return ec_GFp_simple_cmp(group, &a->raw, &b->raw);
773}
774
775int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
776 const EC_POINT *point, BIGNUM *x,
777 BIGNUM *y, BN_CTX *ctx) {
778 if (group->meth->point_get_affine_coordinates == 0) {
779 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
780 return 0;
781 }
782 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
783 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
784 return 0;
785 }
786 EC_FELEM x_felem, y_felem;
787 if (!group->meth->point_get_affine_coordinates(group, &point->raw,
788 x == NULL ? NULL : &x_felem,
789 y == NULL ? NULL : &y_felem) ||
790 (x != NULL && !bn_set_words(x, x_felem.words, group->field.width)) ||
791 (y != NULL && !bn_set_words(y, y_felem.words, group->field.width))) {
792 return 0;
793 }
794 return 1;
795}
796
797int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
798 const BIGNUM *x, const BIGNUM *y,
799 BN_CTX *ctx) {
800 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
801 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
802 return 0;
803 }
804 if (!ec_GFp_simple_point_set_affine_coordinates(group, &point->raw, x, y)) {
805 return 0;
806 }
807
808 if (!EC_POINT_is_on_curve(group, point, ctx)) {
809 // In the event of an error, defend against the caller not checking the
810 // return value by setting a known safe value: the base point.
811 const EC_POINT *generator = EC_GROUP_get0_generator(group);
812 // The generator can be missing if the caller is in the process of
813 // constructing an arbitrary group. In this, we give up and hope they're
814 // checking the return value.
815 if (generator) {
816 ec_GFp_simple_point_copy(&point->raw, &generator->raw);
817 }
818 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
819 return 0;
820 }
821
822 return 1;
823}
824
825int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
826 const EC_POINT *b, BN_CTX *ctx) {
827 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
828 EC_GROUP_cmp(group, a->group, NULL) != 0 ||
829 EC_GROUP_cmp(group, b->group, NULL) != 0) {
830 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
831 return 0;
832 }
833 group->meth->add(group, &r->raw, &a->raw, &b->raw);
834 return 1;
835}
836
837int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
838 BN_CTX *ctx) {
839 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
840 EC_GROUP_cmp(group, a->group, NULL) != 0) {
841 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
842 return 0;
843 }
844 group->meth->dbl(group, &r->raw, &a->raw);
845 return 1;
846}
847
848
849int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
850 if (EC_GROUP_cmp(group, a->group, NULL) != 0) {
851 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
852 return 0;
853 }
854 ec_GFp_simple_invert(group, &a->raw);
855 return 1;
856}
857
858static int arbitrary_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
859 const BIGNUM *in, BN_CTX *ctx) {
860 if (ec_bignum_to_scalar(group, out, in)) {
861 return 1;
862 }
863
864 ERR_clear_error();
865
866 // This is an unusual input, so we do not guarantee constant-time processing.
867 const BIGNUM *order = &group->order;
868 BN_CTX_start(ctx);
869 BIGNUM *tmp = BN_CTX_get(ctx);
870 int ok = tmp != NULL &&
871 BN_nnmod(tmp, in, order, ctx) &&
872 ec_bignum_to_scalar(group, out, tmp);
873 BN_CTX_end(ctx);
874 return ok;
875}
876
877int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
878 const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
879 // Previously, this function set |r| to the point at infinity if there was
880 // nothing to multiply. But, nobody should be calling this function with
881 // nothing to multiply in the first place.
882 if ((g_scalar == NULL && p_scalar == NULL) ||
883 (p == NULL) != (p_scalar == NULL)) {
884 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
885 return 0;
886 }
887
888 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
889 (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
890 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
891 return 0;
892 }
893
894 int ret = 0;
895 BN_CTX *new_ctx = NULL;
896 if (ctx == NULL) {
897 new_ctx = BN_CTX_new();
898 if (new_ctx == NULL) {
899 goto err;
900 }
901 ctx = new_ctx;
902 }
903
904 // If both |g_scalar| and |p_scalar| are non-NULL,
905 // |ec_point_mul_scalar_public| would share the doublings between the two
906 // products, which would be more efficient. However, we conservatively assume
907 // the caller needs a constant-time operation. (ECDSA verification does not
908 // use this function.)
909 //
910 // Previously, the low-level constant-time multiplication function aligned
911 // with this function's calling convention, but this was misleading. Curves
912 // which combined the two multiplications did not avoid the doubling case
913 // in the incomplete addition formula and were not constant-time.
914
915 if (g_scalar != NULL) {
916 EC_SCALAR scalar;
917 if (!arbitrary_bignum_to_scalar(group, &scalar, g_scalar, ctx) ||
918 !ec_point_mul_scalar_base(group, &r->raw, &scalar)) {
919 goto err;
920 }
921 }
922
923 if (p_scalar != NULL) {
924 EC_SCALAR scalar;
925 EC_RAW_POINT tmp;
926 if (!arbitrary_bignum_to_scalar(group, &scalar, p_scalar, ctx) ||
927 !ec_point_mul_scalar(group, &tmp, &p->raw, &scalar)) {
928 goto err;
929 }
930 if (g_scalar == NULL) {
931 OPENSSL_memcpy(&r->raw, &tmp, sizeof(EC_RAW_POINT));
932 } else {
933 group->meth->add(group, &r->raw, &r->raw, &tmp);
934 }
935 }
936
937 ret = 1;
938
939err:
940 BN_CTX_free(new_ctx);
941 return ret;
942}
943
944int ec_point_mul_scalar_public(const EC_GROUP *group, EC_RAW_POINT *r,
945 const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
946 const EC_SCALAR *p_scalar) {
947 if (g_scalar == NULL || p_scalar == NULL || p == NULL) {
948 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
949 return 0;
950 }
951
952 group->meth->mul_public(group, r, g_scalar, p, p_scalar);
953 return 1;
954}
955
956int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
957 const EC_RAW_POINT *p, const EC_SCALAR *scalar) {
958 if (p == NULL || scalar == NULL) {
959 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
960 return 0;
961 }
962
963 group->meth->mul(group, r, p, scalar);
964 return 1;
965}
966
967int ec_point_mul_scalar_base(const EC_GROUP *group, EC_RAW_POINT *r,
968 const EC_SCALAR *scalar) {
969 if (scalar == NULL) {
970 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
971 return 0;
972 }
973
974 group->meth->mul_base(group, r, scalar);
975 return 1;
976}
977
978int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
979 const EC_SCALAR *r) {
980 return group->meth->cmp_x_coordinate(group, p, r);
981}
982
983int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
984 const EC_RAW_POINT *p) {
985 EC_FELEM x;
986 // For simplicity, in case of width mismatches between |group->field| and
987 // |group->order|, zero any untouched words in |x|.
988 OPENSSL_memset(&x, 0, sizeof(x));
989 if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
990 return 0;
991 }
992
993 // We must have p < 2×order, assuming p is not tiny (p >= 17). Thus rather we
994 // can reduce by performing at most one subtraction.
995 //
996 // Proof: We only work with prime order curves, so the number of points on
997 // the curve is the order. Thus Hasse's theorem gives:
998 //
999 // |order - (p + 1)| <= 2×sqrt(p)
1000 // p + 1 - order <= 2×sqrt(p)
1001 // p + 1 - 2×sqrt(p) <= order
1002 // p + 1 - 2×(p/4) < order (p/4 > sqrt(p) for p >= 17)
1003 // p/2 < p/2 + 1 < order
1004 // p < 2×order
1005 //
1006 // Additionally, one can manually check this property for built-in curves. It
1007 // is enforced for legacy custom curves in |EC_GROUP_set_generator|.
1008
1009 // The above does not guarantee |group->field| is not one word larger than
1010 // |group->order|, so read one extra carry word.
1011 BN_ULONG carry =
1012 group->order.width < EC_MAX_WORDS ? x.words[group->order.width] : 0;
1013 bn_reduce_once(out->words, x.words, carry, group->order.d,
1014 group->order.width);
1015 return 1;
1016}
1017
1018int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
1019 uint8_t *out_y, size_t *out_len,
1020 size_t max_out,
1021 const EC_RAW_POINT *p) {
1022 size_t len = BN_num_bytes(&group->field);
1023 assert(len <= EC_MAX_BYTES);
1024 if (max_out < len) {
1025 OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
1026 return 0;
1027 }
1028
1029 EC_FELEM x, y;
1030 if (!group->meth->point_get_affine_coordinates(
1031 group, p, out_x == NULL ? NULL : &x, out_y == NULL ? NULL : &y)) {
1032 return 0;
1033 }
1034
1035 if (out_x != NULL) {
1036 for (size_t i = 0; i < len; i++) {
1037 out_x[i] = x.bytes[len - i - 1];
1038 }
1039 }
1040 if (out_y != NULL) {
1041 for (size_t i = 0; i < len; i++) {
1042 out_y[i] = y.bytes[len - i - 1];
1043 }
1044 }
1045 *out_len = len;
1046 return 1;
1047}
1048
1049void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
1050
1051const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
1052 // This function exists purely to give callers a way to call
1053 // |EC_METHOD_get_field_type|. cryptography.io crashes if |EC_GROUP_method_of|
1054 // returns NULL, so return some other garbage pointer.
1055 return (const EC_METHOD *)0x12340000;
1056}
1057
1058int EC_METHOD_get_field_type(const EC_METHOD *meth) {
1059 return NID_X9_62_prime_field;
1060}
1061
1062void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
1063 point_conversion_form_t form) {
1064 if (form != POINT_CONVERSION_UNCOMPRESSED) {
1065 abort();
1066 }
1067}
1068
1069size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
1070 size_t max_num_curves) {
1071 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
1072
1073 for (size_t i = 0; i < max_num_curves && i < OPENSSL_NUM_BUILT_IN_CURVES;
1074 i++) {
1075 out_curves[i].comment = curves->curves[i].comment;
1076 out_curves[i].nid = curves->curves[i].nid;
1077 }
1078
1079 return OPENSSL_NUM_BUILT_IN_CURVES;
1080}
1081