1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #ifndef BSL_BYTES_H
17 #define BSL_BYTES_H
18
19 #include <stdint.h>
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 /**
26 * @brief convert uint8_t byte stream to uint16_t data
27 *
28 * @attention data cannot be empty
29 *
30 * @param data [IN] uint8_t byte stream
31 *
32 * @return uint16_t converted data
33 */
BSL_ByteToUint16(const uint8_t * data)34 static inline uint16_t BSL_ByteToUint16(const uint8_t *data)
35 {
36 /** Byte 0 is shifted by 8 bits to the left, and byte 1 remains unchanged. uint16_t is obtained after OR */
37 return ((uint16_t)data[0] << 8) | ((uint16_t)data[1]);
38 }
39
40 /**
41 * @brief convert uint16_t data to uint8_t byte stream
42 *
43 * @attention data cannot be empty
44 *
45 * @param num [IN] data to be converted
46 * @param data [OUT] converted data
47 */
BSL_Uint16ToByte(uint16_t num,uint8_t * data)48 static inline void BSL_Uint16ToByte(uint16_t num, uint8_t *data)
49 {
50 /** convert to byte stream */
51 data[0] = (uint8_t)(num >> 8); // data is shifted rightwards by 8 bits and put in byte 0
52 data[1] = (uint8_t)(num & 0xffu); // data AND 0xffu, put in byte 1
53 return;
54 }
55
56 /**
57 * @brief convert uint8_t byte stream to uint24_t data
58 *
59 * @attention data cannot be empty
60 *
61 * @param data [IN] uint8_t byte stream
62 *
63 * @return uint24_t, converted data
64 */
BSL_ByteToUint24(const uint8_t * data)65 static inline uint32_t BSL_ByteToUint24(const uint8_t *data)
66 {
67 /** Byte 0 is shifted left by 16 bits, byte 1 is shifted left by 8 bits, and byte 2 remains unchanged,
68 uint24_t is obtained after the OR operation. */
69 return ((uint32_t)data[0] << 16) | ((uint32_t)data[1] << 8) | ((uint32_t)data[2]);
70 }
71
72 /**
73 * @brief convert uint24_t data to uint8_t byte stream
74 *
75 * @attention data cannot be empty
76 *
77 * @param num [IN] data to be converted
78 * @param data [OUT] converted data
79 */
BSL_Uint24ToByte(uint32_t num,uint8_t * data)80 static inline void BSL_Uint24ToByte(uint32_t num, uint8_t *data)
81 {
82 /** convert to byte stream */
83 data[0] = (uint8_t)(num >> 16); // data is shifted rightwards by 16 bits and put in byte 0
84 data[1] = (uint8_t)(num >> 8); // data is shifted rightwards by 8 bits and placed in byte 1
85 data[2] = (uint8_t)(num & 0xffu); // data AND 0xffu, put in byte 2
86 return;
87 }
88
89 /**
90 * @brief convert uint8_t byte stream to uint32_t data
91 *
92 * @attention data cannot be empty
93 *
94 * @param data [IN] uint8_t byte stream
95 *
96 * @return uint32_t, converted data
97 */
BSL_ByteToUint32(const uint8_t * data)98 static inline uint32_t BSL_ByteToUint32(const uint8_t *data)
99 {
100 /** Byte 0 is shifted leftward by 24 bits, byte 1 is shifted leftward by 16 bits,
101 byte 2 is shifted leftward by 8 bits, and byte 3 remains unchanged, uint32_t is obtained after OR operation. */
102 return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) | ((uint32_t)data[2] << 8) | ((uint32_t)data[3]);
103 }
104
105 /**
106 * @brief convert uint8_t byte stream to uint48_t data
107 *
108 * @attention data cannot be empty
109 *
110 * @param data [IN] uint8_t byte stream
111 *
112 * @return uint48_t, converted data
113 */
BSL_ByteToUint48(const uint8_t * data)114 static inline uint64_t BSL_ByteToUint48(const uint8_t *data)
115 {
116 /** Byte 0 is shifted leftward by 40 bits, byte 1 is shifted leftward by 32 bits,
117 byte 2 is shifted leftward by 24 bits, byte 3 is shifted leftward by 16 bits,
118 byte 4 is shifted leftward by 8 bits, and byte 5 remains unchanged, uint48_t is obtained after OR operation. */
119 return ((uint64_t)data[0] << 40) | ((uint64_t)data[1] << 32) | ((uint64_t)data[2] << 24) |
120 ((uint64_t)data[3] << 16) | ((uint64_t)data[4] << 8) | ((uint64_t)data[5]);
121 }
122
123 /**
124 * @brief convert uint48_t data to uint8_t byte stream
125 *
126 * @attention data cannot be empty
127 *
128 * @param num [IN] data to be converted
129 * @param data [OUT] converted data
130 */
BSL_Uint48ToByte(uint64_t num,uint8_t * data)131 static inline void BSL_Uint48ToByte(uint64_t num, uint8_t *data)
132 {
133 /** convert to byte stream */
134 data[0] = (uint8_t)(num >> 40); // data is shifted rightwards by 40 bits and put in byte 0
135 data[1] = (uint8_t)(num >> 32); // data is shifted rightwards by 32 bits and put in byte 1
136 data[2] = (uint8_t)(num >> 24); // data is shifted rightwards by 24 bits and put in byte 2
137 data[3] = (uint8_t)(num >> 16); // data is shifted rightwards by 16 bits and put in byte 3
138 data[4] = (uint8_t)(num >> 8); // data is shifted rightwards by 8 bits and put in byte 4
139 data[5] = (uint8_t)(num & 0xffu); // data AND 0xffu, put in byte 5
140 return;
141 }
142
143 /**
144 * @brief convert uint8_t byte stream to uint64_t data
145 *
146 * @attention data cannot be empty
147 *
148 * @param data [IN] uint8_t byte stream
149 *
150 * @return uint32_t, converted data
151 */
BSL_ByteToUint64(const uint8_t * data)152 static inline uint64_t BSL_ByteToUint64(const uint8_t *data)
153 {
154 /** Byte 0 is shifted leftward by 56 bits, byte 1 is shifted leftward by 48 bits,
155 byte 2 is shifted leftward by 40 bits, byte 3 is shifted leftward by 32 bits,
156 byte 4 is shifted leftward by 24 bits, byte 5 is shifted leftward by 16 bits,
157 byte 6 is shifted leftward by 8 bits, and byte 7 remains unchanged, uint64_t is obtained after OR operation. */
158 return ((uint64_t)data[0] << 56) | ((uint64_t)data[1] << 48) | ((uint64_t)data[2] << 40) |
159 ((uint64_t)data[3] << 32) | ((uint64_t)data[4] << 24) | ((uint64_t)data[5] << 16) |
160 ((uint64_t)data[6] << 8) | ((uint64_t)data[7]);
161 }
162
163 /**
164 * @brief convert uint32_t data to uint8_t byte stream
165 *
166 * @attention data cannot be empty
167 *
168 * @param num [IN] data to be converted
169 * @param data [OUT] converted data
170 */
BSL_Uint32ToByte(uint32_t num,uint8_t * data)171 static inline void BSL_Uint32ToByte(uint32_t num, uint8_t *data)
172 {
173 /** convert to byte stream */
174 data[0] = (uint8_t)(num >> 24); // data is shifted rightwards by 24 bits and put in byte 0
175 data[1] = (uint8_t)(num >> 16); // data is shifted rightwards by 16 bits and put in byte 1
176 data[2] = (uint8_t)(num >> 8); // data is shifted rightwards by 8 bits and put in byte 2
177 data[3] = (uint8_t)(num & 0xffu); // data AND 0xffu, put in byte 3
178 return;
179 }
180
181 /**
182 * @brief convert uint64_t data to uint8_t byte stream
183 *
184 * @attention data cannot be empty
185 *
186 * @param num [IN] data to be converted
187 * @param data [OUT] converted data
188 */
BSL_Uint64ToByte(uint64_t num,uint8_t * data)189 static inline void BSL_Uint64ToByte(uint64_t num, uint8_t *data)
190 {
191 /** convert to byte stream */
192 data[0] = (uint8_t)(num >> 56); // data is shifted rightwards by 56 bits and put in byte 0
193 data[1] = (uint8_t)(num >> 48); // data is shifted rightwards by 48 bits and put in byte 1
194 data[2] = (uint8_t)(num >> 40); // data is shifted rightwards by 40 bits and put in byte 2
195 data[3] = (uint8_t)(num >> 32); // data is shifted rightwards by 32 bits and put in byte 3
196 data[4] = (uint8_t)(num >> 24); // data is shifted rightwards by 24 bits and put in byte 4
197 data[5] = (uint8_t)(num >> 16); // data is shifted rightwards by 16 bits and put in byte 5
198 data[6] = (uint8_t)(num >> 8); // data is shifted rightwards by 8 bits and put in byte 6
199 data[7] = (uint8_t)(num & 0xffu); // data AND 0xffu, put in byte 7
200 return;
201 }
202
203 // if a's MSB is 0, output 0
204 // else if a' MSB is 1 output 0xffffffff
Uint32ConstTimeMsb(uint32_t a)205 static inline uint32_t Uint32ConstTimeMsb(uint32_t a)
206 {
207 // 31 == (4 * 8 - 1)
208 return 0u - (a >> 31);
209 }
210
211 // if a is 0, output 0xffffffff, else output 0
Uint32ConstTimeIsZero(uint32_t a)212 static inline uint32_t Uint32ConstTimeIsZero(uint32_t a)
213 {
214 return Uint32ConstTimeMsb(~a & (a - 1));
215 }
216
217 // if a == b, output 0xffffffff, else output 0
Uint32ConstTimeEqual(uint32_t a,uint32_t b)218 static inline uint32_t Uint32ConstTimeEqual(uint32_t a, uint32_t b)
219 {
220 return Uint32ConstTimeIsZero(a ^ b);
221 }
222
223 // if mask == 0xffffffff, return a,
224 // else if mask == 0, return b
Uint32ConstTimeSelect(uint32_t mask,uint32_t a,uint32_t b)225 static inline uint32_t Uint32ConstTimeSelect(uint32_t mask, uint32_t a, uint32_t b)
226 {
227 return ((mask) & a) | ((~mask) & b);
228 }
229
Uint8ConstTimeSelect(uint32_t mask,uint8_t a,uint8_t b)230 static inline uint32_t Uint8ConstTimeSelect(uint32_t mask, uint8_t a, uint8_t b)
231 {
232 return (((mask) & a) | ((~mask) & b)) & 0xff;
233 }
234
235 // if a < b, output 0xffffffff, else output 0
Uint32ConstTimeLt(uint32_t a,uint32_t b)236 static inline uint32_t Uint32ConstTimeLt(uint32_t a, uint32_t b)
237 {
238 return Uint32ConstTimeMsb(a ^ ((a ^ b) | ((a - b) ^ a)));
239 }
240
241 // if a >= b, output 0xffffffff, else output 0
Uint32ConstTimeGe(uint32_t a,uint32_t b)242 static inline uint32_t Uint32ConstTimeGe(uint32_t a, uint32_t b)
243 {
244 return ~Uint32ConstTimeLt(a, b);
245 }
246
247 // if a > b, output 0xffffffff, else output 0
Uint32ConstTimeGt(uint32_t a,uint32_t b)248 static inline uint32_t Uint32ConstTimeGt(uint32_t a, uint32_t b)
249 {
250 return Uint32ConstTimeLt(b, a);
251 }
252
Uint32ConstTimeLe(uint32_t a,uint32_t b)253 static inline uint32_t Uint32ConstTimeLe(uint32_t a, uint32_t b)
254 {
255 return Uint32ConstTimeGe(b, a);
256 }
257
258 // if a == b, return 0xffffffff, else return 0
ConstTimeMemcmp(uint8_t * a,uint8_t * b,uint32_t l)259 static inline uint32_t ConstTimeMemcmp(uint8_t *a, uint8_t *b, uint32_t l)
260 {
261 uint8_t r = 0;
262 for (uint32_t i = 0; i < l; i++) {
263 r |= a[i] ^ b[i];
264 }
265 return Uint32ConstTimeIsZero(r);
266 }
267
268 #ifdef __cplusplus
269 }
270 #endif /* __cplusplus */
271
272 #endif // BSL_BYTES_H
273