示例#1
0
        public ServerContext(
            SslServerStream stream,
            SecurityProtocolType securityProtocolType,
            X509Certificate serverCertificate,
            bool clientCertificateRequired,
            bool requestClientCertificate)
            : base(securityProtocolType)
        {
            this.sslStream = stream;
            this.clientCertificateRequired  = clientCertificateRequired;
            this.request_client_certificate = requestClientCertificate;

            // Convert the System.Security cert to a Mono Cert
            MonoX509.X509Certificate cert = new MonoX509.X509Certificate(serverCertificate.GetRawCertData());

            // Add server certificate to the certificate collection
            this.ServerSettings.Certificates = new MonoX509.X509CertificateCollection();
            this.ServerSettings.Certificates.Add(cert);

            this.ServerSettings.UpdateCertificateRSA();

            if (CertificateValidationHelper.SupportsX509Chain)
            {
                // Build the chain for the certificate and if the chain is correct, add all certificates
                // (except the root certificate [FIRST ONE] ... the client is supposed to know that one,
                // otherwise the whole concept of a trusted chain doesn't work out ...
                MonoX509.X509Chain chain = new MonoX509.X509Chain(MonoX509.X509StoreManager.IntermediateCACertificates);

                if (chain.Build(cert))
                {
                    for (int j = chain.Chain.Count - 1; j > 0; j--)
                    {
                        ServerSettings.Certificates.Add(chain.Chain [j]);
                    }
                }
            }

            // Add requested certificate types
            ServerSettings.CertificateTypes = new ClientCertificateType [ServerSettings.Certificates.Count];
            for (int j = 0; j < this.ServerSettings.CertificateTypes.Length; j++)
            {
                ServerSettings.CertificateTypes [j] = ClientCertificateType.RSA;
            }

            if (CertificateValidationHelper.SupportsX509Chain)
            {
                // Add certificate authorities
                MonoX509.X509CertificateCollection trusted = MonoX509.X509StoreManager.TrustedRootCertificates;
                string[] list = new string [trusted.Count];
                int      i    = 0;
                foreach (MonoX509.X509Certificate root in trusted)
                {
                    list [i++] = root.IssuerName;
                }
                this.ServerSettings.DistinguisedNames = list;
            }
        }
示例#2
0
 /// <summary>Override to review certificate validation decisions.</summary>
 protected bool RemoteCertificateValidation(object sender,
     X509Certificate cert, X509Chain chain, int depth, VerifyResult result)
 {
   return result == VerifyResult.X509_V_OK;
 }
示例#3
0
			static SslPolicyErrors GetErrorsFromChain (X509Chain chain)
			{
				SslPolicyErrors errors = SslPolicyErrors.None;
				foreach (var status in chain.ChainStatus) {
					if (status.Status == X509ChainStatusFlags.NoError)
						continue;
					errors |= SslPolicyErrors.RemoteCertificateChainErrors;
					break;
				}
				return errors;
			}
示例#4
0
			static int GetStatusFromChain (X509Chain chain)
			{
				long result = 0;
				foreach (var status in chain.ChainStatus) {
					X509ChainStatusFlags flags = status.Status;
					if (flags == X509ChainStatusFlags.NoError)
						continue;

					// CERT_E_EXPIRED
					if ((flags & X509ChainStatusFlags.NotTimeValid) != 0) result = 0x800B0101;
					// CERT_E_VALIDITYPERIODNESTING
					else if ((flags & X509ChainStatusFlags.NotTimeNested) != 0) result = 0x800B0102;
					// CERT_E_REVOKED
					else if ((flags & X509ChainStatusFlags.Revoked) != 0) result = 0x800B010C;
					// TRUST_E_CERT_SIGNATURE
					else if ((flags & X509ChainStatusFlags.NotSignatureValid) != 0) result = 0x80096004;
					// CERT_E_WRONG_USAGE
					else if ((flags & X509ChainStatusFlags.NotValidForUsage) != 0) result = 0x800B0110;
					// CERT_E_UNTRUSTEDROOT
					else if ((flags & X509ChainStatusFlags.UntrustedRoot) != 0) result = 0x800B0109;
					// CRYPT_E_NO_REVOCATION_CHECK
					else if ((flags & X509ChainStatusFlags.RevocationStatusUnknown) != 0) result = 0x80092012;
					// CERT_E_CHAINING
					else if ((flags & X509ChainStatusFlags.Cyclic) != 0) result = 0x800B010A;
					// TRUST_E_FAIL - generic
					else if ((flags & X509ChainStatusFlags.InvalidExtension) != 0) result = 0x800B010B;
					// CERT_E_UNTRUSTEDROOT
					else if ((flags & X509ChainStatusFlags.InvalidPolicyConstraints) != 0) result = 0x800B010D;
					// TRUST_E_BASIC_CONSTRAINTS
					else if ((flags & X509ChainStatusFlags.InvalidBasicConstraints) != 0) result = 0x80096019;
					// CERT_E_INVALID_NAME
					else if ((flags & X509ChainStatusFlags.InvalidNameConstraints) != 0) result = 0x800B0114;
					// CERT_E_INVALID_NAME
					else if ((flags & X509ChainStatusFlags.HasNotSupportedNameConstraint) != 0) result = 0x800B0114;
					// CERT_E_INVALID_NAME
					else if ((flags & X509ChainStatusFlags.HasNotDefinedNameConstraint) != 0) result = 0x800B0114;
					// CERT_E_INVALID_NAME
					else if ((flags & X509ChainStatusFlags.HasNotPermittedNameConstraint) != 0) result = 0x800B0114;
					// CERT_E_INVALID_NAME
					else if ((flags & X509ChainStatusFlags.HasExcludedNameConstraint) != 0) result = 0x800B0114;
					// CERT_E_CHAINING
					else if ((flags & X509ChainStatusFlags.PartialChain) != 0) result = 0x800B010A;
					// CERT_E_EXPIRED
					else if ((flags & X509ChainStatusFlags.CtlNotTimeValid) != 0) result = 0x800B0101;
					// TRUST_E_CERT_SIGNATURE
					else if ((flags & X509ChainStatusFlags.CtlNotSignatureValid) != 0) result = 0x80096004;
					// CERT_E_WRONG_USAGE
					else if ((flags & X509ChainStatusFlags.CtlNotValidForUsage) != 0) result = 0x800B0110;
					// CRYPT_E_NO_REVOCATION_CHECK
					else if ((flags & X509ChainStatusFlags.OfflineRevocation) != 0) result = 0x80092012;
					// CERT_E_ISSUERCHAINING
					else if ((flags & X509ChainStatusFlags.NoIssuanceChainPolicy) != 0) result = 0x800B0107;
					else result = 0x800B010B; // TRUST_E_FAIL - generic

					break; // Exit the loop on the first error
				}
				return (int) result;
			}
示例#5
0
			// Used when the obsolete ICertificatePolicy is set to DefaultCertificatePolicy
			// and the new ServerCertificateValidationCallback is not null
			internal ValidationResult ValidateChain (MSX.X509CertificateCollection certs)
			{
				// user_denied is true if the user callback is called and returns false
				bool user_denied = false;
				if (certs == null || certs.Count == 0)
					return null;

				ICertificatePolicy policy = ServicePointManager.CertificatePolicy;

				X509Certificate2 leaf = new X509Certificate2 (certs [0].RawData);
				int status11 = 0; // Error code passed to the obsolete ICertificatePolicy callback
				SslPolicyErrors errors = 0;
				X509Chain chain = null;
				bool result = false;
#if MONOTOUCH
				// The X509Chain is not really usable with MonoTouch (since the decision is not based on this data)
				// However if someone wants to override the results (good or bad) from iOS then they will want all
				// the certificates that the server provided (which generally does not include the root) so, only  
				// if there's a user callback, we'll create the X509Chain but won't build it
				// ref: https://bugzilla.xamarin.com/show_bug.cgi?id=7245
				if (ServerCertificateValidationCallback != null) {
#endif
				chain = new X509Chain ();
				chain.ChainPolicy = new X509ChainPolicy ();
#if !MONOTOUCH
				chain.ChainPolicy.RevocationMode = revocation_mode;
#endif
				for (int i = 1; i < certs.Count; i++) {
					X509Certificate2 c2 = new X509Certificate2 (certs [i].RawData);
					chain.ChainPolicy.ExtraStore.Add (c2);
				}
#if MONOTOUCH
				}
#else
				try {
					if (!chain.Build (leaf))
						errors |= GetErrorsFromChain (chain);
				} catch (Exception e) {
					Console.Error.WriteLine ("ERROR building certificate chain: {0}", e);
					Console.Error.WriteLine ("Please, report this problem to the Mono team");
					errors |= SslPolicyErrors.RemoteCertificateChainErrors;
				}

				// for OSX and iOS we're using the native API to check for the SSL server policy and host names
				if (!is_macosx) {
					if (!CheckCertificateUsage (leaf)) {
						errors |= SslPolicyErrors.RemoteCertificateChainErrors;
						status11 = -2146762490; //CERT_E_PURPOSE 0x800B0106
					}

					if (!CheckServerIdentity (certs [0], host)) {
						errors |= SslPolicyErrors.RemoteCertificateNameMismatch;
						status11 = -2146762481; // CERT_E_CN_NO_MATCH 0x800B010F
					}
				} else {
#endif
					// Attempt to use OSX certificates
					// Ideally we should return the SecTrustResult
					OSX509Certificates.SecTrustResult trustResult = OSX509Certificates.SecTrustResult.Deny;
					try {
						trustResult = OSX509Certificates.TrustEvaluateSsl (certs, host);
						// We could use the other values of trustResult to pass this extra information
						// to the .NET 2 callback for values like SecTrustResult.Confirm
						result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
								  trustResult == OSX509Certificates.SecTrustResult.Unspecified);
					} catch {
						// Ignore
					}
					
					if (result) {
						// TrustEvaluateSsl was successful so there's no trust error
						// IOW we discard our own chain (since we trust OSX one instead)
						errors = 0;
					} else {
						// callback and DefaultCertificatePolicy needs this since 'result' is not specified
						status11 = (int) trustResult;
						errors |= SslPolicyErrors.RemoteCertificateChainErrors;
					}
#if !MONOTOUCH
				}
#endif

#if MONODROID && SECURITY_DEP
				result = AndroidPlatform.TrustEvaluateSsl (certs, sender, leaf, chain, errors);
				if (result) {
					// chain.Build() + GetErrorsFromChain() (above) will ALWAYS fail on
					// Android (there are no mozroots or preinstalled root certificates),
					// thus `errors` will ALWAYS have RemoteCertificateChainErrors.
					// Android just verified the chain; clear RemoteCertificateChainErrors.
					errors  &= ~SslPolicyErrors.RemoteCertificateChainErrors;
				}
#endif

				if (policy != null && (!(policy is DefaultCertificatePolicy) || cb == null)) {
					ServicePoint sp = null;
					HttpWebRequest req = sender as HttpWebRequest;
					if (req != null)
						sp = req.ServicePointNoLock;
					if (status11 == 0 && errors != 0)
						status11 = GetStatusFromChain (chain);

					// pre 2.0 callback
					result = policy.CheckValidationResult (sp, leaf, req, status11);
					user_denied = !result && !(policy is DefaultCertificatePolicy);
				}
				// If there's a 2.0 callback, it takes precedence
				if (ServerCertificateValidationCallback != null) {
					result = ServerCertificateValidationCallback (sender, leaf, chain, errors);
					user_denied = !result;
				}
				return new ValidationResult (result, user_denied, status11);
			}
示例#6
0
 bool ClientCertValidationCallback(ClientCertificateParameters certParams, MX.X509Certificate certificate, MX.X509Chain chain, SslPolicyErrors sslPolicyErrors)
 {
     return(true);
 }
		public AuthenticodeDeformatter () : base ()
		{
			reason = -1;
			signerChain = new X509Chain ();
			timestampChain = new X509Chain ();
		}
示例#8
0
		public ServerContext(
			SslServerStream			stream,
			SecurityProtocolType	securityProtocolType,
			X509Certificate			serverCertificate,
			bool					clientCertificateRequired,
			bool					requestClientCertificate)
			: base(securityProtocolType)
		{
			this.sslStream					= stream;
			this.clientCertificateRequired	= clientCertificateRequired;
			this.request_client_certificate	= requestClientCertificate;

			// Convert the System.Security cert to a Mono Cert
			MonoX509.X509Certificate cert = new MonoX509.X509Certificate(serverCertificate.GetRawCertData());

			// Add server certificate to the certificate collection
			this.ServerSettings.Certificates = new MonoX509.X509CertificateCollection();
			this.ServerSettings.Certificates.Add(cert);

			this.ServerSettings.UpdateCertificateRSA();

			if (CertificateValidationHelper.SupportsX509Chain) {
				// Build the chain for the certificate and if the chain is correct, add all certificates 
				// (except the root certificate [FIRST ONE] ... the client is supposed to know that one,
				// otherwise the whole concept of a trusted chain doesn't work out ... 
				MonoX509.X509Chain chain = new MonoX509.X509Chain (MonoX509.X509StoreManager.IntermediateCACertificates);

				if (chain.Build (cert)) {
					for (int j = chain.Chain.Count - 1; j > 0; j--)
						ServerSettings.Certificates.Add (chain.Chain [j]);
				}
			}

			// Add requested certificate types
			ServerSettings.CertificateTypes = new ClientCertificateType [ServerSettings.Certificates.Count];
			for (int j = 0; j < this.ServerSettings.CertificateTypes.Length; j++)
				ServerSettings.CertificateTypes [j] = ClientCertificateType.RSA;

			if (CertificateValidationHelper.SupportsX509Chain) {
				// Add certificate authorities
				MonoX509.X509CertificateCollection trusted = MonoX509.X509StoreManager.TrustedRootCertificates;
				string[] list = new string [trusted.Count];
				int i = 0;
				foreach (MonoX509.X509Certificate root in trusted) {
					list [i++] = root.IssuerName;
				}
				this.ServerSettings.DistinguisedNames = list;
			}
		}
示例#9
0
        private void validateCertificates(Mono.Security.X509.X509CertificateCollection certificates)
        {
            ServerContext    serverContext = (ServerContext)base.Context;
            AlertDescription description   = AlertDescription.BadCertificate;

            System.Security.Cryptography.X509Certificates.X509Certificate x509Certificate = null;
            int[] certificateErrors = null;
            if (certificates.Count > 0)
            {
                Mono.Security.X509.X509Certificate x509Certificate2 = certificates[0];
                ArrayList arrayList = new ArrayList();
                if (!this.checkCertificateUsage(x509Certificate2))
                {
                    arrayList.Add(-2146762490);
                }
                Mono.Security.X509.X509Chain x509Chain;
                if (certificates.Count > 1)
                {
                    Mono.Security.X509.X509CertificateCollection x509CertificateCollection = new Mono.Security.X509.X509CertificateCollection(certificates);
                    x509CertificateCollection.Remove(x509Certificate2);
                    x509Chain = new Mono.Security.X509.X509Chain(x509CertificateCollection);
                }
                else
                {
                    x509Chain = new Mono.Security.X509.X509Chain();
                }
                bool flag = false;
                try
                {
                    flag = x509Chain.Build(x509Certificate2);
                }
                catch (Exception)
                {
                    flag = false;
                }
                if (!flag)
                {
                    Mono.Security.X509.X509ChainStatusFlags status = x509Chain.Status;
                    if (status != Mono.Security.X509.X509ChainStatusFlags.NotTimeValid)
                    {
                        if (status != Mono.Security.X509.X509ChainStatusFlags.NotTimeNested)
                        {
                            if (status != Mono.Security.X509.X509ChainStatusFlags.NotSignatureValid)
                            {
                                if (status != Mono.Security.X509.X509ChainStatusFlags.UntrustedRoot)
                                {
                                    if (status != Mono.Security.X509.X509ChainStatusFlags.InvalidBasicConstraints)
                                    {
                                        if (status != Mono.Security.X509.X509ChainStatusFlags.PartialChain)
                                        {
                                            description = AlertDescription.CertificateUnknown;
                                            arrayList.Add((int)x509Chain.Status);
                                        }
                                        else
                                        {
                                            description = AlertDescription.UnknownCA;
                                            arrayList.Add(-2146762486);
                                        }
                                    }
                                    else
                                    {
                                        arrayList.Add(-2146869223);
                                    }
                                }
                                else
                                {
                                    description = AlertDescription.UnknownCA;
                                    arrayList.Add(-2146762487);
                                }
                            }
                            else
                            {
                                arrayList.Add(-2146869232);
                            }
                        }
                        else
                        {
                            arrayList.Add(-2146762494);
                        }
                    }
                    else
                    {
                        description = AlertDescription.CertificateExpired;
                        arrayList.Add(-2146762495);
                    }
                }
                x509Certificate   = new System.Security.Cryptography.X509Certificates.X509Certificate(x509Certificate2.RawData);
                certificateErrors = (int[])arrayList.ToArray(typeof(int));
            }
            else
            {
                certificateErrors = new int[0];
            }
            System.Security.Cryptography.X509Certificates.X509CertificateCollection x509CertificateCollection2 = new System.Security.Cryptography.X509Certificates.X509CertificateCollection();
            foreach (Mono.Security.X509.X509Certificate x509Certificate3 in certificates)
            {
                x509CertificateCollection2.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(x509Certificate3.RawData));
            }
            if (!serverContext.SslStream.RaiseClientCertificateValidation(x509Certificate, certificateErrors))
            {
                throw new TlsException(description, "Invalid certificate received from client.");
            }
            base.Context.ClientSettings.ClientCertificate = x509Certificate;
        }
示例#10
0
        private void validateCertificates(Mono.Security.X509.X509CertificateCollection certificates)
        {
            ClientContext    clientContext = (ClientContext)base.Context;
            AlertDescription description   = AlertDescription.BadCertificate;

            if (clientContext.SslStream.HaveRemoteValidation2Callback)
            {
                ValidationResult validationResult = clientContext.SslStream.RaiseServerCertificateValidation2(certificates);
                if (validationResult.Trusted)
                {
                    return;
                }
                long num  = (long)validationResult.ErrorCode;
                long num2 = num;
                if (num2 != (long)((ulong)-2146762487))
                {
                    if (num2 != (long)((ulong)-2146762486))
                    {
                        if (num2 != (long)((ulong)-2146762495))
                        {
                            description = AlertDescription.CertificateUnknown;
                        }
                        else
                        {
                            description = AlertDescription.CertificateExpired;
                        }
                    }
                    else
                    {
                        description = AlertDescription.UnknownCA;
                    }
                }
                else
                {
                    description = AlertDescription.UnknownCA;
                }
                string str = string.Format("0x{0:x}", num);
                throw new TlsException(description, "Invalid certificate received from server. Error code: " + str);
            }
            else
            {
                Mono.Security.X509.X509Certificate x509Certificate = certificates[0];
                System.Security.Cryptography.X509Certificates.X509Certificate certificate = new System.Security.Cryptography.X509Certificates.X509Certificate(x509Certificate.RawData);
                ArrayList arrayList = new ArrayList();
                if (!this.checkCertificateUsage(x509Certificate))
                {
                    arrayList.Add(-2146762490);
                }
                if (!this.checkServerIdentity(x509Certificate))
                {
                    arrayList.Add(-2146762481);
                }
                Mono.Security.X509.X509CertificateCollection x509CertificateCollection = new Mono.Security.X509.X509CertificateCollection(certificates);
                x509CertificateCollection.Remove(x509Certificate);
                Mono.Security.X509.X509Chain x509Chain = new Mono.Security.X509.X509Chain(x509CertificateCollection);
                bool flag = false;
                try
                {
                    flag = x509Chain.Build(x509Certificate);
                }
                catch (Exception)
                {
                    flag = false;
                }
                if (!flag)
                {
                    Mono.Security.X509.X509ChainStatusFlags status = x509Chain.Status;
                    if (status != Mono.Security.X509.X509ChainStatusFlags.NotTimeValid)
                    {
                        if (status != Mono.Security.X509.X509ChainStatusFlags.NotTimeNested)
                        {
                            if (status != Mono.Security.X509.X509ChainStatusFlags.NotSignatureValid)
                            {
                                if (status != Mono.Security.X509.X509ChainStatusFlags.UntrustedRoot)
                                {
                                    if (status != Mono.Security.X509.X509ChainStatusFlags.InvalidBasicConstraints)
                                    {
                                        if (status != Mono.Security.X509.X509ChainStatusFlags.PartialChain)
                                        {
                                            description = AlertDescription.CertificateUnknown;
                                            arrayList.Add((int)x509Chain.Status);
                                        }
                                        else
                                        {
                                            description = AlertDescription.UnknownCA;
                                            arrayList.Add(-2146762486);
                                        }
                                    }
                                    else
                                    {
                                        arrayList.Add(-2146869223);
                                    }
                                }
                                else
                                {
                                    description = AlertDescription.UnknownCA;
                                    arrayList.Add(-2146762487);
                                }
                            }
                            else
                            {
                                arrayList.Add(-2146869232);
                            }
                        }
                        else
                        {
                            arrayList.Add(-2146762494);
                        }
                    }
                    else
                    {
                        description = AlertDescription.CertificateExpired;
                        arrayList.Add(-2146762495);
                    }
                }
                int[] certificateErrors = (int[])arrayList.ToArray(typeof(int));
                if (!clientContext.SslStream.RaiseServerCertificateValidation(certificate, certificateErrors))
                {
                    throw new TlsException(description, "Invalid certificate received from server.");
                }
                return;
            }
        }
示例#11
0
        private void validateCertificates(Mono.Security.X509.X509CertificateCollection certificates)
        {
            ClientContext    clientContext = (ClientContext)base.Context;
            AlertDescription description   = AlertDescription.BadCertificate;

            if (clientContext.SslStream.HaveRemoteValidation2Callback)
            {
                ValidationResult validationResult = clientContext.SslStream.RaiseServerCertificateValidation2(certificates);
                if (!validationResult.Trusted)
                {
                    long num = validationResult.ErrorCode;
                    switch (num)
                    {
                    case 2148204801L:
                        description = AlertDescription.CertificateExpired;
                        break;

                    case 2148204810L:
                        description = AlertDescription.UnknownCA;
                        break;

                    case 2148204809L:
                        description = AlertDescription.UnknownCA;
                        break;

                    default:
                        description = AlertDescription.CertificateUnknown;
                        break;
                    }
                    string str = $"0x{num:x}";
                    throw new TlsException(description, "Invalid certificate received from server. Error code: " + str);
                }
                return;
            }
            Mono.Security.X509.X509Certificate x509Certificate = certificates[0];
            System.Security.Cryptography.X509Certificates.X509Certificate certificate = new System.Security.Cryptography.X509Certificates.X509Certificate(x509Certificate.RawData);
            ArrayList arrayList = new ArrayList();

            if (!checkCertificateUsage(x509Certificate))
            {
                arrayList.Add(-2146762490);
            }
            if (!checkServerIdentity(x509Certificate))
            {
                arrayList.Add(-2146762481);
            }
            Mono.Security.X509.X509CertificateCollection x509CertificateCollection = new Mono.Security.X509.X509CertificateCollection(certificates);
            x509CertificateCollection.Remove(x509Certificate);
            Mono.Security.X509.X509Chain x509Chain = new Mono.Security.X509.X509Chain(x509CertificateCollection);
            bool flag = false;

            try
            {
                flag = x509Chain.Build(x509Certificate);
            }
            catch (Exception)
            {
                flag = false;
            }
            if (!flag)
            {
                switch (x509Chain.Status)
                {
                case Mono.Security.X509.X509ChainStatusFlags.InvalidBasicConstraints:
                    arrayList.Add(-2146869223);
                    break;

                case Mono.Security.X509.X509ChainStatusFlags.NotSignatureValid:
                    arrayList.Add(-2146869232);
                    break;

                case Mono.Security.X509.X509ChainStatusFlags.NotTimeNested:
                    arrayList.Add(-2146762494);
                    break;

                case Mono.Security.X509.X509ChainStatusFlags.NotTimeValid:
                    description = AlertDescription.CertificateExpired;
                    arrayList.Add(-2146762495);
                    break;

                case Mono.Security.X509.X509ChainStatusFlags.PartialChain:
                    description = AlertDescription.UnknownCA;
                    arrayList.Add(-2146762486);
                    break;

                case Mono.Security.X509.X509ChainStatusFlags.UntrustedRoot:
                    description = AlertDescription.UnknownCA;
                    arrayList.Add(-2146762487);
                    break;

                default:
                    description = AlertDescription.CertificateUnknown;
                    arrayList.Add((int)x509Chain.Status);
                    break;
                }
            }
            int[] certificateErrors = (int[])arrayList.ToArray(typeof(int));
            if (!clientContext.SslStream.RaiseServerCertificateValidation(certificate, certificateErrors))
            {
                throw new TlsException(description, "Invalid certificate received from server.");
            }
        }