1 /* Copyright (c) 2014, Intel Corporation. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15 /* Developers and authors: 16 * Shay Gueron (1, 2), and Vlad Krasnov (1) 17 * (1) Intel Corporation, Israel Development Center 18 * (2) University of Haifa 19 * Reference: 20 * S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with 21 * 256 Bit Primes" */ 22 23 #include <openssl/ec.h> 24 25 #include <assert.h> 26 #include <stdint.h> 27 #include <string.h> 28 29 #include <openssl/bn.h> 30 #include <openssl/crypto.h> 31 #include <openssl/err.h> 32 33 #include "../bn/internal.h" 34 #include "../ec/internal.h" 35 #include "../internal.h" 36 37 38 #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ 39 !defined(OPENSSL_SMALL) 40 41 42 #if defined(__GNUC__) 43 #define ALIGN(x) __attribute((aligned(x))) 44 #elif defined(_MSC_VER) 45 #define ALIGN(x) __declspec(align(x)) 46 #else 47 #define ALIGN(x) 48 #endif 49 50 #define ALIGNPTR(p, N) ((uint8_t *)p + N - (size_t)p % N) 51 #define P256_LIMBS (256 / BN_BITS2) 52 53 typedef struct { 54 BN_ULONG X[P256_LIMBS]; 55 BN_ULONG Y[P256_LIMBS]; 56 BN_ULONG Z[P256_LIMBS]; 57 } P256_POINT; 58 59 typedef struct { 60 BN_ULONG X[P256_LIMBS]; 61 BN_ULONG Y[P256_LIMBS]; 62 } P256_POINT_AFFINE; 63 64 typedef P256_POINT_AFFINE PRECOMP256_ROW[64]; 65 66 /* Functions implemented in assembly */ 67 68 /* Modular neg: res = -a mod P */ 69 void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]); 70 /* Montgomery mul: res = a*b*2^-256 mod P */ 71 void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS], 72 const BN_ULONG a[P256_LIMBS], 73 const BN_ULONG b[P256_LIMBS]); 74 /* Montgomery sqr: res = a*a*2^-256 mod P */ 75 void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS], 76 const BN_ULONG a[P256_LIMBS]); 77 /* Convert a number from Montgomery domain, by multiplying with 1 */ 78 void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS], 79 const BN_ULONG in[P256_LIMBS]); 80 /* Functions that perform constant time access to the precomputed tables */ 81 void ecp_nistz256_select_w5(P256_POINT *val, const P256_POINT *in_t, int index); 82 void ecp_nistz256_select_w7(P256_POINT_AFFINE *val, 83 const P256_POINT_AFFINE *in_t, int index); 84 85 /* One converted into the Montgomery domain */ 86 static const BN_ULONG ONE[P256_LIMBS] = { 87 TOBN(0x00000000, 0x00000001), TOBN(0xffffffff, 0x00000000), 88 TOBN(0xffffffff, 0xffffffff), TOBN(0x00000000, 0xfffffffe), 89 }; 90 91 /* Precomputed tables for the default generator */ 92 #include "p256-x86_64-table.h" 93 94 /* Recode window to a signed digit, see ecp_nistputil.c for details */ 95 static unsigned booth_recode_w5(unsigned in) { 96 unsigned s, d; 97 98 s = ~((in >> 5) - 1); 99 d = (1 << 6) - in - 1; 100 d = (d & s) | (in & ~s); 101 d = (d >> 1) + (d & 1); 102 103 return (d << 1) + (s & 1); 104 } 105 106 static unsigned booth_recode_w7(unsigned in) { 107 unsigned s, d; 108 109 s = ~((in >> 7) - 1); 110 d = (1 << 8) - in - 1; 111 d = (d & s) | (in & ~s); 112 d = (d >> 1) + (d & 1); 113 114 return (d << 1) + (s & 1); 115 } 116 117 static void copy_conditional(BN_ULONG dst[P256_LIMBS], 118 const BN_ULONG src[P256_LIMBS], BN_ULONG move) { 119 BN_ULONG mask1 = ((BN_ULONG)0) - move; 120 BN_ULONG mask2 = ~mask1; 121 122 dst[0] = (src[0] & mask1) ^ (dst[0] & mask2); 123 dst[1] = (src[1] & mask1) ^ (dst[1] & mask2); 124 dst[2] = (src[2] & mask1) ^ (dst[2] & mask2); 125 dst[3] = (src[3] & mask1) ^ (dst[3] & mask2); 126 if (P256_LIMBS == 8) { 127 dst[4] = (src[4] & mask1) ^ (dst[4] & mask2); 128 dst[5] = (src[5] & mask1) ^ (dst[5] & mask2); 129 dst[6] = (src[6] & mask1) ^ (dst[6] & mask2); 130 dst[7] = (src[7] & mask1) ^ (dst[7] & mask2); 131 } 132 } 133 134 void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a); 135 void ecp_nistz256_point_add(P256_POINT *r, const P256_POINT *a, 136 const P256_POINT *b); 137 void ecp_nistz256_point_add_affine(P256_POINT *r, const P256_POINT *a, 138 const P256_POINT_AFFINE *b); 139 140 /* r = in^-1 mod p */ 141 static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS], 142 const BN_ULONG in[P256_LIMBS]) { 143 /* The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff 144 ffffffff 145 We use FLT and used poly-2 as exponent */ 146 BN_ULONG p2[P256_LIMBS]; 147 BN_ULONG p4[P256_LIMBS]; 148 BN_ULONG p8[P256_LIMBS]; 149 BN_ULONG p16[P256_LIMBS]; 150 BN_ULONG p32[P256_LIMBS]; 151 BN_ULONG res[P256_LIMBS]; 152 int i; 153 154 ecp_nistz256_sqr_mont(res, in); 155 ecp_nistz256_mul_mont(p2, res, in); /* 3*p */ 156 157 ecp_nistz256_sqr_mont(res, p2); 158 ecp_nistz256_sqr_mont(res, res); 159 ecp_nistz256_mul_mont(p4, res, p2); /* f*p */ 160 161 ecp_nistz256_sqr_mont(res, p4); 162 ecp_nistz256_sqr_mont(res, res); 163 ecp_nistz256_sqr_mont(res, res); 164 ecp_nistz256_sqr_mont(res, res); 165 ecp_nistz256_mul_mont(p8, res, p4); /* ff*p */ 166 167 ecp_nistz256_sqr_mont(res, p8); 168 for (i = 0; i < 7; i++) { 169 ecp_nistz256_sqr_mont(res, res); 170 } 171 ecp_nistz256_mul_mont(p16, res, p8); /* ffff*p */ 172 173 ecp_nistz256_sqr_mont(res, p16); 174 for (i = 0; i < 15; i++) { 175 ecp_nistz256_sqr_mont(res, res); 176 } 177 ecp_nistz256_mul_mont(p32, res, p16); /* ffffffff*p */ 178 179 ecp_nistz256_sqr_mont(res, p32); 180 for (i = 0; i < 31; i++) { 181 ecp_nistz256_sqr_mont(res, res); 182 } 183 ecp_nistz256_mul_mont(res, res, in); 184 185 for (i = 0; i < 32 * 4; i++) { 186 ecp_nistz256_sqr_mont(res, res); 187 } 188 ecp_nistz256_mul_mont(res, res, p32); 189 190 for (i = 0; i < 32; i++) { 191 ecp_nistz256_sqr_mont(res, res); 192 } 193 ecp_nistz256_mul_mont(res, res, p32); 194 195 for (i = 0; i < 16; i++) { 196 ecp_nistz256_sqr_mont(res, res); 197 } 198 ecp_nistz256_mul_mont(res, res, p16); 199 200 for (i = 0; i < 8; i++) { 201 ecp_nistz256_sqr_mont(res, res); 202 } 203 ecp_nistz256_mul_mont(res, res, p8); 204 205 ecp_nistz256_sqr_mont(res, res); 206 ecp_nistz256_sqr_mont(res, res); 207 ecp_nistz256_sqr_mont(res, res); 208 ecp_nistz256_sqr_mont(res, res); 209 ecp_nistz256_mul_mont(res, res, p4); 210 211 ecp_nistz256_sqr_mont(res, res); 212 ecp_nistz256_sqr_mont(res, res); 213 ecp_nistz256_mul_mont(res, res, p2); 214 215 ecp_nistz256_sqr_mont(res, res); 216 ecp_nistz256_sqr_mont(res, res); 217 ecp_nistz256_mul_mont(res, res, in); 218 219 memcpy(r, res, sizeof(res)); 220 } 221 222 /* ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and 223 * returns one if it fits. Otherwise it returns zero. */ 224 static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS], 225 const BIGNUM *in) { 226 if (in->top > P256_LIMBS) { 227 return 0; 228 } 229 230 memset(out, 0, sizeof(BN_ULONG) * P256_LIMBS); 231 memcpy(out, in->d, sizeof(BN_ULONG) * in->top); 232 return 1; 233 } 234 235 /* r = p * p_scalar */ 236 static int ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r, 237 const EC_POINT *p, const BIGNUM *p_scalar, 238 BN_CTX *ctx) { 239 assert(p != NULL); 240 assert(p_scalar != NULL); 241 242 static const unsigned kWindowSize = 5; 243 static const unsigned kMask = (1 << (5 /* kWindowSize */ + 1)) - 1; 244 245 /* A |P256_POINT| is (3 * 32) = 96 bytes, and the 64-byte alignment should 246 * add no more than 63 bytes of overhead. Thus, |table| should require 247 * ~1599 ((96 * 16) + 63) bytes of stack space. */ 248 ALIGN(64) P256_POINT table[16]; 249 uint8_t p_str[33]; 250 251 252 int ret = 0; 253 BN_CTX *new_ctx = NULL; 254 int ctx_started = 0; 255 256 if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) { 257 if (ctx == NULL) { 258 new_ctx = BN_CTX_new(); 259 if (new_ctx == NULL) { 260 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 261 goto err; 262 } 263 ctx = new_ctx; 264 } 265 BN_CTX_start(ctx); 266 ctx_started = 1; 267 BIGNUM *mod = BN_CTX_get(ctx); 268 if (mod == NULL) { 269 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 270 goto err; 271 } 272 if (!BN_nnmod(mod, p_scalar, &group->order, ctx)) { 273 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); 274 goto err; 275 } 276 p_scalar = mod; 277 } 278 279 int j; 280 for (j = 0; j < p_scalar->top * BN_BYTES; j += BN_BYTES) { 281 BN_ULONG d = p_scalar->d[j / BN_BYTES]; 282 283 p_str[j + 0] = d & 0xff; 284 p_str[j + 1] = (d >> 8) & 0xff; 285 p_str[j + 2] = (d >> 16) & 0xff; 286 p_str[j + 3] = (d >>= 24) & 0xff; 287 if (BN_BYTES == 8) { 288 d >>= 8; 289 p_str[j + 4] = d & 0xff; 290 p_str[j + 5] = (d >> 8) & 0xff; 291 p_str[j + 6] = (d >> 16) & 0xff; 292 p_str[j + 7] = (d >> 24) & 0xff; 293 } 294 } 295 296 for (; j < 33; j++) { 297 p_str[j] = 0; 298 } 299 300 /* table[0] is implicitly (0,0,0) (the point at infinity), therefore it is 301 * not stored. All other values are actually stored with an offset of -1 in 302 * table. */ 303 P256_POINT *row = table; 304 305 if (!ecp_nistz256_bignum_to_field_elem(row[1 - 1].X, &p->X) || 306 !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Y, &p->Y) || 307 !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Z, &p->Z)) { 308 OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); 309 goto err; 310 } 311 312 ecp_nistz256_point_double(&row[2 - 1], &row[1 - 1]); 313 ecp_nistz256_point_add(&row[3 - 1], &row[2 - 1], &row[1 - 1]); 314 ecp_nistz256_point_double(&row[4 - 1], &row[2 - 1]); 315 ecp_nistz256_point_double(&row[6 - 1], &row[3 - 1]); 316 ecp_nistz256_point_double(&row[8 - 1], &row[4 - 1]); 317 ecp_nistz256_point_double(&row[12 - 1], &row[6 - 1]); 318 ecp_nistz256_point_add(&row[5 - 1], &row[4 - 1], &row[1 - 1]); 319 ecp_nistz256_point_add(&row[7 - 1], &row[6 - 1], &row[1 - 1]); 320 ecp_nistz256_point_add(&row[9 - 1], &row[8 - 1], &row[1 - 1]); 321 ecp_nistz256_point_add(&row[13 - 1], &row[12 - 1], &row[1 - 1]); 322 ecp_nistz256_point_double(&row[14 - 1], &row[7 - 1]); 323 ecp_nistz256_point_double(&row[10 - 1], &row[5 - 1]); 324 ecp_nistz256_point_add(&row[15 - 1], &row[14 - 1], &row[1 - 1]); 325 ecp_nistz256_point_add(&row[11 - 1], &row[10 - 1], &row[1 - 1]); 326 ecp_nistz256_point_add(&row[16 - 1], &row[15 - 1], &row[1 - 1]); 327 328 BN_ULONG tmp[P256_LIMBS]; 329 ALIGN(32) P256_POINT h; 330 unsigned index = 255; 331 unsigned wvalue = p_str[(index - 1) / 8]; 332 wvalue = (wvalue >> ((index - 1) % 8)) & kMask; 333 334 ecp_nistz256_select_w5(r, table, booth_recode_w5(wvalue) >> 1); 335 336 while (index >= 5) { 337 if (index != 255) { 338 unsigned off = (index - 1) / 8; 339 340 wvalue = p_str[off] | p_str[off + 1] << 8; 341 wvalue = (wvalue >> ((index - 1) % 8)) & kMask; 342 343 wvalue = booth_recode_w5(wvalue); 344 345 ecp_nistz256_select_w5(&h, table, wvalue >> 1); 346 347 ecp_nistz256_neg(tmp, h.Y); 348 copy_conditional(h.Y, tmp, (wvalue & 1)); 349 350 ecp_nistz256_point_add(r, r, &h); 351 } 352 353 index -= kWindowSize; 354 355 ecp_nistz256_point_double(r, r); 356 ecp_nistz256_point_double(r, r); 357 ecp_nistz256_point_double(r, r); 358 ecp_nistz256_point_double(r, r); 359 ecp_nistz256_point_double(r, r); 360 } 361 362 /* Final window */ 363 wvalue = p_str[0]; 364 wvalue = (wvalue << 1) & kMask; 365 366 wvalue = booth_recode_w5(wvalue); 367 368 ecp_nistz256_select_w5(&h, table, wvalue >> 1); 369 370 ecp_nistz256_neg(tmp, h.Y); 371 copy_conditional(h.Y, tmp, wvalue & 1); 372 373 ecp_nistz256_point_add(r, r, &h); 374 375 ret = 1; 376 377 err: 378 if (ctx_started) { 379 BN_CTX_end(ctx); 380 } 381 BN_CTX_free(new_ctx); 382 return ret; 383 } 384 385 static int ecp_nistz256_points_mul( 386 const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 387 const EC_POINT *p_, const BIGNUM *p_scalar, BN_CTX *ctx) { 388 assert((p_ != NULL) == (p_scalar != NULL)); 389 390 static const unsigned kWindowSize = 7; 391 static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1; 392 393 ALIGN(32) union { 394 P256_POINT p; 395 P256_POINT_AFFINE a; 396 } t, p; 397 398 int ret = 0; 399 BN_CTX *new_ctx = NULL; 400 int ctx_started = 0; 401 402 /* Need 256 bits for space for all coordinates. */ 403 if (bn_wexpand(&r->X, P256_LIMBS) == NULL || 404 bn_wexpand(&r->Y, P256_LIMBS) == NULL || 405 bn_wexpand(&r->Z, P256_LIMBS) == NULL) { 406 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 407 goto err; 408 } 409 r->X.top = P256_LIMBS; 410 r->Y.top = P256_LIMBS; 411 r->Z.top = P256_LIMBS; 412 413 if (g_scalar != NULL) { 414 if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) { 415 if (ctx == NULL) { 416 new_ctx = BN_CTX_new(); 417 if (new_ctx == NULL) { 418 goto err; 419 } 420 ctx = new_ctx; 421 } 422 BN_CTX_start(ctx); 423 ctx_started = 1; 424 BIGNUM *tmp_scalar = BN_CTX_get(ctx); 425 if (tmp_scalar == NULL) { 426 goto err; 427 } 428 429 if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) { 430 OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); 431 goto err; 432 } 433 g_scalar = tmp_scalar; 434 } 435 436 uint8_t p_str[33] = {0}; 437 int i; 438 for (i = 0; i < g_scalar->top * BN_BYTES; i += BN_BYTES) { 439 BN_ULONG d = g_scalar->d[i / BN_BYTES]; 440 441 p_str[i + 0] = d & 0xff; 442 p_str[i + 1] = (d >> 8) & 0xff; 443 p_str[i + 2] = (d >> 16) & 0xff; 444 p_str[i + 3] = (d >>= 24) & 0xff; 445 if (BN_BYTES == 8) { 446 d >>= 8; 447 p_str[i + 4] = d & 0xff; 448 p_str[i + 5] = (d >> 8) & 0xff; 449 p_str[i + 6] = (d >> 16) & 0xff; 450 p_str[i + 7] = (d >> 24) & 0xff; 451 } 452 } 453 454 for (; i < (int) sizeof(p_str); i++) { 455 p_str[i] = 0; 456 } 457 458 /* First window */ 459 unsigned wvalue = (p_str[0] << 1) & kMask; 460 unsigned index = kWindowSize; 461 462 wvalue = booth_recode_w7(wvalue); 463 464 const PRECOMP256_ROW *const precomputed_table = 465 (const PRECOMP256_ROW *)ecp_nistz256_precomputed; 466 ecp_nistz256_select_w7(&p.a, precomputed_table[0], wvalue >> 1); 467 468 ecp_nistz256_neg(p.p.Z, p.p.Y); 469 copy_conditional(p.p.Y, p.p.Z, wvalue & 1); 470 471 memcpy(p.p.Z, ONE, sizeof(ONE)); 472 473 for (i = 1; i < 37; i++) { 474 unsigned off = (index - 1) / 8; 475 wvalue = p_str[off] | p_str[off + 1] << 8; 476 wvalue = (wvalue >> ((index - 1) % 8)) & kMask; 477 index += kWindowSize; 478 479 wvalue = booth_recode_w7(wvalue); 480 481 ecp_nistz256_select_w7(&t.a, precomputed_table[i], wvalue >> 1); 482 483 ecp_nistz256_neg(t.p.Z, t.a.Y); 484 copy_conditional(t.a.Y, t.p.Z, wvalue & 1); 485 486 ecp_nistz256_point_add_affine(&p.p, &p.p, &t.a); 487 } 488 } 489 490 const int p_is_infinity = g_scalar == NULL; 491 if (p_scalar != NULL) { 492 P256_POINT *out = &t.p; 493 if (p_is_infinity) { 494 out = &p.p; 495 } 496 497 if (!ecp_nistz256_windowed_mul(group, out, p_, p_scalar, ctx)) { 498 goto err; 499 } 500 501 if (!p_is_infinity) { 502 ecp_nistz256_point_add(&p.p, &p.p, out); 503 } 504 } 505 506 memcpy(r->X.d, p.p.X, sizeof(p.p.X)); 507 memcpy(r->Y.d, p.p.Y, sizeof(p.p.Y)); 508 memcpy(r->Z.d, p.p.Z, sizeof(p.p.Z)); 509 510 /* Not constant-time, but we're only operating on the public output. */ 511 bn_correct_top(&r->X); 512 bn_correct_top(&r->Y); 513 bn_correct_top(&r->Z); 514 r->Z_is_one = BN_is_one(&r->Z); 515 516 ret = 1; 517 518 err: 519 if (ctx_started) { 520 BN_CTX_end(ctx); 521 } 522 BN_CTX_free(new_ctx); 523 return ret; 524 } 525 526 static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point, 527 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { 528 BN_ULONG z_inv2[P256_LIMBS]; 529 BN_ULONG z_inv3[P256_LIMBS]; 530 BN_ULONG x_aff[P256_LIMBS]; 531 BN_ULONG y_aff[P256_LIMBS]; 532 BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS]; 533 534 if (EC_POINT_is_at_infinity(group, point)) { 535 OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); 536 return 0; 537 } 538 539 if (!ecp_nistz256_bignum_to_field_elem(point_x, &point->X) || 540 !ecp_nistz256_bignum_to_field_elem(point_y, &point->Y) || 541 !ecp_nistz256_bignum_to_field_elem(point_z, &point->Z)) { 542 OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); 543 return 0; 544 } 545 546 ecp_nistz256_mod_inverse(z_inv3, point_z); 547 ecp_nistz256_sqr_mont(z_inv2, z_inv3); 548 ecp_nistz256_mul_mont(x_aff, z_inv2, point_x); 549 550 if (x != NULL) { 551 if (bn_wexpand(x, P256_LIMBS) == NULL) { 552 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 553 return 0; 554 } 555 x->top = P256_LIMBS; 556 ecp_nistz256_from_mont(x->d, x_aff); 557 bn_correct_top(x); 558 } 559 560 if (y != NULL) { 561 ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2); 562 ecp_nistz256_mul_mont(y_aff, z_inv3, point_y); 563 if (bn_wexpand(y, P256_LIMBS) == NULL) { 564 OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 565 return 0; 566 } 567 y->top = P256_LIMBS; 568 ecp_nistz256_from_mont(y->d, y_aff); 569 bn_correct_top(y); 570 } 571 572 return 1; 573 } 574 575 const EC_METHOD *EC_GFp_nistz256_method(void) { 576 static const EC_METHOD ret = { 577 ec_GFp_mont_group_init, 578 ec_GFp_mont_group_finish, 579 ec_GFp_mont_group_clear_finish, 580 ec_GFp_mont_group_copy, 581 ec_GFp_mont_group_set_curve, 582 ecp_nistz256_get_affine, 583 ecp_nistz256_points_mul, 584 0 /* check_pub_key_order */, 585 ec_GFp_mont_field_mul, 586 ec_GFp_mont_field_sqr, 587 ec_GFp_mont_field_encode, 588 ec_GFp_mont_field_decode, 589 ec_GFp_mont_field_set_to_one, 590 }; 591 592 return &ret; 593 } 594 595 #endif /* !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ 596 !defined(OPENSSL_SMALL) */ 597