-
Notifications
You must be signed in to change notification settings - Fork 5
/
compat.h
225 lines (189 loc) · 6.16 KB
/
compat.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
* SPDX-License-Identifier: MIT
*/
#ifndef FAEST_COMPAT_H
#define FAEST_COMPAT_H
#if defined(HAVE_CONFIG_H)
#include <config.h>
#endif
#include "macros.h"
#include <stddef.h>
#if !defined(HAVE_CONFIG_H) && !defined(OQS)
/* In case cmake checks were not run, define HAVE_* for known good configurations. We skip those if
* building for OQS, as the compat functions from there can be used instead. */
#if defined(__OpenBSD__)
#include <sys/param.h>
#endif /* __OpenBSD__ */
#if !defined(HAVE_ALIGNED_ALLOC) && !defined(__APPLE__) && !defined(__MINGW32__) && \
!defined(__MINGW64__) && !defined(_MSC_VER) && !defined(__ANDROID__) && \
(defined(_ISOC11_SOURCE) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L))
/* aligned_alloc was introduced in ISO C 2011. Even if building with -std=c11, some toolchains do
* not provide aligned_alloc, including toolchains for Android, OS X, MinGW, and others. */
#define HAVE_ALIGNED_ALLOC
#endif /* HAVE_ALIGNED_ALLOC */
#if !defined(HAVE_EXPLICIT_BZERO) && \
(GLIBC_CHECK(2, 25) || (defined(__OpenBSD__) && OpenBSD >= 201405) || FREEBSD_CHECK(11, 0) || \
NETBSD_CHECK(8, 0))
/* explicit_bzero was introduced in glibc 2.35, OpenBSD 5.5, FreeBSD 11.0 and NetBSD 8.0 */
#define HAVE_EXPLICIT_BZERO
#endif /* HAVE_EXPLICIT_BZERO */
#if !defined(HAVE_TIMINGSAFE_BCMP) && ((defined(__OpenBSD__) && OpenBSD >= 201105) || \
FREEBSD_CHECK(12, 0) || MACOSX_CHECK(10, 12, 1))
/* timingsafe_bcmp was introduced in OpenBSD 4.9, FreeBSD 12.0, and MacOS X 10.12 */
#define HAVE_TIMINGSAFE_BCMP
#endif /* HAVE_TIMINGSAFE_BCMP */
#endif /* !HAVE_CONFIG_H && !OQS */
#if defined(HAVE_ALIGNED_ALLOC)
#include <stdlib.h>
#define faest_aligned_alloc(alignment, size) aligned_alloc((alignment), (size))
#define faest_aligned_free(ptr) free((ptr))
#else
FAEST_BEGIN_C_DECL
/**
* Some aligned_alloc compatbility implementations require custom free
* functions, so we provide one too.
*/
void faest_aligned_free(void* ptr);
/**
* Compatibility implementation of aligned_alloc from ISO C 2011.
*/
void* faest_aligned_alloc(size_t alignment, size_t size) ATTR_MALLOC(faest_aligned_free)
ATTR_ALLOC_ALIGN(1) ATTR_ALLOC_SIZE(2);
FAEST_END_C_DECL
#endif /* HAVE_ALIGNED_ALLOC */
#include "endian_compat.h"
#if defined(HAVE_TIMINGSAFE_BCMP)
#include <string.h>
#define faest_timingsafe_bcmp(a, b, len) timingsafe_bcmp((a), (b), (len))
#else
FAEST_BEGIN_C_DECL
/**
* Compatibility implementation of timingsafe_bcmp from OpenBSD 4.9 and FreeBSD 12.0.
*/
int faest_timingsafe_bcmp(const void* a, const void* b, size_t len);
FAEST_END_C_DECL
#endif /* HAVE_TIMINGSAFE_BCMP */
#if defined(HAVE_EXPLICIT_BZERO)
#include <string.h>
#define faest_explicit_bzero(ptr, len) explicit_bzero((ptr), (len))
#else
FAEST_BEGIN_C_DECL
/**
* Compatibility implementation of explicit_bzero
*/
void faest_explicit_bzero(void* a, size_t len);
FAEST_END_C_DECL
#endif /* HAVE_EXPLICIT_BZERO */
#if defined(OQS)
#define faest_aligned_alloc(alignment, size) OQS_MEM_aligned_alloc((alignment), (size))
#define faest_aligned_free(ptr) OQS_MEM_aligned_free((ptr))
#define faest_timingsafe_bcmp(a, b, len) OQS_MEM_secure_bcmp((a), (b), (len))
#define faest_explicit_bzero(ptr, len) OQS_MEM_cleanse(ptr, len)
#endif
/* helper macros/functions for checked integer subtraction */
#if GNUC_CHECK(5, 0) || __has_builtin(__builtin_add_overflow)
#define sub_overflow_size_t(x, y, diff) __builtin_sub_overflow(x, y, diff)
#else
#include <stdbool.h>
#include <stddef.h>
ATTR_ARTIFICIAL
static inline bool sub_overflow_size_t(const size_t x, const size_t y, size_t* diff) {
*diff = x - y;
return x < y;
}
#endif
#include <stdint.h>
#include <limits.h>
/* helper functions for left and right rotations of bytes */
#if GNUC_CHECK(4, 9) && (defined(__x86_64__) || defined(__i386__))
#include <x86intrin.h>
#define rotl8 __rolb
#define rotr8 __rorb
#elif __has_builtin(__builtin_rotateleft) && __has_builtin(__builtin_rotateright)
#define rotl8 __builtin_rotateleft8
#define rotr8 __builtin_rotateright8
#else
ATTR_CONST static inline uint8_t rotl8(uint8_t n, unsigned int c) {
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1);
c &= mask;
return (n << c) | (n >> ((-c) & mask));
}
ATTR_CONST static inline uint8_t rotr8(uint8_t n, unsigned int c) {
const unsigned int mask = (CHAR_BIT * sizeof(n) - 1);
c &= mask;
return (n >> c) | (n << ((-c) & mask));
}
#endif
/* helper functions to compute number of leading zeroes */
#if GNUC_CHECK(4, 7) || __has_builtin(__builtin_clz)
ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t clz(uint32_t x) {
return x ? __builtin_clz(x) : 32;
}
#elif defined(_MSC_VER)
#include <intrin.h>
ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t clz(uint32_t x) {
unsigned long index = 0;
if (_BitScanReverse(&index, x)) {
return 31 - index;
}
return 32;
}
#else
/* Number of leading zeroes of x.
* From the book
* H.S. Warren, *Hacker's Delight*, Pearson Education, 2003.
* http://www.hackersdelight.org/hdcodetxt/nlz.c.txt
*/
ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t clz(uint32_t x) {
if (!x) {
return 32;
}
uint32_t n = 1;
if (!(x >> 16)) {
n = n + 16;
x = x << 16;
}
if (!(x >> 24)) {
n = n + 8;
x = x << 8;
}
if (!(x >> 28)) {
n = n + 4;
x = x << 4;
}
if (!(x >> 30)) {
n = n + 2;
x = x << 2;
}
n = n - (x >> 31);
return n;
}
#endif
ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t ceil_log2(uint32_t x) {
if (!x) {
return 0;
}
return 32 - clz(x - 1);
}
/* helper functions for byte parity: 0 if even number of bits are set, 1 if odd number of bts are
* set */
#if __has_builtin(__builtin_parity)
#define parity8 __builtin_parity
#elif __has_builtin(__builtin_popcount)
#define parity8(x) (__builtin_popcount(x) & 0x1)
#else
ATTR_CONST ATTR_ARTIFICIAL static inline uint8_t parity8(uint8_t n) {
n ^= n >> 4;
n ^= n >> 2;
n ^= n >> 1;
return !((~n) & 1);
}
#endif
#if !defined(__cplusplus)
#include <assert.h>
/* static_assert fallback */
#if !defined(_MSC_VER) && !defined(static_assert)
#define static_assert _Static_assert
#endif
#endif
#endif