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_SCALAR_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 // Additionally, |generator| must been created from
348 // |EC_GROUP_new_curve_GFp|, not a copy, so that
349 // |generator->group->generator| is set correctly.
350 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
351 return 0;
352 }
353
354 if (BN_num_bytes(order) > EC_MAX_SCALAR_BYTES) {
355 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
356 return 0;
357 }
358
359 // Require a cofactor of one for custom curves, which implies prime order.
360 if (!BN_is_one(cofactor)) {
361 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COFACTOR);
362 return 0;
363 }
364
365 // Require that p < 2×order. This simplifies some ECDSA operations.
366 //
367 // Note any curve which did not satisfy this must have been invalid or use a
368 // tiny prime (less than 17). See the proof in |field_element_to_scalar| in
369 // the ECDSA implementation.
370 BIGNUM *tmp = BN_new();
371 if (tmp == NULL ||
372 !BN_lshift1(tmp, order)) {
373 BN_free(tmp);
374 return 0;
375 }
376 int ok = BN_cmp(tmp, &group->field) > 0;
377 BN_free(tmp);
378 if (!ok) {
379 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
380 return 0;
381 }
382
383 EC_POINT *copy = EC_POINT_new(group);
384 if (copy == NULL ||
385 !EC_POINT_copy(copy, generator) ||
386 !BN_copy(&group->order, order)) {
387 EC_POINT_free(copy);
388 return 0;
389 }
390
391 BN_MONT_CTX_free(group->order_mont);
392 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
393 if (group->order_mont == NULL) {
394 return 0;
395 }
396
397 ec_group_set0_generator(group, copy);
398 return 1;
399 }
400
ec_group_new_from_data(const struct built_in_curve * curve)401 static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
402 EC_GROUP *group = NULL;
403 EC_POINT *P = NULL;
404 BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
405 int ok = 0;
406
407 BN_CTX *ctx = BN_CTX_new();
408 if (ctx == NULL) {
409 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
410 goto err;
411 }
412
413 const unsigned param_len = curve->param_len;
414 const uint8_t *params = curve->params;
415
416 if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
417 !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
418 !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
419 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
420 goto err;
421 }
422
423 group = ec_group_new(curve->method);
424 if (group == NULL ||
425 !group->meth->group_set_curve(group, p, a, b, ctx)) {
426 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
427 goto err;
428 }
429
430 if ((P = EC_POINT_new(group)) == NULL) {
431 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
432 goto err;
433 }
434
435 if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
436 !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
437 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
438 goto err;
439 }
440
441 if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
442 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
443 goto err;
444 }
445 if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order)) {
446 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
447 goto err;
448 }
449
450 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx);
451 if (group->order_mont == NULL) {
452 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
453 goto err;
454 }
455
456 ec_group_set0_generator(group, P);
457 P = NULL;
458 ok = 1;
459
460 err:
461 if (!ok) {
462 EC_GROUP_free(group);
463 group = NULL;
464 }
465 EC_POINT_free(P);
466 BN_CTX_free(ctx);
467 BN_free(p);
468 BN_free(a);
469 BN_free(b);
470 BN_free(x);
471 BN_free(y);
472 return group;
473 }
474
475 // Built-in groups are allocated lazily and static once allocated.
476 // TODO(davidben): Make these actually static. https://crbug.com/boringssl/20.
477 struct built_in_groups_st {
478 EC_GROUP *groups[OPENSSL_NUM_BUILT_IN_CURVES];
479 };
480 DEFINE_BSS_GET(struct built_in_groups_st, built_in_groups);
481 DEFINE_STATIC_MUTEX(built_in_groups_lock);
482
EC_GROUP_new_by_curve_name(int nid)483 EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
484 struct built_in_groups_st *groups = built_in_groups_bss_get();
485 EC_GROUP **group_ptr = NULL;
486 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
487 const struct built_in_curve *curve = NULL;
488 for (size_t i = 0; i < OPENSSL_NUM_BUILT_IN_CURVES; i++) {
489 if (curves->curves[i].nid == nid) {
490 curve = &curves->curves[i];
491 group_ptr = &groups->groups[i];
492 break;
493 }
494 }
495
496 if (curve == NULL) {
497 OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
498 return NULL;
499 }
500
501 CRYPTO_STATIC_MUTEX_lock_read(built_in_groups_lock_bss_get());
502 EC_GROUP *ret = *group_ptr;
503 CRYPTO_STATIC_MUTEX_unlock_read(built_in_groups_lock_bss_get());
504 if (ret != NULL) {
505 return ret;
506 }
507
508 ret = ec_group_new_from_data(curve);
509 if (ret == NULL) {
510 return NULL;
511 }
512
513 EC_GROUP *to_free = NULL;
514 CRYPTO_STATIC_MUTEX_lock_write(built_in_groups_lock_bss_get());
515 if (*group_ptr == NULL) {
516 *group_ptr = ret;
517 // Filling in |ret->curve_name| makes |EC_GROUP_free| and |EC_GROUP_dup|
518 // into no-ops. At this point, |ret| is considered static.
519 ret->curve_name = nid;
520 } else {
521 to_free = ret;
522 ret = *group_ptr;
523 }
524 CRYPTO_STATIC_MUTEX_unlock_write(built_in_groups_lock_bss_get());
525
526 EC_GROUP_free(to_free);
527 return ret;
528 }
529
EC_GROUP_free(EC_GROUP * group)530 void EC_GROUP_free(EC_GROUP *group) {
531 if (group == NULL ||
532 // Built-in curves are static.
533 group->curve_name != NID_undef ||
534 !CRYPTO_refcount_dec_and_test_zero(&group->references)) {
535 return;
536 }
537
538 if (group->meth->group_finish != NULL) {
539 group->meth->group_finish(group);
540 }
541
542 ec_point_free(group->generator, 0 /* don't free group */);
543 BN_free(&group->order);
544 BN_MONT_CTX_free(group->order_mont);
545
546 OPENSSL_free(group);
547 }
548
EC_GROUP_dup(const EC_GROUP * a)549 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
550 if (a == NULL ||
551 // Built-in curves are static.
552 a->curve_name != NID_undef) {
553 return (EC_GROUP *)a;
554 }
555
556 // Groups are logically immutable (but for |EC_GROUP_set_generator| which must
557 // be called early on), so we simply take a reference.
558 EC_GROUP *group = (EC_GROUP *)a;
559 CRYPTO_refcount_inc(&group->references);
560 return group;
561 }
562
EC_GROUP_cmp(const EC_GROUP * a,const EC_GROUP * b,BN_CTX * ignored)563 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
564 // Note this function returns 0 if equal and non-zero otherwise.
565 if (a == b) {
566 return 0;
567 }
568 if (a->curve_name != b->curve_name) {
569 return 1;
570 }
571 if (a->curve_name != NID_undef) {
572 // Built-in curves may be compared by curve name alone.
573 return 0;
574 }
575
576 // |a| and |b| are both custom curves. We compare the entire curve
577 // structure. If |a| or |b| is incomplete (due to legacy OpenSSL mistakes,
578 // custom curve construction is sadly done in two parts) but otherwise not the
579 // same object, we consider them always unequal.
580 return a->generator == NULL ||
581 b->generator == NULL ||
582 BN_cmp(&a->order, &b->order) != 0 ||
583 BN_cmp(&a->field, &b->field) != 0 ||
584 BN_cmp(&a->a, &b->a) != 0 ||
585 BN_cmp(&a->b, &b->b) != 0 ||
586 ec_GFp_simple_cmp(a, a->generator, b->generator, NULL) != 0;
587 }
588
EC_GROUP_get0_generator(const EC_GROUP * group)589 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
590 return group->generator;
591 }
592
EC_GROUP_get0_order(const EC_GROUP * group)593 const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
594 assert(!BN_is_zero(&group->order));
595 return &group->order;
596 }
597
EC_GROUP_get_order(const EC_GROUP * group,BIGNUM * order,BN_CTX * ctx)598 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
599 if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) {
600 return 0;
601 }
602 return 1;
603 }
604
EC_GROUP_get_cofactor(const EC_GROUP * group,BIGNUM * cofactor,BN_CTX * ctx)605 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
606 BN_CTX *ctx) {
607 // All |EC_GROUP|s have cofactor 1.
608 return BN_set_word(cofactor, 1);
609 }
610
EC_GROUP_get_curve_GFp(const EC_GROUP * group,BIGNUM * out_p,BIGNUM * out_a,BIGNUM * out_b,BN_CTX * ctx)611 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
612 BIGNUM *out_b, BN_CTX *ctx) {
613 return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b, ctx);
614 }
615
EC_GROUP_get_curve_name(const EC_GROUP * group)616 int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
617
EC_GROUP_get_degree(const EC_GROUP * group)618 unsigned EC_GROUP_get_degree(const EC_GROUP *group) {
619 return ec_GFp_simple_group_get_degree(group);
620 }
621
EC_POINT_new(const EC_GROUP * group)622 EC_POINT *EC_POINT_new(const EC_GROUP *group) {
623 EC_POINT *ret;
624
625 if (group == NULL) {
626 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
627 return NULL;
628 }
629
630 ret = OPENSSL_malloc(sizeof *ret);
631 if (ret == NULL) {
632 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
633 return NULL;
634 }
635
636 ret->group = EC_GROUP_dup(group);
637 if (ret->group == NULL ||
638 !ec_GFp_simple_point_init(ret)) {
639 OPENSSL_free(ret);
640 return NULL;
641 }
642
643 return ret;
644 }
645
ec_point_free(EC_POINT * point,int free_group)646 static void ec_point_free(EC_POINT *point, int free_group) {
647 if (!point) {
648 return;
649 }
650 ec_GFp_simple_point_finish(point);
651 if (free_group) {
652 EC_GROUP_free(point->group);
653 }
654 OPENSSL_free(point);
655 }
656
EC_POINT_free(EC_POINT * point)657 void EC_POINT_free(EC_POINT *point) {
658 ec_point_free(point, 1 /* free group */);
659 }
660
EC_POINT_clear_free(EC_POINT * point)661 void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
662
EC_POINT_copy(EC_POINT * dest,const EC_POINT * src)663 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
664 if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) {
665 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
666 return 0;
667 }
668 if (dest == src) {
669 return 1;
670 }
671 return ec_GFp_simple_point_copy(dest, src);
672 }
673
EC_POINT_dup(const EC_POINT * a,const EC_GROUP * group)674 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
675 if (a == NULL) {
676 return NULL;
677 }
678
679 EC_POINT *ret = EC_POINT_new(group);
680 if (ret == NULL ||
681 !EC_POINT_copy(ret, a)) {
682 EC_POINT_free(ret);
683 return NULL;
684 }
685
686 return ret;
687 }
688
EC_POINT_set_to_infinity(const EC_GROUP * group,EC_POINT * point)689 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
690 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
691 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
692 return 0;
693 }
694 return ec_GFp_simple_point_set_to_infinity(group, point);
695 }
696
EC_POINT_is_at_infinity(const EC_GROUP * group,const EC_POINT * point)697 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
698 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
699 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
700 return 0;
701 }
702 return ec_GFp_simple_is_at_infinity(group, point);
703 }
704
EC_POINT_is_on_curve(const EC_GROUP * group,const EC_POINT * point,BN_CTX * ctx)705 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
706 BN_CTX *ctx) {
707 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
708 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
709 return 0;
710 }
711 return ec_GFp_simple_is_on_curve(group, point, ctx);
712 }
713
EC_POINT_cmp(const EC_GROUP * group,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)714 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
715 BN_CTX *ctx) {
716 if (EC_GROUP_cmp(group, a->group, NULL) != 0 ||
717 EC_GROUP_cmp(group, b->group, NULL) != 0) {
718 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
719 return -1;
720 }
721 return ec_GFp_simple_cmp(group, a, b, ctx);
722 }
723
EC_POINT_make_affine(const EC_GROUP * group,EC_POINT * point,BN_CTX * ctx)724 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
725 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
726 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
727 return 0;
728 }
729 return ec_GFp_simple_make_affine(group, point, ctx);
730 }
731
EC_POINTs_make_affine(const EC_GROUP * group,size_t num,EC_POINT * points[],BN_CTX * ctx)732 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
733 BN_CTX *ctx) {
734 for (size_t i = 0; i < num; i++) {
735 if (EC_GROUP_cmp(group, points[i]->group, NULL) != 0) {
736 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
737 return 0;
738 }
739 }
740 return ec_GFp_simple_points_make_affine(group, num, points, ctx);
741 }
742
EC_POINT_get_affine_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)743 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
744 const EC_POINT *point, BIGNUM *x,
745 BIGNUM *y, BN_CTX *ctx) {
746 if (group->meth->point_get_affine_coordinates == 0) {
747 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
748 return 0;
749 }
750 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
751 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
752 return 0;
753 }
754 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
755 }
756
EC_POINT_set_affine_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)757 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
758 const BIGNUM *x, const BIGNUM *y,
759 BN_CTX *ctx) {
760 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
761 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
762 return 0;
763 }
764 if (!ec_GFp_simple_point_set_affine_coordinates(group, point, x, y, ctx)) {
765 return 0;
766 }
767
768 if (!EC_POINT_is_on_curve(group, point, ctx)) {
769 // In the event of an error, defend against the caller not checking the
770 // return value by setting a known safe value: the base point.
771 const EC_POINT *generator = EC_GROUP_get0_generator(group);
772 // The generator can be missing if the caller is in the process of
773 // constructing an arbitrary group. In this, we give up and hope they're
774 // checking the return value.
775 if (generator) {
776 EC_POINT_copy(point, generator);
777 }
778 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
779 return 0;
780 }
781
782 return 1;
783 }
784
EC_POINT_add(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)785 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
786 const EC_POINT *b, BN_CTX *ctx) {
787 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
788 EC_GROUP_cmp(group, a->group, NULL) != 0 ||
789 EC_GROUP_cmp(group, b->group, NULL) != 0) {
790 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
791 return 0;
792 }
793 return ec_GFp_simple_add(group, r, a, b, ctx);
794 }
795
796
EC_POINT_dbl(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,BN_CTX * ctx)797 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
798 BN_CTX *ctx) {
799 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
800 EC_GROUP_cmp(group, a->group, NULL) != 0) {
801 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
802 return 0;
803 }
804 return ec_GFp_simple_dbl(group, r, a, ctx);
805 }
806
807
EC_POINT_invert(const EC_GROUP * group,EC_POINT * a,BN_CTX * ctx)808 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
809 if (EC_GROUP_cmp(group, a->group, NULL) != 0) {
810 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
811 return 0;
812 }
813 return ec_GFp_simple_invert(group, a, ctx);
814 }
815
arbitrary_bignum_to_scalar(const EC_GROUP * group,EC_SCALAR * out,const BIGNUM * in,BN_CTX * ctx)816 static int arbitrary_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
817 const BIGNUM *in, BN_CTX *ctx) {
818 if (ec_bignum_to_scalar(group, out, in)) {
819 return 1;
820 }
821
822 ERR_clear_error();
823
824 // This is an unusual input, so we do not guarantee constant-time
825 // processing, even ignoring |bn_correct_top|.
826 const BIGNUM *order = &group->order;
827 BN_CTX_start(ctx);
828 BIGNUM *tmp = BN_CTX_get(ctx);
829 int ok = tmp != NULL &&
830 BN_nnmod(tmp, in, order, ctx) &&
831 ec_bignum_to_scalar_unchecked(group, out, tmp);
832 BN_CTX_end(ctx);
833 return ok;
834 }
835
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)836 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
837 const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
838 // Previously, this function set |r| to the point at infinity if there was
839 // nothing to multiply. But, nobody should be calling this function with
840 // nothing to multiply in the first place.
841 if ((g_scalar == NULL && p_scalar == NULL) ||
842 (p == NULL) != (p_scalar == NULL)) {
843 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
844 return 0;
845 }
846
847 int ret = 0;
848 EC_SCALAR g_scalar_storage, p_scalar_storage;
849 EC_SCALAR *g_scalar_arg = NULL, *p_scalar_arg = NULL;
850 BN_CTX *new_ctx = NULL;
851 if (ctx == NULL) {
852 new_ctx = BN_CTX_new();
853 if (new_ctx == NULL) {
854 goto err;
855 }
856 ctx = new_ctx;
857 }
858
859 if (g_scalar != NULL) {
860 if (!arbitrary_bignum_to_scalar(group, &g_scalar_storage, g_scalar, ctx)) {
861 goto err;
862 }
863 g_scalar_arg = &g_scalar_storage;
864 }
865
866 if (p_scalar != NULL) {
867 if (!arbitrary_bignum_to_scalar(group, &p_scalar_storage, p_scalar, ctx)) {
868 goto err;
869 }
870 p_scalar_arg = &p_scalar_storage;
871 }
872
873 ret = ec_point_mul_scalar(group, r, g_scalar_arg, p, p_scalar_arg, ctx);
874
875 err:
876 BN_CTX_free(new_ctx);
877 OPENSSL_cleanse(&g_scalar_storage, sizeof(g_scalar_storage));
878 OPENSSL_cleanse(&p_scalar_storage, sizeof(p_scalar_storage));
879 return ret;
880 }
881
ec_point_mul_scalar_public(const EC_GROUP * group,EC_POINT * r,const EC_SCALAR * g_scalar,const EC_POINT * p,const EC_SCALAR * p_scalar,BN_CTX * ctx)882 int ec_point_mul_scalar_public(const EC_GROUP *group, EC_POINT *r,
883 const EC_SCALAR *g_scalar, const EC_POINT *p,
884 const EC_SCALAR *p_scalar, BN_CTX *ctx) {
885 if ((g_scalar == NULL && p_scalar == NULL) ||
886 (p == NULL) != (p_scalar == NULL)) {
887 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
888 return 0;
889 }
890
891 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
892 (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
893 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
894 return 0;
895 }
896
897 return group->meth->mul_public(group, r, g_scalar, p, p_scalar, ctx);
898 }
899
ec_point_mul_scalar(const EC_GROUP * group,EC_POINT * r,const EC_SCALAR * g_scalar,const EC_POINT * p,const EC_SCALAR * p_scalar,BN_CTX * ctx)900 int ec_point_mul_scalar(const EC_GROUP *group, EC_POINT *r,
901 const EC_SCALAR *g_scalar, const EC_POINT *p,
902 const EC_SCALAR *p_scalar, BN_CTX *ctx) {
903 if ((g_scalar == NULL && p_scalar == NULL) ||
904 (p == NULL) != (p_scalar == NULL)) {
905 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
906 return 0;
907 }
908
909 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
910 (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
911 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
912 return 0;
913 }
914
915 return group->meth->mul(group, r, g_scalar, p, p_scalar, ctx);
916 }
917
EC_GROUP_set_asn1_flag(EC_GROUP * group,int flag)918 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
919
EC_GROUP_method_of(const EC_GROUP * group)920 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
921 return NULL;
922 }
923
EC_METHOD_get_field_type(const EC_METHOD * meth)924 int EC_METHOD_get_field_type(const EC_METHOD *meth) {
925 return NID_X9_62_prime_field;
926 }
927
EC_GROUP_set_point_conversion_form(EC_GROUP * group,point_conversion_form_t form)928 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
929 point_conversion_form_t form) {
930 if (form != POINT_CONVERSION_UNCOMPRESSED) {
931 abort();
932 }
933 }
934
EC_get_builtin_curves(EC_builtin_curve * out_curves,size_t max_num_curves)935 size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
936 size_t max_num_curves) {
937 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
938
939 for (size_t i = 0; i < max_num_curves && i < OPENSSL_NUM_BUILT_IN_CURVES;
940 i++) {
941 out_curves[i].comment = curves->curves[i].comment;
942 out_curves[i].nid = curves->curves[i].nid;
943 }
944
945 return OPENSSL_NUM_BUILT_IN_CURVES;
946 }
947
ec_bignum_to_scalar(const EC_GROUP * group,EC_SCALAR * out,const BIGNUM * in)948 int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
949 const BIGNUM *in) {
950 if (!ec_bignum_to_scalar_unchecked(group, out, in)) {
951 return 0;
952 }
953 if (!bn_less_than_words(out->words, group->order.d, group->order.top)) {
954 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR);
955 return 0;
956 }
957 return 1;
958 }
959
ec_bignum_to_scalar_unchecked(const EC_GROUP * group,EC_SCALAR * out,const BIGNUM * in)960 int ec_bignum_to_scalar_unchecked(const EC_GROUP *group, EC_SCALAR *out,
961 const BIGNUM *in) {
962 if (!bn_copy_words(out->words, group->order.top, in)) {
963 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR);
964 return 0;
965 }
966 return 1;
967 }
968
ec_random_nonzero_scalar(const EC_GROUP * group,EC_SCALAR * out,const uint8_t additional_data[32])969 int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out,
970 const uint8_t additional_data[32]) {
971 return bn_rand_range_words(out->words, 1, group->order.d, group->order.top,
972 additional_data);
973 }
974