1 /* $OpenBSD: crypto_internal.h,v 1.10 2024/04/17 14:43:37 jsing Exp $ */
2 /*
3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <endian.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <string.h>
22
23 #ifndef HEADER_CRYPTO_INTERNAL_H
24 #define HEADER_CRYPTO_INTERNAL_H
25
26 #define CTASSERT(x) \
27 extern char _ctassert[(x) ? 1 : -1] __attribute__((__unused__))
28
29 /*
30 * Constant time operations for uint8_t.
31 */
32 #ifndef HAVE_CRYPTO_CT_NE_ZERO_U8
33 static inline int
crypto_ct_ne_zero_u8(uint8_t v)34 crypto_ct_ne_zero_u8(uint8_t v)
35 {
36 return (uint8_t)(v | ~(v - 1)) >> ((sizeof(v) * 8) - 1);
37 }
38 #endif
39
40 #ifndef HAVE_CRYPTO_CT_NE_ZERO_MASK_U8
41 static inline uint8_t
crypto_ct_ne_zero_mask_u8(uint8_t v)42 crypto_ct_ne_zero_mask_u8(uint8_t v)
43 {
44 return 0 - crypto_ct_ne_zero_u8(v);
45 }
46 #endif
47
48 #ifndef HAVE_CRYPTO_CT_EQ_ZERO_U8
49 static inline int
crypto_ct_eq_zero_u8(uint8_t v)50 crypto_ct_eq_zero_u8(uint8_t v)
51 {
52 return 1 - crypto_ct_ne_zero_u8(v);
53 }
54 #endif
55
56 #ifndef HAVE_CRYPTO_CT_EQ_ZERO_MASK_U8
57 static inline uint8_t
crypto_ct_eq_zero_mask_u8(uint8_t v)58 crypto_ct_eq_zero_mask_u8(uint8_t v)
59 {
60 return 0 - crypto_ct_eq_zero_u8(v);
61 }
62 #endif
63
64 #ifndef HAVE_CRYPTO_CT_NE_U8
65 static inline int
crypto_ct_ne_u8(uint8_t a,uint8_t b)66 crypto_ct_ne_u8(uint8_t a, uint8_t b)
67 {
68 return crypto_ct_ne_zero_u8(a - b);
69 }
70 #endif
71
72 #ifndef HAVE_CRYPTO_CT_NE_MASK_U8
73 static inline uint8_t
crypto_ct_ne_mask_u8(uint8_t a,uint8_t b)74 crypto_ct_ne_mask_u8(uint8_t a, uint8_t b)
75 {
76 return 0 - crypto_ct_ne_u8(a, b);
77 }
78 #endif
79
80 #ifndef HAVE_CRYPTO_CT_EQ_U8
81 static inline int
crypto_ct_eq_u8(uint8_t a,uint8_t b)82 crypto_ct_eq_u8(uint8_t a, uint8_t b)
83 {
84 return crypto_ct_eq_zero_u8(a - b);
85 }
86 #endif
87
88 #ifndef HAVE_CRYPTO_CT_EQ_MASK_U8
89 static inline uint8_t
crypto_ct_eq_mask_u8(uint8_t a,uint8_t b)90 crypto_ct_eq_mask_u8(uint8_t a, uint8_t b)
91 {
92 return 0 - crypto_ct_eq_u8(a, b);
93 }
94 #endif
95
96 /*
97 * crypto_load_be32toh() loads a 32 bit unsigned big endian value as a 32 bit
98 * unsigned host endian value, from the specified address in memory. The memory
99 * address may have any alignment.
100 */
101 #ifndef HAVE_CRYPTO_LOAD_BE32TOH
102 static inline uint32_t
crypto_load_be32toh(const uint8_t * src)103 crypto_load_be32toh(const uint8_t *src)
104 {
105 uint32_t v;
106
107 memcpy(&v, src, sizeof(v));
108
109 return be32toh(v);
110 }
111 #endif
112
113 /*
114 * crypto_store_htobe32() stores a 32 bit unsigned host endian value as a 32 bit
115 * unsigned big endian value, at the specified address in memory. The memory
116 * address may have any alignment.
117 */
118 #ifndef HAVE_CRYPTO_STORE_HTOBE32
119 static inline void
crypto_store_htobe32(uint8_t * dst,uint32_t v)120 crypto_store_htobe32(uint8_t *dst, uint32_t v)
121 {
122 v = htobe32(v);
123 memcpy(dst, &v, sizeof(v));
124 }
125 #endif
126
127 /*
128 * crypto_load_be64toh() loads a 64 bit unsigned big endian value as a 64 bit
129 * unsigned host endian value, from the specified address in memory. The memory
130 * address may have any alignment.
131 */
132 #ifndef HAVE_CRYPTO_LOAD_BE64TOH
133 static inline uint64_t
crypto_load_be64toh(const uint8_t * src)134 crypto_load_be64toh(const uint8_t *src)
135 {
136 uint64_t v;
137
138 memcpy(&v, src, sizeof(v));
139
140 return be64toh(v);
141 }
142 #endif
143
144 /*
145 * crypto_store_htobe64() stores a 64 bit unsigned host endian value as a 64 bit
146 * unsigned big endian value, at the specified address in memory. The memory
147 * address may have any alignment.
148 */
149 #ifndef HAVE_CRYPTO_STORE_HTOBE64
150 static inline void
crypto_store_htobe64(uint8_t * dst,uint64_t v)151 crypto_store_htobe64(uint8_t *dst, uint64_t v)
152 {
153 v = htobe64(v);
154 memcpy(dst, &v, sizeof(v));
155 }
156 #endif
157
158 /*
159 * crypto_load_le32toh() loads a 32 bit unsigned little endian value as a 32 bit
160 * unsigned host endian value, from the specified address in memory. The memory
161 * address may have any alignment.
162 */
163 #ifndef HAVE_CRYPTO_LOAD_LE32TOH
164 static inline uint32_t
crypto_load_le32toh(const uint8_t * src)165 crypto_load_le32toh(const uint8_t *src)
166 {
167 uint32_t v;
168
169 memcpy(&v, src, sizeof(v));
170
171 return le32toh(v);
172 }
173 #endif
174
175 /*
176 * crypto_store_htole32() stores a 32 bit unsigned host endian value as a 32 bit
177 * unsigned little endian value, at the specified address in memory. The memory
178 * address may have any alignment.
179 */
180 #ifndef HAVE_CRYPTO_STORE_HTOLE32
181 static inline void
crypto_store_htole32(uint8_t * dst,uint32_t v)182 crypto_store_htole32(uint8_t *dst, uint32_t v)
183 {
184 v = htole32(v);
185 memcpy(dst, &v, sizeof(v));
186 }
187 #endif
188
189 #ifndef HAVE_CRYPTO_ROL_U32
190 static inline uint32_t
crypto_rol_u32(uint32_t v,size_t shift)191 crypto_rol_u32(uint32_t v, size_t shift)
192 {
193 return (v << shift) | (v >> (32 - shift));
194 }
195 #endif
196
197 #ifndef HAVE_CRYPTO_ROR_U32
198 static inline uint32_t
crypto_ror_u32(uint32_t v,size_t shift)199 crypto_ror_u32(uint32_t v, size_t shift)
200 {
201 return (v << (32 - shift)) | (v >> shift);
202 }
203 #endif
204
205 #ifndef HAVE_CRYPTO_ROL_U64
206 static inline uint64_t
crypto_rol_u64(uint64_t v,size_t shift)207 crypto_rol_u64(uint64_t v, size_t shift)
208 {
209 return (v << shift) | (v >> (64 - shift));
210 }
211 #endif
212
213 #ifndef HAVE_CRYPTO_ROR_U64
214 static inline uint64_t
crypto_ror_u64(uint64_t v,size_t shift)215 crypto_ror_u64(uint64_t v, size_t shift)
216 {
217 return (v << (64 - shift)) | (v >> shift);
218 }
219 #endif
220
221 #endif
222