• 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_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