예제 #1
0
 private void ProcessServerCertificate(IByteBuffer data)
 {
     serverCertificate = DtlsHelper.ParseCertificate(data);
     clientState.KeyExchange.ProcessServerCertificate(serverCertificate);
     clientState.Authentication = clientState.Client.GetAuthentication();
     clientState.Authentication.NotifyServerCertificate(serverCertificate);
 }
예제 #2
0
        public AsyncDtlsClientProtocol(AsyncDtlsClient client, SecureRandom secureRandom, IChannel channel, HandshakeHandler parentHandler, DtlsStateHandler handler, Boolean useExtendedMasterSecret, ProtocolVersion initialVersion)
        {
            this.parentHandler = parentHandler;
            this.handler       = handler;

            this.channel         = channel;
            this.protocolVersion = initialVersion;

            AsyncDtlsSecurityParameters securityParameters = new AsyncDtlsSecurityParameters();

            securityParameters.SetEntity(ConnectionEnd.client);

            clientState               = new AsyncDtlsClientState();
            clientState.Client        = client;
            clientState.ClientContext = new AsyncDtlsClientContext(secureRandom, securityParameters);

            securityParameters.SetExtendedMasterSecret(useExtendedMasterSecret);
            securityParameters.SetClientRandom(DtlsHelper.CreateRandomBlock(client.ShouldUseGmtUnixTime(), clientState.ClientContext.NonceRandomGenerator));
            client.InitClient(clientState.ClientContext);

            clientState.HandshakeHash = new DeferredHash();
            clientState.HandshakeHash.Init(clientState.ClientContext);

            recordLayer = new AsyncDtlsRecordLayer(clientState.HandshakeHash, this, channel, clientState.ClientContext, client);
        }
예제 #3
0
        public void Send(short sequence, MessageType messageType, IByteBuffer buffer)
        {
            if (closed)
            {
                return;
            }

            if (messageType == MessageType.FINISHED)
            {
                AsyncDtlsEpoch nextEpoch = null;
                if (this.inHandshake)
                {
                    nextEpoch = pendingEpoch;
                }

                if (nextEpoch == null)
                {
                    throw new InvalidOperationException();
                }

                IByteBuffer cipherSpecBuf = Unpooled.Buffer(1);
                cipherSpecBuf.WriteByte(1);
                SendRecord(ContentType.change_cipher_spec, cipherSpecBuf);

                writeEpoch = nextEpoch;
            }

            IByteBuffer copy = buffer.Copy();

            byte[] realArray = new byte[copy.ReadableBytes];
            copy.ReadBytes(realArray);

            if (buffer.ReadableBytes <= GetSendLimit())
            {
                SendRecord(ContentType.handshake, buffer);
            }
            else
            {
                int fragmentOffset = 0;
                int totalLength    = buffer.ReadableBytes - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH;

                IByteBuffer header = buffer.ReadBytes(DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH);
                header.Release();

                do
                {
                    int         fragmentLength = Math.Min(buffer.ReadableBytes + DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH, GetSendLimit());
                    IByteBuffer current        = Unpooled.Buffer(fragmentLength);
                    DtlsHelper.WriteHandshakeHeader(fragmentOffset, fragmentLength - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH, sequence, messageType, current, totalLength);
                    buffer.ReadBytes(current, fragmentLength - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH);

                    SendRecord(ContentType.handshake, current);
                    fragmentOffset += fragmentLength - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH;
                }while (buffer.ReadableBytes > 0);
            }

            handshakeHash.BlockUpdate(realArray, 0, DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH);
            handshakeHash.BlockUpdate(realArray, DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH, realArray.Length - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH);
        }
 protected void CheckTrackingHash(Int16 hashAlgorithm)
 {
     if (!hashes.ContainsKey(hashAlgorithm))
     {
         IDigest hash = DtlsHelper.CreateHash(hashAlgorithm);
         hashes[hashAlgorithm] = hash;
     }
 }
예제 #5
0
        private void ProcessCertificateStatus(IByteBuffer data)
        {
            if (!clientState.AllowCertificateStatus)
            {
                throw new TlsFatalAlert(AlertDescription.unexpected_message);
            }

            clientState.CertificateStatus = DtlsHelper.ParseCertificateStatus(data);
        }
        public IDigest ForkPrfHash()
        {
            CheckStopBuffering();

            if (buf != null)
            {
                IDigest prfHash = DtlsHelper.CreateHash((short)prfHashAlgorithm);
                buf.UpdateDigest(prfHash);
                return(prfHash);
            }

            return(DtlsHelper.CloneHash((short)prfHashAlgorithm, (IDigest)hashes[prfHashAlgorithm.Value]));
        }
        public TlsHandshakeHash StopTracking()
        {
            IDigest prfHash = DtlsHelper.CloneHash(prfHashAlgorithm.Value, (IDigest)hashes[prfHashAlgorithm.Value]);

            if (buf != null)
            {
                buf.UpdateDigest(prfHash);
            }

            DeferredHash result = new DeferredHash(prfHashAlgorithm.Value, prfHash);

            result.Init(context);
            return(result);
        }
예제 #8
0
        private void ProcessFinished(IByteBuffer body)
        {
            byte[] expectedClientVerifyData = DtlsHelper.CalculateVerifyData(clientState.ClientContext, ExporterLabel.server_finished, DtlsHelper.GetCurrentPRFHash(clientState.ClientContext, clientState.HandshakeHash, null));
            if (body.ReadableBytes != expectedClientVerifyData.Length)
            {
                throw new TlsFatalAlert(AlertDescription.handshake_failure);
            }

            byte[] serverVerifyData = new byte[body.ReadableBytes];
            body.ReadBytes(serverVerifyData);

            if (!ArrayUtils.Equals(serverVerifyData, expectedClientVerifyData))
            {
                throw new TlsFatalAlert(AlertDescription.handshake_failure);
            }
        }
        public static AsyncCertificateRequest Parse(ProtocolVersion version, IByteBuffer data)
        {
            int numTypes = data.ReadByte() & 0x0FF;

            byte[] certificateTypes = new byte[numTypes];
            for (int i = 0; i < numTypes; ++i)
            {
                certificateTypes[i] = data.ReadByte();
            }

            IList supportedSignatureAlgorithms = null;

            if (ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(version.GetEquivalentTLSVersion()))
            {
                supportedSignatureAlgorithms = DtlsHelper.ParseSupportedSignatureAlgorithms(false, data);
            }

            IList certificateAuthorities = new List <X509Name>();
            int   remainingBytes         = data.ReadUnsignedShort();

            while (remainingBytes > 0)
            {
                byte[] derEncoding = new byte[data.ReadUnsignedShort()];
                data.ReadBytes(derEncoding);
                Asn1InputStream asn1   = new Asn1InputStream(derEncoding);
                Asn1Object      result = asn1.ReadObject();
                asn1.Close();

                if (null == result)
                {
                    throw new TlsFatalAlert(AlertDescription.decode_error);
                }

                if (null != asn1.ReadObject())
                {
                    throw new TlsFatalAlert(AlertDescription.decode_error);
                }

                certificateAuthorities.Add(X509Name.GetInstance(result));
                remainingBytes -= 2 + derEncoding.Length;
            }

            return(new AsyncCertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities));
        }
        public byte[] GetFinalHash(byte hashAlgorithm)
        {
            IDigest d = (IDigest)hashes[hashAlgorithm];

            if (d == null)
            {
                throw new InvalidOperationException("HashAlgorithm." + HashAlgorithm.GetText(hashAlgorithm) + " is not being tracked");
            }

            d = DtlsHelper.CloneHash(hashAlgorithm, d);
            if (buf != null)
            {
                buf.UpdateDigest(d);
            }

            byte[] bs = new byte[d.GetDigestSize()];
            d.DoFinal(bs, 0);
            return(bs);
        }
예제 #11
0
        public void PostProcessFinished()
        {
            if (handshakeState == State.SERVER_HELLO_RECEIVED)
            {
                byte[]      clientVerifyData   = DtlsHelper.CalculateVerifyData(clientState.ClientContext, ExporterLabel.client_finished, DtlsHelper.GetCurrentPRFHash(clientState.ClientContext, clientState.HandshakeHash, null));
                IByteBuffer serverVerifyBuffer = Unpooled.Buffer(DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH + clientVerifyData.Length);
                short       currSequence       = sequence++;
                DtlsHelper.WriteHandshakeHeader(currSequence, MessageType.FINISHED, serverVerifyBuffer, clientVerifyData.Length);
                serverVerifyBuffer.WriteBytes(clientVerifyData);
                recordLayer.Send(currSequence, MessageType.FINISHED, serverVerifyBuffer);
            }

            recordLayer.HandshakeSuccessful();

            if (handshakeState == State.SERVER_HELLO_RECEIVED)
            {
                clientState.ClientContext.ResumableSession = clientState.TlsSession;
            }
            else
            {
                if (clientState.TlsSession != null)
                {
                    AsyncDtlsSecurityParameters parameters = (AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters;
                    clientState.SessionParameters = new SessionParameters.Builder()
                                                    .SetCipherSuite(parameters.CipherSuite)
                                                    .SetCompressionAlgorithm(parameters.CompressionAlgorithm)
                                                    .SetMasterSecret(parameters.MasterSecret)
                                                    .SetPeerCertificate(serverCertificate)
                                                    .SetPskIdentity(parameters.PskIdentity)
                                                    .SetSrpIdentity(parameters.SrpIdentity)
                                                    .SetServerExtensions(clientState.ServerExtensions)
                                                    .Build();

                    clientState.TlsSession = new AsyncDtlsSessionImpl(clientState.TlsSession.SessionID, clientState.SessionParameters);
                    clientState.ClientContext.ResumableSession = clientState.TlsSession;
                }
            }

            clientState.Client.NotifyHandshakeComplete();
        }
예제 #12
0
        private void SendRecord(byte contentType, IByteBuffer buf)
        {
            if (writeVersion == null)
            {
                return;
            }

            int length = buf.ReadableBytes;

            if (length > this.plaintextLimit)
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }

            if (length < 1 && contentType != ContentType.application_data)
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }

            int  recordEpoch          = writeEpoch.Epoch;
            long recordSequenceNumber = writeEpoch.allocateSequenceNumber();

            byte[] plainData = new byte[length];
            buf.ReadBytes(plainData);
            byte[]      ciphertext = writeEpoch.getCipher().EncodePlaintext(GetMacSequenceNumber(recordEpoch, recordSequenceNumber), contentType, plainData, 0, length);
            IByteBuffer buffer     = Unpooled.Buffer(RECORD_HEADER_LENGTH + ciphertext.Length);

            buffer.WriteByte(contentType);
            buffer.WriteByte(writeVersion.MajorVersion);
            buffer.WriteByte(writeVersion.MinorVersion);
            buffer.WriteShort(recordEpoch);
            DtlsHelper.WriteUint48(recordSequenceNumber, buffer);

            buffer.WriteShort(ciphertext.Length);
            buffer.WriteBytes(ciphertext);
            channel.WriteAndFlushAsync(new DatagramPacket(buffer, channel.RemoteAddress));
        }
예제 #13
0
        public void PostProcessServerHelloDone()
        {
            IList <SupplementalDataEntry> clientSupplementalData = (IList <SupplementalDataEntry>)clientState.Client.GetClientSupplementalData();

            if (clientSupplementalData != null)
            {
                int         totalLength            = 3 + DtlsHelper.CalculateSupplementalDataLength(clientSupplementalData);
                IByteBuffer supplementalDataOutput = Unpooled.Buffer(DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH + totalLength);
                short       sdataSequence          = sequence++;
                DtlsHelper.WriteHandshakeHeader(sdataSequence, MessageType.SUPPLEMENTAL_DATA, supplementalDataOutput, totalLength);
                DtlsHelper.WriteSupplementalData(supplementalDataOutput, clientSupplementalData);
                recordLayer.Send(sdataSequence, MessageType.SUPPLEMENTAL_DATA, supplementalDataOutput);
            }

            if (clientState.CertificateRequest != null)
            {
                clientState.ClientCredentials = clientState.Authentication.GetClientCredentials(clientState.CertificateRequest);
                Certificate clientCertificate = null;
                if (clientState.ClientCredentials != null)
                {
                    clientCertificate = clientState.ClientCredentials.Certificate;
                }

                if (clientCertificate == null)
                {
                    clientCertificate = Certificate.EmptyChain;
                }

                short       certificateSequence = sequence++;
                IByteBuffer certificateOutput   = DtlsHelper.WriteCertificate(certificateSequence, clientCertificate);
                recordLayer.Send(certificateSequence, MessageType.CERTIFICATE, certificateOutput);
            }

            if (clientState.ClientCredentials != null)
            {
                clientState.KeyExchange.ProcessClientCredentials(clientState.ClientCredentials);
            }
            else
            {
                clientState.KeyExchange.SkipClientCredentials();
            }

            MemoryStream buf = new MemoryStream();

            clientState.KeyExchange.GenerateClientKeyExchange(buf);
            byte[] clientKeyExchange = buf.GetBuffer();
            Array.Resize(ref clientKeyExchange, clientKeyExchange[0] + 1);

            IByteBuffer keyExchangeOutput = Unpooled.Buffer(DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH + clientKeyExchange.Length);
            short       currSequence      = sequence++;

            DtlsHelper.WriteHandshakeHeader(currSequence, MessageType.CLIENT_KEY_EXCHANGE, keyExchangeOutput, clientKeyExchange.Length);
            keyExchangeOutput.WriteBytes(clientKeyExchange);
            recordLayer.Send(currSequence, MessageType.CLIENT_KEY_EXCHANGE, keyExchangeOutput);

            TlsHandshakeHash prepareFinishHash = clientState.HandshakeHash;

            //clientState.setHandshakeHash(clientState.getHandshakeHash().stopTracking());

            ((AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters).SetSessionHash(DtlsHelper.GetCurrentPRFHash(clientState.ClientContext, prepareFinishHash, null));

            DtlsHelper.EstablishMasterSecret((AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters, clientState.ClientContext, clientState.KeyExchange);
            recordLayer.InitPendingEpoch(clientState.Client.GetCipher());

            if (clientState.ClientCredentials != null && clientState.ClientCredentials is TlsSignerCredentials)
            {
                TlsSignerCredentials signerCredentials = (TlsSignerCredentials)clientState.ClientCredentials;

                SignatureAndHashAlgorithm signatureAndHashAlgorithm = DtlsHelper.GetSignatureAndHashAlgorithm(clientState.ClientContext, signerCredentials);

                byte[] hash;
                if (signatureAndHashAlgorithm == null)
                {
                    hash = ((AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters).SessionHash;
                }
                else
                {
                    hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash);
                }

                byte[] signature = signerCredentials.GenerateCertificateSignature(hash);
                int    addon     = 0;
                if (signatureAndHashAlgorithm != null)
                {
                    addon = 2;
                }

                IByteBuffer certificateVerifyBody = Unpooled.Buffer(DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH + addon + 2 + signature.Length);
                currSequence = sequence++;
                DtlsHelper.WriteHandshakeHeader(currSequence, MessageType.CERTIFICATE_VERIFY, certificateVerifyBody, addon + 2 + signature.Length);
                if (signatureAndHashAlgorithm != null)
                {
                    certificateVerifyBody.WriteByte(signatureAndHashAlgorithm.Hash);
                    certificateVerifyBody.WriteByte(signatureAndHashAlgorithm.Signature);
                }

                certificateVerifyBody.WriteShort(signature.Length);
                certificateVerifyBody.WriteBytes(signature);
                recordLayer.Send(currSequence, MessageType.CERTIFICATE_VERIFY, certificateVerifyBody);
            }

            byte[] clientVerifyData = DtlsHelper.CalculateVerifyData(clientState.ClientContext, ExporterLabel.client_finished, DtlsHelper.GetCurrentPRFHash(clientState.ClientContext, clientState.HandshakeHash, null));

            IByteBuffer serverVerifyBuffer = Unpooled.Buffer(DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH + clientVerifyData.Length);

            currSequence = sequence++;
            DtlsHelper.WriteHandshakeHeader(currSequence, MessageType.FINISHED, serverVerifyBuffer, clientVerifyData.Length);
            serverVerifyBuffer.WriteBytes(clientVerifyData);
            recordLayer.Send(currSequence, MessageType.FINISHED, serverVerifyBuffer);

            clientVerifyData = DtlsHelper.CalculateVerifyData(clientState.ClientContext, ExporterLabel.client_finished, DtlsHelper.GetCurrentPRFHash(clientState.ClientContext, clientState.HandshakeHash, null));
        }
        public IByteBuffer Encode(short sequence)
        {
            int length = DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH;

            if (CertificateTypes == null || CertificateTypes.Length == 0)
            {
                length++;
            }
            else
            {
                length += 1 + CertificateTypes.Length;
            }

            if (SupportedSignatureAlgorithms != null)
            {
                for (int i = 0; i < SupportedSignatureAlgorithms.Count; ++i)
                {
                    SignatureAndHashAlgorithm entry = (SignatureAndHashAlgorithm)SupportedSignatureAlgorithms[i];
                    if (entry.Signature == SignatureAlgorithm.anonymous)
                    {
                        throw new ArgumentException("SignatureAlgorithm.anonymous MUST NOT appear in the signature_algorithms extension");
                    }
                }

                length += 2 * SupportedSignatureAlgorithms.Count + 2;
            }

            IList <byte[]> derEncodings = new List <byte[]>(CertificateAuthorities.Count);
            int            totalLength  = 0;

            if (CertificateAuthorities == null || CertificateAuthorities.Count == 0)
            {
                length += 2;
            }
            else
            {
                length += 2;
                for (int i = 0; i < CertificateAuthorities.Count; ++i)
                {
                    X509Name certificateAuthority = (X509Name)CertificateAuthorities[i];
                    byte[]   derEncoding          = certificateAuthority.GetEncoded(Asn1Encodable.Der);
                    derEncodings.Add(derEncoding);
                    length      += derEncoding.Length + 2;
                    totalLength += derEncoding.Length + 2;
                }
            }

            IByteBuffer buffer = Unpooled.Buffer(length);

            DtlsHelper.WriteHandshakeHeader(sequence, MessageType.CERTIFICATE_REQUEST, buffer, length - DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH);

            if (CertificateTypes == null || CertificateTypes.Length == 0)
            {
                buffer.WriteByte(0);
            }
            else
            {
                buffer.WriteByte(CertificateTypes.Length);
                foreach (byte curr in CertificateTypes)
                {
                    buffer.WriteByte(curr);
                }
            }

            if (SupportedSignatureAlgorithms != null)
            {
                buffer.WriteShort(2 * SupportedSignatureAlgorithms.Count);
                for (int i = 0; i < SupportedSignatureAlgorithms.Count; ++i)
                {
                    SignatureAndHashAlgorithm entry = (SignatureAndHashAlgorithm)SupportedSignatureAlgorithms[i];
                    buffer.WriteByte(entry.Hash);
                    buffer.WriteByte(entry.Signature);
                }
            }

            if (CertificateAuthorities == null || CertificateAuthorities.Count == 0)
            {
                buffer.WriteShort(0);
            }
            else
            {
                buffer.WriteShort(totalLength);
                for (int i = 0; i < derEncodings.Count; ++i)
                {
                    byte[] derEncoding = (byte[])derEncodings[i];
                    buffer.WriteShort(derEncoding.Length);
                    buffer.WriteBytes(derEncoding);
                }
            }

            return(buffer);
        }
예제 #15
0
        private void ProcessServerSupplementalData(IByteBuffer body)
        {
            IList serverSupplementalData = DtlsHelper.ReadSupplementalData(body);

            clientState.Client.ProcessServerSupplementalData(serverSupplementalData);
        }
예제 #16
0
        private void ProcessServerHello(IByteBuffer body)
        {
            ProtocolVersion recordLayerVersion = recordLayer.GetReadVersion();

            ReportServerVersion(recordLayerVersion);
            recordLayer.SetWriteVersion(recordLayerVersion);

            AsyncDtlsSecurityParameters securityParameters = (AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters;

            ProtocolVersion server_version = ProtocolVersion.Get(body.ReadByte() & 0xFF, body.ReadByte() & 0xFF);

            ReportServerVersion(server_version);

            byte[] serverRandom = new byte[32];
            body.ReadBytes(serverRandom);
            securityParameters.SetServerRandom(serverRandom);

            byte[] selectedSessionID = new byte[body.ReadByte() & 0x0FF];
            if (selectedSessionID.Length > 0)
            {
                body.ReadBytes(selectedSessionID);
            }

            clientState.SelectedSessionID = selectedSessionID;
            if (selectedSessionID.Length > 32)
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            clientState.Client.NotifySessionID(selectedSessionID);
            clientState.ResumedSession = selectedSessionID.Length > 0 && clientState.TlsSession != null && ArrayUtils.Equals(clientState.SelectedSessionID, clientState.TlsSession.SessionID);

            int     selectedCipherSuite   = body.ReadUnsignedShort();
            Boolean inOfferedCipherSuites = false;

            for (int i = 0; i < clientState.OfferedCipherSuites.Length; i++)
            {
                if (selectedCipherSuite == clientState.OfferedCipherSuites[i])
                {
                    inOfferedCipherSuites = true;
                    break;
                }
            }

            if (!inOfferedCipherSuites || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL || CipherSuite.IsScsv(selectedCipherSuite) || !DtlsHelper.GetMinimumVersion(selectedCipherSuite).IsEqualOrEarlierVersionOf(clientState.ClientContext.ServerVersion.GetEquivalentTLSVersion()))
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            switch (DtlsHelper.GetEncryptionAlgorithm(selectedCipherSuite))
            {
            case EncryptionAlgorithm.RC4_40:
            case EncryptionAlgorithm.RC4_128:
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }

            clientState.Client.NotifySelectedCipherSuite(selectedCipherSuite);

            byte    selectedCompressionMethod   = body.ReadByte();
            Boolean inOfferedCompressionMethods = false;

            for (int i = 0; i < clientState.OfferedCompressionMethods.Length; i++)
            {
                if (selectedCompressionMethod == clientState.OfferedCompressionMethods[i])
                {
                    inOfferedCompressionMethods = true;
                    break;
                }
            }

            if (!inOfferedCompressionMethods)
            {
                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
            }

            clientState.Client.NotifySelectedCompressionMethod(selectedCompressionMethod);
            clientState.ServerExtensions = DtlsHelper.ReadSelectedExtensions(body);

            if (clientState.ServerExtensions != null)
            {
                foreach (Int32 extType in clientState.ServerExtensions.Keys)
                {
                    if (extType.Equals(DtlsHelper.EXT_RenegotiationInfo))
                    {
                        continue;
                    }

                    if (!clientState.ClientExtensions.Contains(extType))
                    {
                        throw new TlsFatalAlert(AlertDescription.unsupported_extension);
                    }
                }
            }

            byte[] renegExtData = null;
            if (clientState.ServerExtensions.Contains(DtlsHelper.EXT_RenegotiationInfo))
            {
                renegExtData = (byte[])clientState.ServerExtensions[DtlsHelper.EXT_RenegotiationInfo];
            }

            if (renegExtData != null)
            {
                clientState.SecureRenegotiation = true;

                if (!ArrayUtils.Equals(renegExtData, DtlsHelper.EMPTY_BYTES_WITH_LENGTH))
                {
                    throw new TlsFatalAlert(AlertDescription.handshake_failure);
                }
            }

            if (clientState.SecureRenegotiation)
            {
                clientState.Client.NotifySecureRenegotiation(clientState.SecureRenegotiation);
            }

            IDictionary sessionClientExtensions = clientState.ClientExtensions;
            IDictionary sessionServerExtensions = clientState.ServerExtensions;

            if (clientState.ResumedSession)
            {
                if (selectedCipherSuite != clientState.SessionParameters.CipherSuite || selectedCompressionMethod != clientState.SessionParameters.CompressionAlgorithm)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                sessionClientExtensions = null;
                sessionServerExtensions = (Dictionary <Int32, byte[]>)clientState.SessionParameters.ReadServerExtensions();
            }

            securityParameters.SetCipherSuite(selectedCipherSuite);
            securityParameters.SetCompressionAlgorithm(selectedCompressionMethod);

            if (sessionServerExtensions != null)
            {
                byte[] encryptThenMac = null;
                if (sessionServerExtensions.Contains(DtlsHelper.EXT_encrypt_then_mac))
                {
                    encryptThenMac = (byte[])sessionServerExtensions[DtlsHelper.EXT_encrypt_then_mac];
                }

                if (encryptThenMac != null && encryptThenMac.Length > 0)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                Boolean serverSentEncryptThenMAC = encryptThenMac != null;
                if (serverSentEncryptThenMAC && DtlsHelper.GetCipherType(securityParameters.CipherSuite) != CipherType.block)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                securityParameters.SetEncryptThenMAC(serverSentEncryptThenMAC);

                byte[] extendedMacSecret = null;
                if (sessionServerExtensions.Contains(DtlsHelper.EXT_extended_master_secret))
                {
                    extendedMacSecret = (byte[])sessionServerExtensions[DtlsHelper.EXT_extended_master_secret];
                }

                if (extendedMacSecret != null && extendedMacSecret.Length > 0)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                securityParameters.SetExtendedMasterSecret(extendedMacSecret != null);

                securityParameters.SetMaxFragmentLength(DtlsHelper.EvaluateMaxFragmentLengthExtension(clientState.ResumedSession, sessionClientExtensions, sessionServerExtensions, AlertDescription.illegal_parameter));

                byte[] truncatedHMAC = null;
                if (sessionServerExtensions.Contains(DtlsHelper.EXT_truncated_hmac))
                {
                    truncatedHMAC = (byte[])sessionServerExtensions[DtlsHelper.EXT_truncated_hmac];
                }

                if (truncatedHMAC != null && truncatedHMAC.Length > 0)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                securityParameters.SetTruncatedHMac(truncatedHMAC != null);

                byte[] statusRequest = null;
                if (sessionServerExtensions.Contains(DtlsHelper.EXT_status_request))
                {
                    statusRequest = (byte[])sessionServerExtensions[DtlsHelper.EXT_status_request];
                }

                if (statusRequest != null && statusRequest.Length > 0)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                clientState.AllowCertificateStatus = (!clientState.ResumedSession && statusRequest != null);

                byte[] sessionTicket = null;
                if (sessionServerExtensions.Contains(DtlsHelper.EXT_SessionTicket))
                {
                    sessionTicket = (byte[])sessionServerExtensions[DtlsHelper.EXT_SessionTicket];
                }

                if (sessionTicket != null && sessionTicket.Length > 0)
                {
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
                }

                clientState.ExpectSessionTicket = (!clientState.ResumedSession && sessionTicket != null);
            }

            if (sessionClientExtensions != null)
            {
                clientState.Client.ProcessServerExtensions(sessionServerExtensions);
            }

            securityParameters.SetPrfAlgorithm(DtlsHelper.GetPRFAlgorithm(clientState.ClientContext.ServerVersion, securityParameters.CipherSuite));
            securityParameters.SetVerifyDataLength(12);
        }
예제 #17
0
        public List <IByteBuffer> Receive(IByteBuffer record)
        {
            List <IByteBuffer> outputList = new List <IByteBuffer>();

            while (record.ReadableBytes > RECORD_HEADER_LENGTH)
            {
                byte            type    = (byte)(record.ReadByte() & 0x00FF);
                ProtocolVersion version = ProtocolVersion.Get(record.ReadByte() & 0xFF, record.ReadByte() & 0xFF);
                int             epoch   = record.ReadUnsignedShort();
                long            seq     = DtlsHelper.ReadUint48(record);
                //just reading length,not using it
                short  packetLength = record.ReadShort();
                byte[] realData     = new byte[packetLength];
                record.ReadBytes(realData);

                AsyncDtlsEpoch recordEpoch = null;
                if (epoch == readEpoch.Epoch)
                {
                    recordEpoch = readEpoch;
                }

                if (recordEpoch == null)
                {
                    continue;
                }

                if (recordEpoch.ReplayWindow.ShouldDiscard(seq))
                {
                    continue;
                }

                if (!version.IsDtls)
                {
                    continue;
                }

                if (readVersion != null && !readVersion.Equals(version))
                {
                    continue;
                }

                byte[]      plaintext = recordEpoch.getCipher().DecodeCiphertext(GetMacSequenceNumber(recordEpoch.Epoch, seq), type, realData, 0, realData.Length);
                IByteBuffer output    = Unpooled.WrappedBuffer(plaintext);

                recordEpoch.ReplayWindow.ReportAuthenticated(seq);
                if (plaintext.Length > this.plaintextLimit)
                {
                    continue;
                }

                if (readVersion == null)
                {
                    readVersion = version;
                }

                switch (type)
                {
                case ContentType.alert:
                    if (output.ReadableBytes == 2)
                    {
                        byte alertLevel       = (byte)(output.ReadByte() & 0x0FF);
                        byte alertDescription = (byte)(output.ReadByte() & 0x0FF);

                        peer.NotifyAlertReceived(alertLevel, alertDescription);

                        if (alertLevel == AlertLevel.fatal)
                        {
                            Failed();
                            throw new TlsFatalAlert(alertDescription);
                        }

                        if (alertDescription == AlertDescription.close_notify)
                        {
                            CloseTransport();
                        }
                    }

                    continue;

                case ContentType.application_data:
                    if (inHandshake)
                    {
                        continue;
                    }
                    break;

                case ContentType.change_cipher_spec:
                    while (output.ReadableBytes > 0)
                    {
                        short message = (short)(output.ReadByte() & 0x0FF);
                        if (message != ChangeCipherSpec.change_cipher_spec)
                        {
                            continue;
                        }

                        if (pendingEpoch != null)
                        {
                            readEpoch = pendingEpoch;
                        }
                    }

                    continue;

                case ContentType.handshake:
                    if (!inHandshake)
                    {
                        continue;
                    }

                    HandshakeHeader handshakeHeader = DtlsHelper.ReadHandshakeHeader(output);

                    if (handshakeHeader != null)
                    {
                        if (!handshakeHeader.FragmentLength.Equals(handshakeHeader.TotalLength))
                        {
                            PendingMessageData data = null;
                            if (pendingBuffers.ContainsKey(handshakeHeader.MessageSequence))
                            {
                                data = pendingBuffers[handshakeHeader.MessageSequence];
                            }

                            if (data == null)
                            {
                                data = new PendingMessageData(Unpooled.Buffer(handshakeHeader.TotalLength));
                                pendingBuffers[handshakeHeader.MessageSequence] = data;
                            }

                            data.WriteBytes(output, handshakeHeader.FragmentOffset);
                            if (data.WrottenBytes.Equals(handshakeHeader.TotalLength))
                            {
                                data.Buffer.SetWriterIndex(handshakeHeader.TotalLength);
                                byte[]      packetData = null;
                                IByteBuffer copy       = data.Buffer.Copy();
                                packetData = new byte[copy.ReadableBytes];
                                copy.ReadBytes(packetData);

                                if (handshakeHeader.MessageType.HasValue && handshakeHandler != null)
                                {
                                    handshakeHandler.HandleHandshake(handshakeHeader.MessageType.Value, data.Buffer);
                                }

                                byte[]      pseudoHeader = new byte[DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH];
                                IByteBuffer headerBuffer = Unpooled.WrappedBuffer(pseudoHeader);
                                headerBuffer.SetWriterIndex(0);
                                DtlsHelper.WriteHandshakeHeader(handshakeHeader.MessageSequence, handshakeHeader.MessageType.Value, headerBuffer, handshakeHeader.TotalLength);
                                headerBuffer.SetReaderIndex(0);
                                handshakeHash.BlockUpdate(pseudoHeader, 0, pseudoHeader.Length);
                                handshakeHash.BlockUpdate(packetData, 0, packetData.Length);

                                if (handshakeHeader.MessageType.HasValue && handshakeHandler != null)
                                {
                                    handshakeHandler.PostProcessHandshake(handshakeHeader.MessageType.Value, data.Buffer);
                                }

                                pendingBuffers.Remove(handshakeHeader.MessageSequence);
                            }
                        }
                        else
                        {
                            byte[]      packetData = null;
                            IByteBuffer copy       = output.Copy();
                            packetData = new byte[copy.ReadableBytes];
                            copy.ReadBytes(packetData);

                            if (handshakeHeader.MessageType.HasValue && handshakeHandler != null)
                            {
                                handshakeHandler.HandleHandshake(handshakeHeader.MessageType.Value, output);
                            }

                            byte[]      pseudoHeader = new byte[DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH];
                            IByteBuffer headerBuffer = Unpooled.WrappedBuffer(pseudoHeader);
                            headerBuffer.SetWriterIndex(0);
                            DtlsHelper.WriteHandshakeHeader(handshakeHeader.MessageSequence, handshakeHeader.MessageType.Value, headerBuffer, handshakeHeader.TotalLength);
                            headerBuffer.SetReaderIndex(0);
                            handshakeHash.BlockUpdate(pseudoHeader, 0, pseudoHeader.Length);
                            handshakeHash.BlockUpdate(packetData, 0, packetData.Length);

                            if (handshakeHeader.MessageType.HasValue && handshakeHandler != null)
                            {
                                handshakeHandler.PostProcessHandshake(handshakeHeader.MessageType.Value, output);
                            }
                        }
                    }

                    continue;

                case ContentType.heartbeat:
                    continue;
                }

                outputList.Add(output);
            }

            return(outputList);
        }
예제 #18
0
        public void InitHandshake(byte[] cookie)
        {
            AsyncDtlsSecurityParameters securityParameters = (AsyncDtlsSecurityParameters)clientState.ClientContext.SecurityParameters;

            ProtocolVersion client_version = clientState.Client.ClientVersion;

            if (!client_version.IsDtls)
            {
                throw new TlsFatalAlert(AlertDescription.internal_error);
            }

            AsyncDtlsClientContext context = clientState.ClientContext;

            context.ClientVersion = client_version;

            Boolean fallback = clientState.Client.IsFallback;

            //Cipher suites
            clientState.OfferedCipherSuites = clientState.Client.GetCipherSuites();

            // Integer -> byte[]
            clientState.ClientExtensions = clientState.Client.GetClientExtensions();
            if (securityParameters.IsExtendedMasterSecret())
            {
                if (clientState.ClientExtensions == null)
                {
                    clientState.ClientExtensions = new Dictionary <int, byte[]>();
                }

                clientState.ClientExtensions[DtlsHelper.EXT_extended_master_secret] = DtlsHelper.EMPTY_BYTES;
            }

            byte[] renegExtData = null;
            if (clientState.ClientExtensions.Contains(DtlsHelper.EXT_RenegotiationInfo))
            {
                renegExtData = (byte[])clientState.ClientExtensions[DtlsHelper.EXT_RenegotiationInfo];
            }

            Boolean noRenegExt  = (null == renegExtData);
            Boolean noRenegSCSV = true;

            for (int i = 0; i < clientState.OfferedCipherSuites.Length; i++)
            {
                if (clientState.OfferedCipherSuites[i] == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
                {
                    noRenegSCSV = false;
                    break;
                }
            }

            Boolean tlsFallbackFound = false;

            for (int i = 0; i < clientState.OfferedCipherSuites.Length; i++)
            {
                if (clientState.OfferedCipherSuites[i] == CipherSuite.TLS_FALLBACK_SCSV)
                {
                    tlsFallbackFound = true;
                    break;
                }
            }

            int additionalCount = 0;

            if (noRenegExt && noRenegSCSV)
            {
                additionalCount++;
            }

            if (fallback && !tlsFallbackFound)
            {
                additionalCount++;
            }

            int[] offeredCipherSuites = clientState.OfferedCipherSuites;
            if (additionalCount > 0)
            {
                offeredCipherSuites = new int[clientState.OfferedCipherSuites.Length + additionalCount];
                Array.Copy(clientState.OfferedCipherSuites, 0, offeredCipherSuites, 0, clientState.OfferedCipherSuites.Length);
                if (noRenegExt && noRenegSCSV)
                {
                    offeredCipherSuites[clientState.OfferedCipherSuites.Length] = CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
                }

                if (fallback && !tlsFallbackFound)
                {
                    offeredCipherSuites[offeredCipherSuites.Length - 1] = CipherSuite.TLS_FALLBACK_SCSV;
                }
            }

            clientState.OfferedCompressionMethods = new short[] { CompressionMethod.cls_null };

            byte[] session_id = DtlsHelper.EMPTY_BYTES;
            if (clientState.TlsSession != null)
            {
                session_id = clientState.TlsSession.SessionID;
                if (session_id == null || session_id.Length > 32)
                {
                    session_id = DtlsHelper.EMPTY_BYTES;
                }
            }

            int totalLength = 2;

            totalLength += securityParameters.ClientRandom.Length;
            totalLength += 1 + session_id.Length;

            if (cookie != null)
            {
                totalLength += cookie.Length + 1;
            }
            else
            {
                totalLength += 1;
            }

            totalLength += 2 + 2 * offeredCipherSuites.Length;
            totalLength += 1 + clientState.OfferedCompressionMethods.Length;
            totalLength += DtlsHelper.CalculateExtensionsLength(clientState.ClientExtensions);

            int         capacity     = DtlsHelper.HANDSHAKE_MESSAGE_HEADER_LENGTH + totalLength;
            IByteBuffer data         = Unpooled.Buffer(capacity);
            short       currSequence = sequence++;

            DtlsHelper.WriteHandshakeHeader(currSequence, MessageType.CLIENT_HELLO, data, totalLength);
            data.WriteByte(client_version.MajorVersion);
            data.WriteByte(client_version.MinorVersion);

            data.WriteBytes(securityParameters.ClientRandom);

            // Session ID
            data.WriteByte(session_id.Length);
            data.WriteBytes(session_id);

            //Cookie
            if (cookie != null)
            {
                data.WriteByte(cookie.Length);
                data.WriteBytes(cookie);
            }
            else
            {
                data.WriteBytes(DtlsHelper.EMPTY_BYTES_WITH_LENGTH);
            }

            data.WriteShort(2 * offeredCipherSuites.Length);
            for (int i = 0; i < offeredCipherSuites.Length; i++)
            {
                data.WriteShort(offeredCipherSuites[i]);
            }

            data.WriteByte(clientState.OfferedCompressionMethods.Length);
            for (int i = 0; i < clientState.OfferedCompressionMethods.Length; i++)
            {
                data.WriteByte(clientState.OfferedCompressionMethods[i]);
            }

            // Extensions
            if (clientState.ClientExtensions != null)
            {
                DtlsHelper.WriteExtensions(data, clientState.ClientExtensions);
            }

            if (protocolVersion == null)
            {
                recordLayer.SetWriteVersion(ProtocolVersion.DTLSv10);
            }
            else
            {
                recordLayer.SetWriteVersion(protocolVersion);
            }

            recordLayer.Send(currSequence, MessageType.CLIENT_HELLO, data);
            handshakeState = State.CLIENT_HELLO_SENT;

            if (handler != null)
            {
                handler.handshakeStarted(channel);
            }
        }
 public CombinedHash(CombinedHash t)
 {
     this.context = t.context;
     this.md5     = DtlsHelper.CloneHash(HashAlgorithm.md5, t.md5);
     this.sha1    = DtlsHelper.CloneHash(HashAlgorithm.sha1, t.sha1);
 }
 public CombinedHash()
 {
     this.md5  = DtlsHelper.CreateHash(HashAlgorithm.md5);
     this.sha1 = DtlsHelper.CreateHash(HashAlgorithm.sha1);
 }