1 /* Originally written by Bodo Moeller for the OpenSSL project.
2 * ====================================================================
3 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
31 * 6. Redistributions of any form whatsoever must retain the following
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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 * ====================================================================
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).
55 /* ====================================================================
56 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
58 * Portions of the attached software ("Contribution") are developed by
59 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
61 * The Contribution is licensed pursuant to the OpenSSL open source
62 * license provided above.
64 * The elliptic curve binary polynomial software is originally written by
65 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
68 #include <openssl/ec.h>
70 #include <openssl/bn.h>
71 #include <openssl/err.h>
72 #include <openssl/mem.h>
73 #include <openssl/obj.h>
78 static const struct curve_data P224 = {
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,
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,
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,
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,
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,
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,
108 static const struct curve_data P256 = {
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,
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,
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,
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,
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,
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}};
137 static const struct curve_data P384 = {
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,
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,
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,
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,
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,
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}};
172 static const struct curve_data P521 = {
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,
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,
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,
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,
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,
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}};
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},
227 EC_GROUP *ec_group_new(const EC_METHOD *meth) {
231 OPENSSL_PUT_ERROR(EC, ec_group_new, EC_R_SLOT_FULL);
235 if (meth->group_init == 0) {
236 OPENSSL_PUT_ERROR(EC, ec_group_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
240 ret = OPENSSL_malloc(sizeof(EC_GROUP));
242 OPENSSL_PUT_ERROR(EC, ec_group_new, ERR_R_MALLOC_FAILURE);
245 memset(ret, 0, sizeof(EC_GROUP));
248 BN_init(&ret->order);
249 BN_init(&ret->cofactor);
250 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
252 if (!meth->group_init(ret)) {
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();
265 ret = ec_group_new(meth);
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);
275 if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
282 static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
283 EC_GROUP *group = NULL;
286 BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = NULL;
289 const EC_METHOD *meth;
290 const struct curve_data *data;
291 const uint8_t *params;
293 if ((ctx = BN_CTX_new()) == NULL) {
294 OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_MALLOC_FAILURE);
299 param_len = data->param_len;
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);
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);
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);
323 if ((P = EC_POINT_new(group)) == NULL) {
324 OPENSSL_PUT_ERROR(EC, ec_group_new_from_data, ERR_R_EC_LIB);
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);
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);
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);
344 group->generator = P;
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);
356 EC_GROUP_free(group);
378 EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
380 const struct built_in_curve *curve;
381 EC_GROUP *ret = NULL;
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);
392 OPENSSL_PUT_ERROR(EC, EC_GROUP_new_by_curve_name, EC_R_UNKNOWN_GROUP);
396 ret->curve_name = nid;
400 void EC_GROUP_free(EC_GROUP *group) {
405 if (group->meth->group_finish != 0) {
406 group->meth->group_finish(group);
409 ec_pre_comp_free(group->pre_comp);
411 if (group->generator != NULL) {
412 EC_POINT_free(group->generator);
414 BN_free(&group->order);
415 BN_free(&group->cofactor);
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);
425 if (dest->meth != src->meth) {
426 OPENSSL_PUT_ERROR(EC, EC_GROUP_copy, EC_R_INCOMPATIBLE_OBJECTS);
433 ec_pre_comp_free(dest->pre_comp);
434 dest->pre_comp = ec_pre_comp_dup(src->pre_comp);
436 if (src->generator != NULL) {
437 if (dest->generator == NULL) {
438 dest->generator = EC_POINT_new(dest);
439 if (dest->generator == NULL) {
443 if (!EC_POINT_copy(dest->generator, src->generator)) {
447 /* src->generator == NULL */
448 if (dest->generator != NULL) {
449 EC_POINT_clear_free(dest->generator);
450 dest->generator = NULL;
454 if (!BN_copy(&dest->order, &src->order) ||
455 !BN_copy(&dest->cofactor, &src->cofactor)) {
459 dest->curve_name = src->curve_name;
460 dest->asn1_form = src->asn1_form;
462 return dest->meth->group_copy(dest, src);
465 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
473 t = ec_group_new(a->meth);
477 if (!EC_GROUP_copy(t, a)) {
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) {
498 return a->curve_name == b->curve_name;
501 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
502 return group->generator;
505 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
506 if (!BN_copy(order, &group->order)) {
510 return !BN_is_zero(order);
513 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
515 if (!BN_copy(cofactor, &group->cofactor)) {
519 return !BN_is_zero(&group->cofactor);
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);
529 return group->meth->group_get_curve(group, out_p, out_a, out_b, ctx);
532 int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
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);
540 return group->meth->group_get_degree(group);
543 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
544 point_conversion_form_t form) {
545 group->asn1_form = form;
548 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
549 if (group->meth->mul == 0) {
551 return ec_wNAF_precompute_mult(group, ctx);
554 if (group->meth->precompute_mult != 0) {
555 return group->meth->precompute_mult(group, ctx);
558 return 1; /* nothing to do, so report success */
561 int EC_GROUP_have_precompute_mult(const EC_GROUP *group) {
562 if (group->meth->mul == 0) {
564 return ec_wNAF_have_precompute_mult(group);
567 if (group->meth->have_precompute_mult != 0) {
568 return group->meth->have_precompute_mult(group);
571 return 0; /* cannot tell whether precomputation has been performed */
574 EC_POINT *EC_POINT_new(const EC_GROUP *group) {
578 OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_PASSED_NULL_PARAMETER);
581 if (group->meth->point_init == 0) {
582 OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
586 ret = OPENSSL_malloc(sizeof *ret);
588 OPENSSL_PUT_ERROR(EC, EC_POINT_new, ERR_R_MALLOC_FAILURE);
592 ret->meth = group->meth;
594 if (!ret->meth->point_init(ret)) {
602 void EC_POINT_free(EC_POINT *point) {
607 if (point->meth->point_finish != 0) {
608 point->meth->point_finish(point);
613 void EC_POINT_clear_free(EC_POINT *point) {
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);
623 OPENSSL_cleanse(point, sizeof *point);
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);
632 if (dest->meth != src->meth) {
633 OPENSSL_PUT_ERROR(EC, EC_POINT_copy, EC_R_INCOMPATIBLE_OBJECTS);
639 return dest->meth->point_copy(dest, src);
642 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
650 t = EC_POINT_new(group);
652 OPENSSL_PUT_ERROR(EC, EC_POINT_dup, ERR_R_MALLOC_FAILURE);
655 r = EC_POINT_copy(t, a);
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);
670 if (group->meth != point->meth) {
671 OPENSSL_PUT_ERROR(EC, EC_POINT_set_to_infinity, EC_R_INCOMPATIBLE_OBJECTS);
674 return group->meth->point_set_to_infinity(group, point);
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);
683 if (group->meth != point->meth) {
684 OPENSSL_PUT_ERROR(EC, EC_POINT_is_at_infinity, EC_R_INCOMPATIBLE_OBJECTS);
687 return group->meth->is_at_infinity(group, point);
690 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
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);
697 if (group->meth != point->meth) {
698 OPENSSL_PUT_ERROR(EC, EC_POINT_is_on_curve, EC_R_INCOMPATIBLE_OBJECTS);
701 return group->meth->is_on_curve(group, point, ctx);
704 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
706 if (group->meth->point_cmp == 0) {
707 OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
710 if ((group->meth != a->meth) || (a->meth != b->meth)) {
711 OPENSSL_PUT_ERROR(EC, EC_POINT_cmp, EC_R_INCOMPATIBLE_OBJECTS);
714 return group->meth->point_cmp(group, a, b, ctx);
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);
723 if (group->meth != point->meth) {
724 OPENSSL_PUT_ERROR(EC, EC_POINT_make_affine, EC_R_INCOMPATIBLE_OBJECTS);
727 return group->meth->make_affine(group, point, ctx);
730 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
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);
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);
745 return group->meth->points_make_affine(group, num, points, ctx);
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);
756 if (group->meth != point->meth) {
757 OPENSSL_PUT_ERROR(EC, EC_POINT_get_affine_coordinates_GFp,
758 EC_R_INCOMPATIBLE_OBJECTS);
761 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
764 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
765 const BIGNUM *x, const BIGNUM *y,
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);
772 if (group->meth != point->meth) {
773 OPENSSL_PUT_ERROR(EC, EC_POINT_set_affine_coordinates_GFp,
774 EC_R_INCOMPATIBLE_OBJECTS);
777 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
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);
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);
791 return group->meth->add(group, r, a, b, ctx);
795 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
797 if (group->meth->dbl == 0) {
798 OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
801 if ((group->meth != r->meth) || (r->meth != a->meth)) {
802 OPENSSL_PUT_ERROR(EC, EC_POINT_dbl, EC_R_INCOMPATIBLE_OBJECTS);
805 return group->meth->dbl(group, r, a, ctx);
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);
814 if (group->meth != a->meth) {
815 OPENSSL_PUT_ERROR(EC, EC_POINT_invert, EC_R_INCOMPATIBLE_OBJECTS);
818 return group->meth->invert(group, a, ctx);
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() */
825 const EC_POINT *points[1];
826 const BIGNUM *scalars[1];
829 scalars[0] = p_scalar;
831 return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL),
832 points, scalars, ctx);
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[],
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);
843 return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
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);
854 if (group->meth != point->meth) {
855 OPENSSL_PUT_ERROR(EC, ec_point_set_Jprojective_coordinates_GFp,
856 EC_R_INCOMPATIBLE_OBJECTS);
859 return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y,