Botan: src/constructs/rfc3394/rfc3394.cpp Source File

Botan 1.10.16

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
35 SecureVector<byte> rfc3394_keywrap(const MemoryRegion<byte>& key,
36 const SymmetricKey& kek,
37 Algorithm_Factory& af)
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
77 SecureVector<byte> rfc3394_keyunwrap(const MemoryRegion<byte>& key,
78 const SymmetricKey& kek,
79 Algorithm_Factory& af)
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 }
Botan::rfc3394_keywrap
SecureVector< byte > rfc3394_keywrap(const MemoryRegion< byte > &key, const SymmetricKey &kek, Algorithm_Factory &af)
Definition: rfc3394.cpp:35
Botan::Algorithm_Factory
Definition: algo_factory.h:34
Botan::OctetString
Definition: symkey.h:19
Botan::Integrity_Failure
Definition: exceptn.h:147
Botan::byte
unsigned char byte
Definition: types.h:22
Botan::rfc3394_keyunwrap
SecureVector< byte > rfc3394_keyunwrap(const MemoryRegion< byte > &key, const SymmetricKey &kek, Algorithm_Factory &af)
Definition: rfc3394.cpp:77
Botan::MemoryRegion< byte >
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:22
Botan
Definition: algo_base.h:14
Botan::OctetString::length
size_t length() const
Definition: symkey.h:25
Botan::MemoryRegion::size
size_t size() const
Definition: secmem.h:29
Botan::MemoryRegion::begin
T * begin()
Definition: secmem.h:53
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::SecureVector< byte >
Botan::xor_buf
void xor_buf(byte out[], const byte in[], size_t length)
Definition: xor_buf.h:21
Botan::u32bit
unsigned int u32bit
Definition: types.h:32