1 /*
2 * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #ifndef OPENSSL_BYTEORDER_H
11 # define OPENSSL_BYTEORDER_H
12 # pragma once
13
14 # include <openssl/e_os2.h>
15 # include <string.h>
16
17 /*
18 * "Modern" compilers do a decent job of optimising these functions to just a
19 * couple of instruction ([swap +] store, or load [+ swap]) when either no
20 * swapping is required, or a suitable swap instruction is available.
21 */
22
23 # if defined(_MSC_VER) && _MSC_VER>=1300
24 # include <stdlib.h>
25 # pragma intrinsic(_byteswap_ushort)
26 # pragma intrinsic(_byteswap_ulong)
27 # pragma intrinsic(_byteswap_uint64)
28 # define OSSL_HTOBE16(x) _byteswap_ushort(x)
29 # define OSSL_HTOBE32(x) _byteswap_ulong(x)
30 # define OSSL_HTOBE64(x) _byteswap_uint64(x)
31 # define OSSL_BE16TOH(x) _byteswap_ushort(x)
32 # define OSSL_BE32TOH(x) _byteswap_ulong(x)
33 # define OSSL_BE64TOH(x) _byteswap_uint64(x)
34 # define OSSL_HTOLE16(x) (x)
35 # define OSSL_HTOLE32(x) (x)
36 # define OSSL_HTOLE64(x) (x)
37 # define OSSL_LE16TOH(x) (x)
38 # define OSSL_LE32TOH(x) (x)
39 # define OSSL_LE64TOH(x) (x)
40
41 # elif defined(__GLIBC__) && defined(__GLIBC_PREREQ)
42 # if (__GLIBC_PREREQ(2, 19)) && defined(_DEFAULT_SOURCE)
43 # include <endian.h>
44 # define OSSL_HTOBE16(x) htobe16(x)
45 # define OSSL_HTOBE32(x) htobe32(x)
46 # define OSSL_HTOBE64(x) htobe64(x)
47 # define OSSL_BE16TOH(x) be16toh(x)
48 # define OSSL_BE32TOH(x) be32toh(x)
49 # define OSSL_BE64TOH(x) be64toh(x)
50 # define OSSL_HTOLE16(x) htole16(x)
51 # define OSSL_HTOLE32(x) htole32(x)
52 # define OSSL_HTOLE64(x) htole64(x)
53 # define OSSL_LE16TOH(x) le16toh(x)
54 # define OSSL_LE32TOH(x) le32toh(x)
55 # define OSSL_LE64TOH(x) le64toh(x)
56 # endif
57
58 # elif defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__)
59 # if defined(__OpenBSD__)
60 # include <sys/types.h>
61 # else
62 # include <sys/endian.h>
63 # endif
64 # define OSSL_HTOBE16(x) htobe16(x)
65 # define OSSL_HTOBE32(x) htobe32(x)
66 # define OSSL_HTOBE64(x) htobe64(x)
67 # define OSSL_BE16TOH(x) be16toh(x)
68 # define OSSL_BE32TOH(x) be32toh(x)
69 # define OSSL_BE64TOH(x) be64toh(x)
70 # define OSSL_HTOLE16(x) htole16(x)
71 # define OSSL_HTOLE32(x) htole32(x)
72 # define OSSL_HTOLE64(x) htole64(x)
73 # define OSSL_LE16TOH(x) le16toh(x)
74 # define OSSL_LE32TOH(x) le32toh(x)
75 # define OSSL_LE64TOH(x) le64toh(x)
76
77 # elif defined(__APPLE__)
78 # include <libkern/OSByteOrder.h>
79 # define OSSL_HTOBE16(x) OSSwapHostToBigInt16(x)
80 # define OSSL_HTOBE32(x) OSSwapHostToBigInt32(x)
81 # define OSSL_HTOBE64(x) OSSwapHostToBigInt64(x)
82 # define OSSL_BE16TOH(x) OSSwapBigToHostInt16(x)
83 # define OSSL_BE32TOH(x) OSSwapBigToHostInt32(x)
84 # define OSSL_BE64TOH(x) OSSwapBigToHostInt64(x)
85 # define OSSL_HTOLE16(x) OSSwapHostToLittleInt16(x)
86 # define OSSL_HTOLE32(x) OSSwapHostToLittleInt32(x)
87 # define OSSL_HTOLE64(x) OSSwapHostToLittleInt64(x)
88 # define OSSL_LE16TOH(x) OSSwapLittleToHostInt16(x)
89 # define OSSL_LE32TOH(x) OSSwapLittleToHostInt32(x)
90 # define OSSL_LE64TOH(x) OSSwapLittleToHostInt64(x)
91
92 # endif
93
94 static ossl_inline ossl_unused unsigned char *
OPENSSL_store_u16_le(unsigned char * out,uint16_t val)95 OPENSSL_store_u16_le(unsigned char *out, uint16_t val)
96 {
97 # ifdef OSSL_HTOLE16
98 uint16_t t = OSSL_HTOLE16(val);
99
100 memcpy(out, (unsigned char *)&t, 2);
101 return out + 2;
102 # else
103 *out++ = (val & 0xff);
104 *out++ = (val >> 8) & 0xff;
105 return out;
106 # endif
107 }
108
109 static ossl_inline ossl_unused unsigned char *
OPENSSL_store_u16_be(unsigned char * out,uint16_t val)110 OPENSSL_store_u16_be(unsigned char *out, uint16_t val)
111 {
112 # ifdef OSSL_HTOBE16
113 uint16_t t = OSSL_HTOBE16(val);
114
115 memcpy(out, (unsigned char *)&t, 2);
116 return out + 2;
117 # else
118 *out++ = (val >> 8) & 0xff;
119 *out++ = (val & 0xff);
120 return out;
121 # endif
122 }
123
124 static ossl_inline ossl_unused unsigned char *
OPENSSL_store_u32_le(unsigned char * out,uint32_t val)125 OPENSSL_store_u32_le(unsigned char *out, uint32_t val)
126 {
127 # ifdef OSSL_HTOLE32
128 uint32_t t = OSSL_HTOLE32(val);
129
130 memcpy(out, (unsigned char *)&t, 4);
131 return out + 4;
132 # else
133 *out++ = (val & 0xff);
134 *out++ = (val >> 8) & 0xff;
135 *out++ = (val >> 16) & 0xff;
136 *out++ = (val >> 24) & 0xff;
137 return out;
138 # endif
139 }
140
141 static ossl_inline ossl_unused unsigned char *
OPENSSL_store_u32_be(unsigned char * out,uint32_t val)142 OPENSSL_store_u32_be(unsigned char *out, uint32_t val)
143 {
144 # ifdef OSSL_HTOBE32
145 uint32_t t = OSSL_HTOBE32(val);
146
147 memcpy(out, (unsigned char *)&t, 4);
148 return out + 4;
149 # else
150 *out++ = (val >> 24) & 0xff;
151 *out++ = (val >> 16) & 0xff;
152 *out++ = (val >> 8) & 0xff;
153 *out++ = (val & 0xff);
154 return out;
155 # endif
156 }
157
158 static ossl_inline ossl_unused unsigned char *
OPENSSL_store_u64_le(unsigned char * out,uint64_t val)159 OPENSSL_store_u64_le(unsigned char *out, uint64_t val)
160 {
161 # ifdef OSSL_HTOLE64
162 uint64_t t = OSSL_HTOLE64(val);
163
164 memcpy(out, (unsigned char *)&t, 8);
165 return out + 8;
166 # else
167 *out++ = (val & 0xff);
168 *out++ = (val >> 8) & 0xff;
169 *out++ = (val >> 16) & 0xff;
170 *out++ = (val >> 24) & 0xff;
171 *out++ = (val >> 32) & 0xff;
172 *out++ = (val >> 40) & 0xff;
173 *out++ = (val >> 48) & 0xff;
174 *out++ = (val >> 56) & 0xff;
175 return out;
176 # endif
177 }
178
179 static ossl_inline ossl_unused unsigned char *
OPENSSL_store_u64_be(unsigned char * out,uint64_t val)180 OPENSSL_store_u64_be(unsigned char *out, uint64_t val)
181 {
182 # ifdef OSSL_HTOLE64
183 uint64_t t = OSSL_HTOBE64(val);
184
185 memcpy(out, (unsigned char *)&t, 8);
186 return out + 8;
187 # else
188 *out++ = (val >> 56) & 0xff;
189 *out++ = (val >> 48) & 0xff;
190 *out++ = (val >> 40) & 0xff;
191 *out++ = (val >> 32) & 0xff;
192 *out++ = (val >> 24) & 0xff;
193 *out++ = (val >> 16) & 0xff;
194 *out++ = (val >> 8) & 0xff;
195 *out++ = (val & 0xff);
196 return out;
197 # endif
198 }
199
200 static ossl_inline ossl_unused const unsigned char *
OPENSSL_load_u16_le(uint16_t * val,const unsigned char * in)201 OPENSSL_load_u16_le(uint16_t *val, const unsigned char *in)
202 {
203 # ifdef OSSL_LE16TOH
204 uint16_t t;
205
206 memcpy((unsigned char *)&t, in, 2);
207 *val = OSSL_LE16TOH(t);
208 return in + 2;
209 # else
210 uint16_t b0 = *in++;
211 uint16_t b1 = *in++;
212
213 *val = b0 | (b1 << 8);
214 return in;
215 #endif
216 }
217
218 static ossl_inline ossl_unused const unsigned char *
OPENSSL_load_u16_be(uint16_t * val,const unsigned char * in)219 OPENSSL_load_u16_be(uint16_t *val, const unsigned char *in)
220 {
221 # ifdef OSSL_LE16TOH
222 uint16_t t;
223
224 memcpy((unsigned char *)&t, in, 2);
225 *val = OSSL_BE16TOH(t);
226 return in + 2;
227 # else
228 uint16_t b1 = *in++;
229 uint16_t b0 = *in++;
230
231 *val = b0 | (b1 << 8);
232 return in;
233 #endif
234 }
235
236 static ossl_inline ossl_unused const unsigned char *
OPENSSL_load_u32_le(uint32_t * val,const unsigned char * in)237 OPENSSL_load_u32_le(uint32_t *val, const unsigned char *in)
238 {
239 # ifdef OSSL_LE32TOH
240 uint32_t t;
241
242 memcpy((unsigned char *)&t, in, 4);
243 *val = OSSL_LE32TOH(t);
244 return in + 4;
245 # else
246 uint32_t b0 = *in++;
247 uint32_t b1 = *in++;
248 uint32_t b2 = *in++;
249 uint32_t b3 = *in++;
250
251 *val = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
252 return in;
253 #endif
254 }
255
256 static ossl_inline ossl_unused const unsigned char *
OPENSSL_load_u32_be(uint32_t * val,const unsigned char * in)257 OPENSSL_load_u32_be(uint32_t *val, const unsigned char *in)
258 {
259 # ifdef OSSL_LE32TOH
260 uint32_t t;
261
262 memcpy((unsigned char *)&t, in, 4);
263 *val = OSSL_BE32TOH(t);
264 return in + 4;
265 # else
266 uint32_t b3 = *in++;
267 uint32_t b2 = *in++;
268 uint32_t b1 = *in++;
269 uint32_t b0 = *in++;
270
271 *val = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
272 return in;
273 #endif
274 }
275
276 static ossl_inline ossl_unused const unsigned char *
OPENSSL_load_u64_le(uint64_t * val,const unsigned char * in)277 OPENSSL_load_u64_le(uint64_t *val, const unsigned char *in)
278 {
279 # ifdef OSSL_LE64TOH
280 uint64_t t;
281
282 memcpy((unsigned char *)&t, in, 8);
283 *val = OSSL_LE64TOH(t);
284 return in + 8;
285 # else
286 uint64_t b0 = *in++;
287 uint64_t b1 = *in++;
288 uint64_t b2 = *in++;
289 uint64_t b3 = *in++;
290 uint64_t b4 = *in++;
291 uint64_t b5 = *in++;
292 uint64_t b6 = *in++;
293 uint64_t b7 = *in++;
294
295 *val = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)
296 | (b4 << 32) | (b5 << 40) | (b6 << 48) | (b7 << 56);
297 return in;
298 #endif
299 }
300
301 static ossl_inline ossl_unused const unsigned char *
OPENSSL_load_u64_be(uint64_t * val,const unsigned char * in)302 OPENSSL_load_u64_be(uint64_t *val, const unsigned char *in)
303 {
304 # ifdef OSSL_LE64TOH
305 uint64_t t;
306
307 memcpy((unsigned char *)&t, in, 8);
308 *val = OSSL_BE64TOH(t);
309 return in + 8;
310 # else
311 uint64_t b7 = *in++;
312 uint64_t b6 = *in++;
313 uint64_t b5 = *in++;
314 uint64_t b4 = *in++;
315 uint64_t b3 = *in++;
316 uint64_t b2 = *in++;
317 uint64_t b1 = *in++;
318 uint64_t b0 = *in++;
319
320 *val = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)
321 | (b4 << 32) | (b5 << 40) | (b6 << 48) | (b7 << 56);
322 return in;
323 #endif
324 }
325
326 # undef OSSL_HTOBE16
327 # undef OSSL_HTOBE32
328 # undef OSSL_HTOBE64
329 # undef OSSL_BE16TOH
330 # undef OSSL_BE32TOH
331 # undef OSSL_BE64TOH
332 # undef OSSL_HTOLE16
333 # undef OSSL_HTOLE32
334 # undef OSSL_HTOLE64
335 # undef OSSL_LE16TOH
336 # undef OSSL_LE32TOH
337 # undef OSSL_LE64TOH
338
339 #endif
340