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
84 static void ec_point_free(EC_POINT *point, int free_group);
85
86 static 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
113 static 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
140 static 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
173 static 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
DEFINE_METHOD_FUNCTION(struct built_in_curves,OPENSSL_built_in_curves)218 DEFINE_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
ec_group_new(const EC_METHOD * meth)272 EC_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
ec_group_set0_generator(EC_GROUP * group,EC_POINT * generator)304 static 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
EC_GROUP_new_curve_GFp(const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)317 EC_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
EC_GROUP_set_generator(EC_GROUP * group,const EC_POINT * generator,const BIGNUM * order,const BIGNUM * cofactor)341 int 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
409 err:
410 EC_POINT_free(copy);
411 BN_free(tmp);
412 return ret;
413 }
414
ec_group_new_from_data(const struct built_in_curve * curve)415 static 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
482 err:
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.
499 struct built_in_groups_st {
500 EC_GROUP *groups[OPENSSL_NUM_BUILT_IN_CURVES];
501 };
DEFINE_BSS_GET(struct built_in_groups_st,built_in_groups)502 DEFINE_BSS_GET(struct built_in_groups_st, built_in_groups)
503 DEFINE_STATIC_MUTEX(built_in_groups_lock)
504
505 EC_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
EC_GROUP_free(EC_GROUP * group)552 void 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
EC_GROUP_dup(const EC_GROUP * a)571 EC_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
EC_GROUP_cmp(const EC_GROUP * a,const EC_GROUP * b,BN_CTX * ignored)585 int 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
EC_GROUP_get0_generator(const EC_GROUP * group)612 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
613 return group->generator;
614 }
615
EC_GROUP_get0_order(const EC_GROUP * group)616 const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
617 assert(!BN_is_zero(&group->order));
618 return &group->order;
619 }
620
EC_GROUP_get_order(const EC_GROUP * group,BIGNUM * order,BN_CTX * ctx)621 int 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
EC_GROUP_order_bits(const EC_GROUP * group)628 int EC_GROUP_order_bits(const EC_GROUP *group) {
629 return BN_num_bits(&group->order);
630 }
631
EC_GROUP_get_cofactor(const EC_GROUP * group,BIGNUM * cofactor,BN_CTX * ctx)632 int 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
EC_GROUP_get_curve_GFp(const EC_GROUP * group,BIGNUM * out_p,BIGNUM * out_a,BIGNUM * out_b,BN_CTX * ctx)638 int 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
EC_GROUP_get_curve_name(const EC_GROUP * group)643 int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
644
EC_GROUP_get_degree(const EC_GROUP * group)645 unsigned EC_GROUP_get_degree(const EC_GROUP *group) {
646 return BN_num_bits(&group->field);
647 }
648
EC_curve_nid2nist(int nid)649 const 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
EC_curve_nist2nid(const char * name)663 int 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
EC_POINT_new(const EC_GROUP * group)679 EC_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
ec_point_free(EC_POINT * point,int free_group)696 static 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
EC_POINT_free(EC_POINT * point)706 void EC_POINT_free(EC_POINT *point) {
707 ec_point_free(point, 1 /* free group */);
708 }
709
EC_POINT_clear_free(EC_POINT * point)710 void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
711
EC_POINT_copy(EC_POINT * dest,const EC_POINT * src)712 int 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
EC_POINT_dup(const EC_POINT * a,const EC_GROUP * group)724 EC_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
EC_POINT_set_to_infinity(const EC_GROUP * group,EC_POINT * point)739 int 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
EC_POINT_is_at_infinity(const EC_GROUP * group,const EC_POINT * point)748 int 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
EC_POINT_is_on_curve(const EC_GROUP * group,const EC_POINT * point,BN_CTX * ctx)756 int 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
EC_POINT_cmp(const EC_GROUP * group,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)765 int 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
EC_POINT_get_affine_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)775 int 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
EC_POINT_set_affine_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)797 int 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
EC_POINT_add(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)825 int 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
EC_POINT_dbl(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,BN_CTX * ctx)837 int 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
EC_POINT_invert(const EC_GROUP * group,EC_POINT * a,BN_CTX * ctx)849 int 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
arbitrary_bignum_to_scalar(const EC_GROUP * group,EC_SCALAR * out,const BIGNUM * in,BN_CTX * ctx)858 static 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
EC_POINT_mul(const EC_GROUP * group,EC_POINT * r,const BIGNUM * g_scalar,const EC_POINT * p,const BIGNUM * p_scalar,BN_CTX * ctx)877 int 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 EC_SCALAR g_scalar_storage, p_scalar_storage;
896 EC_SCALAR *g_scalar_arg = NULL, *p_scalar_arg = NULL;
897 BN_CTX *new_ctx = NULL;
898 if (ctx == NULL) {
899 new_ctx = BN_CTX_new();
900 if (new_ctx == NULL) {
901 goto err;
902 }
903 ctx = new_ctx;
904 }
905
906 if (g_scalar != NULL) {
907 if (!arbitrary_bignum_to_scalar(group, &g_scalar_storage, g_scalar, ctx)) {
908 goto err;
909 }
910 g_scalar_arg = &g_scalar_storage;
911 }
912
913 if (p_scalar != NULL) {
914 if (!arbitrary_bignum_to_scalar(group, &p_scalar_storage, p_scalar, ctx)) {
915 goto err;
916 }
917 p_scalar_arg = &p_scalar_storage;
918 }
919
920 ret = ec_point_mul_scalar(group, &r->raw, g_scalar_arg,
921 p == NULL ? NULL : &p->raw, p_scalar_arg);
922
923 err:
924 BN_CTX_free(new_ctx);
925 OPENSSL_cleanse(&g_scalar_storage, sizeof(g_scalar_storage));
926 OPENSSL_cleanse(&p_scalar_storage, sizeof(p_scalar_storage));
927 return ret;
928 }
929
ec_point_mul_scalar_public(const EC_GROUP * group,EC_RAW_POINT * r,const EC_SCALAR * g_scalar,const EC_RAW_POINT * p,const EC_SCALAR * p_scalar)930 int ec_point_mul_scalar_public(const EC_GROUP *group, EC_RAW_POINT *r,
931 const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
932 const EC_SCALAR *p_scalar) {
933 if ((g_scalar == NULL && p_scalar == NULL) ||
934 (p == NULL) != (p_scalar == NULL)) {
935 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
936 return 0;
937 }
938
939 group->meth->mul_public(group, r, g_scalar, p, p_scalar);
940 return 1;
941 }
942
ec_point_mul_scalar(const EC_GROUP * group,EC_RAW_POINT * r,const EC_SCALAR * g_scalar,const EC_RAW_POINT * p,const EC_SCALAR * p_scalar)943 int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
944 const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
945 const EC_SCALAR *p_scalar) {
946 if ((g_scalar == NULL && p_scalar == NULL) ||
947 (p == NULL) != (p_scalar == NULL)) {
948 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
949 return 0;
950 }
951
952 group->meth->mul(group, r, g_scalar, p, p_scalar);
953 return 1;
954 }
955
ec_cmp_x_coordinate(const EC_GROUP * group,const EC_RAW_POINT * p,const EC_SCALAR * r)956 int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
957 const EC_SCALAR *r) {
958 return group->meth->cmp_x_coordinate(group, p, r);
959 }
960
ec_get_x_coordinate_as_scalar(const EC_GROUP * group,EC_SCALAR * out,const EC_RAW_POINT * p)961 int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
962 const EC_RAW_POINT *p) {
963 EC_FELEM x;
964 // For simplicity, in case of width mismatches between |group->field| and
965 // |group->order|, zero any untouched words in |x|.
966 OPENSSL_memset(&x, 0, sizeof(x));
967 if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
968 return 0;
969 }
970
971 // We must have p < 2×order, assuming p is not tiny (p >= 17). Thus rather we
972 // can reduce by performing at most one subtraction.
973 //
974 // Proof: We only work with prime order curves, so the number of points on
975 // the curve is the order. Thus Hasse's theorem gives:
976 //
977 // |order - (p + 1)| <= 2×sqrt(p)
978 // p + 1 - order <= 2×sqrt(p)
979 // p + 1 - 2×sqrt(p) <= order
980 // p + 1 - 2×(p/4) < order (p/4 > sqrt(p) for p >= 17)
981 // p/2 < p/2 + 1 < order
982 // p < 2×order
983 //
984 // Additionally, one can manually check this property for built-in curves. It
985 // is enforced for legacy custom curves in |EC_GROUP_set_generator|.
986
987 // The above does not guarantee |group->field| is not one word larger than
988 // |group->order|, so read one extra carry word.
989 BN_ULONG carry =
990 group->order.width < EC_MAX_WORDS ? x.words[group->order.width] : 0;
991 bn_reduce_once(out->words, x.words, carry, group->order.d,
992 group->order.width);
993 return 1;
994 }
995
ec_point_get_affine_coordinate_bytes(const EC_GROUP * group,uint8_t * out_x,uint8_t * out_y,size_t * out_len,size_t max_out,const EC_RAW_POINT * p)996 int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
997 uint8_t *out_y, size_t *out_len,
998 size_t max_out,
999 const EC_RAW_POINT *p) {
1000 size_t len = BN_num_bytes(&group->field);
1001 assert(len <= EC_MAX_BYTES);
1002 if (max_out < len) {
1003 OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
1004 return 0;
1005 }
1006
1007 EC_FELEM x, y;
1008 if (!group->meth->point_get_affine_coordinates(
1009 group, p, out_x == NULL ? NULL : &x, out_y == NULL ? NULL : &y)) {
1010 return 0;
1011 }
1012
1013 if (out_x != NULL) {
1014 for (size_t i = 0; i < len; i++) {
1015 out_x[i] = x.bytes[len - i - 1];
1016 }
1017 }
1018 if (out_y != NULL) {
1019 for (size_t i = 0; i < len; i++) {
1020 out_y[i] = y.bytes[len - i - 1];
1021 }
1022 }
1023 *out_len = len;
1024 return 1;
1025 }
1026
EC_GROUP_set_asn1_flag(EC_GROUP * group,int flag)1027 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
1028
EC_GROUP_method_of(const EC_GROUP * group)1029 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
1030 // This function exists purely to give callers a way to call
1031 // |EC_METHOD_get_field_type|. cryptography.io crashes if |EC_GROUP_method_of|
1032 // returns NULL, so return some other garbage pointer.
1033 return (const EC_METHOD *)0x12340000;
1034 }
1035
EC_METHOD_get_field_type(const EC_METHOD * meth)1036 int EC_METHOD_get_field_type(const EC_METHOD *meth) {
1037 return NID_X9_62_prime_field;
1038 }
1039
EC_GROUP_set_point_conversion_form(EC_GROUP * group,point_conversion_form_t form)1040 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
1041 point_conversion_form_t form) {
1042 if (form != POINT_CONVERSION_UNCOMPRESSED) {
1043 abort();
1044 }
1045 }
1046
EC_get_builtin_curves(EC_builtin_curve * out_curves,size_t max_num_curves)1047 size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
1048 size_t max_num_curves) {
1049 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
1050
1051 for (size_t i = 0; i < max_num_curves && i < OPENSSL_NUM_BUILT_IN_CURVES;
1052 i++) {
1053 out_curves[i].comment = curves->curves[i].comment;
1054 out_curves[i].nid = curves->curves[i].nid;
1055 }
1056
1057 return OPENSSL_NUM_BUILT_IN_CURVES;
1058 }
1059