blob: 158d66cc047db37be19de0c83c03344e54c5b94e [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 Sloanc9abfe42018-11-26 12:19:07 -0800319 if (BN_num_bytes(p) > EC_MAX_BYTES) {
Robert Sloan99319a12017-11-27 10:32:46 -0800320 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 Sloanc9abfe42018-11-26 12:19:07 -0800347 // |generator| must have been created from |EC_GROUP_new_curve_GFp|, not a
348 // copy, so that |generator->group->generator| is set correctly.
Robert Sloan99319a12017-11-27 10:32:46 -0800349 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
350 return 0;
351 }
352
Robert Sloanc9abfe42018-11-26 12:19:07 -0800353 if (BN_num_bytes(order) > EC_MAX_BYTES) {
Robert Sloan5cbb5c82018-04-24 11:35:46 -0700354 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
Adam Langleyf4e42722015-06-04 17:45:09 -0700355 return 0;
356 }
357
Robert Sloan8f860b12017-08-28 07:37:06 -0700358 // Require a cofactor of one for custom curves, which implies prime order.
David Benjaminc895d6b2016-08-11 13:26:41 -0400359 if (!BN_is_one(cofactor)) {
360 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COFACTOR);
361 return 0;
362 }
363
Robert Sloan99319a12017-11-27 10:32:46 -0800364 // Require that p < 2×order. This simplifies some ECDSA operations.
365 //
366 // Note any curve which did not satisfy this must have been invalid or use a
367 // tiny prime (less than 17). See the proof in |field_element_to_scalar| in
368 // the ECDSA implementation.
Robert Sloanc9abfe42018-11-26 12:19:07 -0800369 int ret = 0;
370 EC_POINT *copy = NULL;
Robert Sloan99319a12017-11-27 10:32:46 -0800371 BIGNUM *tmp = BN_new();
372 if (tmp == NULL ||
373 !BN_lshift1(tmp, order)) {
Robert Sloanc9abfe42018-11-26 12:19:07 -0800374 goto err;
Robert Sloan99319a12017-11-27 10:32:46 -0800375 }
Robert Sloanc9abfe42018-11-26 12:19:07 -0800376 if (BN_cmp(tmp, &group->field) <= 0) {
Robert Sloan99319a12017-11-27 10:32:46 -0800377 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
Robert Sloanc9abfe42018-11-26 12:19:07 -0800378 goto err;
Robert Sloan99319a12017-11-27 10:32:46 -0800379 }
380
Robert Sloanc9abfe42018-11-26 12:19:07 -0800381 copy = EC_POINT_new(group);
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700382 if (copy == NULL ||
383 !EC_POINT_copy(copy, generator) ||
384 !BN_copy(&group->order, order)) {
Robert Sloanc9abfe42018-11-26 12:19:07 -0800385 goto err;
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700386 }
Robert Sloanab8b8882018-03-26 11:39:51 -0700387 // Store the order in minimal form, so it can be used with |BN_ULONG| arrays.
388 bn_set_minimal_width(&group->order);
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700389
Robert Sloan99319a12017-11-27 10:32:46 -0800390 BN_MONT_CTX_free(group->order_mont);
Robert Sloan8542c082018-02-05 09:07:34 -0800391 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL);
392 if (group->order_mont == NULL) {
Robert Sloanc9abfe42018-11-26 12:19:07 -0800393 goto err;
394 }
395
396 group->field_greater_than_order = BN_cmp(&group->field, &group->order) > 0;
397 if (group->field_greater_than_order) {
398 if (!BN_sub(tmp, &group->field, &group->order) ||
399 !bn_copy_words(group->field_minus_order.words, group->field.width,
400 tmp)) {
401 goto err;
402 }
Robert Sloan99319a12017-11-27 10:32:46 -0800403 }
404
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700405 ec_group_set0_generator(group, copy);
Robert Sloanc9abfe42018-11-26 12:19:07 -0800406 copy = NULL;
407 ret = 1;
408
409err:
410 EC_POINT_free(copy);
411 BN_free(tmp);
412 return ret;
Adam Langley430091c2015-05-12 19:09:47 -0700413}
414
Robert Sloan99319a12017-11-27 10:32:46 -0800415static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800416 EC_GROUP *group = NULL;
417 EC_POINT *P = NULL;
Kenny Rootb8494592015-09-25 02:29:14 +0000418 BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
Adam Langleyfad63272015-11-12 12:15:39 -0800419 int ok = 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800420
Adam Langleyfad63272015-11-12 12:15:39 -0800421 BN_CTX *ctx = BN_CTX_new();
422 if (ctx == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000423 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800424 goto err;
425 }
426
Robert Sloane56da3e2017-06-26 08:26:42 -0700427 const unsigned param_len = curve->param_len;
428 const uint8_t *params = curve->params;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800429
430 if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
431 !(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
432 !(b = BN_bin2bn(params + 2 * param_len, param_len, NULL))) {
Kenny Rootb8494592015-09-25 02:29:14 +0000433 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800434 goto err;
435 }
436
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400437 group = ec_group_new(curve->method);
438 if (group == NULL ||
439 !group->meth->group_set_curve(group, p, a, b, ctx)) {
440 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
441 goto err;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800442 }
443
444 if ((P = EC_POINT_new(group)) == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000445 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800446 goto err;
447 }
448
449 if (!(x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) ||
450 !(y = BN_bin2bn(params + 4 * param_len, param_len, NULL))) {
Kenny Rootb8494592015-09-25 02:29:14 +0000451 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800452 goto err;
453 }
454
455 if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000456 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800457 goto err;
458 }
David Benjaminc895d6b2016-08-11 13:26:41 -0400459 if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000460 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800461 goto err;
462 }
463
Robert Sloanc9abfe42018-11-26 12:19:07 -0800464 group->field_greater_than_order = BN_cmp(&group->field, &group->order) > 0;
465 if (group->field_greater_than_order) {
466 if (!BN_sub(p, &group->field, &group->order) ||
467 !bn_copy_words(group->field_minus_order.words, group->field.width, p)) {
468 goto err;
469 }
470 }
471
Robert Sloan8542c082018-02-05 09:07:34 -0800472 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx);
473 if (group->order_mont == NULL) {
Robert Sloan99319a12017-11-27 10:32:46 -0800474 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
475 goto err;
Adam Langleyfad63272015-11-12 12:15:39 -0800476 }
477
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700478 ec_group_set0_generator(group, P);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800479 P = NULL;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800480 ok = 1;
481
482err:
483 if (!ok) {
484 EC_GROUP_free(group);
485 group = NULL;
486 }
Adam Langleye9ada862015-05-11 17:20:37 -0700487 EC_POINT_free(P);
488 BN_CTX_free(ctx);
489 BN_free(p);
490 BN_free(a);
491 BN_free(b);
Adam Langleye9ada862015-05-11 17:20:37 -0700492 BN_free(x);
493 BN_free(y);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800494 return group;
495}
496
Robert Sloan99319a12017-11-27 10:32:46 -0800497// Built-in groups are allocated lazily and static once allocated.
498// TODO(davidben): Make these actually static. https://crbug.com/boringssl/20.
499struct built_in_groups_st {
500 EC_GROUP *groups[OPENSSL_NUM_BUILT_IN_CURVES];
501};
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800502DEFINE_BSS_GET(struct built_in_groups_st, built_in_groups)
503DEFINE_STATIC_MUTEX(built_in_groups_lock)
Adam Langleyd9e397b2015-01-22 14:27:53 -0800504
Robert Sloan99319a12017-11-27 10:32:46 -0800505EC_GROUP *EC_GROUP_new_by_curve_name(int nid) {
506 struct built_in_groups_st *groups = built_in_groups_bss_get();
507 EC_GROUP **group_ptr = NULL;
508 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
509 const struct built_in_curve *curve = NULL;
Robert Sloan8ff03552017-06-14 12:40:58 -0700510 for (size_t i = 0; i < OPENSSL_NUM_BUILT_IN_CURVES; i++) {
Robert Sloan99319a12017-11-27 10:32:46 -0800511 if (curves->curves[i].nid == nid) {
512 curve = &curves->curves[i];
513 group_ptr = &groups->groups[i];
Adam Langleyd9e397b2015-01-22 14:27:53 -0800514 break;
515 }
516 }
517
Robert Sloan99319a12017-11-27 10:32:46 -0800518 if (curve == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000519 OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800520 return NULL;
521 }
522
Robert Sloan99319a12017-11-27 10:32:46 -0800523 CRYPTO_STATIC_MUTEX_lock_read(built_in_groups_lock_bss_get());
524 EC_GROUP *ret = *group_ptr;
525 CRYPTO_STATIC_MUTEX_unlock_read(built_in_groups_lock_bss_get());
526 if (ret != NULL) {
527 return ret;
528 }
529
530 ret = ec_group_new_from_data(curve);
531 if (ret == NULL) {
532 return NULL;
533 }
534
535 EC_GROUP *to_free = NULL;
536 CRYPTO_STATIC_MUTEX_lock_write(built_in_groups_lock_bss_get());
537 if (*group_ptr == NULL) {
538 *group_ptr = ret;
539 // Filling in |ret->curve_name| makes |EC_GROUP_free| and |EC_GROUP_dup|
540 // into no-ops. At this point, |ret| is considered static.
541 ret->curve_name = nid;
542 } else {
543 to_free = ret;
544 ret = *group_ptr;
545 }
546 CRYPTO_STATIC_MUTEX_unlock_write(built_in_groups_lock_bss_get());
547
548 EC_GROUP_free(to_free);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800549 return ret;
550}
551
552void EC_GROUP_free(EC_GROUP *group) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700553 if (group == NULL ||
Robert Sloan99319a12017-11-27 10:32:46 -0800554 // Built-in curves are static.
555 group->curve_name != NID_undef ||
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700556 !CRYPTO_refcount_dec_and_test_zero(&group->references)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800557 return;
558 }
559
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700560 if (group->meth->group_finish != NULL) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800561 group->meth->group_finish(group);
562 }
563
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700564 ec_point_free(group->generator, 0 /* don't free group */);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800565 BN_free(&group->order);
Robert Sloan99319a12017-11-27 10:32:46 -0800566 BN_MONT_CTX_free(group->order_mont);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800567
568 OPENSSL_free(group);
569}
570
Adam Langleyd9e397b2015-01-22 14:27:53 -0800571EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
Robert Sloan99319a12017-11-27 10:32:46 -0800572 if (a == NULL ||
573 // Built-in curves are static.
574 a->curve_name != NID_undef) {
575 return (EC_GROUP *)a;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800576 }
577
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700578 // Groups are logically immutable (but for |EC_GROUP_set_generator| which must
579 // be called early on), so we simply take a reference.
580 EC_GROUP *group = (EC_GROUP *)a;
581 CRYPTO_refcount_inc(&group->references);
582 return group;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800583}
584
Kenny Rootc897c7e2015-02-27 13:00:38 -0800585int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700586 // Note this function returns 0 if equal and non-zero otherwise.
587 if (a == b) {
588 return 0;
589 }
590 if (a->curve_name != b->curve_name) {
591 return 1;
592 }
593 if (a->curve_name != NID_undef) {
594 // Built-in curves may be compared by curve name alone.
595 return 0;
596 }
597
598 // |a| and |b| are both custom curves. We compare the entire curve
599 // structure. If |a| or |b| is incomplete (due to legacy OpenSSL mistakes,
600 // custom curve construction is sadly done in two parts) but otherwise not the
601 // same object, we consider them always unequal.
Robert Sloanc6ebb282018-04-30 10:10:26 -0700602 return a->meth != b->meth ||
603 a->generator == NULL ||
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700604 b->generator == NULL ||
605 BN_cmp(&a->order, &b->order) != 0 ||
606 BN_cmp(&a->field, &b->field) != 0 ||
Robert Sloanc6ebb282018-04-30 10:10:26 -0700607 !ec_felem_equal(a, &a->a, &b->a) ||
608 !ec_felem_equal(a, &a->b, &b->b) ||
609 ec_GFp_simple_cmp(a, &a->generator->raw, &b->generator->raw) != 0;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800610}
611
612const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
613 return group->generator;
614}
615
Adam Langley4139edb2016-01-13 15:00:54 -0800616const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
617 assert(!BN_is_zero(&group->order));
618 return &group->order;
619}
620
Adam Langleyd9e397b2015-01-22 14:27:53 -0800621int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
Adam Langley4139edb2016-01-13 15:00:54 -0800622 if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800623 return 0;
624 }
Adam Langley4139edb2016-01-13 15:00:54 -0800625 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800626}
627
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800628int EC_GROUP_order_bits(const EC_GROUP *group) {
629 return BN_num_bits(&group->order);
630}
631
Adam Langleyd9e397b2015-01-22 14:27:53 -0800632int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
633 BN_CTX *ctx) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700634 // All |EC_GROUP|s have cofactor 1.
David Benjaminc895d6b2016-08-11 13:26:41 -0400635 return BN_set_word(cofactor, 1);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800636}
637
638int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
639 BIGNUM *out_b, BN_CTX *ctx) {
Robert Sloanc6ebb282018-04-30 10:10:26 -0700640 return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800641}
642
643int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
644
Kenny Roote99801b2015-11-06 15:31:15 -0800645unsigned EC_GROUP_get_degree(const EC_GROUP *group) {
Robert Sloana51059f2018-11-12 13:38:50 -0800646 return BN_num_bits(&group->field);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800647}
648
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100649const char *EC_curve_nid2nist(int nid) {
650 switch (nid) {
651 case NID_secp224r1:
652 return "P-224";
653 case NID_X9_62_prime256v1:
654 return "P-256";
655 case NID_secp384r1:
656 return "P-384";
657 case NID_secp521r1:
658 return "P-521";
659 }
660 return NULL;
661}
662
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800663int EC_curve_nist2nid(const char *name) {
664 if (strcmp(name, "P-224") == 0) {
665 return NID_secp224r1;
666 }
667 if (strcmp(name, "P-256") == 0) {
668 return NID_X9_62_prime256v1;
669 }
670 if (strcmp(name, "P-384") == 0) {
671 return NID_secp384r1;
672 }
673 if (strcmp(name, "P-521") == 0) {
674 return NID_secp521r1;
675 }
676 return NID_undef;
677}
678
Adam Langleyd9e397b2015-01-22 14:27:53 -0800679EC_POINT *EC_POINT_new(const EC_GROUP *group) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800680 if (group == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000681 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800682 return NULL;
683 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800684
Robert Sloanc6ebb282018-04-30 10:10:26 -0700685 EC_POINT *ret = OPENSSL_malloc(sizeof *ret);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800686 if (ret == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000687 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800688 return NULL;
689 }
690
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700691 ret->group = EC_GROUP_dup(group);
Robert Sloanc6ebb282018-04-30 10:10:26 -0700692 ec_GFp_simple_point_init(&ret->raw);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800693 return ret;
694}
695
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700696static void ec_point_free(EC_POINT *point, int free_group) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800697 if (!point) {
698 return;
699 }
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700700 if (free_group) {
701 EC_GROUP_free(point->group);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800702 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800703 OPENSSL_free(point);
704}
705
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700706void EC_POINT_free(EC_POINT *point) {
707 ec_point_free(point, 1 /* free group */);
708}
709
710void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
711
Adam Langleyd9e397b2015-01-22 14:27:53 -0800712int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700713 if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000714 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800715 return 0;
716 }
717 if (dest == src) {
718 return 1;
719 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700720 ec_GFp_simple_point_copy(&dest->raw, &src->raw);
721 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800722}
723
724EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800725 if (a == NULL) {
726 return NULL;
727 }
728
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400729 EC_POINT *ret = EC_POINT_new(group);
730 if (ret == NULL ||
731 !EC_POINT_copy(ret, a)) {
732 EC_POINT_free(ret);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800733 return NULL;
734 }
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400735
736 return ret;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800737}
738
739int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700740 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000741 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800742 return 0;
743 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700744 ec_GFp_simple_point_set_to_infinity(group, &point->raw);
745 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800746}
747
748int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700749 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000750 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800751 return 0;
752 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700753 return ec_GFp_simple_is_at_infinity(group, &point->raw);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800754}
755
756int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
757 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700758 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000759 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800760 return 0;
761 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700762 return ec_GFp_simple_is_on_curve(group, &point->raw);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800763}
764
765int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
766 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700767 if (EC_GROUP_cmp(group, a->group, NULL) != 0 ||
768 EC_GROUP_cmp(group, b->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000769 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800770 return -1;
771 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700772 return ec_GFp_simple_cmp(group, &a->raw, &b->raw);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800773}
774
775int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
776 const EC_POINT *point, BIGNUM *x,
777 BIGNUM *y, BN_CTX *ctx) {
778 if (group->meth->point_get_affine_coordinates == 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000779 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800780 return 0;
781 }
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700782 if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000783 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800784 return 0;
785 }
Robert Sloana51059f2018-11-12 13:38:50 -0800786 EC_FELEM x_felem, y_felem;
787 if (!group->meth->point_get_affine_coordinates(group, &point->raw,
788 x == NULL ? NULL : &x_felem,
789 y == NULL ? NULL : &y_felem) ||
790 (x != NULL && !bn_set_words(x, x_felem.words, group->field.width)) ||
791 (y != NULL && !bn_set_words(y, y_felem.words, group->field.width))) {
792 return 0;
793 }
794 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800795}
796
797int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
798 const BIGNUM *x, const BIGNUM *y,
799 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700800 if (EC_GROUP_cmp(group, point->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 Sloanc6ebb282018-04-30 10:10:26 -0700804 if (!ec_GFp_simple_point_set_affine_coordinates(group, &point->raw, x, y)) {
Adam Langleyfad63272015-11-12 12:15:39 -0800805 return 0;
806 }
807
808 if (!EC_POINT_is_on_curve(group, point, ctx)) {
Robert Sloan8542c082018-02-05 09:07:34 -0800809 // In the event of an error, defend against the caller not checking the
810 // return value by setting a known safe value: the base point.
Adam Langley9083ef92018-03-05 10:15:53 -0800811 const EC_POINT *generator = EC_GROUP_get0_generator(group);
812 // The generator can be missing if the caller is in the process of
813 // constructing an arbitrary group. In this, we give up and hope they're
814 // checking the return value.
815 if (generator) {
Robert Sloanc6ebb282018-04-30 10:10:26 -0700816 ec_GFp_simple_point_copy(&point->raw, &generator->raw);
Adam Langley9083ef92018-03-05 10:15:53 -0800817 }
Adam Langleyfad63272015-11-12 12:15:39 -0800818 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
819 return 0;
820 }
821
822 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800823}
824
825int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
826 const EC_POINT *b, BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700827 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
828 EC_GROUP_cmp(group, a->group, NULL) != 0 ||
829 EC_GROUP_cmp(group, b->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000830 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800831 return 0;
832 }
Robert Sloana51059f2018-11-12 13:38:50 -0800833 group->meth->add(group, &r->raw, &a->raw, &b->raw);
Robert Sloanc6ebb282018-04-30 10:10:26 -0700834 return 1;
Robert Sloandc2f6092018-04-10 10:22:33 -0700835}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800836
837int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
838 BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700839 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
840 EC_GROUP_cmp(group, a->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000841 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800842 return 0;
843 }
Robert Sloana51059f2018-11-12 13:38:50 -0800844 group->meth->dbl(group, &r->raw, &a->raw);
Robert Sloanc6ebb282018-04-30 10:10:26 -0700845 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800846}
847
848
849int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
Robert Sloan29c1d2c2017-10-30 14:10:28 -0700850 if (EC_GROUP_cmp(group, a->group, NULL) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000851 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800852 return 0;
853 }
Robert Sloanc6ebb282018-04-30 10:10:26 -0700854 ec_GFp_simple_invert(group, &a->raw);
855 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800856}
857
Robert Sloana815d5a2017-12-04 11:49:16 -0800858static int arbitrary_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
859 const BIGNUM *in, BN_CTX *ctx) {
Robert Sloancd79cde2017-12-11 09:06:12 -0800860 if (ec_bignum_to_scalar(group, out, in)) {
861 return 1;
Robert Sloana815d5a2017-12-04 11:49:16 -0800862 }
863
Robert Sloancd79cde2017-12-11 09:06:12 -0800864 ERR_clear_error();
865
Robert Sloanab8b8882018-03-26 11:39:51 -0700866 // This is an unusual input, so we do not guarantee constant-time processing.
Robert Sloancd79cde2017-12-11 09:06:12 -0800867 const BIGNUM *order = &group->order;
868 BN_CTX_start(ctx);
869 BIGNUM *tmp = BN_CTX_get(ctx);
870 int ok = tmp != NULL &&
871 BN_nnmod(tmp, in, order, ctx) &&
Robert Sloan5cbb5c82018-04-24 11:35:46 -0700872 ec_bignum_to_scalar(group, out, tmp);
Robert Sloancd79cde2017-12-11 09:06:12 -0800873 BN_CTX_end(ctx);
874 return ok;
Robert Sloana815d5a2017-12-04 11:49:16 -0800875}
876
Adam Langleyd9e397b2015-01-22 14:27:53 -0800877int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
Adam Langley4139edb2016-01-13 15:00:54 -0800878 const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700879 // Previously, this function set |r| to the point at infinity if there was
880 // nothing to multiply. But, nobody should be calling this function with
881 // nothing to multiply in the first place.
Adam Langley4139edb2016-01-13 15:00:54 -0800882 if ((g_scalar == NULL && p_scalar == NULL) ||
Robert Sloan99319a12017-11-27 10:32:46 -0800883 (p == NULL) != (p_scalar == NULL)) {
884 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
885 return 0;
886 }
887
Robert Sloanc9abfe42018-11-26 12:19:07 -0800888 if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
889 (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
890 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
891 return 0;
892 }
893
Robert Sloan99319a12017-11-27 10:32:46 -0800894 int ret = 0;
Robert Sloana815d5a2017-12-04 11:49:16 -0800895 BN_CTX *new_ctx = NULL;
896 if (ctx == NULL) {
897 new_ctx = BN_CTX_new();
898 if (new_ctx == NULL) {
899 goto err;
900 }
901 ctx = new_ctx;
902 }
903
Pete Bentley0c61efe2019-08-13 09:32:23 +0100904 // If both |g_scalar| and |p_scalar| are non-NULL,
905 // |ec_point_mul_scalar_public| would share the doublings between the two
906 // products, which would be more efficient. However, we conservatively assume
907 // the caller needs a constant-time operation. (ECDSA verification does not
908 // use this function.)
909 //
910 // Previously, the low-level constant-time multiplication function aligned
911 // with this function's calling convention, but this was misleading. Curves
912 // which combined the two multiplications did not avoid the doubling case
913 // in the incomplete addition formula and were not constant-time.
914
Robert Sloan99319a12017-11-27 10:32:46 -0800915 if (g_scalar != NULL) {
Pete Bentley0c61efe2019-08-13 09:32:23 +0100916 EC_SCALAR scalar;
917 if (!arbitrary_bignum_to_scalar(group, &scalar, g_scalar, ctx) ||
918 !ec_point_mul_scalar_base(group, &r->raw, &scalar)) {
Robert Sloan99319a12017-11-27 10:32:46 -0800919 goto err;
920 }
Robert Sloan99319a12017-11-27 10:32:46 -0800921 }
922
923 if (p_scalar != NULL) {
Pete Bentley0c61efe2019-08-13 09:32:23 +0100924 EC_SCALAR scalar;
925 EC_RAW_POINT tmp;
926 if (!arbitrary_bignum_to_scalar(group, &scalar, p_scalar, ctx) ||
927 !ec_point_mul_scalar(group, &tmp, &p->raw, &scalar)) {
Robert Sloan99319a12017-11-27 10:32:46 -0800928 goto err;
929 }
Pete Bentley0c61efe2019-08-13 09:32:23 +0100930 if (g_scalar == NULL) {
931 OPENSSL_memcpy(&r->raw, &tmp, sizeof(EC_RAW_POINT));
932 } else {
933 group->meth->add(group, &r->raw, &r->raw, &tmp);
934 }
Robert Sloan99319a12017-11-27 10:32:46 -0800935 }
936
Pete Bentley0c61efe2019-08-13 09:32:23 +0100937 ret = 1;
Robert Sloan99319a12017-11-27 10:32:46 -0800938
939err:
Robert Sloana815d5a2017-12-04 11:49:16 -0800940 BN_CTX_free(new_ctx);
Robert Sloan99319a12017-11-27 10:32:46 -0800941 return ret;
942}
943
Robert Sloanc9abfe42018-11-26 12:19:07 -0800944int ec_point_mul_scalar_public(const EC_GROUP *group, EC_RAW_POINT *r,
945 const EC_SCALAR *g_scalar, const EC_RAW_POINT *p,
946 const EC_SCALAR *p_scalar) {
Pete Bentley0c61efe2019-08-13 09:32:23 +0100947 if (g_scalar == NULL || p_scalar == NULL || p == NULL) {
Robert Sloan55818102017-12-18 11:26:17 -0800948 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
949 return 0;
950 }
951
Robert Sloanc9abfe42018-11-26 12:19:07 -0800952 group->meth->mul_public(group, r, g_scalar, p, p_scalar);
Robert Sloanc6ebb282018-04-30 10:10:26 -0700953 return 1;
Robert Sloan55818102017-12-18 11:26:17 -0800954}
955
Robert Sloanc9abfe42018-11-26 12:19:07 -0800956int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r,
Pete Bentley0c61efe2019-08-13 09:32:23 +0100957 const EC_RAW_POINT *p, const EC_SCALAR *scalar) {
958 if (p == NULL || scalar == NULL) {
Adam Langley4139edb2016-01-13 15:00:54 -0800959 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
960 return 0;
961 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800962
Pete Bentley0c61efe2019-08-13 09:32:23 +0100963 group->meth->mul(group, r, p, scalar);
964 return 1;
965}
966
967int ec_point_mul_scalar_base(const EC_GROUP *group, EC_RAW_POINT *r,
968 const EC_SCALAR *scalar) {
969 if (scalar == NULL) {
970 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
971 return 0;
972 }
973
974 group->meth->mul_base(group, r, scalar);
Robert Sloanc6ebb282018-04-30 10:10:26 -0700975 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800976}
977
Robert Sloanc9abfe42018-11-26 12:19:07 -0800978int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p,
979 const EC_SCALAR *r) {
980 return group->meth->cmp_x_coordinate(group, p, r);
Robert Sloana51059f2018-11-12 13:38:50 -0800981}
982
Robert Sloanc9abfe42018-11-26 12:19:07 -0800983int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out,
984 const EC_RAW_POINT *p) {
985 EC_FELEM x;
986 // For simplicity, in case of width mismatches between |group->field| and
987 // |group->order|, zero any untouched words in |x|.
988 OPENSSL_memset(&x, 0, sizeof(x));
989 if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) {
990 return 0;
991 }
992
Robert Sloana51059f2018-11-12 13:38:50 -0800993 // We must have p < 2×order, assuming p is not tiny (p >= 17). Thus rather we
994 // can reduce by performing at most one subtraction.
995 //
996 // Proof: We only work with prime order curves, so the number of points on
997 // the curve is the order. Thus Hasse's theorem gives:
998 //
999 // |order - (p + 1)| <= 2×sqrt(p)
1000 // p + 1 - order <= 2×sqrt(p)
1001 // p + 1 - 2×sqrt(p) <= order
1002 // p + 1 - 2×(p/4) < order (p/4 > sqrt(p) for p >= 17)
1003 // p/2 < p/2 + 1 < order
1004 // p < 2×order
1005 //
1006 // Additionally, one can manually check this property for built-in curves. It
1007 // is enforced for legacy custom curves in |EC_GROUP_set_generator|.
Robert Sloanc9abfe42018-11-26 12:19:07 -08001008
1009 // The above does not guarantee |group->field| is not one word larger than
1010 // |group->order|, so read one extra carry word.
1011 BN_ULONG carry =
1012 group->order.width < EC_MAX_WORDS ? x.words[group->order.width] : 0;
1013 bn_reduce_once(out->words, x.words, carry, group->order.d,
1014 group->order.width);
1015 return 1;
1016}
1017
1018int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x,
1019 uint8_t *out_y, size_t *out_len,
1020 size_t max_out,
1021 const EC_RAW_POINT *p) {
1022 size_t len = BN_num_bytes(&group->field);
1023 assert(len <= EC_MAX_BYTES);
1024 if (max_out < len) {
1025 OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
Robert Sloana51059f2018-11-12 13:38:50 -08001026 return 0;
1027 }
Robert Sloanc9abfe42018-11-26 12:19:07 -08001028
1029 EC_FELEM x, y;
1030 if (!group->meth->point_get_affine_coordinates(
1031 group, p, out_x == NULL ? NULL : &x, out_y == NULL ? NULL : &y)) {
1032 return 0;
1033 }
1034
1035 if (out_x != NULL) {
1036 for (size_t i = 0; i < len; i++) {
1037 out_x[i] = x.bytes[len - i - 1];
1038 }
1039 }
1040 if (out_y != NULL) {
1041 for (size_t i = 0; i < len; i++) {
1042 out_y[i] = y.bytes[len - i - 1];
1043 }
1044 }
1045 *out_len = len;
Robert Sloana51059f2018-11-12 13:38:50 -08001046 return 1;
1047}
1048
Adam Langleyf7e890d2015-03-31 18:58:05 -07001049void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
1050
1051const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
Adam Vartanianbfcf3a72018-08-10 14:55:24 +01001052 // This function exists purely to give callers a way to call
1053 // |EC_METHOD_get_field_type|. cryptography.io crashes if |EC_GROUP_method_of|
1054 // returns NULL, so return some other garbage pointer.
1055 return (const EC_METHOD *)0x12340000;
Adam Langleyf7e890d2015-03-31 18:58:05 -07001056}
1057
1058int EC_METHOD_get_field_type(const EC_METHOD *meth) {
1059 return NID_X9_62_prime_field;
1060}
Adam Langley830beae2015-04-20 10:49:33 -07001061
1062void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
1063 point_conversion_form_t form) {
1064 if (form != POINT_CONVERSION_UNCOMPRESSED) {
1065 abort();
1066 }
1067}
David Benjamin4969cc92016-04-22 15:02:23 -04001068
1069size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
1070 size_t max_num_curves) {
Robert Sloan8ff03552017-06-14 12:40:58 -07001071 const struct built_in_curves *const curves = OPENSSL_built_in_curves();
1072
1073 for (size_t i = 0; i < max_num_curves && i < OPENSSL_NUM_BUILT_IN_CURVES;
1074 i++) {
Robert Sloane56da3e2017-06-26 08:26:42 -07001075 out_curves[i].comment = curves->curves[i].comment;
Robert Sloan8ff03552017-06-14 12:40:58 -07001076 out_curves[i].nid = curves->curves[i].nid;
David Benjamin4969cc92016-04-22 15:02:23 -04001077 }
1078
Robert Sloan8ff03552017-06-14 12:40:58 -07001079 return OPENSSL_NUM_BUILT_IN_CURVES;
David Benjamin4969cc92016-04-22 15:02:23 -04001080}