1 /** 2 * TLS Handshake Hash 3 * 4 * Copyright: 5 * (C) 2004-2006,2011,2012 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.tls.handshake_hash; 12 13 import botan.constants; 14 static if (BOTAN_HAS_TLS): 15 package: 16 17 import memutils.vector; 18 import botan.tls.version_; 19 import botan.tls.magic; 20 import botan.tls.exceptn; 21 import botan.hash.hash; 22 import botan.libstate.libstate; 23 import botan.tls.exceptn; 24 import botan.libstate.libstate; 25 import botan.hash.hash; 26 import botan.utils.types; 27 28 /** 29 * TLS Handshake Hash 30 */ 31 struct HandshakeHash 32 { 33 public: 34 void update(const(ubyte)* input, size_t length) 35 { m_data ~= input[0 .. length]; } 36 37 void update(ALLOC)(auto const ref Vector!(ubyte, ALLOC) input) 38 { m_data ~= input[]; } 39 40 /** 41 * Return a TLS Handshake Hash 42 */ 43 SecureVector!ubyte flushInto(TLSProtocolVersion _version, in string mac_algo) const 44 { 45 AlgorithmFactory af = globalState().algorithmFactory(); 46 47 Unique!HashFunction hash; 48 49 if (_version.supportsCiphersuiteSpecificPrf()) 50 { 51 if (mac_algo == "MD5" || mac_algo == "SHA-1") 52 hash = af.makeHashFunction("SHA-256"); 53 else 54 hash = af.makeHashFunction(mac_algo); 55 } 56 else 57 hash = af.makeHashFunction("Parallel(MD5,SHA-160)"); 58 59 hash.update(m_data); 60 return hash.finished(); 61 } 62 63 /** 64 * Return a SSLv3 Handshake Hash 65 */ 66 SecureVector!ubyte finalSSL3()(auto const ref SecureVector!ubyte secret) const 67 { 68 const ubyte PAD_INNER = 0x36, PAD_OUTER = 0x5C; 69 70 AlgorithmFactory af = globalState().algorithmFactory(); 71 72 Unique!HashFunction md5 = af.makeHashFunction("MD5"); 73 Unique!HashFunction sha1 = af.makeHashFunction("SHA-1"); 74 75 md5.update(m_data); 76 sha1.update(m_data); 77 78 md5.update(secret); 79 sha1.update(secret); 80 81 foreach (size_t i; 0 .. 48) 82 md5.update(PAD_INNER); 83 foreach (size_t i; 0 .. 40) 84 sha1.update(PAD_INNER); 85 86 SecureVector!ubyte inner_md5 = md5.finished(), inner_sha1 = sha1.finished(); 87 88 md5.update(secret); 89 sha1.update(secret); 90 91 foreach (size_t i; 0 .. 48) 92 md5.update(PAD_OUTER); 93 foreach (size_t i; 0 .. 40) 94 sha1.update(PAD_OUTER); 95 96 md5.update(inner_md5); 97 sha1.update(inner_sha1); 98 99 SecureVector!ubyte output; 100 output ~= md5.finished(); 101 output ~= sha1.finished(); 102 return output; 103 } 104 105 ref const(Vector!ubyte) getContents() const 106 { return m_data; } 107 108 void reset() { m_data.clear(); } 109 110 @property HandshakeHash dup() const 111 { 112 HandshakeHash ret; 113 ret.m_data = m_data.dup; 114 return ret; 115 } 116 private: 117 Vector!ubyte m_data; 118 }