From 2e5bd2bfe909dd361d2fe344b7e2d70e65e79810 Mon Sep 17 00:00:00 2001 From: Klaus Fischer <klaus.fischer@eloware.com> Date: Tue, 6 Sep 2022 07:40:43 +0200 Subject: [PATCH] Revocation check fails --- FitConnect/Encryption/CertificateHelper.cs | 71 +++++++++++++--------- IntegrationTests/CertificateValidation.cs | 5 +- IntegrationTests/IntegrationTests.csproj | 15 ++++- IntegrationTests/temp/readme.md | 0 4 files changed, 56 insertions(+), 35 deletions(-) create mode 100644 IntegrationTests/temp/readme.md diff --git a/FitConnect/Encryption/CertificateHelper.cs b/FitConnect/Encryption/CertificateHelper.cs index 2076ebe0..ac4d8eae 100644 --- a/FitConnect/Encryption/CertificateHelper.cs +++ b/FitConnect/Encryption/CertificateHelper.cs @@ -18,39 +18,22 @@ public class CertificateHelper { X509Certificate2[]? rootCertificate = null) => ValidateCertificate(new JsonWebKey(keyJson), logLevel, rootCertificate); - internal bool ValidateCertificate(JsonWebKey key, LogLevel logLevel = LogLevel.Error, - X509Certificate2[]? root = null) { - var certificates = key.X5c.Select(s => new X509Certificate2(Convert.FromBase64String(s))) - .ToList(); - - // root ??= new X509Certificate2(Convert.FromBase64String(key.X5t)); - - _logger?.LogTrace("Found {Count} certificate(s)", certificates.Count); - - var valid = certificates.Aggregate(true, - (result, cert) => result - && ValidateCertificate(cert, out _, - root, - logLevel) - && cert.Verify() - ); - return valid; - } - internal bool ValidateCertificate(X509Certificate2 certificate, out X509ChainStatus[] chainStatus, X509Certificate2[]? rootCertificate = null, LogLevel logLevel = LogLevel.Warning) { var certificateChain = new X509Chain(); + certificate.ExportToPem($"./temp/{Guid.NewGuid().ToString()}.pem"); + _logger?.LogDebug("Issuers: {Issuer}", certificate.Issuer); if (rootCertificate != null) { certificateChain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; - // certificateChain.ChainPolicy.ExtraStore.AddRange(rootCertificate); + certificateChain.ChainPolicy.ExtraStore.AddRange(rootCertificate); certificateChain.ChainPolicy.CustomTrustStore.AddRange(rootCertificate); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - certificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; - certificateChain.ChainPolicy.DisableCertificateDownloads = true; + certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.Online; + certificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; + certificateChain.ChainPolicy.DisableCertificateDownloads = false; certificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags; _logger?.LogDebug("Using custom root certificate"); } @@ -73,13 +56,41 @@ public class CertificateHelper { if (!result) _logger?.Log(logLevel, "Certificate status: {ObjStatusInformation}", statusAggregation); -#if DEBUG - if (certificate.Verify() != result) { - _logger?.LogError( - "Certificate verification failed. Verify does not match internal test {Result}", - result); - } -#endif + return result; } + + internal bool ValidateCertificate(JsonWebKey key, LogLevel logLevel = LogLevel.Error, + X509Certificate2[]? root = null) { + var certificates = key.X5c.Select(s => new X509Certificate2(Convert.FromBase64String(s))) + .ToList(); + + if (certificates.Count != 3) { + _logger?.Log(logLevel, "Found {Count} certificate(s) but should be 3", + certificates.Count); + return false; + } + // root ??= new X509Certificate2(Convert.FromBase64String(key.X5t)); + + + var valid = certificates.Aggregate(true, + (result, cert) => result + && ValidateCertificate(cert, out _, root, logLevel) + // && cert.Verify() + ); + return valid; + } +} + +public static class X509Certificate2Extensions { + public static void ExportToPem(this X509Certificate2 certificate, string fileName) { + StringBuilder builder = new StringBuilder(); + builder.AppendLine("-----BEGIN CERTIFICATE-----"); + builder.AppendLine( + Convert.ToBase64String(certificate.RawData, Base64FormattingOptions.InsertLineBreaks)); + builder.AppendLine("-----END CERTIFICATE-----"); + var content = builder.ToString(); + + File.WriteAllText(fileName, content); + } } diff --git a/IntegrationTests/CertificateValidation.cs b/IntegrationTests/CertificateValidation.cs index eefce9cd..31412c81 100644 --- a/IntegrationTests/CertificateValidation.cs +++ b/IntegrationTests/CertificateValidation.cs @@ -159,9 +159,10 @@ public class CertificateValidation { var shouldFail = !fileName.Contains("/valid"); var jwk = new JsonWebKey(File.ReadAllText(fileName)); var valid = _certificateHelper.ValidateCertificate(jwk, - shouldFail ? LogLevel.Debug : LogLevel.Critical, new[] { + shouldFail ? LogLevel.Warning : LogLevel.Critical, new[] { new X509Certificate2("./certificates/root.pem"), - new X509Certificate2("./certificates/ca.30244.der") + new X509Certificate2("./certificates/ca.30244.der"), + new X509Certificate2("./certificates/ca.21636.der") }); if (shouldFail) diff --git a/IntegrationTests/IntegrationTests.csproj b/IntegrationTests/IntegrationTests.csproj index ee4d7ef4..9a0e7d93 100644 --- a/IntegrationTests/IntegrationTests.csproj +++ b/IntegrationTests/IntegrationTests.csproj @@ -36,9 +36,6 @@ <None Update="certificates\www-amazon-de-zertifikatskette.pem"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> - <None Update="certificates\invalidEncJwkWithLessThan3Certificates.json"> - <CopyToOutputDirectory>Always</CopyToOutputDirectory> - </None> <None Update="certificates\validEncJW_KeyUse.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> @@ -57,6 +54,18 @@ <None Update="certificates\ca.30244.der"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> + <None Update="certificates\ca.30244.der"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + <None Update="temp\readme.md"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + <None Update="certificates\ca.21636.der"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + <None Update="certificates\invalidEncJwkWithLessThan3Certificates.json"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> </ItemGroup> </Project> diff --git a/IntegrationTests/temp/readme.md b/IntegrationTests/temp/readme.md new file mode 100644 index 00000000..e69de29b -- GitLab