blob: 904466af3e3026cc390999cc27a9fd1b911f9a26 [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* 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
Adam Langleyfad63272015-11-12 12:15:39 -080070#include <assert.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080071#include <string.h>
72
73#include <openssl/bn.h>
74#include <openssl/err.h>
75#include <openssl/mem.h>
David Benjamin4969cc92016-04-22 15:02:23 -040076#include <openssl/nid.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080077
78#include "internal.h"
Robert Sloan8ff03552017-06-14 12:40:58 -070079#include "../../internal.h"
Robert Sloan99319a12017-11-27 10:32:46 -080080#include "../bn/internal.h"
Robert Sloan8ff03552017-06-14 12:40:58 -070081#include "../delocate.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080082
83
Robert Sloan29c1d2c2017-10-30 14:10:28 -070084static void ec_point_free(EC_POINT *point, int free_group);
85
Robert Sloane56da3e2017-06-26 08:26:42 -070086static const uint8_t kP224Params[6 * 28] = {
Robert Sloan8f860b12017-08-28 07:37:06 -070087 // p
Robert Sloane56da3e2017-06-26 08:26:42 -070088 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,
Robert Sloan8f860b12017-08-28 07:37:06 -070091 // a
Robert Sloane56da3e2017-06-26 08:26:42 -070092 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,
Robert Sloan8f860b12017-08-28 07:37:06 -070095 // b
Robert Sloane56da3e2017-06-26 08:26:42 -070096 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,
Robert Sloan8f860b12017-08-28 07:37:06 -070099 // x
Robert Sloane56da3e2017-06-26 08:26:42 -0700100 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700103 // y
Robert Sloane56da3e2017-06-26 08:26:42 -0700104 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700107 // order
Robert Sloane56da3e2017-06-26 08:26:42 -0700108 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,
Robert Sloan8ff03552017-06-14 12:40:58 -0700111};
Adam Langleyd9e397b2015-01-22 14:27:53 -0800112
Robert Sloane56da3e2017-06-26 08:26:42 -0700113static const uint8_t kP256Params[6 * 32] = {
Robert Sloan8f860b12017-08-28 07:37:06 -0700114 // p
Robert Sloane56da3e2017-06-26 08:26:42 -0700115 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700118 // a
Robert Sloane56da3e2017-06-26 08:26:42 -0700119 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700122 // b
Robert Sloane56da3e2017-06-26 08:26:42 -0700123 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700126 // x
Robert Sloane56da3e2017-06-26 08:26:42 -0700127 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700130 // y
Robert Sloane56da3e2017-06-26 08:26:42 -0700131 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700134 // order
Robert Sloane56da3e2017-06-26 08:26:42 -0700135 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};
Adam Langleyd9e397b2015-01-22 14:27:53 -0800139
Robert Sloane56da3e2017-06-26 08:26:42 -0700140static const uint8_t kP384Params[6 * 48] = {
Robert Sloan8f860b12017-08-28 07:37:06 -0700141 // p
Robert Sloane56da3e2017-06-26 08:26:42 -0700142 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700146 // a
Robert Sloane56da3e2017-06-26 08:26:42 -0700147 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700151 // b
Robert Sloane56da3e2017-06-26 08:26:42 -0700152 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700156 // x
Robert Sloane56da3e2017-06-26 08:26:42 -0700157 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700161 // y
Robert Sloane56da3e2017-06-26 08:26:42 -0700162 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700166 // order
Robert Sloane56da3e2017-06-26 08:26:42 -0700167 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};
Robert Sloan8ff03552017-06-14 12:40:58 -0700172
Robert Sloane56da3e2017-06-26 08:26:42 -0700173static const uint8_t kP521Params[6 * 66] = {
Robert Sloan8f860b12017-08-28 07:37:06 -0700174 // p
Robert Sloane56da3e2017-06-26 08:26:42 -0700175 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700181 // a
Robert Sloane56da3e2017-06-26 08:26:42 -0700182 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700188 // b
Robert Sloane56da3e2017-06-26 08:26:42 -0700189 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700195 // x
Robert Sloane56da3e2017-06-26 08:26:42 -0700196 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700202 // y
Robert Sloane56da3e2017-06-26 08:26:42 -0700203 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,
Robert Sloan8f860b12017-08-28 07:37:06 -0700209 // order
Robert Sloane56da3e2017-06-26 08:26:42 -0700210 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};
Adam Langleyd9e397b2015-01-22 14:27:53 -0800217
Robert Sloan8ff03552017-06-14 12:40:58 -0700218DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700219 // 1.3.132.0.35
Robert Sloan8ff03552017-06-14 12:40:58 -0700220 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);
Robert Sloane56da3e2017-06-26 08:26:42 -0700224 out->curves[0].comment = "NIST P-521";
225 out->curves[0].param_len = 66;
226 out->curves[0].params = kP521Params;
Robert Sloan8ff03552017-06-14 12:40:58 -0700227 out->curves[0].method = EC_GFp_mont_method();
228
Robert Sloan8f860b12017-08-28 07:37:06 -0700229 // 1.3.132.0.34
Robert Sloan8ff03552017-06-14 12:40:58 -0700230 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);
Robert Sloane56da3e2017-06-26 08:26:42 -0700234 out->curves[1].comment = "NIST P-384";
235 out->curves[1].param_len = 48;
236 out->curves[1].params = kP384Params;
Robert Sloan8ff03552017-06-14 12:40:58 -0700237 out->curves[1].method = EC_GFp_mont_method();
238
Robert Sloan8f860b12017-08-28 07:37:06 -0700239 // 1.2.840.10045.3.1.7
Robert Sloan8ff03552017-06-14 12:40:58 -0700240 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);
Robert Sloane56da3e2017-06-26 08:26:42 -0700245 out->curves[2].comment = "NIST P-256";
246 out->curves[2].param_len = 32;
247 out->curves[2].params = kP256Params;
Robert Sloan8ff03552017-06-14 12:40:58 -0700248 out->curves[2].method =
Adam Langleyfad63272015-11-12 12:15:39 -0800249#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
250 !defined(OPENSSL_SMALL)
Robert Sloan8ff03552017-06-14 12:40:58 -0700251 EC_GFp_nistz256_method();
Adam Langleyfad63272015-11-12 12:15:39 -0800252#else
Robert Sloan8ff03552017-06-14 12:40:58 -0700253 EC_GFp_nistp256_method();
Adam Langleyfad63272015-11-12 12:15:39 -0800254#endif
Robert Sloan8ff03552017-06-14 12:40:58 -0700255
Robert Sloan8f860b12017-08-28 07:37:06 -0700256 // 1.3.132.0.33
Robert Sloan8ff03552017-06-14 12:40:58 -0700257 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);
Robert Sloane56da3e2017-06-26 08:26:42 -0700261 out->curves[3].comment = "NIST P-224";
262 out->curves[3].param_len = 28;
263 out->curves[3].params = kP224Params;
Robert Sloan8ff03552017-06-14 12:40:58 -0700264 out->curves[3].method =
Robert Sloan55818102017-12-18 11:26:17 -0800265#if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL)
Robert Sloan8ff03552017-06-14 12:40:58 -0700266 EC_GFp_nistp224_method();
Kenny Roote99801b2015-11-06 15:31:15 -0800267#else
Robert Sloan8ff03552017-06-14 12:40:58 -0700268 EC_GFp_mont_method();
Kenny Roote99801b2015-11-06 15:31:15 -0800269#endif
Robert Sloan8ff03552017-06-14 12:40:58 -0700270}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800271
272EC_GROUP *ec_group_new(const EC_METHOD *meth) {
273 EC_GROUP *ret;
274
275 if (meth == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000276 OPENSSL_PUT_ERROR(EC, EC_R_SLOT_FULL);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800277 return NULL;
278 }
279
280 if (meth->group_init == 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000281 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800282 return NULL;
283 }
284
285 ret = OPENSSL_malloc(sizeof(EC_GROUP));
286 if (ret == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000287 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800288 return NULL;
289 }
Robert Sloan69939df2017-01-09 10:53:07 -0800290 OPENSSL_memset(ret, 0, sizeof(EC_GROUP));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800291
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700292 ret->references = 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800293 ret->meth = meth;
294 BN_init(&ret->order);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800295
296 if (!meth->group_init(ret)) {
297 OPENSSL_free(ret);
298 return NULL;
299 }
300
301 return ret;
302}
303
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700304static 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
Adam Langley430091c2015-05-12 19:09:47 -0700317EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
318 const BIGNUM *b, BN_CTX *ctx) {
Robert Sloan99319a12017-11-27 10:32:46 -0800319 if (BN_num_bytes(p) > EC_MAX_SCALAR_BYTES) {
320 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
321 return NULL;
322 }
323
Robert Sloan8ff03552017-06-14 12:40:58 -0700324 EC_GROUP *ret = ec_group_new(EC_GFp_mont_method());
Adam Langleyd9e397b2015-01-22 14:27:53 -0800325 if (ret == NULL) {
326 return NULL;
327 }
328
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700329 if (ret->meth->group_set_curve == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000330 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700331 EC_GROUP_free(ret);
332 return NULL;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800333 }
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
Adam Langley430091c2015-05-12 19:09:47 -0700341int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
342 const BIGNUM *order, const BIGNUM *cofactor) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700343 if (group->curve_name != NID_undef || group->generator != NULL ||
344 generator->group != group) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700345 // |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.
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700347 // Additionally, |generator| must been created from
348 // |EC_GROUP_new_curve_GFp|, not a copy, so that
349 // |generator->group->generator| is set correctly.
Robert Sloan99319a12017-11-27 10:32:46 -0800350 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
351 return 0;
352 }
353
354 if (BN_num_bytes(order) > EC_MAX_SCALAR_BYTES) {
355 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD);
Adam Langleyf4e42722015-06-04 17:45:09 -0700356 return 0;
357 }
358
Robert Sloan8f860b12017-08-28 07:37:06 -0700359 // Require a cofactor of one for custom curves, which implies prime order.
David Benjaminc895d6b2016-08-11 13:26:41 -0400360 if (!BN_is_one(cofactor)) {
361 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COFACTOR);
362 return 0;
363 }
364
Robert Sloan99319a12017-11-27 10:32:46 -0800365 // Require that p < 2×order. This simplifies some ECDSA operations.
366 //
367 // Note any curve which did not satisfy this must have been invalid or use a
368 // tiny prime (less than 17). See the proof in |field_element_to_scalar| in
369 // the ECDSA implementation.
370 BIGNUM *tmp = BN_new();
371 if (tmp == NULL ||
372 !BN_lshift1(tmp, order)) {
373 BN_free(tmp);
374 return 0;
375 }
376 int ok = BN_cmp(tmp, &group->field) > 0;
377 BN_free(tmp);
378 if (!ok) {
379 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
380 return 0;
381 }
382
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700383 EC_POINT *copy = EC_POINT_new(group);
384 if (copy == NULL ||
385 !EC_POINT_copy(copy, generator) ||
386 !BN_copy(&group->order, order)) {
387 EC_POINT_free(copy);
388 return 0;
389 }
Robert Sloanab8b8882018-03-26 11:39:51 -0700390 // Store the order in minimal form, so it can be used with |BN_ULONG| arrays.
391 bn_set_minimal_width(&group->order);
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700392
Robert Sloan99319a12017-11-27 10:32:46 -0800393 BN_MONT_CTX_free(group->order_mont);
Robert Sloan8542c082018-02-05 09:07:34 -0800394 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
395 if (group->order_mont == NULL) {
Robert Sloan99319a12017-11-27 10:32:46 -0800396 return 0;
397 }
398
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700399 ec_group_set0_generator(group, copy);
400 return 1;
Adam Langley430091c2015-05-12 19:09:47 -0700401}
402
Robert Sloan99319a12017-11-27 10:32:46 -0800403static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800404 EC_GROUP *group = NULL;
405 EC_POINT *P = NULL;
Kenny Rootb8494592015-09-25 02:29:14 +0000406 BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
Adam Langleyfad63272015-11-12 12:15:39 -0800407 int ok = 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800408
Adam Langleyfad63272015-11-12 12:15:39 -0800409 BN_CTX *ctx = BN_CTX_new();
410 if (ctx == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000411 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800412 goto err;
413 }
414
Robert Sloane56da3e2017-06-26 08:26:42 -0700415 const unsigned param_len = curve->param_len;
416 const uint8_t *params = curve->params;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800417
418 if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
419 !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
420 !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
Kenny Rootb8494592015-09-25 02:29:14 +0000421 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800422 goto err;
423 }
424
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400425 group = ec_group_new(curve->method);
426 if (group == NULL ||
427 !group->meth->group_set_curve(group, p, a, b, ctx)) {
428 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
429 goto err;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800430 }
431
432 if ((P = EC_POINT_new(group)) == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000433 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800434 goto err;
435 }
436
437 if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
438 !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
Kenny Rootb8494592015-09-25 02:29:14 +0000439 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800440 goto err;
441 }
442
443 if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000444 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800445 goto err;
446 }
David Benjaminc895d6b2016-08-11 13:26:41 -0400447 if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000448 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800449 goto err;
450 }
451
Robert Sloan8542c082018-02-05 09:07:34 -0800452 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx);
453 if (group->order_mont == NULL) {
Robert Sloan99319a12017-11-27 10:32:46 -0800454 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
455 goto err;
Adam Langleyfad63272015-11-12 12:15:39 -0800456 }
457
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700458 ec_group_set0_generator(group, P);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800459 P = NULL;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800460 ok = 1;
461
462err:
463 if (!ok) {
464 EC_GROUP_free(group);
465 group = NULL;
466 }
Adam Langleye9ada862015-05-11 17:20:37 -0700467 EC_POINT_free(P);
468 BN_CTX_free(ctx);
469 BN_free(p);
470 BN_free(a);
471 BN_free(b);
Adam Langleye9ada862015-05-11 17:20:37 -0700472 BN_free(x);
473 BN_free(y);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800474 return group;
475}
476
Robert Sloan99319a12017-11-27 10:32:46 -0800477// Built-in groups are allocated lazily and static once allocated.
478// TODO(davidben): Make these actually static. https://crbug.com/boringssl/20.
479struct built_in_groups_st {
480 EC_GROUP *groups[OPENSSL_NUM_BUILT_IN_CURVES];
481};
482DEFINE_BSS_GET(struct built_in_groups_st, built_in_groups);
483DEFINE_STATIC_MUTEX(built_in_groups_lock);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800484
Robert Sloan99319a12017-11-27 10:32:46 -0800485EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
486 struct built_in_groups_st *groups = built_in_groups_bss_get();
487 EC_GROUP **group_ptr = NULL;
488 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
489 const struct built_in_curve *curve = NULL;
Robert Sloan8ff03552017-06-14 12:40:58 -0700490 for (size_t i = 0; i < OPENSSL_NUM_BUILT_IN_CURVES; i++) {
Robert Sloan99319a12017-11-27 10:32:46 -0800491 if (curves->curves[i].nid == nid) {
492 curve = &curves->curves[i];
493 group_ptr = &groups->groups[i];
Adam Langleyd9e397b2015-01-22 14:27:53 -0800494 break;
495 }
496 }
497
Robert Sloan99319a12017-11-27 10:32:46 -0800498 if (curve == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000499 OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800500 return NULL;
501 }
502
Robert Sloan99319a12017-11-27 10:32:46 -0800503 CRYPTO_STATIC_MUTEX_lock_read(built_in_groups_lock_bss_get());
504 EC_GROUP *ret = *group_ptr;
505 CRYPTO_STATIC_MUTEX_unlock_read(built_in_groups_lock_bss_get());
506 if (ret != NULL) {
507 return ret;
508 }
509
510 ret = ec_group_new_from_data(curve);
511 if (ret == NULL) {
512 return NULL;
513 }
514
515 EC_GROUP *to_free = NULL;
516 CRYPTO_STATIC_MUTEX_lock_write(built_in_groups_lock_bss_get());
517 if (*group_ptr == NULL) {
518 *group_ptr = ret;
519 // Filling in |ret->curve_name| makes |EC_GROUP_free| and |EC_GROUP_dup|
520 // into no-ops. At this point, |ret| is considered static.
521 ret->curve_name = nid;
522 } else {
523 to_free = ret;
524 ret = *group_ptr;
525 }
526 CRYPTO_STATIC_MUTEX_unlock_write(built_in_groups_lock_bss_get());
527
528 EC_GROUP_free(to_free);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800529 return ret;
530}
531
532void EC_GROUP_free(EC_GROUP *group) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700533 if (group == NULL ||
Robert Sloan99319a12017-11-27 10:32:46 -0800534 // Built-in curves are static.
535 group->curve_name != NID_undef ||
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700536 !CRYPTO_refcount_dec_and_test_zero(&group->references)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800537 return;
538 }
539
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700540 if (group->meth->group_finish != NULL) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800541 group->meth->group_finish(group);
542 }
543
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700544 ec_point_free(group->generator, 0 /* don't free group */);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800545 BN_free(&group->order);
Robert Sloan99319a12017-11-27 10:32:46 -0800546 BN_MONT_CTX_free(group->order_mont);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800547
548 OPENSSL_free(group);
549}
550
Adam Langleyd9e397b2015-01-22 14:27:53 -0800551EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
Robert Sloan99319a12017-11-27 10:32:46 -0800552 if (a == NULL ||
553 // Built-in curves are static.
554 a->curve_name != NID_undef) {
555 return (EC_GROUP *)a;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800556 }
557
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700558 // Groups are logically immutable (but for |EC_GROUP_set_generator| which must
559 // be called early on), so we simply take a reference.
560 EC_GROUP *group = (EC_GROUP *)a;
561 CRYPTO_refcount_inc(&group->references);
562 return group;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800563}
564
Kenny Rootc897c7e2015-02-27 13:00:38 -0800565int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700566 // Note this function returns 0 if equal and non-zero otherwise.
567 if (a == b) {
568 return 0;
569 }
570 if (a->curve_name != b->curve_name) {
571 return 1;
572 }
573 if (a->curve_name != NID_undef) {
574 // Built-in curves may be compared by curve name alone.
575 return 0;
576 }
577
578 // |a| and |b| are both custom curves. We compare the entire curve
579 // structure. If |a| or |b| is incomplete (due to legacy OpenSSL mistakes,
580 // custom curve construction is sadly done in two parts) but otherwise not the
581 // same object, we consider them always unequal.
582 return a->generator == NULL ||
583 b->generator == NULL ||
584 BN_cmp(&a->order, &b->order) != 0 ||
585 BN_cmp(&a->field, &b->field) != 0 ||
586 BN_cmp(&a->a, &b->a) != 0 ||
587 BN_cmp(&a->b, &b->b) != 0 ||
588 ec_GFp_simple_cmp(a, a->generator, b->generator, NULL) != 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800589}
590
591const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
592 return group->generator;
593}
594
Adam Langley4139edb2016-01-13 15:00:54 -0800595const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
596 assert(!BN_is_zero(&group->order));
597 return &group->order;
598}
599
Adam Langleyd9e397b2015-01-22 14:27:53 -0800600int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
Adam Langley4139edb2016-01-13 15:00:54 -0800601 if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800602 return 0;
603 }
Adam Langley4139edb2016-01-13 15:00:54 -0800604 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800605}
606
607int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
608 BN_CTX *ctx) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700609 // All |EC_GROUP|s have cofactor 1.
David Benjaminc895d6b2016-08-11 13:26:41 -0400610 return BN_set_word(cofactor, 1);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800611}
612
613int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
614 BIGNUM *out_b, BN_CTX *ctx) {
Kenny Roote99801b2015-11-06 15:31:15 -0800615 return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800616}
617
618int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
619
Kenny Roote99801b2015-11-06 15:31:15 -0800620unsigned EC_GROUP_get_degree(const EC_GROUP *group) {
621 return ec_GFp_simple_group_get_degree(group);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800622}
623
Adam Langleyd9e397b2015-01-22 14:27:53 -0800624EC_POINT *EC_POINT_new(const EC_GROUP *group) {
625 EC_POINT *ret;
626
627 if (group == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000628 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800629 return NULL;
630 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800631
632 ret = OPENSSL_malloc(sizeof *ret);
633 if (ret == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000634 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800635 return NULL;
636 }
637
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700638 ret->group = EC_GROUP_dup(group);
639 if (ret->group == NULL ||
640 !ec_GFp_simple_point_init(ret)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800641 OPENSSL_free(ret);
642 return NULL;
643 }
644
645 return ret;
646}
647
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700648static void ec_point_free(EC_POINT *point, int free_group) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800649 if (!point) {
650 return;
651 }
Kenny Roote99801b2015-11-06 15:31:15 -0800652 ec_GFp_simple_point_finish(point);
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700653 if (free_group) {
654 EC_GROUP_free(point->group);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800655 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800656 OPENSSL_free(point);
657}
658
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700659void EC_POINT_free(EC_POINT *point) {
660 ec_point_free(point, 1 /* free group */);
661}
662
663void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
664
Adam Langleyd9e397b2015-01-22 14:27:53 -0800665int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700666 if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000667 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800668 return 0;
669 }
670 if (dest == src) {
671 return 1;
672 }
Kenny Roote99801b2015-11-06 15:31:15 -0800673 return ec_GFp_simple_point_copy(dest, src);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800674}
675
676EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800677 if (a == NULL) {
678 return NULL;
679 }
680
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400681 EC_POINT *ret = EC_POINT_new(group);
682 if (ret == NULL ||
683 !EC_POINT_copy(ret, a)) {
684 EC_POINT_free(ret);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800685 return NULL;
686 }
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400687
688 return ret;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800689}
690
691int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700692 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000693 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800694 return 0;
695 }
Kenny Roote99801b2015-11-06 15:31:15 -0800696 return ec_GFp_simple_point_set_to_infinity(group, point);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800697}
698
699int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700700 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000701 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800702 return 0;
703 }
Kenny Roote99801b2015-11-06 15:31:15 -0800704 return ec_GFp_simple_is_at_infinity(group, point);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800705}
706
707int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
708 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700709 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000710 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800711 return 0;
712 }
Kenny Roote99801b2015-11-06 15:31:15 -0800713 return ec_GFp_simple_is_on_curve(group, point, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800714}
715
716int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
717 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700718 if (EC_GROUP_cmp(group, a->group, NULL) != 0 ||
719 EC_GROUP_cmp(group, b->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000720 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800721 return -1;
722 }
Kenny Roote99801b2015-11-06 15:31:15 -0800723 return ec_GFp_simple_cmp(group, a, b, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800724}
725
726int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700727 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000728 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800729 return 0;
730 }
Kenny Roote99801b2015-11-06 15:31:15 -0800731 return ec_GFp_simple_make_affine(group, point, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800732}
733
734int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
735 BN_CTX *ctx) {
David Benjamin7c0d06c2016-08-11 13:26:41 -0400736 for (size_t i = 0; i < num; i++) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700737 if (EC_GROUP_cmp(group, points[i]->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000738 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800739 return 0;
740 }
741 }
Kenny Roote99801b2015-11-06 15:31:15 -0800742 return ec_GFp_simple_points_make_affine(group, num, points, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800743}
744
745int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
746 const EC_POINT *point, BIGNUM *x,
747 BIGNUM *y, BN_CTX *ctx) {
748 if (group->meth->point_get_affine_coordinates == 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000749 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800750 return 0;
751 }
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700752 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000753 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800754 return 0;
755 }
756 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
757}
758
759int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
760 const BIGNUM *x, const BIGNUM *y,
761 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700762 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000763 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800764 return 0;
765 }
Adam Langleyfad63272015-11-12 12:15:39 -0800766 if (!ec_GFp_simple_point_set_affine_coordinates(group, point, x, y, ctx)) {
767 return 0;
768 }
769
770 if (!EC_POINT_is_on_curve(group, point, ctx)) {
Robert Sloan8542c082018-02-05 09:07:34 -0800771 // In the event of an error, defend against the caller not checking the
772 // return value by setting a known safe value: the base point.
Adam Langley9083ef92018-03-05 10:15:53 -0800773 const EC_POINT *generator = EC_GROUP_get0_generator(group);
774 // The generator can be missing if the caller is in the process of
775 // constructing an arbitrary group. In this, we give up and hope they're
776 // checking the return value.
777 if (generator) {
778 EC_POINT_copy(point, generator);
779 }
Adam Langleyfad63272015-11-12 12:15:39 -0800780 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
781 return 0;
782 }
783
784 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800785}
786
787int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
788 const EC_POINT *b, BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700789 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
790 EC_GROUP_cmp(group, a->group, NULL) != 0 ||
791 EC_GROUP_cmp(group, b->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000792 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800793 return 0;
794 }
Kenny Roote99801b2015-11-06 15:31:15 -0800795 return ec_GFp_simple_add(group, r, a, b, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800796}
797
798
799int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
800 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700801 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
802 EC_GROUP_cmp(group, a->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000803 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800804 return 0;
805 }
Kenny Roote99801b2015-11-06 15:31:15 -0800806 return ec_GFp_simple_dbl(group, r, a, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800807}
808
809
810int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700811 if (EC_GROUP_cmp(group, a->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000812 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800813 return 0;
814 }
Kenny Roote99801b2015-11-06 15:31:15 -0800815 return ec_GFp_simple_invert(group, a, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800816}
817
Robert Sloana815d5a2017-12-04 11:49:16 -0800818static int arbitrary_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
819 const BIGNUM *in, BN_CTX *ctx) {
Robert Sloancd79cde2017-12-11 09:06:12 -0800820 if (ec_bignum_to_scalar(group, out, in)) {
821 return 1;
Robert Sloana815d5a2017-12-04 11:49:16 -0800822 }
823
Robert Sloancd79cde2017-12-11 09:06:12 -0800824 ERR_clear_error();
825
Robert Sloanab8b8882018-03-26 11:39:51 -0700826 // This is an unusual input, so we do not guarantee constant-time processing.
Robert Sloancd79cde2017-12-11 09:06:12 -0800827 const BIGNUM *order = &group->order;
828 BN_CTX_start(ctx);
829 BIGNUM *tmp = BN_CTX_get(ctx);
830 int ok = tmp != NULL &&
831 BN_nnmod(tmp, in, order, ctx) &&
832 ec_bignum_to_scalar_unchecked(group, out, tmp);
833 BN_CTX_end(ctx);
834 return ok;
Robert Sloana815d5a2017-12-04 11:49:16 -0800835}
836
Adam Langleyd9e397b2015-01-22 14:27:53 -0800837int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
Adam Langley4139edb2016-01-13 15:00:54 -0800838 const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700839 // Previously, this function set |r| to the point at infinity if there was
840 // nothing to multiply. But, nobody should be calling this function with
841 // nothing to multiply in the first place.
Adam Langley4139edb2016-01-13 15:00:54 -0800842 if ((g_scalar == NULL && p_scalar == NULL) ||
Robert Sloan99319a12017-11-27 10:32:46 -0800843 (p == NULL) != (p_scalar == NULL)) {
844 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
845 return 0;
846 }
847
Robert Sloan99319a12017-11-27 10:32:46 -0800848 int ret = 0;
849 EC_SCALAR g_scalar_storage, p_scalar_storage;
850 EC_SCALAR *g_scalar_arg = NULL, *p_scalar_arg = NULL;
Robert Sloana815d5a2017-12-04 11:49:16 -0800851 BN_CTX *new_ctx = NULL;
852 if (ctx == NULL) {
853 new_ctx = BN_CTX_new();
854 if (new_ctx == NULL) {
855 goto err;
856 }
857 ctx = new_ctx;
858 }
859
Robert Sloan99319a12017-11-27 10:32:46 -0800860 if (g_scalar != NULL) {
Robert Sloana815d5a2017-12-04 11:49:16 -0800861 if (!arbitrary_bignum_to_scalar(group, &g_scalar_storage, g_scalar, ctx)) {
Robert Sloan99319a12017-11-27 10:32:46 -0800862 goto err;
863 }
864 g_scalar_arg = &g_scalar_storage;
865 }
866
867 if (p_scalar != NULL) {
Robert Sloana815d5a2017-12-04 11:49:16 -0800868 if (!arbitrary_bignum_to_scalar(group, &p_scalar_storage, p_scalar, ctx)) {
Robert Sloan99319a12017-11-27 10:32:46 -0800869 goto err;
870 }
871 p_scalar_arg = &p_scalar_storage;
872 }
873
874 ret = ec_point_mul_scalar(group, r, g_scalar_arg, p, p_scalar_arg, ctx);
875
876err:
Robert Sloana815d5a2017-12-04 11:49:16 -0800877 BN_CTX_free(new_ctx);
Robert Sloan99319a12017-11-27 10:32:46 -0800878 OPENSSL_cleanse(&g_scalar_storage, sizeof(g_scalar_storage));
879 OPENSSL_cleanse(&p_scalar_storage, sizeof(p_scalar_storage));
880 return ret;
881}
882
Robert Sloan55818102017-12-18 11:26:17 -0800883int ec_point_mul_scalar_public(const EC_GROUP *group, EC_POINT *r,
884 const EC_SCALAR *g_scalar, const EC_POINT *p,
885 const EC_SCALAR *p_scalar, BN_CTX *ctx) {
886 if ((g_scalar == NULL && p_scalar == NULL) ||
887 (p == NULL) != (p_scalar == NULL)) {
888 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
889 return 0;
890 }
891
892 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
893 (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
894 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
895 return 0;
896 }
897
898 return group->meth->mul_public(group, r, g_scalar, p, p_scalar, ctx);
899}
900
Robert Sloan99319a12017-11-27 10:32:46 -0800901int ec_point_mul_scalar(const EC_GROUP *group, EC_POINT *r,
902 const EC_SCALAR *g_scalar, const EC_POINT *p,
903 const EC_SCALAR *p_scalar, BN_CTX *ctx) {
904 if ((g_scalar == NULL && p_scalar == NULL) ||
905 (p == NULL) != (p_scalar == NULL)) {
Adam Langley4139edb2016-01-13 15:00:54 -0800906 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
907 return 0;
908 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800909
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700910 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
911 (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
Adam Langleyfad63272015-11-12 12:15:39 -0800912 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
913 return 0;
914 }
915
Adam Langley4139edb2016-01-13 15:00:54 -0800916 return group->meth->mul(group, r, g_scalar, p, p_scalar, ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800917}
918
Adam Langleyf7e890d2015-03-31 18:58:05 -0700919void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
920
921const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
922 return NULL;
923}
924
925int EC_METHOD_get_field_type(const EC_METHOD *meth) {
926 return NID_X9_62_prime_field;
927}
Adam Langley830beae2015-04-20 10:49:33 -0700928
929void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
930 point_conversion_form_t form) {
931 if (form != POINT_CONVERSION_UNCOMPRESSED) {
932 abort();
933 }
934}
David Benjamin4969cc92016-04-22 15:02:23 -0400935
936size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
937 size_t max_num_curves) {
Robert Sloan8ff03552017-06-14 12:40:58 -0700938 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
939
940 for (size_t i = 0; i < max_num_curves && i < OPENSSL_NUM_BUILT_IN_CURVES;
941 i++) {
Robert Sloane56da3e2017-06-26 08:26:42 -0700942 out_curves[i].comment = curves->curves[i].comment;
Robert Sloan8ff03552017-06-14 12:40:58 -0700943 out_curves[i].nid = curves->curves[i].nid;
David Benjamin4969cc92016-04-22 15:02:23 -0400944 }
945
Robert Sloan8ff03552017-06-14 12:40:58 -0700946 return OPENSSL_NUM_BUILT_IN_CURVES;
David Benjamin4969cc92016-04-22 15:02:23 -0400947}
Robert Sloan99319a12017-11-27 10:32:46 -0800948
949int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
950 const BIGNUM *in) {
Robert Sloancd79cde2017-12-11 09:06:12 -0800951 if (!ec_bignum_to_scalar_unchecked(group, out, in)) {
952 return 0;
953 }
Robert Sloanab8b8882018-03-26 11:39:51 -0700954 if (!bn_less_than_words(out->words, group->order.d, group->order.width)) {
Robert Sloancd79cde2017-12-11 09:06:12 -0800955 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR);
956 return 0;
957 }
958 return 1;
959}
960
961int ec_bignum_to_scalar_unchecked(const EC_GROUP *group, EC_SCALAR *out,
962 const BIGNUM *in) {
Robert Sloanab8b8882018-03-26 11:39:51 -0700963 if (!bn_copy_words(out->words, group->order.width, in)) {
Robert Sloan99319a12017-11-27 10:32:46 -0800964 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR);
965 return 0;
966 }
Robert Sloan99319a12017-11-27 10:32:46 -0800967 return 1;
968}
969
970int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out,
971 const uint8_t additional_data[32]) {
Robert Sloanab8b8882018-03-26 11:39:51 -0700972 return bn_rand_range_words(out->words, 1, group->order.d, group->order.width,
Robert Sloan99319a12017-11-27 10:32:46 -0800973 additional_data);
974}