public static void ReadServerHello(ReadableBuffer readable, IConnectionStateTls13 connectionState) { var original = readable; ushort version, cipherCode; readable = readable.Slice(HandshakeProcessor.HandshakeHeaderSize); readable = readable.SliceBigEndian(out version); //skip random readable = readable.Slice(RandomLength); readable = readable.SliceBigEndian(out cipherCode); connectionState.CipherSuite = connectionState.CryptoProvider.GetCipherSuiteFromCode(cipherCode, connectionState.Version); if (connectionState.CipherSuite == null) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Could not get a cipher suite during server hello"); } connectionState.StartHandshakeHash(original); readable = BufferExtensions.SliceVector <ushort>(ref readable); ExtensionType ext; readable = readable.SliceBigEndian(out ext); if (ext != ExtensionType.key_share) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "There was no keyshare on the server hello"); } readable = BufferExtensions.SliceVector <ushort>(ref readable); NamedGroup group; readable = readable.SliceBigEndian(out group); if (group != connectionState.KeyShare.NamedGroup) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "The named group didn't match the keyshare during server hello"); } readable = BufferExtensions.SliceVector <ushort>(ref readable); connectionState.KeyShare.SetPeerKey(readable); }
public void RegisterSessionTicket(ReadableBuffer buffer) { //slice off the head first buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize); uint ticketAge, ageRandom; buffer = buffer.SliceBigEndian(out ticketAge); buffer = buffer.SliceBigEndian(out ageRandom); var ticketData = BufferExtensions.SliceVector <ushort>(ref buffer); if (buffer.Length > 0) { //Extensions buffer = BufferExtensions.SliceVector <ushort>(ref buffer); if (buffer.Length > 0) { //seems we can resume data ExtensionType type; buffer = buffer.SliceBigEndian(out type); if (type != ExtensionType.ticket_early_data_info) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Early session ticket received had an invalid extension"); } } } }
public void DecryptSession(ref ReadableBuffer buffer, IConnectionStateTls13 state) { var nounce = buffer.Slice(0, 12).ToArray(); buffer = buffer.Slice(12); ushort cipherCode, version; buffer = buffer.SliceBigEndian(out cipherCode); buffer = buffer.SliceBigEndian(out version); state.CipherSuite = state.CryptoProvider.GetCipherSuiteFromCode(cipherCode, state.Version); state.KeySchedule = new KeySchedule13(state, state.Listener.KeyScheduleProvider.BufferPool, buffer); }
private static TlsVersion GetVersion(ref ReadableBuffer buffer) { //Jump the version header and the randoms buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize); TlsVersion version; buffer = buffer.SliceBigEndian(out version); if (!_supportedVersion.Contains(version)) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.protocol_version, $"The version was not in the supported list {version}"); } //Slice out the random buffer = buffer.Slice(Hello.RandomLength); //No sessions slice and dump BufferExtensions.SliceVector <byte>(ref buffer); //Skip the cipher suites if we find a version we are happy with //then the cipher suite is dealt with by that version BufferExtensions.SliceVector <ushort>(ref buffer); //Skip compression, we don't care about that either, we just want to get to the end BufferExtensions.SliceVector <byte>(ref buffer); //And here we are at the end, if we have no extensions then we must be the header version that //we accepted earlier if (buffer.Length == 0) { return(version); } buffer = BufferExtensions.SliceVector <ushort>(ref buffer); while (buffer.Length >= 8) { ExtensionType type; buffer = buffer.SliceBigEndian(out type); var ext = BufferExtensions.SliceVector <ushort>(ref buffer); if (type == ExtensionType.supported_versions) { //Scan the version for supported ones return(ExtensionsRead.ReadSupportedVersion(ext, _supportedVersion)); } } return(version); }
public unsafe IKeyshareInstance GetKeyshareFromKeyshare(ReadableBuffer buffer) { var originalBuffer = buffer; int keyshareCount = 0; //loop through to find the count of keyshares while (buffer.Length > 1) { buffer = buffer.Slice(sizeof(NamedGroup)); BufferExtensions.SliceVector <ushort>(ref buffer); keyshareCount += 2; } buffer = originalBuffer; var peerKeyshareList = stackalloc ushort[keyshareCount]; int currentIndex = 0; while (buffer.Length > 1) { NamedGroup namedGroup; buffer = buffer.SliceBigEndian(out namedGroup); var index = (ushort)(originalBuffer.Length - buffer.Length); BufferExtensions.SliceVector <ushort>(ref buffer); peerKeyshareList[currentIndex] = (ushort)namedGroup; peerKeyshareList[currentIndex + 1] = index; currentIndex += 2; } for (var i = 0; i < _priorityOrderedKeyExchanges.Length; i++) { for (var x = 0; x < keyshareCount; x += 2) { if (peerKeyshareList[x] == (ushort)_priorityOrderedKeyExchanges[i]) { var instance = _keyShareProvider.GetKeyShareInstance((NamedGroup)peerKeyshareList[x]); if (instance == null) { continue; } originalBuffer = originalBuffer.Slice(peerKeyshareList[x + 1]); originalBuffer = BufferExtensions.SliceVector <ushort>(ref originalBuffer); instance.SetPeerKey(originalBuffer); return(instance); } } } return(null); }
public static void ReadSignatureScheme(ReadableBuffer buffer, IConnectionState connectionState) { buffer = BufferExtensions.SliceVector <ushort>(ref buffer); while (buffer.Length > 1) { SignatureScheme scheme; buffer = buffer.SliceBigEndian(out scheme); var cert = connectionState.CertificateList.GetCertificate(connectionState.ServerName, scheme); if (cert != null) { connectionState.Certificate = cert; connectionState.SignatureScheme = scheme; return; } } Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Failed to find a signature scheme that matches"); }
public static void ReadPskKeyExchangeMode(ReadableBuffer buffer, IConnectionStateTls13 connectionState) { buffer = BufferExtensions.SliceVector <byte>(ref buffer); while (buffer.Length > 0) { PskKeyExchangeMode mode; buffer = buffer.SliceBigEndian(out mode); if (connectionState.PskKeyExchangeMode == PskKeyExchangeMode.none) { connectionState.PskKeyExchangeMode = mode; } else { connectionState.PskKeyExchangeMode |= mode; } } }
public static TlsVersion ReadSupportedVersion(ReadableBuffer buffer, TlsVersion[] supportedVersions) { TlsVersion returnVersion = 0; buffer = BufferExtensions.SliceVector <byte>(ref buffer); while (buffer.Length > 1) { TlsVersion version; buffer = buffer.SliceBigEndian(out version); if (supportedVersions.Contains(version)) { if (version > returnVersion) { returnVersion = version; } } } return(returnVersion); }