internal virtual byte[] DecodeAndVerify(byte type, Stream input, int len) { RecordStream.CheckLength(len, this.mCiphertextLimit, 22); byte[] array = TlsUtilities.ReadFully(len, input); TlsCipher arg_34_0 = this.mReadCipher; long seqNo; this.mReadSeqNo = (seqNo = this.mReadSeqNo) + 1L; byte[] array2 = arg_34_0.DecodeCiphertext(seqNo, type, array, 0, array.Length); RecordStream.CheckLength(array2.Length, this.mCompressedLimit, 22); Stream stream = this.mReadCompression.Decompress(this.mBuffer); if (stream != this.mBuffer) { stream.Write(array2, 0, array2.Length); stream.Flush(); array2 = this.GetBufferContents(); } RecordStream.CheckLength(array2.Length, this.mPlaintextLimit, 30); if (array2.Length < 1 && type != 23) { throw new TlsFatalAlert(47); } return(array2); }
internal virtual void InitPendingEpoch(TlsCipher pendingCipher) { if (this.mPendingEpoch != null) { throw new InvalidOperationException(); } this.mPendingEpoch = new DtlsEpoch(this.mWriteEpoch.Epoch + 1, pendingCipher); }
internal virtual void Init(TlsContext context) { mReadCipher = new TlsNullCipher(context); mWriteCipher = mReadCipher; mHandshakeHash = new DeferredHash(); mHandshakeHash.Init(context); SetPlaintextLimit(16384); }
internal virtual void Init(TlsContext context) { this.mReadCipher = new TlsNullCipher(context); this.mWriteCipher = this.mReadCipher; this.mHandshakeHash = new DeferredHash(); this.mHandshakeHash.Init(context); this.SetPlaintextLimit(0x4000); }
internal virtual void InitPendingEpoch(TlsCipher pendingCipher) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (mPendingEpoch != null) { throw new InvalidOperationException(); } mPendingEpoch = new DtlsEpoch(mWriteEpoch.Epoch + 1, pendingCipher); }
internal virtual void FinaliseHandshake() { if (((this.mReadCompression != this.mPendingCompression) || (this.mWriteCompression != this.mPendingCompression)) || ((this.mReadCipher != this.mPendingCipher) || (this.mWriteCipher != this.mPendingCipher))) { throw new TlsFatalAlert(40); } this.mPendingCompression = null; this.mPendingCipher = null; }
internal virtual void FinaliseHandshake() { if (mReadCompression != mPendingCompression || mWriteCompression != mPendingCompression || mReadCipher != mPendingCipher || mWriteCipher != mPendingCipher) { throw new TlsFatalAlert(40); } mPendingCompression = null; mPendingCipher = null; }
public void InitPendingEpoch(TlsCipher pendingCipher) { if (pendingEpoch != null) { throw new InvalidOperationException(); } this.pendingEpoch = new AsyncDtlsEpoch(writeEpoch.Epoch + 1, pendingCipher); }
internal virtual void ReceivedReadCipherSpec() { if (mPendingCompression == null || mPendingCipher == null) { throw new TlsFatalAlert(40); } mReadCompression = mPendingCompression; mReadCipher = mPendingCipher; mReadSeqNo = 0L; }
internal virtual void SentWriteCipherSpec() { if (mPendingCompression == null || mPendingCipher == null) { throw new TlsFatalAlert(40); } mWriteCompression = mPendingCompression; mWriteCipher = mPendingCipher; mWriteSeqNo = 0L; }
internal virtual void SentWriteCipherSpec() { if ((this.mPendingCompression == null) || (this.mPendingCipher == null)) { throw new TlsFatalAlert(40); } this.mWriteCompression = this.mPendingCompression; this.mWriteCipher = this.mPendingCipher; this.mWriteSeqNo = 0L; }
internal DtlsEpoch(int epoch, TlsCipher cipher) { if (epoch < 0) throw new ArgumentException("must be >= 0", "epoch"); if (cipher == null) throw new ArgumentNullException("cipher"); this.mEpoch = epoch; this.mCipher = cipher; }
internal virtual void FinaliseHandshake() { if (mReadCompression != mPendingCompression || mWriteCompression != mPendingCompression || mReadCipher != mPendingCipher || mWriteCipher != mPendingCipher) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } this.mPendingCompression = null; this.mPendingCipher = null; }
internal virtual void ReceivedReadCipherSpec() { if ((this.mPendingCompression == null) || (this.mPendingCipher == null)) { throw new TlsFatalAlert(40); } this.mReadCompression = this.mPendingCompression; this.mReadCipher = this.mPendingCipher; this.mReadSeqNo = 0L; }
internal RecordStream(TlsProtocolHandler handler, Stream inStr, Stream outStr) { _handler = handler; _inStr = inStr; _outStr = outStr; _hash = new CombinedHash(); _readCompression = new TlsNullCompression(); _writeCompression = _readCompression; _readCipher = new TlsNullCipher(); _writeCipher = _readCipher; }
internal RecordStream(TlsProtocolHandler handler, Stream inStr, Stream outStr) { _handler = handler; _inStr = inStr; _outStr = outStr; _hash = new CombinedHash(); _readCompression = new TlsNullCompression(); _writeCompression = _readCompression; _readCipher = new TlsNullCipher(); _writeCipher = _readCipher; }
internal RecordStream( TlsProtocolHandler handler, Stream inStr, Stream outStr) { this.handler = handler; this.inStr = inStr; this.outStr = outStr; this.hash = new CombinedHash(); this.readCipher = new TlsNullCipher(); this.writeCipher = this.readCipher; }
internal RecordStream( TlsProtocolHandler handler, Stream inStr, Stream outStr) { this.handler = handler; this.inStr = inStr; this.outStr = outStr; this.hash = new CombinedHash(); this.readCipher = new TlsNullCipher(); this.writeCipher = this.readCipher; }
internal DtlsEpoch(int epoch, TlsCipher cipher) { if (epoch < 0) { throw new ArgumentException("must be >= 0", "epoch"); } if (cipher == null) { throw new ArgumentNullException("cipher"); } this.mEpoch = epoch; this.mCipher = cipher; }
internal virtual void InitPendingEpoch(TlsCipher pendingCipher) { if (mPendingEpoch != null) throw new InvalidOperationException(); /* * TODO "In order to ensure that any given sequence/epoch pair is unique, implementations * MUST NOT allow the same epoch value to be reused within two times the TCP maximum segment * lifetime." */ // TODO Check for overflow this.mPendingEpoch = new DtlsEpoch(mWriteEpoch.Epoch + 1, pendingCipher); }
public AsyncDtlsEpoch(int epoch, TlsCipher cipher) { if (epoch < 0) { throw new ArgumentException("'epoch' must be >= 0"); } if (cipher == null) { throw new ArgumentException("'cipher' cannot be null"); } this.epoch = epoch; this.cipher = cipher; }
internal DtlsEpoch(int epoch, TlsCipher cipher) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (epoch < 0) { throw new ArgumentException("must be >= 0", "epoch"); } if (cipher == null) { throw new ArgumentNullException("cipher"); } mEpoch = epoch; mCipher = cipher; }
internal virtual void InitPendingEpoch(TlsCipher pendingCipher) { if (mPendingEpoch != null) { throw new InvalidOperationException(); } /* * TODO "In order to ensure that any given sequence/epoch pair is unique, implementations * MUST NOT allow the same epoch value to be reused within two times the TCP maximum segment * lifetime." */ // TODO Check for overflow this.mPendingEpoch = new DtlsEpoch(mWriteEpoch.Epoch + 1, pendingCipher); }
internal virtual void WriteRecord(byte type, byte[] plaintext, int plaintextOffset, int plaintextLength) { if (this.mWriteVersion == null) { return; } RecordStream.CheckType(type, 80); RecordStream.CheckLength(plaintextLength, this.mPlaintextLimit, 80); if (plaintextLength < 1 && type != 23) { throw new TlsFatalAlert(80); } if (type == 22) { this.UpdateHandshakeData(plaintext, plaintextOffset, plaintextLength); } Stream stream = this.mWriteCompression.Compress(this.mBuffer); byte[] array; if (stream == this.mBuffer) { TlsCipher arg_7B_0 = this.mWriteCipher; long seqNo; this.mWriteSeqNo = (seqNo = this.mWriteSeqNo) + 1L; array = arg_7B_0.EncodePlaintext(seqNo, type, plaintext, plaintextOffset, plaintextLength); } else { stream.Write(plaintext, plaintextOffset, plaintextLength); stream.Flush(); byte[] bufferContents = this.GetBufferContents(); RecordStream.CheckLength(bufferContents.Length, plaintextLength + 1024, 80); TlsCipher arg_CC_0 = this.mWriteCipher; long seqNo2; this.mWriteSeqNo = (seqNo2 = this.mWriteSeqNo) + 1L; array = arg_CC_0.EncodePlaintext(seqNo2, type, bufferContents, 0, bufferContents.Length); } RecordStream.CheckLength(array.Length, this.mCiphertextLimit, 80); byte[] array2 = new byte[array.Length + 5]; TlsUtilities.WriteUint8(type, array2, 0); TlsUtilities.WriteVersion(this.mWriteVersion, array2, 1); TlsUtilities.WriteUint16(array.Length, array2, 3); Array.Copy(array, 0, array2, 5, array.Length); this.mOutput.Write(array2, 0, array2.Length); this.mOutput.Flush(); }
internal void ClientCipherSpecDecided(TlsCompression tlsCompression, TlsCipher tlsCipher) { this.writeCompression = tlsCompression; this.writeCipher = tlsCipher; }
internal virtual void SetPendingConnectionState(TlsCompression tlsCompression, TlsCipher tlsCipher) { this.mPendingCompression = tlsCompression; this.mPendingCipher = tlsCipher; }
internal void ClientCipherSpecDecided(ITlsCompression tlsCompression, TlsCipher tlsCipher) { _writeCompression = tlsCompression; _writeCipher = tlsCipher; }
internal virtual void SetPendingConnectionState(TlsCompression tlsCompression, TlsCipher tlsCipher) { this.mPendingCompression = tlsCompression; this.mPendingCipher = tlsCipher; }
internal virtual void FinaliseHandshake() { if (mReadCompression != mPendingCompression || mWriteCompression != mPendingCompression || mReadCipher != mPendingCipher || mWriteCipher != mPendingCipher) { throw new TlsFatalAlert(AlertDescription.handshake_failure); } this.mPendingCompression = null; this.mPendingCipher = null; }
private async Task _ProcessHandshakeAsync(DTLSRecord record) { if (record == null) { throw new ArgumentNullException(nameof(record)); } var data = record.Fragment; if (this._EncyptedServerEpoch == record.Epoch) { var count = 0; while ((this._Cipher == null) && (count < 500)) { await Task.Delay(10).ConfigureAwait(false); count++; } if (this._Cipher == null) { throw new Exception("Need Cipher for Encrypted Session"); } var sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; data = this._Cipher.DecodeCiphertext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); } using (var tempStream = new MemoryStream(data)) { var handshakeRec = HandshakeRecord.Deserialise(tempStream); if (handshakeRec.Length > (handshakeRec.FragmentLength + handshakeRec.FragmentOffset)) { this._IsFragment = true; this._FragmentedRecordList.Add(data); return; } else if (this._IsFragment) { this._FragmentedRecordList.Add(data); data = new byte[0]; foreach (var rec in this._FragmentedRecordList) { data = data.Concat(rec.Skip(HandshakeRecord.RECORD_OVERHEAD)).ToArray(); } var tempHandshakeRec = new HandshakeRecord() { Length = handshakeRec.Length, MessageSeq = handshakeRec.MessageSeq, MessageType = handshakeRec.MessageType, FragmentLength = handshakeRec.Length, FragmentOffset = 0 }; var tempHandshakeBytes = new byte[HandshakeRecord.RECORD_OVERHEAD]; using (var updateStream = new MemoryStream(tempHandshakeBytes)) { tempHandshakeRec.Serialise(updateStream); } data = tempHandshakeBytes.Concat(data).ToArray(); } } using (var stream = new MemoryStream(data)) { var handshakeRecord = HandshakeRecord.Deserialise(stream); switch (handshakeRecord.MessageType) { case THandshakeType.HelloRequest: { break; } case THandshakeType.ClientHello: { break; } case THandshakeType.ServerHello: { var serverHello = ServerHello.Deserialise(stream); this._HandshakeInfo.UpdateHandshakeHash(data); this._ServerEpoch = record.Epoch; this._HandshakeInfo.CipherSuite = (TCipherSuite)serverHello.CipherSuite; this._HandshakeInfo.ServerRandom = serverHello.Random; this._Version = serverHello.ServerVersion <= this._Version ? serverHello.ServerVersion : _SupportedVersion; break; } case THandshakeType.HelloVerifyRequest: { var helloVerifyRequest = HelloVerifyRequest.Deserialise(stream); this._Version = helloVerifyRequest.ServerVersion; await this._SendHelloAsync(helloVerifyRequest.Cookie).ConfigureAwait(false); break; } case THandshakeType.Certificate: { var cert = Certificate.Deserialise(stream, TCertificateType.X509); this._HandshakeInfo.UpdateHandshakeHash(data); this.ServerCertificate = cert.Cert; break; } case THandshakeType.ServerKeyExchange: { this._HandshakeInfo.UpdateHandshakeHash(data); var keyExchangeAlgorithm = CipherSuites.GetKeyExchangeAlgorithm(this._HandshakeInfo.CipherSuite); byte[] preMasterSecret = null; IKeyExchange keyExchange = null; if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.ECDHE_ECDSA) { var serverKeyExchange = ECDHEServerKeyExchange.Deserialise(stream, this._Version); var keyExchangeECDHE = new ECDHEKeyExchange { CipherSuite = this._HandshakeInfo.CipherSuite, Curve = serverKeyExchange.EllipticCurve, KeyExchangeAlgorithm = keyExchangeAlgorithm, ClientRandom = this._HandshakeInfo.ClientRandom, ServerRandom = this._HandshakeInfo.ServerRandom }; keyExchangeECDHE.GenerateEphemeralKey(); var clientKeyExchange = new ECDHEClientKeyExchange(keyExchangeECDHE.PublicKey); this._ClientKeyExchange = clientKeyExchange; preMasterSecret = keyExchangeECDHE.GetPreMasterSecret(serverKeyExchange.PublicKeyBytes); keyExchange = keyExchangeECDHE; } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.ECDHE_PSK) { var serverKeyExchange = ECDHEPSKServerKeyExchange.Deserialise(stream); var keyExchangeECDHE = new ECDHEKeyExchange { CipherSuite = this._HandshakeInfo.CipherSuite, Curve = serverKeyExchange.EllipticCurve, KeyExchangeAlgorithm = keyExchangeAlgorithm, ClientRandom = this._HandshakeInfo.ClientRandom, ServerRandom = this._HandshakeInfo.ServerRandom }; keyExchangeECDHE.GenerateEphemeralKey(); var clientKeyExchange = new ECDHEPSKClientKeyExchange(keyExchangeECDHE.PublicKey); if (serverKeyExchange.PSKIdentityHint != null) { var key = this.PSKIdentities.GetKey(serverKeyExchange.PSKIdentityHint); if (key != null) { this._PSKIdentity = new PSKIdentity() { Identity = serverKeyExchange.PSKIdentityHint, Key = key }; } } if (this._PSKIdentity == null) { this._PSKIdentity = this.PSKIdentities.GetRandom(); } clientKeyExchange.PSKIdentity = this._PSKIdentity.Identity; this._ClientKeyExchange = clientKeyExchange; var otherSecret = keyExchangeECDHE.GetPreMasterSecret(serverKeyExchange.PublicKeyBytes); preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, this._PSKIdentity.Key); keyExchange = keyExchangeECDHE; } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.PSK) { var serverKeyExchange = PSKServerKeyExchange.Deserialise(stream); var clientKeyExchange = new PSKClientKeyExchange(); if (serverKeyExchange.PSKIdentityHint != null) { var key = this.PSKIdentities.GetKey(serverKeyExchange.PSKIdentityHint); if (key != null) { this._PSKIdentity = new PSKIdentity() { Identity = serverKeyExchange.PSKIdentityHint, Key = key }; } } if (this._PSKIdentity == null) { this._PSKIdentity = this.PSKIdentities.GetRandom(); } var otherSecret = new byte[this._PSKIdentity.Key.Length]; clientKeyExchange.PSKIdentity = this._PSKIdentity.Identity; this._ClientKeyExchange = clientKeyExchange; preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, this._PSKIdentity.Key); } this._Cipher = TLSUtils.AssignCipher(preMasterSecret, true, this._Version, this._HandshakeInfo); break; } case THandshakeType.CertificateRequest: { this._HandshakeInfo.UpdateHandshakeHash(data); this._SendCertificate = true; break; } case THandshakeType.ServerHelloDone: { this._HandshakeInfo.UpdateHandshakeHash(data); var keyExchangeAlgorithm = CipherSuites.GetKeyExchangeAlgorithm(this._HandshakeInfo.CipherSuite); if (this._Cipher == null) { if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.PSK) { var clientKeyExchange = new PSKClientKeyExchange(); this._PSKIdentity = this.PSKIdentities.GetRandom(); var otherSecret = new byte[this._PSKIdentity.Key.Length]; clientKeyExchange.PSKIdentity = this._PSKIdentity.Identity; this._ClientKeyExchange = clientKeyExchange; var preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, this._PSKIdentity.Key); this._Cipher = TLSUtils.AssignCipher(preMasterSecret, true, this._Version, this._HandshakeInfo); } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.RSA) { var clientKeyExchange = new RSAClientKeyExchange(); this._ClientKeyExchange = clientKeyExchange; var PreMasterSecret = TLSUtils.GetRsaPreMasterSecret(this._Version); clientKeyExchange.PremasterSecret = TLSUtils.GetEncryptedRsaPreMasterSecret(this.ServerCertificate, PreMasterSecret); this._Cipher = TLSUtils.AssignCipher(PreMasterSecret, true, this._Version, this._HandshakeInfo); } else { throw new NotImplementedException($"Key Exchange Algorithm {keyExchangeAlgorithm} Not Implemented"); } } if (this._SendCertificate) { await this._SendHandshakeMessageAsync(this._Certificate, false).ConfigureAwait(false); } await this._SendHandshakeMessageAsync(this._ClientKeyExchange, false).ConfigureAwait(false); if (this._SendCertificate) { var signatureHashAlgorithm = new SignatureHashAlgorithm() { Signature = TSignatureAlgorithm.ECDSA, Hash = THashAlgorithm.SHA256 }; if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.RSA) { signatureHashAlgorithm = new SignatureHashAlgorithm() { Signature = TSignatureAlgorithm.RSA, Hash = THashAlgorithm.SHA1 }; } var certVerify = new CertificateVerify { SignatureHashAlgorithm = signatureHashAlgorithm, Signature = TLSUtils.Sign(this._PrivateKey, this._PrivateKeyRsa, true, this._Version, this._HandshakeInfo, signatureHashAlgorithm, this._HandshakeInfo.GetHash(this._Version)) }; await this._SendHandshakeMessageAsync(certVerify, false).ConfigureAwait(false); } await this._SendChangeCipherSpecAsync().ConfigureAwait(false); var handshakeHash = this._HandshakeInfo.GetHash(this._Version); var finished = new Finished { VerifyData = TLSUtils.GetVerifyData(this._Version, this._HandshakeInfo, true, true, handshakeHash) }; await this._SendHandshakeMessageAsync(finished, true).ConfigureAwait(false); break; } case THandshakeType.NewSessionTicket: { this._HandshakeInfo.UpdateHandshakeHash(data); break; } case THandshakeType.CertificateVerify: { break; } case THandshakeType.ClientKeyExchange: { break; } case THandshakeType.Finished: { var serverFinished = Finished.Deserialise(stream); var handshakeHash = this._HandshakeInfo.GetHash(this._Version); var calculatedVerifyData = TLSUtils.GetVerifyData(this._Version, this._HandshakeInfo, true, false, handshakeHash); if (serverFinished.VerifyData.SequenceEqual(calculatedVerifyData)) { this._ConnectionComplete = true; } break; } default: { break; } } } this._IsFragment = false; this._FragmentedRecordList.RemoveAll(x => true); }
internal void ServerClientSpecReceived() { this.readCompression = this.writeCompression; this.readCipher = this.writeCipher; }
internal void ClientCipherSpecDecided(TlsCompression tlsCompression, TlsCipher tlsCipher) { this.writeCompression = tlsCompression; this.writeCipher = tlsCipher; }
internal void ServerClientSpecReceived() { _readCompression = _writeCompression; _readCipher = _writeCipher; }
internal void ClientCipherSpecDecided(ITlsCompression tlsCompression, TlsCipher tlsCipher) { _writeCompression = tlsCompression; _writeCipher = tlsCipher; }
internal void ServerClientSpecReceived() { _readCompression = _writeCompression; _readCipher = _writeCipher; }
internal void ClientCipherSpecDecided(TlsCipher tlsCipher) { this.writeCipher = tlsCipher; }
private void ProcessHandshake(DTLSRecord record) { byte[] data; if (_EncyptedServerEpoch.HasValue && (_EncyptedServerEpoch.Value == record.Epoch)) { int count = 0; while ((_Cipher == null) && (count < 500)) { System.Threading.Thread.Sleep(10); count++; } if (_Cipher == null) throw new Exception(); if (_Cipher != null) { long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; data = _Cipher.DecodeCiphertext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); } else data = record.Fragment; } else data = record.Fragment; using (MemoryStream stream = new MemoryStream(data)) { HandshakeRecord handshakeRecord = HandshakeRecord.Deserialise(stream); if (handshakeRecord != null) { #if DEBUG Console.WriteLine(handshakeRecord.MessageType.ToString()); #endif switch (handshakeRecord.MessageType) { case THandshakeType.HelloRequest: break; case THandshakeType.ClientHello: break; case THandshakeType.ServerHello: ServerHello serverHello = ServerHello.Deserialise(stream); if (serverHello != null) { _ServerEpoch = record.Epoch; _HandshakeInfo.UpdateHandshakeHash(data); _HandshakeInfo.CipherSuite = (TCipherSuite)serverHello.CipherSuite; _HandshakeInfo.ServerRandom = serverHello.Random; Version version = SupportedVersion; if (serverHello.ServerVersion < version) version = serverHello.ServerVersion; _Version = version; } break; case THandshakeType.HelloVerifyRequest: HelloVerifyRequest helloVerifyRequest = HelloVerifyRequest.Deserialise(stream); if (helloVerifyRequest != null) { _Version = helloVerifyRequest.ServerVersion; SendHello(helloVerifyRequest.Cookie); } break; case THandshakeType.Certificate: _HandshakeInfo.UpdateHandshakeHash(data); break; case THandshakeType.ServerKeyExchange: _HandshakeInfo.UpdateHandshakeHash(data); TKeyExchangeAlgorithm keyExchangeAlgorithm = CipherSuites.GetKeyExchangeAlgorithm(_HandshakeInfo.CipherSuite); byte[] preMasterSecret = null; IKeyExchange keyExchange = null; if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.ECDHE_ECDSA) { ECDHEServerKeyExchange serverKeyExchange = ECDHEServerKeyExchange.Deserialise(stream, _Version); ECDHEKeyExchange keyExchangeECDHE = new ECDHEKeyExchange(); keyExchangeECDHE.CipherSuite = _HandshakeInfo.CipherSuite; keyExchangeECDHE.Curve = serverKeyExchange.EllipticCurve; keyExchangeECDHE.KeyExchangeAlgorithm = keyExchangeAlgorithm; keyExchangeECDHE.ClientRandom = _HandshakeInfo.ClientRandom; keyExchangeECDHE.ServerRandom = _HandshakeInfo.ServerRandom; keyExchangeECDHE.GenerateEphemeralKey(); ECDHEClientKeyExchange clientKeyExchange = new ECDHEClientKeyExchange(keyExchangeECDHE.PublicKey); _ClientKeyExchange = clientKeyExchange; preMasterSecret = keyExchangeECDHE.GetPreMasterSecret(serverKeyExchange.PublicKeyBytes); keyExchange = keyExchangeECDHE; } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.ECDHE_PSK) { ECDHEPSKServerKeyExchange serverKeyExchange = ECDHEPSKServerKeyExchange.Deserialise(stream, _Version); ECDHEKeyExchange keyExchangeECDHE = new ECDHEKeyExchange(); keyExchangeECDHE.CipherSuite = _HandshakeInfo.CipherSuite; keyExchangeECDHE.Curve = serverKeyExchange.EllipticCurve; keyExchangeECDHE.KeyExchangeAlgorithm = keyExchangeAlgorithm; keyExchangeECDHE.ClientRandom = _HandshakeInfo.ClientRandom; keyExchangeECDHE.ServerRandom = _HandshakeInfo.ServerRandom; keyExchangeECDHE.GenerateEphemeralKey(); ECDHEPSKClientKeyExchange clientKeyExchange = new ECDHEPSKClientKeyExchange(keyExchangeECDHE.PublicKey); if (serverKeyExchange.PSKIdentityHint != null) { byte[] key = _PSKIdentities.GetKey(serverKeyExchange.PSKIdentityHint); if (key != null) _PSKIdentity = new PSKIdentity() { Identity = serverKeyExchange.PSKIdentityHint, Key = key }; } if (_PSKIdentity == null) _PSKIdentity = _PSKIdentities.GetRandom(); clientKeyExchange.PSKIdentity = _PSKIdentity.Identity; _ClientKeyExchange = clientKeyExchange; byte[] otherSecret = keyExchangeECDHE.GetPreMasterSecret(serverKeyExchange.PublicKeyBytes); preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, _PSKIdentity.Key); keyExchange = keyExchangeECDHE; } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.PSK) { PSKServerKeyExchange serverKeyExchange = PSKServerKeyExchange.Deserialise(stream, _Version); PSKClientKeyExchange clientKeyExchange = new PSKClientKeyExchange(); if (serverKeyExchange.PSKIdentityHint != null) { byte[] key = _PSKIdentities.GetKey(serverKeyExchange.PSKIdentityHint); if (key != null) _PSKIdentity = new PSKIdentity() { Identity = serverKeyExchange.PSKIdentityHint, Key = key }; } if (_PSKIdentity == null) _PSKIdentity = _PSKIdentities.GetRandom(); byte[] otherSecret = new byte[_PSKIdentity.Key.Length]; clientKeyExchange.PSKIdentity = _PSKIdentity.Identity; _ClientKeyExchange = clientKeyExchange; preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, _PSKIdentity.Key); } _Cipher = TLSUtils.AssignCipher(preMasterSecret, true, _Version, _HandshakeInfo); break; case THandshakeType.CertificateRequest: _HandshakeInfo.UpdateHandshakeHash(data); _SendCertificate = true; break; case THandshakeType.ServerHelloDone: _HandshakeInfo.UpdateHandshakeHash(data); if (_Cipher == null) { keyExchangeAlgorithm = CipherSuites.GetKeyExchangeAlgorithm(_HandshakeInfo.CipherSuite); if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.PSK) { PSKClientKeyExchange clientKeyExchange = new PSKClientKeyExchange(); _PSKIdentity = _PSKIdentities.GetRandom(); byte[] otherSecret = new byte[_PSKIdentity.Key.Length]; clientKeyExchange.PSKIdentity = _PSKIdentity.Identity; _ClientKeyExchange = clientKeyExchange; preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, _PSKIdentity.Key); _Cipher = TLSUtils.AssignCipher(preMasterSecret, true, _Version, _HandshakeInfo); } } if (_SendCertificate) { SendHandshakeMessage(_Certificate, false); } SendHandshakeMessage(_ClientKeyExchange, false); if (_SendCertificate) { CertificateVerify certificateVerify = new CertificateVerify(); byte[] signatureHash = _HandshakeInfo.GetHash(); certificateVerify.SignatureHashAlgorithm = new SignatureHashAlgorithm() { Signature = TSignatureAlgorithm.ECDSA, Hash = THashAlgorithm.SHA256 }; certificateVerify.Signature = TLSUtils.Sign(_PrivateKey, true, _Version, _HandshakeInfo, certificateVerify.SignatureHashAlgorithm, signatureHash); SendHandshakeMessage(certificateVerify, false); } SendChangeCipherSpec(); byte[] handshakeHash = _HandshakeInfo.GetHash(); Finished finished = new Finished(); finished.VerifyData = TLSUtils.GetVerifyData(_Version,_HandshakeInfo,true, true, handshakeHash); SendHandshakeMessage(finished, true); #if DEBUG Console.Write("Handshake Hash:"); TLSUtils.WriteToConsole(handshakeHash); Console.Write("Sent Verify:"); TLSUtils.WriteToConsole(finished.VerifyData); #endif break; case THandshakeType.CertificateVerify: break; case THandshakeType.ClientKeyExchange: break; case THandshakeType.Finished: Finished serverFinished = Finished.Deserialise(stream); handshakeHash = _HandshakeInfo.GetHash(); byte[] calculatedVerifyData = TLSUtils.GetVerifyData(_Version,_HandshakeInfo, true, false, handshakeHash); #if DEBUG Console.Write("Recieved Verify:"); TLSUtils.WriteToConsole(serverFinished.VerifyData); Console.Write("Calc Verify:"); TLSUtils.WriteToConsole(calculatedVerifyData); #endif if (TLSUtils.ByteArrayCompare(serverFinished.VerifyData, calculatedVerifyData)) { #if DEBUG Console.WriteLine("Handshake Complete"); #endif _Connected.Set(); } break; default: break; } } } }
internal void ServerClientSpecReceived() { this.readCompression = this.writeCompression; this.readCipher = this.writeCipher; }
private void ProcessHandshake(DTLSRecord record) { byte[] data; if (_EncyptedServerEpoch.HasValue && (_EncyptedServerEpoch.Value == record.Epoch)) { int count = 0; while ((_Cipher == null) && (count < 500)) { System.Threading.Thread.Sleep(10); count++; } if (_Cipher == null) { throw new Exception(); } if (_Cipher != null) { long sequenceNumber = ((long)record.Epoch << 48) + record.SequenceNumber; data = _Cipher.DecodeCiphertext(sequenceNumber, (byte)TRecordType.Handshake, record.Fragment, 0, record.Fragment.Length); } else { data = record.Fragment; } } else { data = record.Fragment; } using (MemoryStream stream = new MemoryStream(data)) { HandshakeRecord handshakeRecord = HandshakeRecord.Deserialise(stream); if (handshakeRecord != null) { #if DEBUG Console.WriteLine(handshakeRecord.MessageType.ToString()); #endif switch (handshakeRecord.MessageType) { case THandshakeType.HelloRequest: break; case THandshakeType.ClientHello: break; case THandshakeType.ServerHello: ServerHello serverHello = ServerHello.Deserialise(stream); if (serverHello != null) { _ServerEpoch = record.Epoch; _HandshakeInfo.UpdateHandshakeHash(data); _HandshakeInfo.CipherSuite = (TCipherSuite)serverHello.CipherSuite; _HandshakeInfo.ServerRandom = serverHello.Random; Version version = SupportedVersion; if (serverHello.ServerVersion < version) { version = serverHello.ServerVersion; } _Version = version; } break; case THandshakeType.HelloVerifyRequest: HelloVerifyRequest helloVerifyRequest = HelloVerifyRequest.Deserialise(stream); if (helloVerifyRequest != null) { _Version = helloVerifyRequest.ServerVersion; SendHello(helloVerifyRequest.Cookie); } break; case THandshakeType.Certificate: _HandshakeInfo.UpdateHandshakeHash(data); break; case THandshakeType.ServerKeyExchange: _HandshakeInfo.UpdateHandshakeHash(data); TKeyExchangeAlgorithm keyExchangeAlgorithm = CipherSuites.GetKeyExchangeAlgorithm(_HandshakeInfo.CipherSuite); byte[] preMasterSecret = null; IKeyExchange keyExchange = null; if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.ECDHE_ECDSA) { ECDHEServerKeyExchange serverKeyExchange = ECDHEServerKeyExchange.Deserialise(stream, _Version); ECDHEKeyExchange keyExchangeECDHE = new ECDHEKeyExchange { CipherSuite = _HandshakeInfo.CipherSuite, Curve = serverKeyExchange.EllipticCurve, KeyExchangeAlgorithm = keyExchangeAlgorithm, ClientRandom = _HandshakeInfo.ClientRandom, ServerRandom = _HandshakeInfo.ServerRandom }; keyExchangeECDHE.GenerateEphemeralKey(); ECDHEClientKeyExchange clientKeyExchange = new ECDHEClientKeyExchange(keyExchangeECDHE.PublicKey); _ClientKeyExchange = clientKeyExchange; preMasterSecret = keyExchangeECDHE.GetPreMasterSecret(serverKeyExchange.PublicKeyBytes); keyExchange = keyExchangeECDHE; } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.ECDHE_PSK) { ECDHEPSKServerKeyExchange serverKeyExchange = ECDHEPSKServerKeyExchange.Deserialise(stream, _Version); ECDHEKeyExchange keyExchangeECDHE = new ECDHEKeyExchange { CipherSuite = _HandshakeInfo.CipherSuite, Curve = serverKeyExchange.EllipticCurve, KeyExchangeAlgorithm = keyExchangeAlgorithm, ClientRandom = _HandshakeInfo.ClientRandom, ServerRandom = _HandshakeInfo.ServerRandom }; keyExchangeECDHE.GenerateEphemeralKey(); ECDHEPSKClientKeyExchange clientKeyExchange = new ECDHEPSKClientKeyExchange(keyExchangeECDHE.PublicKey); if (serverKeyExchange.PSKIdentityHint != null) { byte[] key = _PSKIdentities.GetKey(serverKeyExchange.PSKIdentityHint); if (key != null) { _PSKIdentity = new PSKIdentity() { Identity = serverKeyExchange.PSKIdentityHint, Key = key } } ; } if (_PSKIdentity == null) { _PSKIdentity = _PSKIdentities.GetRandom(); } clientKeyExchange.PSKIdentity = _PSKIdentity.Identity; _ClientKeyExchange = clientKeyExchange; byte[] otherSecret = keyExchangeECDHE.GetPreMasterSecret(serverKeyExchange.PublicKeyBytes); preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, _PSKIdentity.Key); keyExchange = keyExchangeECDHE; } else if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.PSK) { PSKServerKeyExchange serverKeyExchange = PSKServerKeyExchange.Deserialise(stream, _Version); PSKClientKeyExchange clientKeyExchange = new PSKClientKeyExchange(); if (serverKeyExchange.PSKIdentityHint != null) { byte[] key = _PSKIdentities.GetKey(serverKeyExchange.PSKIdentityHint); if (key != null) { _PSKIdentity = new PSKIdentity() { Identity = serverKeyExchange.PSKIdentityHint, Key = key } } ; } if (_PSKIdentity == null) { _PSKIdentity = _PSKIdentities.GetRandom(); } byte[] otherSecret = new byte[_PSKIdentity.Key.Length]; clientKeyExchange.PSKIdentity = _PSKIdentity.Identity; _ClientKeyExchange = clientKeyExchange; preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, _PSKIdentity.Key); } _Cipher = TLSUtils.AssignCipher(preMasterSecret, true, _Version, _HandshakeInfo); break; case THandshakeType.CertificateRequest: _HandshakeInfo.UpdateHandshakeHash(data); _SendCertificate = true; break; case THandshakeType.ServerHelloDone: _HandshakeInfo.UpdateHandshakeHash(data); if (_Cipher == null) { keyExchangeAlgorithm = CipherSuites.GetKeyExchangeAlgorithm(_HandshakeInfo.CipherSuite); if (keyExchangeAlgorithm == TKeyExchangeAlgorithm.PSK) { PSKClientKeyExchange clientKeyExchange = new PSKClientKeyExchange(); _PSKIdentity = _PSKIdentities.GetRandom(); byte[] otherSecret = new byte[_PSKIdentity.Key.Length]; clientKeyExchange.PSKIdentity = _PSKIdentity.Identity; _ClientKeyExchange = clientKeyExchange; preMasterSecret = TLSUtils.GetPSKPreMasterSecret(otherSecret, _PSKIdentity.Key); _Cipher = TLSUtils.AssignCipher(preMasterSecret, true, _Version, _HandshakeInfo); } } if (_SendCertificate) { SendHandshakeMessage(_Certificate, false); } SendHandshakeMessage(_ClientKeyExchange, false); if (_SendCertificate) { CertificateVerify certificateVerify = new CertificateVerify(); byte[] signatureHash = _HandshakeInfo.GetHash(); certificateVerify.SignatureHashAlgorithm = new SignatureHashAlgorithm() { Signature = TSignatureAlgorithm.ECDSA, Hash = THashAlgorithm.SHA256 }; certificateVerify.Signature = TLSUtils.Sign(_PrivateKey, true, _Version, _HandshakeInfo, certificateVerify.SignatureHashAlgorithm, signatureHash); SendHandshakeMessage(certificateVerify, false); } SendChangeCipherSpec(); byte[] handshakeHash = _HandshakeInfo.GetHash(); Finished finished = new Finished { VerifyData = TLSUtils.GetVerifyData(_Version, _HandshakeInfo, true, true, handshakeHash) }; SendHandshakeMessage(finished, true); #if DEBUG Console.Write($"Handshake Hash: {TLSUtils.WriteToString(handshakeHash)}"); Console.Write($"Sent Verify: {TLSUtils.WriteToString(finished.VerifyData)}"); #endif break; case THandshakeType.CertificateVerify: break; case THandshakeType.ClientKeyExchange: break; case THandshakeType.Finished: Finished serverFinished = Finished.Deserialise(stream); handshakeHash = _HandshakeInfo.GetHash(); byte[] calculatedVerifyData = TLSUtils.GetVerifyData(_Version, _HandshakeInfo, true, false, handshakeHash); #if DEBUG Console.Write("$Recieved Verify: {TLSUtils.WriteToString(serverFinished.VerifyData)}"); Console.Write($"Calc Verify: {TLSUtils.WriteToString(calculatedVerifyData)}"); #endif if (TLSUtils.ByteArrayCompare(serverFinished.VerifyData, calculatedVerifyData)) { #if DEBUG Console.WriteLine("Handshake Complete"); #endif _Connected.Set(); } break; default: break; } } } }
internal void ClientCipherSpecDecided(TlsCipher tlsCipher) { this.writeCipher = tlsCipher; }