keyMaterial[1] = new byte[macLen]; // server_write_MAC_secret
keyMaterial[2] = new byte[keyLen]; // client_write_key
keyMaterial[3] = new byte[keyLen]; // server_write_key
keyMaterial[4] = new byte[ivLen]; // client_write_IV
keyMaterial[5] = new byte[ivLen]; // server_write_IV
IRandom prf = null;
if (activeVersion == ProtocolVersion.SSL_3)
{
prf = new SSLRandom();
HashMap attr = new HashMap();
attr.put(SSLRandom.SECRET, session.masterSecret);
attr.put(SSLRandom.SEED, Util.concat(server, client));
prf.init(attr);
}
else
{
prf = new TLSRandom();
HashMap attr = new HashMap();
attr.put(TLSRandom.SECRET, session.masterSecret);
attr.put(TLSRandom.SEED, Util.concat("key expansion".getBytes("UTF-8"),
Util.concat(server, client)));
prf.init(attr);
}
for (int i = 0; i < keyMaterial.length; i++)
{
prf.nextBytes(keyMaterial[i], 0, keyMaterial[i].length);
}
// Exportable ciphers transform their keys once more, and use a
// nonsecret IV for block ciphers.
if (suite.isExportable())
{
int finalLen = suite.getCipher() == "DES" ? 8 : 16;
if (activeVersion == ProtocolVersion.SSL_3)
{
IMessageDigest md5 = HashFactory.getInstance(Registry.MD5_HASH);
md5.update(keyMaterial[2], 0, keyMaterial[2].length);
md5.update(client, 0, client.length);
md5.update(server, 0, server.length);
keyMaterial[2] = Util.trim(md5.digest(), finalLen);
md5.update(keyMaterial[3], 0, keyMaterial[3].length);
md5.update(server, 0, server.length);
md5.update(client, 0, client.length);
keyMaterial[3] = Util.trim(md5.digest(), finalLen);
if (!suite.isStreamCipher())
{
md5.update(client, 0, client.length);
md5.update(server, 0, server.length);
keyMaterial[4] = Util.trim(md5.digest(), ivLen);
md5.update(server, 0, server.length);
md5.update(client, 0, client.length);
keyMaterial[5] = Util.trim(md5.digest(), ivLen);
}
}
else
{
HashMap attr = new HashMap();
attr.put(TLSRandom.SECRET, keyMaterial[2]);
attr.put(TLSRandom.SEED,
Util.concat("client write key".getBytes("UTF-8"),
Util.concat(client, server)));
prf.init(attr);
keyMaterial[2] = new byte[finalLen];
prf.nextBytes(keyMaterial[2], 0, finalLen);
attr.put(TLSRandom.SECRET, keyMaterial[3]);
attr.put(TLSRandom.SEED,
Util.concat("server write key".getBytes("UTF-8"),
Util.concat(client, server)));
prf.init(attr);
keyMaterial[3] = new byte[finalLen];
prf.nextBytes(keyMaterial[3], 0, finalLen);
if (!suite.isStreamCipher())
{
attr.put(TLSRandom.SECRET, new byte[0]);
attr.put(TLSRandom.SEED, Util.concat("IV block".getBytes("UTF-8"),
Util.concat(client, server)));
prf.init(attr);
prf.nextBytes(keyMaterial[4], 0, keyMaterial[4].length);
prf.nextBytes(keyMaterial[5], 0, keyMaterial[5].length);
}
}
}
if (DEBUG_KEY_EXCHANGE)