internal X509ChainElement(X509Certificate2 certificate, X509ChainStatus[] chainElementStatus, String information) { Certificate = certificate; ChainElementStatus = chainElementStatus; Information = information; return; }
// 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, }; }
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; }
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; }
/// <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); }
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; }
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++; } }
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); }