Botan  1.10.9
rfc3394.cpp
Go to the documentation of this file.
1 /*
2 * AES Key Wrap (RFC 3394)
3 * (C) 2011 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/rfc3394.h>
9 #include <botan/algo_factory.h>
10 #include <botan/block_cipher.h>
11 #include <botan/loadstor.h>
12 #include <botan/exceptn.h>
13 #include <botan/internal/xor_buf.h>
14 #include <memory>
15 
16 namespace Botan {
17 
18 namespace {
19 
20 BlockCipher* make_aes(size_t keylength,
21  Algorithm_Factory& af)
22  {
23  if(keylength == 16)
24  return af.make_block_cipher("AES-128");
25  else if(keylength == 24)
26  return af.make_block_cipher("AES-192");
27  else if(keylength == 32)
28  return af.make_block_cipher("AES-256");
29  else
30  throw std::invalid_argument("Bad KEK length for NIST keywrap");
31  }
32 
33 }
34 
36  const SymmetricKey& kek,
38  {
39  if(key.size() % 8 != 0)
40  throw std::invalid_argument("Bad input key size for NIST key wrap");
41 
42  std::auto_ptr<BlockCipher> aes(make_aes(kek.length(), af));
43  aes->set_key(kek);
44 
45  const size_t n = key.size() / 8;
46 
47  SecureVector<byte> R((n + 1) * 8);
48  SecureVector<byte> A(16);
49 
50  for(size_t i = 0; i != 8; ++i)
51  A[i] = 0xA6;
52 
53  copy_mem(&R[8], key.begin(), key.size());
54 
55  for(size_t j = 0; j <= 5; ++j)
56  {
57  for(size_t i = 1; i <= n; ++i)
58  {
59  const u32bit t = (n * j) + i;
60 
61  copy_mem(&A[8], &R[8*i], 8);
62 
63  aes->encrypt(&A[0]);
64  copy_mem(&R[8*i], &A[8], 8);
65 
66  byte t_buf[4] = { 0 };
67  store_be(t, t_buf);
68  xor_buf(&A[4], &t_buf[0], 4);
69  }
70  }
71 
72  copy_mem(&R[0], &A[0], 8);
73 
74  return R;
75  }
76 
78  const SymmetricKey& kek,
80  {
81  if(key.size() < 16 || key.size() % 8 != 0)
82  throw std::invalid_argument("Bad input key size for NIST key unwrap");
83 
84  std::auto_ptr<BlockCipher> aes(make_aes(kek.length(), af));
85  aes->set_key(kek);
86 
87  const size_t n = (key.size() - 8) / 8;
88 
89  SecureVector<byte> R(n * 8);
90  SecureVector<byte> A(16);
91 
92  for(size_t i = 0; i != 8; ++i)
93  A[i] = key[i];
94 
95  copy_mem(&R[0], key.begin() + 8, key.size() - 8);
96 
97  for(size_t j = 0; j <= 5; ++j)
98  {
99  for(size_t i = n; i != 0; --i)
100  {
101  const u32bit t = (5 - j) * n + i;
102 
103  byte t_buf[4] = { 0 };
104  store_be(t, t_buf);
105 
106  xor_buf(&A[4], &t_buf[0], 4);
107 
108  copy_mem(&A[8], &R[8*(i-1)], 8);
109 
110  aes->decrypt(&A[0]);
111 
112  copy_mem(&R[8*(i-1)], &A[8], 8);
113  }
114  }
115 
116  if(load_be<u64bit>(&A[0], 0) != 0xA6A6A6A6A6A6A6A6)
117  throw Integrity_Failure("NIST key unwrap failed");
118 
119  return R;
120  }
121 
122 }
SecureVector< byte > rfc3394_keywrap(const MemoryRegion< byte > &key, const SymmetricKey &kek, Algorithm_Factory &af)
Definition: rfc3394.cpp:35
BigInt n
Definition: numthry.cpp:26
size_t length() const
Definition: symkey.h:25
unsigned char byte
Definition: types.h:22
SecureVector< byte > rfc3394_keyunwrap(const MemoryRegion< byte > &key, const SymmetricKey &kek, Algorithm_Factory &af)
Definition: rfc3394.cpp:77
size_t size() const
Definition: secmem.h:29
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:22
u64bit load_be< u64bit >(const byte in[], size_t off)
Definition: loadstor.h:200
void store_be(u16bit in, byte out[2])
Definition: loadstor.h:412
void xor_buf(byte out[], const byte in[], size_t length)
Definition: xor_buf.h:21
unsigned int u32bit
Definition: types.h:32