1 /**
2 * CBC-MAC
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.mac.cbc_mac;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_CBC_MAC):
15 
16 import botan.mac.mac;
17 import botan.block.block_cipher;
18 import botan.utils.xor_buf;
19 import botan.utils.mem_ops;
20 import std.algorithm;
21 
22 /**
23 * CBC-MAC
24 */
25 final class CBCMAC : MessageAuthenticationCode, SymmetricAlgorithm
26 {
27 public:
28     /*
29     * Return the name of this type
30     */
31     override @property string name() const
32     {
33         return "CBC-MAC(" ~ m_cipher.name ~ ")";
34     }
35 
36     /*
37     * Return a clone of this object
38     */
39     override MessageAuthenticationCode clone() const
40     {
41         return new CBCMAC(m_cipher.clone());
42     }
43 
44     override @property size_t outputLength() const { return m_cipher.blockSize(); }
45 
46     /*
47     * Clear memory of sensitive data
48     */
49     void clear()
50     {
51         m_cipher.clear();
52         zeroise(m_state);
53         m_position = 0;
54     }
55 
56     KeyLengthSpecification keySpec() const
57     {
58         return m_cipher.keySpec();
59     }
60 
61     /**
62     * Params:
63     *  cipher = the underlying block cipher to use
64     */
65     this(BlockCipher cipher)
66     {
67         m_cipher = cipher;
68         m_state = m_cipher.blockSize();
69     }
70 
71 
72 protected:
73     /*
74     * Update an CBC-MAC Calculation
75     */
76     override void addData(const(ubyte)* input, size_t length)
77     {
78         size_t xored = std.algorithm.min(outputLength() - m_position, length);
79         xorBuf(&m_state[m_position], input, xored);
80         m_position += xored;
81         
82         if (m_position < outputLength())
83             return;
84         
85         m_cipher.encrypt(m_state);
86         input += xored;
87         length -= xored;
88         while (length >= outputLength())
89         {
90             xorBuf(m_state, input, outputLength());
91             m_cipher.encrypt(m_state);
92             input += outputLength();
93             length -= outputLength();
94         }
95         
96         xorBuf(m_state, input, length);
97         m_position = length;
98     }    
99 
100     /*
101     * Finalize an CBC-MAC Calculation
102     */
103     override void finalResult(ubyte* mac)
104     {
105         if (m_position)
106             m_cipher.encrypt(m_state);
107         
108         copyMem(mac, m_state.ptr, m_state.length);
109         zeroise(m_state);
110         m_position = 0;
111     }
112 
113     /*
114     * CBC-MAC Key Schedule
115     */
116     override void keySchedule(const(ubyte)* key, size_t length)
117     {
118         m_cipher.setKey(key, length);
119     }
120 
121     Unique!BlockCipher m_cipher;
122     SecureVector!ubyte m_state;
123     size_t m_position;
124 }