Coverage Report

Created: 2026-02-14 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/fipsmodule/ec/wnaf.cc.inc
Line
Count
Source
1
// Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
2
// Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License");
5
// you may not use this file except in compliance with the License.
6
// You may obtain a copy of the License at
7
//
8
//     https://www.apache.org/licenses/LICENSE-2.0
9
//
10
// Unless required by applicable law or agreed to in writing, software
11
// distributed under the License is distributed on an "AS IS" BASIS,
12
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
// See the License for the specific language governing permissions and
14
// limitations under the License.
15
16
#include <openssl/ec.h>
17
18
#include <assert.h>
19
#include <string.h>
20
21
#include <iterator>
22
23
#include <openssl/bn.h>
24
#include <openssl/err.h>
25
#include <openssl/mem.h>
26
27
#include "../../internal.h"
28
#include "../bn/internal.h"
29
#include "internal.h"
30
31
32
using namespace bssl;
33
34
// This file implements the wNAF-based interleaving multi-exponentiation method
35
// at:
36
//   http://link.springer.com/chapter/10.1007%2F3-540-45537-X_13
37
//   http://www.bmoeller.de/pdf/TI-01-08.multiexp.pdf
38
39
void bssl::ec_compute_wNAF(const EC_GROUP *group, int8_t *out,
40
2.21k
                           const EC_SCALAR *scalar, size_t bits, int w) {
41
  // 'int8_t' can represent integers with absolute values less than 2^7.
42
2.21k
  assert(0 < w && w <= 7);
43
2.21k
  assert(bits != 0);
44
2.21k
  int bit = 1 << w;         // 2^w, at most 128
45
2.21k
  int next_bit = bit << 1;  // 2^(w+1), at most 256
46
2.21k
  int mask = next_bit - 1;  // at most 255
47
48
2.21k
  int window_val = scalar->words[0] & mask;
49
890k
  for (size_t j = 0; j < bits + 1; j++) {
50
888k
    assert(0 <= window_val && window_val <= next_bit);
51
888k
    int digit = 0;
52
888k
    if (window_val & 1) {
53
143k
      assert(0 < window_val && window_val < next_bit);
54
143k
      if (window_val & bit) {
55
70.4k
        digit = window_val - next_bit;
56
        // We know -next_bit < digit < 0 and window_val - digit = next_bit.
57
58
        // modified wNAF
59
70.4k
        if (j + w + 1 >= bits) {
60
          // special case for generating modified wNAFs:
61
          // no new bits will be added into window_val,
62
          // so using a positive digit here will decrease
63
          // the total length of the representation
64
65
238
          digit = window_val & (mask >> 1);
66
          // We know 0 < digit < bit and window_val - digit = bit.
67
238
        }
68
73.4k
      } else {
69
73.4k
        digit = window_val;
70
        // We know 0 < digit < bit and window_val - digit = 0.
71
73.4k
      }
72
73
143k
      window_val -= digit;
74
75
      // Now window_val is 0 or 2^(w+1) in standard wNAF generation.
76
      // For modified window NAFs, it may also be 2^w.
77
      //
78
      // See the comments above for the derivation of each of these bounds.
79
143k
      assert(window_val == 0 || window_val == next_bit || window_val == bit);
80
143k
      assert(-bit < digit && digit < bit);
81
82
      // window_val was odd, so digit is also odd.
83
143k
      assert(digit & 1);
84
143k
    }
85
86
888k
    out[j] = digit;
87
88
    // Incorporate the next bit. Previously, |window_val| <= |next_bit|, so if
89
    // we shift and add at most one copy of |bit|, this will continue to hold
90
    // afterwards.
91
888k
    window_val >>= 1;
92
888k
    window_val += bit * bn_is_bit_set_words(scalar->words, group->order.N.width,
93
888k
                                            j + w + 1);
94
888k
    assert(window_val <= next_bit);
95
888k
  }
96
97
  // bits + 1 entries should be sufficient to consume all bits.
98
2.21k
  assert(window_val == 0);
99
2.21k
}
100
101
// compute_precomp sets |out[i]| to (2*i+1)*p, for i from 0 to |len|.
102
static void compute_precomp(const EC_GROUP *group, EC_JACOBIAN *out,
103
2.21k
                            const EC_JACOBIAN *p, size_t len) {
104
2.21k
  ec_GFp_simple_point_copy(&out[0], p);
105
2.21k
  EC_JACOBIAN two_p;
106
2.21k
  ec_GFp_mont_dbl(group, &two_p, p);
107
17.6k
  for (size_t i = 1; i < len; i++) {
108
15.4k
    ec_GFp_mont_add(group, &out[i], &out[i - 1], &two_p);
109
15.4k
  }
110
2.21k
}
111
112
static void lookup_precomp(const EC_GROUP *group, EC_JACOBIAN *out,
113
143k
                           const EC_JACOBIAN *precomp, int digit) {
114
143k
  if (digit < 0) {
115
70.1k
    digit = -digit;
116
70.1k
    ec_GFp_simple_point_copy(out, &precomp[digit >> 1]);
117
70.1k
    ec_GFp_simple_invert(group, out);
118
73.6k
  } else {
119
73.6k
    ec_GFp_simple_point_copy(out, &precomp[digit >> 1]);
120
73.6k
  }
121
143k
}
122
123
// EC_WNAF_WINDOW_BITS is the window size to use for |ec_GFp_mont_mul_public|.
124
4.42k
#define EC_WNAF_WINDOW_BITS 4
125
126
// EC_WNAF_TABLE_SIZE is the table size to use for |ec_GFp_mont_mul_public|.
127
2.21k
#define EC_WNAF_TABLE_SIZE (1 << (EC_WNAF_WINDOW_BITS - 1))
128
129
// EC_WNAF_STACK is the number of points worth of data to stack-allocate and
130
// avoid a malloc.
131
1.10k
#define EC_WNAF_STACK 3
132
133
int bssl::ec_GFp_mont_mul_public_batch(const EC_GROUP *group, EC_JACOBIAN *r,
134
                                       const EC_SCALAR *g_scalar,
135
                                       const EC_JACOBIAN *points,
136
1.10k
                                       const EC_SCALAR *scalars, size_t num) {
137
1.10k
  size_t bits = EC_GROUP_order_bits(group);
138
1.10k
  size_t wNAF_len = bits + 1;
139
140
  // Stack-allocated space, which will be used if the task is small enough.
141
1.10k
  int8_t wNAF_stack[EC_WNAF_STACK][EC_MAX_BYTES * 8 + 1];
142
1.10k
  EC_JACOBIAN precomp_stack[EC_WNAF_STACK][EC_WNAF_TABLE_SIZE];
143
144
  // Allocated pointers, which will remain NULL unless needed.
145
1.10k
  EC_JACOBIAN(*precomp_alloc)[EC_WNAF_TABLE_SIZE] = nullptr;
146
1.10k
  int8_t (*wNAF_alloc)[EC_MAX_BYTES * 8 + 1] = nullptr;
147
148
  // These fields point either to the stack or heap buffers of the same name.
149
1.10k
  int8_t(*wNAF)[EC_MAX_BYTES * 8 + 1];
150
1.10k
  EC_JACOBIAN(*precomp)[EC_WNAF_TABLE_SIZE];
151
152
1.10k
  if (num <= EC_WNAF_STACK) {
153
1.10k
    wNAF = wNAF_stack;
154
1.10k
    precomp = precomp_stack;
155
1.10k
  } else {
156
0
    wNAF_alloc = reinterpret_cast<decltype(wNAF_alloc)>(
157
0
        OPENSSL_calloc(num, sizeof(wNAF_alloc[0])));
158
0
    if (wNAF_alloc == nullptr) {
159
0
      return 0;
160
0
    }
161
0
    precomp_alloc = reinterpret_cast<decltype(precomp_alloc)>(
162
0
        OPENSSL_calloc(num, sizeof(precomp_alloc[0])));
163
0
    if (precomp_alloc == nullptr) {
164
0
      OPENSSL_free(wNAF_alloc);
165
0
      return 0;
166
0
    }
167
168
0
    wNAF = wNAF_alloc;
169
0
    precomp = precomp_alloc;
170
0
  }
171
172
1.10k
  int8_t g_wNAF[EC_MAX_BYTES * 8 + 1];
173
1.10k
  EC_JACOBIAN g_precomp[EC_WNAF_TABLE_SIZE];
174
1.10k
  assert(wNAF_len <= std::size(g_wNAF));
175
1.10k
  const EC_JACOBIAN *g = &group->generator.raw;
176
1.10k
  if (g_scalar != nullptr) {
177
1.10k
    ec_compute_wNAF(group, g_wNAF, g_scalar, bits, EC_WNAF_WINDOW_BITS);
178
1.10k
    compute_precomp(group, g_precomp, g, EC_WNAF_TABLE_SIZE);
179
1.10k
  }
180
181
2.21k
  for (size_t i = 0; i < num; i++) {
182
1.10k
    assert(wNAF_len <= std::size(wNAF[i]));
183
1.10k
    ec_compute_wNAF(group, wNAF[i], &scalars[i], bits, EC_WNAF_WINDOW_BITS);
184
1.10k
    compute_precomp(group, precomp[i], &points[i], EC_WNAF_TABLE_SIZE);
185
1.10k
  }
186
187
1.10k
  EC_JACOBIAN tmp;
188
1.10k
  int r_is_at_infinity = 1;
189
445k
  for (size_t k = wNAF_len - 1; k < wNAF_len; k--) {
190
444k
    if (!r_is_at_infinity) {
191
440k
      ec_GFp_mont_dbl(group, r, r);
192
440k
    }
193
194
444k
    if (g_scalar != nullptr && g_wNAF[k] != 0) {
195
73.3k
      lookup_precomp(group, &tmp, g_precomp, g_wNAF[k]);
196
73.3k
      if (r_is_at_infinity) {
197
666
        ec_GFp_simple_point_copy(r, &tmp);
198
666
        r_is_at_infinity = 0;
199
72.6k
      } else {
200
72.6k
        ec_GFp_mont_add(group, r, r, &tmp);
201
72.6k
      }
202
73.3k
    }
203
204
888k
    for (size_t i = 0; i < num; i++) {
205
444k
      if (wNAF[i][k] != 0) {
206
70.5k
        lookup_precomp(group, &tmp, precomp[i], wNAF[i][k]);
207
70.5k
        if (r_is_at_infinity) {
208
439
          ec_GFp_simple_point_copy(r, &tmp);
209
439
          r_is_at_infinity = 0;
210
70.1k
        } else {
211
70.1k
          ec_GFp_mont_add(group, r, r, &tmp);
212
70.1k
        }
213
70.5k
      }
214
444k
    }
215
444k
  }
216
217
1.10k
  if (r_is_at_infinity) {
218
0
    ec_GFp_simple_point_set_to_infinity(group, r);
219
0
  }
220
221
1.10k
  OPENSSL_free(wNAF_alloc);
222
1.10k
  OPENSSL_free(precomp_alloc);
223
1.10k
  return 1;
224
1.10k
}