123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.IO;
- using System.Threading;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Tls.Crypto;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- namespace BestHTTP.SecureProtocol.Org.BouncyCastle.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 TlsNonceGenerator CreateNonceGenerator(TlsCrypto crypto, 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);
- return crypto.CreateNonceGenerator(additionalSeedMaterial);
- }
- private readonly TlsCrypto m_crypto;
- private readonly int m_connectionEnd;
- private readonly TlsNonceGenerator m_nonceGenerator;
- private SecurityParameters m_securityParameters = null;
- private ProtocolVersion[] m_clientSupportedVersions = null;
- private ProtocolVersion m_clientVersion = null;
- private ProtocolVersion m_rsaPreMasterSecretVersion = null;
- private TlsSession m_session = null;
- private object m_userObject = null;
- private bool m_connected = false;
- internal AbstractTlsContext(TlsCrypto crypto, int connectionEnd)
- {
- this.m_crypto = crypto;
- this.m_connectionEnd = connectionEnd;
- this.m_nonceGenerator = CreateNonceGenerator(crypto, connectionEnd);
- }
- /// <exception cref="IOException"/>
- internal void HandshakeBeginning(TlsPeer peer)
- {
- lock (this)
- {
- //if (null != m_securityParameters)
- // throw new TlsFatalAlert(AlertDescription.internal_error, "Handshake already started");
- var tmp = this.m_securityParameters;
- m_securityParameters = new SecurityParameters();
- m_securityParameters.m_entity = m_connectionEnd;
- if (tmp != null)
- {
- this.m_securityParameters.IsRenegotiating = true;
- this.m_securityParameters.m_secureRenegotiation = tmp.m_secureRenegotiation;
- this.m_securityParameters.m_negotiatedVersion = tmp.m_negotiatedVersion;
- this.m_securityParameters.m_localVerifyData = tmp.m_localVerifyData;
- this.m_securityParameters.m_peerVerifyData = tmp.m_peerVerifyData;
- this.m_securityParameters.PreRenegotiatingServerCert = tmp.m_peerCertificate;
- }
- }
- peer.NotifyHandshakeBeginning();
- }
- /// <exception cref="IOException"/>
- internal void HandshakeComplete(TlsPeer peer, TlsSession session)
- {
- lock (this)
- {
- if (null == m_securityParameters)
- throw new TlsFatalAlert(AlertDescription.internal_error);
- this.m_session = session;
- this.m_connected = true;
- }
- peer.NotifyHandshakeComplete();
- }
- internal bool IsConnected
- {
- get { lock (this) return m_connected; }
- }
- internal bool IsHandshaking
- {
- get { lock (this) return !m_connected && null != m_securityParameters; }
- }
- public TlsCrypto Crypto
- {
- get { return m_crypto; }
- }
- public virtual TlsNonceGenerator NonceGenerator
- {
- get { return m_nonceGenerator; }
- }
- public SecurityParameters SecurityParameters
- {
- get { lock (this) return m_securityParameters; }
- }
- public abstract bool IsServer { get; }
- public virtual ProtocolVersion[] ClientSupportedVersions
- {
- get { return m_clientSupportedVersions; }
- }
- internal void SetClientSupportedVersions(ProtocolVersion[] clientSupportedVersions)
- {
- this.m_clientSupportedVersions = clientSupportedVersions;
- }
- public virtual ProtocolVersion ClientVersion
- {
- get { return m_clientVersion; }
- }
- internal void SetClientVersion(ProtocolVersion clientVersion)
- {
- this.m_clientVersion = clientVersion;
- }
- public virtual ProtocolVersion RsaPreMasterSecretVersion
- {
- get { return m_rsaPreMasterSecretVersion; }
- }
- internal void SetRsaPreMasterSecretVersion(ProtocolVersion rsaPreMasterSecretVersion)
- {
- this.m_rsaPreMasterSecretVersion = rsaPreMasterSecretVersion;
- }
- public virtual ProtocolVersion ServerVersion
- {
- get { return SecurityParameters.NegotiatedVersion; }
- }
- public virtual TlsSession ResumableSession
- {
- get
- {
- TlsSession session = Session;
- if (session == null || !session.IsResumable)
- return null;
- return session;
- }
- }
- public virtual TlsSession Session
- {
- get { return m_session; }
- }
- public virtual object UserObject
- {
- get { return m_userObject; }
- set { this.m_userObject = value; }
- }
- public virtual byte[] ExportChannelBinding(int channelBinding)
- {
- if (!IsConnected)
- throw new InvalidOperationException("Export of channel bindings unavailable before handshake completion");
- SecurityParameters securityParameters = SecurityParameters;
- if (TlsUtilities.IsTlsV13(securityParameters.NegotiatedVersion))
- return null;
- switch (channelBinding)
- {
- case ChannelBinding.tls_server_end_point:
- {
- byte[] tlsServerEndPoint = securityParameters.TlsServerEndPoint;
- return TlsUtilities.IsNullOrEmpty(tlsServerEndPoint) ? null : Arrays.Clone(tlsServerEndPoint);
- }
- case ChannelBinding.tls_unique:
- {
- return Arrays.Clone(securityParameters.TlsUnique);
- }
- case ChannelBinding.tls_unique_for_telnet:
- default:
- throw new NotSupportedException();
- }
- }
- public virtual byte[] ExportEarlyKeyingMaterial(string asciiLabel, byte[] context, int length)
- {
- // TODO[tls13] Ensure early_exporter_master_secret is available suitably early!
- if (!IsConnected)
- throw new InvalidOperationException("Export of early key material only available during handshake");
- SecurityParameters sp = SecurityParameters;
- return ExportKeyingMaterial13(CheckEarlyExportSecret(sp.EarlyExporterMasterSecret),
- sp.PrfCryptoHashAlgorithm, asciiLabel, context, length);
- }
- public virtual byte[] ExportKeyingMaterial(string asciiLabel, byte[] context, int length)
- {
- if (!IsConnected)
- throw new InvalidOperationException("Export of key material unavailable before handshake completion");
- /*
- * TODO[tls13] Introduce a TlsExporter interface? Avoid calculating (early) exporter
- * secret(s) unless the peer actually uses it.
- */
- 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("Export of key material requires extended_master_secret");
- }
- if (TlsUtilities.IsTlsV13(sp.NegotiatedVersion))
- {
- return ExportKeyingMaterial13(CheckExportSecret(sp.ExporterMasterSecret), sp.PrfCryptoHashAlgorithm,
- asciiLabel, context, length);
- }
- byte[] seed = TlsUtilities.CalculateExporterSeed(sp, context);
- return TlsUtilities.Prf(sp, CheckExportSecret(sp.MasterSecret), asciiLabel, seed, length).Extract();
- }
- protected virtual byte[] ExportKeyingMaterial13(TlsSecret secret, int cryptoHashAlgorithm, string asciiLabel,
- byte[] context, int length)
- {
- if (null == context)
- {
- context = TlsUtilities.EmptyBytes;
- }
- else if (!TlsUtilities.IsValidUint16(context.Length))
- {
- throw new ArgumentException("must have length less than 2^16 (or be null)", "context");
- }
- return TlsCryptoUtilities.HkdfExpandLabel(secret, cryptoHashAlgorithm, asciiLabel, context, length)
- .Extract();
- }
- protected virtual TlsSecret CheckEarlyExportSecret(TlsSecret secret)
- {
- if (null == secret)
- {
- // TODO[tls13] For symmetry with normal export, ideally available for NotifyHandshakeBeginning() only
- //throw new InvalidOperationException("Export of early key material only available from NotifyHandshakeBeginning()");
- throw new InvalidOperationException("Export of early key material not available for this handshake");
- }
- return secret;
- }
- protected virtual TlsSecret CheckExportSecret(TlsSecret secret)
- {
- if (null == secret)
- throw new InvalidOperationException(
- "Export of key material only available from NotifyHandshakeComplete()");
- return secret;
- }
- }
- }
- #pragma warning restore
- #endif
|