1 /* Functions to copy data between possibly-unaligned byte buffers
2 and machine integers, fixing the endianness.
3
4 Written by Zack Weinberg <zackw at panix.com> in 2017.
5 To the extent possible under law, Zack Weinberg has waived all
6 copyright and related or neighboring rights to this work.
7
8 See https://creativecommons.org/publicdomain/zero/1.0/ for further
9 details. */
10
11 #ifndef _CRYPT_BYTEORDER_H
12 #define _CRYPT_BYTEORDER_H 1
13
14 static inline uint32_t
15 le32_to_cpu (const unsigned char *buf)
16 {
17 return ((((uint32_t)buf[0]) << 0) |
18 (((uint32_t)buf[1]) << 8) |
19 (((uint32_t)buf[2]) << 16) |
20 (((uint32_t)buf[3]) << 24) );
21 }
22
23 static inline uint32_t
24 be32_to_cpu (const unsigned char *buf)
25 {
26 return ((((uint32_t)buf[0]) << 24) |
27 (((uint32_t)buf[1]) << 16) |
28 (((uint32_t)buf[2]) << 8) |
29 (((uint32_t)buf[3]) << 0) );
30 }
31
32 static inline uint64_t
33 le64_to_cpu (const unsigned char *buf)
34 {
35 return ((((uint64_t)buf[0]) << 0) |
36 (((uint64_t)buf[1]) << 8) |
37 (((uint64_t)buf[2]) << 16) |
38 (((uint64_t)buf[3]) << 24) |
39 (((uint64_t)buf[4]) << 32) |
40 (((uint64_t)buf[5]) << 40) |
41 (((uint64_t)buf[6]) << 48) |
42 (((uint64_t)buf[7]) << 56) );
43 }
44
45 static inline uint64_t
46 be64_to_cpu (const unsigned char *buf)
47 {
48 return ((((uint64_t)buf[0]) << 56) |
49 (((uint64_t)buf[1]) << 48) |
50 (((uint64_t)buf[2]) << 40) |
51 (((uint64_t)buf[3]) << 32) |
52 (((uint64_t)buf[4]) << 24) |
53 (((uint64_t)buf[5]) << 16) |
54 (((uint64_t)buf[6]) << 8) |
55 (((uint64_t)buf[7]) << 0) );
56 }
57
58 static inline void
59 cpu_to_le32 (unsigned char *buf, uint32_t n)
60 {
61 buf[0] = (unsigned char)((n & 0x000000FFu) >> 0);
62 buf[1] = (unsigned char)((n & 0x0000FF00u) >> 8);
63 buf[2] = (unsigned char)((n & 0x00FF0000u) >> 16);
64 buf[3] = (unsigned char)((n & 0xFF000000u) >> 24);
65 }
66
67 static inline void
68 cpu_to_be32 (unsigned char *buf, uint32_t n)
69 {
70 buf[0] = (unsigned char)((n & 0xFF000000u) >> 24);
71 buf[1] = (unsigned char)((n & 0x00FF0000u) >> 16);
72 buf[2] = (unsigned char)((n & 0x0000FF00u) >> 8);
73 buf[3] = (unsigned char)((n & 0x000000FFu) >> 0);
74 }
75
76 static inline void
77 cpu_to_le64 (unsigned char *buf, uint64_t n)
78 {
79 buf[0] = (unsigned char)((n & 0x00000000000000FFull) >> 0);
80 buf[1] = (unsigned char)((n & 0x000000000000FF00ull) >> 8);
81 buf[2] = (unsigned char)((n & 0x0000000000FF0000ull) >> 16);
82 buf[3] = (unsigned char)((n & 0x00000000FF000000ull) >> 24);
83 buf[4] = (unsigned char)((n & 0x000000FF00000000ull) >> 32);
84 buf[5] = (unsigned char)((n & 0x0000FF0000000000ull) >> 40);
85 buf[6] = (unsigned char)((n & 0x00FF000000000000ull) >> 48);
86 buf[7] = (unsigned char)((n & 0xFF00000000000000ull) >> 56);
87 }
88
89 static inline void
90 cpu_to_be64 (unsigned char *buf, uint64_t n)
91 {
92 buf[0] = (unsigned char)((n & 0xFF00000000000000ull) >> 56);
93 buf[1] = (unsigned char)((n & 0x00FF000000000000ull) >> 48);
94 buf[2] = (unsigned char)((n & 0x0000FF0000000000ull) >> 40);
95 buf[3] = (unsigned char)((n & 0x000000FF00000000ull) >> 32);
96 buf[4] = (unsigned char)((n & 0x00000000FF000000ull) >> 24);
97 buf[5] = (unsigned char)((n & 0x0000000000FF0000ull) >> 16);
98 buf[6] = (unsigned char)((n & 0x000000000000FF00ull) >> 8);
99 buf[7] = (unsigned char)((n & 0x00000000000000FFull) >> 0);
100 }
101
102 /* Template: Define a function named cpu_to_<END><BITS>_vect that
103 takes a vector SRC of LEN integers, each of type uint<BITS>_t, and
104 writes them to the buffer DST in the endianness defined by END.
105 Caution: LEN is the number of vector elements, not the total size
106 of the buffers. */
107 #define VECTOR_CPU_TO(end, bits) VECTOR_CPU_TO_(end##bits, uint##bits##_t)
108 #define VECTOR_CPU_TO_(prim, stype) \
109 static inline void \
110 cpu_to_##prim##_vect(uint8_t *dst, const stype *src, size_t len) \
111 { \
112 while (len) \
113 { \
114 cpu_to_##prim(dst, *src); \
115 src += 1; \
116 dst += sizeof(stype); \
117 len -= 1; \
118 } \
119 } struct _swallow_semicolon
120
121 /* Template: Define a function named <END><BITS>_to_cpu_vect that
122 reads a vector of LEN integers, each of type uint<BITS>_t, from the
123 buffer SRC, in the endianness defined by END, and writes them to
124 the vector DST. Caution: LEN is the number of vector elements, not
125 the total size of the buffers. */
126 #define VECTOR_TO_CPU(end, bits) VECTOR_TO_CPU_(end##bits, uint##bits##_t)
127 #define VECTOR_TO_CPU_(prim, dtype) \
128 static inline void \
129 prim##_to_cpu_vect(dtype *dst, const uint8_t *src, size_t len) \
130 { \
131 while (len) \
132 { \
133 *dst = prim##_to_cpu(src); \
134 src += sizeof(dtype); \
135 dst += 1; \
136 len -= 1; \
137 } \
138 } struct _swallow_semicolon
139
140 /* These are the vectorized endianness-conversion functions that are
141 presently used. Add more as necessary. */
142 VECTOR_CPU_TO(be,32);
143 VECTOR_CPU_TO(be,64);
144 VECTOR_TO_CPU(be,32);
145 VECTOR_TO_CPU(be,64);
146
147 /* Alternative names used in code derived from Colin Percival's
148 cryptography libraries. */
149 #define le32enc cpu_to_le32
150 #define le32dec le32_to_cpu
151 #define le64enc cpu_to_le64
152 #define le64dec le64_to_cpu
153
154 #define be32enc cpu_to_be32
155 #define be32dec be32_to_cpu
156 #define be64enc cpu_to_be64
157 #define be64dec be64_to_cpu
158
159 #define be32enc_vect cpu_to_be32_vect
160 #define be32dec_vect be32_to_cpu_vect
161 #define be64enc_vect cpu_to_be64_vect
162 #define be64dec_vect be64_to_cpu_vect
163
164 #endif /* byteorder.h */