You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

166 lines
5.5 KiB

using System;
using System.Threading;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Tls
{
internal abstract class AbstractTlsContext
: TlsContext
{
private static long counter = Times.NanoTime();
#if NETCF_1_0
private static object counterLock = new object();
private static long NextCounterValue()
{
lock (counterLock)
{
return ++counter;
}
}
#else
private static long NextCounterValue()
{
return Interlocked.Increment(ref counter);
}
#endif
private static IRandomGenerator CreateNonceRandom(SecureRandom secureRandom, int connectionEnd)
{
byte[] additionalSeedMaterial = new byte[16];
Pack.UInt64_To_BE((ulong)NextCounterValue(), additionalSeedMaterial, 0);
Pack.UInt64_To_BE((ulong)Times.NanoTime(), additionalSeedMaterial, 8);
additionalSeedMaterial[0] &= 0x7F;
additionalSeedMaterial[0] |= (byte)(connectionEnd << 7);
IDigest digest = TlsUtilities.CreateHash(HashAlgorithm.sha256);
byte[] seed = new byte[digest.GetDigestSize()];
secureRandom.NextBytes(seed);
IRandomGenerator nonceRandom = new DigestRandomGenerator(digest);
nonceRandom.AddSeedMaterial(additionalSeedMaterial);
nonceRandom.AddSeedMaterial(seed);
return nonceRandom;
}
private readonly IRandomGenerator mNonceRandom;
private readonly SecureRandom mSecureRandom;
private readonly SecurityParameters mSecurityParameters;
private ProtocolVersion mClientVersion = null;
private ProtocolVersion mServerVersion = null;
private TlsSession mSession = null;
private object mUserObject = null;
internal AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
{
this.mSecureRandom = secureRandom;
this.mSecurityParameters = securityParameters;
this.mNonceRandom = CreateNonceRandom(secureRandom, securityParameters.Entity);
}
public virtual IRandomGenerator NonceRandomGenerator
{
get { return mNonceRandom; }
}
public virtual SecureRandom SecureRandom
{
get { return mSecureRandom; }
}
public virtual SecurityParameters SecurityParameters
{
get { return mSecurityParameters; }
}
public abstract bool IsServer { get; }
public virtual ProtocolVersion ClientVersion
{
get { return mClientVersion; }
}
internal virtual void SetClientVersion(ProtocolVersion clientVersion)
{
this.mClientVersion = clientVersion;
}
public virtual ProtocolVersion ServerVersion
{
get { return mServerVersion; }
}
internal virtual void SetServerVersion(ProtocolVersion serverVersion)
{
this.mServerVersion = serverVersion;
}
public virtual TlsSession ResumableSession
{
get { return mSession; }
}
internal virtual void SetResumableSession(TlsSession session)
{
this.mSession = session;
}
public virtual object UserObject
{
get { return mUserObject; }
set { this.mUserObject = value; }
}
public virtual byte[] ExportKeyingMaterial(string asciiLabel, byte[] context_value, int length)
{
if (context_value != null && !TlsUtilities.IsValidUint16(context_value.Length))
throw new ArgumentException("must have length less than 2^16 (or be null)", "context_value");
SecurityParameters sp = SecurityParameters;
if (!sp.IsExtendedMasterSecret)
{
/*
* RFC 7627 5.4. If a client or server chooses to continue with a full handshake without
* the extended master secret extension, [..] the client or server MUST NOT export any
* key material based on the new master secret for any subsequent application-level
* authentication. In particular, it MUST disable [RFC5705] [..].
*/
throw new InvalidOperationException("cannot export keying material without extended_master_secret");
}
byte[] cr = sp.ClientRandom, sr = sp.ServerRandom;
int seedLength = cr.Length + sr.Length;
if (context_value != null)
{
seedLength += (2 + context_value.Length);
}
byte[] seed = new byte[seedLength];
int seedPos = 0;
Array.Copy(cr, 0, seed, seedPos, cr.Length);
seedPos += cr.Length;
Array.Copy(sr, 0, seed, seedPos, sr.Length);
seedPos += sr.Length;
if (context_value != null)
{
TlsUtilities.WriteUint16(context_value.Length, seed, seedPos);
seedPos += 2;
Array.Copy(context_value, 0, seed, seedPos, context_value.Length);
seedPos += context_value.Length;
}
if (seedPos != seedLength)
throw new InvalidOperationException("error in calculation of seed for export");
return TlsUtilities.PRF(this, sp.MasterSecret, asciiLabel, seed, length);
}
}
}