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