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); }
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); }