1*2c2f96dcSApple OSS Distributions /* Copyright (c) (2017-2023) Apple Inc. All rights reserved.
2*2c2f96dcSApple OSS Distributions *
3*2c2f96dcSApple OSS Distributions * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
4*2c2f96dcSApple OSS Distributions * is contained in the License.txt file distributed with corecrypto) and only to
5*2c2f96dcSApple OSS Distributions * people who accept that license. IMPORTANT: Any license rights granted to you by
6*2c2f96dcSApple OSS Distributions * Apple Inc. (if any) are limited to internal use within your organization only on
7*2c2f96dcSApple OSS Distributions * devices and computers you own or control, for the sole purpose of verifying the
8*2c2f96dcSApple OSS Distributions * security characteristics and correct functioning of the Apple Software. You may
9*2c2f96dcSApple OSS Distributions * not, directly or indirectly, redistribute the Apple Software or any portions thereof.
10*2c2f96dcSApple OSS Distributions *
11*2c2f96dcSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
12*2c2f96dcSApple OSS Distributions *
13*2c2f96dcSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
14*2c2f96dcSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
15*2c2f96dcSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
16*2c2f96dcSApple OSS Distributions * compliance with the License. The rights granted to you under the License
17*2c2f96dcSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
18*2c2f96dcSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
19*2c2f96dcSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
20*2c2f96dcSApple OSS Distributions * terms of an Apple operating system software license agreement.
21*2c2f96dcSApple OSS Distributions *
22*2c2f96dcSApple OSS Distributions * Please obtain a copy of the License at
23*2c2f96dcSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
24*2c2f96dcSApple OSS Distributions *
25*2c2f96dcSApple OSS Distributions * The Original Code and all software distributed under the License are
26*2c2f96dcSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
27*2c2f96dcSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
28*2c2f96dcSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
29*2c2f96dcSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
30*2c2f96dcSApple OSS Distributions * Please see the License for the specific language governing rights and
31*2c2f96dcSApple OSS Distributions * limitations under the License.
32*2c2f96dcSApple OSS Distributions *
33*2c2f96dcSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
34*2c2f96dcSApple OSS Distributions */
35*2c2f96dcSApple OSS Distributions
36*2c2f96dcSApple OSS Distributions #ifndef _CORECRYPTO_CCN_INTERNAL_H
37*2c2f96dcSApple OSS Distributions #define _CORECRYPTO_CCN_INTERNAL_H
38*2c2f96dcSApple OSS Distributions
39*2c2f96dcSApple OSS Distributions #include <corecrypto/ccn.h>
40*2c2f96dcSApple OSS Distributions #include "cc_workspaces.h"
41*2c2f96dcSApple OSS Distributions #include "cc_memory.h"
42*2c2f96dcSApple OSS Distributions #include "cc_internal.h"
43*2c2f96dcSApple OSS Distributions
44*2c2f96dcSApple OSS Distributions CC_PTRCHECK_CAPABLE_HEADER()
45*2c2f96dcSApple OSS Distributions
46*2c2f96dcSApple OSS Distributions #if CCN_UNIT_SIZE == 8
47*2c2f96dcSApple OSS Distributions
48*2c2f96dcSApple OSS Distributions #if CC_DUNIT_SUPPORTED
49*2c2f96dcSApple OSS Distributions typedef unsigned cc_dunit __attribute__((mode(TI)));
50*2c2f96dcSApple OSS Distributions #endif
51*2c2f96dcSApple OSS Distributions
52*2c2f96dcSApple OSS Distributions #define cc_clz_nonzero cc_clz64
53*2c2f96dcSApple OSS Distributions #define cc_ctz_nonzero cc_ctz64
54*2c2f96dcSApple OSS Distributions #define CC_STORE_UNIT_BE(x, out) cc_store64_be(x, out)
55*2c2f96dcSApple OSS Distributions #define CC_LOAD_UNIT_BE(x, out) (x = cc_load64_be(out))
56*2c2f96dcSApple OSS Distributions
57*2c2f96dcSApple OSS Distributions #elif CCN_UNIT_SIZE == 4
58*2c2f96dcSApple OSS Distributions
59*2c2f96dcSApple OSS Distributions typedef uint64_t cc_dunit;
60*2c2f96dcSApple OSS Distributions
61*2c2f96dcSApple OSS Distributions #define cc_clz_nonzero cc_clz32
62*2c2f96dcSApple OSS Distributions #define cc_ctz_nonzero cc_ctz32
63*2c2f96dcSApple OSS Distributions #define CC_STORE_UNIT_BE(x, out) cc_store32_be(x, out)
64*2c2f96dcSApple OSS Distributions #define CC_LOAD_UNIT_BE(x, out) (x = cc_load32_be(out))
65*2c2f96dcSApple OSS Distributions
66*2c2f96dcSApple OSS Distributions #else
67*2c2f96dcSApple OSS Distributions
68*2c2f96dcSApple OSS Distributions #error Unsupported CCN_UNIT_SIZE
69*2c2f96dcSApple OSS Distributions
70*2c2f96dcSApple OSS Distributions #endif
71*2c2f96dcSApple OSS Distributions
72*2c2f96dcSApple OSS Distributions #if CC_DUNIT_SUPPORTED
73*2c2f96dcSApple OSS Distributions
74*2c2f96dcSApple OSS Distributions // r := x + y
75*2c2f96dcSApple OSS Distributions #define CC_DUNIT_ADD(r, x, y, tmp) \
76*2c2f96dcSApple OSS Distributions do { \
77*2c2f96dcSApple OSS Distributions tmp = ((cc_dunit)(x)) + (y); \
78*2c2f96dcSApple OSS Distributions r = (cc_unit)tmp; \
79*2c2f96dcSApple OSS Distributions } while (0);
80*2c2f96dcSApple OSS Distributions
81*2c2f96dcSApple OSS Distributions // r := x + y + (tmp >> 64)
82*2c2f96dcSApple OSS Distributions #define CC_DUNIT_ADC(r, x, y, tmp) \
83*2c2f96dcSApple OSS Distributions do { \
84*2c2f96dcSApple OSS Distributions cc_unit _c = (tmp) >> CCN_UNIT_BITS; \
85*2c2f96dcSApple OSS Distributions tmp = ((cc_dunit)(x)) + (y) + _c; \
86*2c2f96dcSApple OSS Distributions r = (cc_unit)tmp; \
87*2c2f96dcSApple OSS Distributions } while (0);
88*2c2f96dcSApple OSS Distributions
89*2c2f96dcSApple OSS Distributions // r := x - y
90*2c2f96dcSApple OSS Distributions #define CC_DUNIT_SUB(r, x, y, tmp) \
91*2c2f96dcSApple OSS Distributions do { \
92*2c2f96dcSApple OSS Distributions tmp = ((cc_dunit)(x)) - (y); \
93*2c2f96dcSApple OSS Distributions r = (cc_unit)tmp; \
94*2c2f96dcSApple OSS Distributions } while (0);
95*2c2f96dcSApple OSS Distributions
96*2c2f96dcSApple OSS Distributions // r := x - y - (tmp >> 127)
97*2c2f96dcSApple OSS Distributions #define CC_DUNIT_SBC(r, x, y, tmp) \
98*2c2f96dcSApple OSS Distributions do { \
99*2c2f96dcSApple OSS Distributions cc_unit _b = (tmp) >> (2 * CCN_UNIT_BITS - 1); \
100*2c2f96dcSApple OSS Distributions tmp = ((cc_dunit)(x)) - (y) - _b; \
101*2c2f96dcSApple OSS Distributions r = (cc_unit)tmp; \
102*2c2f96dcSApple OSS Distributions } while (0);
103*2c2f96dcSApple OSS Distributions
104*2c2f96dcSApple OSS Distributions // (hi,lo) += (x * y)
105*2c2f96dcSApple OSS Distributions #define CC_DUNIT_MUL(x, y, hi, lo, tmp) \
106*2c2f96dcSApple OSS Distributions do { \
107*2c2f96dcSApple OSS Distributions tmp = (cc_dunit)(x) * (y); \
108*2c2f96dcSApple OSS Distributions lo += (tmp) & CCN_UNIT_MASK; \
109*2c2f96dcSApple OSS Distributions hi += (tmp) >> CCN_UNIT_BITS; \
110*2c2f96dcSApple OSS Distributions } while (0);
111*2c2f96dcSApple OSS Distributions
112*2c2f96dcSApple OSS Distributions // (hi,lo) += (x * y) * i
113*2c2f96dcSApple OSS Distributions #define CC_DUNIT_MULI(x, y, hi, lo, tmp, i) \
114*2c2f96dcSApple OSS Distributions do { \
115*2c2f96dcSApple OSS Distributions tmp = (cc_dunit)(x) * (y); \
116*2c2f96dcSApple OSS Distributions lo += ((tmp) & CCN_UNIT_MASK) * (i); \
117*2c2f96dcSApple OSS Distributions hi += ((tmp) >> CCN_UNIT_BITS) * (i); \
118*2c2f96dcSApple OSS Distributions } while (0);
119*2c2f96dcSApple OSS Distributions
120*2c2f96dcSApple OSS Distributions // r := lo and (hi,lo) >>= 64
121*2c2f96dcSApple OSS Distributions #define CC_STORE_LO(r, hi, lo) \
122*2c2f96dcSApple OSS Distributions do { \
123*2c2f96dcSApple OSS Distributions r = (cc_unit)lo; \
124*2c2f96dcSApple OSS Distributions hi += lo >> CCN_UNIT_BITS; \
125*2c2f96dcSApple OSS Distributions lo = hi & CCN_UNIT_MASK; \
126*2c2f96dcSApple OSS Distributions hi >>= CCN_UNIT_BITS; \
127*2c2f96dcSApple OSS Distributions } while (0);
128*2c2f96dcSApple OSS Distributions
129*2c2f96dcSApple OSS Distributions #endif
130*2c2f96dcSApple OSS Distributions
131*2c2f96dcSApple OSS Distributions CC_NONNULL((2, 3))
132*2c2f96dcSApple OSS Distributions void ccn_set(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s);
133*2c2f96dcSApple OSS Distributions
134*2c2f96dcSApple OSS Distributions CC_INLINE
135*2c2f96dcSApple OSS Distributions CC_NONNULL((2, 4))
136*2c2f96dcSApple OSS Distributions void
ccn_setn(cc_size n,cc_unit * cc_counted_by (n)r,const cc_size s_size,const cc_unit * cc_counted_by (s_size)s)137*2c2f96dcSApple OSS Distributions ccn_setn(cc_size n, cc_unit *cc_counted_by (n)r, const cc_size s_size, const cc_unit *cc_counted_by (s_size)s)
138*2c2f96dcSApple OSS Distributions {
139*2c2f96dcSApple OSS Distributions cc_assert(n > 0 && s_size <= n);
140*2c2f96dcSApple OSS Distributions
141*2c2f96dcSApple OSS Distributions if (s_size > 0) {
142*2c2f96dcSApple OSS Distributions ccn_set(s_size, r, s);
143*2c2f96dcSApple OSS Distributions }
144*2c2f96dcSApple OSS Distributions
145*2c2f96dcSApple OSS Distributions ccn_zero(n - s_size, r + s_size);
146*2c2f96dcSApple OSS Distributions }
147*2c2f96dcSApple OSS Distributions
148*2c2f96dcSApple OSS Distributions CC_INLINE
149*2c2f96dcSApple OSS Distributions CC_NONNULL((2))
150*2c2f96dcSApple OSS Distributions void
ccn_clear(cc_size n,cc_unit * cc_sized_by (n)r)151*2c2f96dcSApple OSS Distributions ccn_clear(cc_size n, cc_unit *cc_sized_by (n)r)
152*2c2f96dcSApple OSS Distributions {
153*2c2f96dcSApple OSS Distributions cc_clear(ccn_sizeof_n(n), r);
154*2c2f96dcSApple OSS Distributions }
155*2c2f96dcSApple OSS Distributions
156*2c2f96dcSApple OSS Distributions /* Returns the value of bit _k_ of _ccn_, both are only evaluated once. */
157*2c2f96dcSApple OSS Distributions CC_INLINE cc_unit
ccn_bit(const cc_unit * cc_indexable x,size_t k)158*2c2f96dcSApple OSS Distributions ccn_bit(const cc_unit *cc_indexable x, size_t k)
159*2c2f96dcSApple OSS Distributions {
160*2c2f96dcSApple OSS Distributions return 1 & (x[k >> CCN_LOG2_BITS_PER_UNIT] >> (k & (CCN_UNIT_BITS - 1)));
161*2c2f96dcSApple OSS Distributions }
162*2c2f96dcSApple OSS Distributions
163*2c2f96dcSApple OSS Distributions /* |s - t| -> r return 1 iff t > s, 0 otherwise */
164*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
165*2c2f96dcSApple OSS Distributions cc_unit ccn_abs(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, const cc_unit *cc_counted_by(n) t);
166*2c2f96dcSApple OSS Distributions
167*2c2f96dcSApple OSS Distributions /* Returns the number of bits which are zero before the first one bit
168*2c2f96dcSApple OSS Distributions * counting from least to most significant bit. */
169*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
170*2c2f96dcSApple OSS Distributions CC_NONNULL((2))
171*2c2f96dcSApple OSS Distributions size_t ccn_trailing_zeros(cc_size n, const cc_unit *s);
172*2c2f96dcSApple OSS Distributions
173*2c2f96dcSApple OSS Distributions /*! @function ccn_shift_right
174*2c2f96dcSApple OSS Distributions * @abstract Shifts s to the right by k bits, where 0 <= k < CCN_UNIT_BITS.
175*2c2f96dcSApple OSS Distributions *
176*2c2f96dcSApple OSS Distributions * @param n Length of r and s
177*2c2f96dcSApple OSS Distributions * @param r Resulting big int.
178*2c2f96dcSApple OSS Distributions * @param s Big int to shift.
179*2c2f96dcSApple OSS Distributions * @param k Number of bits to shift by.
180*2c2f96dcSApple OSS Distributions */
181*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
182*2c2f96dcSApple OSS Distributions void ccn_shift_right(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, size_t k) __asm__("_ccn_shift_right");
183*2c2f96dcSApple OSS Distributions
184*2c2f96dcSApple OSS Distributions /*! @function ccn_shift_right_multi
185*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe, right shift.
186*2c2f96dcSApple OSS Distributions *
187*2c2f96dcSApple OSS Distributions * @param n Length of r and s as number of cc_units.
188*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with s.
189*2c2f96dcSApple OSS Distributions * @param s Input that's shifted by k bits.
190*2c2f96dcSApple OSS Distributions * @param k Number of bits by which to shift s to the right.
191*2c2f96dcSApple OSS Distributions */
192*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
193*2c2f96dcSApple OSS Distributions void ccn_shift_right_multi(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, size_t k);
194*2c2f96dcSApple OSS Distributions
195*2c2f96dcSApple OSS Distributions /* s << k -> r return bits shifted out of most significant word in bits [0, n>
196*2c2f96dcSApple OSS Distributions * { N bit, scalar -> N bit } N = n * sizeof(cc_unit) * 8
197*2c2f96dcSApple OSS Distributions * the _multi version doesn't return the shifted bits, but does support multiple
198*2c2f96dcSApple OSS Distributions * word shifts */
199*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
200*2c2f96dcSApple OSS Distributions void ccn_shift_left(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, size_t k) __asm__("_ccn_shift_left");
201*2c2f96dcSApple OSS Distributions
202*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
203*2c2f96dcSApple OSS Distributions void ccn_shift_left_multi(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, size_t k);
204*2c2f96dcSApple OSS Distributions
205*2c2f96dcSApple OSS Distributions // Conditionally swap the content of r0 and r1 buffers in constant time
206*2c2f96dcSApple OSS Distributions // r0:r1 <- r1*k1 + s0*(k1-1)
207*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
208*2c2f96dcSApple OSS Distributions void ccn_cond_swap(cc_size n, cc_unit ki, cc_unit *cc_counted_by(n) r0, cc_unit *cc_counted_by(n) r1);
209*2c2f96dcSApple OSS Distributions
210*2c2f96dcSApple OSS Distributions /*! @function ccn_cond_shift_right
211*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe, conditional right shift.
212*2c2f96dcSApple OSS Distributions *
213*2c2f96dcSApple OSS Distributions * @param n Length of each of r and a as number of cc_units.
214*2c2f96dcSApple OSS Distributions * @param s Selector bit (0 or 1).
215*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with a.
216*2c2f96dcSApple OSS Distributions * @param a Input that's shifted by k bits, if s=1.
217*2c2f96dcSApple OSS Distributions * @param k Number of bits by which to shift a to the right, if s=1.
218*2c2f96dcSApple OSS Distributions * (k must not be larger than CCN_UNIT_BITS.)
219*2c2f96dcSApple OSS Distributions */
220*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
221*2c2f96dcSApple OSS Distributions void ccn_cond_shift_right(cc_size n, cc_unit s, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) a, size_t k);
222*2c2f96dcSApple OSS Distributions
223*2c2f96dcSApple OSS Distributions /*! @function ccn_cond_neg
224*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe, conditional negation.
225*2c2f96dcSApple OSS Distributions *
226*2c2f96dcSApple OSS Distributions * @param n Length of each of r and x as number of cc_units.
227*2c2f96dcSApple OSS Distributions * @param s Selector bit (0 or 1).
228*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with x.
229*2c2f96dcSApple OSS Distributions * @param x Input that's negated, if s=1.
230*2c2f96dcSApple OSS Distributions */
231*2c2f96dcSApple OSS Distributions void ccn_cond_neg(cc_size n, cc_unit s, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) x);
232*2c2f96dcSApple OSS Distributions
233*2c2f96dcSApple OSS Distributions /*! @function ccn_cond_shift_right_carry
234*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe, conditional right shift.
235*2c2f96dcSApple OSS Distributions *
236*2c2f96dcSApple OSS Distributions * @param n Length of each of r and a as number of cc_units.
237*2c2f96dcSApple OSS Distributions * @param s Selector bit (0 or 1).
238*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with a.
239*2c2f96dcSApple OSS Distributions * @param a Input that's shifted by k bits, if s=1.
240*2c2f96dcSApple OSS Distributions * @param k Number of bits by which to shift a to the right, if s=1.
241*2c2f96dcSApple OSS Distributions * (k must not be larger than CCN_UNIT_BITS.)
242*2c2f96dcSApple OSS Distributions * @param c Carry bit(s), the most significant bit(s) after shifting, if s=1.
243*2c2f96dcSApple OSS Distributions */
244*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
245*2c2f96dcSApple OSS Distributions void ccn_cond_shift_right_carry(cc_size n, cc_unit s, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) a, size_t k, cc_unit c);
246*2c2f96dcSApple OSS Distributions
247*2c2f96dcSApple OSS Distributions /*! @function ccn_cond_add
248*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe, conditional addition.
249*2c2f96dcSApple OSS Distributions * Computes r:= x + y, iff s = 1. Set r := x otherwise.
250*2c2f96dcSApple OSS Distributions *
251*2c2f96dcSApple OSS Distributions * @param n Length of each of r, x, and y as number of cc_units.
252*2c2f96dcSApple OSS Distributions * @param s Selector bit (0 or 1).
253*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with x or y.
254*2c2f96dcSApple OSS Distributions * @param x First addend.
255*2c2f96dcSApple OSS Distributions * @param y Second addend.
256*2c2f96dcSApple OSS Distributions *
257*2c2f96dcSApple OSS Distributions * @return The carry bit, if s=1. 0 otherwise.
258*2c2f96dcSApple OSS Distributions */
259*2c2f96dcSApple OSS Distributions CC_WARN_RESULT CC_NONNULL_ALL
260*2c2f96dcSApple OSS Distributions cc_unit ccn_cond_add(cc_size n, cc_unit s, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) x, const cc_unit *cc_counted_by(n) y);
261*2c2f96dcSApple OSS Distributions
262*2c2f96dcSApple OSS Distributions /*! @function ccn_cond_rsub
263*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe, conditional reverse subtraction.
264*2c2f96dcSApple OSS Distributions * Computes r := y - x, iff s = 1. Sets r := x otherwise.
265*2c2f96dcSApple OSS Distributions *
266*2c2f96dcSApple OSS Distributions * @param n Length of each of r, x, and y as number of cc_units.
267*2c2f96dcSApple OSS Distributions * @param s Selector bit (0 or 1).
268*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with x or y.
269*2c2f96dcSApple OSS Distributions * @param x Subtrahend.
270*2c2f96dcSApple OSS Distributions * @param y Minuend.
271*2c2f96dcSApple OSS Distributions *
272*2c2f96dcSApple OSS Distributions * @return The carry bit, if s=1. 0 otherwise.
273*2c2f96dcSApple OSS Distributions */
274*2c2f96dcSApple OSS Distributions CC_WARN_RESULT CC_NONNULL_ALL
275*2c2f96dcSApple OSS Distributions cc_unit ccn_cond_rsub(cc_size n, cc_unit s, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) x, const cc_unit *cc_counted_by(n) y);
276*2c2f96dcSApple OSS Distributions
277*2c2f96dcSApple OSS Distributions /*! @function ccn_cond_sub
278*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe, conditional subtraction.
279*2c2f96dcSApple OSS Distributions * Computes r := x - y, iff s = 1. Sets r := x otherwise.
280*2c2f96dcSApple OSS Distributions *
281*2c2f96dcSApple OSS Distributions * @param n Length of each of r, x, and y as number of cc_units.
282*2c2f96dcSApple OSS Distributions * @param s Selector bit (0 or 1).
283*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with x or y.
284*2c2f96dcSApple OSS Distributions * @param x Minuend.
285*2c2f96dcSApple OSS Distributions * @param y Subtrahend.
286*2c2f96dcSApple OSS Distributions *
287*2c2f96dcSApple OSS Distributions * @return The carry bit, if s=1. 0 otherwise.
288*2c2f96dcSApple OSS Distributions */
289*2c2f96dcSApple OSS Distributions CC_WARN_RESULT CC_NONNULL_ALL
290*2c2f96dcSApple OSS Distributions cc_unit ccn_cond_sub(cc_size n, cc_unit s, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) x, const cc_unit *cc_counted_by(n) y);
291*2c2f96dcSApple OSS Distributions
292*2c2f96dcSApple OSS Distributions /*! @function ccn_cond_clear
293*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe, conditional zeroization.
294*2c2f96dcSApple OSS Distributions * Sets r := 0, if s = 1. Does nothing otherwise.
295*2c2f96dcSApple OSS Distributions *
296*2c2f96dcSApple OSS Distributions * @param n Length of r as number of cc_units.
297*2c2f96dcSApple OSS Distributions * @param s Selector bit (0 or 1).
298*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with x or y.
299*2c2f96dcSApple OSS Distributions */
300*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
301*2c2f96dcSApple OSS Distributions void ccn_cond_clear(cc_size n, cc_unit s, cc_unit *r);
302*2c2f96dcSApple OSS Distributions
303*2c2f96dcSApple OSS Distributions /*! @function ccn_mux
304*2c2f96dcSApple OSS Distributions * @abstract Constant-time, SPA-safe multiplexer. Sets r = (s ? a : b).
305*2c2f96dcSApple OSS Distributions *
306*2c2f96dcSApple OSS Distributions * @discussion This works like a normal multiplexer (s & a) | (~s & b) but is
307*2c2f96dcSApple OSS Distributions * slightly more complicated and expensive. Out of `s` we build
308*2c2f96dcSApple OSS Distributions * half-word masks to hide extreme Hamming weights of operands.
309*2c2f96dcSApple OSS Distributions *
310*2c2f96dcSApple OSS Distributions * @param n Length of each of r, a, and b as number of cc_units.
311*2c2f96dcSApple OSS Distributions * @param s Selector bit (0 or 1).
312*2c2f96dcSApple OSS Distributions * @param r Destination, can overlap with a or b.
313*2c2f96dcSApple OSS Distributions * @param a Input selected when s=1.
314*2c2f96dcSApple OSS Distributions * @param b Input selected when s=0.
315*2c2f96dcSApple OSS Distributions */
316*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
317*2c2f96dcSApple OSS Distributions void ccn_mux(cc_size n, cc_unit s, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) a, const cc_unit *cc_counted_by(n) b);
318*2c2f96dcSApple OSS Distributions
319*2c2f96dcSApple OSS Distributions /*! @function ccn_gcd_ws
320*2c2f96dcSApple OSS Distributions * @abstract Computes the greatest common divisor of s and t,
321*2c2f96dcSApple OSS Distributions * r = gcd(s,t) / 2^k, and returns k.
322*2c2f96dcSApple OSS Distributions *
323*2c2f96dcSApple OSS Distributions * @param ws Workspace.
324*2c2f96dcSApple OSS Distributions * @param rn Length of r as a number of cc_units.
325*2c2f96dcSApple OSS Distributions * @param r Resulting GCD.
326*2c2f96dcSApple OSS Distributions * @param sn Length of s as a number of cc_units.
327*2c2f96dcSApple OSS Distributions * @param s First number s.
328*2c2f96dcSApple OSS Distributions * @param tn Length of t as a number of cc_units.
329*2c2f96dcSApple OSS Distributions * @param t First number t.
330*2c2f96dcSApple OSS Distributions *
331*2c2f96dcSApple OSS Distributions * @return The factor of two to shift r by to compute the actual GCD.
332*2c2f96dcSApple OSS Distributions */
333*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
334*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
335*2c2f96dcSApple OSS Distributions size_t ccn_gcd_ws(cc_ws_t ws, cc_size rn, cc_unit *cc_counted_by(rn) r, cc_size sn, const cc_unit *cc_counted_by(sn) s, cc_size tn, const cc_unit *cc_counted_by(tn) t);
336*2c2f96dcSApple OSS Distributions
337*2c2f96dcSApple OSS Distributions /*! @function ccn_lcm_ws
338*2c2f96dcSApple OSS Distributions * @abstract Computes lcm(s,t), the least common multiple of s and t.
339*2c2f96dcSApple OSS Distributions *
340*2c2f96dcSApple OSS Distributions * @param ws Workspace.
341*2c2f96dcSApple OSS Distributions * @param n Length of s,t as a number of cc_units.
342*2c2f96dcSApple OSS Distributions * @param r2n Resulting LCM of length 2*n.
343*2c2f96dcSApple OSS Distributions * @param s First number s.
344*2c2f96dcSApple OSS Distributions * @param t First number t.
345*2c2f96dcSApple OSS Distributions */
346*2c2f96dcSApple OSS Distributions void ccn_lcm_ws(cc_ws_t ws, cc_size n, cc_unit *cc_unsafe_indexable r2n, const cc_unit *cc_counted_by(n)s, const cc_unit *cc_counted_by(n)t);
347*2c2f96dcSApple OSS Distributions
348*2c2f96dcSApple OSS Distributions /* s * t -> r_2n r_2n must not overlap with s nor t
349*2c2f96dcSApple OSS Distributions * { n bit, n bit -> 2 * n bit } n = count * sizeof(cc_unit) * 8
350*2c2f96dcSApple OSS Distributions * { N bit, N bit -> 2N bit } N = ccn_bitsof(n) */
351*2c2f96dcSApple OSS Distributions CC_NONNULL((2, 3, 4))
352*2c2f96dcSApple OSS Distributions void ccn_mul(cc_size n, cc_unit *cc_unsafe_indexable r_2n, const cc_unit *cc_counted_by(n)s, const cc_unit *cc_counted_by(n)t) __asm__("_ccn_mul");
353*2c2f96dcSApple OSS Distributions
354*2c2f96dcSApple OSS Distributions /* s[0..n) * v -> r[0..n)+return value
355*2c2f96dcSApple OSS Distributions * { N bit, sizeof(cc_unit) * 8 bit -> N + sizeof(cc_unit) * 8 bit } N = n * sizeof(cc_unit) * 8 */
356*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
357*2c2f96dcSApple OSS Distributions CC_NONNULL((2, 3))
358*2c2f96dcSApple OSS Distributions cc_unit ccn_mul1(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, const cc_unit v);
359*2c2f96dcSApple OSS Distributions
360*2c2f96dcSApple OSS Distributions /* s[0..n) * v[0..nv] -> r[0..n+nv)
361*2c2f96dcSApple OSS Distributions * { n bit, nv bit -> n + nv bit} n = count * sizeof(cc_unit) * 8
362*2c2f96dcSApple OSS Distributions * { N bit, NV bit -> N + NV bit} N = ccn_bitsof(n), NV = ccn_bitsof(nv)
363*2c2f96dcSApple OSS Distributions * r, s, and v should not overlap
364*2c2f96dcSApple OSS Distributions * Leaks n and nv through timing */
365*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
366*2c2f96dcSApple OSS Distributions void ccn_muln(cc_size n, cc_unit *cc_counted_by(n + nv) r, const cc_unit *cc_counted_by(n) s, cc_size nv, const cc_unit *cc_counted_by(n) v);
367*2c2f96dcSApple OSS Distributions
368*2c2f96dcSApple OSS Distributions /* s[0..n) * v + r[0..n) -> r[0..n)+return value
369*2c2f96dcSApple OSS Distributions * { N bit, sizeof(cc_unit) * 8 bit -> N + sizeof(cc_unit) * 8 bit } N = n * sizeof(cc_unit) * 8 */
370*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
371*2c2f96dcSApple OSS Distributions CC_NONNULL((2, 3))
372*2c2f96dcSApple OSS Distributions cc_unit ccn_addmul1(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, const cc_unit v);
373*2c2f96dcSApple OSS Distributions
374*2c2f96dcSApple OSS Distributions /* s * t -> r_2n r_2n must not overlap with s nor t
375*2c2f96dcSApple OSS Distributions * { n bit, n bit -> 2 * n bit } n = count * sizeof(cc_unit) * 8
376*2c2f96dcSApple OSS Distributions * { N bit, N bit -> 2N bit } N = ccn_bitsof(n)
377*2c2f96dcSApple OSS Distributions * Provide a workspace for potential speedup */
378*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
379*2c2f96dcSApple OSS Distributions void ccn_mul_ws(cc_ws_t ws, cc_size count, cc_unit *cc_unsafe_indexable r, const cc_unit *cc_counted_by(count)s, const cc_unit *cc_counted_by(count)t);
380*2c2f96dcSApple OSS Distributions
381*2c2f96dcSApple OSS Distributions /* s^2 -> r
382*2c2f96dcSApple OSS Distributions * { n bit -> 2 * n bit } */
383*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
384*2c2f96dcSApple OSS Distributions void ccn_sqr_ws(cc_ws_t ws, cc_size n, cc_unit *cc_unsafe_indexable r, const cc_unit *cc_counted_by(n)s);
385*2c2f96dcSApple OSS Distributions
386*2c2f96dcSApple OSS Distributions /*! @function ccn_mod_ws
387*2c2f96dcSApple OSS Distributions * @abstract Computes r = a % d.
388*2c2f96dcSApple OSS Distributions *
389*2c2f96dcSApple OSS Distributions * @discussion Use CCN_DIVMOD_WORKSPACE_N(n) for the workspace.
390*2c2f96dcSApple OSS Distributions *
391*2c2f96dcSApple OSS Distributions * @param ws Workspace
392*2c2f96dcSApple OSS Distributions * @param na Length of a as a number of cc_units.
393*2c2f96dcSApple OSS Distributions * @param a The dividend a.
394*2c2f96dcSApple OSS Distributions * @param n Length of r,d as a number of cc_units.
395*2c2f96dcSApple OSS Distributions * @param r The resulting remainder.
396*2c2f96dcSApple OSS Distributions * @param d The divisor d.
397*2c2f96dcSApple OSS Distributions */
398*2c2f96dcSApple OSS Distributions #define ccn_mod_ws(ws, na, a, n, r, d) ccn_divmod_ws(ws, na, a, 0, NULL, n, r, d)
399*2c2f96dcSApple OSS Distributions #define ccn_mod(na, a, n, r, d) ccn_divmod(na, a, 0, NULL, n, r, d)
400*2c2f96dcSApple OSS Distributions
401*2c2f96dcSApple OSS Distributions /*! @function ccn_neg
402*2c2f96dcSApple OSS Distributions * @abstract Computes the two's complement of x.
403*2c2f96dcSApple OSS Distributions *
404*2c2f96dcSApple OSS Distributions * @param n Length of r and x
405*2c2f96dcSApple OSS Distributions * @param r Result of the negation
406*2c2f96dcSApple OSS Distributions * @param x Number to negate
407*2c2f96dcSApple OSS Distributions */
408*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
409*2c2f96dcSApple OSS Distributions void ccn_neg(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) x);
410*2c2f96dcSApple OSS Distributions
411*2c2f96dcSApple OSS Distributions /*! @function ccn_invert
412*2c2f96dcSApple OSS Distributions * @abstract Computes x^-1 (mod 2^w).
413*2c2f96dcSApple OSS Distributions *
414*2c2f96dcSApple OSS Distributions * @param x Number to invert
415*2c2f96dcSApple OSS Distributions *
416*2c2f96dcSApple OSS Distributions * @return x^-1 (mod 2^w)
417*2c2f96dcSApple OSS Distributions */
418*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
419*2c2f96dcSApple OSS Distributions CC_CONST CC_NONNULL_ALL
420*2c2f96dcSApple OSS Distributions CC_INLINE cc_unit
ccn_invert(cc_unit x)421*2c2f96dcSApple OSS Distributions ccn_invert(cc_unit x)
422*2c2f96dcSApple OSS Distributions {
423*2c2f96dcSApple OSS Distributions cc_assert(x & 1);
424*2c2f96dcSApple OSS Distributions
425*2c2f96dcSApple OSS Distributions // Initial precision is 5 bits.
426*2c2f96dcSApple OSS Distributions cc_unit y = (3 * x) ^ 2;
427*2c2f96dcSApple OSS Distributions
428*2c2f96dcSApple OSS Distributions // Newton-Raphson iterations.
429*2c2f96dcSApple OSS Distributions // Precision doubles with every step.
430*2c2f96dcSApple OSS Distributions y *= 2 - y * x;
431*2c2f96dcSApple OSS Distributions y *= 2 - y * x;
432*2c2f96dcSApple OSS Distributions y *= 2 - y * x;
433*2c2f96dcSApple OSS Distributions #if CCN_UNIT_SIZE == 8
434*2c2f96dcSApple OSS Distributions y *= 2 - y * x;
435*2c2f96dcSApple OSS Distributions #endif
436*2c2f96dcSApple OSS Distributions
437*2c2f96dcSApple OSS Distributions cc_assert(y * x == 1);
438*2c2f96dcSApple OSS Distributions return y;
439*2c2f96dcSApple OSS Distributions }
440*2c2f96dcSApple OSS Distributions
441*2c2f96dcSApple OSS Distributions /*! @function ccn_div_exact_ws
442*2c2f96dcSApple OSS Distributions * @abstract Computes q = a / d where a = 0 (mod d).
443*2c2f96dcSApple OSS Distributions *
444*2c2f96dcSApple OSS Distributions * @param ws Workspace
445*2c2f96dcSApple OSS Distributions * @param n Length of q,a,d as a number of cc_units.
446*2c2f96dcSApple OSS Distributions * @param q The resulting exact quotient.
447*2c2f96dcSApple OSS Distributions * @param a The dividend a.
448*2c2f96dcSApple OSS Distributions * @param d The divisor d.
449*2c2f96dcSApple OSS Distributions */
450*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
451*2c2f96dcSApple OSS Distributions void ccn_div_exact_ws(cc_ws_t ws, cc_size n, cc_unit *cc_counted_by(n) q, const cc_unit *cc_counted_by(n) a, const cc_unit *cc_counted_by(n) d);
452*2c2f96dcSApple OSS Distributions
453*2c2f96dcSApple OSS Distributions /*! @function ccn_divides1
454*2c2f96dcSApple OSS Distributions * @abstract Returns whether q divides x.
455*2c2f96dcSApple OSS Distributions *
456*2c2f96dcSApple OSS Distributions * @param n Length of x as a number of cc_units.
457*2c2f96dcSApple OSS Distributions * @param x The dividend x.
458*2c2f96dcSApple OSS Distributions * @param q The divisor q.
459*2c2f96dcSApple OSS Distributions *
460*2c2f96dcSApple OSS Distributions * @return True if q divides x without remainder, false otherwise.
461*2c2f96dcSApple OSS Distributions */
462*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
463*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
464*2c2f96dcSApple OSS Distributions bool ccn_divides1(cc_size n, const cc_unit *cc_counted_by(n)x, cc_unit q);
465*2c2f96dcSApple OSS Distributions
466*2c2f96dcSApple OSS Distributions /*! @function ccn_select
467*2c2f96dcSApple OSS Distributions * @abstract Select r[i] in constant-time, not revealing i via cache-timing.
468*2c2f96dcSApple OSS Distributions *
469*2c2f96dcSApple OSS Distributions * @param start Start index.
470*2c2f96dcSApple OSS Distributions * @param end End index (length of r).
471*2c2f96dcSApple OSS Distributions * @param r Big int r.
472*2c2f96dcSApple OSS Distributions * @param i Offset into r.
473*2c2f96dcSApple OSS Distributions *
474*2c2f96dcSApple OSS Distributions * @return r[i], or zero if start > i or end < i.
475*2c2f96dcSApple OSS Distributions */
476*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
477*2c2f96dcSApple OSS Distributions CC_INLINE cc_unit
ccn_select(cc_size start,cc_size end,const cc_unit * cc_counted_by (end)r,cc_size i)478*2c2f96dcSApple OSS Distributions ccn_select(cc_size start, cc_size end, const cc_unit *cc_counted_by(end)r, cc_size i)
479*2c2f96dcSApple OSS Distributions {
480*2c2f96dcSApple OSS Distributions cc_unit ri = 0;
481*2c2f96dcSApple OSS Distributions
482*2c2f96dcSApple OSS Distributions for (cc_size j = start; j < end; j++) {
483*2c2f96dcSApple OSS Distributions cc_size i_neq_j; // i≠j?
484*2c2f96dcSApple OSS Distributions CC_HEAVISIDE_STEP(i_neq_j, i ^ j);
485*2c2f96dcSApple OSS Distributions ri |= r[j] & ((cc_unit)i_neq_j - 1);
486*2c2f96dcSApple OSS Distributions }
487*2c2f96dcSApple OSS Distributions
488*2c2f96dcSApple OSS Distributions return ri;
489*2c2f96dcSApple OSS Distributions }
490*2c2f96dcSApple OSS Distributions
491*2c2f96dcSApple OSS Distributions /*! @function ccn_invmod_ws
492*2c2f96dcSApple OSS Distributions * @abstract Computes the inverse of x modulo m, r = x^-1 (mod m).
493*2c2f96dcSApple OSS Distributions * Returns an error if there's no inverse, i.e. gcd(x,m) ≠ 1.
494*2c2f96dcSApple OSS Distributions *
495*2c2f96dcSApple OSS Distributions * @discussion This is a very generic version of the binary XGCD algorithm. You
496*2c2f96dcSApple OSS Distributions * don't want to use it when you have an odd modulus.
497*2c2f96dcSApple OSS Distributions *
498*2c2f96dcSApple OSS Distributions * This function is meant to be used by RSA key generation, for
499*2c2f96dcSApple OSS Distributions * computation of d = e^1 (mod lcm(p-1,q-1)), where m can be even.
500*2c2f96dcSApple OSS Distributions *
501*2c2f96dcSApple OSS Distributions * x > m is allowed as long as xn == n, i.e. they occupy the same
502*2c2f96dcSApple OSS Distributions * number of cc_units.
503*2c2f96dcSApple OSS Distributions *
504*2c2f96dcSApple OSS Distributions * @param ws Workspace.
505*2c2f96dcSApple OSS Distributions * @param n Length of r and m as a number of cc_units.
506*2c2f96dcSApple OSS Distributions * @param r The resulting inverse r.
507*2c2f96dcSApple OSS Distributions * @param xn Length of x as a number of cc_units.
508*2c2f96dcSApple OSS Distributions * @param x The number to invert.
509*2c2f96dcSApple OSS Distributions * @param m The modulus.
510*2c2f96dcSApple OSS Distributions *
511*2c2f96dcSApple OSS Distributions * @return 0 on success, non-zero on failure. See cc_error.h for more details.
512*2c2f96dcSApple OSS Distributions */
513*2c2f96dcSApple OSS Distributions CC_WARN_RESULT
514*2c2f96dcSApple OSS Distributions int ccn_invmod_ws(cc_ws_t ws, cc_size n, cc_unit *cc_counted_by(n) r, cc_size xn, const cc_unit *cc_counted_by(xn) x, const cc_unit *cc_counted_by(n) m);
515*2c2f96dcSApple OSS Distributions
516*2c2f96dcSApple OSS Distributions /*! @function ccn_mux_seed_mask
517*2c2f96dcSApple OSS Distributions * @abstract Refreshes the internal state of the PRNG used to mask cmov/cswap
518*2c2f96dcSApple OSS Distributions * operations with a given seed.
519*2c2f96dcSApple OSS Distributions *
520*2c2f96dcSApple OSS Distributions * @discussion The seed should be of good entropy, i.e. generated by our default
521*2c2f96dcSApple OSS Distributions * RNG. This function should be called before running algorithms that
522*2c2f96dcSApple OSS Distributions * defend against side-channel attacks by using cmov/cswap. Examples
523*2c2f96dcSApple OSS Distributions * are blinded modular exponentation (for RSA, DH, or MR) and EC
524*2c2f96dcSApple OSS Distributions * scalar multiplication.
525*2c2f96dcSApple OSS Distributions *
526*2c2f96dcSApple OSS Distributions * @param seed A seed value.
527*2c2f96dcSApple OSS Distributions */
528*2c2f96dcSApple OSS Distributions void ccn_mux_seed_mask(cc_unit seed);
529*2c2f96dcSApple OSS Distributions
530*2c2f96dcSApple OSS Distributions /*! @function ccn_divmod
531*2c2f96dcSApple OSS Distributions * @abstract Computes a = q * d + r with r < d.
532*2c2f96dcSApple OSS Distributions *
533*2c2f96dcSApple OSS Distributions * @param na Length of a as a number of cc_units.
534*2c2f96dcSApple OSS Distributions * @param a The dividend a.
535*2c2f96dcSApple OSS Distributions * @param nq Length of q as a number of cc_units.
536*2c2f96dcSApple OSS Distributions * @param q The quotient q.
537*2c2f96dcSApple OSS Distributions * @param n Length of r and d as a number of cc_units.
538*2c2f96dcSApple OSS Distributions * @param r The remainder r.
539*2c2f96dcSApple OSS Distributions * @param d The divisor d.
540*2c2f96dcSApple OSS Distributions *
541*2c2f96dcSApple OSS Distributions * @return 0 on success, non-zero on failure. See cc_error.h for more details.
542*2c2f96dcSApple OSS Distributions */
543*2c2f96dcSApple OSS Distributions CC_NONNULL((2, 7)) CC_WARN_RESULT
544*2c2f96dcSApple OSS Distributions int ccn_divmod(cc_size na, const cc_unit *cc_counted_by(na) a, cc_size nq, cc_unit *cc_counted_by(nq) q, cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) d);
545*2c2f96dcSApple OSS Distributions
546*2c2f96dcSApple OSS Distributions CC_NONNULL((1, 3, 8))
547*2c2f96dcSApple OSS Distributions void ccn_divmod_ws(cc_ws_t ws, cc_size na, const cc_unit *cc_counted_by(na) a, cc_size nq, cc_unit *cc_counted_by(nq) q, cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) d);
548*2c2f96dcSApple OSS Distributions
549*2c2f96dcSApple OSS Distributions CC_NONNULL((2)) CC_SENTINEL
550*2c2f96dcSApple OSS Distributions void ccn_zero_multi(cc_size n, cc_unit *r, ...);
551*2c2f96dcSApple OSS Distributions
552*2c2f96dcSApple OSS Distributions CC_NONNULL((3, 4, 5))
553*2c2f96dcSApple OSS Distributions cc_unit ccn_add_ws(cc_ws_t ws, cc_size count, cc_unit *r, const cc_unit *s, const cc_unit *t);
554*2c2f96dcSApple OSS Distributions
555*2c2f96dcSApple OSS Distributions CC_NONNULL((3, 4, 5))
556*2c2f96dcSApple OSS Distributions cc_unit ccn_sub_ws(cc_ws_t ws, cc_size count, cc_unit *r, const cc_unit *s, const cc_unit *t);
557*2c2f96dcSApple OSS Distributions
558*2c2f96dcSApple OSS Distributions CC_NONNULL((3, 4))
559*2c2f96dcSApple OSS Distributions cc_unit ccn_add1_ws(cc_ws_t ws, cc_size n, cc_unit *r, const cc_unit *s, cc_unit v);
560*2c2f96dcSApple OSS Distributions
561*2c2f96dcSApple OSS Distributions /* s + t -> r return carry if result doesn't fit in n bits
562*2c2f96dcSApple OSS Distributions * { N bit, NT bit -> N bit NT <= N} N = n * sizeof(cc_unit) * 8 */
563*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
564*2c2f96dcSApple OSS Distributions cc_unit ccn_addn(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, cc_size nt, const cc_unit *cc_counted_by(nt) t);
565*2c2f96dcSApple OSS Distributions
566*2c2f96dcSApple OSS Distributions /* s - v -> r return 1 iff v > s return 0 otherwise.
567*2c2f96dcSApple OSS Distributions * { N bit, sizeof(cc_unit) * 8 bit -> N bit } N = n * sizeof(cc_unit) * 8 */
568*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
569*2c2f96dcSApple OSS Distributions cc_unit ccn_sub1(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, cc_unit v);
570*2c2f96dcSApple OSS Distributions
571*2c2f96dcSApple OSS Distributions /* s - t -> r return 1 iff t > s
572*2c2f96dcSApple OSS Distributions * { N bit, NT bit -> N bit NT <= N} N = n * sizeof(cc_unit) * 8 */
573*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
574*2c2f96dcSApple OSS Distributions cc_unit ccn_subn(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, cc_size nt, const cc_unit *cc_counted_by(nt) t);
575*2c2f96dcSApple OSS Distributions
576*2c2f96dcSApple OSS Distributions /* Return the number of used units after stripping leading 0 units. */
577*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
578*2c2f96dcSApple OSS Distributions cc_size ccn_n(cc_size n, const cc_unit *cc_counted_by(n)s);
579*2c2f96dcSApple OSS Distributions
580*2c2f96dcSApple OSS Distributions /* Make a ccn of size ccn_nof(nbits) units with up to nbits sized random value. */
581*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
582*2c2f96dcSApple OSS Distributions int ccn_random_bits(cc_size nbits, cc_unit *cc_unsafe_indexable r, struct ccrng_state *rng);
583*2c2f96dcSApple OSS Distributions
584*2c2f96dcSApple OSS Distributions /* Like ccn_random_bits, but uses ccrng_generate_fips under the hood. */
585*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
586*2c2f96dcSApple OSS Distributions int ccn_random_bits_fips(cc_size nbits, cc_unit *cc_unsafe_indexable r, struct ccrng_state *rng);
587*2c2f96dcSApple OSS Distributions
588*2c2f96dcSApple OSS Distributions // Joint Sparse Form recoding context for EC double-scalar multiplication.
589*2c2f96dcSApple OSS Distributions struct ccn_rjsf_state {
590*2c2f96dcSApple OSS Distributions uint8_t u[2];
591*2c2f96dcSApple OSS Distributions const cc_unit *s;
592*2c2f96dcSApple OSS Distributions const cc_unit *t;
593*2c2f96dcSApple OSS Distributions };
594*2c2f96dcSApple OSS Distributions
595*2c2f96dcSApple OSS Distributions /*! @function ccn_recode_jsf_init
596*2c2f96dcSApple OSS Distributions * @abstract Initialize Joint Sparse Form recoding for EC scalars s and t.
597*2c2f96dcSApple OSS Distributions *
598*2c2f96dcSApple OSS Distributions * @param r JSF-recoding context.
599*2c2f96dcSApple OSS Distributions * @param nbits Max. bit length of s and t.
600*2c2f96dcSApple OSS Distributions * @param s Scalar to be recoded.
601*2c2f96dcSApple OSS Distributions * @param t Scalar to be recoded.
602*2c2f96dcSApple OSS Distributions */
603*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
604*2c2f96dcSApple OSS Distributions void ccn_recode_jsf_init(struct ccn_rjsf_state *r, size_t nbits, const cc_unit *s, const cc_unit *t);
605*2c2f96dcSApple OSS Distributions
606*2c2f96dcSApple OSS Distributions /*! @function ccn_recode_jsf_column
607*2c2f96dcSApple OSS Distributions * @abstract Retrieve JSF-recoded digits for column k.
608*2c2f96dcSApple OSS Distributions *
609*2c2f96dcSApple OSS Distributions * @param r JSF-recoding context.
610*2c2f96dcSApple OSS Distributions * @param k Column index.
611*2c2f96dcSApple OSS Distributions * @param c Digits (output).
612*2c2f96dcSApple OSS Distributions */
613*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
614*2c2f96dcSApple OSS Distributions void ccn_recode_jsf_column(struct ccn_rjsf_state *r, size_t k, int c[2]);
615*2c2f96dcSApple OSS Distributions
616*2c2f96dcSApple OSS Distributions /*! @function ccn_recode_jsf_index
617*2c2f96dcSApple OSS Distributions * @abstract Retrieve the lookup table index for given column digits.
618*2c2f96dcSApple OSS Distributions *
619*2c2f96dcSApple OSS Distributions * @discussion For EC double-scalar multiplication, we assume a lookup table
620*2c2f96dcSApple OSS Distributions * holding the four values [P, Q, P+Q, P-Q], in the same order.
621*2c2f96dcSApple OSS Distributions *
622*2c2f96dcSApple OSS Distributions * @param c Column digits.
623*2c2f96dcSApple OSS Distributions *
624*2c2f96dcSApple OSS Distributions * @return The lookup table index.
625*2c2f96dcSApple OSS Distributions */
626*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL CC_WARN_RESULT
627*2c2f96dcSApple OSS Distributions size_t ccn_recode_jsf_index(int c[2]);
628*2c2f96dcSApple OSS Distributions
629*2c2f96dcSApple OSS Distributions /*! @function ccn_recode_jsf_direction
630*2c2f96dcSApple OSS Distributions * @abstract Retrieve the "direction" for given column digits.
631*2c2f96dcSApple OSS Distributions *
632*2c2f96dcSApple OSS Distributions * @discussion For EC double-scalar multiplication, we assume a lookup table
633*2c2f96dcSApple OSS Distributions * holding the four values [P, Q, P+Q, P-Q]. Negating each of
634*2c2f96dcSApple OSS Distributions * these also yields [-P, -Q, -P-Q, -P+Q].
635*2c2f96dcSApple OSS Distributions *
636*2c2f96dcSApple OSS Distributions * An EC double-and-add algorithm will either add or subtract a
637*2c2f96dcSApple OSS Distributions * precomputed point to cover all possible digit combinations of two
638*2c2f96dcSApple OSS Distributions * JSF-recoded EC scalars.
639*2c2f96dcSApple OSS Distributions *
640*2c2f96dcSApple OSS Distributions * @param c Column digits.
641*2c2f96dcSApple OSS Distributions *
642*2c2f96dcSApple OSS Distributions * @return The "direction". 1 for addition. -1 for subtraction.
643*2c2f96dcSApple OSS Distributions */
644*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL CC_WARN_RESULT
645*2c2f96dcSApple OSS Distributions int ccn_recode_jsf_direction(int c[2]);
646*2c2f96dcSApple OSS Distributions
647*2c2f96dcSApple OSS Distributions /*! @function ccn_read_le_bytes
648*2c2f96dcSApple OSS Distributions * @abstract Copies a number given as little-endian bytes into `out`.
649*2c2f96dcSApple OSS Distributions *
650*2c2f96dcSApple OSS Distributions * @param n Number of limbs of `out`.
651*2c2f96dcSApple OSS Distributions * @param in Number to parse as little-endian bytes.
652*2c2f96dcSApple OSS Distributions * @param out Output.
653*2c2f96dcSApple OSS Distributions */
654*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
655*2c2f96dcSApple OSS Distributions CC_INLINE void
ccn_read_le_bytes(cc_size n,const uint8_t * in,cc_unit * out)656*2c2f96dcSApple OSS Distributions ccn_read_le_bytes(cc_size n, const uint8_t *in, cc_unit *out)
657*2c2f96dcSApple OSS Distributions {
658*2c2f96dcSApple OSS Distributions for (cc_size i = 0; i < n; i++) {
659*2c2f96dcSApple OSS Distributions out[i] = cc_load_le(&in[i * CCN_UNIT_SIZE]);
660*2c2f96dcSApple OSS Distributions }
661*2c2f96dcSApple OSS Distributions }
662*2c2f96dcSApple OSS Distributions
663*2c2f96dcSApple OSS Distributions /*! @function ccn_write_le_bytes
664*2c2f96dcSApple OSS Distributions * @abstract Encodes a number as little-endian bytes into `out`.
665*2c2f96dcSApple OSS Distributions *
666*2c2f96dcSApple OSS Distributions * @param n Number of limbs of `in`.
667*2c2f96dcSApple OSS Distributions * @param in Number to encode as little-endian bytes.
668*2c2f96dcSApple OSS Distributions * @param out Output.
669*2c2f96dcSApple OSS Distributions */
670*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
671*2c2f96dcSApple OSS Distributions CC_INLINE void
ccn_write_le_bytes(cc_size n,const cc_unit * in,uint8_t * out)672*2c2f96dcSApple OSS Distributions ccn_write_le_bytes(cc_size n, const cc_unit *in, uint8_t *out)
673*2c2f96dcSApple OSS Distributions {
674*2c2f96dcSApple OSS Distributions for (cc_size i = 0; i < n; i++) {
675*2c2f96dcSApple OSS Distributions cc_store_le(in[i], &out[i * CCN_UNIT_SIZE]);
676*2c2f96dcSApple OSS Distributions }
677*2c2f96dcSApple OSS Distributions }
678*2c2f96dcSApple OSS Distributions
679*2c2f96dcSApple OSS Distributions /*! @function ccn_recode_ssw
680*2c2f96dcSApple OSS Distributions * @abstract Recodes a given number into signed sliding windows.
681*2c2f96dcSApple OSS Distributions *
682*2c2f96dcSApple OSS Distributions * @param n Number of limbs of `s`.
683*2c2f96dcSApple OSS Distributions * @param s Number to recode.
684*2c2f96dcSApple OSS Distributions * @param w Recode width, for windows in range (-2^w,2^w).
685*2c2f96dcSApple OSS Distributions * @param r Output for the computed signed sliding windows.
686*2c2f96dcSApple OSS Distributions */
687*2c2f96dcSApple OSS Distributions CC_NONNULL_ALL
688*2c2f96dcSApple OSS Distributions void ccn_recode_ssw(cc_size n, const cc_unit *s, int w, int8_t *r);
689*2c2f96dcSApple OSS Distributions
690*2c2f96dcSApple OSS Distributions #endif // _CORECRYPTO_CCN_INTERNAL_H
691