1 /** 2 * TLS v1.0 and v1.2 PRFs 3 * 4 * Copyright: 5 * (C) 2004-2010 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.kdf.prf_tls; 12 13 import botan.constants; 14 static if (BOTAN_HAS_TLS || BOTAN_HAS_PUBLIC_KEY_CRYPTO): 15 16 import botan.kdf.kdf; 17 import botan.mac.mac; 18 import botan.utils.xor_buf; 19 import botan.mac.hmac; 20 import botan.hash.md5; 21 import botan.hash.sha160; 22 import std.conv : to; 23 import std.algorithm : min, max; 24 25 /** 26 * PRF used in TLS 1.0/1.1 27 */ 28 class TLSPRF : KDF 29 { 30 public: 31 /* 32 * TLS PRF 33 */ 34 override SecureVector!ubyte derive(size_t key_len, 35 const(ubyte)* secret, size_t secret_len, 36 const(ubyte)* seed, size_t seed_len) const 37 { 38 SecureVector!ubyte output = SecureVector!ubyte(key_len); 39 40 size_t S1_len = (secret_len + 1) / 2; 41 size_t S2_len = (secret_len + 1) / 2; 42 const(ubyte)* S1 = secret; 43 const(ubyte)* S2 = secret + (secret_len - S2_len); 44 45 P_hash(output, cast() *m_hmac_md5, S1, S1_len, seed, seed_len); 46 P_hash(output, cast() *m_hmac_sha1, S2, S2_len, seed, seed_len); 47 48 return output; 49 } 50 51 override @property string name() const { return "TLS-PRF"; } 52 override KDF clone() const { return new TLSPRF; } 53 54 /* 55 * TLS PRF Constructor and Destructor 56 */ 57 this() 58 { 59 m_hmac_md5 = new HMAC(new MD5); 60 m_hmac_sha1= new HMAC(new SHA160); 61 } 62 63 private: 64 Unique!MessageAuthenticationCode m_hmac_md5; 65 Unique!MessageAuthenticationCode m_hmac_sha1; 66 } 67 68 /** 69 * PRF used in TLS 1.2 70 */ 71 class TLS12PRF : KDF 72 { 73 public: 74 override SecureVector!ubyte derive(size_t key_len, 75 const(ubyte)* secret, size_t secret_len, 76 const(ubyte)* seed, size_t seed_len) const 77 { 78 SecureVector!ubyte output = SecureVector!ubyte(key_len); 79 80 P_hash(output, cast() *m_hmac, secret, secret_len, seed, seed_len); 81 82 return output; 83 } 84 85 override @property string name() const { return "TLSv12-PRF(" ~ m_hmac.name ~ ")"; } 86 override KDF clone() const { return new TLS12PRF(m_hmac.clone()); } 87 88 /* 89 * TLS v1.2 PRF Constructor and Destructor 90 */ 91 this(MessageAuthenticationCode mac) 92 { 93 m_hmac = mac; 94 } 95 private: 96 Unique!MessageAuthenticationCode m_hmac; 97 } 98 99 100 private: 101 /* 102 * TLS PRF P_hash function 103 */ 104 void P_hash(ref SecureVector!ubyte output, 105 MessageAuthenticationCode mac, 106 const(ubyte)* secret, size_t secret_len, 107 const(ubyte)* seed, size_t seed_len) 108 { 109 try 110 { 111 mac.setKey(secret, secret_len); 112 } 113 catch(InvalidKeyLength) 114 { 115 throw new InternalError("The premaster secret of " ~ to!string(secret_len) ~ " bytes is too long for the PRF"); 116 } 117 118 SecureVector!ubyte A = SecureVector!ubyte(seed[0 .. seed_len]); 119 120 size_t offset = 0; 121 122 while (offset != output.length) 123 { 124 const size_t this_block_len = min(mac.outputLength, output.length - offset); 125 126 A = mac.process(A); 127 128 mac.update(A); 129 mac.update(seed, seed_len); 130 SecureVector!ubyte block = mac.finished(); 131 132 xorBuf(&output[offset], block.ptr, this_block_len); 133 offset += this_block_len; 134 } 135 }