xref: /xnu-10063.121.3/osfmk/corecrypto/cc_internal.h (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1*2c2f96dcSApple OSS Distributions /* Copyright (c) (2019,2021-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_CC_INTERNAL_H_
37*2c2f96dcSApple OSS Distributions #define _CORECRYPTO_CC_INTERNAL_H_
38*2c2f96dcSApple OSS Distributions 
39*2c2f96dcSApple OSS Distributions #include <corecrypto/cc_priv.h>
40*2c2f96dcSApple OSS Distributions #include "cc_runtime_config.h"
41*2c2f96dcSApple OSS Distributions 
42*2c2f96dcSApple OSS Distributions #if CC_XNU_KERNEL_PRIVATE
43*2c2f96dcSApple OSS Distributions #elif CC_EFI
44*2c2f96dcSApple OSS Distributions #elif CC_KERNEL
45*2c2f96dcSApple OSS Distributions #include <libkern/libkern.h>
46*2c2f96dcSApple OSS Distributions #else
47*2c2f96dcSApple OSS Distributions #include <stdlib.h>
48*2c2f96dcSApple OSS Distributions #include <stdio.h>
49*2c2f96dcSApple OSS Distributions #endif
50*2c2f96dcSApple OSS Distributions 
51*2c2f96dcSApple OSS Distributions #include <stdarg.h>
52*2c2f96dcSApple OSS Distributions 
53*2c2f96dcSApple OSS Distributions #include "cc_macros.h"
54*2c2f96dcSApple OSS Distributions 
55*2c2f96dcSApple OSS Distributions #if CC_EFI
56*2c2f96dcSApple OSS Distributions #include "cc_efi_shim.h"
57*2c2f96dcSApple OSS Distributions int cc_memcmp(const void *buf1, const void *buf2, size_t len);
58*2c2f96dcSApple OSS Distributions #else
59*2c2f96dcSApple OSS Distributions     #define cc_memcmp(buf1, buf2, len) memcmp(buf1, buf2, len)
60*2c2f96dcSApple OSS Distributions #endif
61*2c2f96dcSApple OSS Distributions 
62*2c2f96dcSApple OSS Distributions extern bool cc_rdrand(uint64_t *rand);
63*2c2f96dcSApple OSS Distributions 
64*2c2f96dcSApple OSS Distributions #if CC_BUILT_FOR_TESTING
65*2c2f96dcSApple OSS Distributions extern bool (*cc_rdrand_mock)(uint64_t *rand);
66*2c2f96dcSApple OSS Distributions 
67*2c2f96dcSApple OSS Distributions extern void (*cc_abort_mock)(const char *msg);
68*2c2f96dcSApple OSS Distributions #endif
69*2c2f96dcSApple OSS Distributions 
70*2c2f96dcSApple OSS Distributions 
71*2c2f96dcSApple OSS Distributions #if CC_DIT_MAYBE_SUPPORTED
72*2c2f96dcSApple OSS Distributions 
73*2c2f96dcSApple OSS Distributions // Use the DIT register's encoded name to avoid assembler
74*2c2f96dcSApple OSS Distributions // complaints when compiling for ARM64 before v8.4.
75*2c2f96dcSApple OSS Distributions #define CC_DIT_REGISTER "s3_3_c4_c2_5"
76*2c2f96dcSApple OSS Distributions 
77*2c2f96dcSApple OSS Distributions #define CC_DIT_BIT (1U << 24)
78*2c2f96dcSApple OSS Distributions 
79*2c2f96dcSApple OSS Distributions CC_INLINE bool
cc_is_dit_enabled(void)80*2c2f96dcSApple OSS Distributions cc_is_dit_enabled(void)
81*2c2f96dcSApple OSS Distributions {
82*2c2f96dcSApple OSS Distributions 	return __builtin_arm_rsr64(CC_DIT_REGISTER) & CC_DIT_BIT;
83*2c2f96dcSApple OSS Distributions }
84*2c2f96dcSApple OSS Distributions 
85*2c2f96dcSApple OSS Distributions CC_INLINE bool
cc_enable_dit(void)86*2c2f96dcSApple OSS Distributions cc_enable_dit(void)
87*2c2f96dcSApple OSS Distributions {
88*2c2f96dcSApple OSS Distributions 	if (!CC_HAS_DIT()) {
89*2c2f96dcSApple OSS Distributions 		return false;
90*2c2f96dcSApple OSS Distributions 	}
91*2c2f96dcSApple OSS Distributions 
92*2c2f96dcSApple OSS Distributions 	// DIT might have already been enabled by another corecrypto function, in
93*2c2f96dcSApple OSS Distributions 	// that case that function is responsible for disabling DIT when returning.
94*2c2f96dcSApple OSS Distributions 	//
95*2c2f96dcSApple OSS Distributions 	// This also covers when code _outside_ corecrypto enabled DIT before
96*2c2f96dcSApple OSS Distributions 	// calling us. In that case we're not responsible for disabling it either.
97*2c2f96dcSApple OSS Distributions 	if (cc_is_dit_enabled()) {
98*2c2f96dcSApple OSS Distributions 		return false;
99*2c2f96dcSApple OSS Distributions 	}
100*2c2f96dcSApple OSS Distributions 
101*2c2f96dcSApple OSS Distributions 	// Encoding of <msr dit, #1>.
102*2c2f96dcSApple OSS Distributions 	__asm__ __volatile__ (".long 0xd503415f");
103*2c2f96dcSApple OSS Distributions 
104*2c2f96dcSApple OSS Distributions #if CC_BUILT_FOR_TESTING
105*2c2f96dcSApple OSS Distributions 	// Check that DIT was enabled.
106*2c2f96dcSApple OSS Distributions 	cc_try_abort_if(!cc_is_dit_enabled(), "DIT not enabled");
107*2c2f96dcSApple OSS Distributions #endif
108*2c2f96dcSApple OSS Distributions 
109*2c2f96dcSApple OSS Distributions 	// To the cleanup function, indicate that we toggled DIT and
110*2c2f96dcSApple OSS Distributions 	// that cc_disable_dit() should actually disable it again.
111*2c2f96dcSApple OSS Distributions 	return true;
112*2c2f96dcSApple OSS Distributions }
113*2c2f96dcSApple OSS Distributions 
114*2c2f96dcSApple OSS Distributions void cc_disable_dit(volatile bool *cc_unsafe_indexable dit_was_enabled);
115*2c2f96dcSApple OSS Distributions 
116*2c2f96dcSApple OSS Distributions #define CC_ENSURE_DIT_ENABLED                    \
117*2c2f96dcSApple OSS Distributions     volatile bool _cc_dit_auto_disable           \
118*2c2f96dcSApple OSS Distributions 	__attribute__((cleanup(cc_disable_dit))) \
119*2c2f96dcSApple OSS Distributions 	__attribute__((unused)) = cc_enable_dit();
120*2c2f96dcSApple OSS Distributions 
121*2c2f96dcSApple OSS Distributions #else
122*2c2f96dcSApple OSS Distributions 
123*2c2f96dcSApple OSS Distributions #define CC_ENSURE_DIT_ENABLED
124*2c2f96dcSApple OSS Distributions 
125*2c2f96dcSApple OSS Distributions #endif // CC_DIT_MAYBE_SUPPORTED
126*2c2f96dcSApple OSS Distributions 
127*2c2f96dcSApple OSS Distributions /*!
128*2c2f96dcSApple OSS Distributions  *  @function cc_is_vmm_present
129*2c2f96dcSApple OSS Distributions  *  @abstract Determine if corecrypto is running in a VM
130*2c2f96dcSApple OSS Distributions  *
131*2c2f96dcSApple OSS Distributions  *  @return True iff running in a VM; false otherwise
132*2c2f96dcSApple OSS Distributions  *
133*2c2f96dcSApple OSS Distributions  *  @discussion This function merely checks the relevant sysctl, which
134*2c2f96dcSApple OSS Distributions  *  may not be accurate. Thus, it should not be used to make any
135*2c2f96dcSApple OSS Distributions  *  security decisions.
136*2c2f96dcSApple OSS Distributions  */
137*2c2f96dcSApple OSS Distributions extern bool cc_is_vmm_present(void);
138*2c2f96dcSApple OSS Distributions 
139*2c2f96dcSApple OSS Distributions /*!
140*2c2f96dcSApple OSS Distributions  *  @function cc_current_arch
141*2c2f96dcSApple OSS Distributions  *  @abstract The architecture loaded in the current process
142*2c2f96dcSApple OSS Distributions  *
143*2c2f96dcSApple OSS Distributions  *  @return A string representation of the current architecture or
144*2c2f96dcSApple OSS Distributions  *  "unknown"
145*2c2f96dcSApple OSS Distributions  */
146*2c2f96dcSApple OSS Distributions extern const char *cc_current_arch(void);
147*2c2f96dcSApple OSS Distributions 
148*2c2f96dcSApple OSS Distributions // MARK: - popcount
149*2c2f96dcSApple OSS Distributions 
150*2c2f96dcSApple OSS Distributions /// Count number of bits set
151*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_popcount32_fallback(uint32_t v)152*2c2f96dcSApple OSS Distributions cc_popcount32_fallback(uint32_t v)
153*2c2f96dcSApple OSS Distributions {
154*2c2f96dcSApple OSS Distributions 	v = v - ((v >> 1) & 0x55555555);
155*2c2f96dcSApple OSS Distributions 	v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
156*2c2f96dcSApple OSS Distributions 	return ((v + (v >> 4) & 0xf0f0f0f) * 0x1010101) >> 24;
157*2c2f96dcSApple OSS Distributions }
158*2c2f96dcSApple OSS Distributions 
159*2c2f96dcSApple OSS Distributions /// Count number of bits set
160*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_popcount64_fallback(uint64_t v)161*2c2f96dcSApple OSS Distributions cc_popcount64_fallback(uint64_t v)
162*2c2f96dcSApple OSS Distributions {
163*2c2f96dcSApple OSS Distributions 	v = v - ((v >> 1) & 0x5555555555555555);
164*2c2f96dcSApple OSS Distributions 	v = (v & 0x3333333333333333) + ((v >> 2) & 0x3333333333333333);
165*2c2f96dcSApple OSS Distributions 	v = (v + (v >> 4)) & 0xf0f0f0f0f0f0f0f;
166*2c2f96dcSApple OSS Distributions 	return (v * 0x101010101010101) >> 56;
167*2c2f96dcSApple OSS Distributions }
168*2c2f96dcSApple OSS Distributions 
169*2c2f96dcSApple OSS Distributions /// Count number of bits set
170*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_popcount32(uint32_t data)171*2c2f96dcSApple OSS Distributions cc_popcount32(uint32_t data)
172*2c2f96dcSApple OSS Distributions {
173*2c2f96dcSApple OSS Distributions #if __has_builtin(__builtin_popcount)
174*2c2f96dcSApple OSS Distributions 	return (unsigned)__builtin_popcount(data);
175*2c2f96dcSApple OSS Distributions #else
176*2c2f96dcSApple OSS Distributions 	return cc_popcount32_fallback(data);
177*2c2f96dcSApple OSS Distributions #endif
178*2c2f96dcSApple OSS Distributions }
179*2c2f96dcSApple OSS Distributions 
180*2c2f96dcSApple OSS Distributions /// Count number of bits set
181*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_popcount64(uint64_t data)182*2c2f96dcSApple OSS Distributions cc_popcount64(uint64_t data)
183*2c2f96dcSApple OSS Distributions {
184*2c2f96dcSApple OSS Distributions #if __has_builtin(__builtin_popcountll)
185*2c2f96dcSApple OSS Distributions 	return (unsigned)__builtin_popcountll(data);
186*2c2f96dcSApple OSS Distributions #else
187*2c2f96dcSApple OSS Distributions 	return cc_popcount64_fallback(data);
188*2c2f96dcSApple OSS Distributions #endif
189*2c2f96dcSApple OSS Distributions }
190*2c2f96dcSApple OSS Distributions 
191*2c2f96dcSApple OSS Distributions // Use with volatile variables only.
192*2c2f96dcSApple OSS Distributions #define CC_MULTI_IF_AND(condition) \
193*2c2f96dcSApple OSS Distributions     ((condition) && (condition) && (condition))
194*2c2f96dcSApple OSS Distributions 
195*2c2f96dcSApple OSS Distributions // MARK: - Byte Extraction
196*2c2f96dcSApple OSS Distributions #ifdef _MSC_VER
197*2c2f96dcSApple OSS Distributions #define cc_byte(x, n) ((unsigned char)((x) >> (8 * (n))))
198*2c2f96dcSApple OSS Distributions #else
199*2c2f96dcSApple OSS Distributions #define cc_byte(x, n) (((x) >> (8 * (n))) & 255)
200*2c2f96dcSApple OSS Distributions #endif
201*2c2f96dcSApple OSS Distributions 
202*2c2f96dcSApple OSS Distributions // MARK: - 32-bit Rotates
203*2c2f96dcSApple OSS Distributions 
204*2c2f96dcSApple OSS Distributions #if defined(_MSC_VER)
205*2c2f96dcSApple OSS Distributions // MARK: -- MSVC version
206*2c2f96dcSApple OSS Distributions 
207*2c2f96dcSApple OSS Distributions #include <stdlib.h>
208*2c2f96dcSApple OSS Distributions #if !defined(__clang__)
209*2c2f96dcSApple OSS Distributions  #pragma intrinsic(_lrotr,_lrotl)
210*2c2f96dcSApple OSS Distributions #endif
211*2c2f96dcSApple OSS Distributions #define    CC_ROR(x, n) _lrotr(x,n)
212*2c2f96dcSApple OSS Distributions #define    CC_ROL(x, n) _lrotl(x,n)
213*2c2f96dcSApple OSS Distributions #define    CC_RORc(x, n) _lrotr(x,n)
214*2c2f96dcSApple OSS Distributions #define    CC_ROLc(x, n) _lrotl(x,n)
215*2c2f96dcSApple OSS Distributions 
216*2c2f96dcSApple OSS Distributions #elif (defined(__i386__) || defined(__x86_64__))
217*2c2f96dcSApple OSS Distributions // MARK: -- intel asm version
218*2c2f96dcSApple OSS Distributions 
219*2c2f96dcSApple OSS Distributions CC_INLINE uint32_t
CC_ROL(uint32_t word,int i)220*2c2f96dcSApple OSS Distributions CC_ROL(uint32_t word, int i)
221*2c2f96dcSApple OSS Distributions {
222*2c2f96dcSApple OSS Distributions 	__asm__ ("roll %%cl,%0"
223*2c2f96dcSApple OSS Distributions              :"=r" (word)
224*2c2f96dcSApple OSS Distributions              :"0" (word),"c" (i));
225*2c2f96dcSApple OSS Distributions 	return word;
226*2c2f96dcSApple OSS Distributions }
227*2c2f96dcSApple OSS Distributions 
228*2c2f96dcSApple OSS Distributions CC_INLINE uint32_t
CC_ROR(uint32_t word,int i)229*2c2f96dcSApple OSS Distributions CC_ROR(uint32_t word, int i)
230*2c2f96dcSApple OSS Distributions {
231*2c2f96dcSApple OSS Distributions 	__asm__ ("rorl %%cl,%0"
232*2c2f96dcSApple OSS Distributions              :"=r" (word)
233*2c2f96dcSApple OSS Distributions              :"0" (word),"c" (i));
234*2c2f96dcSApple OSS Distributions 	return word;
235*2c2f96dcSApple OSS Distributions }
236*2c2f96dcSApple OSS Distributions 
237*2c2f96dcSApple OSS Distributions /* Need to be a macro here, because 'i' is an immediate (constant) */
238*2c2f96dcSApple OSS Distributions #define CC_ROLc(word, i)                \
239*2c2f96dcSApple OSS Distributions ({  uint32_t _word=(word);              \
240*2c2f96dcSApple OSS Distributions     __asm__ __volatile__ ("roll %2,%0"  \
241*2c2f96dcSApple OSS Distributions 	:"=r" (_word)                   \
242*2c2f96dcSApple OSS Distributions 	:"0" (_word),"I" (i));          \
243*2c2f96dcSApple OSS Distributions     _word;                              \
244*2c2f96dcSApple OSS Distributions })
245*2c2f96dcSApple OSS Distributions 
246*2c2f96dcSApple OSS Distributions 
247*2c2f96dcSApple OSS Distributions #define CC_RORc(word, i)                \
248*2c2f96dcSApple OSS Distributions ({  uint32_t _word=(word);              \
249*2c2f96dcSApple OSS Distributions     __asm__ __volatile__ ("rorl %2,%0"  \
250*2c2f96dcSApple OSS Distributions 	:"=r" (_word)                   \
251*2c2f96dcSApple OSS Distributions 	:"0" (_word),"I" (i));          \
252*2c2f96dcSApple OSS Distributions     _word;                              \
253*2c2f96dcSApple OSS Distributions })
254*2c2f96dcSApple OSS Distributions 
255*2c2f96dcSApple OSS Distributions #else
256*2c2f96dcSApple OSS Distributions 
257*2c2f96dcSApple OSS Distributions // MARK: -- default version
258*2c2f96dcSApple OSS Distributions 
259*2c2f96dcSApple OSS Distributions CC_INLINE uint32_t
CC_ROL(uint32_t word,int i)260*2c2f96dcSApple OSS Distributions CC_ROL(uint32_t word, int i)
261*2c2f96dcSApple OSS Distributions {
262*2c2f96dcSApple OSS Distributions 	return (word << (i & 31)) | (word >> ((32 - (i & 31)) & 31));
263*2c2f96dcSApple OSS Distributions }
264*2c2f96dcSApple OSS Distributions 
265*2c2f96dcSApple OSS Distributions CC_INLINE uint32_t
CC_ROR(uint32_t word,int i)266*2c2f96dcSApple OSS Distributions CC_ROR(uint32_t word, int i)
267*2c2f96dcSApple OSS Distributions {
268*2c2f96dcSApple OSS Distributions 	return (word >> (i & 31)) | (word << ((32 - (i & 31)) & 31));
269*2c2f96dcSApple OSS Distributions }
270*2c2f96dcSApple OSS Distributions 
271*2c2f96dcSApple OSS Distributions #define    CC_ROLc(x, y) CC_ROL(x, y)
272*2c2f96dcSApple OSS Distributions #define    CC_RORc(x, y) CC_ROR(x, y)
273*2c2f96dcSApple OSS Distributions 
274*2c2f96dcSApple OSS Distributions #endif
275*2c2f96dcSApple OSS Distributions 
276*2c2f96dcSApple OSS Distributions // MARK: - 64 bits rotates
277*2c2f96dcSApple OSS Distributions 
278*2c2f96dcSApple OSS Distributions #if defined(__x86_64__) && !defined(_MSC_VER) //clang _MSVC doesn't support GNU-style inline assembly
279*2c2f96dcSApple OSS Distributions // MARK: -- intel 64 asm version
280*2c2f96dcSApple OSS Distributions 
281*2c2f96dcSApple OSS Distributions CC_INLINE uint64_t
CC_ROL64(uint64_t word,int i)282*2c2f96dcSApple OSS Distributions CC_ROL64(uint64_t word, int i)
283*2c2f96dcSApple OSS Distributions {
284*2c2f96dcSApple OSS Distributions 	__asm__("rolq %%cl,%0"
285*2c2f96dcSApple OSS Distributions             :"=r" (word)
286*2c2f96dcSApple OSS Distributions             :"0" (word),"c" (i));
287*2c2f96dcSApple OSS Distributions 	return word;
288*2c2f96dcSApple OSS Distributions }
289*2c2f96dcSApple OSS Distributions 
290*2c2f96dcSApple OSS Distributions CC_INLINE uint64_t
CC_ROR64(uint64_t word,int i)291*2c2f96dcSApple OSS Distributions CC_ROR64(uint64_t word, int i)
292*2c2f96dcSApple OSS Distributions {
293*2c2f96dcSApple OSS Distributions 	__asm__("rorq %%cl,%0"
294*2c2f96dcSApple OSS Distributions             :"=r" (word)
295*2c2f96dcSApple OSS Distributions             :"0" (word),"c" (i));
296*2c2f96dcSApple OSS Distributions 	return word;
297*2c2f96dcSApple OSS Distributions }
298*2c2f96dcSApple OSS Distributions 
299*2c2f96dcSApple OSS Distributions /* Need to be a macro here, because 'i' is an immediate (constant) */
300*2c2f96dcSApple OSS Distributions #define CC_ROL64c(word, i)      \
301*2c2f96dcSApple OSS Distributions ({                              \
302*2c2f96dcSApple OSS Distributions     uint64_t _word=(word);      \
303*2c2f96dcSApple OSS Distributions     __asm__("rolq %2,%0"        \
304*2c2f96dcSApple OSS Distributions 	:"=r" (_word)           \
305*2c2f96dcSApple OSS Distributions 	:"0" (_word),"J" (i));  \
306*2c2f96dcSApple OSS Distributions     _word;                      \
307*2c2f96dcSApple OSS Distributions })
308*2c2f96dcSApple OSS Distributions 
309*2c2f96dcSApple OSS Distributions #define CC_ROR64c(word, i)      \
310*2c2f96dcSApple OSS Distributions ({                              \
311*2c2f96dcSApple OSS Distributions     uint64_t _word=(word);      \
312*2c2f96dcSApple OSS Distributions     __asm__("rorq %2,%0"        \
313*2c2f96dcSApple OSS Distributions 	:"=r" (_word)           \
314*2c2f96dcSApple OSS Distributions 	:"0" (_word),"J" (i));  \
315*2c2f96dcSApple OSS Distributions     _word;                      \
316*2c2f96dcSApple OSS Distributions })
317*2c2f96dcSApple OSS Distributions 
318*2c2f96dcSApple OSS Distributions 
319*2c2f96dcSApple OSS Distributions #else /* Not x86_64  */
320*2c2f96dcSApple OSS Distributions 
321*2c2f96dcSApple OSS Distributions // MARK: -- default C version
322*2c2f96dcSApple OSS Distributions 
323*2c2f96dcSApple OSS Distributions CC_INLINE uint64_t
CC_ROL64(uint64_t word,int i)324*2c2f96dcSApple OSS Distributions CC_ROL64(uint64_t word, int i)
325*2c2f96dcSApple OSS Distributions {
326*2c2f96dcSApple OSS Distributions 	return (word << (i & 63)) | (word >> ((64 - (i & 63)) & 63));
327*2c2f96dcSApple OSS Distributions }
328*2c2f96dcSApple OSS Distributions 
329*2c2f96dcSApple OSS Distributions CC_INLINE uint64_t
CC_ROR64(uint64_t word,int i)330*2c2f96dcSApple OSS Distributions CC_ROR64(uint64_t word, int i)
331*2c2f96dcSApple OSS Distributions {
332*2c2f96dcSApple OSS Distributions 	return (word >> (i & 63)) | (word << ((64 - (i & 63)) & 63));
333*2c2f96dcSApple OSS Distributions }
334*2c2f96dcSApple OSS Distributions 
335*2c2f96dcSApple OSS Distributions #define    CC_ROL64c(x, y) CC_ROL64(x, y)
336*2c2f96dcSApple OSS Distributions #define    CC_ROR64c(x, y) CC_ROR64(x, y)
337*2c2f96dcSApple OSS Distributions 
338*2c2f96dcSApple OSS Distributions #endif
339*2c2f96dcSApple OSS Distributions 
340*2c2f96dcSApple OSS Distributions // MARK: -- Count Leading / Trailing Zeros
341*2c2f96dcSApple OSS Distributions /* Count leading zeros (for nonzero inputs) */
342*2c2f96dcSApple OSS Distributions 
343*2c2f96dcSApple OSS Distributions /*
344*2c2f96dcSApple OSS Distributions  *  On i386 and x86_64, we know clang and GCC will generate BSR for
345*2c2f96dcSApple OSS Distributions  *  __builtin_clzl.  This instruction IS NOT constant time on all micro-
346*2c2f96dcSApple OSS Distributions  *  architectures, but it *is* constant time on all micro-architectures that
347*2c2f96dcSApple OSS Distributions  *  have been used by Apple, and we expect that to continue to be the case.
348*2c2f96dcSApple OSS Distributions  *
349*2c2f96dcSApple OSS Distributions  *  When building for x86_64h with clang, this produces LZCNT, which is exactly
350*2c2f96dcSApple OSS Distributions  *  what we want.
351*2c2f96dcSApple OSS Distributions  *
352*2c2f96dcSApple OSS Distributions  *  On arm and arm64, we know that clang and GCC generate the constant-time CLZ
353*2c2f96dcSApple OSS Distributions  *  instruction from __builtin_clzl( ).
354*2c2f96dcSApple OSS Distributions  */
355*2c2f96dcSApple OSS Distributions 
356*2c2f96dcSApple OSS Distributions #if defined(_WIN32)
357*2c2f96dcSApple OSS Distributions /* We use the Windows implementations below. */
358*2c2f96dcSApple OSS Distributions #elif defined(__x86_64__) || defined(__i386__) || defined(__arm64__) || defined(__arm__)
359*2c2f96dcSApple OSS Distributions /* We use a thought-to-be-good version of __builtin_clz. */
360*2c2f96dcSApple OSS Distributions #elif defined __GNUC__
361*2c2f96dcSApple OSS Distributions #warning Using __builtin_clz() on an unknown architecture; it may not be constant-time.
362*2c2f96dcSApple OSS Distributions /* If you find yourself seeing this warning, file a radar for someone to
363*2c2f96dcSApple OSS Distributions  * check whether or not __builtin_clz() generates a constant-time
364*2c2f96dcSApple OSS Distributions  * implementation on the architecture you are targeting.  If it does, append
365*2c2f96dcSApple OSS Distributions  * the name of that architecture to the list of "safe" architectures above.  */
366*2c2f96dcSApple OSS Distributions #endif
367*2c2f96dcSApple OSS Distributions 
368*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_clz32_fallback(uint32_t data)369*2c2f96dcSApple OSS Distributions cc_clz32_fallback(uint32_t data)
370*2c2f96dcSApple OSS Distributions {
371*2c2f96dcSApple OSS Distributions 	unsigned int b = 0;
372*2c2f96dcSApple OSS Distributions 	unsigned int bit = 0;
373*2c2f96dcSApple OSS Distributions 	// Work from LSB to MSB
374*2c2f96dcSApple OSS Distributions 	for (int i = 0; i < 32; i++) {
375*2c2f96dcSApple OSS Distributions 		bit = (data >> i) & 1;
376*2c2f96dcSApple OSS Distributions 		// If the bit is 0, update the "leading bits are zero" counter "b".
377*2c2f96dcSApple OSS Distributions 		b += (1 - bit);
378*2c2f96dcSApple OSS Distributions 		/* If the bit is 0, (bit - 1) is 0xffff... therefore b is retained.
379*2c2f96dcSApple OSS Distributions 		 * If the bit is 1, (bit - 1) is 0 therefore b is set to 0.
380*2c2f96dcSApple OSS Distributions 		 */
381*2c2f96dcSApple OSS Distributions 		b &= (bit - 1);
382*2c2f96dcSApple OSS Distributions 	}
383*2c2f96dcSApple OSS Distributions 	return b;
384*2c2f96dcSApple OSS Distributions }
385*2c2f96dcSApple OSS Distributions 
386*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_clz64_fallback(uint64_t data)387*2c2f96dcSApple OSS Distributions cc_clz64_fallback(uint64_t data)
388*2c2f96dcSApple OSS Distributions {
389*2c2f96dcSApple OSS Distributions 	unsigned int b = 0;
390*2c2f96dcSApple OSS Distributions 	unsigned int bit = 0;
391*2c2f96dcSApple OSS Distributions 	// Work from LSB to MSB
392*2c2f96dcSApple OSS Distributions 	for (int i = 0; i < 64; i++) {
393*2c2f96dcSApple OSS Distributions 		bit = (data >> i) & 1;
394*2c2f96dcSApple OSS Distributions 		// If the bit is 0, update the "leading bits are zero" counter.
395*2c2f96dcSApple OSS Distributions 		b += (1 - bit);
396*2c2f96dcSApple OSS Distributions 		/* If the bit is 0, (bit - 1) is 0xffff... therefore b is retained.
397*2c2f96dcSApple OSS Distributions 		 * If the bit is 1, (bit - 1) is 0 therefore b is set to 0.
398*2c2f96dcSApple OSS Distributions 		 */
399*2c2f96dcSApple OSS Distributions 		b &= (bit - 1);
400*2c2f96dcSApple OSS Distributions 	}
401*2c2f96dcSApple OSS Distributions 	return b;
402*2c2f96dcSApple OSS Distributions }
403*2c2f96dcSApple OSS Distributions 
404*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_ctz32_fallback(uint32_t data)405*2c2f96dcSApple OSS Distributions cc_ctz32_fallback(uint32_t data)
406*2c2f96dcSApple OSS Distributions {
407*2c2f96dcSApple OSS Distributions 	unsigned int b = 0;
408*2c2f96dcSApple OSS Distributions 	unsigned int bit = 0;
409*2c2f96dcSApple OSS Distributions 	// Work from MSB to LSB
410*2c2f96dcSApple OSS Distributions 	for (int i = 31; i >= 0; i--) {
411*2c2f96dcSApple OSS Distributions 		bit = (data >> i) & 1;
412*2c2f96dcSApple OSS Distributions 		// If the bit is 0, update the "trailing zero bits" counter.
413*2c2f96dcSApple OSS Distributions 		b += (1 - bit);
414*2c2f96dcSApple OSS Distributions 		/* If the bit is 0, (bit - 1) is 0xffff... therefore b is retained.
415*2c2f96dcSApple OSS Distributions 		 * If the bit is 1, (bit - 1) is 0 therefore b is set to 0.
416*2c2f96dcSApple OSS Distributions 		 */
417*2c2f96dcSApple OSS Distributions 		b &= (bit - 1);
418*2c2f96dcSApple OSS Distributions 	}
419*2c2f96dcSApple OSS Distributions 	return b;
420*2c2f96dcSApple OSS Distributions }
421*2c2f96dcSApple OSS Distributions 
422*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_ctz64_fallback(uint64_t data)423*2c2f96dcSApple OSS Distributions cc_ctz64_fallback(uint64_t data)
424*2c2f96dcSApple OSS Distributions {
425*2c2f96dcSApple OSS Distributions 	unsigned int b = 0;
426*2c2f96dcSApple OSS Distributions 	unsigned int bit = 0;
427*2c2f96dcSApple OSS Distributions 	// Work from MSB to LSB
428*2c2f96dcSApple OSS Distributions 	for (int i = 63; i >= 0; i--) {
429*2c2f96dcSApple OSS Distributions 		bit = (data >> i) & 1;
430*2c2f96dcSApple OSS Distributions 		// If the bit is 0, update the "trailing zero bits" counter.
431*2c2f96dcSApple OSS Distributions 		b += (1 - bit);
432*2c2f96dcSApple OSS Distributions 		/* If the bit is 0, (bit - 1) is 0xffff... therefore b is retained.
433*2c2f96dcSApple OSS Distributions 		 * If the bit is 1, (bit - 1) is 0 therefore b is set to 0.
434*2c2f96dcSApple OSS Distributions 		 */
435*2c2f96dcSApple OSS Distributions 		b &= (bit - 1);
436*2c2f96dcSApple OSS Distributions 	}
437*2c2f96dcSApple OSS Distributions 	return b;
438*2c2f96dcSApple OSS Distributions }
439*2c2f96dcSApple OSS Distributions 
440*2c2f96dcSApple OSS Distributions /*!
441*2c2f96dcSApple OSS Distributions  *  @function cc_clz32
442*2c2f96dcSApple OSS Distributions  *  @abstract Count leading zeros of a nonzero 32-bit value
443*2c2f96dcSApple OSS Distributions  *
444*2c2f96dcSApple OSS Distributions  *  @param data A nonzero 32-bit value
445*2c2f96dcSApple OSS Distributions  *
446*2c2f96dcSApple OSS Distributions  *  @result Count of leading zeros of @p data
447*2c2f96dcSApple OSS Distributions  *
448*2c2f96dcSApple OSS Distributions  *  @discussion @p data is assumed to be nonzero.
449*2c2f96dcSApple OSS Distributions  */
450*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_clz32(uint32_t data)451*2c2f96dcSApple OSS Distributions cc_clz32(uint32_t data)
452*2c2f96dcSApple OSS Distributions {
453*2c2f96dcSApple OSS Distributions 	cc_assert(data != 0);
454*2c2f96dcSApple OSS Distributions #if __has_builtin(__builtin_clz)
455*2c2f96dcSApple OSS Distributions 	cc_static_assert(sizeof(unsigned) == 4, "clz relies on an unsigned int being 4 bytes");
456*2c2f96dcSApple OSS Distributions 	return (unsigned)__builtin_clz(data);
457*2c2f96dcSApple OSS Distributions #else
458*2c2f96dcSApple OSS Distributions 	return cc_clz32_fallback(data);
459*2c2f96dcSApple OSS Distributions #endif
460*2c2f96dcSApple OSS Distributions }
461*2c2f96dcSApple OSS Distributions 
462*2c2f96dcSApple OSS Distributions /*!
463*2c2f96dcSApple OSS Distributions  *  @function cc_clz64
464*2c2f96dcSApple OSS Distributions  *  @abstract Count leading zeros of a nonzero 64-bit value
465*2c2f96dcSApple OSS Distributions  *
466*2c2f96dcSApple OSS Distributions  *  @param data A nonzero 64-bit value
467*2c2f96dcSApple OSS Distributions  *
468*2c2f96dcSApple OSS Distributions  *  @result Count of leading zeros of @p data
469*2c2f96dcSApple OSS Distributions  *
470*2c2f96dcSApple OSS Distributions  *  @discussion @p data is assumed to be nonzero.
471*2c2f96dcSApple OSS Distributions  */
472*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_clz64(uint64_t data)473*2c2f96dcSApple OSS Distributions cc_clz64(uint64_t data)
474*2c2f96dcSApple OSS Distributions {
475*2c2f96dcSApple OSS Distributions 	cc_assert(data != 0);
476*2c2f96dcSApple OSS Distributions #if __has_builtin(__builtin_clzll)
477*2c2f96dcSApple OSS Distributions 	return (unsigned)__builtin_clzll(data);
478*2c2f96dcSApple OSS Distributions #else
479*2c2f96dcSApple OSS Distributions 	return cc_clz64_fallback(data);
480*2c2f96dcSApple OSS Distributions #endif
481*2c2f96dcSApple OSS Distributions }
482*2c2f96dcSApple OSS Distributions 
483*2c2f96dcSApple OSS Distributions /*!
484*2c2f96dcSApple OSS Distributions  *  @function cc_ctz32
485*2c2f96dcSApple OSS Distributions  *  @abstract Count trailing zeros of a nonzero 32-bit value
486*2c2f96dcSApple OSS Distributions  *
487*2c2f96dcSApple OSS Distributions  *  @param data A nonzero 32-bit value
488*2c2f96dcSApple OSS Distributions  *
489*2c2f96dcSApple OSS Distributions  *  @result Count of trailing zeros of @p data
490*2c2f96dcSApple OSS Distributions  *
491*2c2f96dcSApple OSS Distributions  *  @discussion @p data is assumed to be nonzero.
492*2c2f96dcSApple OSS Distributions  */
493*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_ctz32(uint32_t data)494*2c2f96dcSApple OSS Distributions cc_ctz32(uint32_t data)
495*2c2f96dcSApple OSS Distributions {
496*2c2f96dcSApple OSS Distributions 	cc_assert(data != 0);
497*2c2f96dcSApple OSS Distributions #if __has_builtin(__builtin_ctz)
498*2c2f96dcSApple OSS Distributions 	cc_static_assert(sizeof(unsigned) == 4, "ctz relies on an unsigned int being 4 bytes");
499*2c2f96dcSApple OSS Distributions 	return (unsigned)__builtin_ctz(data);
500*2c2f96dcSApple OSS Distributions #else
501*2c2f96dcSApple OSS Distributions 	return cc_ctz32_fallback(data);
502*2c2f96dcSApple OSS Distributions #endif
503*2c2f96dcSApple OSS Distributions }
504*2c2f96dcSApple OSS Distributions 
505*2c2f96dcSApple OSS Distributions /*!
506*2c2f96dcSApple OSS Distributions  *  @function cc_ctz64
507*2c2f96dcSApple OSS Distributions  *  @abstract Count trailing zeros of a nonzero 64-bit value
508*2c2f96dcSApple OSS Distributions  *
509*2c2f96dcSApple OSS Distributions  *  @param data A nonzero 64-bit value
510*2c2f96dcSApple OSS Distributions  *
511*2c2f96dcSApple OSS Distributions  *  @result Count of trailing zeros of @p data
512*2c2f96dcSApple OSS Distributions  *
513*2c2f96dcSApple OSS Distributions  *  @discussion @p data is assumed to be nonzero.
514*2c2f96dcSApple OSS Distributions  */
515*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_ctz64(uint64_t data)516*2c2f96dcSApple OSS Distributions cc_ctz64(uint64_t data)
517*2c2f96dcSApple OSS Distributions {
518*2c2f96dcSApple OSS Distributions 	cc_assert(data != 0);
519*2c2f96dcSApple OSS Distributions #if __has_builtin(__builtin_ctzll)
520*2c2f96dcSApple OSS Distributions 	return (unsigned)__builtin_ctzll(data);
521*2c2f96dcSApple OSS Distributions #else
522*2c2f96dcSApple OSS Distributions 	return cc_ctz64_fallback(data);
523*2c2f96dcSApple OSS Distributions #endif
524*2c2f96dcSApple OSS Distributions }
525*2c2f96dcSApple OSS Distributions 
526*2c2f96dcSApple OSS Distributions // MARK: -- Find first bit set
527*2c2f96dcSApple OSS Distributions 
528*2c2f96dcSApple OSS Distributions /*!
529*2c2f96dcSApple OSS Distributions  *  @function cc_ffs32_fallback
530*2c2f96dcSApple OSS Distributions  *  @abstract Find first bit set in a 32-bit value
531*2c2f96dcSApple OSS Distributions  *
532*2c2f96dcSApple OSS Distributions  *  @param data A 32-bit value
533*2c2f96dcSApple OSS Distributions  *
534*2c2f96dcSApple OSS Distributions  *  @result One plus the index of the least-significant bit set in @p data or, if @p data is zero, zero
535*2c2f96dcSApple OSS Distributions  */
536*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_ffs32_fallback(int32_t data)537*2c2f96dcSApple OSS Distributions cc_ffs32_fallback(int32_t data)
538*2c2f96dcSApple OSS Distributions {
539*2c2f96dcSApple OSS Distributions 	unsigned b = 0;
540*2c2f96dcSApple OSS Distributions 	unsigned bit = 0;
541*2c2f96dcSApple OSS Distributions 	unsigned seen = 0;
542*2c2f96dcSApple OSS Distributions 
543*2c2f96dcSApple OSS Distributions 	// Work from LSB to MSB
544*2c2f96dcSApple OSS Distributions 	for (int i = 0; i < 32; i++) {
545*2c2f96dcSApple OSS Distributions 		bit = ((uint32_t)data >> i) & 1;
546*2c2f96dcSApple OSS Distributions 
547*2c2f96dcSApple OSS Distributions 		// Track whether we've seen a 1 bit.
548*2c2f96dcSApple OSS Distributions 		seen |= bit;
549*2c2f96dcSApple OSS Distributions 
550*2c2f96dcSApple OSS Distributions 		// If the bit is 0 and we haven't seen a 1 yet, increment b.
551*2c2f96dcSApple OSS Distributions 		b += (1 - bit) & (seen - 1);
552*2c2f96dcSApple OSS Distributions 	}
553*2c2f96dcSApple OSS Distributions 
554*2c2f96dcSApple OSS Distributions 	// If we saw a 1, return b + 1, else 0.
555*2c2f96dcSApple OSS Distributions 	return (~(seen - 1)) & (b + 1);
556*2c2f96dcSApple OSS Distributions }
557*2c2f96dcSApple OSS Distributions 
558*2c2f96dcSApple OSS Distributions /*!
559*2c2f96dcSApple OSS Distributions  *  @function cc_ffs64_fallback
560*2c2f96dcSApple OSS Distributions  *  @abstract Find first bit set in a 64-bit value
561*2c2f96dcSApple OSS Distributions  *
562*2c2f96dcSApple OSS Distributions  *  @param data A 64-bit value
563*2c2f96dcSApple OSS Distributions  *
564*2c2f96dcSApple OSS Distributions  *  @result One plus the index of the least-significant bit set in @p data or, if @p data is zero, zero
565*2c2f96dcSApple OSS Distributions  */
566*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_ffs64_fallback(int64_t data)567*2c2f96dcSApple OSS Distributions cc_ffs64_fallback(int64_t data)
568*2c2f96dcSApple OSS Distributions {
569*2c2f96dcSApple OSS Distributions 	unsigned b = 0;
570*2c2f96dcSApple OSS Distributions 	unsigned bit = 0;
571*2c2f96dcSApple OSS Distributions 	unsigned seen = 0;
572*2c2f96dcSApple OSS Distributions 
573*2c2f96dcSApple OSS Distributions 	// Work from LSB to MSB
574*2c2f96dcSApple OSS Distributions 	for (int i = 0; i < 64; i++) {
575*2c2f96dcSApple OSS Distributions 		bit = ((uint64_t)data >> i) & 1;
576*2c2f96dcSApple OSS Distributions 
577*2c2f96dcSApple OSS Distributions 		// Track whether we've seen a 1 bit.
578*2c2f96dcSApple OSS Distributions 		seen |= bit;
579*2c2f96dcSApple OSS Distributions 
580*2c2f96dcSApple OSS Distributions 		// If the bit is 0 and we haven't seen a 1 yet, increment b.
581*2c2f96dcSApple OSS Distributions 		b += (1 - bit) & (seen - 1);
582*2c2f96dcSApple OSS Distributions 	}
583*2c2f96dcSApple OSS Distributions 
584*2c2f96dcSApple OSS Distributions 	// If we saw a 1, return b + 1, else 0.
585*2c2f96dcSApple OSS Distributions 	return (~(seen - 1)) & (b + 1);
586*2c2f96dcSApple OSS Distributions }
587*2c2f96dcSApple OSS Distributions 
588*2c2f96dcSApple OSS Distributions /*!
589*2c2f96dcSApple OSS Distributions  *  @function cc_ffs32
590*2c2f96dcSApple OSS Distributions  *  @abstract Find first bit set in a 32-bit value
591*2c2f96dcSApple OSS Distributions  *
592*2c2f96dcSApple OSS Distributions  *  @param data A 32-bit value
593*2c2f96dcSApple OSS Distributions  *
594*2c2f96dcSApple OSS Distributions  *  @result One plus the index of the least-significant bit set in @p data or, if @p data is zero, zero
595*2c2f96dcSApple OSS Distributions  */
596*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_ffs32(int32_t data)597*2c2f96dcSApple OSS Distributions cc_ffs32(int32_t data)
598*2c2f96dcSApple OSS Distributions {
599*2c2f96dcSApple OSS Distributions 	cc_static_assert(sizeof(int) == 4, "ffs relies on an int being 4 bytes");
600*2c2f96dcSApple OSS Distributions #if __has_builtin(__builtin_ffs)
601*2c2f96dcSApple OSS Distributions 	return (unsigned)__builtin_ffs(data);
602*2c2f96dcSApple OSS Distributions #else
603*2c2f96dcSApple OSS Distributions 	return cc_ffs32_fallback(data);
604*2c2f96dcSApple OSS Distributions #endif
605*2c2f96dcSApple OSS Distributions }
606*2c2f96dcSApple OSS Distributions 
607*2c2f96dcSApple OSS Distributions /*!
608*2c2f96dcSApple OSS Distributions  *  @function cc_ffs64
609*2c2f96dcSApple OSS Distributions  *  @abstract Find first bit set in a 64-bit value
610*2c2f96dcSApple OSS Distributions  *
611*2c2f96dcSApple OSS Distributions  *  @param data A 64-bit value
612*2c2f96dcSApple OSS Distributions  *
613*2c2f96dcSApple OSS Distributions  *  @result One plus the index of the least-significant bit set in @p data or, if @p data is zero, zero
614*2c2f96dcSApple OSS Distributions  */
615*2c2f96dcSApple OSS Distributions CC_INLINE CC_CONST unsigned
cc_ffs64(int64_t data)616*2c2f96dcSApple OSS Distributions cc_ffs64(int64_t data)
617*2c2f96dcSApple OSS Distributions {
618*2c2f96dcSApple OSS Distributions #if __has_builtin(__builtin_ffsll)
619*2c2f96dcSApple OSS Distributions 	return (unsigned)__builtin_ffsll(data);
620*2c2f96dcSApple OSS Distributions #else
621*2c2f96dcSApple OSS Distributions 	return cc_ffs64_fallback(data);
622*2c2f96dcSApple OSS Distributions #endif
623*2c2f96dcSApple OSS Distributions }
624*2c2f96dcSApple OSS Distributions 
625*2c2f96dcSApple OSS Distributions // MARK: -- Overflow wrappers
626*2c2f96dcSApple OSS Distributions #define cc_add_overflow __builtin_add_overflow
627*2c2f96dcSApple OSS Distributions 
628*2c2f96dcSApple OSS Distributions // On 32-bit architectures, clang emits libcalls to __mulodi4 when
629*2c2f96dcSApple OSS Distributions // __builtin_mul_overflow() encounters `long long` types.
630*2c2f96dcSApple OSS Distributions //
631*2c2f96dcSApple OSS Distributions // The libgcc runtime does not provide __mulodi4, so for Linux on ARMv7
632*2c2f96dcSApple OSS Distributions // we cannot call __builtin_mul_overflow().
633*2c2f96dcSApple OSS Distributions //
634*2c2f96dcSApple OSS Distributions // Using __has_builtin(__builtin_mul_overflow) would be better but that will
635*2c2f96dcSApple OSS Distributions // return the correct response for ARMv7/Linux only with LLVM-14 or higher.
636*2c2f96dcSApple OSS Distributions #if defined(__clang__) && defined(__arm__) && CC_LINUX
637*2c2f96dcSApple OSS Distributions CC_INLINE bool
cc_mul_overflow(uint64_t a,uint64_t b,uint64_t * r)638*2c2f96dcSApple OSS Distributions cc_mul_overflow(uint64_t a, uint64_t b, uint64_t *r)
639*2c2f96dcSApple OSS Distributions {
640*2c2f96dcSApple OSS Distributions 	*r = a * b;
641*2c2f96dcSApple OSS Distributions 	return (a != 0) && ((*r / a) != b);
642*2c2f96dcSApple OSS Distributions }
643*2c2f96dcSApple OSS Distributions #else
644*2c2f96dcSApple OSS Distributions #define cc_mul_overflow __builtin_mul_overflow
645*2c2f96dcSApple OSS Distributions #endif
646*2c2f96dcSApple OSS Distributions 
647*2c2f96dcSApple OSS Distributions // MARK: -- Heavyside Step
648*2c2f96dcSApple OSS Distributions /* HEAVISIDE_STEP (shifted by one)
649*2c2f96dcSApple OSS Distributions  *  function f(x): x->0, when x=0
650*2c2f96dcSApple OSS Distributions  *                 x->1, when x>0
651*2c2f96dcSApple OSS Distributions  *  Can also be seen as a bitwise operation:
652*2c2f96dcSApple OSS Distributions  *     f(x): x -> y
653*2c2f96dcSApple OSS Distributions  *       y[0]=(OR x[i]) for all i (all bits)
654*2c2f96dcSApple OSS Distributions  *       y[i]=0 for all i>0
655*2c2f96dcSApple OSS Distributions  *  Run in constant time (log2(<bitsize of x>))
656*2c2f96dcSApple OSS Distributions  *  Useful to run constant time checks
657*2c2f96dcSApple OSS Distributions  */
658*2c2f96dcSApple OSS Distributions #define CC_HEAVISIDE_STEP(r, s) do {                                         \
659*2c2f96dcSApple OSS Distributions     cc_static_assert(sizeof(uint64_t) >= sizeof(s), "max type is uint64_t"); \
660*2c2f96dcSApple OSS Distributions     const uint64_t _s = (uint64_t)s;                                         \
661*2c2f96dcSApple OSS Distributions     const uint64_t _t = (_s & 0xffffffff) | (_s >> 32);                      \
662*2c2f96dcSApple OSS Distributions     r = (uint8_t)((_t + 0xffffffff) >> 32);                                  \
663*2c2f96dcSApple OSS Distributions } while (0)
664*2c2f96dcSApple OSS Distributions 
665*2c2f96dcSApple OSS Distributions /* Return 1 if x mod 4 =1,2,3, 0 otherwise */
666*2c2f96dcSApple OSS Distributions #define CC_CARRY_2BITS(x) (((x>>1) | x) & 0x1)
667*2c2f96dcSApple OSS Distributions #define CC_CARRY_3BITS(x) (((x>>2) | (x>>1) | x) & 0x1)
668*2c2f96dcSApple OSS Distributions 
669*2c2f96dcSApple OSS Distributions /*!
670*2c2f96dcSApple OSS Distributions  *  @brief     CC_MUXU(r, s, a, b) is equivalent to r = s ? a : b, but executes in constant time
671*2c2f96dcSApple OSS Distributions  *  @param a   Input a
672*2c2f96dcSApple OSS Distributions  *  @param b   Input b
673*2c2f96dcSApple OSS Distributions  *  @param s   Selection parameter s. Must be 0 or 1.
674*2c2f96dcSApple OSS Distributions  *  @param r   Output, set to a if s=1, or b if s=0.
675*2c2f96dcSApple OSS Distributions  */
676*2c2f96dcSApple OSS Distributions #define CC_MUXU(r, s, a, b) do {            \
677*2c2f96dcSApple OSS Distributions     cc_assert((s) == 0 || (s) == 1);        \
678*2c2f96dcSApple OSS Distributions     r = (~((s)-1) & (a)) | (((s)-1) & (b)); \
679*2c2f96dcSApple OSS Distributions } while (0)
680*2c2f96dcSApple OSS Distributions 
681*2c2f96dcSApple OSS Distributions #endif // _CORECRYPTO_CC_INTERNAL_H_
682