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 }