diff options
author | jsing <> | 2023-02-14 18:31:02 +0000 |
---|---|---|
committer | jsing <> | 2023-02-14 18:31:02 +0000 |
commit | 5f8f1614f88870fb8337b56253e6079518e33848 (patch) | |
tree | 9d35b43f24f1326a565456cfa35df66008ee9722 /src | |
parent | c6e3089538d69e8e70c037404ec0d7cb5bcece4d (diff) | |
download | openbsd-5f8f1614f88870fb8337b56253e6079518e33848.tar.gz openbsd-5f8f1614f88870fb8337b56253e6079518e33848.tar.bz2 openbsd-5f8f1614f88870fb8337b56253e6079518e33848.zip |
Provide big number primitives for word addition/multiplication.
These use a consistent naming scheme and are implemented using
bitwise/constant time style operations, which should generally be safe on
all platforms (until a compiler decides to optimise and use branches).
More optimised versions can be provided for a given architecture.
ok tb@
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/bn/bn_internal.h | 115 |
1 files changed, 114 insertions, 1 deletions
diff --git a/src/lib/libcrypto/bn/bn_internal.h b/src/lib/libcrypto/bn/bn_internal.h index 003d8cac2d..ab3efd14f4 100644 --- a/src/lib/libcrypto/bn/bn_internal.h +++ b/src/lib/libcrypto/bn/bn_internal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_internal.h,v 1.2 2023/02/14 17:58:26 jsing Exp $ */ | 1 | /* $OpenBSD: bn_internal.h,v 1.3 2023/02/14 18:31:02 jsing Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -54,6 +54,54 @@ bn_ct_eq_zero_mask(BN_ULONG w) | |||
54 | } | 54 | } |
55 | #endif | 55 | #endif |
56 | 56 | ||
57 | /* | ||
58 | * Big number primitives are named as the operation followed by a suffix | ||
59 | * that indicates the number of words that it operates on, where 'w' means | ||
60 | * single word, 'dw' means double word, 'tw' means triple word and 'qw' means | ||
61 | * quadruple word. Unless otherwise noted, the size of the output is implied | ||
62 | * based on its inputs, for example bn_mulw() takes two single word inputs | ||
63 | * and is going to produce a double word result. | ||
64 | * | ||
65 | * Where a function implements multiple operations, these are listed in order. | ||
66 | * For example, a function that computes (r1:r0) = a * b + c is named | ||
67 | * bn_mulw_addw(), producing a double word result. | ||
68 | */ | ||
69 | |||
70 | /* | ||
71 | * bn_addw() computes (r1:r0) = a + b, where both inputs are single words, | ||
72 | * producing a double word result. The value of r1 is the carry from the | ||
73 | * addition. | ||
74 | */ | ||
75 | #ifndef HAVE_BN_ADDW | ||
76 | #ifdef BN_LLONG | ||
77 | static inline void | ||
78 | bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0) | ||
79 | { | ||
80 | BN_ULLONG r; | ||
81 | |||
82 | r = (BN_ULLONG)a + (BN_ULLONG)b; | ||
83 | |||
84 | *out_r1 = r >> BN_BITS2; | ||
85 | *out_r0 = r & BN_MASK2; | ||
86 | } | ||
87 | #else | ||
88 | |||
89 | static inline void | ||
90 | bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0) | ||
91 | { | ||
92 | BN_ULONG r1, r0, c1, c2; | ||
93 | |||
94 | c1 = a | b; | ||
95 | c2 = a & b; | ||
96 | r0 = a + b; | ||
97 | r1 = ((c1 & ~r0) | c2) >> (BN_BITS2 - 1); /* carry */ | ||
98 | |||
99 | *out_r1 = r1; | ||
100 | *out_r0 = r0; | ||
101 | } | ||
102 | #endif | ||
103 | #endif | ||
104 | |||
57 | #ifndef HAVE_BN_UMUL_HILO | 105 | #ifndef HAVE_BN_UMUL_HILO |
58 | #ifdef BN_LLONG | 106 | #ifdef BN_LLONG |
59 | static inline void | 107 | static inline void |
@@ -188,4 +236,69 @@ bn_umul_hi(BN_ULONG a, BN_ULONG b) | |||
188 | } | 236 | } |
189 | #endif | 237 | #endif |
190 | 238 | ||
239 | /* | ||
240 | * bn_mulw_addw() computes (r1:r0) = a * b + c with all inputs being single | ||
241 | * words, producing a double word result. | ||
242 | */ | ||
243 | #ifndef HAVE_BN_MULW_ADDW | ||
244 | static inline void | ||
245 | bn_mulw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1, | ||
246 | BN_ULONG *out_r0) | ||
247 | { | ||
248 | BN_ULONG carry, r1, r0; | ||
249 | |||
250 | bn_umul_hilo(a, b, &r1, &r0); | ||
251 | bn_addw(r0, c, &carry, &r0); | ||
252 | r1 += carry; | ||
253 | |||
254 | *out_r1 = r1; | ||
255 | *out_r0 = r0; | ||
256 | } | ||
257 | #endif | ||
258 | |||
259 | /* | ||
260 | * bn_mulw_addw_addw() computes (r1:r0) = a * b + c + d with all inputs being | ||
261 | * single words, producing a double word result. | ||
262 | */ | ||
263 | #ifndef HAVE_BN_MULW_ADDW_ADDW | ||
264 | static inline void | ||
265 | bn_mulw_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG d, | ||
266 | BN_ULONG *out_r1, BN_ULONG *out_r0) | ||
267 | { | ||
268 | BN_ULONG carry, r1, r0; | ||
269 | |||
270 | bn_mulw_addw(a, b, c, &r1, &r0); | ||
271 | bn_addw(r0, d, &carry, &r0); | ||
272 | r1 += carry; | ||
273 | |||
274 | *out_r1 = r1; | ||
275 | *out_r0 = r0; | ||
276 | } | ||
277 | #endif | ||
278 | |||
279 | /* | ||
280 | * bn_mulw_addtw() computes (r2:r1:r0) = a * b + (c2:c1:c0), where a and b are | ||
281 | * single words and (c2:c1:c0) is a triple word, producing a triple word result. | ||
282 | * The caller must ensure that the inputs provided do not result in c2 | ||
283 | * overflowing. | ||
284 | */ | ||
285 | #ifndef HAVE_BN_MULW_ADDTW | ||
286 | static inline void | ||
287 | bn_mulw_addtw(BN_ULONG a, BN_ULONG b, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0, | ||
288 | BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0) | ||
289 | { | ||
290 | BN_ULONG carry, r2, r1, r0, x1, x0; | ||
291 | |||
292 | bn_umul_hilo(a, b, &x1, &x0); | ||
293 | bn_addw(c0, x0, &carry, &r0); | ||
294 | x1 += carry; | ||
295 | bn_addw(c1, x1, &carry, &r1); | ||
296 | r2 = c2 + carry; | ||
297 | |||
298 | *out_r2 = r2; | ||
299 | *out_r1 = r1; | ||
300 | *out_r0 = r0; | ||
301 | } | ||
302 | #endif | ||
303 | |||
191 | #endif | 304 | #endif |