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 }