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 }