1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 4e1051a39Sopenharmony_ci * 5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 6e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 9e1051a39Sopenharmony_ci */ 10e1051a39Sopenharmony_ci 11e1051a39Sopenharmony_ci/* 12e1051a39Sopenharmony_ci * ECDSA low level APIs are deprecated for public use, but still ok for 13e1051a39Sopenharmony_ci * internal use. 14e1051a39Sopenharmony_ci */ 15e1051a39Sopenharmony_ci#include "internal/deprecated.h" 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#include <string.h> 18e1051a39Sopenharmony_ci#include <openssl/err.h> 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 21e1051a39Sopenharmony_ci#include "crypto/bn.h" 22e1051a39Sopenharmony_ci#include "ec_local.h" 23e1051a39Sopenharmony_ci#include "internal/refcount.h" 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci/* 26e1051a39Sopenharmony_ci * This file implements the wNAF-based interleaving multi-exponentiation method 27e1051a39Sopenharmony_ci * Formerly at: 28e1051a39Sopenharmony_ci * http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp 29e1051a39Sopenharmony_ci * You might now find it here: 30e1051a39Sopenharmony_ci * http://link.springer.com/chapter/10.1007%2F3-540-45537-X_13 31e1051a39Sopenharmony_ci * http://www.bmoeller.de/pdf/TI-01-08.multiexp.pdf 32e1051a39Sopenharmony_ci * For multiplication with precomputation, we use wNAF splitting, formerly at: 33e1051a39Sopenharmony_ci * http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp 34e1051a39Sopenharmony_ci */ 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci/* structure for precomputed multiples of the generator */ 37e1051a39Sopenharmony_cistruct ec_pre_comp_st { 38e1051a39Sopenharmony_ci const EC_GROUP *group; /* parent EC_GROUP object */ 39e1051a39Sopenharmony_ci size_t blocksize; /* block size for wNAF splitting */ 40e1051a39Sopenharmony_ci size_t numblocks; /* max. number of blocks for which we have 41e1051a39Sopenharmony_ci * precomputation */ 42e1051a39Sopenharmony_ci size_t w; /* window size */ 43e1051a39Sopenharmony_ci EC_POINT **points; /* array with pre-calculated multiples of 44e1051a39Sopenharmony_ci * generator: 'num' pointers to EC_POINT 45e1051a39Sopenharmony_ci * objects followed by a NULL */ 46e1051a39Sopenharmony_ci size_t num; /* numblocks * 2^(w-1) */ 47e1051a39Sopenharmony_ci CRYPTO_REF_COUNT references; 48e1051a39Sopenharmony_ci CRYPTO_RWLOCK *lock; 49e1051a39Sopenharmony_ci}; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_cistatic EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) 52e1051a39Sopenharmony_ci{ 53e1051a39Sopenharmony_ci EC_PRE_COMP *ret = NULL; 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci if (!group) 56e1051a39Sopenharmony_ci return NULL; 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci ret = OPENSSL_zalloc(sizeof(*ret)); 59e1051a39Sopenharmony_ci if (ret == NULL) { 60e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 61e1051a39Sopenharmony_ci return ret; 62e1051a39Sopenharmony_ci } 63e1051a39Sopenharmony_ci 64e1051a39Sopenharmony_ci ret->group = group; 65e1051a39Sopenharmony_ci ret->blocksize = 8; /* default */ 66e1051a39Sopenharmony_ci ret->w = 4; /* default */ 67e1051a39Sopenharmony_ci ret->references = 1; 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_ci ret->lock = CRYPTO_THREAD_lock_new(); 70e1051a39Sopenharmony_ci if (ret->lock == NULL) { 71e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 72e1051a39Sopenharmony_ci OPENSSL_free(ret); 73e1051a39Sopenharmony_ci return NULL; 74e1051a39Sopenharmony_ci } 75e1051a39Sopenharmony_ci return ret; 76e1051a39Sopenharmony_ci} 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_ciEC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre) 79e1051a39Sopenharmony_ci{ 80e1051a39Sopenharmony_ci int i; 81e1051a39Sopenharmony_ci if (pre != NULL) 82e1051a39Sopenharmony_ci CRYPTO_UP_REF(&pre->references, &i, pre->lock); 83e1051a39Sopenharmony_ci return pre; 84e1051a39Sopenharmony_ci} 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_civoid EC_ec_pre_comp_free(EC_PRE_COMP *pre) 87e1051a39Sopenharmony_ci{ 88e1051a39Sopenharmony_ci int i; 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci if (pre == NULL) 91e1051a39Sopenharmony_ci return; 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); 94e1051a39Sopenharmony_ci REF_PRINT_COUNT("EC_ec", pre); 95e1051a39Sopenharmony_ci if (i > 0) 96e1051a39Sopenharmony_ci return; 97e1051a39Sopenharmony_ci REF_ASSERT_ISNT(i < 0); 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci if (pre->points != NULL) { 100e1051a39Sopenharmony_ci EC_POINT **pts; 101e1051a39Sopenharmony_ci 102e1051a39Sopenharmony_ci for (pts = pre->points; *pts != NULL; pts++) 103e1051a39Sopenharmony_ci EC_POINT_free(*pts); 104e1051a39Sopenharmony_ci OPENSSL_free(pre->points); 105e1051a39Sopenharmony_ci } 106e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(pre->lock); 107e1051a39Sopenharmony_ci OPENSSL_free(pre); 108e1051a39Sopenharmony_ci} 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci#define EC_POINT_BN_set_flags(P, flags) do { \ 111e1051a39Sopenharmony_ci BN_set_flags((P)->X, (flags)); \ 112e1051a39Sopenharmony_ci BN_set_flags((P)->Y, (flags)); \ 113e1051a39Sopenharmony_ci BN_set_flags((P)->Z, (flags)); \ 114e1051a39Sopenharmony_ci} while(0) 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_ci/*- 117e1051a39Sopenharmony_ci * This functions computes a single point multiplication over the EC group, 118e1051a39Sopenharmony_ci * using, at a high level, a Montgomery ladder with conditional swaps, with 119e1051a39Sopenharmony_ci * various timing attack defenses. 120e1051a39Sopenharmony_ci * 121e1051a39Sopenharmony_ci * It performs either a fixed point multiplication 122e1051a39Sopenharmony_ci * (scalar * generator) 123e1051a39Sopenharmony_ci * when point is NULL, or a variable point multiplication 124e1051a39Sopenharmony_ci * (scalar * point) 125e1051a39Sopenharmony_ci * when point is not NULL. 126e1051a39Sopenharmony_ci * 127e1051a39Sopenharmony_ci * `scalar` cannot be NULL and should be in the range [0,n) otherwise all 128e1051a39Sopenharmony_ci * constant time bets are off (where n is the cardinality of the EC group). 129e1051a39Sopenharmony_ci * 130e1051a39Sopenharmony_ci * This function expects `group->order` and `group->cardinality` to be well 131e1051a39Sopenharmony_ci * defined and non-zero: it fails with an error code otherwise. 132e1051a39Sopenharmony_ci * 133e1051a39Sopenharmony_ci * NB: This says nothing about the constant-timeness of the ladder step 134e1051a39Sopenharmony_ci * implementation (i.e., the default implementation is based on EC_POINT_add and 135e1051a39Sopenharmony_ci * EC_POINT_dbl, which of course are not constant time themselves) or the 136e1051a39Sopenharmony_ci * underlying multiprecision arithmetic. 137e1051a39Sopenharmony_ci * 138e1051a39Sopenharmony_ci * The product is stored in `r`. 139e1051a39Sopenharmony_ci * 140e1051a39Sopenharmony_ci * This is an internal function: callers are in charge of ensuring that the 141e1051a39Sopenharmony_ci * input parameters `group`, `r`, `scalar` and `ctx` are not NULL. 142e1051a39Sopenharmony_ci * 143e1051a39Sopenharmony_ci * Returns 1 on success, 0 otherwise. 144e1051a39Sopenharmony_ci */ 145e1051a39Sopenharmony_ciint ossl_ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, 146e1051a39Sopenharmony_ci const BIGNUM *scalar, const EC_POINT *point, 147e1051a39Sopenharmony_ci BN_CTX *ctx) 148e1051a39Sopenharmony_ci{ 149e1051a39Sopenharmony_ci int i, cardinality_bits, group_top, kbit, pbit, Z_is_one; 150e1051a39Sopenharmony_ci EC_POINT *p = NULL; 151e1051a39Sopenharmony_ci EC_POINT *s = NULL; 152e1051a39Sopenharmony_ci BIGNUM *k = NULL; 153e1051a39Sopenharmony_ci BIGNUM *lambda = NULL; 154e1051a39Sopenharmony_ci BIGNUM *cardinality = NULL; 155e1051a39Sopenharmony_ci int ret = 0; 156e1051a39Sopenharmony_ci 157e1051a39Sopenharmony_ci /* early exit if the input point is the point at infinity */ 158e1051a39Sopenharmony_ci if (point != NULL && EC_POINT_is_at_infinity(group, point)) 159e1051a39Sopenharmony_ci return EC_POINT_set_to_infinity(group, r); 160e1051a39Sopenharmony_ci 161e1051a39Sopenharmony_ci if (BN_is_zero(group->order)) { 162e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER); 163e1051a39Sopenharmony_ci return 0; 164e1051a39Sopenharmony_ci } 165e1051a39Sopenharmony_ci if (BN_is_zero(group->cofactor)) { 166e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR); 167e1051a39Sopenharmony_ci return 0; 168e1051a39Sopenharmony_ci } 169e1051a39Sopenharmony_ci 170e1051a39Sopenharmony_ci BN_CTX_start(ctx); 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ci if (((p = EC_POINT_new(group)) == NULL) 173e1051a39Sopenharmony_ci || ((s = EC_POINT_new(group)) == NULL)) { 174e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 175e1051a39Sopenharmony_ci goto err; 176e1051a39Sopenharmony_ci } 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci if (point == NULL) { 179e1051a39Sopenharmony_ci if (!EC_POINT_copy(p, group->generator)) { 180e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); 181e1051a39Sopenharmony_ci goto err; 182e1051a39Sopenharmony_ci } 183e1051a39Sopenharmony_ci } else { 184e1051a39Sopenharmony_ci if (!EC_POINT_copy(p, point)) { 185e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); 186e1051a39Sopenharmony_ci goto err; 187e1051a39Sopenharmony_ci } 188e1051a39Sopenharmony_ci } 189e1051a39Sopenharmony_ci 190e1051a39Sopenharmony_ci EC_POINT_BN_set_flags(p, BN_FLG_CONSTTIME); 191e1051a39Sopenharmony_ci EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME); 192e1051a39Sopenharmony_ci EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME); 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci cardinality = BN_CTX_get(ctx); 195e1051a39Sopenharmony_ci lambda = BN_CTX_get(ctx); 196e1051a39Sopenharmony_ci k = BN_CTX_get(ctx); 197e1051a39Sopenharmony_ci if (k == NULL) { 198e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 199e1051a39Sopenharmony_ci goto err; 200e1051a39Sopenharmony_ci } 201e1051a39Sopenharmony_ci 202e1051a39Sopenharmony_ci if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) { 203e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 204e1051a39Sopenharmony_ci goto err; 205e1051a39Sopenharmony_ci } 206e1051a39Sopenharmony_ci 207e1051a39Sopenharmony_ci /* 208e1051a39Sopenharmony_ci * Group cardinalities are often on a word boundary. 209e1051a39Sopenharmony_ci * So when we pad the scalar, some timing diff might 210e1051a39Sopenharmony_ci * pop if it needs to be expanded due to carries. 211e1051a39Sopenharmony_ci * So expand ahead of time. 212e1051a39Sopenharmony_ci */ 213e1051a39Sopenharmony_ci cardinality_bits = BN_num_bits(cardinality); 214e1051a39Sopenharmony_ci group_top = bn_get_top(cardinality); 215e1051a39Sopenharmony_ci if ((bn_wexpand(k, group_top + 2) == NULL) 216e1051a39Sopenharmony_ci || (bn_wexpand(lambda, group_top + 2) == NULL)) { 217e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 218e1051a39Sopenharmony_ci goto err; 219e1051a39Sopenharmony_ci } 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci if (!BN_copy(k, scalar)) { 222e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 223e1051a39Sopenharmony_ci goto err; 224e1051a39Sopenharmony_ci } 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_ci BN_set_flags(k, BN_FLG_CONSTTIME); 227e1051a39Sopenharmony_ci 228e1051a39Sopenharmony_ci if ((BN_num_bits(k) > cardinality_bits) || (BN_is_negative(k))) { 229e1051a39Sopenharmony_ci /*- 230e1051a39Sopenharmony_ci * this is an unusual input, and we don't guarantee 231e1051a39Sopenharmony_ci * constant-timeness 232e1051a39Sopenharmony_ci */ 233e1051a39Sopenharmony_ci if (!BN_nnmod(k, k, cardinality, ctx)) { 234e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 235e1051a39Sopenharmony_ci goto err; 236e1051a39Sopenharmony_ci } 237e1051a39Sopenharmony_ci } 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci if (!BN_add(lambda, k, cardinality)) { 240e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 241e1051a39Sopenharmony_ci goto err; 242e1051a39Sopenharmony_ci } 243e1051a39Sopenharmony_ci BN_set_flags(lambda, BN_FLG_CONSTTIME); 244e1051a39Sopenharmony_ci if (!BN_add(k, lambda, cardinality)) { 245e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 246e1051a39Sopenharmony_ci goto err; 247e1051a39Sopenharmony_ci } 248e1051a39Sopenharmony_ci /* 249e1051a39Sopenharmony_ci * lambda := scalar + cardinality 250e1051a39Sopenharmony_ci * k := scalar + 2*cardinality 251e1051a39Sopenharmony_ci */ 252e1051a39Sopenharmony_ci kbit = BN_is_bit_set(lambda, cardinality_bits); 253e1051a39Sopenharmony_ci BN_consttime_swap(kbit, k, lambda, group_top + 2); 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci group_top = bn_get_top(group->field); 256e1051a39Sopenharmony_ci if ((bn_wexpand(s->X, group_top) == NULL) 257e1051a39Sopenharmony_ci || (bn_wexpand(s->Y, group_top) == NULL) 258e1051a39Sopenharmony_ci || (bn_wexpand(s->Z, group_top) == NULL) 259e1051a39Sopenharmony_ci || (bn_wexpand(r->X, group_top) == NULL) 260e1051a39Sopenharmony_ci || (bn_wexpand(r->Y, group_top) == NULL) 261e1051a39Sopenharmony_ci || (bn_wexpand(r->Z, group_top) == NULL) 262e1051a39Sopenharmony_ci || (bn_wexpand(p->X, group_top) == NULL) 263e1051a39Sopenharmony_ci || (bn_wexpand(p->Y, group_top) == NULL) 264e1051a39Sopenharmony_ci || (bn_wexpand(p->Z, group_top) == NULL)) { 265e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 266e1051a39Sopenharmony_ci goto err; 267e1051a39Sopenharmony_ci } 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci /* ensure input point is in affine coords for ladder step efficiency */ 270e1051a39Sopenharmony_ci if (!p->Z_is_one && (group->meth->make_affine == NULL 271e1051a39Sopenharmony_ci || !group->meth->make_affine(group, p, ctx))) { 272e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); 273e1051a39Sopenharmony_ci goto err; 274e1051a39Sopenharmony_ci } 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ci /* Initialize the Montgomery ladder */ 277e1051a39Sopenharmony_ci if (!ec_point_ladder_pre(group, r, s, p, ctx)) { 278e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_LADDER_PRE_FAILURE); 279e1051a39Sopenharmony_ci goto err; 280e1051a39Sopenharmony_ci } 281e1051a39Sopenharmony_ci 282e1051a39Sopenharmony_ci /* top bit is a 1, in a fixed pos */ 283e1051a39Sopenharmony_ci pbit = 1; 284e1051a39Sopenharmony_ci 285e1051a39Sopenharmony_ci#define EC_POINT_CSWAP(c, a, b, w, t) do { \ 286e1051a39Sopenharmony_ci BN_consttime_swap(c, (a)->X, (b)->X, w); \ 287e1051a39Sopenharmony_ci BN_consttime_swap(c, (a)->Y, (b)->Y, w); \ 288e1051a39Sopenharmony_ci BN_consttime_swap(c, (a)->Z, (b)->Z, w); \ 289e1051a39Sopenharmony_ci t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \ 290e1051a39Sopenharmony_ci (a)->Z_is_one ^= (t); \ 291e1051a39Sopenharmony_ci (b)->Z_is_one ^= (t); \ 292e1051a39Sopenharmony_ci} while(0) 293e1051a39Sopenharmony_ci 294e1051a39Sopenharmony_ci /*- 295e1051a39Sopenharmony_ci * The ladder step, with branches, is 296e1051a39Sopenharmony_ci * 297e1051a39Sopenharmony_ci * k[i] == 0: S = add(R, S), R = dbl(R) 298e1051a39Sopenharmony_ci * k[i] == 1: R = add(S, R), S = dbl(S) 299e1051a39Sopenharmony_ci * 300e1051a39Sopenharmony_ci * Swapping R, S conditionally on k[i] leaves you with state 301e1051a39Sopenharmony_ci * 302e1051a39Sopenharmony_ci * k[i] == 0: T, U = R, S 303e1051a39Sopenharmony_ci * k[i] == 1: T, U = S, R 304e1051a39Sopenharmony_ci * 305e1051a39Sopenharmony_ci * Then perform the ECC ops. 306e1051a39Sopenharmony_ci * 307e1051a39Sopenharmony_ci * U = add(T, U) 308e1051a39Sopenharmony_ci * T = dbl(T) 309e1051a39Sopenharmony_ci * 310e1051a39Sopenharmony_ci * Which leaves you with state 311e1051a39Sopenharmony_ci * 312e1051a39Sopenharmony_ci * k[i] == 0: U = add(R, S), T = dbl(R) 313e1051a39Sopenharmony_ci * k[i] == 1: U = add(S, R), T = dbl(S) 314e1051a39Sopenharmony_ci * 315e1051a39Sopenharmony_ci * Swapping T, U conditionally on k[i] leaves you with state 316e1051a39Sopenharmony_ci * 317e1051a39Sopenharmony_ci * k[i] == 0: R, S = T, U 318e1051a39Sopenharmony_ci * k[i] == 1: R, S = U, T 319e1051a39Sopenharmony_ci * 320e1051a39Sopenharmony_ci * Which leaves you with state 321e1051a39Sopenharmony_ci * 322e1051a39Sopenharmony_ci * k[i] == 0: S = add(R, S), R = dbl(R) 323e1051a39Sopenharmony_ci * k[i] == 1: R = add(S, R), S = dbl(S) 324e1051a39Sopenharmony_ci * 325e1051a39Sopenharmony_ci * So we get the same logic, but instead of a branch it's a 326e1051a39Sopenharmony_ci * conditional swap, followed by ECC ops, then another conditional swap. 327e1051a39Sopenharmony_ci * 328e1051a39Sopenharmony_ci * Optimization: The end of iteration i and start of i-1 looks like 329e1051a39Sopenharmony_ci * 330e1051a39Sopenharmony_ci * ... 331e1051a39Sopenharmony_ci * CSWAP(k[i], R, S) 332e1051a39Sopenharmony_ci * ECC 333e1051a39Sopenharmony_ci * CSWAP(k[i], R, S) 334e1051a39Sopenharmony_ci * (next iteration) 335e1051a39Sopenharmony_ci * CSWAP(k[i-1], R, S) 336e1051a39Sopenharmony_ci * ECC 337e1051a39Sopenharmony_ci * CSWAP(k[i-1], R, S) 338e1051a39Sopenharmony_ci * ... 339e1051a39Sopenharmony_ci * 340e1051a39Sopenharmony_ci * So instead of two contiguous swaps, you can merge the condition 341e1051a39Sopenharmony_ci * bits and do a single swap. 342e1051a39Sopenharmony_ci * 343e1051a39Sopenharmony_ci * k[i] k[i-1] Outcome 344e1051a39Sopenharmony_ci * 0 0 No Swap 345e1051a39Sopenharmony_ci * 0 1 Swap 346e1051a39Sopenharmony_ci * 1 0 Swap 347e1051a39Sopenharmony_ci * 1 1 No Swap 348e1051a39Sopenharmony_ci * 349e1051a39Sopenharmony_ci * This is XOR. pbit tracks the previous bit of k. 350e1051a39Sopenharmony_ci */ 351e1051a39Sopenharmony_ci 352e1051a39Sopenharmony_ci for (i = cardinality_bits - 1; i >= 0; i--) { 353e1051a39Sopenharmony_ci kbit = BN_is_bit_set(k, i) ^ pbit; 354e1051a39Sopenharmony_ci EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one); 355e1051a39Sopenharmony_ci 356e1051a39Sopenharmony_ci /* Perform a single step of the Montgomery ladder */ 357e1051a39Sopenharmony_ci if (!ec_point_ladder_step(group, r, s, p, ctx)) { 358e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_LADDER_STEP_FAILURE); 359e1051a39Sopenharmony_ci goto err; 360e1051a39Sopenharmony_ci } 361e1051a39Sopenharmony_ci /* 362e1051a39Sopenharmony_ci * pbit logic merges this cswap with that of the 363e1051a39Sopenharmony_ci * next iteration 364e1051a39Sopenharmony_ci */ 365e1051a39Sopenharmony_ci pbit ^= kbit; 366e1051a39Sopenharmony_ci } 367e1051a39Sopenharmony_ci /* one final cswap to move the right value into r */ 368e1051a39Sopenharmony_ci EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one); 369e1051a39Sopenharmony_ci#undef EC_POINT_CSWAP 370e1051a39Sopenharmony_ci 371e1051a39Sopenharmony_ci /* Finalize ladder (and recover full point coordinates) */ 372e1051a39Sopenharmony_ci if (!ec_point_ladder_post(group, r, s, p, ctx)) { 373e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_LADDER_POST_FAILURE); 374e1051a39Sopenharmony_ci goto err; 375e1051a39Sopenharmony_ci } 376e1051a39Sopenharmony_ci 377e1051a39Sopenharmony_ci ret = 1; 378e1051a39Sopenharmony_ci 379e1051a39Sopenharmony_ci err: 380e1051a39Sopenharmony_ci EC_POINT_free(p); 381e1051a39Sopenharmony_ci EC_POINT_clear_free(s); 382e1051a39Sopenharmony_ci BN_CTX_end(ctx); 383e1051a39Sopenharmony_ci 384e1051a39Sopenharmony_ci return ret; 385e1051a39Sopenharmony_ci} 386e1051a39Sopenharmony_ci 387e1051a39Sopenharmony_ci#undef EC_POINT_BN_set_flags 388e1051a39Sopenharmony_ci 389e1051a39Sopenharmony_ci/* 390e1051a39Sopenharmony_ci * Table could be optimised for the wNAF-based implementation, 391e1051a39Sopenharmony_ci * sometimes smaller windows will give better performance (thus the 392e1051a39Sopenharmony_ci * boundaries should be increased) 393e1051a39Sopenharmony_ci */ 394e1051a39Sopenharmony_ci#define EC_window_bits_for_scalar_size(b) \ 395e1051a39Sopenharmony_ci ((size_t) \ 396e1051a39Sopenharmony_ci ((b) >= 2000 ? 6 : \ 397e1051a39Sopenharmony_ci (b) >= 800 ? 5 : \ 398e1051a39Sopenharmony_ci (b) >= 300 ? 4 : \ 399e1051a39Sopenharmony_ci (b) >= 70 ? 3 : \ 400e1051a39Sopenharmony_ci (b) >= 20 ? 2 : \ 401e1051a39Sopenharmony_ci 1)) 402e1051a39Sopenharmony_ci 403e1051a39Sopenharmony_ci/*- 404e1051a39Sopenharmony_ci * Compute 405e1051a39Sopenharmony_ci * \sum scalars[i]*points[i], 406e1051a39Sopenharmony_ci * also including 407e1051a39Sopenharmony_ci * scalar*generator 408e1051a39Sopenharmony_ci * in the addition if scalar != NULL 409e1051a39Sopenharmony_ci */ 410e1051a39Sopenharmony_ciint ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 411e1051a39Sopenharmony_ci size_t num, const EC_POINT *points[], 412e1051a39Sopenharmony_ci const BIGNUM *scalars[], BN_CTX *ctx) 413e1051a39Sopenharmony_ci{ 414e1051a39Sopenharmony_ci const EC_POINT *generator = NULL; 415e1051a39Sopenharmony_ci EC_POINT *tmp = NULL; 416e1051a39Sopenharmony_ci size_t totalnum; 417e1051a39Sopenharmony_ci size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */ 418e1051a39Sopenharmony_ci size_t pre_points_per_block = 0; 419e1051a39Sopenharmony_ci size_t i, j; 420e1051a39Sopenharmony_ci int k; 421e1051a39Sopenharmony_ci int r_is_inverted = 0; 422e1051a39Sopenharmony_ci int r_is_at_infinity = 1; 423e1051a39Sopenharmony_ci size_t *wsize = NULL; /* individual window sizes */ 424e1051a39Sopenharmony_ci signed char **wNAF = NULL; /* individual wNAFs */ 425e1051a39Sopenharmony_ci size_t *wNAF_len = NULL; 426e1051a39Sopenharmony_ci size_t max_len = 0; 427e1051a39Sopenharmony_ci size_t num_val; 428e1051a39Sopenharmony_ci EC_POINT **val = NULL; /* precomputation */ 429e1051a39Sopenharmony_ci EC_POINT **v; 430e1051a39Sopenharmony_ci EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or 431e1051a39Sopenharmony_ci * 'pre_comp->points' */ 432e1051a39Sopenharmony_ci const EC_PRE_COMP *pre_comp = NULL; 433e1051a39Sopenharmony_ci int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be 434e1051a39Sopenharmony_ci * treated like other scalars, i.e. 435e1051a39Sopenharmony_ci * precomputation is not available */ 436e1051a39Sopenharmony_ci int ret = 0; 437e1051a39Sopenharmony_ci 438e1051a39Sopenharmony_ci if (!BN_is_zero(group->order) && !BN_is_zero(group->cofactor)) { 439e1051a39Sopenharmony_ci /*- 440e1051a39Sopenharmony_ci * Handle the common cases where the scalar is secret, enforcing a 441e1051a39Sopenharmony_ci * scalar multiplication implementation based on a Montgomery ladder, 442e1051a39Sopenharmony_ci * with various timing attack defenses. 443e1051a39Sopenharmony_ci */ 444e1051a39Sopenharmony_ci if ((scalar != group->order) && (scalar != NULL) && (num == 0)) { 445e1051a39Sopenharmony_ci /*- 446e1051a39Sopenharmony_ci * In this case we want to compute scalar * GeneratorPoint: this 447e1051a39Sopenharmony_ci * codepath is reached most prominently by (ephemeral) key 448e1051a39Sopenharmony_ci * generation of EC cryptosystems (i.e. ECDSA keygen and sign setup, 449e1051a39Sopenharmony_ci * ECDH keygen/first half), where the scalar is always secret. This 450e1051a39Sopenharmony_ci * is why we ignore if BN_FLG_CONSTTIME is actually set and we 451e1051a39Sopenharmony_ci * always call the ladder version. 452e1051a39Sopenharmony_ci */ 453e1051a39Sopenharmony_ci return ossl_ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); 454e1051a39Sopenharmony_ci } 455e1051a39Sopenharmony_ci if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) { 456e1051a39Sopenharmony_ci /*- 457e1051a39Sopenharmony_ci * In this case we want to compute scalar * VariablePoint: this 458e1051a39Sopenharmony_ci * codepath is reached most prominently by the second half of ECDH, 459e1051a39Sopenharmony_ci * where the secret scalar is multiplied by the peer's public point. 460e1051a39Sopenharmony_ci * To protect the secret scalar, we ignore if BN_FLG_CONSTTIME is 461e1051a39Sopenharmony_ci * actually set and we always call the ladder version. 462e1051a39Sopenharmony_ci */ 463e1051a39Sopenharmony_ci return ossl_ec_scalar_mul_ladder(group, r, scalars[0], points[0], 464e1051a39Sopenharmony_ci ctx); 465e1051a39Sopenharmony_ci } 466e1051a39Sopenharmony_ci } 467e1051a39Sopenharmony_ci 468e1051a39Sopenharmony_ci if (scalar != NULL) { 469e1051a39Sopenharmony_ci generator = EC_GROUP_get0_generator(group); 470e1051a39Sopenharmony_ci if (generator == NULL) { 471e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR); 472e1051a39Sopenharmony_ci goto err; 473e1051a39Sopenharmony_ci } 474e1051a39Sopenharmony_ci 475e1051a39Sopenharmony_ci /* look if we can use precomputed multiples of generator */ 476e1051a39Sopenharmony_ci 477e1051a39Sopenharmony_ci pre_comp = group->pre_comp.ec; 478e1051a39Sopenharmony_ci if (pre_comp && pre_comp->numblocks 479e1051a39Sopenharmony_ci && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == 480e1051a39Sopenharmony_ci 0)) { 481e1051a39Sopenharmony_ci blocksize = pre_comp->blocksize; 482e1051a39Sopenharmony_ci 483e1051a39Sopenharmony_ci /* 484e1051a39Sopenharmony_ci * determine maximum number of blocks that wNAF splitting may 485e1051a39Sopenharmony_ci * yield (NB: maximum wNAF length is bit length plus one) 486e1051a39Sopenharmony_ci */ 487e1051a39Sopenharmony_ci numblocks = (BN_num_bits(scalar) / blocksize) + 1; 488e1051a39Sopenharmony_ci 489e1051a39Sopenharmony_ci /* 490e1051a39Sopenharmony_ci * we cannot use more blocks than we have precomputation for 491e1051a39Sopenharmony_ci */ 492e1051a39Sopenharmony_ci if (numblocks > pre_comp->numblocks) 493e1051a39Sopenharmony_ci numblocks = pre_comp->numblocks; 494e1051a39Sopenharmony_ci 495e1051a39Sopenharmony_ci pre_points_per_block = (size_t)1 << (pre_comp->w - 1); 496e1051a39Sopenharmony_ci 497e1051a39Sopenharmony_ci /* check that pre_comp looks sane */ 498e1051a39Sopenharmony_ci if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) { 499e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 500e1051a39Sopenharmony_ci goto err; 501e1051a39Sopenharmony_ci } 502e1051a39Sopenharmony_ci } else { 503e1051a39Sopenharmony_ci /* can't use precomputation */ 504e1051a39Sopenharmony_ci pre_comp = NULL; 505e1051a39Sopenharmony_ci numblocks = 1; 506e1051a39Sopenharmony_ci num_scalar = 1; /* treat 'scalar' like 'num'-th element of 507e1051a39Sopenharmony_ci * 'scalars' */ 508e1051a39Sopenharmony_ci } 509e1051a39Sopenharmony_ci } 510e1051a39Sopenharmony_ci 511e1051a39Sopenharmony_ci totalnum = num + numblocks; 512e1051a39Sopenharmony_ci 513e1051a39Sopenharmony_ci wsize = OPENSSL_malloc(totalnum * sizeof(wsize[0])); 514e1051a39Sopenharmony_ci wNAF_len = OPENSSL_malloc(totalnum * sizeof(wNAF_len[0])); 515e1051a39Sopenharmony_ci /* include space for pivot */ 516e1051a39Sopenharmony_ci wNAF = OPENSSL_malloc((totalnum + 1) * sizeof(wNAF[0])); 517e1051a39Sopenharmony_ci val_sub = OPENSSL_malloc(totalnum * sizeof(val_sub[0])); 518e1051a39Sopenharmony_ci 519e1051a39Sopenharmony_ci /* Ensure wNAF is initialised in case we end up going to err */ 520e1051a39Sopenharmony_ci if (wNAF != NULL) 521e1051a39Sopenharmony_ci wNAF[0] = NULL; /* preliminary pivot */ 522e1051a39Sopenharmony_ci 523e1051a39Sopenharmony_ci if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) { 524e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 525e1051a39Sopenharmony_ci goto err; 526e1051a39Sopenharmony_ci } 527e1051a39Sopenharmony_ci 528e1051a39Sopenharmony_ci /* 529e1051a39Sopenharmony_ci * num_val will be the total number of temporarily precomputed points 530e1051a39Sopenharmony_ci */ 531e1051a39Sopenharmony_ci num_val = 0; 532e1051a39Sopenharmony_ci 533e1051a39Sopenharmony_ci for (i = 0; i < num + num_scalar; i++) { 534e1051a39Sopenharmony_ci size_t bits; 535e1051a39Sopenharmony_ci 536e1051a39Sopenharmony_ci bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar); 537e1051a39Sopenharmony_ci wsize[i] = EC_window_bits_for_scalar_size(bits); 538e1051a39Sopenharmony_ci num_val += (size_t)1 << (wsize[i] - 1); 539e1051a39Sopenharmony_ci wNAF[i + 1] = NULL; /* make sure we always have a pivot */ 540e1051a39Sopenharmony_ci wNAF[i] = 541e1051a39Sopenharmony_ci bn_compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], 542e1051a39Sopenharmony_ci &wNAF_len[i]); 543e1051a39Sopenharmony_ci if (wNAF[i] == NULL) 544e1051a39Sopenharmony_ci goto err; 545e1051a39Sopenharmony_ci if (wNAF_len[i] > max_len) 546e1051a39Sopenharmony_ci max_len = wNAF_len[i]; 547e1051a39Sopenharmony_ci } 548e1051a39Sopenharmony_ci 549e1051a39Sopenharmony_ci if (numblocks) { 550e1051a39Sopenharmony_ci /* we go here iff scalar != NULL */ 551e1051a39Sopenharmony_ci 552e1051a39Sopenharmony_ci if (pre_comp == NULL) { 553e1051a39Sopenharmony_ci if (num_scalar != 1) { 554e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 555e1051a39Sopenharmony_ci goto err; 556e1051a39Sopenharmony_ci } 557e1051a39Sopenharmony_ci /* we have already generated a wNAF for 'scalar' */ 558e1051a39Sopenharmony_ci } else { 559e1051a39Sopenharmony_ci signed char *tmp_wNAF = NULL; 560e1051a39Sopenharmony_ci size_t tmp_len = 0; 561e1051a39Sopenharmony_ci 562e1051a39Sopenharmony_ci if (num_scalar != 0) { 563e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 564e1051a39Sopenharmony_ci goto err; 565e1051a39Sopenharmony_ci } 566e1051a39Sopenharmony_ci 567e1051a39Sopenharmony_ci /* 568e1051a39Sopenharmony_ci * use the window size for which we have precomputation 569e1051a39Sopenharmony_ci */ 570e1051a39Sopenharmony_ci wsize[num] = pre_comp->w; 571e1051a39Sopenharmony_ci tmp_wNAF = bn_compute_wNAF(scalar, wsize[num], &tmp_len); 572e1051a39Sopenharmony_ci if (!tmp_wNAF) 573e1051a39Sopenharmony_ci goto err; 574e1051a39Sopenharmony_ci 575e1051a39Sopenharmony_ci if (tmp_len <= max_len) { 576e1051a39Sopenharmony_ci /* 577e1051a39Sopenharmony_ci * One of the other wNAFs is at least as long as the wNAF 578e1051a39Sopenharmony_ci * belonging to the generator, so wNAF splitting will not buy 579e1051a39Sopenharmony_ci * us anything. 580e1051a39Sopenharmony_ci */ 581e1051a39Sopenharmony_ci 582e1051a39Sopenharmony_ci numblocks = 1; 583e1051a39Sopenharmony_ci totalnum = num + 1; /* don't use wNAF splitting */ 584e1051a39Sopenharmony_ci wNAF[num] = tmp_wNAF; 585e1051a39Sopenharmony_ci wNAF[num + 1] = NULL; 586e1051a39Sopenharmony_ci wNAF_len[num] = tmp_len; 587e1051a39Sopenharmony_ci /* 588e1051a39Sopenharmony_ci * pre_comp->points starts with the points that we need here: 589e1051a39Sopenharmony_ci */ 590e1051a39Sopenharmony_ci val_sub[num] = pre_comp->points; 591e1051a39Sopenharmony_ci } else { 592e1051a39Sopenharmony_ci /* 593e1051a39Sopenharmony_ci * don't include tmp_wNAF directly into wNAF array - use wNAF 594e1051a39Sopenharmony_ci * splitting and include the blocks 595e1051a39Sopenharmony_ci */ 596e1051a39Sopenharmony_ci 597e1051a39Sopenharmony_ci signed char *pp; 598e1051a39Sopenharmony_ci EC_POINT **tmp_points; 599e1051a39Sopenharmony_ci 600e1051a39Sopenharmony_ci if (tmp_len < numblocks * blocksize) { 601e1051a39Sopenharmony_ci /* 602e1051a39Sopenharmony_ci * possibly we can do with fewer blocks than estimated 603e1051a39Sopenharmony_ci */ 604e1051a39Sopenharmony_ci numblocks = (tmp_len + blocksize - 1) / blocksize; 605e1051a39Sopenharmony_ci if (numblocks > pre_comp->numblocks) { 606e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 607e1051a39Sopenharmony_ci OPENSSL_free(tmp_wNAF); 608e1051a39Sopenharmony_ci goto err; 609e1051a39Sopenharmony_ci } 610e1051a39Sopenharmony_ci totalnum = num + numblocks; 611e1051a39Sopenharmony_ci } 612e1051a39Sopenharmony_ci 613e1051a39Sopenharmony_ci /* split wNAF in 'numblocks' parts */ 614e1051a39Sopenharmony_ci pp = tmp_wNAF; 615e1051a39Sopenharmony_ci tmp_points = pre_comp->points; 616e1051a39Sopenharmony_ci 617e1051a39Sopenharmony_ci for (i = num; i < totalnum; i++) { 618e1051a39Sopenharmony_ci if (i < totalnum - 1) { 619e1051a39Sopenharmony_ci wNAF_len[i] = blocksize; 620e1051a39Sopenharmony_ci if (tmp_len < blocksize) { 621e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 622e1051a39Sopenharmony_ci OPENSSL_free(tmp_wNAF); 623e1051a39Sopenharmony_ci goto err; 624e1051a39Sopenharmony_ci } 625e1051a39Sopenharmony_ci tmp_len -= blocksize; 626e1051a39Sopenharmony_ci } else 627e1051a39Sopenharmony_ci /* 628e1051a39Sopenharmony_ci * last block gets whatever is left (this could be 629e1051a39Sopenharmony_ci * more or less than 'blocksize'!) 630e1051a39Sopenharmony_ci */ 631e1051a39Sopenharmony_ci wNAF_len[i] = tmp_len; 632e1051a39Sopenharmony_ci 633e1051a39Sopenharmony_ci wNAF[i + 1] = NULL; 634e1051a39Sopenharmony_ci wNAF[i] = OPENSSL_malloc(wNAF_len[i]); 635e1051a39Sopenharmony_ci if (wNAF[i] == NULL) { 636e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 637e1051a39Sopenharmony_ci OPENSSL_free(tmp_wNAF); 638e1051a39Sopenharmony_ci goto err; 639e1051a39Sopenharmony_ci } 640e1051a39Sopenharmony_ci memcpy(wNAF[i], pp, wNAF_len[i]); 641e1051a39Sopenharmony_ci if (wNAF_len[i] > max_len) 642e1051a39Sopenharmony_ci max_len = wNAF_len[i]; 643e1051a39Sopenharmony_ci 644e1051a39Sopenharmony_ci if (*tmp_points == NULL) { 645e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 646e1051a39Sopenharmony_ci OPENSSL_free(tmp_wNAF); 647e1051a39Sopenharmony_ci goto err; 648e1051a39Sopenharmony_ci } 649e1051a39Sopenharmony_ci val_sub[i] = tmp_points; 650e1051a39Sopenharmony_ci tmp_points += pre_points_per_block; 651e1051a39Sopenharmony_ci pp += blocksize; 652e1051a39Sopenharmony_ci } 653e1051a39Sopenharmony_ci OPENSSL_free(tmp_wNAF); 654e1051a39Sopenharmony_ci } 655e1051a39Sopenharmony_ci } 656e1051a39Sopenharmony_ci } 657e1051a39Sopenharmony_ci 658e1051a39Sopenharmony_ci /* 659e1051a39Sopenharmony_ci * All points we precompute now go into a single array 'val'. 660e1051a39Sopenharmony_ci * 'val_sub[i]' is a pointer to the subarray for the i-th point, or to a 661e1051a39Sopenharmony_ci * subarray of 'pre_comp->points' if we already have precomputation. 662e1051a39Sopenharmony_ci */ 663e1051a39Sopenharmony_ci val = OPENSSL_malloc((num_val + 1) * sizeof(val[0])); 664e1051a39Sopenharmony_ci if (val == NULL) { 665e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 666e1051a39Sopenharmony_ci goto err; 667e1051a39Sopenharmony_ci } 668e1051a39Sopenharmony_ci val[num_val] = NULL; /* pivot element */ 669e1051a39Sopenharmony_ci 670e1051a39Sopenharmony_ci /* allocate points for precomputation */ 671e1051a39Sopenharmony_ci v = val; 672e1051a39Sopenharmony_ci for (i = 0; i < num + num_scalar; i++) { 673e1051a39Sopenharmony_ci val_sub[i] = v; 674e1051a39Sopenharmony_ci for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) { 675e1051a39Sopenharmony_ci *v = EC_POINT_new(group); 676e1051a39Sopenharmony_ci if (*v == NULL) 677e1051a39Sopenharmony_ci goto err; 678e1051a39Sopenharmony_ci v++; 679e1051a39Sopenharmony_ci } 680e1051a39Sopenharmony_ci } 681e1051a39Sopenharmony_ci if (!(v == val + num_val)) { 682e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 683e1051a39Sopenharmony_ci goto err; 684e1051a39Sopenharmony_ci } 685e1051a39Sopenharmony_ci 686e1051a39Sopenharmony_ci if ((tmp = EC_POINT_new(group)) == NULL) 687e1051a39Sopenharmony_ci goto err; 688e1051a39Sopenharmony_ci 689e1051a39Sopenharmony_ci /*- 690e1051a39Sopenharmony_ci * prepare precomputed values: 691e1051a39Sopenharmony_ci * val_sub[i][0] := points[i] 692e1051a39Sopenharmony_ci * val_sub[i][1] := 3 * points[i] 693e1051a39Sopenharmony_ci * val_sub[i][2] := 5 * points[i] 694e1051a39Sopenharmony_ci * ... 695e1051a39Sopenharmony_ci */ 696e1051a39Sopenharmony_ci for (i = 0; i < num + num_scalar; i++) { 697e1051a39Sopenharmony_ci if (i < num) { 698e1051a39Sopenharmony_ci if (!EC_POINT_copy(val_sub[i][0], points[i])) 699e1051a39Sopenharmony_ci goto err; 700e1051a39Sopenharmony_ci } else { 701e1051a39Sopenharmony_ci if (!EC_POINT_copy(val_sub[i][0], generator)) 702e1051a39Sopenharmony_ci goto err; 703e1051a39Sopenharmony_ci } 704e1051a39Sopenharmony_ci 705e1051a39Sopenharmony_ci if (wsize[i] > 1) { 706e1051a39Sopenharmony_ci if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) 707e1051a39Sopenharmony_ci goto err; 708e1051a39Sopenharmony_ci for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) { 709e1051a39Sopenharmony_ci if (!EC_POINT_add 710e1051a39Sopenharmony_ci (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) 711e1051a39Sopenharmony_ci goto err; 712e1051a39Sopenharmony_ci } 713e1051a39Sopenharmony_ci } 714e1051a39Sopenharmony_ci } 715e1051a39Sopenharmony_ci 716e1051a39Sopenharmony_ci if (group->meth->points_make_affine == NULL 717e1051a39Sopenharmony_ci || !group->meth->points_make_affine(group, num_val, val, ctx)) 718e1051a39Sopenharmony_ci goto err; 719e1051a39Sopenharmony_ci 720e1051a39Sopenharmony_ci r_is_at_infinity = 1; 721e1051a39Sopenharmony_ci 722e1051a39Sopenharmony_ci for (k = max_len - 1; k >= 0; k--) { 723e1051a39Sopenharmony_ci if (!r_is_at_infinity) { 724e1051a39Sopenharmony_ci if (!EC_POINT_dbl(group, r, r, ctx)) 725e1051a39Sopenharmony_ci goto err; 726e1051a39Sopenharmony_ci } 727e1051a39Sopenharmony_ci 728e1051a39Sopenharmony_ci for (i = 0; i < totalnum; i++) { 729e1051a39Sopenharmony_ci if (wNAF_len[i] > (size_t)k) { 730e1051a39Sopenharmony_ci int digit = wNAF[i][k]; 731e1051a39Sopenharmony_ci int is_neg; 732e1051a39Sopenharmony_ci 733e1051a39Sopenharmony_ci if (digit) { 734e1051a39Sopenharmony_ci is_neg = digit < 0; 735e1051a39Sopenharmony_ci 736e1051a39Sopenharmony_ci if (is_neg) 737e1051a39Sopenharmony_ci digit = -digit; 738e1051a39Sopenharmony_ci 739e1051a39Sopenharmony_ci if (is_neg != r_is_inverted) { 740e1051a39Sopenharmony_ci if (!r_is_at_infinity) { 741e1051a39Sopenharmony_ci if (!EC_POINT_invert(group, r, ctx)) 742e1051a39Sopenharmony_ci goto err; 743e1051a39Sopenharmony_ci } 744e1051a39Sopenharmony_ci r_is_inverted = !r_is_inverted; 745e1051a39Sopenharmony_ci } 746e1051a39Sopenharmony_ci 747e1051a39Sopenharmony_ci /* digit > 0 */ 748e1051a39Sopenharmony_ci 749e1051a39Sopenharmony_ci if (r_is_at_infinity) { 750e1051a39Sopenharmony_ci if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) 751e1051a39Sopenharmony_ci goto err; 752e1051a39Sopenharmony_ci 753e1051a39Sopenharmony_ci /*- 754e1051a39Sopenharmony_ci * Apply coordinate blinding for EC_POINT. 755e1051a39Sopenharmony_ci * 756e1051a39Sopenharmony_ci * The underlying EC_METHOD can optionally implement this function: 757e1051a39Sopenharmony_ci * ossl_ec_point_blind_coordinates() returns 0 in case of errors or 1 on 758e1051a39Sopenharmony_ci * success or if coordinate blinding is not implemented for this 759e1051a39Sopenharmony_ci * group. 760e1051a39Sopenharmony_ci */ 761e1051a39Sopenharmony_ci if (!ossl_ec_point_blind_coordinates(group, r, ctx)) { 762e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_POINT_COORDINATES_BLIND_FAILURE); 763e1051a39Sopenharmony_ci goto err; 764e1051a39Sopenharmony_ci } 765e1051a39Sopenharmony_ci 766e1051a39Sopenharmony_ci r_is_at_infinity = 0; 767e1051a39Sopenharmony_ci } else { 768e1051a39Sopenharmony_ci if (!EC_POINT_add 769e1051a39Sopenharmony_ci (group, r, r, val_sub[i][digit >> 1], ctx)) 770e1051a39Sopenharmony_ci goto err; 771e1051a39Sopenharmony_ci } 772e1051a39Sopenharmony_ci } 773e1051a39Sopenharmony_ci } 774e1051a39Sopenharmony_ci } 775e1051a39Sopenharmony_ci } 776e1051a39Sopenharmony_ci 777e1051a39Sopenharmony_ci if (r_is_at_infinity) { 778e1051a39Sopenharmony_ci if (!EC_POINT_set_to_infinity(group, r)) 779e1051a39Sopenharmony_ci goto err; 780e1051a39Sopenharmony_ci } else { 781e1051a39Sopenharmony_ci if (r_is_inverted) 782e1051a39Sopenharmony_ci if (!EC_POINT_invert(group, r, ctx)) 783e1051a39Sopenharmony_ci goto err; 784e1051a39Sopenharmony_ci } 785e1051a39Sopenharmony_ci 786e1051a39Sopenharmony_ci ret = 1; 787e1051a39Sopenharmony_ci 788e1051a39Sopenharmony_ci err: 789e1051a39Sopenharmony_ci EC_POINT_free(tmp); 790e1051a39Sopenharmony_ci OPENSSL_free(wsize); 791e1051a39Sopenharmony_ci OPENSSL_free(wNAF_len); 792e1051a39Sopenharmony_ci if (wNAF != NULL) { 793e1051a39Sopenharmony_ci signed char **w; 794e1051a39Sopenharmony_ci 795e1051a39Sopenharmony_ci for (w = wNAF; *w != NULL; w++) 796e1051a39Sopenharmony_ci OPENSSL_free(*w); 797e1051a39Sopenharmony_ci 798e1051a39Sopenharmony_ci OPENSSL_free(wNAF); 799e1051a39Sopenharmony_ci } 800e1051a39Sopenharmony_ci if (val != NULL) { 801e1051a39Sopenharmony_ci for (v = val; *v != NULL; v++) 802e1051a39Sopenharmony_ci EC_POINT_clear_free(*v); 803e1051a39Sopenharmony_ci 804e1051a39Sopenharmony_ci OPENSSL_free(val); 805e1051a39Sopenharmony_ci } 806e1051a39Sopenharmony_ci OPENSSL_free(val_sub); 807e1051a39Sopenharmony_ci return ret; 808e1051a39Sopenharmony_ci} 809e1051a39Sopenharmony_ci 810e1051a39Sopenharmony_ci/*- 811e1051a39Sopenharmony_ci * ossl_ec_wNAF_precompute_mult() 812e1051a39Sopenharmony_ci * creates an EC_PRE_COMP object with preprecomputed multiples of the generator 813e1051a39Sopenharmony_ci * for use with wNAF splitting as implemented in ossl_ec_wNAF_mul(). 814e1051a39Sopenharmony_ci * 815e1051a39Sopenharmony_ci * 'pre_comp->points' is an array of multiples of the generator 816e1051a39Sopenharmony_ci * of the following form: 817e1051a39Sopenharmony_ci * points[0] = generator; 818e1051a39Sopenharmony_ci * points[1] = 3 * generator; 819e1051a39Sopenharmony_ci * ... 820e1051a39Sopenharmony_ci * points[2^(w-1)-1] = (2^(w-1)-1) * generator; 821e1051a39Sopenharmony_ci * points[2^(w-1)] = 2^blocksize * generator; 822e1051a39Sopenharmony_ci * points[2^(w-1)+1] = 3 * 2^blocksize * generator; 823e1051a39Sopenharmony_ci * ... 824e1051a39Sopenharmony_ci * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) * generator 825e1051a39Sopenharmony_ci * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) * generator 826e1051a39Sopenharmony_ci * ... 827e1051a39Sopenharmony_ci * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator 828e1051a39Sopenharmony_ci * points[2^(w-1)*numblocks] = NULL 829e1051a39Sopenharmony_ci */ 830e1051a39Sopenharmony_ciint ossl_ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 831e1051a39Sopenharmony_ci{ 832e1051a39Sopenharmony_ci const EC_POINT *generator; 833e1051a39Sopenharmony_ci EC_POINT *tmp_point = NULL, *base = NULL, **var; 834e1051a39Sopenharmony_ci const BIGNUM *order; 835e1051a39Sopenharmony_ci size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num; 836e1051a39Sopenharmony_ci EC_POINT **points = NULL; 837e1051a39Sopenharmony_ci EC_PRE_COMP *pre_comp; 838e1051a39Sopenharmony_ci int ret = 0; 839e1051a39Sopenharmony_ci int used_ctx = 0; 840e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 841e1051a39Sopenharmony_ci BN_CTX *new_ctx = NULL; 842e1051a39Sopenharmony_ci#endif 843e1051a39Sopenharmony_ci 844e1051a39Sopenharmony_ci /* if there is an old EC_PRE_COMP object, throw it away */ 845e1051a39Sopenharmony_ci EC_pre_comp_free(group); 846e1051a39Sopenharmony_ci if ((pre_comp = ec_pre_comp_new(group)) == NULL) 847e1051a39Sopenharmony_ci return 0; 848e1051a39Sopenharmony_ci 849e1051a39Sopenharmony_ci generator = EC_GROUP_get0_generator(group); 850e1051a39Sopenharmony_ci if (generator == NULL) { 851e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_UNDEFINED_GENERATOR); 852e1051a39Sopenharmony_ci goto err; 853e1051a39Sopenharmony_ci } 854e1051a39Sopenharmony_ci 855e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 856e1051a39Sopenharmony_ci if (ctx == NULL) 857e1051a39Sopenharmony_ci ctx = new_ctx = BN_CTX_new(); 858e1051a39Sopenharmony_ci#endif 859e1051a39Sopenharmony_ci if (ctx == NULL) 860e1051a39Sopenharmony_ci goto err; 861e1051a39Sopenharmony_ci 862e1051a39Sopenharmony_ci BN_CTX_start(ctx); 863e1051a39Sopenharmony_ci used_ctx = 1; 864e1051a39Sopenharmony_ci 865e1051a39Sopenharmony_ci order = EC_GROUP_get0_order(group); 866e1051a39Sopenharmony_ci if (order == NULL) 867e1051a39Sopenharmony_ci goto err; 868e1051a39Sopenharmony_ci if (BN_is_zero(order)) { 869e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_ORDER); 870e1051a39Sopenharmony_ci goto err; 871e1051a39Sopenharmony_ci } 872e1051a39Sopenharmony_ci 873e1051a39Sopenharmony_ci bits = BN_num_bits(order); 874e1051a39Sopenharmony_ci /* 875e1051a39Sopenharmony_ci * The following parameters mean we precompute (approximately) one point 876e1051a39Sopenharmony_ci * per bit. TBD: The combination 8, 4 is perfect for 160 bits; for other 877e1051a39Sopenharmony_ci * bit lengths, other parameter combinations might provide better 878e1051a39Sopenharmony_ci * efficiency. 879e1051a39Sopenharmony_ci */ 880e1051a39Sopenharmony_ci blocksize = 8; 881e1051a39Sopenharmony_ci w = 4; 882e1051a39Sopenharmony_ci if (EC_window_bits_for_scalar_size(bits) > w) { 883e1051a39Sopenharmony_ci /* let's not make the window too small ... */ 884e1051a39Sopenharmony_ci w = EC_window_bits_for_scalar_size(bits); 885e1051a39Sopenharmony_ci } 886e1051a39Sopenharmony_ci 887e1051a39Sopenharmony_ci numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks 888e1051a39Sopenharmony_ci * to use for wNAF 889e1051a39Sopenharmony_ci * splitting */ 890e1051a39Sopenharmony_ci 891e1051a39Sopenharmony_ci pre_points_per_block = (size_t)1 << (w - 1); 892e1051a39Sopenharmony_ci num = pre_points_per_block * numblocks; /* number of points to compute 893e1051a39Sopenharmony_ci * and store */ 894e1051a39Sopenharmony_ci 895e1051a39Sopenharmony_ci points = OPENSSL_malloc(sizeof(*points) * (num + 1)); 896e1051a39Sopenharmony_ci if (points == NULL) { 897e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 898e1051a39Sopenharmony_ci goto err; 899e1051a39Sopenharmony_ci } 900e1051a39Sopenharmony_ci 901e1051a39Sopenharmony_ci var = points; 902e1051a39Sopenharmony_ci var[num] = NULL; /* pivot */ 903e1051a39Sopenharmony_ci for (i = 0; i < num; i++) { 904e1051a39Sopenharmony_ci if ((var[i] = EC_POINT_new(group)) == NULL) { 905e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 906e1051a39Sopenharmony_ci goto err; 907e1051a39Sopenharmony_ci } 908e1051a39Sopenharmony_ci } 909e1051a39Sopenharmony_ci 910e1051a39Sopenharmony_ci if ((tmp_point = EC_POINT_new(group)) == NULL 911e1051a39Sopenharmony_ci || (base = EC_POINT_new(group)) == NULL) { 912e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 913e1051a39Sopenharmony_ci goto err; 914e1051a39Sopenharmony_ci } 915e1051a39Sopenharmony_ci 916e1051a39Sopenharmony_ci if (!EC_POINT_copy(base, generator)) 917e1051a39Sopenharmony_ci goto err; 918e1051a39Sopenharmony_ci 919e1051a39Sopenharmony_ci /* do the precomputation */ 920e1051a39Sopenharmony_ci for (i = 0; i < numblocks; i++) { 921e1051a39Sopenharmony_ci size_t j; 922e1051a39Sopenharmony_ci 923e1051a39Sopenharmony_ci if (!EC_POINT_dbl(group, tmp_point, base, ctx)) 924e1051a39Sopenharmony_ci goto err; 925e1051a39Sopenharmony_ci 926e1051a39Sopenharmony_ci if (!EC_POINT_copy(*var++, base)) 927e1051a39Sopenharmony_ci goto err; 928e1051a39Sopenharmony_ci 929e1051a39Sopenharmony_ci for (j = 1; j < pre_points_per_block; j++, var++) { 930e1051a39Sopenharmony_ci /* 931e1051a39Sopenharmony_ci * calculate odd multiples of the current base point 932e1051a39Sopenharmony_ci */ 933e1051a39Sopenharmony_ci if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx)) 934e1051a39Sopenharmony_ci goto err; 935e1051a39Sopenharmony_ci } 936e1051a39Sopenharmony_ci 937e1051a39Sopenharmony_ci if (i < numblocks - 1) { 938e1051a39Sopenharmony_ci /* 939e1051a39Sopenharmony_ci * get the next base (multiply current one by 2^blocksize) 940e1051a39Sopenharmony_ci */ 941e1051a39Sopenharmony_ci size_t k; 942e1051a39Sopenharmony_ci 943e1051a39Sopenharmony_ci if (blocksize <= 2) { 944e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 945e1051a39Sopenharmony_ci goto err; 946e1051a39Sopenharmony_ci } 947e1051a39Sopenharmony_ci 948e1051a39Sopenharmony_ci if (!EC_POINT_dbl(group, base, tmp_point, ctx)) 949e1051a39Sopenharmony_ci goto err; 950e1051a39Sopenharmony_ci for (k = 2; k < blocksize; k++) { 951e1051a39Sopenharmony_ci if (!EC_POINT_dbl(group, base, base, ctx)) 952e1051a39Sopenharmony_ci goto err; 953e1051a39Sopenharmony_ci } 954e1051a39Sopenharmony_ci } 955e1051a39Sopenharmony_ci } 956e1051a39Sopenharmony_ci 957e1051a39Sopenharmony_ci if (group->meth->points_make_affine == NULL 958e1051a39Sopenharmony_ci || !group->meth->points_make_affine(group, num, points, ctx)) 959e1051a39Sopenharmony_ci goto err; 960e1051a39Sopenharmony_ci 961e1051a39Sopenharmony_ci pre_comp->group = group; 962e1051a39Sopenharmony_ci pre_comp->blocksize = blocksize; 963e1051a39Sopenharmony_ci pre_comp->numblocks = numblocks; 964e1051a39Sopenharmony_ci pre_comp->w = w; 965e1051a39Sopenharmony_ci pre_comp->points = points; 966e1051a39Sopenharmony_ci points = NULL; 967e1051a39Sopenharmony_ci pre_comp->num = num; 968e1051a39Sopenharmony_ci SETPRECOMP(group, ec, pre_comp); 969e1051a39Sopenharmony_ci pre_comp = NULL; 970e1051a39Sopenharmony_ci ret = 1; 971e1051a39Sopenharmony_ci 972e1051a39Sopenharmony_ci err: 973e1051a39Sopenharmony_ci if (used_ctx) 974e1051a39Sopenharmony_ci BN_CTX_end(ctx); 975e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 976e1051a39Sopenharmony_ci BN_CTX_free(new_ctx); 977e1051a39Sopenharmony_ci#endif 978e1051a39Sopenharmony_ci EC_ec_pre_comp_free(pre_comp); 979e1051a39Sopenharmony_ci if (points) { 980e1051a39Sopenharmony_ci EC_POINT **p; 981e1051a39Sopenharmony_ci 982e1051a39Sopenharmony_ci for (p = points; *p != NULL; p++) 983e1051a39Sopenharmony_ci EC_POINT_free(*p); 984e1051a39Sopenharmony_ci OPENSSL_free(points); 985e1051a39Sopenharmony_ci } 986e1051a39Sopenharmony_ci EC_POINT_free(tmp_point); 987e1051a39Sopenharmony_ci EC_POINT_free(base); 988e1051a39Sopenharmony_ci return ret; 989e1051a39Sopenharmony_ci} 990e1051a39Sopenharmony_ci 991e1051a39Sopenharmony_ciint ossl_ec_wNAF_have_precompute_mult(const EC_GROUP *group) 992e1051a39Sopenharmony_ci{ 993e1051a39Sopenharmony_ci return HAVEPRECOMP(group, ec); 994e1051a39Sopenharmony_ci} 995