diff options
| author | jsing <> | 2023-02-14 18:31:02 +0000 |
|---|---|---|
| committer | jsing <> | 2023-02-14 18:31:02 +0000 |
| commit | 6a0118974ed883dc49b2e9cf80076ffd212ff90b (patch) | |
| tree | 9d35b43f24f1326a565456cfa35df66008ee9722 /src | |
| parent | 99cba5ab7b530f01483ea8d31860b0984f146f07 (diff) | |
| download | openbsd-6a0118974ed883dc49b2e9cf80076ffd212ff90b.tar.gz openbsd-6a0118974ed883dc49b2e9cf80076ffd212ff90b.tar.bz2 openbsd-6a0118974ed883dc49b2e9cf80076ffd212ff90b.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 |
