Botan
1.11.15
|
00001 /* 00002 * OCB Mode 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/ocb.h> 00010 #include <botan/cmac.h> 00011 00012 namespace Botan { 00013 00014 BOTAN_REGISTER_BLOCK_CIPHER_MODE_LEN(OCB_Encryption, OCB_Decryption, 16); 00015 00016 // Has to be in Botan namespace so unique_ptr can reference it 00017 class L_computer 00018 { 00019 public: 00020 L_computer(const BlockCipher& cipher) 00021 { 00022 m_L_star.resize(cipher.block_size()); 00023 cipher.encrypt(m_L_star); 00024 m_L_dollar = poly_double(star()); 00025 m_L.push_back(poly_double(dollar())); 00026 } 00027 00028 const secure_vector<byte>& star() const { return m_L_star; } 00029 00030 const secure_vector<byte>& dollar() const { return m_L_dollar; } 00031 00032 const secure_vector<byte>& operator()(size_t i) const { return get(i); } 00033 00034 const secure_vector<byte>& compute_offsets(secure_vector<byte>& offset, 00035 size_t block_index, 00036 size_t blocks) const 00037 { 00038 const size_t BS = m_L_star.size(); 00039 m_offset_buf.resize(blocks * BS); 00040 00041 for(size_t i = 0; i != blocks; ++i) 00042 { // could be done in parallel 00043 offset ^= get(ctz(block_index + 1 + i)); 00044 copy_mem(&m_offset_buf[BS*i], &offset[0], BS); 00045 } 00046 00047 return m_offset_buf; 00048 } 00049 00050 private: 00051 const secure_vector<byte>& get(size_t i) const 00052 { 00053 while(m_L.size() <= i) 00054 m_L.push_back(poly_double(m_L.back())); 00055 00056 return m_L.at(i); 00057 } 00058 00059 secure_vector<byte> poly_double(const secure_vector<byte>& in) const 00060 { 00061 return CMAC::poly_double(in); 00062 } 00063 00064 secure_vector<byte> m_L_dollar, m_L_star; 00065 mutable std::vector<secure_vector<byte>> m_L; 00066 mutable secure_vector<byte> m_offset_buf; 00067 }; 00068 00069 namespace { 00070 00071 /* 00072 * OCB's HASH 00073 */ 00074 secure_vector<byte> ocb_hash(const L_computer& L, 00075 const BlockCipher& cipher, 00076 const byte ad[], size_t ad_len) 00077 { 00078 const size_t BS = cipher.block_size(); 00079 00080 secure_vector<byte> sum(BS); 00081 secure_vector<byte> offset(BS); 00082 00083 secure_vector<byte> buf(BS); 00084 00085 const size_t ad_blocks = (ad_len / BS); 00086 const size_t ad_remainder = (ad_len % BS); 00087 00088 for(size_t i = 0; i != ad_blocks; ++i) 00089 { 00090 // this loop could run in parallel 00091 offset ^= L(ctz(i+1)); 00092 00093 buf = offset; 00094 xor_buf(&buf[0], &ad[BS*i], BS); 00095 00096 cipher.encrypt(buf); 00097 00098 sum ^= buf; 00099 } 00100 00101 if(ad_remainder) 00102 { 00103 offset ^= L.star(); 00104 00105 buf = offset; 00106 xor_buf(&buf[0], &ad[BS*ad_blocks], ad_remainder); 00107 buf[ad_len % BS] ^= 0x80; 00108 00109 cipher.encrypt(buf); 00110 00111 sum ^= buf; 00112 } 00113 00114 return sum; 00115 } 00116 00117 } 00118 00119 OCB_Mode::OCB_Mode(BlockCipher* cipher, size_t tag_size) : 00120 m_cipher(cipher), 00121 m_BS(m_cipher->block_size()), 00122 m_checksum(m_cipher->parallel_bytes()), 00123 m_offset(m_BS), 00124 m_ad_hash(m_BS), 00125 m_tag_size(tag_size) 00126 { 00127 if(BS() != 16) 00128 throw std::invalid_argument("OCB is not compatible with " + m_cipher->name()); 00129 00130 if(m_tag_size % 4 != 0 || m_tag_size < 8 || m_tag_size > BS()) 00131 throw std::invalid_argument("OCB cannot produce a " + std::to_string(m_tag_size) + 00132 " byte tag"); 00133 00134 } 00135 00136 OCB_Mode::~OCB_Mode() { /* for unique_ptr destructor */ } 00137 00138 void OCB_Mode::clear() 00139 { 00140 m_cipher.reset(); 00141 m_L.reset(); 00142 00143 zeroise(m_ad_hash); 00144 zeroise(m_offset); 00145 zeroise(m_checksum); 00146 } 00147 00148 bool OCB_Mode::valid_nonce_length(size_t length) const 00149 { 00150 return (length > 0 && length < m_cipher->block_size()); 00151 } 00152 00153 std::string OCB_Mode::name() const 00154 { 00155 return m_cipher->name() + "/OCB"; // include tag size 00156 } 00157 00158 size_t OCB_Mode::update_granularity() const 00159 { 00160 return m_cipher->parallel_bytes(); 00161 } 00162 00163 Key_Length_Specification OCB_Mode::key_spec() const 00164 { 00165 return m_cipher->key_spec(); 00166 } 00167 00168 void OCB_Mode::key_schedule(const byte key[], size_t length) 00169 { 00170 m_cipher->set_key(key, length); 00171 m_L.reset(new L_computer(*m_cipher)); 00172 } 00173 00174 void OCB_Mode::set_associated_data(const byte ad[], size_t ad_len) 00175 { 00176 BOTAN_ASSERT(m_L, "A key was set"); 00177 m_ad_hash = ocb_hash(*m_L, *m_cipher, &ad[0], ad_len); 00178 } 00179 00180 secure_vector<byte> 00181 OCB_Mode::update_nonce(const byte nonce[], size_t nonce_len) 00182 { 00183 BOTAN_ASSERT(nonce_len < BS(), "OCB nonce is less than cipher block size"); 00184 00185 secure_vector<byte> nonce_buf(BS()); 00186 00187 copy_mem(&nonce_buf[BS() - nonce_len], nonce, nonce_len); 00188 nonce_buf[0] = ((tag_size() * 8) % 128) << 1; 00189 nonce_buf[BS() - nonce_len - 1] = 1; 00190 00191 const byte bottom = nonce_buf[BS()-1] & 0x3F; 00192 nonce_buf[BS()-1] &= 0xC0; 00193 00194 const bool need_new_stretch = (m_last_nonce != nonce_buf); 00195 00196 if(need_new_stretch) 00197 { 00198 m_last_nonce = nonce_buf; 00199 00200 m_cipher->encrypt(nonce_buf); 00201 00202 for(size_t i = 0; i != BS() / 2; ++i) 00203 nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i+1]); 00204 00205 m_stretch = nonce_buf; 00206 } 00207 00208 // now set the offset from stretch and bottom 00209 00210 const size_t shift_bytes = bottom / 8; 00211 const size_t shift_bits = bottom % 8; 00212 00213 secure_vector<byte> offset(BS()); 00214 for(size_t i = 0; i != BS(); ++i) 00215 { 00216 offset[i] = (m_stretch[i+shift_bytes] << shift_bits); 00217 offset[i] |= (m_stretch[i+shift_bytes+1] >> (8-shift_bits)); 00218 } 00219 00220 return offset; 00221 } 00222 00223 secure_vector<byte> OCB_Mode::start_raw(const byte nonce[], size_t nonce_len) 00224 { 00225 if(!valid_nonce_length(nonce_len)) 00226 throw Invalid_IV_Length(name(), nonce_len); 00227 00228 BOTAN_ASSERT(m_L, "A key was set"); 00229 00230 m_offset = update_nonce(nonce, nonce_len); 00231 zeroise(m_checksum); 00232 m_block_index = 0; 00233 00234 return secure_vector<byte>(); 00235 } 00236 00237 void OCB_Encryption::encrypt(byte buffer[], size_t blocks) 00238 { 00239 const size_t par_blocks = m_checksum.size() / BS(); 00240 00241 while(blocks) 00242 { 00243 const size_t proc_blocks = std::min(blocks, par_blocks); 00244 const size_t proc_bytes = proc_blocks * BS(); 00245 00246 const auto& offsets = m_L->compute_offsets(m_offset, m_block_index, proc_blocks); 00247 00248 xor_buf(&m_checksum[0], &buffer[0], proc_bytes); 00249 00250 xor_buf(&buffer[0], &offsets[0], proc_bytes); 00251 m_cipher->encrypt_n(&buffer[0], &buffer[0], proc_blocks); 00252 xor_buf(&buffer[0], &offsets[0], proc_bytes); 00253 00254 buffer += proc_bytes; 00255 blocks -= proc_blocks; 00256 m_block_index += proc_blocks; 00257 } 00258 } 00259 00260 void OCB_Encryption::update(secure_vector<byte>& buffer, size_t offset) 00261 { 00262 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00263 const size_t sz = buffer.size() - offset; 00264 byte* buf = &buffer[offset]; 00265 00266 BOTAN_ASSERT(sz % BS() == 0, "Input length is an even number of blocks"); 00267 encrypt(buf, sz / BS()); 00268 } 00269 00270 void OCB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) 00271 { 00272 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00273 const size_t sz = buffer.size() - offset; 00274 byte* buf = &buffer[offset]; 00275 00276 if(sz) 00277 { 00278 const size_t final_full_blocks = sz / BS(); 00279 const size_t remainder_bytes = sz - (final_full_blocks * BS()); 00280 00281 encrypt(buf, final_full_blocks); 00282 00283 if(remainder_bytes) 00284 { 00285 BOTAN_ASSERT(remainder_bytes < BS(), "Only a partial block left"); 00286 byte* remainder = &buf[sz - remainder_bytes]; 00287 00288 xor_buf(&m_checksum[0], &remainder[0], remainder_bytes); 00289 m_checksum[remainder_bytes] ^= 0x80; 00290 00291 m_offset ^= m_L->star(); // Offset_* 00292 00293 secure_vector<byte> zeros(BS()); 00294 m_cipher->encrypt(m_offset, zeros); 00295 xor_buf(&remainder[0], &zeros[0], remainder_bytes); 00296 } 00297 } 00298 00299 secure_vector<byte> checksum(BS()); 00300 00301 // fold checksum 00302 for(size_t i = 0; i != m_checksum.size(); ++i) 00303 checksum[i % checksum.size()] ^= m_checksum[i]; 00304 00305 // now compute the tag 00306 secure_vector<byte> mac = m_offset; 00307 mac ^= checksum; 00308 mac ^= m_L->dollar(); 00309 00310 m_cipher->encrypt(mac); 00311 00312 mac ^= m_ad_hash; 00313 00314 buffer += std::make_pair(&mac[0], tag_size()); 00315 00316 zeroise(m_checksum); 00317 zeroise(m_offset); 00318 m_block_index = 0; 00319 } 00320 00321 void OCB_Decryption::decrypt(byte buffer[], size_t blocks) 00322 { 00323 const size_t par_bytes = m_cipher->parallel_bytes(); 00324 00325 BOTAN_ASSERT(par_bytes % BS() == 0, "Cipher is parallel in full blocks"); 00326 00327 const size_t par_blocks = par_bytes / BS(); 00328 00329 while(blocks) 00330 { 00331 const size_t proc_blocks = std::min(blocks, par_blocks); 00332 const size_t proc_bytes = proc_blocks * BS(); 00333 00334 const auto& offsets = m_L->compute_offsets(m_offset, m_block_index, proc_blocks); 00335 00336 xor_buf(&buffer[0], &offsets[0], proc_bytes); 00337 m_cipher->decrypt_n(&buffer[0], &buffer[0], proc_blocks); 00338 xor_buf(&buffer[0], &offsets[0], proc_bytes); 00339 00340 xor_buf(&m_checksum[0], &buffer[0], proc_bytes); 00341 00342 buffer += proc_bytes; 00343 blocks -= proc_blocks; 00344 m_block_index += proc_blocks; 00345 } 00346 } 00347 00348 void OCB_Decryption::update(secure_vector<byte>& buffer, size_t offset) 00349 { 00350 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00351 const size_t sz = buffer.size() - offset; 00352 byte* buf = &buffer[offset]; 00353 00354 BOTAN_ASSERT(sz % BS() == 0, "Input length is an even number of blocks"); 00355 00356 decrypt(buf, sz / BS()); 00357 } 00358 00359 void OCB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) 00360 { 00361 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); 00362 const size_t sz = buffer.size() - offset; 00363 byte* buf = &buffer[offset]; 00364 00365 BOTAN_ASSERT(sz >= tag_size(), "We have the tag"); 00366 00367 const size_t remaining = sz - tag_size(); 00368 00369 if(remaining) 00370 { 00371 const size_t final_full_blocks = remaining / BS(); 00372 const size_t final_bytes = remaining - (final_full_blocks * BS()); 00373 00374 decrypt(&buf[0], final_full_blocks); 00375 00376 if(final_bytes) 00377 { 00378 BOTAN_ASSERT(final_bytes < BS(), "Only a partial block left"); 00379 00380 byte* remainder = &buf[remaining - final_bytes]; 00381 00382 m_offset ^= m_L->star(); // Offset_* 00383 00384 secure_vector<byte> pad(BS()); 00385 m_cipher->encrypt(m_offset, pad); // P_* 00386 00387 xor_buf(&remainder[0], &pad[0], final_bytes); 00388 00389 xor_buf(&m_checksum[0], &remainder[0], final_bytes); 00390 m_checksum[final_bytes] ^= 0x80; 00391 } 00392 } 00393 00394 secure_vector<byte> checksum(BS()); 00395 00396 // fold checksum 00397 for(size_t i = 0; i != m_checksum.size(); ++i) 00398 checksum[i % checksum.size()] ^= m_checksum[i]; 00399 00400 // compute the mac 00401 secure_vector<byte> mac = m_offset; 00402 mac ^= checksum; 00403 mac ^= m_L->dollar(); 00404 00405 m_cipher->encrypt(mac); 00406 00407 mac ^= m_ad_hash; 00408 00409 // reset state 00410 zeroise(m_checksum); 00411 zeroise(m_offset); 00412 m_block_index = 0; 00413 00414 // compare mac 00415 const byte* included_tag = &buf[remaining]; 00416 00417 if(!same_mem(&mac[0], included_tag, tag_size())) 00418 throw Integrity_Failure("OCB tag check failed"); 00419 00420 // remove tag from end of message 00421 buffer.resize(remaining + offset); 00422 } 00423 00424 }