public RuleResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature, deep: true); var result = RuleResult.Pass; foreach (var signature in signatures) { if (signature.DigestAlgorithm.Value == KnownOids.MD2) { verboseWriter.LogSignatureMessage(signature, $"Uses the {nameof(KnownOids.MD2)} digest algorithm."); result = RuleResult.Fail; } else if (signature.DigestAlgorithm.Value == KnownOids.MD4) { verboseWriter.LogSignatureMessage(signature, $"Uses the {nameof(KnownOids.MD4)} digest algorithm."); result = RuleResult.Fail; } else if (signature.DigestAlgorithm.Value == KnownOids.MD5) { verboseWriter.LogSignatureMessage(signature, $"Uses the {nameof(KnownOids.MD5)} digest algorithm."); result = RuleResult.Fail; } } return(result); }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature, deep: true); var result = TestResult.Pass; foreach (var signature in signatures) { var certificates = signature.AdditionalCertificates; using (var chain = new X509Chain()) { chain.ChainPolicy.ExtraStore.AddRange(certificates); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; //The purpose of this check is not to validate the chain, completely. //The chain is needed so we know which certificate is the root and intermediates so we know which to validate and which not to validate. //It is possible to have a valid Authenticode signature if the certificate is expired but was //timestamped while it was valid. In this case we still want to successfully build a chain to perform validation. chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid; bool success = chain.Build(signature.Certificate); if (!success) { verboseWriter.LogSignatureMessage(signature, $"Cannot build a chain successfully with signing certificate {signature.Certificate.SerialNumber}."); result = TestResult.Fail; continue; } if (!ValidateChain(signature, chain, verboseWriter)) { result = TestResult.Fail; } } } return(result); }
public RuleResult Validate(IReadOnlyList <ISignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.Any | SignatureKind.Deep); var result = RuleResult.Pass; foreach (var signature in signatures) { var keyInfo = BitStrengthCalculator.CalculateStrength(signature.Certificate); switch (keyInfo.AlgorithmName) { case PublicKeyAlgorithm.ECDSA: if (keyInfo.BitSize == null) { verboseWriter.LogSignatureMessage(signature, "Signature uses ECDSA with an unknown curve."); result = RuleResult.Fail; } else if (keyInfo.BitSize > MAX_ECDSA_KEY_SIZE) { verboseWriter.LogSignatureMessage(signature, $"Signature uses ECDSA signature with a key size of {keyInfo.BitSize} exeeding maximum size of {MAX_ECDSA_KEY_SIZE}."); result = RuleResult.Fail; } break; case PublicKeyAlgorithm.RSA: if (keyInfo.BitSize == null) { verboseWriter.LogSignatureMessage(signature, "Signature has an unknown RSA key size."); result = RuleResult.Fail; } else if (keyInfo.BitSize > MAX_RSA_KEY_SIZE) { verboseWriter.LogSignatureMessage(signature, $"Signature uses RSA signature with a key size of {keyInfo.BitSize} exeeding maximum size of {MAX_RSA_KEY_SIZE}."); result = RuleResult.Fail; } break; case PublicKeyAlgorithm.DSA: if (keyInfo.BitSize == null) { verboseWriter.LogSignatureMessage(signature, "Signature has an unknown DSA key size."); result = RuleResult.Fail; } else if (keyInfo.BitSize > MAX_DSA_KEY_SIZE) { verboseWriter.LogSignatureMessage(signature, $"Signature uses DSA signature with a key size of {keyInfo.BitSize} exeeding maximum size of {MAX_DSA_KEY_SIZE}."); result = RuleResult.Fail; } break; case PublicKeyAlgorithm.Other: goto default; default: verboseWriter.LogSignatureMessage(signature, $"Signature uses an unknown algorithm."); result = RuleResult.Fail; break; } } return(result); }
public RuleResult Validate(IReadOnlyList <ISignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); var result = RuleResult.Pass; foreach (var signature in signatures) { var counterSignatures = signature.VisitAll(SignatureKind.AnyCounterSignature); foreach (var counterSignature in counterSignatures) { foreach (var attribute in counterSignature.UnsignedAttributes) { if (!_trustedUnsignedAttributes.Contains(attribute.Oid.Value)) { result = RuleResult.Fail; var displayName = attribute.Oid.FriendlyName ?? "<no friendly name>"; verboseWriter.LogSignatureMessage(signature, $"Signature contains counter signer with unknown unsigned attribute {displayName} ({attribute.Oid.Value})."); } } } foreach (var attribute in signature.UnsignedAttributes) { if (!_trustedUnsignedAttributes.Contains(attribute.Oid.Value)) { result = RuleResult.Fail; var displayName = attribute.Oid.FriendlyName ?? "<no friendly name>"; verboseWriter.LogSignatureMessage(signature, $"Signature contains unknown unsigned attribute {displayName} ({attribute.Oid.Value})."); } } } return(result); }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); var pass = false; foreach (var signature in signatures) { string serialNumber = ""; string KU = ""; Boolean KUCritical = false; int KU_extension = 0; string thumbprint = signature.Certificate.Thumbprint; serialNumber = signature.Certificate.SerialNumber; X509ExtensionCollection extensions = signature.Certificate.Extensions; foreach (X509Extension extension in extensions) { //extension.Oid.FriendlyName Console.WriteLine(extension.Oid.FriendlyName + "(" + extension.Oid.Value + ")"); if (extension.Oid.FriendlyName == "Key Usage") { X509KeyUsageExtension ext = (X509KeyUsageExtension)extension; KUCritical = ext.Critical; KU = ext.KeyUsages.ToString(); Console.WriteLine(KU); KU_extension++; } } if (KU_extension == 1) { if (KUCritical) { verboseWriter.LogSignatureMessage(signature, "Key Usage extension is marked critical."); pass = true; } else { verboseWriter.LogSignatureMessage(signature, "Key Usage extension is not marked critical."); pass = false; } } else if (KU_extension == 0) { verboseWriter.LogSignatureMessage(signature, "Signature does not have Key Usage extension."); pass = false; } else if (KU_extension > 1) { verboseWriter.LogSignatureMessage(signature, "Signature has duplicate Key Usage extension."); pass = false; } } return(pass ? TestResult.Pass : TestResult.Fail); }
public RuleResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.Any | SignatureKind.Any); var result = RuleResult.Pass; foreach (var signature in signatures) { var keyInfo = BitStrengthCalculator.CalculateStrength(signature.Certificate); switch (keyInfo.AlgorithmName) { case PublicKeyAlgorithm.ECDSA when keyInfo.BitSize is null: verboseWriter.LogSignatureMessage(signature, "Signature uses ECDSA with an unknown curve."); result = RuleResult.Fail; break; case PublicKeyAlgorithm.ECDSA when keyInfo.BitSize < MIN_ECDSA_KEY_SIZE: verboseWriter.LogSignatureMessage(signature, $"Signature uses a ECDSA key of size {keyInfo.BitSize} which is below the recommended {MIN_ECDSA_KEY_SIZE}."); result = RuleResult.Fail; break; case PublicKeyAlgorithm.ECDSA: break; case PublicKeyAlgorithm.RSA when keyInfo.BitSize is null: verboseWriter.LogSignatureMessage(signature, "Signature has an unknown RSA key size."); result = RuleResult.Fail; break; case PublicKeyAlgorithm.RSA when keyInfo.BitSize < MIN_RSADSA_KEY_SIZE: verboseWriter.LogSignatureMessage(signature, $"Signature uses a RSA key of size {keyInfo.BitSize} which is below the recommended {MIN_RSADSA_KEY_SIZE}."); result = RuleResult.Fail; break; case PublicKeyAlgorithm.RSA when keyInfo.BitSize >= MIN_RSADSA_KEY_SIZE: break; case PublicKeyAlgorithm.DSA when keyInfo.BitSize is null: verboseWriter.LogSignatureMessage(signature, "Signature has an unknown DSA key size."); result = RuleResult.Fail; break; case PublicKeyAlgorithm.DSA when keyInfo.BitSize < MIN_RSADSA_KEY_SIZE: //Effectively, 1024 is the max for a DSA key, so this will likely always fail. verboseWriter.LogSignatureMessage(signature, $"Signature uses a DSA key of size {keyInfo.BitSize} which is below the recommended {MIN_RSADSA_KEY_SIZE}."); result = RuleResult.Fail; break; case PublicKeyAlgorithm.DSA: break; default: verboseWriter.LogSignatureMessage(signature, $"Signature uses an unknown algorithm."); result = RuleResult.Fail; break; } } return(result); }
public RuleResult Validate(IReadOnlyList <ISignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.Any | SignatureKind.Any); var result = RuleResult.Pass; foreach (var signature in signatures) { var keyInfo = BitStrengthCalculator.CalculateStrength(signature.Certificate); switch (keyInfo.AlgorithmName) { case PublicKeyAlgorithm.ECDSA: if (keyInfo.BitSize == null) { verboseWriter.LogSignatureMessage(signature, "Signature uses ECDSA with an unknown curve."); result = RuleResult.Fail; } //We don't actually check the key size for ECDSA since all known values are acceptable. break; case PublicKeyAlgorithm.RSA: if (keyInfo.BitSize == null) { verboseWriter.LogSignatureMessage(signature, "Signature has an unknown RSA key size."); result = RuleResult.Fail; } else if (keyInfo.BitSize < MIN_RSADSA_KEY_SIZE) { verboseWriter.LogSignatureMessage(signature, $"Signature uses a RSA key of size {keyInfo.BitSize} which is below the recommended {MIN_RSADSA_KEY_SIZE}."); result = RuleResult.Fail; } break; case PublicKeyAlgorithm.DSA: if (keyInfo.BitSize == null) { verboseWriter.LogSignatureMessage(signature, "Signature has an unknown DSA key size."); result = RuleResult.Fail; } else if (keyInfo.BitSize < MIN_RSADSA_KEY_SIZE) { //Effectively, 1024 is the max for a DSA key, so this will likely always fail. verboseWriter.LogSignatureMessage(signature, $"Signature uses a DSA key of size {keyInfo.BitSize} which is below the recommended {MIN_RSADSA_KEY_SIZE}."); result = RuleResult.Fail; } break; case PublicKeyAlgorithm.Other: goto default; default: verboseWriter.LogSignatureMessage(signature, $"Signature uses an unknown algorithm."); result = RuleResult.Fail; break; } } return(result); }
public RuleResult Validate(string file, SignatureLogger verboseWriter, CheckConfiguration configuration) { var padding = CertificatePaddingExtractor.ExtractPadding(file); if (padding?.Any(p => p != 0) == true) { verboseWriter.LogMessage($"Non-zero data found after PKCS#7 structure: {Convert.ToBase64String(padding)}."); return(RuleResult.Fail); } return(RuleResult.Pass); }
public RuleResult Validate(string file, SignatureLogger verboseWriter, CheckConfiguration configuration) { var inspector = new FileInspector(file); var result = inspector.Validate(configuration.RevocationMode); if (result == SignatureCheckResult.Valid) { return(RuleResult.Pass); } verboseWriter.LogMessage($"Authenticode signature validation failed with '{result}'."); return(RuleResult.Fail); }
public RuleResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); if (signatures.Any(s => s.DigestAlgorithm.Value == KnownOids.SHA256 || s.DigestAlgorithm.Value == KnownOids.SHA384 || s.DigestAlgorithm.Value == KnownOids.SHA512)) { return(RuleResult.Pass); } return(RuleResult.Fail); }
public RuleResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { if (graph.Count == 0) { return(RuleResult.Fail); } if (graph.Count > 1) { verboseWriter.LogMessage("Multiple primary signatures exist."); return(RuleResult.Fail); } return(RuleResult.Pass); }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); int AIA_extension = 0; Boolean AIACritical = false; string authorityInformationAccess = ""; var pass = false; foreach (var signature in signatures) { string serialNumber = ""; AIA_extension = 0; AIACritical = false; authorityInformationAccess = ""; string thumbprint = signature.Certificate.Thumbprint; var digestStr = HashHelpers.GetHashForSignature(signature);//message digest of siganture(signature->details->advance->msg digest) serialNumber = signature.Certificate.SerialNumber; X509ExtensionCollection extensions = signature.Certificate.Extensions; foreach (X509Extension extension in extensions) { /*This extension MUST be present and MUST NOT be marked critical. * The extension MUST contain the HTTP URL of the CA’s OCSP responder (accessMethod = 1.3.6.1.5.5.7.48.1) * and the HTTP URL for the Root CA’s certificate (accessMethod = 1.3.6.1.5.5.7.48.2).*/ if (extension.Oid.FriendlyName == "Authority Information Access") { if (AIA_extension != 0) { authorityInformationAccess = extension.Format(true); AIACritical = extension.Critical; } Console.WriteLine(authorityInformationAccess); } } if (authorityInformationAccess != "" && authorityInformationAccess.Contains("http://") && !AIACritical) { verboseWriter.LogSignatureMessage(signature, "Signature has properly provided OCSP distribution point."); pass = true; } else { verboseWriter.LogSignatureMessage(signature, "Signature has not properly provided OCSP distribution point."); pass = false; } } return(pass ? TestResult.Pass : TestResult.Fail); }
public RuleResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { if (graph.Count == 0) { return(RuleResult.Fail); } var primary = graph[0]; if (primary.DigestAlgorithm.Value != KnownOids.SHA1) { verboseWriter.LogSignatureMessage(primary, $"Expected {nameof(KnownOids.SHA1)} digest algorithm but is {primary.DigestAlgorithm.FriendlyName}."); return(RuleResult.Fail); } return(RuleResult.Pass); }
public RuleResult Validate(IReadOnlyList <ISignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature | SignatureKind.Deep); var result = RuleResult.Pass; foreach (var signature in signatures) { PublisherInformation info = null; foreach (var attribute in signature.SignedAttributes) { if (attribute.Oid.Value == KnownOids.OpusInfo) { info = new PublisherInformation(attribute.Values[0]); break; } } if (info == null) { result = RuleResult.Fail; verboseWriter.LogSignatureMessage(signature, "Signature does not have any publisher information."); } else { if (string.IsNullOrWhiteSpace(info.Description)) { result = RuleResult.Fail; verboseWriter.LogSignatureMessage(signature, "Signature does not have an accompanying description."); } if (string.IsNullOrWhiteSpace(info.UrlLink)) { result = RuleResult.Fail; verboseWriter.LogSignatureMessage(signature, "Signature does not have an accompanying URL."); } else { Uri uri; if (!Uri.TryCreate(info.UrlLink, UriKind.Absolute, out uri)) { result = RuleResult.Fail; verboseWriter.LogSignatureMessage(signature, "Signature's accompanying URL is not a valid URI."); } } } } return(result); }
public unsafe RuleResult Validate(string file, SignatureLogger verboseWriter, CheckConfiguration configuration) { var pathPtr = Marshal.StringToHGlobalUni(file); try { var flags = WinTrustProviderFlags.NONE; var revocationFlags = WinTrustRevocationChecks.WTD_REVOKE_NONE; switch (configuration.RevocationMode) { case RevocationChecking.None: flags |= WinTrustProviderFlags.WTD_REVOCATION_CHECK_NONE; break; case RevocationChecking.Offline: flags |= WinTrustProviderFlags.WTD_CACHE_ONLY_URL_RETRIEVAL; goto default; default: flags |= WinTrustProviderFlags.WTD_REVOCATION_CHECK_CHAIN; revocationFlags |= WinTrustRevocationChecks.WTD_REVOKE_WHOLECHAIN; break; } var trust = stackalloc WINTRUST_DATA[1]; var fileInfo = stackalloc WINTRUST_FILE_INFO[1]; trust->cbStruct = (uint)Marshal.SizeOf <WINTRUST_DATA>(); trust->dwProvFlags = flags; trust->dwStateAction = WinTrustStateAction.WTD_STATEACTION_IGNORE; trust->dwUIChoice = WinTrustDataUIChoice.WTD_UI_NONE; trust->dwUIContext = WinTrustUIContext.WTD_UICONTEXT_EXECUTE; trust->dwUnionChoice = WinTrustUnionChoice.WTD_CHOICE_FILE; trust->fdwRevocationChecks = revocationFlags; trust->trustUnion = new WINTRUST_DATA_UNION(); trust->trustUnion.pFile = fileInfo; trust->trustUnion.pFile->cbStruct = (uint)Marshal.SizeOf <WINTRUST_FILE_INFO>(); trust->trustUnion.pFile->pcwszFilePath = pathPtr; if (Wintrust.WinVerifyTrustEx(new IntPtr(-1), KnownGuids.WINTRUST_ACTION_GENERIC_VERIFY_V2, trust) == 0) { return(RuleResult.Pass); } return(RuleResult.Fail); } finally { Marshal.FreeHGlobal(pathPtr); } }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); var pass = false; foreach (var signature in signatures) { string serialNumber = ""; string certificatePolicies = ""; Boolean CPCritical = false; int certificatePolicies_extension = 0; string thumbprint = signature.Certificate.Thumbprint; serialNumber = signature.Certificate.SerialNumber; X509ExtensionCollection extensions = signature.Certificate.Extensions; foreach (X509Extension extension in extensions) { //extension.Oid.FriendlyName Console.WriteLine(extension.Oid.FriendlyName + "(" + extension.Oid.Value + ")"); if (extension.Oid.FriendlyName == "Certificate Policies") { certificatePolicies_extension = 1; certificatePolicies = extension.Format(true); CPCritical = extension.Critical; Console.WriteLine(certificatePolicies); } } if (certificatePolicies_extension == 1) { verboseWriter.LogSignatureMessage(signature, "has certificate policies extension."); pass = true; } else { verboseWriter.LogSignatureMessage(signature, "does not have certificate policies extension."); pass = false; } } return(pass ? TestResult.Pass : TestResult.Fail); }
public RuleResult Validate(IReadOnlyList <ISignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var primary = graph.SingleOrDefault(); //There are zero signatures. if (primary == null) { return(RuleResult.Fail); } var info = BitStrengthCalculator.CalculateStrength(primary.Certificate); if (info.AlgorithmName != PublicKeyAlgorithm.RSA && info.AlgorithmName != PublicKeyAlgorithm.DSA) { verboseWriter.LogSignatureMessage(primary, $"Primary signature should use RSA or DSA key but uses ${info.AlgorithmName.ToString()}"); return(RuleResult.Fail); } return(RuleResult.Pass); }
public RuleResult Validate(IReadOnlyList <ISignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var result = RuleResult.Pass; //We exclude Authenticode timestamps because they cannot contain "additional" certificates but rather //Use their parent. Including Authenticode timestamps will produce duplicate warnings. var signatures = graph.VisitAll(SignatureKind.AnySignature | SignatureKind.Rfc3161Timestamp | SignatureKind.Deep); foreach (var signature in signatures) { var allEmbeddedCertificates = signature.AdditionalCertificates.Cast <X509Certificate2>().ToList(); var certificatesRequiringEliminiation = new HashSet <X509Certificate2>(allEmbeddedCertificates, new CertificateThumbprintComparer()); foreach (var certificate in allEmbeddedCertificates) { if (!certificatesRequiringEliminiation.Contains(certificate)) { //This certificate was already eliminated because it was part of a previous chain. continue; } using (var chain = new X509Chain()) { chain.ChainPolicy.ExtraStore.AddRange(signature.AdditionalCertificates); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; //All we care is that we can even find an authority. chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags & ~X509VerificationFlags.AllowUnknownCertificateAuthority; if (chain.Build(certificate)) { certificatesRequiringEliminiation.ExceptWith(chain.ChainElements.Cast <X509ChainElement>().Select(c => c.Certificate)); } } } if (certificatesRequiringEliminiation.Count > 0) { foreach (var certificate in certificatesRequiringEliminiation) { verboseWriter.LogSignatureMessage(signature, $"Signature contained untrusted certificate \"{certificate.Subject}\" ({certificate.Thumbprint})."); } result = RuleResult.Fail; } } return(result); }
public RuleResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature, deep: true); var result = RuleResult.Pass; foreach (var signature in signatures) { PublisherInformation?info = null; foreach (var attribute in signature.SignedAttributes) { if (attribute.Oid.Value == KnownOids.OpusInfo) { info = new PublisherInformation(attribute.Values[0]); break; } } if (info == null || info.IsEmpty) { result = RuleResult.Fail; verboseWriter.LogSignatureMessage(signature, "Signature does not have any publisher information."); } else { if (string.IsNullOrWhiteSpace(info.UrlLink)) { result = RuleResult.Fail; verboseWriter.LogSignatureMessage(signature, "Signature does not have an accompanying URL."); } else if (!info.UrlLink.StartsWith(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)) { result = RuleResult.Fail; verboseWriter.LogSignatureMessage(signature, $"Signature's publisher information URL \"{info.UrlLink}\" does not use the secure HTTPS scheme."); } } } return(result); }
public unsafe RuleResult Validate(IReadOnlyList <ISignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); var pass = true; foreach (var signature in signatures) { var counterSignatures = signature.VisitAll(SignatureKind.AnyCounterSignature).ToList(); var isSigned = false; var strongSign = false; foreach (var counterSignature in counterSignatures) { isSigned = true; if (counterSignature.DigestAlgorithm.Value == signature.DigestAlgorithm.Value) { strongSign = true; break; } } if (!isSigned && strongSign) { throw new InvalidOperationException("Unexpectedly have a strong signature."); } if (!isSigned) { verboseWriter.LogSignatureMessage(signature, "Signature is not timestamped."); pass = false; } else if (!strongSign) { verboseWriter.LogSignatureMessage(signature, $"Signature is not timestamped with the expected hash algorithm {signature.DigestAlgorithm.FriendlyName}."); pass = false; } } return(pass ? RuleResult.Pass : RuleResult.Fail); }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); var pass = false; foreach (var signature in signatures) { string serialNumber = ""; string crlDistPoint = ""; Boolean crlCritical = false; string thumbprint = signature.Certificate.Thumbprint; var digestStr = HashHelpers.GetHashForSignature(signature);//message digest of siganture(signature->details->advance->msg digest) serialNumber = signature.Certificate.SerialNumber; X509ExtensionCollection extensions = signature.Certificate.Extensions; foreach (X509Extension extension in extensions) { if (extension.Oid.FriendlyName == "CRL Distribution Points") { /* This extension MAY be present.If present, it MUST NOT be marked critical, * and it MUST contain the HTTP URL of the CA’s CRL service.*/ //Boolean crlHttpExists = false; crlDistPoint = extension.Format(true); crlCritical = extension.Critical; Console.WriteLine(crlDistPoint); /* if (crlDistPoint.Contains("http://")) * { * //crlHttpExists = true; * Console.WriteLine("Has http crl"); * } * if (crlDistPoint.Contains("ldap://")) * { * Console.WriteLine("Has ldap crl"); * * }*/ } } if (crlDistPoint != "") { if (crlDistPoint.Contains("http://") && !crlCritical) { verboseWriter.LogSignatureMessage(signature, "Signature has properly provided CRL distribution point."); pass = true; } else { verboseWriter.LogSignatureMessage(signature, "Signature has not properly provided CRL distribution point."); pass = false; } } else { verboseWriter.LogSignatureMessage(signature, "Signature has not provided CRL distribution point."); pass = false; } } return(pass ? TestResult.Pass : TestResult.Fail); }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature, deep: true); var result = TestResult.Pass; foreach (var signature in signatures) { link = ""; Msg = ""; description = ""; link = ""; PublisherInformation info = null; foreach (var attribute in signature.SignedAttributes) { if (attribute.Oid.Value == KnownOids.OpusInfo) { info = new PublisherInformation(attribute.Values[0]); break; } } if (info == null || info.IsEmpty) { result = TestResult.Fail; Msg = "Signature does not have any publisher information."; verboseWriter.LogSignatureMessage(signature, "Signature does not have any publisher information."); } else { if (string.IsNullOrWhiteSpace(info.Description)) { result = TestResult.Fail; Msg = "Signature does not have an accompanying description."; verboseWriter.LogSignatureMessage(signature, "Signature does not have an accompanying description."); } if (string.IsNullOrWhiteSpace(info.UrlLink)) { result = TestResult.Fail; Msg = "Signature does not have an accompanying URL."; verboseWriter.LogSignatureMessage(signature, "Signature does not have an accompanying URL."); } else { if (!Uri.TryCreate(info.UrlLink, UriKind.Absolute, out _)) { result = TestResult.Fail; Msg = "Signature's accompanying URL is not a valid URI."; verboseWriter.LogSignatureMessage(signature, "Signature's accompanying URL is not a valid URI."); } } } if (!string.IsNullOrWhiteSpace(info.UrlLink)) { link = info.UrlLink; } if (!string.IsNullOrWhiteSpace(info.Description)) { description = info.Description; } DBConnect.InsertPublisherTable(Program.appName, Program.fileName, link, signature.Certificate.Thumbprint, description, Msg); } return(result); }
protected abstract bool ValidateChain(ICmsSignature signer, X509Chain chain, SignatureLogger verboseWriter);
private static bool ValidatEKUForChain(ICmsSignature signature, X509Chain chain, SignatureLogger verboseWriter) { bool signingCertEKU = false; bool chainEKU = false; X509ExtensionCollection extensions = signature.Certificate.Extensions; foreach (X509Extension extension in extensions) { if (extension.Oid.FriendlyName == "Enhanced Key Usage") { signingCertEKU = true; //break; X509EnhancedKeyUsageExtension ext = (X509EnhancedKeyUsageExtension)extension; OidCollection oids = ext.EnhancedKeyUsages; EKUCritical = ext.Critical; foreach (Oid oid in oids) { //if (oid.Equals("1.3.6.1.5.5.7.3.3")) EKU_oidStr = oid.FriendlyName + "(" + oid.Value + ")" + ";" + EKU_oidStr; } Console.WriteLine(EKU_oidStr); } } string EKU = var signatureStrength = GetHashStrenghForComparison(signature.DigestAlgorithm.Value); var strongShaChain = true; var leafCertificateSignatureAlgorithm = chain.ChainElements[0].Certificate.SignatureAlgorithm; var leafCertificateSignatureAlgorithmStrength = GetHashStrenghForComparison(leafCertificateSignatureAlgorithm.Value); //We use count-1 because we don't want to validate the root certificate. for (var i = 0; i < chain.ChainElements.Count - 1; i++) { var element = chain.ChainElements[i]; var signatureAlgorithm = element.Certificate.SignatureAlgorithm; var certificateHashStrength = GetHashStrenghForComparison(signatureAlgorithm.Value); if (certificateHashStrength < signatureStrength) { verboseWriter.LogSignatureMessage(signature, $"Certificate {element.Certificate.Thumbprint} in chain uses {element.Certificate.SignatureAlgorithm.FriendlyName} for its signature algorithm instead of at least {signature.DigestAlgorithm.FriendlyName}."); strongShaChain = false; } //Check that all intermediates are at least as strong as the leaf. else if (certificateHashStrength < leafCertificateSignatureAlgorithmStrength) { verboseWriter.LogSignatureMessage(signature, $"Certificate {element.Certificate.Thumbprint} in chain uses {element.Certificate.SignatureAlgorithm.FriendlyName} for its signature algorithm instead of at least {signature.DigestAlgorithm.FriendlyName}."); } } return(strongShaChain); }
protected override bool ValidateChain(ICmsSignature signer, X509Chain chain, SignatureLogger verboseWriter) { return(ValidatEKUForChain(signer, chain, verboseWriter)); }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); var pass = true; int signatureIndex = 0; foreach (var signature in signatures) { var counterSignatures = signature.VisitAll(SignatureKind.AnyCounterSignature).ToList(); int ts = counterSignatures.Count; var isSigned = false; var strongSign = 0; var tsDigestString = ""; string serialNumber = ""; string thumbprint = signature.Certificate.Thumbprint; var digestStr = HashHelpers.GetHashForSignature(signature);//message digest of siganture(signature->details->advance->msg digest) DBConnect.InsertSignatureTable(Program.fileName, Program.appName, digestStr, signature.DigestAlgorithm.FriendlyName, signature.Certificate.Version, ts, thumbprint, signature.Certificate.Issuer, signature.Certificate.IssuerName.Name, signature.Certificate.Subject, signature.Certificate.SubjectName.Name, signatureIndex); System.DateTime notBeforeDate = signature.Certificate.NotBefore; System.DateTime notAfterDate = signature.Certificate.NotAfter; serialNumber = signature.Certificate.SerialNumber; DBConnect.InsertSignatureDateTable(Program.appName, Program.fileName, digestStr, notBeforeDate.Year, notBeforeDate.Month, notBeforeDate.Day, notAfterDate.Year, notAfterDate.Month, notAfterDate.Day, thumbprint, signatureIndex); X509ExtensionCollection extensions = signature.Certificate.Extensions; int tssignatureIndex = 0; foreach (var counterSignature in counterSignatures) { tsDigestString = HashHelpers.GetHashForSignature(counterSignature);//message digest of siganture(signature->details->advance->msg digest) System.DateTime tsNotBeforeDate = counterSignature.Certificate.NotBefore; System.DateTime tsNotAfterDate = counterSignature.Certificate.NotAfter; DBConnect.InsertTSSignatureDateTable(Program.appName, Program.fileName, tsDigestString, tsNotBeforeDate.Year, tsNotBeforeDate.Month, tsNotBeforeDate.Day, tsNotAfterDate.Year, tsNotAfterDate.Month, tsNotAfterDate.Day, counterSignature.Certificate.Thumbprint, tssignatureIndex); isSigned = true; if (counterSignature.DigestAlgorithm.Value == signature.DigestAlgorithm.Value) { strongSign++; DBConnect.InsertTSSignatureTable(Program.appName, Program.fileName, tsDigestString, counterSignature.DigestAlgorithm.FriendlyName, counterSignature.Certificate.Version, 1, thumbprint, counterSignature.Certificate.Thumbprint, counterSignature.Certificate.Issuer, counterSignature.Certificate.IssuerName.Name, counterSignature.Certificate.Subject, counterSignature.Certificate.SubjectName.Name); } else { DBConnect.InsertTSSignatureTable(Program.appName, Program.fileName, tsDigestString, counterSignature.DigestAlgorithm.FriendlyName, counterSignature.Certificate.Version, 0, thumbprint, counterSignature.Certificate.Thumbprint, counterSignature.Certificate.Issuer, counterSignature.Certificate.IssuerName.Name, counterSignature.Certificate.Subject, counterSignature.Certificate.SubjectName.Name); } } if (!isSigned && strongSign >= 1) { throw new InvalidOperationException("Unexpectedly have a strong signature."); } if (!isSigned) { verboseWriter.LogSignatureMessage(signature, "Signature is not timestamped."); pass = false; } else if (strongSign == 0) { verboseWriter.LogSignatureMessage(signature, $"Signature is not timestamped with the expected hash algorithm {signature.DigestAlgorithm.FriendlyName}."); pass = false; } signatureIndex++; } return(pass ? TestResult.Pass : TestResult.Fail); }
private static TestResult ValidateBasicConstraints(ICmsSignature signature, X509Chain chain, SignatureLogger verboseWriter) { var pass = false; Boolean BCCritical = false; int BC_extension = 0; Boolean BC_CA = false; Boolean hasPathLength = false; string KU = ""; int pathLength = 0; string issuer = ""; var leafCertificateSignatureAlgorithm = chain.ChainElements[0].Certificate.SignatureAlgorithm; //We use count-1 because we don't want to validate the root certificate. for (var i = 0; i < chain.ChainElements.Count - 1; i++) { var element = chain.ChainElements[i]; var signatureAlgorithm = element.Certificate.SignatureAlgorithm; issuer = element.Certificate.Issuer; X509ExtensionCollection extensions = element.Certificate.Extensions; BC_extension = 0; BC_CA = false; hasPathLength = false; pathLength = 0; KU = ""; foreach (X509Extension extension in extensions) { if (extension.Oid.FriendlyName == "Basic Constraints") { X509BasicConstraintsExtension ext = (X509BasicConstraintsExtension)extension; BCCritical = ext.Critical; BC_extension++; BC_CA = ext.CertificateAuthority; hasPathLength = ext.HasPathLengthConstraint; pathLength = ext.PathLengthConstraint; } } /* if (BC_extension == 0 && i>0) * { * Console.WriteLine(issuer); * Console.WriteLine("No BC."); * Console.WriteLine(KU); * Console.WriteLine(Program.appName); * Console.WriteLine("=================================================================="); * }*/ if (i == 0) { if (BC_extension == 1 && !BC_CA) { pass = true; } else if (BC_extension > 1) { verboseWriter.LogSignatureMessage(signature, $"Signature has duplicate Basic Constraints extension."); pass = false; } else if (BC_extension == 1 && BC_CA) { verboseWriter.LogSignatureMessage(signature, $"Signature has violating CA filed for Basic Constraints."); pass = false; } else { pass = false; } } else { verboseWriter.LogSignatureMessage(signature, $"Not a leaf certificate."); } } return(pass ? TestResult.Pass : TestResult.Fail); }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.Any | SignatureKind.Any); var result = TestResult.Pass; int signatureIndex = 0; foreach (var signature in signatures) { string thumbprint = signature.Certificate.Thumbprint; string errMsg = ""; int keySize = 0; var keyInfo = BitStrengthCalculator.CalculateStrength(signature.Certificate); if (!(keyInfo.BitSize is null)) { keySize = (int)keyInfo.BitSize; } string signatureAlgorithm = ""; switch (keyInfo.AlgorithmName) { case PublicKeyAlgorithm.ECDSA when keyInfo.BitSize is null: errMsg = "Signature uses ECDSA with an unknown curve."; verboseWriter.LogSignatureMessage(signature, "Signature uses ECDSA with an unknown curve."); signatureAlgorithm = "ECDSA"; result = TestResult.Fail; break; case PublicKeyAlgorithm.ECDSA when keyInfo.BitSize < MIN_ECDSA_KEY_SIZE: errMsg = $"Signature uses a ECDSA key of size {keyInfo.BitSize} which is below the recommended {MIN_ECDSA_KEY_SIZE}."; verboseWriter.LogSignatureMessage(signature, $"Signature uses a ECDSA key of size {keyInfo.BitSize} which is below the recommended {MIN_ECDSA_KEY_SIZE}."); result = TestResult.Fail; signatureAlgorithm = "ECDSA"; break; case PublicKeyAlgorithm.ECDSA: signatureAlgorithm = "ECDSA"; break; case PublicKeyAlgorithm.RSA when keyInfo.BitSize is null: errMsg = "Signature has an unknown RSA key size."; verboseWriter.LogSignatureMessage(signature, "Signature has an unknown RSA key size."); result = TestResult.Fail; signatureAlgorithm = "RSA"; break; case PublicKeyAlgorithm.RSA when keyInfo.BitSize < MIN_RSADSA_KEY_SIZE: errMsg = $"Signature uses a RSA key of size {keyInfo.BitSize} which is below the recommended {MIN_RSADSA_KEY_SIZE}."; verboseWriter.LogSignatureMessage(signature, $"Signature uses a RSA key of size {keyInfo.BitSize} which is below the recommended {MIN_RSADSA_KEY_SIZE}."); signatureAlgorithm = "RSA"; result = TestResult.Fail; break; case PublicKeyAlgorithm.RSA when keyInfo.BitSize >= MIN_RSADSA_KEY_SIZE: signatureAlgorithm = "RSA"; break; case PublicKeyAlgorithm.DSA when keyInfo.BitSize is null: errMsg = "Signature has an unknown DSA key size."; verboseWriter.LogSignatureMessage(signature, "Signature has an unknown DSA key size."); result = TestResult.Fail; signatureAlgorithm = "DSA"; break; case PublicKeyAlgorithm.DSA when keyInfo.BitSize < MIN_RSADSA_KEY_SIZE: //Effectively, 1024 is the max for a DSA key, so this will likely always fail. errMsg = $"Signature uses a DSA key of size {keyInfo.BitSize} which is below the recommended {MIN_RSADSA_KEY_SIZE}."; verboseWriter.LogSignatureMessage(signature, $"Signature uses a DSA key of size {keyInfo.BitSize} which is below the recommended {MIN_RSADSA_KEY_SIZE}."); result = TestResult.Fail; signatureAlgorithm = "DSA"; break; case PublicKeyAlgorithm.DSA: signatureAlgorithm = "DSA"; break; default: errMsg = $"Signature uses an unknown algorithm."; verboseWriter.LogSignatureMessage(signature, $"Signature uses an unknown algorithm."); result = TestResult.Fail; break; } DBConnect.InsertPublicKeyInfo(Program.appName, Program.fileName, signatureAlgorithm, keySize, thumbprint, errMsg, signatureIndex); signatureIndex++; } return(result); }
private static bool ValidateStrongChain(ICmsSignature signature, X509Chain chain, SignatureLogger verboseWriter) { var signatureStrength = GetHashStrenghForComparison(signature.DigestAlgorithm.Value !); var strongShaChain = true; var leafCertificateSignatureAlgorithm = chain.ChainElements[0].Certificate.SignatureAlgorithm; var leafCertificateSignatureAlgorithmStrength = GetHashStrenghForComparison(leafCertificateSignatureAlgorithm.Value !); //We use count-1 because we don't want to validate the root certificate. for (var i = 0; i < chain.ChainElements.Count - 1; i++) { var element = chain.ChainElements[i]; var signatureAlgorithm = element.Certificate.SignatureAlgorithm; var certificateHashStrength = GetHashStrenghForComparison(signatureAlgorithm.Value !); if (certificateHashStrength < signatureStrength) { verboseWriter.LogSignatureMessage(signature, $"Certificate {element.Certificate.Thumbprint} in chain uses {element.Certificate.SignatureAlgorithm.FriendlyName} for its signature algorithm instead of at least {signature.DigestAlgorithm.FriendlyName}."); strongShaChain = false; } //Check that all intermediates are at least as strong as the leaf. else if (certificateHashStrength < leafCertificateSignatureAlgorithmStrength) { verboseWriter.LogSignatureMessage(signature, $"Certificate {element.Certificate.Thumbprint} in chain uses {element.Certificate.SignatureAlgorithm.FriendlyName} for its signature algorithm instead of at least {signature.DigestAlgorithm.FriendlyName}."); } } return(strongShaChain); }
public TestResult Validate(IReadOnlyList <ICmsSignature> graph, SignatureLogger verboseWriter, CheckConfiguration configuration) { var signatures = graph.VisitAll(SignatureKind.AnySignature); var pass = true; int signatureIndex = 0; foreach (var signature in signatures) { string repeatedExtension = ""; var counterSignatures = signature.VisitAll(SignatureKind.AnyCounterSignature).ToList(); int ts = counterSignatures.Count; var isSigned = false; var strongSign = 0; var tsDigestString = ""; string otherExtensions = ""; string serialNumber = ""; int pathLength = 0; Boolean BC_CA = false; Boolean hasPathLength = false; string KU = ""; Boolean KUCritical = false; string SKI = ""; string EKU_oidStr = ""; string AKI = ""; string certificatePolicies = ""; string crlDistPoint = ""; string authorityInformationAccess = ""; Boolean crlCritical = false; Boolean EKUCritical = false; Boolean BCCritical = false; Boolean CPCritical = false; Boolean SKICritical = false; Boolean AKICritical = false; Boolean AIACritical = false; // Boolean CS_EKU = false; int KU_extension = 0; int EKU_extension = 0; int BC_extension = 0; int SKI_extension = 0; int AKI_extension = 0; int crl_extension = 0; int CP_extension = 0; int AIA_extension = 0; string thumbprint = signature.Certificate.Thumbprint; var digestStr = HashHelpers.GetHashForSignature(signature);//message digest of siganture(signature->details->advance->msg digest) DBConnect.InsertSignatureTable(Program.fileName, Program.appName, digestStr, signature.DigestAlgorithm.FriendlyName, signature.Certificate.Version, ts, thumbprint, signature.Certificate.Issuer, signature.Certificate.IssuerName.Name, signature.Certificate.Subject, signature.Certificate.SubjectName.Name, signatureIndex); System.DateTime notBeforeDate = signature.Certificate.NotBefore; System.DateTime notAfterDate = signature.Certificate.NotAfter; serialNumber = signature.Certificate.SerialNumber; DBConnect.InsertSignatureDateTable(Program.appName, Program.fileName, digestStr, notBeforeDate.Year, notBeforeDate.Month, notBeforeDate.Day, notAfterDate.Year, notAfterDate.Month, notAfterDate.Day, thumbprint, signatureIndex); X509ExtensionCollection extensions = signature.Certificate.Extensions; foreach (X509Extension extension in extensions) { //extension.Oid.FriendlyName Console.WriteLine(extension.Oid.FriendlyName + "(" + extension.Oid.Value + ")"); if (extension.Oid.FriendlyName == "Key Usage") { X509KeyUsageExtension ext = (X509KeyUsageExtension)extension; KUCritical = ext.Critical; if (KU_extension != 0) { repeatedExtension += extension.Oid.FriendlyName + ","; } KU = ext.KeyUsages.ToString(); Console.WriteLine(KU); KU_extension++; } else if (extension.Oid.FriendlyName == "Basic Constraints") { X509BasicConstraintsExtension ext = (X509BasicConstraintsExtension)extension; BCCritical = ext.Critical; if (BC_extension != 0) { repeatedExtension += extension.Oid.FriendlyName + ","; } BC_CA = ext.CertificateAuthority; hasPathLength = ext.HasPathLengthConstraint; pathLength = ext.PathLengthConstraint; Console.WriteLine(BC_CA); Console.WriteLine(hasPathLength); Console.WriteLine(pathLength); BC_extension++; } else if (extension.Oid.FriendlyName == "Subject Key Identifier") { X509SubjectKeyIdentifierExtension ext = (X509SubjectKeyIdentifierExtension)extension; SKICritical = ext.Critical; if (SKI_extension != 0) { repeatedExtension += extension.Oid.FriendlyName + ","; } SKI = ext.SubjectKeyIdentifier.ToString(); Console.WriteLine(SKI); SKI_extension++; } else if (extension.Oid.FriendlyName == "Authority Key Identifier") { AKICritical = extension.Critical; if (AKI_extension != 0) { repeatedExtension += extension.Oid.FriendlyName + ","; } AKI = extension.Format(true); Console.WriteLine(AKI); AKI_extension++; } else if (extension.Oid.FriendlyName == "Enhanced Key Usage") { if (EKU_extension != 0) { repeatedExtension += extension.Oid.FriendlyName + ","; } X509EnhancedKeyUsageExtension ext = (X509EnhancedKeyUsageExtension)extension; OidCollection oids = ext.EnhancedKeyUsages; EKUCritical = ext.Critical; foreach (Oid oid in oids) { //if (oid.Equals("1.3.6.1.5.5.7.3.3")) EKU_oidStr = oid.FriendlyName + "(" + oid.Value + ")" + ";" + EKU_oidStr; } Console.WriteLine(EKU_oidStr); EKU_extension++; } else if (extension.Oid.FriendlyName == "CRL Distribution Points") { /*This extension MUST be present, MUST NOT be marked critical, * and MUST contain the HTTP URL of the CA’s CRL service*/ //Boolean crlHttpExists = false; if (crl_extension != 0) { repeatedExtension += extension.Oid.FriendlyName + ","; } crlDistPoint = extension.Format(true); crlCritical = extension.Critical; Console.WriteLine(crlDistPoint); if (crlDistPoint.Contains("http://")) { //crlHttpExists = true; Console.WriteLine("has http crl"); } if (crlDistPoint.Contains("ldap://")) { Console.WriteLine("has ldap crl"); } crl_extension++; } else if (extension.Oid.FriendlyName == "Certificate Policies") { if (CP_extension != 0) { repeatedExtension += extension.Oid.FriendlyName + ","; } certificatePolicies = extension.Format(true); CPCritical = extension.Critical; Console.WriteLine(certificatePolicies); CP_extension++; } else if (extension.Oid.FriendlyName == "Authority Information Access") { if (AIA_extension != 0) { repeatedExtension += extension.Oid.FriendlyName + ","; } authorityInformationAccess = extension.Format(true); AIACritical = extension.Critical; Console.WriteLine(authorityInformationAccess); AIA_extension++; } else { otherExtensions += ";" + extension.Oid.FriendlyName + "(" + extension.Oid.Value.ToString() + ")"; } } DBConnect.InsertRepeatedExtensionsTable(Program.appName, Program.fileName, repeatedExtension, thumbprint); DBConnect.InsertExtensionsTable(Program.appName, Program.fileName, digestStr, serialNumber, Convert.ToInt32(BC_CA), pathLength, Convert.ToInt32(hasPathLength), KU, SKI, EKU_oidStr, AKI, certificatePolicies, crlDistPoint, Convert.ToInt32(crlCritical), Convert.ToInt32(EKUCritical), Convert.ToInt32(KUCritical), Convert.ToInt32(BCCritical), Convert.ToInt32(CPCritical), Convert.ToInt32(SKICritical), Convert.ToInt32(AKICritical), otherExtensions, authorityInformationAccess, Convert.ToInt32(AIACritical), thumbprint, signatureIndex); Validation.validateWithSignTool(Program.filePath, signatureIndex, thumbprint); int tssignatureIndex = 0; foreach (var counterSignature in counterSignatures) { //reset extensions' values otherExtensions = ""; serialNumber = ""; pathLength = 0; BC_CA = false; hasPathLength = false; KU = ""; KUCritical = false; SKI = ""; EKU_oidStr = ""; AKI = ""; certificatePolicies = ""; crlDistPoint = ""; authorityInformationAccess = ""; crlCritical = false; EKUCritical = false; BCCritical = false; CPCritical = false; SKICritical = false; AKICritical = false; AIACritical = false; tsDigestString = HashHelpers.GetHashForSignature(counterSignature);//message digest of siganture(signature->details->advance->msg digest) System.DateTime tsNotBeforeDate = counterSignature.Certificate.NotBefore; System.DateTime tsNotAfterDate = counterSignature.Certificate.NotAfter; DBConnect.InsertTSSignatureDateTable(Program.appName, Program.fileName, tsDigestString, tsNotBeforeDate.Year, tsNotBeforeDate.Month, tsNotBeforeDate.Day, tsNotAfterDate.Year, tsNotAfterDate.Month, tsNotAfterDate.Day, counterSignature.Certificate.Thumbprint, tssignatureIndex); isSigned = true; if (counterSignature.DigestAlgorithm.Value == signature.DigestAlgorithm.Value) { strongSign++; DBConnect.InsertTSSignatureTable(Program.appName, Program.fileName, tsDigestString, counterSignature.DigestAlgorithm.FriendlyName, counterSignature.Certificate.Version, 1, thumbprint, counterSignature.Certificate.Thumbprint, counterSignature.Certificate.Issuer, counterSignature.Certificate.IssuerName.Name, counterSignature.Certificate.Subject, counterSignature.Certificate.SubjectName.Name); } else { DBConnect.InsertTSSignatureTable(Program.appName, Program.fileName, tsDigestString, counterSignature.DigestAlgorithm.FriendlyName, counterSignature.Certificate.Version, 0, thumbprint, counterSignature.Certificate.Thumbprint, counterSignature.Certificate.Issuer, counterSignature.Certificate.IssuerName.Name, counterSignature.Certificate.Subject, counterSignature.Certificate.SubjectName.Name); } //extracting extensions of timestamp certificate X509ExtensionCollection tsEextensions = signature.Certificate.Extensions; foreach (X509Extension extension in tsEextensions) { //extension.Oid.FriendlyName Console.WriteLine(extension.Oid.FriendlyName + "(" + extension.Oid.Value + ")"); if (extension.Oid.FriendlyName == "Key Usage") { X509KeyUsageExtension ext = (X509KeyUsageExtension)extension; KUCritical = ext.Critical; KU = ext.KeyUsages.ToString(); Console.WriteLine(KU); } else if (extension.Oid.FriendlyName == "Basic Constraints") { X509BasicConstraintsExtension ext = (X509BasicConstraintsExtension)extension; BCCritical = ext.Critical; BC_CA = ext.CertificateAuthority; hasPathLength = ext.HasPathLengthConstraint; pathLength = ext.PathLengthConstraint; Console.WriteLine(BC_CA); Console.WriteLine(hasPathLength); Console.WriteLine(pathLength); } else if (extension.Oid.FriendlyName == "Subject Key Identifier") { X509SubjectKeyIdentifierExtension ext = (X509SubjectKeyIdentifierExtension)extension; SKICritical = ext.Critical; SKI = ext.SubjectKeyIdentifier.ToString(); Console.WriteLine(SKI); } else if (extension.Oid.FriendlyName == "Authority Key Identifier") { AKICritical = extension.Critical; AKI = extension.Format(true); Console.WriteLine(AKI); } else if (extension.Oid.FriendlyName == "Enhanced Key Usage") { //Boolean CS_EKU; X509EnhancedKeyUsageExtension ext = (X509EnhancedKeyUsageExtension)extension; OidCollection oids = ext.EnhancedKeyUsages; EKUCritical = ext.Critical; foreach (Oid oid in oids) { //if (oid.Equals("1.3.6.1.5.5.7.3.3")) // CS_EKU = true; EKU_oidStr = oid.FriendlyName + "(" + oid.Value + ")" + ";" + EKU_oidStr; } Console.WriteLine(EKU_oidStr); } else if (extension.Oid.FriendlyName == "CRL Distribution Points") { /*This extension MUST be present, MUST NOT be marked critical, * and MUST contain the HTTP URL of the CA’s CRL service*/ //Boolean crlHttpExists = false; crlDistPoint = extension.Format(true); crlCritical = extension.Critical; Console.WriteLine(crlDistPoint); if (crlDistPoint.Contains("http://")) { //crlHttpExists = true; Console.WriteLine("has http crl"); } if (crlDistPoint.Contains("ldap://")) { Console.WriteLine("has ldap crl"); } } else if (extension.Oid.FriendlyName == "Certificate Policies") { certificatePolicies = extension.Format(true); CPCritical = extension.Critical; Console.WriteLine(certificatePolicies); } else if (extension.Oid.FriendlyName == "Authority Information Access") { authorityInformationAccess = extension.Format(true); AIACritical = extension.Critical; Console.WriteLine(authorityInformationAccess); } else { otherExtensions += ";" + extension.Oid.FriendlyName + "(" + extension.Oid.Value.ToString() + ")"; } } DBConnect.InsertTSExtensionsTable(Program.appName, Program.fileName, digestStr, serialNumber, Convert.ToInt32(BC_CA), pathLength, Convert.ToInt32(hasPathLength), KU, SKI, EKU_oidStr, AKI, certificatePolicies, crlDistPoint, Convert.ToInt32(crlCritical), Convert.ToInt32(EKUCritical), Convert.ToInt32(KUCritical), Convert.ToInt32(BCCritical), Convert.ToInt32(CPCritical), Convert.ToInt32(SKICritical), Convert.ToInt32(AKICritical), otherExtensions, authorityInformationAccess, Convert.ToInt32(AIACritical), thumbprint, tssignatureIndex); tssignatureIndex++; } if (!isSigned && strongSign >= 1) { throw new InvalidOperationException("Unexpectedly have a strong signature."); } if (!isSigned) { verboseWriter.LogSignatureMessage(signature, "Signature is not timestamped."); pass = false; } else if (strongSign == 0) { verboseWriter.LogSignatureMessage(signature, $"Signature is not timestamped with the expected hash algorithm {signature.DigestAlgorithm.FriendlyName}."); pass = false; } signatureIndex++; } return(pass ? TestResult.Pass : TestResult.Fail); }