1 /** 2 * SSL3-MAC 3 * 4 * Copyright: 5 * (C) 1999-2004 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.ssl3_mac; 12 13 import botan.constants; 14 static if (BOTAN_HAS_SSL3_MAC): 15 16 import botan.hash.hash; 17 import botan.mac.mac; 18 import botan.utils.mem_ops; 19 import std.algorithm : fill; 20 21 /** 22 * A MAC only used in SSLv3. Do not use elsewhere! Use HMAC instead. 23 */ 24 final class SSL3MAC : MessageAuthenticationCode, SymmetricAlgorithm 25 { 26 public: 27 /* 28 * Return the name of this type 29 */ 30 override @property string name() const 31 { 32 return "SSL3-MAC(" ~ m_hash.name ~ ")"; 33 } 34 35 override @property size_t outputLength() const { return m_hash.outputLength; } 36 37 /* 38 * Return a clone of this object 39 */ 40 override MessageAuthenticationCode clone() const 41 { 42 return new SSL3MAC(m_hash.clone()); 43 } 44 45 46 /* 47 * Clear memory of sensitive data 48 */ 49 void clear() 50 { 51 m_hash.clear(); 52 zap(m_ikey); 53 zap(m_okey); 54 } 55 56 KeyLengthSpecification keySpec() const 57 { 58 return KeyLengthSpecification(m_hash.outputLength); 59 } 60 61 /** 62 * Params: 63 * hash = the underlying hash to use 64 */ 65 this(HashFunction hash) 66 { 67 m_hash = hash; 68 if (m_hash.hashBlockSize == 0) 69 throw new InvalidArgument("SSL3-MAC cannot be used with " ~ m_hash.name); 70 } 71 protected: 72 /* 73 * Update a SSL3-MAC Calculation 74 */ 75 override void addData(const(ubyte)* input, size_t length) 76 { 77 m_hash.update(input, length); 78 } 79 80 /* 81 * Finalize a SSL3-MAC Calculation 82 */ 83 override void finalResult(ubyte* mac) 84 { 85 m_hash.flushInto(mac); 86 m_hash.update(m_okey); 87 m_hash.update(mac, outputLength()); 88 m_hash.flushInto(mac); 89 m_hash.update(m_ikey); 90 } 91 92 /* 93 * SSL3-MAC Key Schedule 94 */ 95 override void keySchedule(const(ubyte)* key, size_t length) 96 { 97 m_hash.clear(); 98 99 // Quirk to deal with specification bug 100 const size_t inner_hash_length = (m_hash.name == "SHA-160") ? 60 : m_hash.hashBlockSize; 101 102 m_ikey.resize(inner_hash_length); 103 m_okey.resize(inner_hash_length); 104 105 fill(m_ikey.ptr[0 .. m_ikey.length], cast(ubyte) 0x36); 106 fill(m_okey.ptr[0 .. m_ikey.length], cast(ubyte) 0x5C); 107 108 copyMem(m_ikey.ptr, key, length); 109 copyMem(m_okey.ptr, key, length); 110 111 m_hash.update(m_ikey); 112 } 113 114 Unique!HashFunction m_hash; 115 SecureVector!ubyte m_ikey, m_okey; 116 }