summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/libcrypto/bn/bn_internal.h115
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
77static inline void
78bn_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
89static inline void
90bn_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
59static inline void 107static 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
244static inline void
245bn_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
264static inline void
265bn_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
286static inline void
287bn_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