blob: ba101fea9bc1eabb11c90a24c553ee272550ed2a [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) {
Robert Sloan5cbb5c82018-04-24 11:35:46 -0700355 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
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.
Robert Sloanc6ebb282018-04-30 10:10:26 -0700582 return a->meth != b->meth ||
583 a->generator == NULL ||
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700584 b->generator == NULL ||
585 BN_cmp(&a->order, &b->order) != 0 ||
586 BN_cmp(&a->field, &b->field) != 0 ||
Robert Sloanc6ebb282018-04-30 10:10:26 -0700587 !ec_felem_equal(a, &a->a, &b->a) ||
588 !ec_felem_equal(a, &a->b, &b->b) ||
589 ec_GFp_simple_cmp(a, &a->generator->raw, &b->generator->raw) != 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800590}
591
592const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
593 return group->generator;
594}
595
Adam Langley4139edb2016-01-13 15:00:54 -0800596const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
597 assert(!BN_is_zero(&group->order));
598 return &group->order;
599}
600
Adam Langleyd9e397b2015-01-22 14:27:53 -0800601int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
Adam Langley4139edb2016-01-13 15:00:54 -0800602 if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800603 return 0;
604 }
Adam Langley4139edb2016-01-13 15:00:54 -0800605 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800606}
607
608int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
609 BN_CTX *ctx) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700610 // All |EC_GROUP|s have cofactor 1.
David Benjaminc895d6b2016-08-11 13:26:41 -0400611 return BN_set_word(cofactor, 1);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800612}
613
614int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
615 BIGNUM *out_b, BN_CTX *ctx) {
Robert Sloanc6ebb282018-04-30 10:10:26 -0700616 return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800617}
618
619int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
620
Kenny Roote99801b2015-11-06 15:31:15 -0800621unsigned EC_GROUP_get_degree(const EC_GROUP *group) {
Robert Sloana51059f2018-11-12 13:38:50 -0800622 return BN_num_bits(&group->field);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800623}
624
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100625const char *EC_curve_nid2nist(int nid) {
626 switch (nid) {
627 case NID_secp224r1:
628 return "P-224";
629 case NID_X9_62_prime256v1:
630 return "P-256";
631 case NID_secp384r1:
632 return "P-384";
633 case NID_secp521r1:
634 return "P-521";
635 }
636 return NULL;
637}
638
Adam Langleyd9e397b2015-01-22 14:27:53 -0800639EC_POINT *EC_POINT_new(const EC_GROUP *group) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800640 if (group == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000641 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800642 return NULL;
643 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800644
Robert Sloanc6ebb282018-04-30 10:10:26 -0700645 EC_POINT *ret = OPENSSL_malloc(sizeof *ret);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800646 if (ret == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000647 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800648 return NULL;
649 }
650
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700651 ret->group = EC_GROUP_dup(group);
Robert Sloanc6ebb282018-04-30 10:10:26 -0700652 ec_GFp_simple_point_init(&ret->raw);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800653 return ret;
654}
655
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700656static void ec_point_free(EC_POINT *point, int free_group) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800657 if (!point) {
658 return;
659 }
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700660 if (free_group) {
661 EC_GROUP_free(point->group);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800662 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800663 OPENSSL_free(point);
664}
665
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700666void EC_POINT_free(EC_POINT *point) {
667 ec_point_free(point, 1 /* free group */);
668}
669
670void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
671
Adam Langleyd9e397b2015-01-22 14:27:53 -0800672int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700673 if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000674 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800675 return 0;
676 }
677 if (dest == src) {
678 return 1;
679 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700680 ec_GFp_simple_point_copy(&dest->raw, &src->raw);
681 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800682}
683
684EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800685 if (a == NULL) {
686 return NULL;
687 }
688
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400689 EC_POINT *ret = EC_POINT_new(group);
690 if (ret == NULL ||
691 !EC_POINT_copy(ret, a)) {
692 EC_POINT_free(ret);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800693 return NULL;
694 }
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400695
696 return ret;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800697}
698
699int EC_POINT_set_to_infinity(const EC_GROUP *group, 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 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700704 ec_GFp_simple_point_set_to_infinity(group, &point->raw);
705 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800706}
707
708int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
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 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700713 return ec_GFp_simple_is_at_infinity(group, &point->raw);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800714}
715
716int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
717 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700718 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000719 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800720 return 0;
721 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700722 return ec_GFp_simple_is_on_curve(group, &point->raw);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800723}
724
725int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
726 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700727 if (EC_GROUP_cmp(group, a->group, NULL) != 0 ||
728 EC_GROUP_cmp(group, b->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000729 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800730 return -1;
731 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700732 return ec_GFp_simple_cmp(group, &a->raw, &b->raw);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800733}
734
735int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
736 const EC_POINT *point, BIGNUM *x,
737 BIGNUM *y, BN_CTX *ctx) {
738 if (group->meth->point_get_affine_coordinates == 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000739 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800740 return 0;
741 }
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700742 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000743 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800744 return 0;
745 }
Robert Sloana51059f2018-11-12 13:38:50 -0800746 EC_FELEM x_felem, y_felem;
747 if (!group->meth->point_get_affine_coordinates(group, &point->raw,
748 x == NULL ? NULL : &x_felem,
749 y == NULL ? NULL : &y_felem) ||
750 (x != NULL && !bn_set_words(x, x_felem.words, group->field.width)) ||
751 (y != NULL && !bn_set_words(y, y_felem.words, group->field.width))) {
752 return 0;
753 }
754 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800755}
756
757int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
758 const BIGNUM *x, const BIGNUM *y,
759 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700760 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000761 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800762 return 0;
763 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700764 if (!ec_GFp_simple_point_set_affine_coordinates(group, &point->raw, x, y)) {
Adam Langleyfad63272015-11-12 12:15:39 -0800765 return 0;
766 }
767
768 if (!EC_POINT_is_on_curve(group, point, ctx)) {
Robert Sloan8542c082018-02-05 09:07:34 -0800769 // In the event of an error, defend against the caller not checking the
770 // return value by setting a known safe value: the base point.
Adam Langley9083ef92018-03-05 10:15:53 -0800771 const EC_POINT *generator = EC_GROUP_get0_generator(group);
772 // The generator can be missing if the caller is in the process of
773 // constructing an arbitrary group. In this, we give up and hope they're
774 // checking the return value.
775 if (generator) {
Robert Sloanc6ebb282018-04-30 10:10:26 -0700776 ec_GFp_simple_point_copy(&point->raw, &generator->raw);
Adam Langley9083ef92018-03-05 10:15:53 -0800777 }
Adam Langleyfad63272015-11-12 12:15:39 -0800778 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
779 return 0;
780 }
781
782 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800783}
784
785int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
786 const EC_POINT *b, BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700787 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
788 EC_GROUP_cmp(group, a->group, NULL) != 0 ||
789 EC_GROUP_cmp(group, b->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000790 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800791 return 0;
792 }
Robert Sloana51059f2018-11-12 13:38:50 -0800793 group->meth->add(group, &r->raw, &a->raw, &b->raw);
Robert Sloanc6ebb282018-04-30 10:10:26 -0700794 return 1;
Robert Sloandc2f6092018-04-10 10:22:33 -0700795}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800796
797int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
798 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700799 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
800 EC_GROUP_cmp(group, a->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000801 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800802 return 0;
803 }
Robert Sloana51059f2018-11-12 13:38:50 -0800804 group->meth->dbl(group, &r->raw, &a->raw);
Robert Sloanc6ebb282018-04-30 10:10:26 -0700805 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800806}
807
808
809int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700810 if (EC_GROUP_cmp(group, a->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000811 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800812 return 0;
813 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700814 ec_GFp_simple_invert(group, &a->raw);
815 return 1;
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) &&
Robert Sloan5cbb5c82018-04-24 11:35:46 -0700832 ec_bignum_to_scalar(group, out, tmp);
Robert Sloancd79cde2017-12-11 09:06:12 -0800833 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
Robert Sloanc6ebb282018-04-30 10:10:26 -0700898 group->meth->mul_public(group, &r->raw, g_scalar, &p->raw, p_scalar);
899 return 1;
Robert Sloan55818102017-12-18 11:26:17 -0800900}
901
Robert Sloan99319a12017-11-27 10:32:46 -0800902int ec_point_mul_scalar(const EC_GROUP *group, EC_POINT *r,
903 const EC_SCALAR *g_scalar, const EC_POINT *p,
904 const EC_SCALAR *p_scalar, BN_CTX *ctx) {
905 if ((g_scalar == NULL && p_scalar == NULL) ||
906 (p == NULL) != (p_scalar == NULL)) {
Adam Langley4139edb2016-01-13 15:00:54 -0800907 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
908 return 0;
909 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800910
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700911 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
912 (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
Adam Langleyfad63272015-11-12 12:15:39 -0800913 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
914 return 0;
915 }
916
Robert Sloanc6ebb282018-04-30 10:10:26 -0700917 group->meth->mul(group, &r->raw, g_scalar, (p == NULL) ? NULL : &p->raw,
918 p_scalar);
919 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800920}
921
Robert Sloana51059f2018-11-12 13:38:50 -0800922int ec_cmp_x_coordinate(int *out_result, const EC_GROUP *group,
923 const EC_POINT *p, const BIGNUM *r, BN_CTX *ctx) {
924 return group->meth->cmp_x_coordinate(out_result, group, p, r, ctx);
925}
926
927int ec_field_element_to_scalar(const EC_GROUP *group, BIGNUM *r) {
928 // We must have p < 2×order, assuming p is not tiny (p >= 17). Thus rather we
929 // can reduce by performing at most one subtraction.
930 //
931 // Proof: We only work with prime order curves, so the number of points on
932 // the curve is the order. Thus Hasse's theorem gives:
933 //
934 // |order - (p + 1)| <= 2×sqrt(p)
935 // p + 1 - order <= 2×sqrt(p)
936 // p + 1 - 2×sqrt(p) <= order
937 // p + 1 - 2×(p/4) < order (p/4 > sqrt(p) for p >= 17)
938 // p/2 < p/2 + 1 < order
939 // p < 2×order
940 //
941 // Additionally, one can manually check this property for built-in curves. It
942 // is enforced for legacy custom curves in |EC_GROUP_set_generator|.
943 //
944 // TODO(davidben): Introduce |EC_FIELD_ELEMENT|, make this a function from
945 // |EC_FIELD_ELEMENT| to |EC_SCALAR|, and cut out the |BIGNUM|. Does this need
946 // to be constant-time for signing? |r| is the x-coordinate for kG, which is
947 // public unless k was rerolled because |s| was zero.
948 assert(!BN_is_negative(r));
949 assert(BN_cmp(r, &group->field) < 0);
950 if (BN_cmp(r, &group->order) >= 0 &&
951 !BN_sub(r, r, &group->order)) {
952 return 0;
953 }
954 assert(!BN_is_negative(r));
955 assert(BN_cmp(r, &group->order) < 0);
956 return 1;
957}
958
Adam Langleyf7e890d2015-03-31 18:58:05 -0700959void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
960
961const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100962 // This function exists purely to give callers a way to call
963 // |EC_METHOD_get_field_type|. cryptography.io crashes if |EC_GROUP_method_of|
964 // returns NULL, so return some other garbage pointer.
965 return (const EC_METHOD *)0x12340000;
Adam Langleyf7e890d2015-03-31 18:58:05 -0700966}
967
968int EC_METHOD_get_field_type(const EC_METHOD *meth) {
969 return NID_X9_62_prime_field;
970}
Adam Langley830beae2015-04-20 10:49:33 -0700971
972void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
973 point_conversion_form_t form) {
974 if (form != POINT_CONVERSION_UNCOMPRESSED) {
975 abort();
976 }
977}
David Benjamin4969cc92016-04-22 15:02:23 -0400978
979size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
980 size_t max_num_curves) {
Robert Sloan8ff03552017-06-14 12:40:58 -0700981 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
982
983 for (size_t i = 0; i < max_num_curves && i < OPENSSL_NUM_BUILT_IN_CURVES;
984 i++) {
Robert Sloane56da3e2017-06-26 08:26:42 -0700985 out_curves[i].comment = curves->curves[i].comment;
Robert Sloan8ff03552017-06-14 12:40:58 -0700986 out_curves[i].nid = curves->curves[i].nid;
David Benjamin4969cc92016-04-22 15:02:23 -0400987 }
988
Robert Sloan8ff03552017-06-14 12:40:58 -0700989 return OPENSSL_NUM_BUILT_IN_CURVES;
David Benjamin4969cc92016-04-22 15:02:23 -0400990}