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 }