1 /** 2 * OFB Mode 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.stream.ofb; 12 13 import botan.constants; 14 static if (BOTAN_HAS_OFB): 15 16 import botan.stream.stream_cipher; 17 import botan.block.block_cipher; 18 import botan.utils.xor_buf; 19 import botan.utils.mem_ops; 20 21 /** 22 * Output Feedback Mode 23 */ 24 final class OFB : StreamCipher, SymmetricAlgorithm 25 { 26 public: 27 override void cipher(const(ubyte)* input, ubyte* output, size_t length) 28 { 29 size_t len_mem = length; 30 ubyte* output_mem = output; 31 while (length >= m_buffer.length - m_buf_pos) 32 { 33 xorBuf(output, input, &m_buffer[m_buf_pos], m_buffer.length - m_buf_pos); 34 length -= (m_buffer.length - m_buf_pos); 35 input += (m_buffer.length - m_buf_pos); 36 output += (m_buffer.length - m_buf_pos); 37 m_cipher.encrypt(m_buffer); 38 m_buf_pos = 0; 39 } 40 xorBuf(output, input, &m_buffer[m_buf_pos], length); 41 m_buf_pos += length; 42 } 43 44 override void setIv(const(ubyte)* iv, size_t iv_len) 45 { 46 if (!validIvLength(iv_len)) 47 throw new InvalidIVLength(name, iv_len); 48 zeroise(m_buffer); 49 bufferInsert(m_buffer, 0, iv, iv_len); 50 if (iv_len > 0) m_cipher.encrypt(m_buffer); 51 m_buf_pos = 0; 52 } 53 54 override bool validIvLength(size_t iv_len) const 55 { return (iv_len <= m_cipher.blockSize()); } 56 57 KeyLengthSpecification keySpec() const 58 { 59 return m_cipher.keySpec(); 60 } 61 62 @property string name() const 63 { 64 return "OFB(" ~ m_cipher.name ~ ")"; 65 } 66 67 override OFB clone() const 68 { return new OFB(m_cipher.clone()); } 69 70 void clear() 71 { 72 m_cipher.clear(); 73 zeroise(m_buffer); 74 m_buf_pos = 0; 75 } 76 77 /** 78 * Params: 79 * cipher = the underlying block cipher to use 80 */ 81 this(BlockCipher cipher) 82 { 83 m_cipher = cipher; 84 m_buffer = SecureVector!ubyte(m_cipher.blockSize()); 85 m_buf_pos = 0; 86 } 87 88 protected: 89 override void keySchedule(const(ubyte)* key, size_t length) 90 { 91 m_cipher.setKey(key, length); 92 93 // Set a default all-zeros IV 94 setIv(null, 0); 95 } 96 97 Unique!BlockCipher m_cipher; 98 size_t m_buf_pos; 99 private: 100 SecureVector!ubyte m_buffer; 101 }