Exemple #1
0
        private static ServiceResult CheckChainStatus(X509ChainStatus status, CertificateIdentifier id, CertificateIdentifier issuer, bool isIssuer)
        {
            switch (status.Status)
            {
            case X509ChainStatusFlags.NotValidForUsage:
            {
                return(ServiceResult.Create(
                           (isIssuer) ? StatusCodes.BadCertificateUseNotAllowed : StatusCodes.BadCertificateIssuerUseNotAllowed,
                           "Certificate may not be used as an application instance certificate. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.NoError:
            case X509ChainStatusFlags.OfflineRevocation:
            case X509ChainStatusFlags.InvalidBasicConstraints:
            case X509ChainStatusFlags.PartialChain:
            {
                break;
            }

            case X509ChainStatusFlags.UntrustedRoot:
            {
                // self signed cert signature validation
                // .Net Core ChainStatus returns NotSignatureValid only on Windows,
                // so we have to do the extra cert signature check on all platforms
                if (issuer == null && !isIssuer &&
                    id.Certificate != null && Utils.CompareDistinguishedName(id.Certificate.Subject, id.Certificate.Subject))
                {
                    if (!IsSignatureValid(id.Certificate))
                    {
                        goto case X509ChainStatusFlags.NotSignatureValid;
                    }
                }

                // ignore this error because the root check is done
                // by looking the certificate up in the trusted issuer stores passed to the validator.
                // the ChainStatus uses the trusted issuer stores.
                break;
            }

            case X509ChainStatusFlags.RevocationStatusUnknown:
            {
                if (issuer != null)
                {
                    if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0)
                    {
                        break;
                    }
                }

                // check for meaning less errors for self-signed certificates.
                if (id.Certificate != null && Utils.CompareDistinguishedName(id.Certificate.Subject, id.Certificate.Subject))
                {
                    break;
                }

                return(ServiceResult.Create(
                           (isIssuer) ? StatusCodes.BadCertificateIssuerRevocationUnknown : StatusCodes.BadCertificateRevocationUnknown,
                           "Certificate revocation status cannot be verified. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.Revoked:
            {
                return(ServiceResult.Create(
                           (isIssuer) ? StatusCodes.BadCertificateIssuerRevoked : StatusCodes.BadCertificateRevoked,
                           "Certificate has been revoked. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.NotTimeNested:
            {
                if (id != null && ((id.ValidationOptions & CertificateValidationOptions.SuppressCertificateExpired) != 0))
                {
                    break;
                }

                return(ServiceResult.Create(
                           StatusCodes.BadCertificateIssuerTimeInvalid,
                           "Certificate issuer validatity time does not overhas is expired or not yet valid. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }


            case X509ChainStatusFlags.NotTimeValid:
            {
                if (id != null && ((id.ValidationOptions & CertificateValidationOptions.SuppressCertificateExpired) != 0))
                {
                    break;
                }

                return(ServiceResult.Create(
                           (isIssuer) ? StatusCodes.BadCertificateIssuerTimeInvalid : StatusCodes.BadCertificateTimeInvalid,
                           "Certificate has is expired or not yet valid. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }

            case X509ChainStatusFlags.NotSignatureValid:
            {
                return(ServiceResult.Create(
                           StatusCodes.BadCertificateUntrusted,
                           status.StatusInformation));
            }

            default:
            {
                return(ServiceResult.Create(
                           StatusCodes.BadCertificateInvalid,
                           "Certificate validation failed. {0}: {1}",
                           status.Status,
                           status.StatusInformation));
            }
            }

            return(null);
        }
Exemple #2
0
		private void Set (X509ChainStatus[] status, ref int position, X509ChainStatusFlags flags, X509ChainStatusFlags mask)
		{
			if ((flags & mask) != 0) {
				status [position].Status = mask;
				status [position].StatusInformation = X509ChainStatus.GetInformation (mask);
				position++;
			}
		}
        private static X509ChainStatus[] GetChainStatusInformation(CertTrustErrorStatus dwStatus)
        {
            if (dwStatus == CertTrustErrorStatus.CERT_TRUST_NO_ERROR)
            {
                return(Array.Empty <X509ChainStatus>());
            }

            int count = 0;

            for (uint bits = (uint)dwStatus; bits != 0; bits = bits >> 1)
            {
                if ((bits & 0x1) != 0)
                {
                    count++;
                }
            }

            X509ChainStatus[] chainStatus = new X509ChainStatus[count];
            int index = 0;

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_NOT_SIGNATURE_VALID) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.TRUST_E_CERT_SIGNATURE);
                chainStatus[index].Status            = X509ChainStatusFlags.NotSignatureValid;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_NOT_SIGNATURE_VALID;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.TRUST_E_CERT_SIGNATURE);
                chainStatus[index].Status            = X509ChainStatusFlags.CtlNotSignatureValid;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_UNTRUSTED_ROOT) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_UNTRUSTEDROOT);
                chainStatus[index].Status            = X509ChainStatusFlags.UntrustedRoot;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_UNTRUSTED_ROOT;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_PARTIAL_CHAIN) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_CHAINING);
                chainStatus[index].Status            = X509ChainStatusFlags.PartialChain;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_PARTIAL_CHAIN;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_REVOKED) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CRYPT_E_REVOKED);
                chainStatus[index].Status            = X509ChainStatusFlags.Revoked;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_REVOKED;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_NOT_VALID_FOR_USAGE) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_WRONG_USAGE);
                chainStatus[index].Status            = X509ChainStatusFlags.NotValidForUsage;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_WRONG_USAGE);
                chainStatus[index].Status            = X509ChainStatusFlags.CtlNotValidForUsage;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_VALID) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_EXPIRED);
                chainStatus[index].Status            = X509ChainStatusFlags.NotTimeValid;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_VALID;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_TIME_VALID) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_EXPIRED);
                chainStatus[index].Status            = X509ChainStatusFlags.CtlNotTimeValid;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_TIME_VALID;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_INVALID_NAME_CONSTRAINTS) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME);
                chainStatus[index].Status            = X509ChainStatusFlags.InvalidNameConstraints;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_INVALID_NAME_CONSTRAINTS;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME);
                chainStatus[index].Status            = X509ChainStatusFlags.HasNotSupportedNameConstraint;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME);
                chainStatus[index].Status            = X509ChainStatusFlags.HasNotDefinedNameConstraint;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME);
                chainStatus[index].Status            = X509ChainStatusFlags.HasNotPermittedNameConstraint;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME);
                chainStatus[index].Status            = X509ChainStatusFlags.HasExcludedNameConstraint;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_INVALID_POLICY_CONSTRAINTS) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_POLICY);
                chainStatus[index].Status            = X509ChainStatusFlags.InvalidPolicyConstraints;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_INVALID_POLICY_CONSTRAINTS;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_POLICY);
                chainStatus[index].Status            = X509ChainStatusFlags.NoIssuanceChainPolicy;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_INVALID_BASIC_CONSTRAINTS) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.TRUST_E_BASIC_CONSTRAINTS);
                chainStatus[index].Status            = X509ChainStatusFlags.InvalidBasicConstraints;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_NESTED) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_VALIDITYPERIODNESTING);
                chainStatus[index].Status            = X509ChainStatusFlags.NotTimeNested;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_NESTED;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_REVOCATION_STATUS_UNKNOWN) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CRYPT_E_NO_REVOCATION_CHECK);
                chainStatus[index].Status            = X509ChainStatusFlags.RevocationStatusUnknown;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_REVOCATION_STATUS_UNKNOWN;
            }

            if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_OFFLINE_REVOCATION) != 0)
            {
                chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CRYPT_E_REVOCATION_OFFLINE);
                chainStatus[index].Status            = X509ChainStatusFlags.OfflineRevocation;
                index++;
                dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_OFFLINE_REVOCATION;
            }

            int shiftCount = 0;

            for (uint bits = (uint)dwStatus; bits != 0; bits = bits >> 1)
            {
                if ((bits & 0x1) != 0)
                {
                    chainStatus[index].Status            = (X509ChainStatusFlags)(1 << shiftCount);
                    chainStatus[index].StatusInformation = SR.Unknown_Error;
                    index++;
                }
                shiftCount++;
            }

            return(chainStatus);
        }
        public static IChainPal BuildChain(
            X509Certificate2 leaf,
            List <X509Certificate2> candidates,
            List <X509Certificate2> downloaded,
            List <X509Certificate2> systemTrusted,
            OidCollection applicationPolicy,
            OidCollection certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            DateTime verificationTime,
            ref TimeSpan remainingDownloadTime)
        {
            X509ChainElement[]     elements;
            List <X509ChainStatus> overallStatus = new List <X509ChainStatus>();
            WorkingChain           workingChain  = new WorkingChain();

            Interop.Crypto.X509StoreVerifyCallback workingCallback = workingChain.VerifyCallback;

            // An X509_STORE is more comparable to Cryptography.X509Certificate2Collection than to
            // Cryptography.X509Store. So read this with OpenSSL eyes, not CAPI/CNG eyes.
            //
            // (If you need to think of it as an X509Store, it's a volatile memory store)
            using (SafeX509StoreHandle store = Interop.Crypto.X509StoreCreate())
                using (SafeX509StoreCtxHandle storeCtx = Interop.Crypto.X509StoreCtxCreate())
                {
                    Interop.Crypto.CheckValidOpenSslHandle(store);
                    Interop.Crypto.CheckValidOpenSslHandle(storeCtx);

                    bool lookupCrl = revocationMode != X509RevocationMode.NoCheck;

                    foreach (X509Certificate2 cert in candidates)
                    {
                        OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)cert.Pal;

                        if (!Interop.Crypto.X509StoreAddCert(store, pal.SafeHandle))
                        {
                            throw Interop.Crypto.CreateOpenSslCryptographicException();
                        }

                        if (lookupCrl)
                        {
                            CrlCache.AddCrlForCertificate(
                                cert,
                                store,
                                revocationMode,
                                verificationTime,
                                ref remainingDownloadTime);

                            // If we only wanted the end-entity certificate CRL then don't look up
                            // any more of them.
                            lookupCrl = revocationFlag != X509RevocationFlag.EndCertificateOnly;
                        }
                    }

                    if (revocationMode != X509RevocationMode.NoCheck)
                    {
                        if (!Interop.Crypto.X509StoreSetRevocationFlag(store, revocationFlag))
                        {
                            throw Interop.Crypto.CreateOpenSslCryptographicException();
                        }
                    }

                    SafeX509Handle leafHandle = ((OpenSslX509CertificateReader)leaf.Pal).SafeHandle;

                    if (!Interop.Crypto.X509StoreCtxInit(storeCtx, store, leafHandle))
                    {
                        throw Interop.Crypto.CreateOpenSslCryptographicException();
                    }

                    Interop.Crypto.X509StoreCtxSetVerifyCallback(storeCtx, workingCallback);
                    Interop.Crypto.SetX509ChainVerifyTime(storeCtx, verificationTime);

                    int verify = Interop.Crypto.X509VerifyCert(storeCtx);

                    if (verify < 0)
                    {
                        throw Interop.Crypto.CreateOpenSslCryptographicException();
                    }

                    // Because our callback tells OpenSSL that every problem is ignorable, it should tell us that the
                    // chain is just fine (unless it returned a negative code for an exception)
                    Debug.Assert(verify == 1, "verify == 1");

                    using (SafeX509StackHandle chainStack = Interop.Crypto.X509StoreCtxGetChain(storeCtx))
                    {
                        int chainSize = Interop.Crypto.GetX509StackFieldCount(chainStack);
                        elements = new X509ChainElement[chainSize];
                        int maybeRootDepth = chainSize - 1;

                        // The leaf cert is 0, up to (maybe) the root at chainSize - 1
                        for (int i = 0; i < chainSize; i++)
                        {
                            List <X509ChainStatus> status = new List <X509ChainStatus>();

                            List <Interop.Crypto.X509VerifyStatusCode> elementErrors =
                                i < workingChain.Errors.Count ? workingChain.Errors[i] : null;

                            if (elementErrors != null)
                            {
                                AddElementStatus(elementErrors, status, overallStatus);
                            }

                            IntPtr elementCertPtr = Interop.Crypto.GetX509StackField(chainStack, i);

                            if (elementCertPtr == IntPtr.Zero)
                            {
                                throw Interop.Crypto.CreateOpenSslCryptographicException();
                            }

                            // Duplicate the certificate handle
                            X509Certificate2 elementCert = new X509Certificate2(elementCertPtr);

                            // If the last cert is self signed then it's the root cert, do any extra checks.
                            if (i == maybeRootDepth && IsSelfSigned(elementCert))
                            {
                                // If the root certificate was downloaded or the system
                                // doesn't trust it, it's untrusted.
                                if (downloaded.Contains(elementCert) ||
                                    !systemTrusted.Contains(elementCert))
                                {
                                    AddElementStatus(
                                        Interop.Crypto.X509VerifyStatusCode.X509_V_ERR_CERT_UNTRUSTED,
                                        status,
                                        overallStatus);
                                }
                            }

                            elements[i] = new X509ChainElement(elementCert, status.ToArray(), "");
                        }
                    }
                }

            GC.KeepAlive(workingCallback);

            if ((certificatePolicy != null && certificatePolicy.Count > 0) ||
                (applicationPolicy != null && applicationPolicy.Count > 0))
            {
                List <X509Certificate2> certsToRead = new List <X509Certificate2>();

                foreach (X509ChainElement element in elements)
                {
                    certsToRead.Add(element.Certificate);
                }

                CertificatePolicyChain policyChain = new CertificatePolicyChain(certsToRead);

                bool failsPolicyChecks = false;

                if (certificatePolicy != null)
                {
                    if (!policyChain.MatchesCertificatePolicies(certificatePolicy))
                    {
                        failsPolicyChecks = true;
                    }
                }

                if (applicationPolicy != null)
                {
                    if (!policyChain.MatchesApplicationPolicies(applicationPolicy))
                    {
                        failsPolicyChecks = true;
                    }
                }

                if (failsPolicyChecks)
                {
                    X509ChainElement leafElement = elements[0];

                    X509ChainStatus chainStatus = new X509ChainStatus
                    {
                        Status            = X509ChainStatusFlags.InvalidPolicyConstraints,
                        StatusInformation = SR.Chain_NoPolicyMatch,
                    };

                    var elementStatus = new List <X509ChainStatus>(leafElement.ChainElementStatus.Length + 1);
                    elementStatus.AddRange(leafElement.ChainElementStatus);

                    AddUniqueStatus(elementStatus, ref chainStatus);
                    AddUniqueStatus(overallStatus, ref chainStatus);

                    elements[0] = new X509ChainElement(
                        leafElement.Certificate,
                        elementStatus.ToArray(),
                        leafElement.Information);
                }
            }

            return(new OpenSslX509ChainProcessor
            {
                ChainStatus = overallStatus.ToArray(),
                ChainElements = elements,
            });
        }
Exemple #5
0
 /// <summary>
 /// Constructor with chainstatus as keyword
 /// </summary>
 /// <param name="chainStatus">chainstatus as keyword</param>
 public CertificateFailedChainValidationException(X509ChainStatus chainStatus, string subject)
     : base(GetKeywords(chainStatus, subject))
 {
 }
Exemple #6
0
 private static Dictionary <string, string> GetKeywords(X509ChainStatus chainStatus, string subject)
 {
     return(GetKeywords(chainStatus.Status.ToString(), subject));
 }
Exemple #7
0
        /// <summary>
        /// Performs the secure handshake so we can start sending messages.
        /// </summary>
        /// <returns></returns>
        private async Task HandshakeAsync()
        {
            // wait on semaphore
            await _handshakeSemaphore.WaitAsync();

            // check if we got raced
            if (_serverEncryptionKey != null && !SecureUtils.HasTimeSlotExpired(_serverEncryptionKeyTimeSlot, false))
            {
                return;
            }

            try {
                // create client key
                GenerateHandshakeKey();

                // get certificate if we don't have it yet
                if (_serverCertificate == null)
                {
                    // log
#if DEBUG_SECURE
                    Console.WriteLine($"[Secure] Handshake Requesting certificate...");
#endif

                    // request certificate
                    SecureHeader requestCertificate = new SecureHeader(SecureHeader.HeaderVersion, SecureMessageType.RequestCertificate);

                    // send request
                    Envelope respondCert = await _node.AskAsync(_address, new byte[0], _configuration.HandshakeTimeout, new Dictionary <string, object>() {
                        { SecureHeader.HeaderName, requestCertificate.ToString() }
                    });

                    // parse response header
                    SecureHeader respondCertHeader = null;

                    try {
                        respondCertHeader = new SecureHeader(Encoding.UTF8.GetString(respondCert.Headers[SecureHeader.HeaderName] as byte[]));
                    } catch (Exception ex) {
                        throw new InvalidDataException("The certificate request response header was invalid", ex);
                    }

                    // check if the certificate response is an error or if it's an incorrect type
                    if (respondCertHeader.Type == SecureMessageType.Error)
                    {
                        SecureErrorMsg errorMsg = respondCert.AsProtoBuf <SecureErrorMsg>();

                        throw new SecurityException($"{errorMsg.Message} ({errorMsg.Code})");
                    }
                    else if (respondCertHeader.Type != SecureMessageType.RespondCertificate)
                    {
                        throw new InvalidDataException("The certificate request response header was invalid");
                    }

                    // decode the certificate response and then check it has actual data
                    SecureRespondCertificateMsg respondCertMsg = respondCert.AsProtoBuf <SecureRespondCertificateMsg>();

                    if (respondCertMsg.CertificateData == null)
                    {
                        throw new InvalidDataException("The certificate request response was invalid");
                    }

                    // load certificate from response
                    X509Certificate2 cert = new X509Certificate2(respondCertMsg.CertificateData);

                    // validate it's allowed to act as this service
                    if (_configuration.ValidateAddress)
                    {
                        // check extension is actually there
                        if (cert.Extensions["HolonSecureServices"] == null)
                        {
                            throw new InvalidDataException("The service certificate has no claim for the invoked operation");
                        }

                        // parse extension
                        X509Extension servicesExt = cert.Extensions["HolonSecureServices"];
                    }
                    else
                    {
#if DEBUG_SECURE
                        Console.WriteLine($"[Secure] Handshake WARNING: Not validating services due to configuration!");
#endif
                    }

                    // validate that it's signed by ca authority
                    if (_configuration.ValidateAuthority)
                    {
                        X509Chain chain = new X509Chain();
                        chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                        chain.ChainPolicy.ExtraStore.Add(_configuration.RootAuthority);
                        chain.Build(cert);

                        // get status
                        X509ChainStatus status = chain.ChainStatus.First();

                        if (status.Status != X509ChainStatusFlags.UntrustedRoot && status.Status != X509ChainStatusFlags.NoError)
                        {
                            throw new InvalidDataException("The service certificate is not signed by the root authority");
                        }
                    }
                    else
                    {
#if DEBUG_SECURE
                        Console.WriteLine($"[Secure] Handshake WARNING: Not validating authority due to configuration!");
#endif
                    }

                    // log
#if DEBUG_SECURE
                    Console.WriteLine($"[Secure] Handshake Got certifcate {cert.Subject} ({cert.Thumbprint})");
#endif

                    _serverCertificate = cert;
                }

                // log
#if DEBUG_SECURE
                Console.WriteLine($"[Secure] Handshake Requesting key... FirstTime: {_serverEncryptionKey == null}");
#endif

                // key request
                SecureRequestKeyMsg requestKeyMsg = new SecureRequestKeyMsg()
                {
                    HandshakeIV  = _handshakeEncryptionIV,
                    HandshakeKey = _handshakeEncryptionKey
                };
                SecureHeader requestKey = new SecureHeader(SecureHeader.HeaderVersion, SecureMessageType.RequestKey);

                // send request
                Envelope respondKey = null;

                using (RSA rsa = _serverCertificate.GetRSAPublicKey()) {
                    using (MemoryStream ms = new MemoryStream()) {
                        // serialize to stream
                        Serializer.Serialize(ms, requestKeyMsg);

                        // encrypt with server certificate
                        byte[] keyRequestBody = rsa.Encrypt(ms.ToArray(), RSAEncryptionPadding.Pkcs1);

                        respondKey = await _node.AskAsync(_address, keyRequestBody, _configuration.HandshakeTimeout, new Dictionary <string, object>() {
                            { SecureHeader.HeaderName, requestKey.ToString() }
                        });
                    }
                }

                // parse response
                SecureHeader respondKeyHeader = null;

                try {
                    respondKeyHeader = new SecureHeader(Encoding.UTF8.GetString(respondKey.Headers[SecureHeader.HeaderName] as byte[]));
                } catch (Exception ex) {
                    throw new InvalidDataException("The key request response header was invalid", ex);
                }

                // check if the key response is an error or if it's an incorrect type
                if (respondKeyHeader.Type == SecureMessageType.Error)
                {
                    SecureErrorMsg errorMsg = respondKey.AsProtoBuf <SecureErrorMsg>();

                    throw new SecurityException($"{errorMsg.Message} ({errorMsg.Code})");
                }
                else if (respondKeyHeader.Type != SecureMessageType.RespondKey)
                {
                    throw new InvalidDataException("The key request response header was invalid");
                }

                // try and decrypt
                using (MemoryStream decryptedStream = new MemoryStream()) {
                    using (Aes aes = Aes.Create()) {
                        aes.Key = _handshakeEncryptionKey;
                        aes.IV  = _handshakeEncryptionIV;

                        using (CryptoStream decryptStream = new CryptoStream(respondKey.AsStream(), aes.CreateDecryptor(), CryptoStreamMode.Read)) {
                            decryptStream.CopyTo(decryptedStream);
                        }
                    }

                    // seek to beginning
                    decryptedStream.Seek(0, SeekOrigin.Begin);

                    // deserialize
                    SecureRespondKeyMsg respondKeyMsg = Serializer.Deserialize <SecureRespondKeyMsg>(decryptedStream);

                    // validate key
                    if (respondKeyMsg.ServerKey == null || respondKeyMsg.ServerNonce == null || respondKeyMsg.ServerKey.Length != 16)
                    {
                        throw new InvalidDataException("The secure key is invalid");
                    }

                    // log
#if DEBUG_SECURE
                    Console.WriteLine($"[Secure] Handshake Got key Timeslot: {respondKeyMsg.KeyTimeSlot} Nonce: {BitConverter.ToString(respondKeyMsg.ServerNonce).Replace("-", "")}");
#endif

                    // set server encryption key
                    _serverEncryptionKey         = respondKeyMsg.ServerKey;
                    _serverNonce                 = respondKeyMsg.ServerNonce;
                    _serverEncryptionKeyTimeSlot = respondKeyMsg.KeyTimeSlot;
                }
            } finally {
                // make sure to release semaphore no matter what
                _handshakeSemaphore.Release();
            }
        }
        public static IChainPal BuildChain(
            X509Certificate2 leaf,
            X509Certificate2Collection candidates,
            OidCollection applicationPolicy,
            OidCollection certificatePolicy,
            DateTime verificationTime)
        {
            X509ChainElement[]     elements;
            List <X509ChainStatus> overallStatus = new List <X509ChainStatus>();

            // An X509_STORE is more comparable to Cryptography.X509Certificate2Collection than to
            // Cryptography.X509Store. So read this with OpenSSL eyes, not CAPI/CNG eyes.
            //
            // (If you need to think of it as an X509Store, it's a volatile memory store)
            using (SafeX509StoreHandle store = Interop.libcrypto.X509_STORE_new())
                using (SafeX509StoreCtxHandle storeCtx = Interop.libcrypto.X509_STORE_CTX_new())
                {
                    Interop.libcrypto.CheckValidOpenSslHandle(store);
                    Interop.libcrypto.CheckValidOpenSslHandle(storeCtx);

                    foreach (X509Certificate2 cert in candidates)
                    {
                        OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)cert.Pal;

                        if (!Interop.libcrypto.X509_STORE_add_cert(store, pal.SafeHandle))
                        {
                            throw Interop.libcrypto.CreateOpenSslCryptographicException();
                        }
                    }

                    // When CRL checking support is added, it should be done before the call to
                    // X509_STORE_CTX_init (aka here) by calling X509_STORE_set_flags(store, flags);

                    SafeX509Handle leafHandle = ((OpenSslX509CertificateReader)leaf.Pal).SafeHandle;

                    if (!Interop.libcrypto.X509_STORE_CTX_init(storeCtx, store, leafHandle, IntPtr.Zero))
                    {
                        throw Interop.libcrypto.CreateOpenSslCryptographicException();
                    }

                    Interop.NativeCrypto.SetX509ChainVerifyTime(storeCtx, verificationTime);

                    int verify = Interop.libcrypto.X509_verify_cert(storeCtx);

                    if (verify < 0)
                    {
                        throw Interop.libcrypto.CreateOpenSslCryptographicException();
                    }

                    using (SafeX509StackHandle chainStack = Interop.libcrypto.X509_STORE_CTX_get1_chain(storeCtx))
                    {
                        int chainSize  = Interop.NativeCrypto.GetX509StackFieldCount(chainStack);
                        int errorDepth = -1;
                        Interop.libcrypto.X509VerifyStatusCode errorCode = 0;
                        string errorMsg = null;

                        if (verify == 0)
                        {
                            errorCode  = Interop.libcrypto.X509_STORE_CTX_get_error(storeCtx);
                            errorDepth = Interop.libcrypto.X509_STORE_CTX_get_error_depth(storeCtx);
                            errorMsg   = Interop.libcrypto.X509_verify_cert_error_string(errorCode);
                        }

                        elements = new X509ChainElement[chainSize];

                        for (int i = 0; i < chainSize; i++)
                        {
                            List <X509ChainStatus> status = new List <X509ChainStatus>();

                            if (i == errorDepth)
                            {
                                X509ChainStatus chainStatus = new X509ChainStatus
                                {
                                    Status            = MapVerifyErrorToChainStatus(errorCode),
                                    StatusInformation = errorMsg,
                                };

                                status.Add(chainStatus);
                                AddUniqueStatus(overallStatus, ref chainStatus);
                            }

                            IntPtr elementCertPtr = Interop.NativeCrypto.GetX509StackField(chainStack, i);

                            if (elementCertPtr == IntPtr.Zero)
                            {
                                throw Interop.libcrypto.CreateOpenSslCryptographicException();
                            }

                            // Duplicate the certificate handle
                            X509Certificate2 elementCert = new X509Certificate2(elementCertPtr);

                            elements[i] = new X509ChainElement(elementCert, status.ToArray(), "");
                        }
                    }
                }

            if ((certificatePolicy != null && certificatePolicy.Count > 0) ||
                (applicationPolicy != null && applicationPolicy.Count > 0))
            {
                X509Certificate2Collection certsToRead = new X509Certificate2Collection();

                foreach (X509ChainElement element in elements)
                {
                    certsToRead.Add(element.Certificate);
                }

                CertificatePolicyChain policyChain = new CertificatePolicyChain(certsToRead);

                bool failsPolicyChecks = false;

                if (certificatePolicy != null)
                {
                    if (!policyChain.MatchesCertificatePolicies(certificatePolicy))
                    {
                        failsPolicyChecks = true;
                    }
                }

                if (applicationPolicy != null)
                {
                    if (!policyChain.MatchesApplicationPolicies(applicationPolicy))
                    {
                        failsPolicyChecks = true;
                    }
                }

                if (failsPolicyChecks)
                {
                    X509ChainElement leafElement = elements[0];

                    X509ChainStatus chainStatus = new X509ChainStatus
                    {
                        Status            = X509ChainStatusFlags.InvalidPolicyConstraints,
                        StatusInformation = SR.Chain_NoPolicyMatch,
                    };

                    var elementStatus = new List <X509ChainStatus>(leafElement.ChainElementStatus.Length + 1);
                    elementStatus.AddRange(leafElement.ChainElementStatus);

                    AddUniqueStatus(elementStatus, ref chainStatus);
                    AddUniqueStatus(overallStatus, ref chainStatus);

                    elements[0] = new X509ChainElement(
                        leafElement.Certificate,
                        elementStatus.ToArray(),
                        leafElement.Information);
                }
            }

            return(new OpenSslX509ChainProcessor
            {
                ChainStatus = overallStatus.ToArray(),
                ChainElements = elements,
            });
        }
        private bool loadSigners()
        {
            bool checkCRL = Convert.ToBoolean(assinadorRegistry.GetValue("ConsultCRL"));

            if (documents == null)
            {
                return(false);
            }

            this.Cursor = Cursors.WaitCursor;

            lstSigners.Items.Clear();
            lstSigners.Groups.Clear();

            if (lstDocuments.SelectedItems.Count > 0)
            {
                List <string> problematicFoundDocuments = new List <string>();
                Signers       commonSigners             = new Signers();

                List <X509Certificate2> nonconformitySigners = new List <X509Certificate2>();
                List <X509Certificate2> conformitySigners    = new List <X509Certificate2>();
                Hashtable certificatesList = new Hashtable();
                foreach (FileHistory filepath in selectedDocuments)
                {
                    try
                    {
                        loadDigitalSignature(filepath.NewPath);

                        if (digitalSignature.error)
                        {
                            if (digitalSignature.DocumentType.Equals(Types.XpsDocument))
                            {
                                digitalSignature.xpsDocument.Close();
                            }
                            else if (digitalSignature.DocumentType.Equals(Types.PdfDocument))
                            {
                                // nothing to-do here
                            }
                            else
                            {
                                digitalSignature.package.Close();
                            }
                            this.Cursor = Cursors.Arrow;
                            return(false);
                        }

                        invalidSignatures.Clear();
                        if (!digitalSignature.Validate())
                        {
                            invalidSignatures = digitalSignature.InvalidDigitalSignatureHolderNames;
                        }

                        ListViewGroup sigaturesGroup = new ListViewGroup(Path.GetFileName(filepath.NewPath));
                        lstSigners.Groups.Add(sigaturesGroup);

                        foreach (Signer signer in digitalSignature.signers)
                        {
                            string[] signature = new string[5];
                            signature[0] = signer.name;
                            signature[1] = signer.issuer;
                            signature[2] = signer.uri;
                            signature[3] = signer.date;
                            signature[4] = signer.serialNumber;

                            X509Certificate2 signatureCertificate = signer.signerCertificate;
                            if ((!nonconformitySigners.Contains(signatureCertificate)) && (!conformitySigners.Contains(signatureCertificate)))
                            {
                                if (!CertificateUtils.ValidateCertificate(signatureCertificate, checkCRL, false) ?? true)
                                {
                                    nonconformitySigners.Add(signatureCertificate);
                                }
                                else
                                {
                                    conformitySigners.Add(signatureCertificate);
                                }
                                certificatesList.Add(signatureCertificate, CertificateUtils.buildStatus);
                            }

                            X509ChainStatus chainStatus = new X509ChainStatus();
                            chainStatus = (X509ChainStatus)certificatesList[signatureCertificate];

                            ChainDocumentStatus chainDocumentStatus = new ChainDocumentStatus();
                            int signatureIcon;
                            if (!(invalidSignatures.Contains(signature[0]) && invalidSignatures.Contains(signature[1]) &&
                                  invalidSignatures.Contains(signature[2]) && invalidSignatures.Contains(signature[3])))
                            {
                                chainDocumentStatus = new ChainDocumentStatus(chainStatus, null);
                                if (nonconformitySigners.Contains(signatureCertificate))
                                {
                                    signatureIcon = 1;
                                }
                                else
                                {
                                    signatureIcon = 2;
                                }
                            }
                            else
                            {
                                signatureIcon       = 0;
                                chainDocumentStatus = new ChainDocumentStatus(chainStatus, ChainDocumentStatus.ChainDocumentStatusFlags.CorruptedDocument);
                            }

                            ListViewItem newSignerItem = new ListViewItem();    //INDEX
                            newSignerItem.Text       = signature[0].ToString(); //0 signer.name
                            newSignerItem.ImageIndex = signatureIcon;
                            newSignerItem.Group      = sigaturesGroup;
                            newSignerItem.SubItems.Add(signature[1]);           //1 signer.issuer
                            newSignerItem.SubItems.Add(signature[3]);           //2 signer.date
                            newSignerItem.SubItems.Add(filepath.NewPath);       //3 signer.path
                            newSignerItem.SubItems.Add(signature[4]);           //4 signer.serialNumber
                            newSignerItem.SubItems.Add(signature[2]);           //5 signer.URI
                            newSignerItem.SubItems.Add(filepath.OriginalPath);  //6 signer.originalPath

                            ListViewItem.ListViewSubItem chainSt = new ListViewItem.ListViewSubItem();
                            chainSt.Text = "";
                            chainSt.Tag  = (object)chainDocumentStatus;
                            newSignerItem.SubItems.Add(chainSt);                //7 Tag chainStatus

                            newSignerItem.Tag = (object)signatureCertificate;   //Tag signer.signerCertificate

                            lstSigners.Items.Add(newSignerItem);

                            if (lstSigners.Groups.Count == 1)
                            {
                                Signer sgn = new Signer();
                                sgn.name              = signature[0].ToString();
                                sgn.issuer            = signature[1].ToString();
                                sgn.serialNumber      = signature[4].ToString();
                                sgn.signerCertificate = signatureCertificate;
                                if (!commonSigners.Contains(sgn))
                                {
                                    commonSigners.Add(sgn);
                                }
                            }
                        }
                        Signers commonRecentlyFoundSigners = new Signers();
                        foreach (ListViewItem lst in sigaturesGroup.Items)
                        {
                            foreach (Signer sgn in commonSigners)
                            {
                                if (lst.SubItems[0].Text == sgn.name &&
                                    lst.SubItems[1].Text == sgn.issuer &&
                                    lst.SubItems[4].Text == sgn.serialNumber &&
                                    !commonRecentlyFoundSigners.Contains(sgn))
                                {
                                    commonRecentlyFoundSigners.Add(sgn);
                                }
                            }
                        }
                        commonSigners = commonRecentlyFoundSigners;
                    }
                    #region catch
                    catch (IOException ioex)
                    {
                        if
                        (
                            MessageBox.Show
                            (
                                "Erro ao abrir o documento " + System.IO.Path.GetFileName(filepath.NewPath) +
                                ".\nCertifique-se de que o documento não foi movido ou está em uso por outra aplicação." +
                                "\n\nDeseja retirá-lo da lista?" +
                                "\n\nInformações adicionais do erro: " + ioex.Message,
                                System.IO.Path.GetFileName(filepath.NewPath),
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question
                            ) == DialogResult.Yes
                        )
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    lstDocuments.Items.Remove(item);
                                }
                            }
                        }
                        else
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    item.Selected = false;
                                    if (lstDocuments.SelectedItems.Count > 0)
                                    {
                                        lstDocuments.FocusedItem = lstDocuments.SelectedItems[0];
                                    }
                                }
                            }
                        }
                    }
                    catch (FileFormatException ffex)
                    {
                        if
                        (
                            MessageBox.Show
                            (
                                "Erro ao abrir o documento " + System.IO.Path.GetFileName(filepath.NewPath) +
                                ".\nSeu conteúdo está corrompido, talvez seja um arquivo temporário.\n\nDeseja retirá-lo da lista?" +
                                "\n\nInformações adicionais do erro: " + ffex.Message,
                                System.IO.Path.GetFileName(filepath.NewPath),
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question
                            ) == DialogResult.Yes
                        )
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    lstDocuments.Items.Remove(item);
                                }
                            }
                        }
                        else
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    item.Selected = false;
                                    if (lstDocuments.SelectedItems.Count > 0)
                                    {
                                        lstDocuments.FocusedItem = lstDocuments.SelectedItems[0];
                                    }
                                }
                            }
                        }
                    }
                    catch (ArgumentNullException anex)
                    {
                        if
                        (
                            MessageBox.Show
                            (
                                "O Documento " + System.IO.Path.GetFileName(filepath.NewPath) +
                                "não está disponível para abertura.\n\nDeseja retirá-lo da lista?" +
                                "\n\nInformações adicionais do erro: " + anex.Message,
                                System.IO.Path.GetFileName(filepath.NewPath),
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question
                            ) == DialogResult.Yes
                        )
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    lstDocuments.Items.Remove(item);
                                }
                            }
                        }
                        else
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    item.Selected = false;
                                    if (lstDocuments.SelectedItems.Count > 0)
                                    {
                                        lstDocuments.FocusedItem = lstDocuments.SelectedItems[0];
                                    }
                                }
                            }
                        }
                    }
                    catch (OpenXmlPackageException oxpex)
                    {
                        if
                        (
                            MessageBox.Show
                            (
                                "O Documento " + System.IO.Path.GetFileName(filepath.NewPath) +
                                " não é um pacote Open XML válido.\n\nDeseja retirá-lo da lista?" +
                                "\n\nInformações adicionais do erro: " + oxpex.Message,
                                System.IO.Path.GetFileName(filepath.NewPath),
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question
                            ) == DialogResult.Yes
                        )
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    lstDocuments.Items.Remove(item);
                                }
                            }
                        }
                        else
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    item.Selected = false;
                                    if (lstDocuments.SelectedItems.Count > 0)
                                    {
                                        lstDocuments.FocusedItem = lstDocuments.SelectedItems[0];
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception err)
                    {
                        if
                        (
                            MessageBox.Show
                            (
                                "Houve um problema na listagem do seguinte documento:\n " +
                                System.IO.Path.GetFileName(filepath.NewPath) + "\n" +
                                err.Message.Substring(0, err.Message.IndexOf(".") + 1) +
                                "\n\nDeseja excluí-lo da lista?",
                                System.IO.Path.GetFileName(filepath.NewPath),
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question
                            ) == DialogResult.Yes
                        )
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    lstDocuments.Items.Remove(item);
                                }
                            }
                        }
                        else
                        {
                            foreach (ListViewItem item in lstDocuments.Items)
                            {
                                if (item.SubItems[2].Text == filepath.NewPath)
                                {
                                    problematicFoundDocuments.Add(item.SubItems[2].Text);
                                    item.Selected = false;
                                    if (lstDocuments.SelectedItems.Count > 0)
                                    {
                                        lstDocuments.FocusedItem = lstDocuments.SelectedItems[0];
                                    }
                                }
                            }
                        }
                    }
                    #endregion
                }

                if (lstDocuments.SelectedItems.Count > 1)
                {
                    ListViewGroup commonSigaturesGroup = new ListViewGroup("commonSignatures", "Assinaturas em Comum");
                    lstSigners.Groups.Insert(0, commonSigaturesGroup);

                    foreach (Signer sig in commonSigners)
                    {
                        ListViewItem newCommonSignerItem = new ListViewItem();
                        newCommonSignerItem.Text  = sig.name;                    //0 signer.name
                        newCommonSignerItem.Group = commonSigaturesGroup;
                        newCommonSignerItem.SubItems.Add(sig.issuer);            //1 signer.issuer
                        newCommonSignerItem.SubItems.Add("");                    //2 signer.date
                        newCommonSignerItem.SubItems.Add("");                    //3 signer.path
                        newCommonSignerItem.SubItems.Add(sig.serialNumber);      //4 signer.serialNumber
                        newCommonSignerItem.SubItems.Add("");                    //5 signer.URI
                        newCommonSignerItem.SubItems.Add("");                    //6 signer.originalPath
                        newCommonSignerItem.Tag = (object)sig.signerCertificate; //Tag signer.signerCertificate

                        lstSigners.Items.Add(newCommonSignerItem);
                    }
                }
                selectedDocuments.Clear();
                foreach (ListViewItem lvi in lstDocuments.SelectedItems)
                {
                    FileHistory fh = new FileHistory(lvi.SubItems[3].Text, lvi.SubItems[2].Text);
                    selectedDocuments.Add(fh);
                }
            }
            if (lstDocuments.SelectedItems.Count > 0)
            {
                loadFileDescription();
                if (digitalSignature.DocumentType.Equals(Types.XpsDocument))
                {
                    digitalSignature.xpsDocument.Close();
                }
                else if (digitalSignature.DocumentType.Equals(Types.PdfDocument))
                {
                    // nothing to-do here
                }
                else
                {
                    digitalSignature.package.Close();
                }
            }
            else if (lstDocuments.Items.Count == 0)
            {
                MessageBox.Show(Constants.NotValidFormat, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.Close();
            }
            this.Cursor = Cursors.Arrow;
            return(true);
        }
        public static IChainPal BuildChain(
            X509Certificate2 leaf,
            List <X509Certificate2> candidates,
            List <X509Certificate2> downloaded,
            List <X509Certificate2> systemTrusted,
            OidCollection applicationPolicy,
            OidCollection certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            DateTime verificationTime,
            ref TimeSpan remainingDownloadTime)
        {
            X509ChainElement[]     elements;
            List <X509ChainStatus> overallStatus = new List <X509ChainStatus>();

            // An X509_STORE is more comparable to Cryptography.X509Certificate2Collection than to
            // Cryptography.X509Store. So read this with OpenSSL eyes, not CAPI/CNG eyes.
            //
            // (If you need to think of it as an X509Store, it's a volatile memory store)
            using (SafeX509StoreHandle store = Interop.libcrypto.X509_STORE_new())
                using (SafeX509StoreCtxHandle storeCtx = Interop.libcrypto.X509_STORE_CTX_new())
                {
                    Interop.Crypto.CheckValidOpenSslHandle(store);
                    Interop.Crypto.CheckValidOpenSslHandle(storeCtx);

                    bool lookupCrl = revocationMode != X509RevocationMode.NoCheck;

                    foreach (X509Certificate2 cert in candidates)
                    {
                        OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)cert.Pal;

                        if (!Interop.libcrypto.X509_STORE_add_cert(store, pal.SafeHandle))
                        {
                            throw Interop.Crypto.CreateOpenSslCryptographicException();
                        }

                        if (lookupCrl)
                        {
                            CrlCache.AddCrlForCertificate(
                                cert,
                                store,
                                revocationMode,
                                verificationTime,
                                ref remainingDownloadTime);

                            // If we only wanted the end-entity certificate CRL then don't look up
                            // any more of them.
                            lookupCrl = revocationFlag != X509RevocationFlag.EndCertificateOnly;
                        }
                    }

                    if (revocationMode != X509RevocationMode.NoCheck)
                    {
                        Interop.libcrypto.X509VerifyFlags vfyFlags = Interop.libcrypto.X509VerifyFlags.X509_V_FLAG_CRL_CHECK;

                        if (revocationFlag != X509RevocationFlag.EndCertificateOnly)
                        {
                            vfyFlags |= Interop.libcrypto.X509VerifyFlags.X509_V_FLAG_CRL_CHECK_ALL;
                        }

                        if (!Interop.libcrypto.X509_STORE_set_flags(store, vfyFlags))
                        {
                            throw Interop.Crypto.CreateOpenSslCryptographicException();
                        }
                    }

                    // When CRL checking support is added, it should be done before the call to
                    // X509_STORE_CTX_init (aka here) by calling X509_STORE_set_flags(store, flags);

                    SafeX509Handle leafHandle = ((OpenSslX509CertificateReader)leaf.Pal).SafeHandle;

                    if (!Interop.libcrypto.X509_STORE_CTX_init(storeCtx, store, leafHandle, IntPtr.Zero))
                    {
                        throw Interop.Crypto.CreateOpenSslCryptographicException();
                    }

                    Interop.Crypto.SetX509ChainVerifyTime(storeCtx, verificationTime);

                    int verify = Interop.libcrypto.X509_verify_cert(storeCtx);

                    if (verify < 0)
                    {
                        throw Interop.Crypto.CreateOpenSslCryptographicException();
                    }

                    using (SafeX509StackHandle chainStack = Interop.libcrypto.X509_STORE_CTX_get1_chain(storeCtx))
                    {
                        int chainSize  = Interop.Crypto.GetX509StackFieldCount(chainStack);
                        int errorDepth = -1;
                        Interop.libcrypto.X509VerifyStatusCode errorCode = 0;

                        if (verify == 0)
                        {
                            errorCode  = Interop.libcrypto.X509_STORE_CTX_get_error(storeCtx);
                            errorDepth = Interop.libcrypto.X509_STORE_CTX_get_error_depth(storeCtx);
                        }

                        elements = new X509ChainElement[chainSize];
                        int maybeRootDepth = chainSize - 1;

                        // The leaf cert is 0, up to (maybe) the root at chainSize - 1
                        for (int i = 0; i < chainSize; i++)
                        {
                            List <X509ChainStatus> status = new List <X509ChainStatus>();

                            if (i == errorDepth)
                            {
                                AddElementStatus(errorCode, status, overallStatus);
                            }

                            IntPtr elementCertPtr = Interop.Crypto.GetX509StackField(chainStack, i);

                            if (elementCertPtr == IntPtr.Zero)
                            {
                                throw Interop.Crypto.CreateOpenSslCryptographicException();
                            }

                            // Duplicate the certificate handle
                            X509Certificate2 elementCert = new X509Certificate2(elementCertPtr);

                            // If the last cert is self signed then it's the root cert, do any extra checks.
                            if (i == maybeRootDepth && IsSelfSigned(elementCert))
                            {
                                // If the root certificate was downloaded or the system
                                // doesn't trust it, it's untrusted.
                                if (downloaded.Contains(elementCert) ||
                                    !systemTrusted.Contains(elementCert))
                                {
                                    AddElementStatus(
                                        Interop.libcrypto.X509VerifyStatusCode.X509_V_ERR_CERT_UNTRUSTED,
                                        status,
                                        overallStatus);
                                }
                            }

                            elements[i] = new X509ChainElement(elementCert, status.ToArray(), "");
                        }
                    }
                }

            if ((certificatePolicy != null && certificatePolicy.Count > 0) ||
                (applicationPolicy != null && applicationPolicy.Count > 0))
            {
                List <X509Certificate2> certsToRead = new List <X509Certificate2>();

                foreach (X509ChainElement element in elements)
                {
                    certsToRead.Add(element.Certificate);
                }

                CertificatePolicyChain policyChain = new CertificatePolicyChain(certsToRead);

                bool failsPolicyChecks = false;

                if (certificatePolicy != null)
                {
                    if (!policyChain.MatchesCertificatePolicies(certificatePolicy))
                    {
                        failsPolicyChecks = true;
                    }
                }

                if (applicationPolicy != null)
                {
                    if (!policyChain.MatchesApplicationPolicies(applicationPolicy))
                    {
                        failsPolicyChecks = true;
                    }
                }

                if (failsPolicyChecks)
                {
                    X509ChainElement leafElement = elements[0];

                    X509ChainStatus chainStatus = new X509ChainStatus
                    {
                        Status            = X509ChainStatusFlags.InvalidPolicyConstraints,
                        StatusInformation = SR.Chain_NoPolicyMatch,
                    };

                    var elementStatus = new List <X509ChainStatus>(leafElement.ChainElementStatus.Length + 1);
                    elementStatus.AddRange(leafElement.ChainElementStatus);

                    AddUniqueStatus(elementStatus, ref chainStatus);
                    AddUniqueStatus(overallStatus, ref chainStatus);

                    elements[0] = new X509ChainElement(
                        leafElement.Certificate,
                        elementStatus.ToArray(),
                        leafElement.Information);
                }
            }

            return(new OpenSslX509ChainProcessor
            {
                ChainStatus = overallStatus.ToArray(),
                ChainElements = elements,
            });
        }
 public X509ChainStatus2(X509ChainStatus nativeStatus)
 {
     Status            = (X509ChainStatusFlags2)nativeStatus.Status;
     StatusInformation = nativeStatus.StatusInformation;
 }