Botan 1.10.17
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
16namespace Botan {
17
18namespace {
19
20BlockCipher* make_aes(size_t keylength,
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);
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);
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}
size_t size() const
Definition secmem.h:29
size_t length() const
Definition symkey.h:25
OctetString SymmetricKey
Definition symkey.h:147
T load_be(const byte in[], size_t off)
Definition loadstor.h:100
SecureVector< byte > rfc3394_keyunwrap(const MemoryRegion< byte > &key, const SymmetricKey &kek, Algorithm_Factory &af)
Definition rfc3394.cpp:77
void xor_buf(byte out[], const byte in[], size_t length)
Definition xor_buf.h:21
void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:22
SecureVector< byte > rfc3394_keywrap(const MemoryRegion< byte > &key, const SymmetricKey &kek, Algorithm_Factory &af)
Definition rfc3394.cpp:35
unsigned int u32bit
Definition types.h:32
void store_be(u16bit in, byte out[2])
Definition loadstor.h:412
Integrity_Failure(const std::string &msg)
Definition exceptn.h:149