xref: /openbsd-src/lib/libcrypto/crypto_internal.h (revision dcc91c2622318df8f66a9bca2d2864253df1bfc3)
1 /*	$OpenBSD: crypto_internal.h,v 1.11 2024/08/11 13:02:39 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 #include "crypto_arch.h"
24 
25 #ifndef HEADER_CRYPTO_INTERNAL_H
26 #define HEADER_CRYPTO_INTERNAL_H
27 
28 #define CTASSERT(x) \
29     extern char _ctassert[(x) ? 1 : -1] __attribute__((__unused__))
30 
31 /*
32  * Constant time operations for uint8_t.
33  */
34 #ifndef HAVE_CRYPTO_CT_NE_ZERO_U8
35 static inline int
36 crypto_ct_ne_zero_u8(uint8_t v)
37 {
38 	return (uint8_t)(v | ~(v - 1)) >> ((sizeof(v) * 8) - 1);
39 }
40 #endif
41 
42 #ifndef HAVE_CRYPTO_CT_NE_ZERO_MASK_U8
43 static inline uint8_t
44 crypto_ct_ne_zero_mask_u8(uint8_t v)
45 {
46 	return 0 - crypto_ct_ne_zero_u8(v);
47 }
48 #endif
49 
50 #ifndef HAVE_CRYPTO_CT_EQ_ZERO_U8
51 static inline int
52 crypto_ct_eq_zero_u8(uint8_t v)
53 {
54 	return 1 - crypto_ct_ne_zero_u8(v);
55 }
56 #endif
57 
58 #ifndef HAVE_CRYPTO_CT_EQ_ZERO_MASK_U8
59 static inline uint8_t
60 crypto_ct_eq_zero_mask_u8(uint8_t v)
61 {
62 	return 0 - crypto_ct_eq_zero_u8(v);
63 }
64 #endif
65 
66 #ifndef HAVE_CRYPTO_CT_NE_U8
67 static inline int
68 crypto_ct_ne_u8(uint8_t a, uint8_t b)
69 {
70 	return crypto_ct_ne_zero_u8(a - b);
71 }
72 #endif
73 
74 #ifndef HAVE_CRYPTO_CT_NE_MASK_U8
75 static inline uint8_t
76 crypto_ct_ne_mask_u8(uint8_t a, uint8_t b)
77 {
78 	return 0 - crypto_ct_ne_u8(a, b);
79 }
80 #endif
81 
82 #ifndef HAVE_CRYPTO_CT_EQ_U8
83 static inline int
84 crypto_ct_eq_u8(uint8_t a, uint8_t b)
85 {
86 	return crypto_ct_eq_zero_u8(a - b);
87 }
88 #endif
89 
90 #ifndef HAVE_CRYPTO_CT_EQ_MASK_U8
91 static inline uint8_t
92 crypto_ct_eq_mask_u8(uint8_t a, uint8_t b)
93 {
94 	return 0 - crypto_ct_eq_u8(a, b);
95 }
96 #endif
97 
98 /*
99  * crypto_load_be32toh() loads a 32 bit unsigned big endian value as a 32 bit
100  * unsigned host endian value, from the specified address in memory. The memory
101  * address may have any alignment.
102  */
103 #ifndef HAVE_CRYPTO_LOAD_BE32TOH
104 static inline uint32_t
105 crypto_load_be32toh(const uint8_t *src)
106 {
107 	uint32_t v;
108 
109 	memcpy(&v, src, sizeof(v));
110 
111 	return be32toh(v);
112 }
113 #endif
114 
115 /*
116  * crypto_store_htobe32() stores a 32 bit unsigned host endian value as a 32 bit
117  * unsigned big endian value, at the specified address in memory. The memory
118  * address may have any alignment.
119  */
120 #ifndef HAVE_CRYPTO_STORE_HTOBE32
121 static inline void
122 crypto_store_htobe32(uint8_t *dst, uint32_t v)
123 {
124 	v = htobe32(v);
125 	memcpy(dst, &v, sizeof(v));
126 }
127 #endif
128 
129 /*
130  * crypto_load_be64toh() loads a 64 bit unsigned big endian value as a 64 bit
131  * unsigned host endian value, from the specified address in memory. The memory
132  * address may have any alignment.
133  */
134 #ifndef HAVE_CRYPTO_LOAD_BE64TOH
135 static inline uint64_t
136 crypto_load_be64toh(const uint8_t *src)
137 {
138 	uint64_t v;
139 
140 	memcpy(&v, src, sizeof(v));
141 
142 	return be64toh(v);
143 }
144 #endif
145 
146 /*
147  * crypto_store_htobe64() stores a 64 bit unsigned host endian value as a 64 bit
148  * unsigned big endian value, at the specified address in memory. The memory
149  * address may have any alignment.
150  */
151 #ifndef HAVE_CRYPTO_STORE_HTOBE64
152 static inline void
153 crypto_store_htobe64(uint8_t *dst, uint64_t v)
154 {
155 	v = htobe64(v);
156 	memcpy(dst, &v, sizeof(v));
157 }
158 #endif
159 
160 /*
161  * crypto_load_le32toh() loads a 32 bit unsigned little endian value as a 32 bit
162  * unsigned host endian value, from the specified address in memory. The memory
163  * address may have any alignment.
164  */
165 #ifndef HAVE_CRYPTO_LOAD_LE32TOH
166 static inline uint32_t
167 crypto_load_le32toh(const uint8_t *src)
168 {
169 	uint32_t v;
170 
171 	memcpy(&v, src, sizeof(v));
172 
173 	return le32toh(v);
174 }
175 #endif
176 
177 /*
178  * crypto_store_htole32() stores a 32 bit unsigned host endian value as a 32 bit
179  * unsigned little endian value, at the specified address in memory. The memory
180  * address may have any alignment.
181  */
182 #ifndef HAVE_CRYPTO_STORE_HTOLE32
183 static inline void
184 crypto_store_htole32(uint8_t *dst, uint32_t v)
185 {
186 	v = htole32(v);
187 	memcpy(dst, &v, sizeof(v));
188 }
189 #endif
190 
191 #ifndef HAVE_CRYPTO_ROL_U32
192 static inline uint32_t
193 crypto_rol_u32(uint32_t v, size_t shift)
194 {
195 	return (v << shift) | (v >> (32 - shift));
196 }
197 #endif
198 
199 #ifndef HAVE_CRYPTO_ROR_U32
200 static inline uint32_t
201 crypto_ror_u32(uint32_t v, size_t shift)
202 {
203 	return (v << (32 - shift)) | (v >> shift);
204 }
205 #endif
206 
207 #ifndef HAVE_CRYPTO_ROL_U64
208 static inline uint64_t
209 crypto_rol_u64(uint64_t v, size_t shift)
210 {
211 	return (v << shift) | (v >> (64 - shift));
212 }
213 #endif
214 
215 #ifndef HAVE_CRYPTO_ROR_U64
216 static inline uint64_t
217 crypto_ror_u64(uint64_t v, size_t shift)
218 {
219 	return (v << (64 - shift)) | (v >> shift);
220 }
221 #endif
222 
223 #endif
224