public ExternalCertificate(ReadableBuffer buffer) { var reader = new BigEndianAdvancingSpan(buffer.ToSpan()); reader.Read <HandshakeHeader>(); reader = reader.ReadVector <UInt24>(); _certificate = new X509Certificate2(reader.ReadVector <UInt24>().ToArray()); if (reader.Length > 0) { _collection = new X509Certificate2Collection(); while (reader.Length > 0) { var cert = new X509Certificate2(reader.ReadVector <UInt24>().ToArray()); _collection.Add(cert); } } Debug.Assert(reader.Length == 0); _rsaPublicKey = _certificate.GetRSAPublicKey(); if (_rsaPublicKey != null) { _certificateType = CertificateType.rsa; _signatureSize = _rsaPublicKey.KeySize / 8; _certificateType = CertificateType.rsa; return; } _ecdsaPublicKey = _certificate.GetECDsaPublicKey(); if (_ecdsaPublicKey != null) { _certificateType = CertificateType.ecdsa; switch (_ecdsaPublicKey.KeySize) { case 256: _signatureScheme = SignatureScheme.ecdsa_secp256r1_sha256; _signatureSize = 72; break; case 384: _signatureScheme = SignatureScheme.ecdsa_secp384r1_sha384; throw new NotImplementedException(); case 521: _signatureSize = 132; _signatureScheme = SignatureScheme.ecdsa_secp521r1_sha512; break; default: throw new InvalidOperationException($"Unsupported Ecdsa Keysize {_ecdsaPublicKey.KeySize}"); } return; } }
public ServerHelloParser(ReadableBuffer buffer, SecurePipeConnection secureConnection) { _originalMessage = buffer.ToSpan(); var span = new BigEndianAdvancingSpan(_originalMessage); span.Read <HandshakeHeader>(); _tlsVersion = span.Read <TlsVersion>(); _serverRandom = span.TakeSlice(TlsConstants.RandomLength).ToSpan(); _sessionId = span.ReadVector <byte>().ToSpan(); _cipherSuite = span.Read <ushort>(); var compression = span.Read <byte>(); //Dump compression if (compression != 0) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Compression is not supported"); } _supportedGroups = default; if (span.Length == 0) { return; } span = span.ReadVector <ushort>(); while (span.Length > 0) { var extType = span.Read <ExtensionType>(); var extBuffer = span.ReadVector <ushort>(); switch (extType) { case ExtensionType.supported_groups: throw new NotImplementedException(); case ExtensionType.application_layer_protocol_negotiation: throw new NotImplementedException(); case ExtensionType.server_name: throw new NotImplementedException(); case ExtensionType.SessionTicket: throw new NotImplementedException(); case ExtensionType.signature_algorithms: throw new NotImplementedException(); case ExtensionType.renegotiation_info: throw new NotImplementedException(); } } }
//This can be extended to check that we match a list of servernames //or any other logic that is required public string ProcessHostNameExtension(BigEndianAdvancingSpan buffer) { buffer = buffer.ReadVector <ushort>(); var type = buffer.Read <byte>(); if (type != 0) { Alerts.AlertException.ThrowDecode("Unknown host type"); } buffer = buffer.ReadVector <ushort>(); return(string.Empty);// Ascii.ToUtf16String(buffer.ToSpan()); }
public SignatureScheme SelectAlgorithm(BigEndianAdvancingSpan buffer) { if (_certificateType == CertificateType.ecdsa) { return(_ecDsaSignatureScheme); } if (buffer.Length == 0) { return(DefaultSignatureScheme); } buffer = buffer.ReadVector <ushort>(); while (buffer.Length > 0) { var scheme = buffer.Read <SignatureScheme>(); var lastByte = 0x00FF & (ushort)scheme; switch (_certificateType) { case CertificateType.rsa: if (lastByte == 1) { return(scheme); } if ((0xFF00 & (ushort)scheme) == 0x0800 && lastByte > 3 && lastByte < 7) { return(scheme); } break; } } Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Failed to find an appropriate signature scheme"); return(SignatureScheme.none); }
public void SetPeerKey(BigEndianAdvancingSpan peerKey, ICertificate certificate, SignatureScheme scheme) { peerKey = peerKey.ReadVector <ushort>(); var decryptedLength = certificate.Decrypt(scheme, peerKey.ToSpan(), peerKey.ToSpan()); peerKey = peerKey.TakeSlice(decryptedLength); _premasterSecret = peerKey.ToArray(); }
public void SetPeerKey(BigEndianAdvancingSpan peerKey, ICertificate certificate, SignatureScheme scheme) { peerKey = peerKey.ReadVector <byte>(); if (peerKey.Length != _keyExchangeSize) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, $"The peer key is not the length of the keyexchange size {peerKey.Length} - {_keyExchangeSize}"); } InternalSetPeerKey(peerKey.ToSpan()); }
public void SetPeerKey(BigEndianAdvancingSpan peerKey, ICertificate certificate, SignatureScheme scheme) { peerKey = peerKey.ReadVector <byte>(); if (peerKey.Length != _keyExchangeSize) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, "Peer key is bad"); } InternalSetPeerKey(peerKey.ToSpan()); }
public ServerKeyExchangeParser(ReadableBuffer reader) { var originalSpan = reader.ToSpan(); var span = new BigEndianAdvancingSpan(originalSpan); span.Read <HandshakeHeader>(); _curveType = span.Read <ECCurveType>(); if (_curveType != ECCurveType.named_curve) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "We only support named curves"); } _namedGroup = span.Read <NamedGroup>(); _key = span; span.ReadVector <byte>(); var dataLength = originalSpan.Length - span.Length; _data = originalSpan.Slice(4, dataLength - 4); _signatureScheme = span.Read <SignatureScheme>(); _signature = span.ReadVector <ushort>().ToSpan(); Debug.Assert(span.Length == 0); }
public (ICertificate, SignatureScheme) GetCertificate(BigEndianAdvancingSpan buffer) { buffer = buffer.ReadVector <ushort>(); while (buffer.Length > 0) { var scheme = buffer.Read <SignatureScheme>(); for (var i = 0; i < _certificates.Count; i++) { if (_certificates[i].SupportsScheme(scheme)) { return(_certificates[i], scheme); } } } Alerts.AlertException.ThrowFailedHandshake("Failed to find a certificate and scheme that matches"); return(null, SignatureScheme.none); }
private IKeyExchange EcdheKeyExchange(BigEndianAdvancingSpan supportedGroups) { if (supportedGroups.Length == 0) { return(GetEcdheKeyExchange(DefaultNamedGroup)); } supportedGroups = supportedGroups.ReadVector <ushort>(); while (supportedGroups.Length > 0) { var namedGroup = supportedGroups.Read <NamedGroup>(); if (!_supportedNamedGroups.Contains(namedGroup)) { continue; } var key = GetEcdheKeyExchange(namedGroup); if (key != null) { return(key); } } Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Unable to match key exchange"); return(null); }
public ClientHelloParser(ReadableBuffer buffer, SecurePipeConnection secureConnection) { _originalMessage = buffer.ToSpan(); var span = new BigEndianAdvancingSpan(_originalMessage); span.Read <HandshakeHeader>(); _tlsVersion = span.Read <TlsVersion>(); _clientRandom = span.TakeSlice(TlsConstants.RandomLength).ToSpan(); _sessionId = span.ReadVector <byte>().ToSpan(); _cipherSuite = span.ReadVector <ushort>(); _compressionMethods = span.ReadVector <byte>().ToSpan(); _negotiatedAlpn = ApplicationLayerProtocolType.None; _hostName = null; if (span.Length == 0) { return; } var extensionSpan = new BigEndianAdvancingSpan(span.ReadVector <ushort>().ToSpan()); while (extensionSpan.Length > 0) { var extType = extensionSpan.Read <ExtensionType>(); var extBuffer = extensionSpan.ReadVector <ushort>(); switch (extType) { case ExtensionType.application_layer_protocol_negotiation: _negotiatedAlpn = secureConnection.Listener.AlpnProvider.ProcessExtension(extBuffer); break; case ExtensionType.server_name: _hostName = secureConnection.Listener.HostNameProvider.ProcessHostNameExtension(extBuffer); break; case ExtensionType.signature_algorithms: _signatureAlgos = extBuffer; break; case ExtensionType.supported_groups: _supportedGroups = extBuffer; break; case ExtensionType.SessionTicket: _sessionTicket = extBuffer; break; case ExtensionType.psk_key_exchange_modes: case ExtensionType.pre_shared_key: case ExtensionType.supported_versions: case ExtensionType.key_share: break; } } if (span.Length > 0) { ThrowBytesLeftOver(); } }