private void ProcessServerCertificate(IByteBuffer data) { serverCertificate = DtlsHelper.ParseCertificate(data); clientState.KeyExchange.ProcessServerCertificate(serverCertificate); clientState.Authentication = clientState.Client.GetAuthentication(); clientState.Authentication.NotifyServerCertificate(serverCertificate); }
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); }
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; } }
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); }
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); }
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(); }
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)); }
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); }
private void ProcessServerSupplementalData(IByteBuffer body) { IList serverSupplementalData = DtlsHelper.ReadSupplementalData(body); clientState.Client.ProcessServerSupplementalData(serverSupplementalData); }
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); }
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); }
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); }