• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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