diff --git a/crypto/src/tls/SecurityParameters.cs b/crypto/src/tls/SecurityParameters.cs
index 84c3b9f11..f4aa1ac5a 100644
--- a/crypto/src/tls/SecurityParameters.cs
+++ b/crypto/src/tls/SecurityParameters.cs
@@ -22,6 +22,7 @@ namespace Org.BouncyCastle.Tls
internal TlsSecret m_exporterMasterSecret = null;
internal TlsSecret m_handshakeSecret = null;
internal TlsSecret m_masterSecret = null;
+ internal TlsSecret m_preSharedKey = null;
internal TlsSecret m_sharedSecret = null;
internal TlsSecret m_trafficSecretClient = null;
internal TlsSecret m_trafficSecretServer = null;
@@ -29,7 +30,6 @@ namespace Org.BouncyCastle.Tls
internal byte[] m_serverRandom = null;
internal byte[] m_sessionHash = null;
internal byte[] m_sessionID = null;
- internal byte[] m_psk = null;
internal byte[] m_pskIdentity = null;
internal byte[] m_srpIdentity = null;
internal byte[] m_tlsServerEndPoint = null;
@@ -79,6 +79,7 @@ namespace Org.BouncyCastle.Tls
this.m_exporterMasterSecret = ClearSecret(m_exporterMasterSecret);
this.m_handshakeSecret = ClearSecret(m_handshakeSecret);
this.m_masterSecret = ClearSecret(m_masterSecret);
+ this.m_preSharedKey = null;
this.m_sharedSecret = ClearSecret(m_sharedSecret);
}
@@ -227,6 +228,11 @@ namespace Org.BouncyCastle.Tls
get { return m_peerVerifyData; }
}
+ public TlsSecret PreSharedKey
+ {
+ get { return m_preSharedKey; }
+ }
+
public int PrfAlgorithm
{
get { return m_prfAlgorithm; }
@@ -242,11 +248,6 @@ namespace Org.BouncyCastle.Tls
get { return m_prfHashLength; }
}
- public byte[] Psk
- {
- get { return m_psk; }
- }
-
public byte[] PskIdentity
{
get { return m_pskIdentity; }
diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs
index 52b554801..adead624b 100644
--- a/crypto/src/tls/TlsUtilities.cs
+++ b/crypto/src/tls/TlsUtilities.cs
@@ -1459,6 +1459,23 @@ namespace Org.BouncyCastle.Tls
return Arrays.ConcatenateAll(cr, sr, contextLength, context);
}
+ private static byte[] CalculateFinishedHmac(SecurityParameters securityParameters, TlsSecret baseKey,
+ byte[] transcriptHash)
+ {
+ int cryptoHashAlgorithm = TlsCryptoUtilities.GetHash(securityParameters.PrfHashAlgorithm);
+ TlsSecret finishedKey = TlsCryptoUtilities.HkdfExpandLabel(baseKey, cryptoHashAlgorithm, "finished",
+ EmptyBytes, securityParameters.PrfHashLength);
+
+ try
+ {
+ return finishedKey.CalculateHmac(cryptoHashAlgorithm, transcriptHash, 0, transcriptHash.Length);
+ }
+ finally
+ {
+ finishedKey.Destroy();
+ }
+ }
+
internal static TlsSecret CalculateMasterSecret(TlsContext context, TlsSecret preMasterSecret)
{
SecurityParameters sp = context.SecurityParameters;
@@ -1479,6 +1496,28 @@ namespace Org.BouncyCastle.Tls
return Prf(sp, preMasterSecret, asciiLabel, seed, 48);
}
+ internal static byte[] CalculatePskBinder(TlsContext context, bool isExternalPsk, TlsSecret earlySecret,
+ byte[] transcriptHash)
+ {
+ TlsCrypto crypto = context.Crypto;
+ SecurityParameters securityParameters = context.SecurityParameters;
+ int cryptoHashAlgorithm = TlsCryptoUtilities.GetHash(securityParameters.PrfHashAlgorithm);
+
+ string label = isExternalPsk ? "ext binder" : "res binder";
+ byte[] emptyTranscriptHash = crypto.CreateHash(cryptoHashAlgorithm).CalculateHash();
+
+ TlsSecret baseKey = DeriveSecret(securityParameters, earlySecret, label, emptyTranscriptHash);
+
+ try
+ {
+ return CalculateFinishedHmac(securityParameters, baseKey, transcriptHash);
+ }
+ finally
+ {
+ baseKey.Destroy();
+ }
+ }
+
internal static byte[] CalculateVerifyData(TlsContext context, TlsHandshakeHash handshakeHash, bool isServer)
{
SecurityParameters securityParameters = context.SecurityParameters;
@@ -1489,12 +1528,9 @@ namespace Org.BouncyCastle.Tls
TlsSecret baseKey = isServer
? securityParameters.BaseKeyServer
: securityParameters.BaseKeyClient;
-
- TlsSecret finishedKey = DeriveSecret(securityParameters, baseKey, "finished", EmptyBytes);
- int cryptoHashAlgorithm = TlsCryptoUtilities.GetHash(securityParameters.PrfHashAlgorithm);
byte[] transcriptHash = GetCurrentPrfHash(handshakeHash);
- return finishedKey.CalculateHmac(cryptoHashAlgorithm, transcriptHash, 0, transcriptHash.Length);
+ return CalculateFinishedHmac(securityParameters, baseKey, transcriptHash);
}
if (negotiatedVersion.IsSsl)
@@ -1513,43 +1549,43 @@ namespace Org.BouncyCastle.Tls
internal static void Establish13PhaseSecrets(TlsContext context)
{
+ TlsCrypto crypto = context.Crypto;
SecurityParameters securityParameters = context.SecurityParameters;
int cryptoHashAlgorithm = TlsCryptoUtilities.GetHash(securityParameters.PrfHashAlgorithm);
- int hashLen = securityParameters.PrfHashLength;
- byte[] zeroes = new byte[hashLen];
+ TlsSecret zeros = crypto.HkdfInit(cryptoHashAlgorithm);
+ byte[] emptyTranscriptHash = crypto.CreateHash(cryptoHashAlgorithm).CalculateHash();
- byte[] psk = securityParameters.Psk;
- if (null == psk)
- {
- psk = zeroes;
- }
- else
+ TlsSecret preSharedKey = securityParameters.PreSharedKey;
+ if (null == preSharedKey)
{
- securityParameters.m_psk = null;
+ preSharedKey = zeros;
}
- byte[] ecdhe = zeroes;
+ TlsSecret earlySecret = crypto.HkdfInit(cryptoHashAlgorithm)
+ .HkdfExtract(cryptoHashAlgorithm, preSharedKey);
+
TlsSecret sharedSecret = securityParameters.SharedSecret;
- if (null != sharedSecret)
+ if (null == sharedSecret)
{
- securityParameters.m_sharedSecret = null;
- ecdhe = sharedSecret.Extract();
+ sharedSecret = zeros;
}
- TlsCrypto crypto = context.Crypto;
+ TlsSecret handshakeSecret = DeriveSecret(securityParameters, earlySecret, "derived", emptyTranscriptHash)
+ .HkdfExtract(cryptoHashAlgorithm, sharedSecret);
- byte[] emptyTranscriptHash = crypto.CreateHash(cryptoHashAlgorithm).CalculateHash();
+ if (sharedSecret != zeros)
+ {
+ sharedSecret.Destroy();
+ }
- TlsSecret earlySecret = crypto.HkdfInit(cryptoHashAlgorithm)
- .HkdfExtract(cryptoHashAlgorithm, psk);
- TlsSecret handshakeSecret = DeriveSecret(securityParameters, earlySecret, "derived", emptyTranscriptHash)
- .HkdfExtract(cryptoHashAlgorithm, ecdhe);
TlsSecret masterSecret = DeriveSecret(securityParameters, handshakeSecret, "derived", emptyTranscriptHash)
- .HkdfExtract(cryptoHashAlgorithm, zeroes);
+ .HkdfExtract(cryptoHashAlgorithm, zeros);
securityParameters.m_earlySecret = earlySecret;
securityParameters.m_handshakeSecret = handshakeSecret;
securityParameters.m_masterSecret = masterSecret;
+ securityParameters.m_preSharedKey = null;
+ securityParameters.m_sharedSecret = null;
}
private static void Establish13TrafficSecrets(TlsContext context, byte[] transcriptHash, TlsSecret phaseSecret,
@@ -5170,8 +5206,13 @@ namespace Org.BouncyCastle.Tls
internal static TlsSecret DeriveSecret(SecurityParameters securityParameters, TlsSecret secret, string label,
byte[] transcriptHash)
{
- return TlsCryptoUtilities.HkdfExpandLabel(secret, securityParameters.PrfHashAlgorithm, label,
- transcriptHash, securityParameters.PrfHashLength);
+ short prfHashAlgorithm = securityParameters.PrfHashAlgorithm;
+ int prfHashLength = securityParameters.PrfHashLength;
+
+ if (transcriptHash.Length != prfHashLength)
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+
+ return TlsCryptoUtilities.HkdfExpandLabel(secret, prfHashAlgorithm, label, transcriptHash, prfHashLength);
}
internal static TlsSecret GetSessionMasterSecret(TlsCrypto crypto, TlsSecret masterSecret)
diff --git a/crypto/src/tls/crypto/TlsSecret.cs b/crypto/src/tls/crypto/TlsSecret.cs
index 8c39c56f7..8aea34bcf 100644
--- a/crypto/src/tls/crypto/TlsSecret.cs
+++ b/crypto/src/tls/crypto/TlsSecret.cs
@@ -61,7 +61,7 @@ namespace Org.BouncyCastle.Tls.Crypto
/// <see cref="CryptoHashAlgorithm"/> for values.</param>
/// <param name="ikm">input keying material.</param>
/// <returns>a pseudo-random key (of HashLen octets).</returns>
- TlsSecret HkdfExtract(int cryptoHashAlgorithm, byte[] ikm);
+ TlsSecret HkdfExtract(int cryptoHashAlgorithm, TlsSecret ikm);
bool IsAlive();
}
diff --git a/crypto/src/tls/crypto/impl/AbstractTlsSecret.cs b/crypto/src/tls/crypto/impl/AbstractTlsSecret.cs
index 1ea25344d..cc07f978f 100644
--- a/crypto/src/tls/crypto/impl/AbstractTlsSecret.cs
+++ b/crypto/src/tls/crypto/impl/AbstractTlsSecret.cs
@@ -9,6 +9,11 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl
public abstract class AbstractTlsSecret
: TlsSecret
{
+ protected static byte[] CopyData(AbstractTlsSecret other)
+ {
+ return other.CopyData();
+ }
+
protected byte[] m_data;
/// <summary>Base constructor.</summary>
@@ -79,7 +84,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl
public abstract TlsSecret HkdfExpand(int cryptoHashAlgorithm, byte[] info, int length);
- public abstract TlsSecret HkdfExtract(int cryptoHashAlgorithm, byte[] ikm);
+ public abstract TlsSecret HkdfExtract(int cryptoHashAlgorithm, TlsSecret ikm);
public virtual bool IsAlive()
{
diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsSecret.cs b/crypto/src/tls/crypto/impl/bc/BcTlsSecret.cs
index b76c1612a..47a3d1212 100644
--- a/crypto/src/tls/crypto/impl/bc/BcTlsSecret.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcTlsSecret.cs
@@ -12,6 +12,21 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
public class BcTlsSecret
: AbstractTlsSecret
{
+ public static BcTlsSecret Convert(BcTlsCrypto crypto, TlsSecret secret)
+ {
+ if (secret is BcTlsSecret)
+ return (BcTlsSecret)secret;
+
+ if (secret is AbstractTlsSecret)
+ {
+ AbstractTlsSecret abstractTlsSecret = (AbstractTlsSecret)secret;
+
+ return crypto.AdoptLocalSecret(CopyData(abstractTlsSecret));
+ }
+
+ throw new ArgumentException("unrecognized TlsSecret - cannot copy data: " + Platform.GetTypeName(secret));
+ }
+
// SSL3 magic mix constants ("A", "BB", "CCC", ...)
private static readonly byte[] Ssl3Const = GenerateSsl3Constants();
@@ -105,7 +120,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
}
}
- public override TlsSecret HkdfExtract(int cryptoHashAlgorithm, byte[] ikm)
+ public override TlsSecret HkdfExtract(int cryptoHashAlgorithm, TlsSecret ikm)
{
lock (this)
{
@@ -117,7 +132,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
HMac hmac = new HMac(m_crypto.CreateDigest(cryptoHashAlgorithm));
hmac.Init(new KeyParameter(salt));
- hmac.BlockUpdate(ikm, 0, ikm.Length);
+ Convert(m_crypto, ikm).UpdateMac(hmac);
byte[] prk = new byte[hmac.GetMacSize()];
hmac.DoFinal(prk, 0);
@@ -238,5 +253,15 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
HmacHash(digest, m_data, 0, m_data.Length, labelSeed, result);
return result;
}
+
+ protected virtual void UpdateMac(IMac mac)
+ {
+ lock (this)
+ {
+ CheckAlive();
+
+ mac.BlockUpdate(m_data, 0, m_data.Length);
+ }
+ }
}
}
diff --git a/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs b/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs
index cf1397ef2..75a3d1e00 100644
--- a/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs
+++ b/crypto/test/src/tls/crypto/test/BcTlsCryptoTest.cs
@@ -236,7 +236,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Tests
// {server} extract secret "early":
{
- byte[] ikm = new byte[32];
+ TlsSecret ikm = m_crypto.HkdfInit(hash);
early = init.HkdfExtract(hash, ikm);
Expect(early, "33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a");
}
@@ -250,7 +250,8 @@ namespace Org.BouncyCastle.Tls.Crypto.Tests
// {server} extract secret "handshake":
{
- byte[] ikm = Hex("8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d");
+ TlsSecret ikm = m_crypto.CreateSecret(
+ Hex("8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d 35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d"));
handshake = handshake.HkdfExtract(hash, ikm);
Expect(handshake, "1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b 01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac");
}
@@ -284,7 +285,7 @@ namespace Org.BouncyCastle.Tls.Crypto.Tests
// {server} extract secret "master":
{
- byte[] ikm = new byte[32];
+ TlsSecret ikm = m_crypto.HkdfInit(hash);
master = master.HkdfExtract(hash, ikm);
Expect(master, "18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a 47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19");
}
@@ -408,11 +409,11 @@ namespace Org.BouncyCastle.Tls.Crypto.Tests
{
int hash = hashes[i];
int hashLen = TlsCryptoUtilities.GetHashOutputSize(hash);
- byte[] zeroes = new byte[hashLen];
+ TlsSecret zeros = m_crypto.HkdfInit(hash);
int limit = 255 * hashLen;
- TlsSecret secret = m_crypto.HkdfInit(hash).HkdfExtract(hash, zeroes);
+ TlsSecret secret = m_crypto.HkdfInit(hash).HkdfExtract(hash, zeros);
try
{
|