summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2024-11-22 16:17:36 +0000
committertb <>2024-11-22 16:17:36 +0000
commit3407b244274030ec9f0d4dab8a3526efa35e316a (patch)
tree5b41e9cc92d7436753b37127c268b16d6a0e6aaf /src
parenta29313894a38fcde54ef40f2cabd640fd2250447 (diff)
downloadopenbsd-3407b244274030ec9f0d4dab8a3526efa35e316a.tar.gz
openbsd-3407b244274030ec9f0d4dab8a3526efa35e316a.tar.bz2
openbsd-3407b244274030ec9f0d4dab8a3526efa35e316a.zip
First pass over compute_wNAF()
This streamlines this mess and adapts the API better to its only caller. Nothing much going on here, except that we drop confusing checks and unhelpful comment, thereby making the algorithm more cleanly visible. ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ec_mult.c225
1 files changed, 80 insertions, 145 deletions
diff --git a/src/lib/libcrypto/ec/ec_mult.c b/src/lib/libcrypto/ec/ec_mult.c
index 1b7eb4ec1b..c119410e4a 100644
--- a/src/lib/libcrypto/ec/ec_mult.c
+++ b/src/lib/libcrypto/ec/ec_mult.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_mult.c,v 1.43 2024/11/22 15:21:14 tb Exp $ */ 1/* $OpenBSD: ec_mult.c,v 1.44 2024/11/22 16:17:36 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project. 3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
4 */ 4 */
@@ -70,154 +70,95 @@
70#include "bn_local.h" 70#include "bn_local.h"
71#include "ec_local.h" 71#include "ec_local.h"
72 72
73/* 73static int
74 * This file implements the wNAF-based interleaving multi-exponentation method 74ec_window_bits(const BIGNUM *bn)
75 * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>); 75{
76 * for multiplication with precomputation, we use wNAF splitting 76 int bits = BN_num_bits(bn);
77 * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>). 77
78 */ 78 if (bits >= 2000)
79 return 6;
80 if (bits >= 800)
81 return 5;
82 if (bits >= 300)
83 return 4;
84 if (bits >= 70)
85 return 3;
86 if (bits >= 20)
87 return 2;
88
89 return 1;
90}
79 91
80/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. 92static int
81 * This is an array r[] of values that are either zero or odd with an 93ec_compute_wNAF(const BIGNUM *bn, signed char **out_wNAF, size_t *out_wNAF_len,
82 * absolute value less than 2^w satisfying 94 size_t *out_len)
83 * scalar = \sum_j r[j]*2^j
84 * where at most one of any w+1 consecutive digits is non-zero
85 * with the exception that the most significant digit may be only
86 * w-1 zeros away from that next non-zero digit.
87 */
88static signed char *
89compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
90{ 95{
91 int window_val; 96 signed char *wNAF = NULL;
92 int ok = 0; 97 size_t wNAF_len = 1, len = 1;
93 signed char *r = NULL; 98 int digit, bit, next, mask, sign, wbits, window;
94 int sign = 1; 99 size_t i;
95 int bit, next_bit, mask; 100 int ret = 0;
96 size_t len = 0, j; 101
97 102 if (BN_is_zero(bn)) {
98 if (BN_is_zero(scalar)) { 103 if ((wNAF = calloc(1, 1)) == NULL) {
99 r = malloc(1);
100 if (!r) {
101 ECerror(ERR_R_MALLOC_FAILURE); 104 ECerror(ERR_R_MALLOC_FAILURE);
102 goto err; 105 goto err;
103 } 106 }
104 r[0] = 0;
105 *ret_len = 1;
106 return r;
107 }
108 if (w <= 0 || w > 7) {
109 /* 'signed char' can represent integers with
110 * absolute values less than 2^7 */
111 ECerror(ERR_R_INTERNAL_ERROR);
112 goto err;
113 }
114 bit = 1 << w; /* at most 128 */
115 next_bit = bit << 1; /* at most 256 */
116 mask = next_bit - 1; /* at most 255 */
117 107
118 if (BN_is_negative(scalar)) { 108 goto done;
119 sign = -1;
120 } 109 }
121 if (scalar->d == NULL || scalar->top == 0) { 110
122 ECerror(ERR_R_INTERNAL_ERROR); 111 wNAF_len = BN_num_bits(bn);
123 goto err; 112 if ((wNAF = calloc(1, wNAF_len + 1)) == NULL) {
124 }
125 len = BN_num_bits(scalar);
126 r = malloc(len + 1); /* modified wNAF may be one digit longer than
127 * binary representation (*ret_len will be
128 * set to the actual length, i.e. at most
129 * BN_num_bits(scalar) + 1) */
130 if (r == NULL) {
131 ECerror(ERR_R_MALLOC_FAILURE); 113 ECerror(ERR_R_MALLOC_FAILURE);
132 goto err; 114 goto err;
133 } 115 }
134 window_val = scalar->d[0] & mask;
135 j = 0;
136 while ((window_val != 0) || (j + w + 1 < len)) {
137 /* if j+w+1 >= len, window_val will not increase */
138 int digit = 0;
139
140 /* 0 <= window_val <= 2^(w+1) */
141 if (window_val & 1) {
142 /* 0 < window_val < 2^(w+1) */
143 if (window_val & bit) {
144 digit = window_val - next_bit; /* -2^w < digit < 0 */
145
146#if 1 /* modified wNAF */
147 if (j + w + 1 >= len) {
148 /*
149 * special case for generating
150 * modified wNAFs: no new bits will
151 * be added into window_val, so using
152 * a positive digit here will
153 * decrease the total length of the
154 * representation
155 */
156
157 digit = window_val & (mask >> 1); /* 0 < digit < 2^w */
158 }
159#endif
160 } else {
161 digit = window_val; /* 0 < digit < 2^w */
162 }
163 116
164 if (digit <= -bit || digit >= bit || !(digit & 1)) { 117 wbits = ec_window_bits(bn);
165 ECerror(ERR_R_INTERNAL_ERROR); 118 len = 1 << (wbits - 1);
166 goto err;
167 }
168 window_val -= digit;
169
170 /*
171 * now window_val is 0 or 2^(w+1) in standard wNAF
172 * generation; for modified window NAFs, it may also
173 * be 2^w
174 */
175 if (window_val != 0 && window_val != next_bit && window_val != bit) {
176 ECerror(ERR_R_INTERNAL_ERROR);
177 goto err;
178 }
179 }
180 r[j++] = sign * digit;
181 119
182 window_val >>= 1; 120 bit = 1 << wbits;
183 window_val += bit * BN_is_bit_set(scalar, j + w); 121 next = bit << 1;
122 mask = next - 1;
184 123
185 if (window_val > next_bit) { 124 sign = BN_is_negative(bn) ? -1 : 1;
186 ECerror(ERR_R_INTERNAL_ERROR); 125
187 goto err; 126 window = bn->d[0] & mask;
127 i = 0;
128 while (window != 0 || i + wbits + 1 < wNAF_len) {
129 digit = 0;
130
131 if ((window & 1) != 0) {
132 digit = window;
133 if ((window & bit) != 0) {
134 digit = window - next;
135
136 if (i + wbits + 1 >= wNAF_len)
137 digit = window & (mask >> 1);
138 }
139 window -= digit;
188 } 140 }
189 }
190 141
191 if (j > len + 1) { 142 wNAF[i++] = sign * digit;
192 ECerror(ERR_R_INTERNAL_ERROR); 143 window >>= 1;
193 goto err; 144 window += bit * BN_is_bit_set(bn, i + wbits);
194 } 145 }
195 len = j;
196 ok = 1;
197 146
198 err: 147 wNAF_len = i;
199 if (!ok) {
200 free(r);
201 r = NULL;
202 }
203 if (ok)
204 *ret_len = len;
205 return r;
206}
207 148
149 done:
150 *out_wNAF = wNAF;
151 wNAF = NULL;
152 *out_wNAF_len = wNAF_len;
153 *out_len = len;
208 154
209/* TODO: table should be optimised for the wNAF-based implementation, 155 ret = 1;
210 * sometimes smaller windows will give better performance 156
211 * (thus the boundaries should be increased) 157 err:
212 */ 158 free(wNAF);
213#define EC_window_bits_for_scalar_size(b) \ 159
214 ((size_t) \ 160 return ret;
215 ((b) >= 2000 ? 6 : \ 161}
216 (b) >= 800 ? 5 : \
217 (b) >= 300 ? 4 : \
218 (b) >= 70 ? 3 : \
219 (b) >= 20 ? 2 : \
220 1))
221 162
222static int 163static int
223ec_compute_odd_multiples(const EC_GROUP *group, const EC_POINT *point, 164ec_compute_odd_multiples(const EC_GROUP *group, const EC_POINT *point,
@@ -270,8 +211,8 @@ ec_wNAF_precompute(const EC_GROUP *group, const BIGNUM *m, const EC_POINT *point
270 EC_POINT **val = NULL; 211 EC_POINT **val = NULL;
271 size_t val_len = 0; 212 size_t val_len = 0;
272 const EC_POINT *generator; 213 const EC_POINT *generator;
273 size_t wsize[2] = { 0 }; 214 size_t len[2] = { 0 };
274 size_t i, len0, len1; 215 size_t i;
275 int ret = 0; 216 int ret = 0;
276 217
277 *out_val = NULL; 218 *out_val = NULL;
@@ -282,29 +223,23 @@ ec_wNAF_precompute(const EC_GROUP *group, const BIGNUM *m, const EC_POINT *point
282 goto err; 223 goto err;
283 } 224 }
284 225
285 wsize[0] = EC_window_bits_for_scalar_size(BN_num_bits(m)); 226 if (!ec_compute_wNAF(m, &wNAF[0], &wNAF_len[0], &len[0]))
286 if ((wNAF[0] = compute_wNAF(m, wsize[0], &wNAF_len[0])) == NULL)
287 goto err; 227 goto err;
288 228 if (!ec_compute_wNAF(n, &wNAF[1], &wNAF_len[1], &len[1]))
289 wsize[1] = EC_window_bits_for_scalar_size(BN_num_bits(n));
290 if ((wNAF[1] = compute_wNAF(n, wsize[1], &wNAF_len[1])) == NULL)
291 goto err; 229 goto err;
292 230
293 len0 = 1 << (wsize[0] - 1); 231 if ((val = calloc(len[0] + len[1], sizeof(*val))) == NULL) {
294 len1 = 1 << (wsize[1] - 1);
295
296 if ((val = calloc(len0 + len1, sizeof(*val))) == NULL) {
297 ECerror(ERR_R_MALLOC_FAILURE); 232 ECerror(ERR_R_MALLOC_FAILURE);
298 goto err; 233 goto err;
299 } 234 }
300 val_len = len0 + len1; 235 val_len = len[0] + len[1];
301 236
302 row[0] = &val[0]; 237 row[0] = &val[0];
303 row[1] = &val[len0]; 238 row[1] = &val[len[0]];
304 239
305 if (!ec_compute_odd_multiples(group, generator, row[0], len0, ctx)) 240 if (!ec_compute_odd_multiples(group, generator, row[0], len[0], ctx))
306 goto err; 241 goto err;
307 if (!ec_compute_odd_multiples(group, point, row[1], len1, ctx)) 242 if (!ec_compute_odd_multiples(group, point, row[1], len[1], ctx))
308 goto err; 243 goto err;
309 244
310 if (!EC_POINTs_make_affine(group, val_len, val, ctx)) 245 if (!EC_POINTs_make_affine(group, val_len, val, ctx))