1 /**
2 * TLS Session Key
3 * 
4 * Copyright:
5 * (C) 2004-2006,2011 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.session_key;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_TLS):
15 package:
16 
17 import botan.algo_base.symkey;
18 import botan.tls.handshake_state;
19 import botan.tls.messages;
20 
21 /**
22 * TLS TLSSession Keys
23 */
24 struct TLSSessionKeys
25 {
26 public:
27     const(SymmetricKey) clientCipherKey() const { return m_c_cipher; }
28     const(SymmetricKey) serverCipherKey() const { return m_s_cipher; }
29 
30     const(SymmetricKey) clientMacKey() const { return m_c_mac; }
31     const(SymmetricKey) serverMacKey() const { return m_s_mac; }
32 
33     const(InitializationVector) clientIv() const { return m_c_iv; }
34     const(InitializationVector) serverIv() const { return m_s_iv; }
35 
36     ref const(SecureVector!ubyte) masterSecret() const { return m_master_sec; }
37 
38     @disable this();
39 
40     /**
41     * TLSSessionKeys Constructor
42     */
43     this()(in HandshakeState state, auto ref SecureVector!ubyte pre_master_secret, bool resuming)
44     {
45         const size_t cipher_keylen = state.ciphersuite().cipherKeylen();
46         const size_t mac_keylen = state.ciphersuite().macKeylen();
47         const size_t cipher_nonce_bytes = state.ciphersuite().nonceBytesFromHandshake();
48 		const bool extended_master_secret = state.serverHello().supportsExtendedMasterSecret();
49 
50         const size_t prf_gen = 2 * (mac_keylen + cipher_keylen + cipher_nonce_bytes);
51         
52         __gshared immutable immutable(ubyte)[] MASTER_SECRET_MAGIC = [
53             0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74 ];
54         
55         __gshared immutable immutable(ubyte)[] KEY_GEN_MAGIC = [
56             0x6B, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6E, 0x73, 0x69, 0x6F, 0x6E ];
57         
58 		__gshared immutable immutable(ubyte)[] EXT_MASTER_SECRET_MAGIC = [
59 		    0x65, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20,
60 		    0x6D, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74 ];
61 
62         Unique!KDF prf = state.protocolSpecificPrf();
63         
64         if (resuming)
65         {
66             m_master_sec = pre_master_secret.dup;
67         }
68         else
69         {
70             SecureVector!ubyte salt;
71 			salt.reserve(64);
72 
73 			if (extended_master_secret)
74 			{
75 				   salt ~= cast(ubyte[])EXT_MASTER_SECRET_MAGIC;
76 				   salt ~= state.hash().flushInto(state.Version(),
77 				                                   state.ciphersuite().prfAlgo());
78 			}
79 			else
80 			{
81 				   salt ~= cast(ubyte[])MASTER_SECRET_MAGIC;
82 				   salt ~= state.clientHello().random()[];
83 				   salt ~= state.serverHello().random()[];
84 			}
85             
86             m_master_sec = prf.deriveKey(48, pre_master_secret, salt);
87         }
88         
89         SecureVector!ubyte salt;
90 		salt.reserve(64);
91         salt ~= cast(ubyte[])KEY_GEN_MAGIC;
92 		salt ~= state.serverHello().randomBytes();
93 		salt ~= state.clientHello().randomBytes();
94         
95         SymmetricKey keyblock = prf.deriveKey(prf_gen, m_master_sec, salt);
96         
97         const(ubyte)* key_data = keyblock.ptr;
98         
99         m_c_mac = SymmetricKey(key_data, mac_keylen);
100         key_data += mac_keylen;
101         
102         m_s_mac = SymmetricKey(key_data, mac_keylen);
103         key_data += mac_keylen;
104         
105         m_c_cipher = SymmetricKey(key_data, cipher_keylen);
106         key_data += cipher_keylen;
107         
108         m_s_cipher = SymmetricKey(key_data, cipher_keylen);
109         key_data += cipher_keylen;
110         
111         m_c_iv = InitializationVector(key_data, cipher_nonce_bytes);
112         key_data += cipher_nonce_bytes;
113         
114         m_s_iv = InitializationVector(key_data, cipher_nonce_bytes);
115     }
116 
117 private:
118     SecureVector!ubyte m_master_sec;
119     SymmetricKey m_c_cipher, m_s_cipher, m_c_mac, m_s_mac;
120     InitializationVector m_c_iv, m_s_iv;
121 }