Botan
1.11.15
|
00001 /* 00002 * AES Key Wrap (RFC 3394) 00003 * (C) 2011 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/rfc3394.h> 00009 #include <botan/internal/algo_registry.h> 00010 #include <botan/block_cipher.h> 00011 #include <botan/loadstor.h> 00012 #include <botan/exceptn.h> 00013 #include <botan/internal/xor_buf.h> 00014 00015 namespace Botan { 00016 00017 namespace { 00018 00019 BlockCipher* make_aes(size_t keylength) 00020 { 00021 auto& block_ciphers = Algo_Registry<BlockCipher>::global_registry(); 00022 if(keylength == 16) 00023 return block_ciphers.make("AES-128"); 00024 else if(keylength == 24) 00025 return block_ciphers.make("AES-192"); 00026 else if(keylength == 32) 00027 return block_ciphers.make("AES-256"); 00028 else 00029 throw std::invalid_argument("Bad KEK length for NIST keywrap"); 00030 } 00031 00032 } 00033 00034 secure_vector<byte> rfc3394_keywrap(const secure_vector<byte>& key, 00035 const SymmetricKey& kek) 00036 { 00037 if(key.size() % 8 != 0) 00038 throw std::invalid_argument("Bad input key size for NIST key wrap"); 00039 00040 std::unique_ptr<BlockCipher> aes(make_aes(kek.length())); 00041 aes->set_key(kek); 00042 00043 const size_t n = key.size() / 8; 00044 00045 secure_vector<byte> R((n + 1) * 8); 00046 secure_vector<byte> A(16); 00047 00048 for(size_t i = 0; i != 8; ++i) 00049 A[i] = 0xA6; 00050 00051 copy_mem(&R[8], &key[0], key.size()); 00052 00053 for(size_t j = 0; j <= 5; ++j) 00054 { 00055 for(size_t i = 1; i <= n; ++i) 00056 { 00057 const u32bit t = (n * j) + i; 00058 00059 copy_mem(&A[8], &R[8*i], 8); 00060 00061 aes->encrypt(&A[0]); 00062 copy_mem(&R[8*i], &A[8], 8); 00063 00064 byte t_buf[4] = { 0 }; 00065 store_be(t, t_buf); 00066 xor_buf(&A[4], &t_buf[0], 4); 00067 } 00068 } 00069 00070 copy_mem(&R[0], &A[0], 8); 00071 00072 return R; 00073 } 00074 00075 secure_vector<byte> rfc3394_keyunwrap(const secure_vector<byte>& key, 00076 const SymmetricKey& kek) 00077 { 00078 if(key.size() < 16 || key.size() % 8 != 0) 00079 throw std::invalid_argument("Bad input key size for NIST key unwrap"); 00080 00081 std::unique_ptr<BlockCipher> aes(make_aes(kek.length())); 00082 aes->set_key(kek); 00083 00084 const size_t n = (key.size() - 8) / 8; 00085 00086 secure_vector<byte> R(n * 8); 00087 secure_vector<byte> A(16); 00088 00089 for(size_t i = 0; i != 8; ++i) 00090 A[i] = key[i]; 00091 00092 copy_mem(&R[0], &key[8], key.size() - 8); 00093 00094 for(size_t j = 0; j <= 5; ++j) 00095 { 00096 for(size_t i = n; i != 0; --i) 00097 { 00098 const u32bit t = (5 - j) * n + i; 00099 00100 byte t_buf[4] = { 0 }; 00101 store_be(t, t_buf); 00102 00103 xor_buf(&A[4], &t_buf[0], 4); 00104 00105 copy_mem(&A[8], &R[8*(i-1)], 8); 00106 00107 aes->decrypt(&A[0]); 00108 00109 copy_mem(&R[8*(i-1)], &A[8], 8); 00110 } 00111 } 00112 00113 if(load_be<u64bit>(&A[0], 0) != 0xA6A6A6A6A6A6A6A6) 00114 throw Integrity_Failure("NIST key unwrap failed"); 00115 00116 return R; 00117 } 00118 00119 }