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
33static inline int
34crypto_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
41static inline uint8_t
42crypto_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
49static inline int
50crypto_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
57static inline uint8_t
58crypto_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
65static inline int
66crypto_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
73static inline uint8_t
74crypto_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
81static inline int
82crypto_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
89static inline uint8_t
90crypto_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
102static inline uint32_t
103crypto_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
119static inline void
120crypto_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
133static inline uint64_t
134crypto_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
150static inline void
151crypto_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
164static inline uint32_t
165crypto_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
181static inline void
182crypto_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
190static inline uint32_t
191crypto_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
198static inline uint32_t
199crypto_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
206static inline uint64_t
207crypto_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
214static inline uint64_t
215crypto_ror_u64(uint64_t v, size_t shift)
216{
217	return (v << (64 - shift)) | (v >> shift);
218}
219#endif
220
221#endif
222