Botan  2.1.0
Crypto and TLS for C++11
rfc3394.cpp
Go to the documentation of this file.
1 /*
2 * AES Key Wrap (RFC 3394)
3 * (C) 2011 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/rfc3394.h>
9 #include <botan/block_cipher.h>
10 #include <botan/loadstor.h>
11 #include <botan/exceptn.h>
12 
13 namespace Botan {
14 
16  const SymmetricKey& kek)
17  {
18  if(key.size() % 8 != 0)
19  throw Invalid_Argument("Bad input key size for NIST key wrap");
20 
21  if(kek.size() != 16 && kek.size() != 24 && kek.size() != 32)
22  throw Invalid_Argument("Bad KEK length " + std::to_string(kek.size()) + " for NIST key wrap");
23 
24  const std::string cipher_name = "AES-" + std::to_string(8*kek.size());
25  std::unique_ptr<BlockCipher> aes(BlockCipher::create_or_throw(cipher_name));
26  aes->set_key(kek);
27 
28  const size_t n = key.size() / 8;
29 
30  secure_vector<uint8_t> R((n + 1) * 8);
32 
33  for(size_t i = 0; i != 8; ++i)
34  A[i] = 0xA6;
35 
36  copy_mem(&R[8], key.data(), key.size());
37 
38  for(size_t j = 0; j <= 5; ++j)
39  {
40  for(size_t i = 1; i <= n; ++i)
41  {
42  const uint32_t t = (n * j) + i;
43 
44  copy_mem(&A[8], &R[8*i], 8);
45 
46  aes->encrypt(A.data());
47  copy_mem(&R[8*i], &A[8], 8);
48 
49  uint8_t t_buf[4] = { 0 };
50  store_be(t, t_buf);
51  xor_buf(&A[4], t_buf, 4);
52  }
53  }
54 
55  copy_mem(R.data(), A.data(), 8);
56 
57  return R;
58  }
59 
61  const SymmetricKey& kek)
62  {
63  if(key.size() < 16 || key.size() % 8 != 0)
64  throw Invalid_Argument("Bad input key size for NIST key unwrap");
65 
66  if(kek.size() != 16 && kek.size() != 24 && kek.size() != 32)
67  throw Invalid_Argument("Bad KEK length " + std::to_string(kek.size()) + " for NIST key unwrap");
68 
69  const std::string cipher_name = "AES-" + std::to_string(8*kek.size());
70  std::unique_ptr<BlockCipher> aes(BlockCipher::create_or_throw(cipher_name));
71  aes->set_key(kek);
72 
73  const size_t n = (key.size() - 8) / 8;
74 
75  secure_vector<uint8_t> R(n * 8);
77 
78  for(size_t i = 0; i != 8; ++i)
79  A[i] = key[i];
80 
81  copy_mem(R.data(), &key[8], key.size() - 8);
82 
83  for(size_t j = 0; j <= 5; ++j)
84  {
85  for(size_t i = n; i != 0; --i)
86  {
87  const uint32_t t = (5 - j) * n + i;
88 
89  uint8_t t_buf[4] = { 0 };
90  store_be(t, t_buf);
91 
92  xor_buf(&A[4], t_buf, 4);
93 
94  copy_mem(&A[8], &R[8*(i-1)], 8);
95 
96  aes->decrypt(A.data());
97 
98  copy_mem(&R[8*(i-1)], &A[8], 8);
99  }
100  }
101 
102  if(load_be<uint64_t>(A.data(), 0) != 0xA6A6A6A6A6A6A6A6)
103  throw Integrity_Failure("NIST key unwrap failed");
104 
105  return R;
106  }
107 
108 }
void xor_buf(T out[], const T in[], size_t length)
Definition: mem_ops.h:115
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:441
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:47
secure_vector< uint8_t > rfc3394_keywrap(const secure_vector< uint8_t > &key, const SymmetricKey &kek)
Definition: rfc3394.cpp:15
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:223
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:68
Definition: alg_id.cpp:13
static std::unique_ptr< BlockCipher > create_or_throw(const std::string &algo_spec, const std::string &provider="")
secure_vector< uint8_t > rfc3394_keyunwrap(const secure_vector< uint8_t > &key, const SymmetricKey &kek)
Definition: rfc3394.cpp:60
size_t size() const
Definition: symkey.h:26