7#include <botan/nist_keywrap.h>
8#include <botan/block_cipher.h>
9#include <botan/loadstor.h>
10#include <botan/exceptn.h>
17raw_nist_key_wrap(
const uint8_t input[],
19 const BlockCipher& bc,
22 const size_t n = (input_len + 7) / 8;
24 secure_vector<uint8_t> R((n + 1) * 8);
25 secure_vector<uint8_t> A(16);
31 for(
size_t j = 0; j <= 5; ++j)
33 for(
size_t i = 1; i <= n; ++i)
35 const uint32_t t =
static_cast<uint32_t
>((n * j) + i);
42 uint8_t t_buf[4] = { 0 };
50 return std::vector<uint8_t>(R.begin(), R.end());
54raw_nist_key_unwrap(
const uint8_t input[],
56 const BlockCipher& bc,
59 if(input_len < 16 || input_len % 8 != 0)
60 throw Invalid_Argument(
"Bad input size for NIST key unwrap");
62 const size_t n = (input_len - 8) / 8;
64 secure_vector<uint8_t> R(n * 8);
65 secure_vector<uint8_t> A(16);
67 for(
size_t i = 0; i != 8; ++i)
70 copy_mem(R.data(), input + 8, input_len - 8);
72 for(
size_t j = 0; j <= 5; ++j)
74 for(
size_t i = n; i != 0; --i)
76 const uint32_t t =
static_cast<uint32_t
>((5 - j) * n + i);
78 uint8_t t_buf[4] = { 0 };
104 throw Invalid_Argument(
"NIST key wrap algorithm requires a 128-bit cipher");
106 if(input_len % 8 != 0)
109 return raw_nist_key_wrap(input, input_len, bc, 0xA6A6A6A6A6A6A6A6);
112secure_vector<uint8_t>
118 throw Invalid_Argument(
"NIST key wrap algorithm requires a 128-bit cipher");
120 if(input_len < 16 || input_len % 8 != 0)
123 uint64_t ICV_out = 0;
127 if(ICV_out != 0xA6A6A6A6A6A6A6A6)
139 throw Invalid_Argument(
"NIST key wrap algorithm requires a 128-bit cipher");
141 const uint64_t ICV = 0xA65959A600000000 |
static_cast<uint32_t
>(input_len);
148 std::vector<uint8_t> block(16);
150 copy_mem(block.data() + 8, input, input_len);
156 return raw_nist_key_wrap(input, input_len, bc, ICV);
160secure_vector<uint8_t>
166 throw Invalid_Argument(
"NIST key wrap algorithm requires a 128-bit cipher");
168 if(input_len < 16 || input_len % 8 != 0)
171 uint64_t ICV_out = 0;
181 copy_mem(R.data(), block.data() + 8, 8);
185 R = raw_nist_key_unwrap(input, input_len, bc, ICV_out);
188 if((ICV_out >> 32) != 0xA65959A6)
191 const size_t len = (ICV_out & 0xFFFFFFFF);
193 if(R.size() < 8 || len > R.size() || len < R.size() - 8)
196 const size_t padding = R.size() - len;
198 for(
size_t i = 0; i != padding; ++i)
200 if(R[R.size() - i - 1] != 0)
204 R.resize(R.size() - padding);
void encrypt(const uint8_t in[], uint8_t out[]) const
void decrypt(const uint8_t in[], uint8_t out[]) const
virtual size_t block_size() const =0
std::vector< uint8_t > nist_key_wrap(const uint8_t input[], size_t input_len, const BlockCipher &bc)
void store_be(uint16_t in, uint8_t out[2])
void copy_mem(T *out, const T *in, size_t n)
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
std::vector< uint8_t > nist_key_wrap_padded(const uint8_t input[], size_t input_len, const BlockCipher &bc)
secure_vector< uint8_t > nist_key_unwrap_padded(const uint8_t input[], size_t input_len, const BlockCipher &bc)
std::vector< T, secure_allocator< T > > secure_vector
secure_vector< uint8_t > nist_key_unwrap(const uint8_t input[], size_t input_len, const BlockCipher &bc)