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