Coverage Report

Created: 2023-06-07 06:59

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