1 /** 2 * SSLv3 PRF 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.kdf.prf_ssl3; 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.algo_base.symkey; 18 import botan.utils.exceptn; 19 import botan.hash.hash; 20 import botan.hash.sha160; 21 import botan.hash.md5; 22 import botan.utils.types; 23 import std.algorithm : min; 24 25 /** 26 * PRF used in SSLv3 27 */ 28 class SSL3PRF : KDF 29 { 30 public: 31 /* 32 * SSL3 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 if (key_len > 416) 39 throw new InvalidArgument("SSL3_PRF: Requested key length is too large"); 40 41 Unique!MD5 md5 = new MD5(); 42 Unique!SHA160 sha1 = new SHA160(); 43 44 OctetString output = OctetString(""); 45 46 int counter = 0; 47 while (key_len) 48 { 49 size_t produce = min(key_len, md5.outputLength); 50 51 output ~= nextHash(counter++, produce, *md5, *sha1, secret, secret_len, seed, seed_len); 52 53 key_len -= produce; 54 } 55 return output.bitsOf().dup; 56 } 57 58 override @property string name() const { return "SSL3-PRF"; } 59 override KDF clone() const { return new SSL3PRF; } 60 } 61 62 private: 63 64 /* 65 * Return the next inner hash 66 */ 67 OctetString nextHash(size_t where, size_t want, 68 HashFunction md5, HashFunction sha1, 69 const(ubyte)* secret, size_t secret_len, 70 const(ubyte)* seed, size_t seed_len) 71 { 72 assert(want <= md5.outputLength, 73 "Output size producable by MD5"); 74 75 __gshared immutable ubyte ASCII_A_CHAR = 0x41; 76 77 foreach (size_t j; 0 .. where + 1) 78 sha1.update(cast(ubyte)(ASCII_A_CHAR + where)); 79 sha1.update(secret, secret_len); 80 sha1.update(seed, seed_len); 81 SecureVector!ubyte sha1_hash = sha1.finished(); 82 83 md5.update(secret, secret_len); 84 md5.update(sha1_hash); 85 SecureVector!ubyte md5_hash = md5.finished(); 86 87 return OctetString(md5_hash.ptr, want); 88 }