Botan: src/utils/loadstor.h Source File

Botan 1.10.16

loadstor.h
Go to the documentation of this file.
1 /*
2 * Load/Store Operators
3 * (C) 1999-2007 Jack Lloyd
4 * 2007 Yves Jerschow
5 *
6 * Distributed under the terms of the Botan license
7 */
8
9 #ifndef BOTAN_LOAD_STORE_H__
10 #define BOTAN_LOAD_STORE_H__
11
12 #include <botan/types.h>
13 #include <botan/bswap.h>
14 #include <botan/get_byte.h>
15 #include <cstring>
16
17 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
18
19 #if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
20
21 #define BOTAN_ENDIAN_N2B(x) (x)
22 #define BOTAN_ENDIAN_B2N(x) (x)
23
24 #define BOTAN_ENDIAN_N2L(x) reverse_bytes(x)
25 #define BOTAN_ENDIAN_L2N(x) reverse_bytes(x)
26
27 #elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
28
29 #define BOTAN_ENDIAN_N2L(x) (x)
30 #define BOTAN_ENDIAN_L2N(x) (x)
31
32 #define BOTAN_ENDIAN_N2B(x) reverse_bytes(x)
33 #define BOTAN_ENDIAN_B2N(x) reverse_bytes(x)
34
35 #endif
36
37 #endif
38
39 namespace Botan {
40
41 /**
42 * Make a u16bit from two bytes
43 * @param i0 the first byte
44 * @param i1 the second byte
45 * @return i0 || i1
46 */
47 inline u16bit make_u16bit(byte i0, byte i1)
48 {
49 return ((static_cast<u16bit>(i0) << 8) | i1);
50 }
51
52 /**
53 * Make a u32bit from four bytes
54 * @param i0 the first byte
55 * @param i1 the second byte
56 * @param i2 the third byte
57 * @param i3 the fourth byte
58 * @return i0 || i1 || i2 || i3
59 */
60 inline u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
61 {
62 return ((static_cast<u32bit>(i0) << 24) |
63 (static_cast<u32bit>(i1) << 16) |
64 (static_cast<u32bit>(i2) << 8) |
65 (static_cast<u32bit>(i3)));
66 }
67
68 /**
69 * Make a u32bit from eight bytes
70 * @param i0 the first byte
71 * @param i1 the second byte
72 * @param i2 the third byte
73 * @param i3 the fourth byte
74 * @param i4 the fifth byte
75 * @param i5 the sixth byte
76 * @param i6 the seventh byte
77 * @param i7 the eighth byte
78 * @return i0 || i1 || i2 || i3 || i4 || i5 || i6 || i7
79 */
80 inline u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3,
81 byte i4, byte i5, byte i6, byte i7)
82 {
83 return ((static_cast<u64bit>(i0) << 56) |
84 (static_cast<u64bit>(i1) << 48) |
85 (static_cast<u64bit>(i2) << 40) |
86 (static_cast<u64bit>(i3) << 32) |
87 (static_cast<u64bit>(i4) << 24) |
88 (static_cast<u64bit>(i5) << 16) |
89 (static_cast<u64bit>(i6) << 8) |
90 (static_cast<u64bit>(i7)));
91 }
92
93 /**
94 * Load a big-endian word
95 * @param in a pointer to some bytes
96 * @param off an offset into the array
97 * @return off'th T of in, as a big-endian value
98 */
99 template<typename T>
100 inline T load_be(const byte in[], size_t off)
101 {
102 in += off * sizeof(T);
103 T out = 0;
104 for(size_t i = 0; i != sizeof(T); ++i)
105 out = (out << 8) | in[i];
106 return out;
107 }
108
109 /**
110 * Load a little-endian word
111 * @param in a pointer to some bytes
112 * @param off an offset into the array
113 * @return off'th T of in, as a litte-endian value
114 */
115 template<typename T>
116 inline T load_le(const byte in[], size_t off)
117 {
118 in += off * sizeof(T);
119 T out = 0;
120 for(size_t i = 0; i != sizeof(T); ++i)
121 out = (out << 8) | in[sizeof(T)-1-i];
122 return out;
123 }
124
125 /**
126 * Load a big-endian u16bit
127 * @param in a pointer to some bytes
128 * @param off an offset into the array
129 * @return off'th u16bit of in, as a big-endian value
130 */
131 template<>
132 inline u16bit load_be<u16bit>(const byte in[], size_t off)
133 {
134 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
135 return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u16bit*>(in) + off));
136 #else
137 in += off * sizeof(u16bit);
138 return make_u16bit(in[0], in[1]);
139 #endif
140 }
141
142 /**
143 * Load a little-endian u16bit
144 * @param in a pointer to some bytes
145 * @param off an offset into the array
146 * @return off'th u16bit of in, as a little-endian value
147 */
148 template<>
149 inline u16bit load_le<u16bit>(const byte in[], size_t off)
150 {
151 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
152 return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u16bit*>(in) + off));
153 #else
154 in += off * sizeof(u16bit);
155 return make_u16bit(in[1], in[0]);
156 #endif
157 }
158
159 /**
160 * Load a big-endian u32bit
161 * @param in a pointer to some bytes
162 * @param off an offset into the array
163 * @return off'th u32bit of in, as a big-endian value
164 */
165 template<>
166 inline u32bit load_be<u32bit>(const byte in[], size_t off)
167 {
168 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
169 return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u32bit*>(in) + off));
170 #else
171 in += off * sizeof(u32bit);
172 return make_u32bit(in[0], in[1], in[2], in[3]);
173 #endif
174 }
175
176 /**
177 * Load a little-endian u32bit
178 * @param in a pointer to some bytes
179 * @param off an offset into the array
180 * @return off'th u32bit of in, as a little-endian value
181 */
182 template<>
183 inline u32bit load_le<u32bit>(const byte in[], size_t off)
184 {
185 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
186 return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u32bit*>(in) + off));
187 #else
188 in += off * sizeof(u32bit);
189 return make_u32bit(in[3], in[2], in[1], in[0]);
190 #endif
191 }
192
193 /**
194 * Load a big-endian u64bit
195 * @param in a pointer to some bytes
196 * @param off an offset into the array
197 * @return off'th u64bit of in, as a big-endian value
198 */
199 template<>
200 inline u64bit load_be<u64bit>(const byte in[], size_t off)
201 {
202 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
203 return BOTAN_ENDIAN_N2B(*(reinterpret_cast<const u64bit*>(in) + off));
204 #else
205 in += off * sizeof(u64bit);
206 return make_u64bit(in[0], in[1], in[2], in[3],
207 in[4], in[5], in[6], in[7]);
208 #endif
209 }
210
211 /**
212 * Load a little-endian u64bit
213 * @param in a pointer to some bytes
214 * @param off an offset into the array
215 * @return off'th u64bit of in, as a little-endian value
216 */
217 template<>
218 inline u64bit load_le<u64bit>(const byte in[], size_t off)
219 {
220 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
221 return BOTAN_ENDIAN_N2L(*(reinterpret_cast<const u64bit*>(in) + off));
222 #else
223 in += off * sizeof(u64bit);
224 return make_u64bit(in[7], in[6], in[5], in[4],
225 in[3], in[2], in[1], in[0]);
226 #endif
227 }
228
229 /**
230 * Load two little-endian words
231 * @param in a pointer to some bytes
232 * @param x0 where the first word will be written
233 * @param x1 where the second word will be written
234 */
235 template<typename T>
236 inline void load_le(const byte in[], T& x0, T& x1)
237 {
238 x0 = load_le<T>(in, 0);
239 x1 = load_le<T>(in, 1);
240 }
241
242 /**
243 * Load four little-endian words
244 * @param in a pointer to some bytes
245 * @param x0 where the first word will be written
246 * @param x1 where the second word will be written
247 * @param x2 where the third word will be written
248 * @param x3 where the fourth word will be written
249 */
250 template<typename T>
251 inline void load_le(const byte in[],
252 T& x0, T& x1, T& x2, T& x3)
253 {
254 x0 = load_le<T>(in, 0);
255 x1 = load_le<T>(in, 1);
256 x2 = load_le<T>(in, 2);
257 x3 = load_le<T>(in, 3);
258 }
259
260 /**
261 * Load eight little-endian words
262 * @param in a pointer to some bytes
263 * @param x0 where the first word will be written
264 * @param x1 where the second word will be written
265 * @param x2 where the third word will be written
266 * @param x3 where the fourth word will be written
267 * @param x4 where the fifth word will be written
268 * @param x5 where the sixth word will be written
269 * @param x6 where the seventh word will be written
270 * @param x7 where the eighth word will be written
271 */
272 template<typename T>
273 inline void load_le(const byte in[],
274 T& x0, T& x1, T& x2, T& x3,
275 T& x4, T& x5, T& x6, T& x7)
276 {
277 x0 = load_le<T>(in, 0);
278 x1 = load_le<T>(in, 1);
279 x2 = load_le<T>(in, 2);
280 x3 = load_le<T>(in, 3);
281 x4 = load_le<T>(in, 4);
282 x5 = load_le<T>(in, 5);
283 x6 = load_le<T>(in, 6);
284 x7 = load_le<T>(in, 7);
285 }
286
287 /**
288 * Load a variable number of little-endian words
289 * @param out the output array of words
290 * @param in the input array of bytes
291 * @param count how many words are in in
292 */
293 template<typename T>
294 inline void load_le(T out[],
295 const byte in[],
296 size_t count)
297 {
298 #if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS)
299 std::memcpy(out, in, sizeof(T)*count);
300
301 #if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
302 const size_t blocks = count - (count % 4);
303 const size_t left = count - blocks;
304
305 for(size_t i = 0; i != blocks; i += 4)
306 bswap_4(out + i);
307
308 for(size_t i = 0; i != left; ++i)
309 out[blocks+i] = reverse_bytes(out[blocks+i]);
310 #endif
311
312 #else
313 for(size_t i = 0; i != count; ++i)
314 out[i] = load_le<T>(in, i);
315 #endif
316 }
317
318 /**
319 * Load two big-endian words
320 * @param in a pointer to some bytes
321 * @param x0 where the first word will be written
322 * @param x1 where the second word will be written
323 */
324 template<typename T>
325 inline void load_be(const byte in[], T& x0, T& x1)
326 {
327 x0 = load_be<T>(in, 0);
328 x1 = load_be<T>(in, 1);
329 }
330
331 /**
332 * Load four big-endian words
333 * @param in a pointer to some bytes
334 * @param x0 where the first word will be written
335 * @param x1 where the second word will be written
336 * @param x2 where the third word will be written
337 * @param x3 where the fourth word will be written
338 */
339 template<typename T>
340 inline void load_be(const byte in[],
341 T& x0, T& x1, T& x2, T& x3)
342 {
343 x0 = load_be<T>(in, 0);
344 x1 = load_be<T>(in, 1);
345 x2 = load_be<T>(in, 2);
346 x3 = load_be<T>(in, 3);
347 }
348
349 /**
350 * Load eight big-endian words
351 * @param in a pointer to some bytes
352 * @param x0 where the first word will be written
353 * @param x1 where the second word will be written
354 * @param x2 where the third word will be written
355 * @param x3 where the fourth word will be written
356 * @param x4 where the fifth word will be written
357 * @param x5 where the sixth word will be written
358 * @param x6 where the seventh word will be written
359 * @param x7 where the eighth word will be written
360 */
361 template<typename T>
362 inline void load_be(const byte in[],
363 T& x0, T& x1, T& x2, T& x3,
364 T& x4, T& x5, T& x6, T& x7)
365 {
366 x0 = load_be<T>(in, 0);
367 x1 = load_be<T>(in, 1);
368 x2 = load_be<T>(in, 2);
369 x3 = load_be<T>(in, 3);
370 x4 = load_be<T>(in, 4);
371 x5 = load_be<T>(in, 5);
372 x6 = load_be<T>(in, 6);
373 x7 = load_be<T>(in, 7);
374 }
375
376 /**
377 * Load a variable number of big-endian words
378 * @param out the output array of words
379 * @param in the input array of bytes
380 * @param count how many words are in in
381 */
382 template<typename T>
383 inline void load_be(T out[],
384 const byte in[],
385 size_t count)
386 {
387 #if defined(BOTAN_TARGET_CPU_HAS_KNOWN_ENDIANNESS)
388 std::memcpy(out, in, sizeof(T)*count);
389
390 #if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
391 const size_t blocks = count - (count % 4);
392 const size_t left = count - blocks;
393
394 for(size_t i = 0; i != blocks; i += 4)
395 bswap_4(out + i);
396
397 for(size_t i = 0; i != left; ++i)
398 out[blocks+i] = reverse_bytes(out[blocks+i]);
399 #endif
400
401 #else
402 for(size_t i = 0; i != count; ++i)
403 out[i] = load_be<T>(in, i);
404 #endif
405 }
406
407 /**
408 * Store a big-endian u16bit
409 * @param in the input u16bit
410 * @param out the byte array to write to
411 */
412 inline void store_be(u16bit in, byte out[2])
413 {
414 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
415 *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_B2N(in);
416 #else
417 out[0] = get_byte(0, in);
418 out[1] = get_byte(1, in);
419 #endif
420 }
421
422 /**
423 * Store a little-endian u16bit
424 * @param in the input u16bit
425 * @param out the byte array to write to
426 */
427 inline void store_le(u16bit in, byte out[2])
428 {
429 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
430 *reinterpret_cast<u16bit*>(out) = BOTAN_ENDIAN_L2N(in);
431 #else
432 out[0] = get_byte(1, in);
433 out[1] = get_byte(0, in);
434 #endif
435 }
436
437 /**
438 * Store a big-endian u32bit
439 * @param in the input u32bit
440 * @param out the byte array to write to
441 */
442 inline void store_be(u32bit in, byte out[4])
443 {
444 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
445 *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_B2N(in);
446 #else
447 out[0] = get_byte(0, in);
448 out[1] = get_byte(1, in);
449 out[2] = get_byte(2, in);
450 out[3] = get_byte(3, in);
451 #endif
452 }
453
454 /**
455 * Store a little-endian u32bit
456 * @param in the input u32bit
457 * @param out the byte array to write to
458 */
459 inline void store_le(u32bit in, byte out[4])
460 {
461 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
462 *reinterpret_cast<u32bit*>(out) = BOTAN_ENDIAN_L2N(in);
463 #else
464 out[0] = get_byte(3, in);
465 out[1] = get_byte(2, in);
466 out[2] = get_byte(1, in);
467 out[3] = get_byte(0, in);
468 #endif
469 }
470
471 /**
472 * Store a big-endian u64bit
473 * @param in the input u64bit
474 * @param out the byte array to write to
475 */
476 inline void store_be(u64bit in, byte out[8])
477 {
478 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
479 *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_B2N(in);
480 #else
481 out[0] = get_byte(0, in);
482 out[1] = get_byte(1, in);
483 out[2] = get_byte(2, in);
484 out[3] = get_byte(3, in);
485 out[4] = get_byte(4, in);
486 out[5] = get_byte(5, in);
487 out[6] = get_byte(6, in);
488 out[7] = get_byte(7, in);
489 #endif
490 }
491
492 /**
493 * Store a little-endian u64bit
494 * @param in the input u64bit
495 * @param out the byte array to write to
496 */
497 inline void store_le(u64bit in, byte out[8])
498 {
499 #if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
500 *reinterpret_cast<u64bit*>(out) = BOTAN_ENDIAN_L2N(in);
501 #else
502 out[0] = get_byte(7, in);
503 out[1] = get_byte(6, in);
504 out[2] = get_byte(5, in);
505 out[3] = get_byte(4, in);
506 out[4] = get_byte(3, in);
507 out[5] = get_byte(2, in);
508 out[6] = get_byte(1, in);
509 out[7] = get_byte(0, in);
510 #endif
511 }
512
513 /**
514 * Store two little-endian words
515 * @param out the output byte array
516 * @param x0 the first word
517 * @param x1 the second word
518 */
519 template<typename T>
520 inline void store_le(byte out[], T x0, T x1)
521 {
522 store_le(x0, out + (0 * sizeof(T)));
523 store_le(x1, out + (1 * sizeof(T)));
524 }
525
526 /**
527 * Store two big-endian words
528 * @param out the output byte array
529 * @param x0 the first word
530 * @param x1 the second word
531 */
532 template<typename T>
533 inline void store_be(byte out[], T x0, T x1)
534 {
535 store_be(x0, out + (0 * sizeof(T)));
536 store_be(x1, out + (1 * sizeof(T)));
537 }
538
539 /**
540 * Store four little-endian words
541 * @param out the output byte array
542 * @param x0 the first word
543 * @param x1 the second word
544 * @param x2 the third word
545 * @param x3 the fourth word
546 */
547 template<typename T>
548 inline void store_le(byte out[], T x0, T x1, T x2, T x3)
549 {
550 store_le(x0, out + (0 * sizeof(T)));
551 store_le(x1, out + (1 * sizeof(T)));
552 store_le(x2, out + (2 * sizeof(T)));
553 store_le(x3, out + (3 * sizeof(T)));
554 }
555
556 /**
557 * Store four big-endian words
558 * @param out the output byte array
559 * @param x0 the first word
560 * @param x1 the second word
561 * @param x2 the third word
562 * @param x3 the fourth word
563 */
564 template<typename T>
565 inline void store_be(byte out[], T x0, T x1, T x2, T x3)
566 {
567 store_be(x0, out + (0 * sizeof(T)));
568 store_be(x1, out + (1 * sizeof(T)));
569 store_be(x2, out + (2 * sizeof(T)));
570 store_be(x3, out + (3 * sizeof(T)));
571 }
572
573 /**
574 * Store eight little-endian words
575 * @param out the output byte array
576 * @param x0 the first word
577 * @param x1 the second word
578 * @param x2 the third word
579 * @param x3 the fourth word
580 * @param x4 the fifth word
581 * @param x5 the sixth word
582 * @param x6 the seventh word
583 * @param x7 the eighth word
584 */
585 template<typename T>
586 inline void store_le(byte out[], T x0, T x1, T x2, T x3,
587 T x4, T x5, T x6, T x7)
588 {
589 store_le(x0, out + (0 * sizeof(T)));
590 store_le(x1, out + (1 * sizeof(T)));
591 store_le(x2, out + (2 * sizeof(T)));
592 store_le(x3, out + (3 * sizeof(T)));
593 store_le(x4, out + (4 * sizeof(T)));
594 store_le(x5, out + (5 * sizeof(T)));
595 store_le(x6, out + (6 * sizeof(T)));
596 store_le(x7, out + (7 * sizeof(T)));
597 }
598
599 /**
600 * Store eight big-endian words
601 * @param out the output byte array
602 * @param x0 the first word
603 * @param x1 the second word
604 * @param x2 the third word
605 * @param x3 the fourth word
606 * @param x4 the fifth word
607 * @param x5 the sixth word
608 * @param x6 the seventh word
609 * @param x7 the eighth word
610 */
611 template<typename T>
612 inline void store_be(byte out[], T x0, T x1, T x2, T x3,
613 T x4, T x5, T x6, T x7)
614 {
615 store_be(x0, out + (0 * sizeof(T)));
616 store_be(x1, out + (1 * sizeof(T)));
617 store_be(x2, out + (2 * sizeof(T)));
618 store_be(x3, out + (3 * sizeof(T)));
619 store_be(x4, out + (4 * sizeof(T)));
620 store_be(x5, out + (5 * sizeof(T)));
621 store_be(x6, out + (6 * sizeof(T)));
622 store_be(x7, out + (7 * sizeof(T)));
623 }
624
625 }
626
627 #endif
Botan::load_be
T load_be(const byte in[], size_t off)
Definition: loadstor.h:100
Botan::load_le
T load_le(const byte in[], size_t off)
Definition: loadstor.h:116
Botan::store_le
void store_le(u16bit in, byte out[2])
Definition: loadstor.h:427
Botan::get_byte
byte get_byte(size_t byte_num, T input)
Definition: get_byte.h:21
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::u64bit
unsigned long long u64bit
Definition: types.h:49
Botan::load_be< u16bit >
u16bit load_be< u16bit >(const byte in[], size_t off)
Definition: loadstor.h:132
Botan::load_le< u32bit >
u32bit load_le< u32bit >(const byte in[], size_t off)
Definition: loadstor.h:183
Botan::u16bit
unsigned short u16bit
Definition: types.h:27
Botan
Definition: algo_base.h:14
Botan::bswap_4
void bswap_4(T x[4])
Definition: bswap.h:112
Botan::load_be< u32bit >
u32bit load_be< u32bit >(const byte in[], size_t off)
Definition: loadstor.h:166
Botan::load_le< u16bit >
u16bit load_le< u16bit >(const byte in[], size_t off)
Definition: loadstor.h:149
Botan::load_be< u64bit >
u64bit load_be< u64bit >(const byte in[], size_t off)
Definition: loadstor.h:200
Botan::store_be
void store_be(u16bit in, byte out[2])
Definition: loadstor.h:412
Botan::make_u16bit
u16bit make_u16bit(byte i0, byte i1)
Definition: loadstor.h:47
Botan::make_u64bit
u64bit make_u64bit(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7)
Definition: loadstor.h:80
Botan::make_u32bit
u32bit make_u32bit(byte i0, byte i1, byte i2, byte i3)
Definition: loadstor.h:60
Botan::u32bit
unsigned int u32bit
Definition: types.h:32
Botan::load_le< u64bit >
u64bit load_le< u64bit >(const byte in[], size_t off)
Definition: loadstor.h:218
Botan::reverse_bytes
u16bit reverse_bytes(u16bit val)
Definition: bswap.h:24