1 /* Originally written by Bodo Moeller for the OpenSSL project. 2 * ==================================================================== 3 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core (at) 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 (at) cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh (at) cryptsoft.com). 53 * 54 */ 55 /* ==================================================================== 56 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 57 * 58 * Portions of the attached software ("Contribution") are developed by 59 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. 60 * 61 * The Contribution is licensed pursuant to the OpenSSL open source 62 * license provided above. 63 * 64 * The elliptic curve binary polynomial software is originally written by 65 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems 66 * Laboratories. */ 67 68 #include <openssl/ec.h> 69 70 #include <assert.h> 71 #include <string.h> 72 73 #include <openssl/bn.h> 74 #include <openssl/err.h> 75 #include <openssl/mem.h> 76 #include <openssl/nid.h> 77 78 #include "internal.h" 79 #include "../../internal.h" 80 #include "../bn/internal.h" 81 #include "../delocate.h" 82 83 84 static void ec_point_free(EC_POINT *point, int free_group); 85 86 static const uint8_t kP224Params[6 * 28] = { 87 // p 88 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, 91 // a 92 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, 95 // b 96 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, 99 // x 100 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, 103 // y 104 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, 107 // order 108 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, 111 }; 112 113 static const uint8_t kP256Params[6 * 32] = { 114 // p 115 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, 118 // a 119 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, 122 // b 123 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, 126 // x 127 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, 130 // y 131 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, 134 // order 135 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 }; 139 140 static const uint8_t kP384Params[6 * 48] = { 141 // p 142 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 143 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 144 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 146 // a 147 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 148 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 149 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 151 // b 152 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, 153 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, 154 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D, 155 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF, 156 // x 157 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, 158 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, 159 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D, 160 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7, 161 // y 162 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, 163 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, 164 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, 165 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f, 166 // order 167 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 168 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 169 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, 170 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73, 171 }; 172 173 static const uint8_t kP521Params[6 * 66] = { 174 // p 175 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, 181 // a 182 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, 188 // b 189 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, 195 // x 196 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, 202 // y 203 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, 209 // order 210 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 }; 217 218 DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) { 219 // 1.3.132.0.35 220 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); 224 out->curves[0].comment = "NIST P-521"; 225 out->curves[0].param_len = 66; 226 out->curves[0].params = kP521Params; 227 out->curves[0].method = EC_GFp_mont_method(); 228 229 // 1.3.132.0.34 230 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); 234 out->curves[1].comment = "NIST P-384"; 235 out->curves[1].param_len = 48; 236 out->curves[1].params = kP384Params; 237 out->curves[1].method = EC_GFp_mont_method(); 238 239 // 1.2.840.10045.3.1.7 240 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); 245 out->curves[2].comment = "NIST P-256"; 246 out->curves[2].param_len = 32; 247 out->curves[2].params = kP256Params; 248 out->curves[2].method = 249 #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ 250 !defined(OPENSSL_SMALL) 251 EC_GFp_nistz256_method(); 252 #else 253 EC_GFp_nistp256_method(); 254 #endif 255 256 // 1.3.132.0.33 257 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); 261 out->curves[3].comment = "NIST P-224"; 262 out->curves[3].param_len = 28; 263 out->curves[3].params = kP224Params; 264 out->curves[3].method = 265 #if defined(BORINGSSL_HAS_UINT128) && !defined(OPENSSL_SMALL) 266 EC_GFp_nistp224_method(); 267 #else 268 EC_GFp_mont_method(); 269 #endif 270 } 271 272 EC_GROUP *ec_group_new(const EC_METHOD *meth) { 273 EC_GROUP *ret; 274 275 if (meth == NULL) { 276 OPENSSL_PUT_ERROR(EC, EC_R_SLOT_FULL); 277 return NULL; 278 } 279 280 if (meth->group_init == 0) { 281 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 282 return NULL; 283 } 284 285 ret = OPENSSL_malloc(sizeof(EC_GROUP)); 286 if (ret == NULL) { 287 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 288 return NULL; 289 } 290 OPENSSL_memset(ret, 0, sizeof(EC_GROUP)); 291 292 ret->references = 1; 293 ret->meth = meth; 294 BN_init(&ret->order); 295 296 if (!meth->group_init(ret)) { 297 OPENSSL_free(ret); 298 return NULL; 299 } 300 301 return ret; 302 } 303 304 static 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 317 EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, 318 const BIGNUM *b, BN_CTX *ctx) { 319 if (BN_num_bytes(p) > EC_MAX_BYTES) { 320 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FIELD); 321 return NULL; 322 } 323 324 EC_GROUP *ret = ec_group_new(EC_GFp_mont_method()); 325 if (ret == NULL) { 326 return NULL; 327 } 328 329 if (ret->meth->group_set_curve == NULL) { 330 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 331 EC_GROUP_free(ret); 332 return NULL; 333 } 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 341 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, 342 const BIGNUM *order, const BIGNUM *cofactor) { 343 if (group->curve_name != NID_undef || group->generator != NULL || 344 generator->group != group) { 345 // |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. 347 // |generator| must have been created from |EC_GROUP_new_curve_GFp|, not a 348 // copy, so that |generator->group->generator| is set correctly. 349 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 350 return 0; 351 } 352 353 if (BN_num_bytes(order) > EC_MAX_BYTES) { 354 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER); 355 return 0; 356 } 357 358 // Require a cofactor of one for custom curves, which implies prime order. 359 if (!BN_is_one(cofactor)) { 360 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COFACTOR); 361 return 0; 362 } 363 364 // Require that p < 2order. 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. 369 int ret = 0; 370 EC_POINT *copy = NULL; 371 BIGNUM *tmp = BN_new(); 372 if (tmp == NULL || 373 !BN_lshift1(tmp, order)) { 374 goto err; 375 } 376 if (BN_cmp(tmp, &group->field) <= 0) { 377 OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER); 378 goto err; 379 } 380 381 copy = EC_POINT_new(group); 382 if (copy == NULL || 383 !EC_POINT_copy(copy, generator) || 384 !BN_copy(&group->order, order)) { 385 goto err; 386 } 387 // Store the order in minimal form, so it can be used with |BN_ULONG| arrays. 388 bn_set_minimal_width(&group->order); 389 390 BN_MONT_CTX_free(group->order_mont); 391 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, NULL); 392 if (group->order_mont == NULL) { 393 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 } 403 } 404 405 ec_group_set0_generator(group, copy); 406 copy = NULL; 407 ret = 1; 408 409 err: 410 EC_POINT_free(copy); 411 BN_free(tmp); 412 return ret; 413 } 414 415 static EC_GROUP *ec_group_new_from_data(const struct built_in_curve *curve) { 416 EC_GROUP *group = NULL; 417 EC_POINT *P = NULL; 418 BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; 419 int ok = 0; 420 421 BN_CTX *ctx = BN_CTX_new(); 422 if (ctx == NULL) { 423 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 424 goto err; 425 } 426 427 const unsigned param_len = curve->param_len; 428 const uint8_t *params = curve->params; 429 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))) { 433 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); 434 goto err; 435 } 436 437 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; 442 } 443 444 if ((P = EC_POINT_new(group)) == NULL) { 445 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); 446 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))) { 451 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); 452 goto err; 453 } 454 455 if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) { 456 OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); 457 goto err; 458 } 459 if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order)) { 460 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); 461 goto err; 462 } 463 464 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 472 group->order_mont = BN_MONT_CTX_new_for_modulus(&group->order, ctx); 473 if (group->order_mont == NULL) { 474 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); 475 goto err; 476 } 477 478 ec_group_set0_generator(group, P); 479 P = NULL; 480 ok = 1; 481 482 err: 483 if (!ok) { 484 EC_GROUP_free(group); 485 group = NULL; 486 } 487 EC_POINT_free(P); 488 BN_CTX_free(ctx); 489 BN_free(p); 490 BN_free(a); 491 BN_free(b); 492 BN_free(x); 493 BN_free(y); 494 return group; 495 } 496 497 // Built-in groups are allocated lazily and static once allocated. 498 // TODO(davidben): Make these actually static. https://crbug.com/boringssl/20. 499 struct built_in_groups_st { 500 EC_GROUP *groups[OPENSSL_NUM_BUILT_IN_CURVES]; 501 }; 502 DEFINE_BSS_GET(struct built_in_groups_st, built_in_groups) 503 DEFINE_STATIC_MUTEX(built_in_groups_lock) 504 505 EC_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; 510 for (size_t i = 0; i < OPENSSL_NUM_BUILT_IN_CURVES; i++) { 511 if (curves->curves[i].nid == nid) { 512 curve = &curves->curves[i]; 513 group_ptr = &groups->groups[i]; 514 break; 515 } 516 } 517 518 if (curve == NULL) { 519 OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP); 520 return NULL; 521 } 522 523 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); 549 return ret; 550 } 551 552 void EC_GROUP_free(EC_GROUP *group) { 553 if (group == NULL || 554 // Built-in curves are static. 555 group->curve_name != NID_undef || 556 !CRYPTO_refcount_dec_and_test_zero(&group->references)) { 557 return; 558 } 559 560 if (group->meth->group_finish != NULL) { 561 group->meth->group_finish(group); 562 } 563 564 ec_point_free(group->generator, 0 /* don't free group */); 565 BN_free(&group->order); 566 BN_MONT_CTX_free(group->order_mont); 567 568 OPENSSL_free(group); 569 } 570 571 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) { 572 if (a == NULL || 573 // Built-in curves are static. 574 a->curve_name != NID_undef) { 575 return (EC_GROUP *)a; 576 } 577 578 // 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; 583 } 584 585 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) { 586 // 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. 602 return a->meth != b->meth || 603 a->generator == NULL || 604 b->generator == NULL || 605 BN_cmp(&a->order, &b->order) != 0 || 606 BN_cmp(&a->field, &b->field) != 0 || 607 !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; 610 } 611 612 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) { 613 return group->generator; 614 } 615 616 const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) { 617 assert(!BN_is_zero(&group->order)); 618 return &group->order; 619 } 620 621 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) { 622 if (BN_copy(order, EC_GROUP_get0_order(group)) == NULL) { 623 return 0; 624 } 625 return 1; 626 } 627 628 int EC_GROUP_order_bits(const EC_GROUP *group) { 629 return BN_num_bits(&group->order); 630 } 631 632 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, 633 BN_CTX *ctx) { 634 // All |EC_GROUP|s have cofactor 1. 635 return BN_set_word(cofactor, 1); 636 } 637 638 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a, 639 BIGNUM *out_b, BN_CTX *ctx) { 640 return ec_GFp_simple_group_get_curve(group, out_p, out_a, out_b); 641 } 642 643 int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; } 644 645 unsigned EC_GROUP_get_degree(const EC_GROUP *group) { 646 return BN_num_bits(&group->field); 647 } 648 649 const 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 663 int 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 679 EC_POINT *EC_POINT_new(const EC_GROUP *group) { 680 if (group == NULL) { 681 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 682 return NULL; 683 } 684 685 EC_POINT *ret = OPENSSL_malloc(sizeof *ret); 686 if (ret == NULL) { 687 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 688 return NULL; 689 } 690 691 ret->group = EC_GROUP_dup(group); 692 ec_GFp_simple_point_init(&ret->raw); 693 return ret; 694 } 695 696 static void ec_point_free(EC_POINT *point, int free_group) { 697 if (!point) { 698 return; 699 } 700 if (free_group) { 701 EC_GROUP_free(point->group); 702 } 703 OPENSSL_free(point); 704 } 705 706 void EC_POINT_free(EC_POINT *point) { 707 ec_point_free(point, 1 /* free group */); 708 } 709 710 void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); } 711 712 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) { 713 if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) { 714 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 715 return 0; 716 } 717 if (dest == src) { 718 return 1; 719 } 720 ec_GFp_simple_point_copy(&dest->raw, &src->raw); 721 return 1; 722 } 723 724 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) { 725 if (a == NULL) { 726 return NULL; 727 } 728 729 EC_POINT *ret = EC_POINT_new(group); 730 if (ret == NULL || 731 !EC_POINT_copy(ret, a)) { 732 EC_POINT_free(ret); 733 return NULL; 734 } 735 736 return ret; 737 } 738 739 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) { 740 if (EC_GROUP_cmp(group, point->group, NULL) != 0) { 741 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 742 return 0; 743 } 744 ec_GFp_simple_point_set_to_infinity(group, &point->raw); 745 return 1; 746 } 747 748 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) { 749 if (EC_GROUP_cmp(group, point->group, NULL) != 0) { 750 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 751 return 0; 752 } 753 return ec_GFp_simple_is_at_infinity(group, &point->raw); 754 } 755 756 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 757 BN_CTX *ctx) { 758 if (EC_GROUP_cmp(group, point->group, NULL) != 0) { 759 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 760 return 0; 761 } 762 return ec_GFp_simple_is_on_curve(group, &point->raw); 763 } 764 765 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, 766 BN_CTX *ctx) { 767 if (EC_GROUP_cmp(group, a->group, NULL) != 0 || 768 EC_GROUP_cmp(group, b->group, NULL) != 0) { 769 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 770 return -1; 771 } 772 return ec_GFp_simple_cmp(group, &a->raw, &b->raw); 773 } 774 775 int 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) { 779 OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 780 return 0; 781 } 782 if (EC_GROUP_cmp(group, point->group, NULL) != 0) { 783 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 784 return 0; 785 } 786 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; 795 } 796 797 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 798 const BIGNUM *x, const BIGNUM *y, 799 BN_CTX *ctx) { 800 if (EC_GROUP_cmp(group, point->group, NULL) != 0) { 801 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 802 return 0; 803 } 804 if (!ec_GFp_simple_point_set_affine_coordinates(group, &point->raw, x, y)) { 805 return 0; 806 } 807 808 if (!EC_POINT_is_on_curve(group, point, ctx)) { 809 // 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. 811 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) { 816 ec_GFp_simple_point_copy(&point->raw, &generator->raw); 817 } 818 OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); 819 return 0; 820 } 821 822 return 1; 823 } 824 825 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 826 const EC_POINT *b, BN_CTX *ctx) { 827 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) { 830 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 831 return 0; 832 } 833 group->meth->add(group, &r->raw, &a->raw, &b->raw); 834 return 1; 835 } 836 837 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 838 BN_CTX *ctx) { 839 if (EC_GROUP_cmp(group, r->group, NULL) != 0 || 840 EC_GROUP_cmp(group, a->group, NULL) != 0) { 841 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 842 return 0; 843 } 844 group->meth->dbl(group, &r->raw, &a->raw); 845 return 1; 846 } 847 848 849 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) { 850 if (EC_GROUP_cmp(group, a->group, NULL) != 0) { 851 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 852 return 0; 853 } 854 ec_GFp_simple_invert(group, &a->raw); 855 return 1; 856 } 857 858 static int arbitrary_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out, 859 const BIGNUM *in, BN_CTX *ctx) { 860 if (ec_bignum_to_scalar(group, out, in)) { 861 return 1; 862 } 863 864 ERR_clear_error(); 865 866 // This is an unusual input, so we do not guarantee constant-time processing. 867 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) && 872 ec_bignum_to_scalar(group, out, tmp); 873 BN_CTX_end(ctx); 874 return ok; 875 } 876 877 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 878 const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) { 879 // 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. 882 if ((g_scalar == NULL && p_scalar == NULL) || 883 (p == NULL) != (p_scalar == NULL)) { 884 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 885 return 0; 886 } 887 888 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 894 int ret = 0; 895 EC_SCALAR g_scalar_storage, p_scalar_storage; 896 EC_SCALAR *g_scalar_arg = NULL, *p_scalar_arg = NULL; 897 BN_CTX *new_ctx = NULL; 898 if (ctx == NULL) { 899 new_ctx = BN_CTX_new(); 900 if (new_ctx == NULL) { 901 goto err; 902 } 903 ctx = new_ctx; 904 } 905 906 if (g_scalar != NULL) { 907 if (!arbitrary_bignum_to_scalar(group, &g_scalar_storage, g_scalar, ctx)) { 908 goto err; 909 } 910 g_scalar_arg = &g_scalar_storage; 911 } 912 913 if (p_scalar != NULL) { 914 if (!arbitrary_bignum_to_scalar(group, &p_scalar_storage, p_scalar, ctx)) { 915 goto err; 916 } 917 p_scalar_arg = &p_scalar_storage; 918 } 919 920 ret = ec_point_mul_scalar(group, &r->raw, g_scalar_arg, 921 p == NULL ? NULL : &p->raw, p_scalar_arg); 922 923 err: 924 BN_CTX_free(new_ctx); 925 OPENSSL_cleanse(&g_scalar_storage, sizeof(g_scalar_storage)); 926 OPENSSL_cleanse(&p_scalar_storage, sizeof(p_scalar_storage)); 927 return ret; 928 } 929 930 int ec_point_mul_scalar_public(const EC_GROUP *group, EC_RAW_POINT *r, 931 const EC_SCALAR *g_scalar, const EC_RAW_POINT *p, 932 const EC_SCALAR *p_scalar) { 933 if ((g_scalar == NULL && p_scalar == NULL) || 934 (p == NULL) != (p_scalar == NULL)) { 935 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 936 return 0; 937 } 938 939 group->meth->mul_public(group, r, g_scalar, p, p_scalar); 940 return 1; 941 } 942 943 int ec_point_mul_scalar(const EC_GROUP *group, EC_RAW_POINT *r, 944 const EC_SCALAR *g_scalar, const EC_RAW_POINT *p, 945 const EC_SCALAR *p_scalar) { 946 if ((g_scalar == NULL && p_scalar == NULL) || 947 (p == NULL) != (p_scalar == NULL)) { 948 OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); 949 return 0; 950 } 951 952 group->meth->mul(group, r, g_scalar, p, p_scalar); 953 return 1; 954 } 955 956 int ec_cmp_x_coordinate(const EC_GROUP *group, const EC_RAW_POINT *p, 957 const EC_SCALAR *r) { 958 return group->meth->cmp_x_coordinate(group, p, r); 959 } 960 961 int ec_get_x_coordinate_as_scalar(const EC_GROUP *group, EC_SCALAR *out, 962 const EC_RAW_POINT *p) { 963 EC_FELEM x; 964 // For simplicity, in case of width mismatches between |group->field| and 965 // |group->order|, zero any untouched words in |x|. 966 OPENSSL_memset(&x, 0, sizeof(x)); 967 if (!group->meth->point_get_affine_coordinates(group, p, &x, NULL)) { 968 return 0; 969 } 970 971 // We must have p < 2order, assuming p is not tiny (p >= 17). Thus rather we 972 // can reduce by performing at most one subtraction. 973 // 974 // Proof: We only work with prime order curves, so the number of points on 975 // the curve is the order. Thus Hasse's theorem gives: 976 // 977 // |order - (p + 1)| <= 2sqrt(p) 978 // p + 1 - order <= 2sqrt(p) 979 // p + 1 - 2sqrt(p) <= order 980 // p + 1 - 2(p/4) < order (p/4 > sqrt(p) for p >= 17) 981 // p/2 < p/2 + 1 < order 982 // p < 2order 983 // 984 // Additionally, one can manually check this property for built-in curves. It 985 // is enforced for legacy custom curves in |EC_GROUP_set_generator|. 986 987 // The above does not guarantee |group->field| is not one word larger than 988 // |group->order|, so read one extra carry word. 989 BN_ULONG carry = 990 group->order.width < EC_MAX_WORDS ? x.words[group->order.width] : 0; 991 bn_reduce_once(out->words, x.words, carry, group->order.d, 992 group->order.width); 993 return 1; 994 } 995 996 int ec_point_get_affine_coordinate_bytes(const EC_GROUP *group, uint8_t *out_x, 997 uint8_t *out_y, size_t *out_len, 998 size_t max_out, 999 const EC_RAW_POINT *p) { 1000 size_t len = BN_num_bytes(&group->field); 1001 assert(len <= EC_MAX_BYTES); 1002 if (max_out < len) { 1003 OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); 1004 return 0; 1005 } 1006 1007 EC_FELEM x, y; 1008 if (!group->meth->point_get_affine_coordinates( 1009 group, p, out_x == NULL ? NULL : &x, out_y == NULL ? NULL : &y)) { 1010 return 0; 1011 } 1012 1013 if (out_x != NULL) { 1014 for (size_t i = 0; i < len; i++) { 1015 out_x[i] = x.bytes[len - i - 1]; 1016 } 1017 } 1018 if (out_y != NULL) { 1019 for (size_t i = 0; i < len; i++) { 1020 out_y[i] = y.bytes[len - i - 1]; 1021 } 1022 } 1023 *out_len = len; 1024 return 1; 1025 } 1026 1027 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {} 1028 1029 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) { 1030 // This function exists purely to give callers a way to call 1031 // |EC_METHOD_get_field_type|. cryptography.io crashes if |EC_GROUP_method_of| 1032 // returns NULL, so return some other garbage pointer. 1033 return (const EC_METHOD *)0x12340000; 1034 } 1035 1036 int EC_METHOD_get_field_type(const EC_METHOD *meth) { 1037 return NID_X9_62_prime_field; 1038 } 1039 1040 void EC_GROUP_set_point_conversion_form(EC_GROUP *group, 1041 point_conversion_form_t form) { 1042 if (form != POINT_CONVERSION_UNCOMPRESSED) { 1043 abort(); 1044 } 1045 } 1046 1047 size_t EC_get_builtin_curves(EC_builtin_curve *out_curves, 1048 size_t max_num_curves) { 1049 const struct built_in_curves *const curves = OPENSSL_built_in_curves(); 1050 1051 for (size_t i = 0; i < max_num_curves && i < OPENSSL_NUM_BUILT_IN_CURVES; 1052 i++) { 1053 out_curves[i].comment = curves->curves[i].comment; 1054 out_curves[i].nid = curves->curves[i].nid; 1055 } 1056 1057 return OPENSSL_NUM_BUILT_IN_CURVES; 1058 } 1059