Example #1
0
 internal X509ChainElement(X509Certificate2 certificate, X509ChainStatus[] chainElementStatus, String information)
 {
     Certificate = certificate;
     ChainElementStatus = chainElementStatus;
     Information = information;
     return;
 }
Example #2
0
		// this method avoid having a dependance on the order of status
		public void CheckChainStatus (X509ChainStatusFlags expected, X509ChainStatus[] status, string msg)
		{
			if ((expected == X509ChainStatusFlags.NoError) && (status.Length == 0))
				return;

			X509ChainStatusFlags actual = X509ChainStatusFlags.NoError;
			foreach (X509ChainStatus s in status) {
				actual |= s.Status;
			}
			Assert.AreEqual (expected, actual, msg);
		}
        private static string GetChainStatusInformation(X509ChainStatus[] chainStatus)
        {
            if (chainStatus != null)
            {
                StringBuilder error = new StringBuilder(128);
                for (int i = 0; i < chainStatus.Length; ++i)
                {
                    error.Append(chainStatus[i].StatusInformation);
                    error.Append(" ");
                }

                return error.ToString();
            }

            return string.Empty;
        }
        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;

            foreach (X509ChainErrorMapping mapping in s_x509ChainErrorMappings)
            {
                if ((dwStatus & mapping.Win32Flag) != 0)
                {
                    Debug.Assert(index < chainStatus.Length);

                    chainStatus[index].StatusInformation = GetSystemErrorString(mapping.Win32ErrorCode);
                    chainStatus[index].Status = mapping.ChainStatusFlag;
                    index++;
                    dwStatus &= ~mapping.Win32Flag;
                }
            }

            int shiftCount = 0;
            for (uint bits = (uint)dwStatus; bits != 0; bits = bits >> 1)
            {
                if ((bits & 0x1) != 0)
                {
                    Debug.Assert(index < chainStatus.Length);

                    chainStatus[index].Status = (X509ChainStatusFlags)(1 << shiftCount);
                    chainStatus[index].StatusInformation = SR.Unknown_Error;
                    index++;
                }
                shiftCount++;
            }

            Debug.Assert(index == chainStatus.Length);

            return chainStatus;
        }
        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:
                {
                    // 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 Windows 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);
                }

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

            return null;
        }
        private static void AddElementStatus(
            Interop.Crypto.X509VerifyStatusCode errorCode,
            List<X509ChainStatus> elementStatus,
            List<X509ChainStatus> overallStatus)
        {
            X509ChainStatusFlags statusFlag = MapVerifyErrorToChainStatus(errorCode);

            Debug.Assert(
                (statusFlag & (statusFlag - 1)) == 0,
                "Status flag has more than one bit set",
                "More than one bit is set in status '{0}' for error code '{1}'",
                statusFlag,
                errorCode);

            foreach (X509ChainStatus currentStatus in elementStatus)
            {
                if ((currentStatus.Status & statusFlag) != 0)
                {
                    return;
                }
            }

            X509ChainStatus chainStatus = new X509ChainStatus
            {
                Status = statusFlag,
                StatusInformation = Interop.Crypto.GetX509VerifyCertErrorString(errorCode),
            };

            elementStatus.Add(chainStatus);
            AddUniqueStatus(overallStatus, ref chainStatus);
        }
        public static IChainPal BuildChain(
            X509Certificate2 leaf,
            HashSet<X509Certificate2> candidates,
            HashSet<X509Certificate2> downloaded,
            HashSet<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.NotValidForUsage,
                        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,
            };
        }
Example #8
0
            internal void Evaluate(
                DateTime verificationTime,
                OidCollection?applicationPolicy,
                OidCollection?certificatePolicy,
                X509RevocationMode revocationMode,
                X509RevocationFlag revocationFlag)
            {
                Debug.Assert(_chainContext != null);

                long timeInMsFromUnixEpoch = new DateTimeOffset(verificationTime).ToUnixTimeMilliseconds();

                _isValid = Interop.AndroidCrypto.X509ChainBuild(_chainContext, timeInMsFromUnixEpoch);
                if (!_isValid)
                {
                    // Android always validates name, time, signature, and trusted root.
                    // There is no way bypass that validation and build a path.
                    ChainElements = Array.Empty <X509ChainElement>();

                    Interop.AndroidCrypto.ValidationError[] errors = Interop.AndroidCrypto.X509ChainGetErrors(_chainContext);
                    var chainStatus = new X509ChainStatus[errors.Length];
                    for (int i = 0; i < errors.Length; i++)
                    {
                        Interop.AndroidCrypto.ValidationError error = errors[i];
                        chainStatus[i] = ValidationErrorToChainStatus(error);
                        Marshal.FreeHGlobal(error.Message);
                    }

                    ChainStatus = chainStatus;
                    return;
                }

                byte checkedRevocation;
                int  res = Interop.AndroidCrypto.X509ChainValidate(_chainContext, revocationMode, revocationFlag, out checkedRevocation);

                if (res != 1)
                {
                    throw new CryptographicException();
                }

                X509Certificate2[]     certs         = Interop.AndroidCrypto.X509ChainGetCertificates(_chainContext);
                List <X509ChainStatus> overallStatus = new List <X509ChainStatus>();

                List <X509ChainStatus>[] statuses = new List <X509ChainStatus> [certs.Length];

                // Android will stop checking after the first error it hits, so we track the first
                // instances of revocation and non-revocation errors to fix-up the status of elements
                // beyond the first error
                int firstNonRevocationErrorIndex = -1;
                int firstRevocationErrorIndex    = -1;
                Dictionary <int, List <X509ChainStatus> > errorsByIndex = GetStatusByIndex(_chainContext);

                foreach (int index in errorsByIndex.Keys)
                {
                    List <X509ChainStatus> errors = errorsByIndex[index];
                    for (int i = 0; i < errors.Count; i++)
                    {
                        X509ChainStatus status = errors[i];
                        AddUniqueStatus(overallStatus, ref status);
                    }

                    // -1 indicates that error is not tied to a specific index
                    if (index != -1)
                    {
                        statuses[index] = errorsByIndex[index];
                        if (errorsByIndex[index].Exists(s => s.Status == X509ChainStatusFlags.Revoked || s.Status == X509ChainStatusFlags.RevocationStatusUnknown))
                        {
                            firstRevocationErrorIndex = Math.Max(index, firstRevocationErrorIndex);
                        }
                        else
                        {
                            firstNonRevocationErrorIndex = Math.Max(index, firstNonRevocationErrorIndex);
                        }
                    }
                }

                if (firstNonRevocationErrorIndex > 0)
                {
                    // Assign PartialChain to everything from the first non-revocation error to the end certificate
                    X509ChainStatus partialChainStatus = new X509ChainStatus
                    {
                        Status            = X509ChainStatusFlags.PartialChain,
                        StatusInformation = SR.Chain_PartialChain,
                    };
                    AddStatusFromIndexToEndCertificate(firstNonRevocationErrorIndex - 1, ref partialChainStatus, statuses, overallStatus);
                }

                if (firstRevocationErrorIndex > 0)
                {
                    // Assign RevocationStatusUnknown to everything from the first revocation error to the end certificate
                    X509ChainStatus revocationUnknownStatus = new X509ChainStatus
                    {
                        Status            = X509ChainStatusFlags.RevocationStatusUnknown,
                        StatusInformation = SR.Chain_RevocationStatusUnknown,
                    };
                    AddStatusFromIndexToEndCertificate(firstRevocationErrorIndex - 1, ref revocationUnknownStatus, statuses, overallStatus);
                }

                if (revocationMode != X509RevocationMode.NoCheck && checkedRevocation == 0)
                {
                    // Revocation checking was requested, but not performed (due to basic validation failing)
                    // Assign RevocationStatusUnknown to everything
                    X509ChainStatus revocationUnknownStatus = new X509ChainStatus
                    {
                        Status            = X509ChainStatusFlags.RevocationStatusUnknown,
                        StatusInformation = SR.Chain_RevocationStatusUnknown,
                    };
                    AddStatusFromIndexToEndCertificate(statuses.Length - 1, ref revocationUnknownStatus, statuses, overallStatus);
                }

                if (!IsPolicyMatch(certs, applicationPolicy, certificatePolicy))
                {
                    // Assign NotValidForUsage to everything
                    X509ChainStatus policyFailStatus = new X509ChainStatus
                    {
                        Status            = X509ChainStatusFlags.NotValidForUsage,
                        StatusInformation = SR.Chain_NoPolicyMatch,
                    };
                    AddStatusFromIndexToEndCertificate(statuses.Length - 1, ref policyFailStatus, statuses, overallStatus);
                }

                X509ChainElement[] elements = new X509ChainElement[certs.Length];
                for (int i = 0; i < certs.Length; i++)
                {
                    X509ChainStatus[] elementStatus = statuses[i] == null?Array.Empty <X509ChainStatus>() : statuses[i].ToArray();

                    elements[i] = new X509ChainElement(certs[i], elementStatus, string.Empty);
                }

                ChainElements = elements;
                ChainStatus   = overallStatus.ToArray();
            }
        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.libcrypto.CheckValidOpenSslHandle(store);
                Interop.libcrypto.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.libcrypto.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.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.Crypto.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.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.libcrypto.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,
            };
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="X509ChainElementWrap"/> class.
 /// </summary>
 /// <param name="certificate">
 /// The certificate.
 /// </param>
 /// <param name="chainElementStatus">
 /// The error status of the current X.509 certificate in a chain.
 /// </param>
 public X509ChainElementWrap(IX509Certificate certificate,
                             X509ChainStatus[] chainElementStatus)
 {
     this.Certificate = certificate;
     this.ChainElementStatus = chainElementStatus;
 }
Example #11
0
        internal static X509ChainStatus[] GetChainStatusInformation (uint dwStatus) {
            if (dwStatus == 0)
                return new X509ChainStatus[0];

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

            X509ChainStatus[] chainStatus = new X509ChainStatus[count];

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return chainStatus;
        }
Example #12
0
        /// <summary>
        /// Validates the time-stamp token in case of arbitration or with a specified trusted time.
        /// </summary>
        /// <param name="tst"></param>
        /// <param name="crls"></param>
        /// <param name="ocsps"></param>
        /// <param name="trustedTime">The trusted time, <c>null</c> for the current time in case of Arbitration</param>
        /// <returns>The validation chain of the signing certificate</returns>
        /// <exception cref="InvalidTokenException">When the token isn't signed by the indicated certificate</exception>
        public static Timestamp Validate(this TimeStampToken tst, ref IList<CertificateList> crls, ref IList<BasicOcspResponse> ocsps, DateTime? trustedTime)
        {
            var value = new Timestamp();
            value.TimestampStatus = new List<X509ChainStatus>();

            //check if the indicated certificate is the signer
            BC::X509Certificate signerBc = tst.GetSigner();
            if (signerBc == null)
            {
                trace.TraceEvent(TraceEventType.Warning, 0, "The signer of the time-stamp {0} isn't found", tst.TimeStampInfo.SerialNumber);
                X509ChainStatus status = new X509ChainStatus();
                status.Status = X509ChainStatusFlags.NotSignatureValid;
                status.StatusInformation = "Signer not found";
                X509CertificateHelper.AddErrorStatus(value.TimestampStatus, status);
            }
            else
            {
                try
                {
                    tst.Validate(signerBc);
                }
                catch (Exception e)
                {
                    trace.TraceEvent(TraceEventType.Warning, 0, "The signature from {1} of the time-stamp {0} is invalid: {2}", tst.TimeStampInfo.SerialNumber, signerBc.SubjectDN, e.Message);
                    X509ChainStatus status = new X509ChainStatus();
                    status.Status = X509ChainStatusFlags.NotSignatureValid;
                    status.StatusInformation = "Time-stamp not signed by indicated certificate: " + e.Message;
                    X509CertificateHelper.AddErrorStatus(value.TimestampStatus, status);
                }
            }

            //Get some info
            DateTime now = DateTime.UtcNow;
            value.Time = tst.TimeStampInfo.GenTime;
            //allow for some clock skewness
            DateTime signingTime = value.Time > now && (value.Time - ClockSkewness) < now  ? now : value.Time;
            DateTime validationTime = trustedTime != null ? trustedTime.Value : signingTime;
            var extraStore = new X509Certificate2Collection();
            foreach (Org.BouncyCastle.X509.X509Certificate cert in tst.GetCertificates("Collection").GetMatches(null))
            {
                extraStore.Add(new X509Certificate2(cert.GetEncoded()));
            }

            //Check the chain
            value.CertificateChain = (new X509Certificate2(signerBc.GetEncoded())).BuildChain(signingTime, extraStore, ref crls, ref ocsps, validationTime); //we assume time-stamp signers aren't suspended, only permanently revoked

            //get the renewal time
            value.RenewalTime = DateTime.MaxValue;
            foreach (ChainElement chainE in value.CertificateChain.ChainElements)
            {
                if (chainE.Certificate.NotAfter < value.RenewalTime)
                {
                    value.RenewalTime = chainE.Certificate.NotAfter;
                }
            }

            //check if the certificate may be used for time-stamping
            IList signerExtKeyUsage = signerBc.GetExtendedKeyUsage();
            if (!signerExtKeyUsage.Contains("1.3.6.1.5.5.7.3.8"))
            {
                trace.TraceEvent(TraceEventType.Warning, 0, "The signer {1} of the time-stamp {0} isn't allowed to sign timestamps", tst.TimeStampInfo.SerialNumber, signerBc.SubjectDN);
                X509ChainStatus status = new X509ChainStatus();
                status.Status = X509ChainStatusFlags.NotValidForUsage;
                status.StatusInformation = "The certificate may not be used for timestamps";

                X509CertificateHelper.AddErrorStatus(value.TimestampStatus, status);
            }

            if (value.TimestampStatus.Count == 0) {
                X509ChainStatus status = new X509ChainStatus();
                status.Status = X509ChainStatusFlags.NoError;
                value.TimestampStatus.Add(status);
            }
            return value;
        }
 private static string GetChainStatusInformation(X509ChainStatus[] chainStatus)
 {
     if (chainStatus == null)
     {
         return string.Empty;
     }
     StringBuilder builder = new StringBuilder(0x80);
     for (int i = 0; i < chainStatus.Length; i++)
     {
         builder.Append(chainStatus[i].StatusInformation);
         builder.Append(" ");
     }
     return builder.ToString();
 }
        private static void AddUniqueStatus(IList<X509ChainStatus> list, ref X509ChainStatus status)
        {
            X509ChainStatusFlags statusCode = status.Status;

            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].Status == statusCode)
                {
                    return;
                }
            }

            list.Add(status);
        }
Example #15
0
        internal static X509ChainStatus[] GetChainStatusInformation (uint dwStatus) {
            if (dwStatus == 0)
                return new X509ChainStatus[0];

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

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

            foreach (X509ChainErrorMapping mapping in s_x509ChainErrorMappings)
            {
                if ((dwStatus & mapping.Win32Flag) != 0)
                {
                    Debug.Assert(index < chainStatus.Length);

                    chainStatus[index].StatusInformation = X509Utils.GetSystemErrorString(mapping.Win32ErrorCode);
                    chainStatus[index].Status = mapping.ChainStatusFlag;
                    index++;
                    dwStatus &= ~mapping.Win32Flag;
                }
            }

            int shiftCount = 0;
            for (uint bits = dwStatus; bits != 0; bits = bits >> 1) {
                if ((bits & 0x1) != 0) {
                    Debug.Assert(index < chainStatus.Length);

                    chainStatus[index].Status = (X509ChainStatusFlags) (1 << shiftCount);
                    chainStatus[index].StatusInformation = SR.GetString(SR.Unknown_Error);
                    index++;
                }
                shiftCount++;
            }

            Debug.Assert(index == chainStatus.Length);

            return chainStatus;
        }
        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.Crypto.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.Crypto.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.Crypto.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,
            };
        }
 internal static X509ChainStatus[] GetChainStatusInformation(uint dwStatus)
 {
     if (dwStatus == 0)
     {
         return new X509ChainStatus[0];
     }
     int num = 0;
     for (uint i = dwStatus; i != 0; i = i >> 1)
     {
         if ((i & 1) != 0)
         {
             num++;
         }
     }
     X509ChainStatus[] statusArray = new X509ChainStatus[num];
     int index = 0;
     if ((dwStatus & 8) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146869244);
         statusArray[index].Status = X509ChainStatusFlags.NotSignatureValid;
         index++;
         dwStatus &= 0xfffffff7;
     }
     if ((dwStatus & 0x40000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146869244);
         statusArray[index].Status = X509ChainStatusFlags.CtlNotSignatureValid;
         index++;
         dwStatus &= 0xfffbffff;
     }
     if ((dwStatus & 0x20) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762487);
         statusArray[index].Status = X509ChainStatusFlags.UntrustedRoot;
         index++;
         dwStatus &= 0xffffffdf;
     }
     if ((dwStatus & 0x10000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762486);
         statusArray[index].Status = X509ChainStatusFlags.PartialChain;
         index++;
         dwStatus &= 0xfffeffff;
     }
     if ((dwStatus & 4) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146885616);
         statusArray[index].Status = X509ChainStatusFlags.Revoked;
         index++;
         dwStatus &= 0xfffffffb;
     }
     if ((dwStatus & 0x10) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762480);
         statusArray[index].Status = X509ChainStatusFlags.NotValidForUsage;
         index++;
         dwStatus &= 0xffffffef;
     }
     if ((dwStatus & 0x80000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762480);
         statusArray[index].Status = X509ChainStatusFlags.CtlNotValidForUsage;
         index++;
         dwStatus &= 0xfff7ffff;
     }
     if ((dwStatus & 1) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762495);
         statusArray[index].Status = X509ChainStatusFlags.NotTimeValid;
         index++;
         dwStatus &= 0xfffffffe;
     }
     if ((dwStatus & 0x20000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762495);
         statusArray[index].Status = X509ChainStatusFlags.CtlNotTimeValid;
         index++;
         dwStatus &= 0xfffdffff;
     }
     if ((dwStatus & 0x800) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762476);
         statusArray[index].Status = X509ChainStatusFlags.InvalidNameConstraints;
         index++;
         dwStatus &= 0xfffff7ff;
     }
     if ((dwStatus & 0x1000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762476);
         statusArray[index].Status = X509ChainStatusFlags.HasNotSupportedNameConstraint;
         index++;
         dwStatus &= 0xffffefff;
     }
     if ((dwStatus & 0x2000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762476);
         statusArray[index].Status = X509ChainStatusFlags.HasNotDefinedNameConstraint;
         index++;
         dwStatus &= 0xffffdfff;
     }
     if ((dwStatus & 0x4000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762476);
         statusArray[index].Status = X509ChainStatusFlags.HasNotPermittedNameConstraint;
         index++;
         dwStatus &= 0xffffbfff;
     }
     if ((dwStatus & 0x8000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762476);
         statusArray[index].Status = X509ChainStatusFlags.HasExcludedNameConstraint;
         index++;
         dwStatus &= 0xffff7fff;
     }
     if ((dwStatus & 0x200) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762477);
         statusArray[index].Status = X509ChainStatusFlags.InvalidPolicyConstraints;
         index++;
         dwStatus &= 0xfffffdff;
     }
     if ((dwStatus & 0x2000000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762477);
         statusArray[index].Status = X509ChainStatusFlags.NoIssuanceChainPolicy;
         index++;
         dwStatus &= 0xfdffffff;
     }
     if ((dwStatus & 0x400) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146869223);
         statusArray[index].Status = X509ChainStatusFlags.InvalidBasicConstraints;
         index++;
         dwStatus &= 0xfffffbff;
     }
     if ((dwStatus & 2) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146762494);
         statusArray[index].Status = X509ChainStatusFlags.NotTimeNested;
         index++;
         dwStatus &= 0xfffffffd;
     }
     if ((dwStatus & 0x40) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146885614);
         statusArray[index].Status = X509ChainStatusFlags.RevocationStatusUnknown;
         index++;
         dwStatus &= 0xffffffbf;
     }
     if ((dwStatus & 0x1000000) != 0)
     {
         statusArray[index].StatusInformation = System.Security.Cryptography.X509Certificates.X509Utils.GetSystemErrorString(-2146885613);
         statusArray[index].Status = X509ChainStatusFlags.OfflineRevocation;
         index++;
         dwStatus &= 0xfeffffff;
     }
     int num4 = 0;
     for (uint j = dwStatus; j != 0; j = j >> 1)
     {
         if ((j & 1) != 0)
         {
             statusArray[index].Status = (X509ChainStatusFlags) (((int) 1) << num4);
             statusArray[index].StatusInformation = SR.GetString("Unknown_Error");
             index++;
         }
         num4++;
     }
     return statusArray;
 }
Example #18
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++;
			}
		}
Example #19
0
        internal static X509ChainStatus[] GetChainStatusInformation(uint dwStatus)
        {
            if (dwStatus == 0)
            {
                return(new X509ChainStatus[0]);
            }

            int count = 0;

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

            X509ChainStatus[] chainStatus = new X509ChainStatus[count];

            int index = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            int shiftCount = 0;

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

            return(chainStatus);
        }