Botan
1.11.15
|
00001 /* 00002 * SIV Mode Encryption 00003 * (C) 2013 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/mode_utils.h> 00009 #include <botan/siv.h> 00010 #include <botan/cmac.h> 00011 #include <botan/ctr.h> 00012 #include <botan/parsing.h> 00013 00014 namespace Botan { 00015 00016 BOTAN_REGISTER_BLOCK_CIPHER_MODE(SIV_Encryption, SIV_Decryption); 00017 00018 SIV_Mode::SIV_Mode(BlockCipher* cipher) : 00019 m_name(cipher->name() + "/SIV"), 00020 m_ctr(new CTR_BE(cipher->clone())), 00021 m_cmac(new CMAC(cipher)) 00022 { 00023 } 00024 00025 void SIV_Mode::clear() 00026 { 00027 m_ctr.reset(); 00028 m_nonce.clear(); 00029 m_msg_buf.clear(); 00030 m_ad_macs.clear(); 00031 } 00032 00033 std::string SIV_Mode::name() const 00034 { 00035 return m_name; 00036 } 00037 00038 bool SIV_Mode::valid_nonce_length(size_t) const 00039 { 00040 return true; 00041 } 00042 00043 size_t SIV_Mode::update_granularity() const 00044 { 00045 /* 00046 This value does not particularly matter as regardless SIV_Mode::update 00047 buffers all input, so in theory this could be 1. However as for instance 00048 Transform_Filter creates update_granularity() byte buffers, use a 00049 somewhat large size to avoid bouncing on a tiny buffer. 00050 */ 00051 return 128; 00052 } 00053 00054 Key_Length_Specification SIV_Mode::key_spec() const 00055 { 00056 return m_cmac->key_spec().multiple(2); 00057 } 00058 00059 void SIV_Mode::key_schedule(const byte key[], size_t length) 00060 { 00061 const size_t keylen = length / 2; 00062 m_cmac->set_key(key, keylen); 00063 m_ctr->set_key(key + keylen, keylen); 00064 m_ad_macs.clear(); 00065 } 00066 00067 void SIV_Mode::set_associated_data_n(size_t n, const byte ad[], size_t length) 00068 { 00069 if(n >= m_ad_macs.size()) 00070 m_ad_macs.resize(n+1); 00071 00072 m_ad_macs[n] = m_cmac->process(ad, length); 00073 } 00074 00075 secure_vector<byte> SIV_Mode::start_raw(const byte nonce[], size_t nonce_len) 00076 { 00077 if(!valid_nonce_length(nonce_len)) 00078 throw Invalid_IV_Length(name(), nonce_len); 00079 00080 if(nonce_len) 00081 m_nonce = m_cmac->process(nonce, nonce_len); 00082 else 00083 m_nonce.clear(); 00084 00085 m_msg_buf.clear(); 00086 00087 return secure_vector<byte>(); 00088 } 00089 00090 void SIV_Mode::update(secure_vector<byte>& buffer, size_t offset) 00091 { 00092 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00093 const size_t sz = buffer.size() - offset; 00094 byte* buf = &buffer[offset]; 00095 00096 m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz); 00097 buffer.resize(offset); // truncate msg 00098 } 00099 00100 secure_vector<byte> SIV_Mode::S2V(const byte* text, size_t text_len) 00101 { 00102 const byte zero[16] = { 0 }; 00103 00104 secure_vector<byte> V = m_cmac->process(zero, 16); 00105 00106 for(size_t i = 0; i != m_ad_macs.size(); ++i) 00107 { 00108 V = CMAC::poly_double(V); 00109 V ^= m_ad_macs[i]; 00110 } 00111 00112 if(m_nonce.size()) 00113 { 00114 V = CMAC::poly_double(V); 00115 V ^= m_nonce; 00116 } 00117 00118 if(text_len < 16) 00119 { 00120 V = CMAC::poly_double(V); 00121 xor_buf(&V[0], text, text_len); 00122 V[text_len] ^= 0x80; 00123 return m_cmac->process(V); 00124 } 00125 00126 m_cmac->update(text, text_len - 16); 00127 xor_buf(&V[0], &text[text_len - 16], 16); 00128 m_cmac->update(V); 00129 00130 return m_cmac->final(); 00131 } 00132 00133 void SIV_Mode::set_ctr_iv(secure_vector<byte> V) 00134 { 00135 V[8] &= 0x7F; 00136 V[12] &= 0x7F; 00137 00138 ctr().set_iv(&V[0], V.size()); 00139 } 00140 00141 void SIV_Encryption::finish(secure_vector<byte>& buffer, size_t offset) 00142 { 00143 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00144 00145 buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end()); 00146 00147 secure_vector<byte> V = S2V(&buffer[offset], buffer.size() - offset); 00148 00149 buffer.insert(buffer.begin() + offset, V.begin(), V.end()); 00150 00151 set_ctr_iv(V); 00152 ctr().cipher1(&buffer[offset + V.size()], buffer.size() - offset - V.size()); 00153 } 00154 00155 void SIV_Decryption::finish(secure_vector<byte>& buffer, size_t offset) 00156 { 00157 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00158 00159 buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end()); 00160 00161 const size_t sz = buffer.size() - offset; 00162 00163 BOTAN_ASSERT(sz >= tag_size(), "We have the tag"); 00164 00165 secure_vector<byte> V(&buffer[offset], &buffer[offset + 16]); 00166 00167 set_ctr_iv(V); 00168 00169 ctr().cipher(&buffer[offset + V.size()], 00170 &buffer[offset], 00171 buffer.size() - offset - V.size()); 00172 00173 secure_vector<byte> T = S2V(&buffer[offset], buffer.size() - offset - V.size()); 00174 00175 if(T != V) 00176 throw Integrity_Failure("SIV tag check failed"); 00177 00178 buffer.resize(buffer.size() - tag_size()); 00179 } 00180 00181 }