Upstream version 10.39.225.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_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
523                            BIGNUM *out_b, BN_CTX *ctx) {
524   if (group->meth->group_get_curve == 0) {
525     OPENSSL_PUT_ERROR(EC, EC_GROUP_get_curve_GFp,
526                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
527     return 0;
528   }
529   return group->meth->group_get_curve(group, out_p, out_a, out_b, ctx);
530 }
531
532 int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
533
534 int EC_GROUP_get_degree(const EC_GROUP *group) {
535   if (group->meth->group_get_degree == 0) {
536     OPENSSL_PUT_ERROR(EC, EC_GROUP_get_degree,
537                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
538     return 0;
539   }
540   return group->meth->group_get_degree(group);
541 }
542
543 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
544                                         point_conversion_form_t form) {
545   group->asn1_form = form;
546 }
547
548 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
549   if (group->meth->mul == 0) {
550     /* use default */
551     return ec_wNAF_precompute_mult(group, ctx);
552   }
553
554   if (group->meth->precompute_mult != 0) {
555     return group->meth->precompute_mult(group, ctx);
556   }
557
558   return 1; /* nothing to do, so report success */
559 }
560
561 int EC_GROUP_have_precompute_mult(const EC_GROUP *group) {
562   if (group->meth->mul == 0) {
563     /* use default */
564     return ec_wNAF_have_precompute_mult(group);
565   }
566
567   if (group->meth->have_precompute_mult != 0) {
568     return group->meth->have_precompute_mult(group);
569   }
570
571   return 0; /* cannot tell whether precomputation has been performed */
572 }
573
574 EC_POINT *EC_POINT_new(const EC_GROUP *group) {
575   EC_POINT *ret;
576
577   if (group == NULL) {
578     OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_PASSED_NULL_PARAMETER);
579     return NULL;
580   }
581   if (group->meth->point_init == 0) {
582     OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
583     return NULL;
584   }
585
586   ret = OPENSSL_malloc(sizeof *ret);
587   if (ret == NULL) {
588     OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_MALLOC_FAILURE);
589     return NULL;
590   }
591
592   ret->meth = group->meth;
593
594   if (!ret->meth->point_init(ret)) {
595     OPENSSL_free(ret);
596     return NULL;
597   }
598
599   return ret;
600 }
601
602 void EC_POINT_free(EC_POINT *point) {
603   if (!point) {
604     return;
605   }
606
607   if (point->meth->point_finish != 0) {
608     point->meth->point_finish(point);
609   }
610   OPENSSL_free(point);
611 }
612
613 void EC_POINT_clear_free(EC_POINT *point) {
614   if (!point) {
615     return;
616   }
617
618   if (point->meth->point_clear_finish != 0) {
619     point->meth->point_clear_finish(point);
620   } else if (point->meth->point_finish != 0) {
621     point->meth->point_finish(point);
622   }
623   OPENSSL_cleanse(point, sizeof *point);
624   OPENSSL_free(point);
625 }
626
627 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
628   if (dest->meth->point_copy == 0) {
629     OPENSSL_PUT_ERROR(EC, EC_POINT_copy, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
630     return 0;
631   }
632   if (dest->meth != src->meth) {
633     OPENSSL_PUT_ERROR(EC, EC_POINT_copy, EC_R_INCOMPATIBLE_OBJECTS);
634     return 0;
635   }
636   if (dest == src) {
637     return 1;
638   }
639   return dest->meth->point_copy(dest, src);
640 }
641
642 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
643   EC_POINT *t;
644   int r;
645
646   if (a == NULL) {
647     return NULL;
648   }
649
650   t = EC_POINT_new(group);
651   if (t == NULL) {
652     OPENSSL_PUT_ERROR(EC, EC_POINT_dup, ERR_R_MALLOC_FAILURE);
653     return NULL;
654   }
655   r = EC_POINT_copy(t, a);
656   if (!r) {
657     EC_POINT_free(t);
658     return NULL;
659   } else {
660     return t;
661   }
662 }
663
664 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
665   if (group->meth->point_set_to_infinity == 0) {
666     OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity,
667                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
668     return 0;
669   }
670   if (group->meth != point->meth) {
671     OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity, EC_R_INCOMPATIBLE_OBJECTS);
672     return 0;
673   }
674   return group->meth->point_set_to_infinity(group, point);
675 }
676
677 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
678   if (group->meth->is_at_infinity == 0) {
679     OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity,
680                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
681     return 0;
682   }
683   if (group->meth != point->meth) {
684     OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity, EC_R_INCOMPATIBLE_OBJECTS);
685     return 0;
686   }
687   return group->meth->is_at_infinity(group, point);
688 }
689
690 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
691                          BN_CTX *ctx) {
692   if (group->meth->is_on_curve == 0) {
693     OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve,
694                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
695     return 0;
696   }
697   if (group->meth != point->meth) {
698     OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve, EC_R_INCOMPATIBLE_OBJECTS);
699     return 0;
700   }
701   return group->meth->is_on_curve(group, point, ctx);
702 }
703
704 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
705                  BN_CTX *ctx) {
706   if (group->meth->point_cmp == 0) {
707     OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
708     return -1;
709   }
710   if ((group->meth != a->meth) || (a->meth != b->meth)) {
711     OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, EC_R_INCOMPATIBLE_OBJECTS);
712     return -1;
713   }
714   return group->meth->point_cmp(group, a, b, ctx);
715 }
716
717 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
718   if (group->meth->make_affine == 0) {
719     OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine,
720                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
721     return 0;
722   }
723   if (group->meth != point->meth) {
724     OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
725     return 0;
726   }
727   return group->meth->make_affine(group, point, ctx);
728 }
729
730 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
731                           BN_CTX *ctx) {
732   size_t i;
733
734   if (group->meth->points_make_affine == 0) {
735     OPENSSL_PUT_ERROR(EC, EC_POINTs_make_affine,
736                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
737     return 0;
738   }
739   for (i = 0; i < num; i++) {
740     if (group->meth != points[i]->meth) {
741       OPENSSL_PUT_ERROR(EC, EC_POINTs_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
742       return 0;
743     }
744   }
745   return group->meth->points_make_affine(group, num, points, ctx);
746 }
747
748 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
749                                         const EC_POINT *point, BIGNUM *x,
750                                         BIGNUM *y, BN_CTX *ctx) {
751   if (group->meth->point_get_affine_coordinates == 0) {
752     OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
753                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
754     return 0;
755   }
756   if (group->meth != point->meth) {
757     OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
758                       EC_R_INCOMPATIBLE_OBJECTS);
759     return 0;
760   }
761   return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
762 }
763
764 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
765                                         const BIGNUM *x, const BIGNUM *y,
766                                         BN_CTX *ctx) {
767   if (group->meth->point_set_affine_coordinates == 0) {
768     OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
769                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
770     return 0;
771   }
772   if (group->meth != point->meth) {
773     OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
774                       EC_R_INCOMPATIBLE_OBJECTS);
775     return 0;
776   }
777   return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
778 }
779
780 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
781                  const EC_POINT *b, BN_CTX *ctx) {
782   if (group->meth->add == 0) {
783     OPENSSL_PUT_ERROR(EC, EC_POINT_add, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
784     return 0;
785   }
786   if ((group->meth != r->meth) || (r->meth != a->meth) ||
787       (a->meth != b->meth)) {
788     OPENSSL_PUT_ERROR(EC, EC_POINT_add, EC_R_INCOMPATIBLE_OBJECTS);
789     return 0;
790   }
791   return group->meth->add(group, r, a, b, ctx);
792 }
793
794
795 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
796                  BN_CTX *ctx) {
797   if (group->meth->dbl == 0) {
798     OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
799     return 0;
800   }
801   if ((group->meth != r->meth) || (r->meth != a->meth)) {
802     OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, EC_R_INCOMPATIBLE_OBJECTS);
803     return 0;
804   }
805   return group->meth->dbl(group, r, a, ctx);
806 }
807
808
809 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
810   if (group->meth->invert == 0) {
811     OPENSSL_PUT_ERROR(EC, EC_POINT_invert, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
812     return 0;
813   }
814   if (group->meth != a->meth) {
815     OPENSSL_PUT_ERROR(EC, EC_POINT_invert, EC_R_INCOMPATIBLE_OBJECTS);
816     return 0;
817   }
818   return group->meth->invert(group, a, ctx);
819 }
820
821 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
822                  const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) {
823   /* just a convenient interface to EC_POINTs_mul() */
824
825   const EC_POINT *points[1];
826   const BIGNUM *scalars[1];
827
828   points[0] = point;
829   scalars[0] = p_scalar;
830
831   return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL),
832                        points, scalars, ctx);
833 }
834
835 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
836                   size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
837                   BN_CTX *ctx) {
838   if (group->meth->mul == 0) {
839     /* use default. Warning, not constant-time. */
840     return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
841   }
842
843   return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
844 }
845
846 int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
847                                              const BIGNUM *x, const BIGNUM *y,
848                                              const BIGNUM *z, BN_CTX *ctx) {
849   if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
850     OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
851                       ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
852     return 0;
853   }
854   if (group->meth != point->meth) {
855     OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
856                       EC_R_INCOMPATIBLE_OBJECTS);
857     return 0;
858   }
859   return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y,
860                                                             z, ctx);
861 }