1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Originally written by Bodo Moeller for the OpenSSL project. 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ==================================================================== 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met: 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer. 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer in 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the documentation and/or other materials provided with the 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * distribution. 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * software must display the following acknowledgment: 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * endorse or promote products derived from this software without 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * prior written permission. For written permission, please contact 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * openssl-core@openssl.org. 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL" 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * nor may "OpenSSL" appear in their names without prior written 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * permission of the OpenSSL Project. 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * acknowledgment: 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ==================================================================== 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com). This product includes software written by Tim 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ==================================================================== 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Portions of the attached software ("Contribution") are developed by 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The Contribution is licensed pursuant to the OpenSSL open source 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * license provided above. 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The elliptic curve binary polynomial software is originally written by 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Laboratories. */ 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ec.h> 69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bn.h> 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h> 75e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/thread.h> 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h" 78f4e427204234da139fd0585def4b4e22502e33f0Adam Langley#include "../internal.h" 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* This file implements the wNAF-based interleaving multi-exponentation method 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>); 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * */ 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This is an array r[] of values that are either zero or odd with an 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * absolute value less than 2^w satisfying 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * scalar = \sum_j r[j]*2^j 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * where at most one of any w+1 consecutive digits is non-zero 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * with the exception that the most significant digit may be only 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * w-1 zeros away from that next non-zero digit. 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) { 94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int window_val; 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ok = 0; 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley signed char *r = NULL; 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int sign = 1; 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int bit, next_bit, mask; 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t len = 0, j; 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(scalar)) { 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r = OPENSSL_malloc(1); 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!r) { 104b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r[0] = 0; 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *ret_len = 1; 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return r; 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley values less than 2^7 */ 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 115b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley bit = 1 << w; /* at most 128 */ 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley next_bit = bit << 1; /* at most 256 */ 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley mask = next_bit - 1; /* at most 255 */ 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_negative(scalar)) { 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sign = -1; 124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (scalar->d == NULL || scalar->top == 0) { 127b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len = BN_num_bits(scalar); 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r = OPENSSL_malloc( 133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len + 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 1); /* modified wNAF may be one digit longer than binary representation 135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (*ret_len will be set to the actual length, i.e. at most 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * BN_num_bits(scalar) + 1) */ 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (r == NULL) { 138b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley window_val = scalar->d[0] & mask; 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley j = 0; 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley while ((window_val != 0) || 144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */ 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int digit = 0; 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* 0 <= window_val <= 2^(w+1) */ 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (window_val & 1) { 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* 0 < window_val < 2^(w+1) */ 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (window_val & bit) { 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley digit = window_val - next_bit; /* -2^w < digit < 0 */ 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if 1 /* modified wNAF */ 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (j + w + 1 >= len) { 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* special case for generating modified wNAFs: 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * no new bits will be added into window_val, 160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * so using a positive digit here will decrease 161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the total length of the representation */ 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley digit = window_val & (mask >> 1); /* 0 < digit < 2^w */ 164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif 166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley digit = window_val; /* 0 < digit < 2^w */ 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (digit <= -bit || digit >= bit || !(digit & 1)) { 171b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley window_val -= digit; 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* now window_val is 0 or 2^(w+1) in standard wNAF generation; 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for modified window NAFs, it may also be 2^w 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (window_val != 0 && window_val != next_bit && window_val != bit) { 181b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r[j++] = sign * digit; 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley window_val >>= 1; 189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley window_val += bit * BN_is_bit_set(scalar, j + w); 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (window_val > next_bit) { 192b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (j > len + 1) { 198b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley len = j; 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ok = 1; 203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 204d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!ok) { 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(r); 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r = NULL; 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 209e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ok) { 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *ret_len = len; 211e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return r; 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* TODO: table should be optimised for the wNAF-based implementation, 217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * sometimes smaller windows will give better performance 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (thus the boundaries should be increased) 219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#define EC_window_bits_for_scalar_size(b) \ 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ((size_t)((b) >= 2000 ? 6 : (b) >= 800 ? 5 : (b) >= 300 \ 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ? 4 \ 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley : (b) >= 70 ? 3 : (b) >= 20 \ 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ? 2 \ 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley : 1)) 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2274139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, 2284139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) { 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *new_ctx = NULL; 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_POINT *generator = NULL; 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT *tmp = NULL; 2324139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley size_t total_num; 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t i, j; 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int k; 235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int r_is_inverted = 0; 236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int r_is_at_infinity = 1; 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t *wsize = NULL; /* individual window sizes */ 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley signed char **wNAF = NULL; /* individual wNAFs */ 239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t *wNAF_len = NULL; 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t max_len = 0; 241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t num_val; 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT **val = NULL; /* precomputation */ 243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT **v; 2444139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' */ 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx == NULL) { 248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx = new_ctx = BN_CTX_new(); 249e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ctx == NULL) { 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 251e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2544139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley /* TODO: This function used to take |points| and |scalars| as arrays of 2554139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley * |num| elements. The code below should be simplified to work in terms of |p| 2564139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley * and |p_scalar|. */ 2574139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley size_t num = p != NULL ? 1 : 0; 2584139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley const EC_POINT **points = p != NULL ? &p : NULL; 2594139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley const BIGNUM **scalars = p != NULL ? &p_scalar : NULL; 2604139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley 2614139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley total_num = num; 2624139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley 2634139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if (g_scalar != NULL) { 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley generator = EC_GROUP_get0_generator(group); 265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (generator == NULL) { 266b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_UNDEFINED_GENERATOR); 267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2704139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley ++total_num; /* treat 'g_scalar' like 'num'-th element of 'scalars' */ 271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2744139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley wsize = OPENSSL_malloc(total_num * sizeof wsize[0]); 2754139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley wNAF_len = OPENSSL_malloc(total_num * sizeof wNAF_len[0]); 2764139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley wNAF = OPENSSL_malloc((total_num + 1) * 277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sizeof wNAF[0]); /* includes space for pivot */ 2784139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley val_sub = OPENSSL_malloc(total_num * sizeof val_sub[0]); 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Ensure wNAF is initialised in case we end up going to err. */ 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (wNAF) { 282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley wNAF[0] = NULL; /* preliminary pivot */ 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!wsize || !wNAF_len || !wNAF || !val_sub) { 286b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* num_val will be the total number of temporarily precomputed points */ 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley num_val = 0; 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2934139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley for (i = 0; i < total_num; i++) { 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t bits; 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 2964139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(g_scalar); 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley wsize[i] = EC_window_bits_for_scalar_size(bits); 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley num_val += (size_t)1 << (wsize[i] - 1); 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley wNAF[i + 1] = NULL; /* make sure we always have a pivot */ 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley wNAF[i] = 3014139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley compute_wNAF((i < num ? scalars[i] : g_scalar), wsize[i], &wNAF_len[i]); 302e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (wNAF[i] == NULL) { 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 304e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 305e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (wNAF_len[i] > max_len) { 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley max_len = wNAF_len[i]; 307e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 3104139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley /* All points we precompute now go into a single array 'val'. 'val_sub[i]' is 3114139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley * a pointer to the subarray for the i-th point. */ 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley val = OPENSSL_malloc((num_val + 1) * sizeof val[0]); 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (val == NULL) { 314b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley val[num_val] = NULL; /* pivot element */ 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* allocate points for precomputation */ 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley v = val; 3214139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley for (i = 0; i < total_num; i++) { 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley val_sub[i] = v; 323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) { 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *v = EC_POINT_new(group); 325e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (*v == NULL) { 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 327e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley v++; 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!(v == val + num_val)) { 332b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 336e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!(tmp = EC_POINT_new(group))) { 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 338e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* prepare precomputed values: 341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * val_sub[i][0] := points[i] 342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * val_sub[i][1] := 3 * points[i] 343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * val_sub[i][2] := 5 * points[i] 344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ... 345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 3464139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley for (i = 0; i < total_num; i++) { 347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (i < num) { 348e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_copy(val_sub[i][0], points[i])) { 349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 350e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 351e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } else if (!EC_POINT_copy(val_sub[i][0], generator)) { 352e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley goto err; 353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (wsize[i] > 1) { 356e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) { 357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 358e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) { 360e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) { 361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 362e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */ 368e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINTs_make_affine(group, num_val, val, ctx)) { 369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 370e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r_is_at_infinity = 1; 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (k = max_len - 1; k >= 0; k--) { 376e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!r_is_at_infinity && !EC_POINT_dbl(group, r, r, ctx)) { 377e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley goto err; 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 3804139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley for (i = 0; i < total_num; i++) { 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (wNAF_len[i] > (size_t)k) { 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int digit = wNAF[i][k]; 383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int is_neg; 384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (digit) { 386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley is_neg = digit < 0; 387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 388e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (is_neg) { 389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley digit = -digit; 390e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (is_neg != r_is_inverted) { 393e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!r_is_at_infinity && !EC_POINT_invert(group, r, ctx)) { 394e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley goto err; 395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r_is_inverted = !r_is_inverted; 397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* digit > 0 */ 400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (r_is_at_infinity) { 402e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) { 403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 404e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley r_is_at_infinity = 0; 406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 407e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx)) { 408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 409e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (r_is_at_infinity) { 417e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_set_to_infinity(group, r)) { 418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 419e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 420e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } else if (r_is_inverted && !EC_POINT_invert(group, r, ctx)) { 421e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley goto err; 422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 426d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 427e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_CTX_free(new_ctx); 428e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley EC_POINT_free(tmp); 429e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley OPENSSL_free(wsize); 430e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley OPENSSL_free(wNAF_len); 431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (wNAF != NULL) { 432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley signed char **w; 433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 434e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (w = wNAF; *w != NULL; w++) { 435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(*w); 436e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(wNAF); 439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (val != NULL) { 441e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (v = val; *v != NULL; v++) { 442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT_clear_free(*v); 443e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley OPENSSL_free(val); 446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 447e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley OPENSSL_free(val_sub); 448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 450