Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / boringssl / src / crypto / ec / ec.c
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 <openssl/bn.h>
71 #include <openssl/err.h>
72 #include <openssl/mem.h>
73 #include <openssl/obj.h>
74
75 #include "internal.h"
76
77
78 static const struct curve_data P224 = {
79     "NIST P-224",
80     28,
81     1,
82     {/* p */
83      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
84      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85      0x00, 0x00, 0x00, 0x01,
86      /* a */
87      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
88      0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89      0xFF, 0xFF, 0xFF, 0xFE,
90      /* b */
91      0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
92      0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
93      0x23, 0x55, 0xFF, 0xB4,
94      /* x */
95      0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
96      0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
97      0x11, 0x5C, 0x1D, 0x21,
98      /* y */
99      0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
100      0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
101      0x85, 0x00, 0x7e, 0x34,
102      /* order */
103      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104      0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
105      0x5C, 0x5C, 0x2A, 0x3D,
106     }};
107
108 static const struct curve_data P256 = {
109     "NIST P-256",
110     32,
111     1,
112     {/* p */
113      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
114      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
115      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116      /* a */
117      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
118      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
119      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
120      /* b */
121      0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
122      0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
123      0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,
124      /* x */
125      0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
126      0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
127      0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
128      /* y */
129      0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
130      0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
131      0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
132      /* order */
133      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
134      0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
135      0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}};
136
137 static const struct curve_data P384 = {
138     "NIST P-384",
139     48,
140     1,
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 static const struct curve_data P521 = {
173     "NIST P-521",
174     66,
175     1,
176     {/* p */
177      0x01, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
181      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
182      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
183      /* a */
184      0x01, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
188      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
189      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
190      /* b */
191      0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
192      0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
193      0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
194      0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
195      0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
196      0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
197      /* x */
198      0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
199      0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
200      0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
201      0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
202      0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
203      0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
204      /* y */
205      0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
206      0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
207      0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
208      0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
209      0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
210      0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
211      /* order */
212      0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
213      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
214      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
215      0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
216      0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
217      0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09}};
218
219 const struct built_in_curve OPENSSL_built_in_curves[] = {
220   {NID_secp224r1, &P224, 0},
221   {NID_X9_62_prime256v1, &P256, 0},
222   {NID_secp384r1, &P384, 0},
223   {NID_secp521r1, &P521, 0},
224   {NID_undef, 0, 0},
225 };
226
227 EC_GROUP *ec_group_new(const EC_METHOD *meth) {
228   EC_GROUP *ret;
229
230   if (meth == NULL) {
231     OPENSSL_PUT_ERROR(EC, ec_group_new, EC_R_SLOT_FULL);
232     return NULL;
233   }
234
235   if (meth->group_init == 0) {
236     OPENSSL_PUT_ERROR(EC, ec_group_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
237     return NULL;
238   }
239
240   ret = OPENSSL_malloc(sizeof(EC_GROUP));
241   if (ret == NULL) {
242     OPENSSL_PUT_ERROR(EC, ec_group_new, ERR_R_MALLOC_FAILURE);
243     return NULL;
244   }
245   memset(ret, 0, sizeof(EC_GROUP));
246
247   ret->meth = meth;
248   BN_init(&ret->order);
249   BN_init(&ret->cofactor);
250   ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
251
252   if (!meth->group_init(ret)) {
253     OPENSSL_free(ret);
254     return NULL;
255   }
256
257   return ret;
258 }
259
260 static EC_GROUP *ec_group_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
261                                         const BIGNUM *b, BN_CTX *ctx) {
262   const EC_METHOD *meth = EC_GFp_mont_method();
263   EC_GROUP *ret;
264
265   ret = ec_group_new(meth);
266   if (ret == NULL) {
267     return NULL;
268   }
269
270   if (ret->meth->group_set_curve == 0) {
271     OPENSSL_PUT_ERROR(EC, ec_group_new_curve_GFp,
272                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
273     return 0;
274   }
275   if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
276     EC_GROUP_free(ret);
277     return NULL;
278   }
279   return ret;
280 }
281
282 static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
283   EC_GROUP *group = NULL;
284   EC_POINT *P = NULL;
285   BN_CTX *ctx = NULL;
286   BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = NULL;
287   int ok = 0;
288   unsigned param_len;
289   const EC_METHOD *meth;
290   const struct curve_data *data;
291   const uint8_t *params;
292
293   if ((ctx = BN_CTX_new()) == NULL) {
294     OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_MALLOC_FAILURE);
295     goto err;
296   }
297
298   data = curve->data;
299   param_len = data->param_len;
300   params = data->data;
301
302   if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
303       !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
304       !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
305     OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
306     goto err;
307   }
308
309   if (curve->method != 0) {
310     meth = curve->method();
311     if (((group = ec_group_new(meth)) == NULL) ||
312         (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
313       OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
314       goto err;
315     }
316   } else {
317     if ((group = ec_group_new_curve_GFp(p, a, b, ctx)) == NULL) {
318       OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
319       goto err;
320     }
321   }
322
323   if ((P = EC_POINT_new(group)) == NULL) {
324     OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
325     goto err;
326   }
327
328   if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
329       !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
330     OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
331     goto err;
332   }
333
334   if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
335     OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
336     goto err;
337   }
338   if (!(order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) ||
339       !BN_set_word(x, (BN_ULONG)data->cofactor)) {
340     OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
341     goto err;
342   }
343
344   group->generator = P;
345   P = NULL;
346   if (!BN_copy(&group->order, order) ||
347       !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) {
348     OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_BN_LIB);
349     goto err;
350   }
351
352   ok = 1;
353
354 err:
355   if (!ok) {
356     EC_GROUP_free(group);
357     group = NULL;
358   }
359   if (P)
360     EC_POINT_free(P);
361   if (ctx)
362     BN_CTX_free(ctx);
363   if (p)
364     BN_free(p);
365   if (a)
366     BN_free(a);
367   if (b)
368     BN_free(b);
369   if (order)
370     BN_free(order);
371   if (x)
372     BN_free(x);
373   if (y)
374     BN_free(y);
375   return group;
376 }
377
378 EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
379   unsigned i;
380   const struct built_in_curve *curve;
381   EC_GROUP *ret = NULL;
382
383   for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
384     curve = &OPENSSL_built_in_curves[i];
385     if (curve->nid == nid) {
386       ret = ec_group_new_from_data(curve);
387       break;
388     }
389   }
390
391   if (ret == NULL) {
392     OPENSSL_PUT_ERROR(EC, EC_GROUP_new_by_curve_name, EC_R_UNKNOWN_GROUP);
393     return NULL;
394   }
395
396   ret->curve_name = nid;
397   return ret;
398 }
399
400 void EC_GROUP_free(EC_GROUP *group) {
401   if (!group) {
402     return;
403   }
404
405   if (group->meth->group_finish != 0) {
406     group->meth->group_finish(group);
407   }
408
409   ec_pre_comp_free(group->pre_comp);
410
411   if (group->generator != NULL) {
412     EC_POINT_free(group->generator);
413   }
414   BN_free(&group->order);
415   BN_free(&group->cofactor);
416
417   OPENSSL_free(group);
418 }
419
420 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) {
421   if (dest->meth->group_copy == 0) {
422     OPENSSL_PUT_ERROR(EC, EC_GROUP_copy, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
423     return 0;
424   }
425   if (dest->meth != src->meth) {
426     OPENSSL_PUT_ERROR(EC, EC_GROUP_copy, EC_R_INCOMPATIBLE_OBJECTS);
427     return 0;
428   }
429   if (dest == src) {
430     return 1;
431   }
432
433   ec_pre_comp_free(dest->pre_comp);
434   dest->pre_comp = ec_pre_comp_dup(src->pre_comp);
435
436   if (src->generator != NULL) {
437     if (dest->generator == NULL) {
438       dest->generator = EC_POINT_new(dest);
439       if (dest->generator == NULL) {
440         return 0;
441       }
442     }
443     if (!EC_POINT_copy(dest->generator, src->generator)) {
444       return 0;
445     }
446   } else {
447     /* src->generator == NULL */
448     if (dest->generator != NULL) {
449       EC_POINT_clear_free(dest->generator);
450       dest->generator = NULL;
451     }
452   }
453
454   if (!BN_copy(&dest->order, &src->order) ||
455       !BN_copy(&dest->cofactor, &src->cofactor)) {
456     return 0;
457   }
458
459   dest->curve_name = src->curve_name;
460   dest->asn1_form = src->asn1_form;
461
462   return dest->meth->group_copy(dest, src);
463 }
464
465 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
466   EC_GROUP *t = NULL;
467   int ok = 0;
468
469   if (a == NULL) {
470     return NULL;
471   }
472
473   t = ec_group_new(a->meth);
474   if (t == NULL) {
475     return NULL;
476   }
477   if (!EC_GROUP_copy(t, a)) {
478     goto err;
479   }
480
481   ok = 1;
482
483 err:
484   if (!ok) {
485     if (t) {
486       EC_GROUP_free(t);
487     }
488     return NULL;
489   } else {
490     return t;
491   }
492 }
493
494 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b) {
495   if (a->curve_name == NID_undef || b->curve_name == NID_undef) {
496     return 0;
497   }
498   return a->curve_name == b->curve_name;
499 }
500
501 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
502   return group->generator;
503 }
504
505 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
506   if (!BN_copy(order, &group->order)) {
507     return 0;
508   }
509
510   return !BN_is_zero(order);
511 }
512
513 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
514                           BN_CTX *ctx) {
515   if (!BN_copy(cofactor, &group->cofactor)) {
516     return 0;
517   }
518
519   return !BN_is_zero(&group->cofactor);
520 }
521
522 int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
523
524 int EC_GROUP_get_degree(const EC_GROUP *group) {
525   if (group->meth->group_get_degree == 0) {
526     OPENSSL_PUT_ERROR(EC, EC_GROUP_get_degree,
527                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
528     return 0;
529   }
530   return group->meth->group_get_degree(group);
531 }
532
533 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
534                                         point_conversion_form_t form) {
535   group->asn1_form = form;
536 }
537
538 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
539   if (group->meth->mul == 0) {
540     /* use default */
541     return ec_wNAF_precompute_mult(group, ctx);
542   }
543
544   if (group->meth->precompute_mult != 0) {
545     return group->meth->precompute_mult(group, ctx);
546   }
547
548   return 1; /* nothing to do, so report success */
549 }
550
551 int EC_GROUP_have_precompute_mult(const EC_GROUP *group) {
552   if (group->meth->mul == 0) {
553     /* use default */
554     return ec_wNAF_have_precompute_mult(group);
555   }
556
557   if (group->meth->have_precompute_mult != 0) {
558     return group->meth->have_precompute_mult(group);
559   }
560
561   return 0; /* cannot tell whether precomputation has been performed */
562 }
563
564 EC_POINT *EC_POINT_new(const EC_GROUP *group) {
565   EC_POINT *ret;
566
567   if (group == NULL) {
568     OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_PASSED_NULL_PARAMETER);
569     return NULL;
570   }
571   if (group->meth->point_init == 0) {
572     OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
573     return NULL;
574   }
575
576   ret = OPENSSL_malloc(sizeof *ret);
577   if (ret == NULL) {
578     OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_MALLOC_FAILURE);
579     return NULL;
580   }
581
582   ret->meth = group->meth;
583
584   if (!ret->meth->point_init(ret)) {
585     OPENSSL_free(ret);
586     return NULL;
587   }
588
589   return ret;
590 }
591
592 void EC_POINT_free(EC_POINT *point) {
593   if (!point) {
594     return;
595   }
596
597   if (point->meth->point_finish != 0) {
598     point->meth->point_finish(point);
599   }
600   OPENSSL_free(point);
601 }
602
603 void EC_POINT_clear_free(EC_POINT *point) {
604   if (!point) {
605     return;
606   }
607
608   if (point->meth->point_clear_finish != 0) {
609     point->meth->point_clear_finish(point);
610   } else if (point->meth->point_finish != 0) {
611     point->meth->point_finish(point);
612   }
613   OPENSSL_cleanse(point, sizeof *point);
614   OPENSSL_free(point);
615 }
616
617 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
618   if (dest->meth->point_copy == 0) {
619     OPENSSL_PUT_ERROR(EC, EC_POINT_copy, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
620     return 0;
621   }
622   if (dest->meth != src->meth) {
623     OPENSSL_PUT_ERROR(EC, EC_POINT_copy, EC_R_INCOMPATIBLE_OBJECTS);
624     return 0;
625   }
626   if (dest == src) {
627     return 1;
628   }
629   return dest->meth->point_copy(dest, src);
630 }
631
632 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
633   EC_POINT *t;
634   int r;
635
636   if (a == NULL) {
637     return NULL;
638   }
639
640   t = EC_POINT_new(group);
641   if (t == NULL) {
642     OPENSSL_PUT_ERROR(EC, EC_POINT_dup, ERR_R_MALLOC_FAILURE);
643     return NULL;
644   }
645   r = EC_POINT_copy(t, a);
646   if (!r) {
647     EC_POINT_free(t);
648     return NULL;
649   } else {
650     return t;
651   }
652 }
653
654 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
655   if (group->meth->point_set_to_infinity == 0) {
656     OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity,
657                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
658     return 0;
659   }
660   if (group->meth != point->meth) {
661     OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity, EC_R_INCOMPATIBLE_OBJECTS);
662     return 0;
663   }
664   return group->meth->point_set_to_infinity(group, point);
665 }
666
667 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
668   if (group->meth->is_at_infinity == 0) {
669     OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity,
670                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
671     return 0;
672   }
673   if (group->meth != point->meth) {
674     OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity, EC_R_INCOMPATIBLE_OBJECTS);
675     return 0;
676   }
677   return group->meth->is_at_infinity(group, point);
678 }
679
680 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
681                          BN_CTX *ctx) {
682   if (group->meth->is_on_curve == 0) {
683     OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve,
684                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
685     return 0;
686   }
687   if (group->meth != point->meth) {
688     OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve, EC_R_INCOMPATIBLE_OBJECTS);
689     return 0;
690   }
691   return group->meth->is_on_curve(group, point, ctx);
692 }
693
694 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
695                  BN_CTX *ctx) {
696   if (group->meth->point_cmp == 0) {
697     OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
698     return -1;
699   }
700   if ((group->meth != a->meth) || (a->meth != b->meth)) {
701     OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, EC_R_INCOMPATIBLE_OBJECTS);
702     return -1;
703   }
704   return group->meth->point_cmp(group, a, b, ctx);
705 }
706
707 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
708   if (group->meth->make_affine == 0) {
709     OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine,
710                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
711     return 0;
712   }
713   if (group->meth != point->meth) {
714     OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
715     return 0;
716   }
717   return group->meth->make_affine(group, point, ctx);
718 }
719
720 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
721                           BN_CTX *ctx) {
722   size_t i;
723
724   if (group->meth->points_make_affine == 0) {
725     OPENSSL_PUT_ERROR(EC, EC_POINTs_make_affine,
726                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
727     return 0;
728   }
729   for (i = 0; i < num; i++) {
730     if (group->meth != points[i]->meth) {
731       OPENSSL_PUT_ERROR(EC, EC_POINTs_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
732       return 0;
733     }
734   }
735   return group->meth->points_make_affine(group, num, points, ctx);
736 }
737
738 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
739                                         const EC_POINT *point, BIGNUM *x,
740                                         BIGNUM *y, BN_CTX *ctx) {
741   if (group->meth->point_get_affine_coordinates == 0) {
742     OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
743                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
744     return 0;
745   }
746   if (group->meth != point->meth) {
747     OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
748                       EC_R_INCOMPATIBLE_OBJECTS);
749     return 0;
750   }
751   return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
752 }
753
754 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
755                                         const BIGNUM *x, const BIGNUM *y,
756                                         BN_CTX *ctx) {
757   if (group->meth->point_set_affine_coordinates == 0) {
758     OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
759                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
760     return 0;
761   }
762   if (group->meth != point->meth) {
763     OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
764                       EC_R_INCOMPATIBLE_OBJECTS);
765     return 0;
766   }
767   return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
768 }
769
770 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
771                  const EC_POINT *b, BN_CTX *ctx) {
772   if (group->meth->add == 0) {
773     OPENSSL_PUT_ERROR(EC, EC_POINT_add, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
774     return 0;
775   }
776   if ((group->meth != r->meth) || (r->meth != a->meth) ||
777       (a->meth != b->meth)) {
778     OPENSSL_PUT_ERROR(EC, EC_POINT_add, EC_R_INCOMPATIBLE_OBJECTS);
779     return 0;
780   }
781   return group->meth->add(group, r, a, b, ctx);
782 }
783
784
785 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
786                  BN_CTX *ctx) {
787   if (group->meth->dbl == 0) {
788     OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
789     return 0;
790   }
791   if ((group->meth != r->meth) || (r->meth != a->meth)) {
792     OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, EC_R_INCOMPATIBLE_OBJECTS);
793     return 0;
794   }
795   return group->meth->dbl(group, r, a, ctx);
796 }
797
798
799 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
800   if (group->meth->invert == 0) {
801     OPENSSL_PUT_ERROR(EC, EC_POINT_invert, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
802     return 0;
803   }
804   if (group->meth != a->meth) {
805     OPENSSL_PUT_ERROR(EC, EC_POINT_invert, EC_R_INCOMPATIBLE_OBJECTS);
806     return 0;
807   }
808   return group->meth->invert(group, a, ctx);
809 }
810
811 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
812                  const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) {
813   /* just a convenient interface to EC_POINTs_mul() */
814
815   const EC_POINT *points[1];
816   const BIGNUM *scalars[1];
817
818   points[0] = point;
819   scalars[0] = p_scalar;
820
821   return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL),
822                        points, scalars, ctx);
823 }
824
825 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
826                   size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
827                   BN_CTX *ctx) {
828   if (group->meth->mul == 0) {
829     /* use default. Warning, not constant-time. */
830     return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
831   }
832
833   return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
834 }
835
836 int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
837                                              const BIGNUM *x, const BIGNUM *y,
838                                              const BIGNUM *z, BN_CTX *ctx) {
839   if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
840     OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
841                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
842     return 0;
843   }
844   if (group->meth != point->meth) {
845     OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
846                       EC_R_INCOMPATIBLE_OBJECTS);
847     return 0;
848   }
849   return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y,
850                                                             z, ctx);
851 }