|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Numerics;
namespace System.Security.Cryptography.X509Certificates
{
internal sealed partial class ChainPal : IDisposable, IChainPal
{
private static X509ChainStatus[] GetChainStatusInformation(CertTrustErrorStatus dwStatus)
{
if (dwStatus == CertTrustErrorStatus.CERT_TRUST_NO_ERROR)
return Array.Empty<X509ChainStatus>();
int count = BitOperations.PopCount((uint)dwStatus);
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 = mapping.Message;
chainStatus[index].Status = mapping.ChainStatusFlag;
index++;
dwStatus &= ~mapping.Win32Flag;
}
}
int shiftCount = 0;
for (uint bits = (uint)dwStatus; bits != 0; 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 readonly struct X509ChainErrorMapping
{
public readonly CertTrustErrorStatus Win32Flag;
public readonly int Win32ErrorCode;
public readonly X509ChainStatusFlags ChainStatusFlag;
public readonly string Message;
public X509ChainErrorMapping(CertTrustErrorStatus win32Flag, int win32ErrorCode, X509ChainStatusFlags chainStatusFlag)
{
Win32Flag = win32Flag;
Win32ErrorCode = win32ErrorCode;
ChainStatusFlag = chainStatusFlag;
Message = Interop.Kernel32.GetMessage(win32ErrorCode);
}
}
private static readonly X509ChainErrorMapping[] s_x509ChainErrorMappings = new[]
{
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_NOT_SIGNATURE_VALID, ErrorCode.TRUST_E_CERT_SIGNATURE, X509ChainStatusFlags.NotSignatureValid),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID, ErrorCode.TRUST_E_CERT_SIGNATURE, X509ChainStatusFlags.CtlNotSignatureValid),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_UNTRUSTED_ROOT, ErrorCode.CERT_E_UNTRUSTEDROOT, X509ChainStatusFlags.UntrustedRoot),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_PARTIAL_CHAIN, ErrorCode.CERT_E_CHAINING, X509ChainStatusFlags.PartialChain),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_REVOKED, ErrorCode.CRYPT_E_REVOKED, X509ChainStatusFlags.Revoked),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_NOT_VALID_FOR_USAGE, ErrorCode.CERT_E_WRONG_USAGE, X509ChainStatusFlags.NotValidForUsage),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE, ErrorCode.CERT_E_WRONG_USAGE, X509ChainStatusFlags.CtlNotValidForUsage),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_VALID, ErrorCode.CERT_E_EXPIRED, X509ChainStatusFlags.NotTimeValid),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_TIME_VALID, ErrorCode.CERT_E_EXPIRED, X509ChainStatusFlags.CtlNotTimeValid),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_INVALID_NAME_CONSTRAINTS, ErrorCode.CERT_E_INVALID_NAME, X509ChainStatusFlags.InvalidNameConstraints),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT, ErrorCode.CERT_E_INVALID_NAME, X509ChainStatusFlags.HasNotSupportedNameConstraint),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT, ErrorCode.CERT_E_INVALID_NAME, X509ChainStatusFlags.HasNotDefinedNameConstraint),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT, ErrorCode.CERT_E_INVALID_NAME, X509ChainStatusFlags.HasNotPermittedNameConstraint),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT, ErrorCode.CERT_E_INVALID_NAME, X509ChainStatusFlags.HasExcludedNameConstraint),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_INVALID_POLICY_CONSTRAINTS, ErrorCode.CERT_E_INVALID_POLICY, X509ChainStatusFlags.InvalidPolicyConstraints),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY, ErrorCode.CERT_E_INVALID_POLICY, X509ChainStatusFlags.NoIssuanceChainPolicy),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_INVALID_BASIC_CONSTRAINTS, ErrorCode.TRUST_E_BASIC_CONSTRAINTS, X509ChainStatusFlags.InvalidBasicConstraints),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_NESTED, ErrorCode.CERT_E_VALIDITYPERIODNESTING, X509ChainStatusFlags.NotTimeNested),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_REVOCATION_STATUS_UNKNOWN, ErrorCode.CRYPT_E_NO_REVOCATION_CHECK, X509ChainStatusFlags.RevocationStatusUnknown),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_OFFLINE_REVOCATION, ErrorCode.CRYPT_E_REVOCATION_OFFLINE, X509ChainStatusFlags.OfflineRevocation),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_IS_EXPLICIT_DISTRUST, ErrorCode.TRUST_E_EXPLICIT_DISTRUST, X509ChainStatusFlags.ExplicitDistrust),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT, ErrorCode.CERT_E_CRITICAL, X509ChainStatusFlags.HasNotSupportedCriticalExtension),
new X509ChainErrorMapping(CertTrustErrorStatus.CERT_TRUST_HAS_WEAK_SIGNATURE, ErrorCode.CERTSRV_E_WEAK_SIGNATURE_OR_KEY, X509ChainStatusFlags.HasWeakSignature),
};
}
}
|