public BigEndianAdvancingSpan ProcessSessionTicket(BigEndianAdvancingSpan sessionTicket)
        {
            var keyId = sessionTicket.Read <Guid>();

            if (keyId != _keyGuid)
            {
                return(new BigEndianAdvancingSpan());
            }
            var key = _keys.Take();

            try
            {
                var nounce = sessionTicket.Read <long>();
                key.IV.Span.Slice(4).Write(nounce);
                key.Init(KeyMode.Decryption);
                var span = sessionTicket.ToSpan();
                key.SetTag(span.Slice(span.Length - 16));
                key.Finish(span.Slice(0, span.Length - 16));
                return(new BigEndianAdvancingSpan(span.Slice(0, span.Length - 16)));
            }
            finally
            {
                _keys.Add(key);
            }
        }
Example #2
0
 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 ProcessExtension(BigEndianAdvancingSpan span)
 {
     if (span.Length != 1)
     {
         Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "We don't support renegotiation so cannot support a secure renegotiation");
     }
 }
Example #4
0
        public AlertException(Span <byte> alertSpan)
        {
            var reader = new BigEndianAdvancingSpan(alertSpan);

            Level            = reader.Read <AlertLevel>();
            Description      = reader.Read <AlertDescription>();
            ReceivedFromPeer = true;
        }
Example #5
0
        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());
 }
Example #8
0
        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;
            }
        }
Example #9
0
        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();
                }
            }
        }
Example #10
0
 private void ProcessSessionTicket(BigEndianAdvancingSpan buffer)
 {
     if (Connection.Listener.SessionProvider == null)
     {
         return;
     }
     _requiresTicket = true;
     if (buffer.Length == 0 || !_secretSchedule.ReadSessionTicket(buffer))
     {
         return;
     }
     _abbreviatedHandshake = true;
 }
Example #11
0
        //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());
        }
Example #12
0
        private void GenerateCipherSuiteBuffer()
        {
            var size = _cipherSuites.Length * Unsafe.SizeOf <ushort>();

            _cipherSuitesBuffer = new byte[size + Unsafe.SizeOf <ushort>()];
            var span = new BigEndianAdvancingSpan((Span <byte>)_cipherSuitesBuffer);

            span.Write((ushort)size);
            for (var i = 0; i < _cipherSuites.Length; i++)
            {
                span.Write(_cipherSuites[i].Code);
            }
            Debug.Assert(span.Length == 0);
        }
        /// <summary>
        /// Heritage KeyExchange selection (pre tls 1.3)
        /// </summary>
        /// <param name="keyExchange"></param>
        /// <param name="supportedGroups"></param>
        /// <returns></returns>
        public IKeyExchange GetKeyExchange(KeyExchangeType keyExchange, BigEndianAdvancingSpan supportedGroups)
        {
            switch (keyExchange)
            {
            case KeyExchangeType.Rsa:
                return(new RsaKeyExchange());

            case KeyExchangeType.Ecdhe:
                return(EcdheKeyExchange(supportedGroups));

            default:
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Unable to match key exchange");
                return(null);
            }
        }
Example #14
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);
 }
Example #15
0
        public bool ReadSessionTicket(BigEndianAdvancingSpan buffer)
        {
            var advanceBuffer = Sessions.ProcessSessionTicket(buffer);

            if (advanceBuffer.Length == 0)
            {
                return(false);
            }
            var info = advanceBuffer.Read <SessionInfo>();

            if (info.Version != _state.RecordVersion)
            {
                return(false);
            }
            _state.CipherSuite = _cryptoProvider.CipherSuites.GetCipherSuite(info.CipherSuite);
            advanceBuffer.ToSpan().CopyTo(_masterSecret.Span);
            return(true);
        }
Example #16
0
 public CipherSuite GetCipherSuite(TlsVersion tlsVersion, BigEndianAdvancingSpan cipherSuites)
 {
     for (var x = 0; x < _cipherSuites.Length; x++)
     {
         var tempSpan = cipherSuites;
         while (tempSpan.Length > 0)
         {
             var cipherSuite = tempSpan.Read <ushort>();
             if (cipherSuite == _cipherSuites[x].Code)
             {
                 if (_cipherSuites[x].SupportsVersion(tlsVersion))
                 {
                     return(_cipherSuites[x]);
                 }
             }
         }
     }
     Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Unable to match cipher suites");
     return(null);
 }
Example #17
0
        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);
        }
 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);
 }
Example #19
0
        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();
            }
        }
Example #20
0
 public SignatureScheme SelectAlgorithm(BigEndianAdvancingSpan buffer) => throw new NotImplementedException();
Example #21
0
 public void SetPeerKey(BigEndianAdvancingSpan peerKey) => throw new NotSupportedException();