xref: /xnu-10002.81.5/EXTERNAL_HEADERS/corecrypto/ccn.h (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1 /* Copyright (c) (2010-2021) Apple Inc. All rights reserved.
2  *
3  * corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
4  * is contained in the License.txt file distributed with corecrypto) and only to
5  * people who accept that license. IMPORTANT:  Any license rights granted to you by
6  * Apple Inc. (if any) are limited to internal use within your organization only on
7  * devices and computers you own or control, for the sole purpose of verifying the
8  * security characteristics and correct functioning of the Apple Software.  You may
9  * not, directly or indirectly, redistribute the Apple Software or any portions thereof.
10  */
11 
12 #ifndef _CORECRYPTO_CCN_H_
13 #define _CORECRYPTO_CCN_H_
14 
15 #include <corecrypto/cc.h>
16 #include <stdint.h>
17 #include <stdarg.h>
18 
19 CC_PTRCHECK_CAPABLE_HEADER()
20 
21 typedef uint8_t cc_byte;
22 typedef size_t  cc_size;
23 
24 #if CCN_UNIT_SIZE == 8
25 typedef uint64_t cc_unit;          // 64 bit unit
26 typedef int64_t  cc_int;
27 #define CCN_LOG2_BITS_PER_UNIT  6  // 2^6 = 64 bits
28 #define CC_UNIT_C(x) UINT64_C(x)
29 #elif CCN_UNIT_SIZE == 4
30 typedef uint32_t cc_unit;          // 32 bit unit
31 typedef int32_t cc_int;
32 #define CCN_LOG2_BITS_PER_UNIT  5  // 2^5 = 32 bits
33 #define CC_UNIT_C(x) UINT32_C(x)
34 
35 #else
36 #error Unsupported CCN_UNIT_SIZE
37 #endif
38 
39 #define CCN_UNIT_BITS  (sizeof(cc_unit) * 8)
40 #define CCN_UNIT_MASK  ((cc_unit)~0)
41 #define CCN_UNIT_LOWER_HALF_MASK  ((CCN_UNIT_MASK) >> (CCN_UNIT_BITS/2))
42 #define CCN_UNIT_UPPER_HALF_MASK  (~CCN_UNIT_LOWER_HALF_MASK)
43 #define CCN_UNIT_HALF_BITS (CCN_UNIT_BITS / 2)
44 
45 /* Conversions between n sizeof and bits */
46 
47 /* Returns the sizeof a ccn vector of length _n_ units. */
48 #define ccn_sizeof_n(_n_)  (sizeof(cc_unit) * (_n_))
49 
50 /* Returns the count (n) of a ccn vector that can represent _bits_. */
51 #define ccn_nof(_bits_)  (((_bits_) + CCN_UNIT_BITS - 1) >> CCN_LOG2_BITS_PER_UNIT)
52 
53 /* Returns the sizeof a ccn vector that can represent _bits_. */
54 #define ccn_sizeof(_bits_)  (ccn_sizeof_n(ccn_nof(_bits_)))
55 
56 /* Returns the count (n) of a ccn vector that can represent _size_ bytes. */
57 #define ccn_nof_size(_size_)  (((_size_) + sizeof(cc_unit) - 1) / sizeof(cc_unit))
58 
59 #define ccn_nof_sizeof(_expr_) ccn_nof_size(sizeof(_expr_))
60 
61 /* Return the max number of bits a ccn vector of _n_ units can hold. */
62 #define ccn_bitsof_n(_n_)  ((_n_) * CCN_UNIT_BITS)
63 
64 /* Return the max number of bits a ccn vector of _size_ bytes can hold. */
65 #define ccn_bitsof_size(_size_)  ((_size_) * 8)
66 
67 /* Return the size of a ccn of size bytes in bytes. */
68 #define ccn_sizeof_size(_size_)  ccn_sizeof_n(ccn_nof_size(_size_))
69 
70 /* Returns the value of bit _k_ of _ccn_, both are only evaluated once.  */
ccn_bit(const cc_unit * cc_indexable x,size_t k)71 CC_INLINE cc_unit ccn_bit(const cc_unit *cc_indexable x, size_t k)
72 {
73     return 1 & (x[k >> CCN_LOG2_BITS_PER_UNIT] >> (k & (CCN_UNIT_BITS - 1)));
74 }
75 
76 /* Set the value of bit _k_ of _ccn_ to the value _v_  */
ccn_set_bit(cc_unit * cc_indexable x,size_t k,cc_unit v)77 CC_INLINE void ccn_set_bit(cc_unit *cc_indexable x, size_t k, cc_unit v)
78 {
79     if (v) {
80         x[k >> CCN_LOG2_BITS_PER_UNIT] |= (cc_unit)1 << (k & (CCN_UNIT_BITS - 1));
81     } else {
82         x[k >> CCN_LOG2_BITS_PER_UNIT] &= ~((cc_unit)1 << (k & (CCN_UNIT_BITS - 1)));
83     }
84 }
85 
86 /* Macros for making ccn constants.  You must use list of CCN64_C() instances
87  separated by commas, with an optional smaller sized CCN32_C, CCN16_C, or
88  CCN8_C() instance at the end of the list, when making macros to declare
89  larger sized constants. */
90 #define CCN8_C(a0) CC_UNIT_C(0x##a0)
91 
92 #define CCN16_C(a1,a0) CC_UNIT_C(0x##a1##a0)
93 #define ccn16_v(a0)  (a0)
94 
95 #define CCN32_C(a3,a2,a1,a0) CC_UNIT_C(0x##a3##a2##a1##a0)
96 #define ccn32_v(a0)  (a0)
97 
98 #if CCN_UNIT_SIZE == 8
99 #define CCN64_C(a7,a6,a5,a4,a3,a2,a1,a0) CC_UNIT_C(0x##a7##a6##a5##a4##a3##a2##a1##a0)
100 #define CCN40_C(a4,a3,a2,a1,a0) CC_UNIT_C(0x##a4##a3##a2##a1##a0)
101 #define ccn64_v(a0)  (a0)
102 #else
103 #define CCN64_C(a7,a6,a5,a4,a3,a2,a1,a0) CCN32_C(a3,a2,a1,a0),CCN32_C(a7,a6,a5,a4)
104 #define CCN40_C(a4,a3,a2,a1,a0) CCN32_C(a3,a2,a1,a0),CCN8_C(a4)
105 #define ccn64_v(a0)  ccn32_v((uint64_t)a0 & UINT32_C(0xffffffff)),ccn32_v((uint64_t)a0 >> 32)
106 #endif
107 
108 /* Macro's for reading uint32_t and uint64_t from ccns, the index is in 32 or
109  64 bit units respectively. */
110 #if CCN_UNIT_SIZE == 8
111 
112 #define ccn64_32(a1,a0) (((const cc_unit)a1) << 32 | ((const cc_unit)a0))
113 #define ccn32_32(a0) a0
114 #if __LITTLE_ENDIAN__
115 #define ccn32_32_parse(p,i) (((const uint32_t *)p)[i])
116 #else
117 #define ccn32_32_parse(p,i) (((const uint32_t *)p)[i^1])
118 #endif
119 #define ccn32_32_null 0
120 
121 #define ccn64_64(a0) a0
122 #define ccn64_64_parse(p,i) p[i]
123 #define ccn64_64_null 0
124 
125 #elif CCN_UNIT_SIZE == 4
126 
127 #define ccn32_32(a0) a0
128 #define ccn32_32_parse(p,i) p[i]
129 #define ccn32_32_null 0
130 #define ccn64_32(a1,a0) ccn32_32(a0),ccn32_32(a1)
131 
132 #define ccn64_64(a1,a0) a0,a1
133 #define ccn64_64_parse(p,i) p[1+(i<<1)],p[i<<1]
134 #define ccn64_64_null 0,0
135 
136 #endif
137 
138 
139 /* Macros to construct fixed size ccn arrays from 64 or 32 bit quantities. */
140 #define ccn192_64(a2,a1,a0) ccn64_64(a0),ccn64_64(a1),ccn64_64(a2)
141 #define ccn192_32(a5,a4,a3,a2,a1,a0) ccn64_32(a1,a0),ccn64_32(a3,a2),ccn64_32(a5,a4)
142 #define ccn224_32(a6,a5,a4,a3,a2,a1,a0) ccn64_32(a1,a0),ccn64_32(a3,a2),ccn64_32(a5,a4),ccn32_32(a6)
143 #define ccn256_32(a7,a6,a5,a4,a3,a2,a1,a0) ccn64_32(a1,a0),ccn64_32(a3,a2),ccn64_32(a5,a4),ccn64_32(a7,a6)
144 #define ccn384_32(a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0) ccn64_32(a1,a0),ccn64_32(a3,a2),ccn64_32(a5,a4),ccn64_32(a7,a6),ccn64_32(a9,a8),ccn64_32(a11,a10)
145 
146 
147 #define CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
148     CCN64_C(a7,a6,a5,a4,a3,a2,a1,a0),\
149     CCN64_C(b7,b6,b5,b4,b3,b2,b1,b0),\
150     CCN64_C(c7,c6,c5,c4,c3,c2,c1,c0)
151 
152 #define CCN200_C(d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
153     CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
154     CCN8_C(d0)
155 
156 #define CCN224_C(d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
157     CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
158     CCN32_C(d3,d2,d1,d0)
159 
160 #define CCN232_C(d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
161     CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
162     CCN40_C(d4,d3,d2,d1,d0)
163 
164 #define CCN256_C(d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
165     CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
166     CCN64_C(d7,d6,d5,d4,d3,d2,d1,d0)
167 
168 #define CCN384_C(f7,f6,f5,f4,f3,f2,f1,f0,e7,e6,e5,e4,e3,e2,e1,e0,d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
169     CCN256_C(d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
170     CCN64_C(e7,e6,e5,e4,e3,e2,e1,e0),\
171     CCN64_C(f7,f6,f5,f4,f3,f2,f1,f0)
172 
173 #define CCN528_C(i1,i0,h7,h6,h5,h4,h3,h2,h1,h0,g7,g6,g5,g4,g3,g2,g1,g0,f7,f6,f5,f4,f3,f2,f1,f0,e7,e6,e5,e4,e3,e2,e1,e0,d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
174     CCN256_C(d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
175     CCN256_C(h7,h6,h5,h4,h3,h2,h1,h0,g7,g6,g5,g4,g3,g2,g1,g0,f7,f6,f5,f4,f3,f2,f1,f0,e7,e6,e5,e4,e3,e2,e1,e0),\
176     CCN16_C(i1,i0)
177 
178 #define CCN192_N  ccn_nof(192)
179 #define CCN224_N  ccn_nof(224)
180 #define CCN256_N  ccn_nof(256)
181 #define CCN384_N  ccn_nof(384)
182 #define CCN512_N  ccn_nof(512)
183 #define CCN521_N  ccn_nof(521)
184 
185 /* Return the number of used units after stripping leading 0 units.  */
186 CC_PURE CC_NONNULL((2))
187 cc_size ccn_n(cc_size n, const cc_unit *cc_counted_by(n) s) __asm__("_ccn_n");
188 
189 /*! @function ccn_shift_right
190  @abstract Shifts s to the right by k bits, where 0 <= k < CCN_UNIT_BITS.
191 
192  @param n Length of r and s
193  @param r Resulting big int.
194  @param s Big int to shift.
195  @param k Number of bits to shift by.
196  */
197 CC_NONNULL_ALL
198 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");
199 
200 /* s == 0 -> return 0 | s > 0 -> return index (starting at 1) of most
201  * significant bit that is 1.
202  * { N bit } N = n * sizeof(cc_unit) * 8
203  *
204  * Runs in constant time, independent of the value of `s`.
205  */
206 CC_NONNULL((2))
207 size_t ccn_bitlen(cc_size n, const cc_unit *cc_counted_by(n) s);
208 
209 /* s == 0 -> return true | s != 0 -> return false
210  { N bit } N = n * sizeof(cc_unit) * 8 */
211 #define ccn_is_zero(_n_, _s_) (!ccn_n(_n_, _s_))
212 
213 /* s == 1 -> return true | s != 1 -> return false
214  { N bit } N = n * sizeof(cc_unit) * 8 */
215 #define ccn_is_one(_n_, _s_) (ccn_n(_n_, _s_) == 1 && _s_[0] == 1)
216 
217 #define ccn_is_zero_or_one(_n_, _s_) (((_n_)==0) || ((ccn_n(_n_, _s_) <= 1) && (_s_[0] <= 1)))
218 
219 /* s < t -> return - 1 | s == t -> return 0 | s > t -> return 1
220  { N bit, N bit -> int } N = n * sizeof(cc_unit) * 8 */
221 CC_PURE CC_NONNULL((2, 3))
222 int ccn_cmp(cc_size n, const cc_unit *cc_counted_by(n) s, const cc_unit *cc_counted_by(n) t) __asm__("_ccn_cmp");
223 
224 /*! @function ccn_cmpn
225  @abstract Compares the values of two big ints of different lengths.
226 
227  @discussion The execution time does not depend on the values of either s or t.
228              The function does not hide ns, nt, or whether ns > nt.
229 
230  @param ns  Length of s
231  @param s   First integer
232  @param nt  Length of t
233  @param t   Second integer
234 
235  @return 1 if s > t, -1 if s < t, 0 otherwise.
236  */
237 CC_NONNULL_ALL
238 int ccn_cmpn(cc_size ns, const cc_unit *cc_counted_by(ns) s, cc_size nt, const cc_unit *cc_counted_by(nt) t);
239 
240 /* s - t -> r return 1 iff t > s
241  { N bit, N bit -> N bit } N = n * sizeof(cc_unit) * 8 */
242 CC_NONNULL((2, 3, 4))
243 cc_unit ccn_sub(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) __asm__("_ccn_sub");
244 
245 /* s - v -> r return 1 iff v > s return 0 otherwise.
246  { N bit, sizeof(cc_unit) * 8 bit -> N bit } N = n * sizeof(cc_unit) * 8 */
247 CC_NONNULL((2, 3))
248 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);
249 
250 /* s - t -> r return 1 iff t > s
251  { N bit, NT bit -> N bit  NT <= N} N = n * sizeof(cc_unit) * 8 */
252 CC_INLINE
253 CC_NONNULL((2, 3, 5))
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)254 cc_unit ccn_subn(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s,
255              cc_size nt, const cc_unit *cc_counted_by(nt) t) {
256     assert(n >= nt);
257     return ccn_sub1(n - nt, r + nt, s + nt, ccn_sub(nt, r, s, t));
258 }
259 
260 
261 /* s + t -> r return carry if result doesn't fit in n bits.
262  { N bit, N bit -> N bit } N = n * sizeof(cc_unit) * 8 */
263 CC_NONNULL((2, 3, 4))
264 cc_unit ccn_add(cc_size n, cc_unit *cc_sized_by(n) r, const cc_unit *cc_sized_by(n) s, const cc_unit *cc_sized_by(n) t) __asm__("_ccn_add");
265 
266 /* s + v -> r return carry if result doesn't fit in n bits.
267  { N bit, sizeof(cc_unit) * 8 bit -> N bit } N = n * sizeof(cc_unit) * 8 */
268 CC_NONNULL((2, 3))
269 cc_unit ccn_add1(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, cc_unit v);
270 
271 /* s + t -> r return carry if result doesn't fit in n bits
272  { N bit, NT bit -> N bit  NT <= N} N = n * sizeof(cc_unit) * 8 */
273 CC_INLINE
274 CC_NONNULL((2, 3, 5))
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)275 cc_unit ccn_addn(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s,
276                  cc_size nt, const cc_unit *cc_counted_by(nt) t) {
277     assert(n >= nt);
278     return ccn_add1(n - nt, r + nt, s + nt, ccn_add(nt, r, s, t));
279 }
280 
281 
282 /*!
283  @function   ccn_read_uint
284  @abstract   Copy big endian integer and represent it in cc_units
285 
286  @param n           Input allocated size of the cc_unit output array r
287  @param r           Ouput cc_unit array for unsigned integer
288  @param data_nbytes Input byte size of data
289  @param data        Input unsigned integer represented in big endian
290 
291  @result r is initialized with the big unsigned number
292 
293  @return 0 if no error, !=0 if the big number cannot be represented in the allocated cc_unit array.
294 
295  @discussion The execution pattern of this function depends on both n and data_nbytes but not on data values except the handling
296  of the error case.
297  */
298 
299 CC_NONNULL((2, 4))
300 int ccn_read_uint(cc_size n, cc_unit *cc_counted_by(n) r, size_t data_nbytes, const uint8_t *cc_sized_by(data_nbytes) data);
301 
302 /* r = (data, len) treated as a big endian byte array, return -1 if data
303  doesn't fit in r, return 0 otherwise.
304  ccn_read_uint strips leading zeroes and doesn't care about sign. */
305 #define ccn_read_int(n, r, data_size, data) ccn_read_uint(n, r, data_size, data)
306 
307 /*!
308  @function   ccn_write_uint_size
309  @abstract   Compute the minimum size required to store an big integer
310 
311  @param n           Input size of the cc_unit array representing the input
312  @param s           Input cc_unit array
313 
314  @result Return value is the exact byte size of the big integer
315 
316  @discussion
317  The execution flow is independent on the value of the big integer.
318  However, the use of the returned value may leak the position of the most significant byte
319  */
320 CC_PURE CC_NONNULL((2)) size_t ccn_write_uint_size(cc_size n, const cc_unit *cc_counted_by(n) s);
321 
322 /*!
323  @function   ccn_write_uint
324  @abstract   Serialize the big integer into a big endian byte buffer
325 
326  @param n           Input size of the cc_unit array representing the input
327  @param s           Input cc_unit array
328  @param out_size    Size of the output buffer
329  @param out         Output byte array of size at least  out_size
330 
331  @discussion This function writes exactly
332  MIN(out_size,ccn_write_uint_size(n,s)) bytes truncating to keep the
333  most significant bytes when out_size<ccn_write_uint_size(n,s). The
334  execution flow of function is based on the position of the most
335  significant byte as well as input sizes.
336 
337  */
338 
339 CC_NONNULL((2, 4))
340 void ccn_write_uint(cc_size n, const cc_unit *cc_counted_by(n) s, size_t out_size, void *cc_sized_by(out_size) out);
341 
342 /*!
343  @function   ccn_write_uint_padded_ct
344  @abstract   Serialize the big integer into a big endian byte buffer
345 
346  @param n           Input size of the cc_unit array representing the input
347  @param s           Input cc_unit array
348  @param out_size    Size of the output buffer
349  @param out         Output byte array of size at least  out_size
350 
351  @return number of leading zero bytes in case of success, a negative error value in case of failure
352 
353  @result  This function writes exactly out_size byte, padding with zeroes when necessary.
354  This function DOES NOT support truncation and returns an error if out_size < ccn_write_uint_size
355 
356  @discussion The execution flow of function is independent on the value of the big integer
357  However, the processing of the return value by the caller may expose the position of
358  the most significant byte
359  */
360 CC_NONNULL((2, 4))
361 int ccn_write_uint_padded_ct(cc_size n, const cc_unit *cc_sized_by(n) s, size_t out_size, uint8_t *cc_counted_by(out_size) out);
362 
363 /*!
364  @function   ccn_write_uint_padded
365  @abstract   Serialize the big integer into a big endian byte buffer
366  Not recommended, for most cases ccn_write_uint_padded_ct is more appropriate
367  Sensitive big integers are exposed since the processing expose the position of the MS byte
368 
369  @param n           Input size of the cc_unit array representing the input
370  @param s           Input cc_unit array
371  @param out_size    Size of the output buffer
372  @param out         Output byte array of size at least  out_size
373 
374  @return number of leading zero bytes
375 
376  @result  This function writes exactly out_size byte, padding with zeroes when necessary.
377  This function DOES support truncation when out_size<ccn_write_uint_size()
378 
379  @discussion The execution flow of this function DEPENDS on the position of the most significant byte in
380  case truncation is required.
381  */
382 
ccn_write_uint_padded(cc_size n,const cc_unit * cc_counted_by (n)s,size_t out_size,uint8_t * cc_sized_by (out_size)out)383 CC_INLINE CC_NONNULL((2, 4)) size_t ccn_write_uint_padded(cc_size n, const cc_unit *cc_counted_by(n) s, size_t out_size, uint8_t *cc_sized_by(out_size) out)
384 {
385     size_t offset = 0;
386     // Try first the non-truncation case
387     int offset_int = ccn_write_uint_padded_ct(n, s, out_size, out);
388     if (offset_int >= 0) {
389         // It worked
390         offset = (size_t)offset_int;
391     } else {
392         // Truncation case, execution depends on the position of the MSByte
393         ccn_write_uint(n, s, out_size, out);
394     }
395     return offset;
396 }
397 
398 
399 /*  Return actual size in bytes needed to serialize s as int
400     (adding leading zero if high bit is set). */
401 CC_PURE CC_NONNULL((2))
402 size_t ccn_write_int_size(cc_size n, const cc_unit *cc_counted_by(n) s);
403 
404 /*  Serialize s, to out.
405     First byte of byte stream is the m.s. byte of s,
406     regardless of the size of cc_unit.
407 
408     No assumption is made about the alignment of out.
409 
410     The out_size argument should be the value returned from ccn_write_int_size,
411     and is also the exact number of bytes this function will write to out.
412     If out_size if less than the value returned by ccn_write_int_size, only the
413     first out_size non-zero most significant octets of s will be written. */
414 CC_NONNULL((2, 4))
415 void ccn_write_int(cc_size n, const cc_unit *cc_counted_by(n) s, size_t out_size, void *cc_sized_by(out_size) out);
416 
417 /* s -> r
418  { n bit -> n bit } */
419 CC_NONNULL((2, 3))
420 void ccn_set(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s);
421 
422 CC_INLINE CC_NONNULL((2))
ccn_zero(cc_size n,cc_unit * cc_sized_by (n)r)423 void ccn_zero(cc_size n, cc_unit *cc_sized_by(n) r) {
424     cc_clear(ccn_sizeof_n(n),r);
425 }
426 
427 CC_INLINE CC_NONNULL((2))
ccn_clear(cc_size n,cc_unit * cc_sized_by (n)r)428 void ccn_clear(cc_size n, cc_unit *cc_sized_by(n) r) {
429     cc_clear(ccn_sizeof_n(n),r);
430 }
431 
432 CC_NONNULL((2))
433 void ccn_zero_multi(cc_size n, cc_unit *cc_counted_by(n) r, ...) CC_SENTINEL;
434 
435 CC_INLINE CC_NONNULL((2))
ccn_seti(cc_size n,cc_unit * cc_counted_by (n)r,cc_unit v)436 void ccn_seti(cc_size n, cc_unit *cc_counted_by(n) r, cc_unit v) {
437     assert(n > 0);
438     r[0] = v;
439     ccn_zero(n - 1, r + 1);
440 }
441 
442 CC_INLINE CC_NONNULL((2, 4))
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)443 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) {
444     assert(n > 0);
445     assert(s_size <= n);
446     if (s_size > 0) {
447         ccn_set(s_size, r, s);
448     }
449     ccn_zero(n - s_size, r + s_size);
450 }
451 
452 #define CC_SWAP_HOST_BIG_64(x) \
453     ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
454     (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
455     (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
456     (((uint64_t)(x) & 0x000000ff00000000ULL) >>  8) | \
457     (((uint64_t)(x) & 0x00000000ff000000ULL) <<  8) | \
458     (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
459     (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
460     (((uint64_t)(x) & 0x00000000000000ffULL) << 56)))
461 #define CC_SWAP_HOST_BIG_32(x) \
462     ((((x) & 0xff000000) >> 24) | \
463     (((x) & 0x00ff0000) >>  8) | \
464     (((x) & 0x0000ff00) <<  8) | \
465     (((x) & 0x000000ff) <<  24))
466 #define CC_SWAP_HOST_BIG_16(x) \
467     ((((x) & 0xff00) >>  8) | \
468     (((x) & 0x00ff) <<  8))
469 
470 /* This should probably move if we move ccn_swap out of line. */
471 #if CCN_UNIT_SIZE == 8
472 #define CC_UNIT_TO_BIG(x) CC_SWAP_HOST_BIG_64(x)
473 #elif CCN_UNIT_SIZE == 4
474 #define CC_UNIT_TO_BIG(x) CC_SWAP_HOST_BIG_32(x)
475 #else
476 #error Unsupported CCN_UNIT_SIZE
477 #endif
478 
479 /* Swap units in r in place from cc_unit vector byte order to big endian byte order (or back). */
480 CC_INLINE CC_NONNULL((2))
ccn_swap(cc_size n,cc_unit * cc_counted_by (n)r)481 void ccn_swap(cc_size n, cc_unit *cc_counted_by(n) r) {
482     cc_unit *local_r = r;
483     cc_unit *e;
484     for (e = local_r + n - 1; local_r < e; ++local_r, --e) {
485         cc_unit t = CC_UNIT_TO_BIG(*local_r);
486         *local_r = CC_UNIT_TO_BIG(*e);
487         *e = t;
488     }
489     if (n & 1)
490         *local_r = CC_UNIT_TO_BIG(*local_r);
491 }
492 
493 CC_INLINE CC_NONNULL((2, 3, 4))
ccn_xor(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)494 void ccn_xor(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) {
495     cc_size _n = n;
496     while (_n--) {
497         r[_n] = s[_n] ^ t[_n];
498     }
499 }
500 
501 /* Debugging */
502 CC_NONNULL((2))
503 void ccn_print(cc_size n, const cc_unit *cc_counted_by(n) s);
504 CC_NONNULL((3))
505 void ccn_lprint(cc_size n, const char *cc_cstring label, const cc_unit *cc_counted_by(n) s);
506 
507 /* Forward declaration so we don't depend on ccrng.h. */
508 struct ccrng_state;
509 
510 #if 0
511 CC_INLINE CC_NONNULL((2, 3))
512 int ccn_random(cc_size n, cc_unit *cc_counted_by(n) r, struct ccrng_state *rng) {
513     return (RNG)->generate((RNG), ccn_sizeof_n(n), (unsigned char *)r);
514 }
515 #else
516 #define ccn_random(_n_,_r_,_ccrng_ctx_) \
517     ccrng_generate(_ccrng_ctx_, ccn_sizeof_n(_n_), (unsigned char *)_r_)
518 #endif
519 
520 /* Make a ccn of size ccn_nof(nbits) units with up to nbits sized random value. */
521 CC_NONNULL((2, 3))
522 int ccn_random_bits(cc_size nbits, cc_unit *cc_unsafe_indexable r, struct ccrng_state *rng);
523 
524 #endif /* _CORECRYPTO_CCN_H_ */
525