public override SignatureVerificationSummary Verify( Timestamp timestamp, SignatureVerifySettings settings, HashAlgorithmName fingerprintAlgorithm, X509Certificate2Collection certificateExtraStore) { var issues = new List <SignatureLog>(); settings = settings ?? SignatureVerifySettings.Default; issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.SignatureType, Type.ToString()))); issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.NuGetV3ServiceIndexUrl, V3ServiceIndexUrl.ToString()))); if (PackageOwners != null) { issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.NuGetPackageOwners, string.Join(", ", PackageOwners)))); } var summary = base.Verify(timestamp, settings, fingerprintAlgorithm, certificateExtraStore); return(new SignatureVerificationSummary( summary.SignatureType, summary.Status, summary.Flags, summary.Timestamp, summary.ExpirationTime, issues.Concat(summary.Issues))); }
private SignatureVerificationSummary VerifyValidityAndTrust( Signature signature, SignedPackageVerifierSettings verifierSettings, SignatureVerifySettings settings, X509Certificate2Collection certificateExtraStore) { Timestamp timestamp; var timestampSummary = GetTimestamp(signature, verifierSettings, out timestamp); var status = signature.Verify( timestamp, settings, _fingerprintAlgorithm, certificateExtraStore); if (timestampSummary.Status != SignatureVerificationStatus.Valid && !verifierSettings.AllowIgnoreTimestamp) { return(new SignatureVerificationSummary( signature.Type, SignatureVerificationStatus.Disallowed, SignatureVerificationStatusFlags.NoValidTimestamp, status.Issues.Concat(timestampSummary.Issues))); } return(new SignatureVerificationSummary( status.SignatureType, status.Status, status.Flags, status.Timestamp, status.ExpirationTime, status.Issues.Concat(timestampSummary.Issues))); }
private SignatureVerificationStatus VerifyRepositorySignature( Signature signature, X509Certificate2Collection certificates) { var settings = new SignatureVerifySettings( treatIssuesAsErrors: !_settings.AllowIllegal, allowUntrustedRoot: _settings.AllowUntrusted, allowUnknownRevocation: _settings.AllowUnknownRevocation, logOnSignatureExpired: false); var issues = new List <SignatureLog>(); Timestamp timestamp = null; if (!_settings.AllowIgnoreTimestamp && !signature.TryGetValidTimestamp( _settings, _fingerprintAlgorithm, issues, out var verificationFlags, out timestamp)) { return(VerificationUtility.GetSignatureVerificationStatus(verificationFlags)); } var summary = signature.Verify( timestamp, settings, _fingerprintAlgorithm, certificates, issues); return(summary.Status); }
private SignatureVerificationSummary VerifyValidityAndTrust( Signature signature, SignedPackageVerifierSettings verifierSettings, SignatureVerifySettings settings, X509Certificate2Collection certificateExtraStore, List <SignatureLog> issues) { var timestampIssues = new List <SignatureLog>(); if (!signature.TryGetValidTimestamp(verifierSettings, _fingerprintAlgorithm, timestampIssues, out var verificationFlags, out var validTimestamp) && !verifierSettings.AllowIgnoreTimestamp) { issues.AddRange(timestampIssues); return(null); } var status = signature.Verify( validTimestamp, settings, _fingerprintAlgorithm, certificateExtraStore, issues); issues.AddRange(timestampIssues); return(status); }
private PackageVerificationResult VerifySignatureAndCountersignature( PrimarySignature signature, SignedPackageVerifierSettings settings) { var issues = new List <SignatureLog>(); var certificateExtraStore = signature.SignedCms.Certificates; var primarySignatureHasCountersignature = SignatureUtility.HasRepositoryCountersignature(signature); var status = SignatureVerificationStatus.Illegal; // Only accept untrusted root if the signature has a countersignature that we can validate against var verifySettings = new SignatureVerifySettings( treatIssuesAsErrors: !settings.AllowIllegal, allowUntrustedRoot: primarySignatureHasCountersignature, allowUnknownRevocation: settings.AllowUnknownRevocation, logOnSignatureExpired: !primarySignatureHasCountersignature); var primarySummary = VerifyValidityAndTrust(signature, settings, verifySettings, certificateExtraStore, issues); if (primarySummary != null) { status = primarySummary.Status; if (primarySignatureHasCountersignature) { if (settings.AlwaysVerifyCountersignature || ShouldFallbackToRepositoryCountersignature(primarySummary)) { var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(signature); verifySettings = new SignatureVerifySettings( treatIssuesAsErrors: !settings.AllowIllegal, allowUntrustedRoot: false, allowUnknownRevocation: settings.AllowUnknownRevocation, logOnSignatureExpired: true); var counterSummary = VerifyValidityAndTrust(countersignature, settings, verifySettings, certificateExtraStore, issues); status = counterSummary.Status; if (!Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, counterSummary.Timestamp)) { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3011, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureNotTimeValid, signature.FriendlyName))); status = SignatureVerificationStatus.Illegal; } } else if (primarySummary.Flags.HasFlag(SignatureVerificationStatusFlags.CertificateExpired)) { // We are not adding this log if the primary signature has a countersignature to check the expiration against the countersignature's timestamp. // If the countersignature shouldn't be check and the primary signature was expired, add this log. issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3011, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureNotTimeValid, signature.FriendlyName))); } } } return(new SignedPackageVerificationResult(status, signature, issues)); }
public override SignatureVerificationSummary Verify( Timestamp timestamp, SignatureVerifySettings settings, HashAlgorithmName fingerprintAlgorithm, X509Certificate2Collection certificateExtraStore, List <SignatureLog> issues) { if (issues == null) { throw new ArgumentNullException(nameof(issues)); } settings = settings ?? SignatureVerifySettings.Default; issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.SignatureType, Type.ToString()))); return(base.Verify(timestamp, settings, fingerprintAlgorithm, certificateExtraStore, issues)); }
public override SignatureVerificationSummary Verify( Timestamp timestamp, SignatureVerifySettings settings, HashAlgorithmName fingerprintAlgorithm, X509Certificate2Collection certificateExtraStore) { var issues = new List <SignatureLog>(); settings = settings ?? SignatureVerifySettings.Default; issues.Add(SignatureLog.MinimalLog(Environment.NewLine + string.Format(CultureInfo.CurrentCulture, Strings.SignatureType, Type.ToString()))); var summary = base.Verify(timestamp, settings, fingerprintAlgorithm, certificateExtraStore); return(new SignatureVerificationSummary( summary.SignatureType, summary.Status, summary.Flags, summary.Timestamp, summary.ExpirationTime, issues.Concat(summary.Issues))); }
/// <summary> /// Verify if the signature object meets the specification trust and validity requirements. /// </summary> /// <param name="timestamp">Timestamp for this signature, if signature is not timestamped it can be null.</param> /// <param name="allowUntrusted">Setting that tells if a signature that does not meet any soft failure requirements can still be allowed. Used to know if warnings or errors should be logged for an issue.</param> /// <param name="allowUnknownRevocation">Setting that tells if unkown revocation is valid when building the chain.</param> /// <param name="allowUntrustedSelfSignedCertificate">Setting that tells if an untrusted self-signed certificate should be allowed as the signing certificate.</param> /// <param name="fingerprintAlgorithm">Algorithm used to calculate and display the certificate's fingerprint.</param> /// <param name="certificateExtraStore">Collection of certificates to help the chain building engine as an extra store.</param> /// <param name="issues">List of log messages.</param> /// <remarks>This is only public for ease of testing</remarks> /// <returns>Status of trust for signature.</returns> public virtual SignatureVerificationSummary Verify( Timestamp timestamp, SignatureVerifySettings settings, HashAlgorithmName fingerprintAlgorithm, X509Certificate2Collection certificateExtraStore) { settings = settings ?? SignatureVerifySettings.Default; var flags = SignatureVerificationStatusFlags.NoErrors; var issues = new List <SignatureLog>(); SignatureVerificationStatus status; var certificate = SignerInfo.Certificate; if (certificate == null) { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3010, string.Format(CultureInfo.CurrentCulture, Strings.Verify_ErrorNoCertificate, FriendlyName))); flags |= SignatureVerificationStatusFlags.NoCertificate; status = settings.AllowIllegal? SignatureVerificationStatus.Valid: SignatureVerificationStatus.Disallowed; return(new SignatureVerificationSummary(Type, status, flags, issues)); } issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.VerificationCertDisplay, FriendlyName, $"{Environment.NewLine}{CertificateUtility.X509Certificate2ToString(certificate, fingerprintAlgorithm)}"))); try { SignerInfo.CheckSignature(verifySignatureOnly: true); } catch (Exception e) { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureVerificationFailed, FriendlyName))); issues.Add(SignatureLog.DebugLog(e.ToString())); flags |= SignatureVerificationStatusFlags.SignatureCheckFailed; status = settings.AllowIllegal ? SignatureVerificationStatus.Valid : SignatureVerificationStatus.Disallowed; return(new SignatureVerificationSummary(Type, status, flags, issues)); } DateTimeOffset?expirationTime = null; var certificateFlags = VerificationUtility.ValidateSigningCertificate(certificate, !settings.AllowIllegal, FriendlyName, issues); if (certificateFlags != SignatureVerificationStatusFlags.NoErrors) { flags |= certificateFlags; } else { timestamp = timestamp ?? new Timestamp(); using (var chainHolder = new X509ChainHolder()) { var chain = chainHolder.Chain; // This flag should only be set for verification scenarios, not signing. chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid; CertificateChainUtility.SetCertBuildChainPolicy(chain.ChainPolicy, certificateExtraStore, timestamp.UpperLimit.LocalDateTime, CertificateType.Signature); if (settings.RevocationMode == RevocationMode.Offline) { chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; } else { chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; } var chainBuildingSucceeded = CertificateChainUtility.BuildCertificateChain(chain, certificate, out var chainStatuses); var x509ChainString = CertificateUtility.X509ChainToString(chain, fingerprintAlgorithm); if (!string.IsNullOrWhiteSpace(x509ChainString)) { issues.Add(SignatureLog.DetailedLog(x509ChainString)); } var chainBuildingHasIssues = false; if (!chainBuildingSucceeded) { var statusFlags = CertificateChainUtility.DefaultObservedStatusFlags; IEnumerable <string> messages; if (CertificateChainUtility.TryGetStatusMessage(chainStatuses, statusFlags, out messages)) { foreach (var message in messages) { issues.Add(SignatureLog.Issue(!settings.AllowIllegal, NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, message))); } chainBuildingHasIssues = true; flags |= SignatureVerificationStatusFlags.ChainBuildingFailure; } // For all the special cases, chain status list only has unique elements for each chain status flag present // therefore if we are checking for one specific chain status we can use the first of the returned list // if we are combining checks for more than one, then we have to use the whole list. if (CertificateChainUtility.TryGetStatusMessage(chainStatuses, X509ChainStatusFlags.Revoked, out messages)) { issues.Add(SignatureLog.Error(NuGetLogCode.NU3012, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, messages.First()))); flags |= SignatureVerificationStatusFlags.CertificateRevoked; return(new SignatureVerificationSummary(Type, SignatureVerificationStatus.Suspect, flags, timestamp, issues)); } if (CertificateChainUtility.TryGetStatusMessage(chainStatuses, X509ChainStatusFlags.UntrustedRoot, out messages)) { if (settings.ReportUntrustedRoot) { issues.Add(SignatureLog.Issue(!settings.AllowUntrusted, NuGetLogCode.NU3018, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, messages.First()))); } if (!settings.AllowUntrusted) { chainBuildingHasIssues = true; flags |= SignatureVerificationStatusFlags.UntrustedRoot; } } var offlineRevocationErrors = CertificateChainUtility.TryGetStatusMessage(chainStatuses, X509ChainStatusFlags.OfflineRevocation, out var _); var unknownRevocationErrors = CertificateChainUtility.TryGetStatusMessage(chainStatuses, X509ChainStatusFlags.RevocationStatusUnknown, out var unknownRevocationStatusMessages); if (offlineRevocationErrors || unknownRevocationErrors) { if (settings.ReportUnknownRevocation) { string unknownRevocationMessage = null; if (unknownRevocationErrors) { unknownRevocationMessage = string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, unknownRevocationStatusMessages.First()); } if (settings.RevocationMode == RevocationMode.Offline) { if (offlineRevocationErrors) { issues.Add(SignatureLog.InformationLog(string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOffline))); } if (unknownRevocationMessage != null) { issues.Add(SignatureLog.InformationLog(unknownRevocationMessage)); } } else { if (offlineRevocationErrors) { issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3018, string.Format(CultureInfo.CurrentCulture, Strings.VerifyChainBuildingIssue, FriendlyName, Strings.VerifyCertTrustOfflineWhileRevocationModeOnline))); } if (unknownRevocationMessage != null) { issues.Add(SignatureLog.Issue(!settings.AllowUnknownRevocation, NuGetLogCode.NU3018, unknownRevocationMessage)); } } } if (!settings.AllowUnknownRevocation) { chainBuildingHasIssues = true; flags |= SignatureVerificationStatusFlags.UnknownRevocation; } } // Debug log any errors issues.Add(SignatureLog.DebugLog( string.Format( CultureInfo.CurrentCulture, Strings.VerifyError_InvalidCertificateChain, FriendlyName, string.Join(", ", chainStatuses.Select(x => x.Status.ToString()))))); } var isSignatureTimeValid = Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(certificate, timestamp); if (isSignatureTimeValid && !chainBuildingHasIssues) { return(new SignatureVerificationSummary(Type, SignatureVerificationStatus.Valid, flags, timestamp, issues)); } else if (!isSignatureTimeValid) { issues.Add( SignatureLog.Issue( !settings.AllowUntrusted, NuGetLogCode.NU3037, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_SignatureNotTimeValid, FriendlyName))); if (!settings.AllowUntrusted) { flags |= SignatureVerificationStatusFlags.CertificateExpired; } expirationTime = DateTime.SpecifyKind(certificate.NotAfter, DateTimeKind.Local); } } } status = VerificationUtility.GetSignatureVerificationStatus(flags); return(new SignatureVerificationSummary(Type, status, flags, timestamp, expirationTime, issues)); }
private PackageVerificationResult Verify( PrimarySignature signature, SignedPackageVerifierSettings settings) { var certificateExtraStore = signature.SignedCms.Certificates; var repositoryCountersignatureExists = SignatureUtility.HasRepositoryCountersignature(signature); var isRepositoryCountersignatureVerificationRequested = settings.VerificationTarget.HasFlag(VerificationTarget.Repository) && settings.SignaturePlacement.HasFlag(SignaturePlacement.Countersignature); var allowDeferralToRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists; var status = SignatureVerificationStatus.Unknown; var issues = Enumerable.Empty <SignatureLog>(); var isUntrustedRootAllowed = IsUntrustedRootAllowed(signature); var verifySettings = new SignatureVerifySettings( allowIllegal: settings.AllowIllegal, allowUntrusted: settings.AllowUntrusted || isUntrustedRootAllowed, allowUnknownRevocation: settings.AllowUnknownRevocation, reportUnknownRevocation: settings.ReportUnknownRevocation, reportUntrustedRoot: !isUntrustedRootAllowed, revocationMode: settings.RevocationMode); SignatureVerificationSummary primarySummary = null; if (settings.SignaturePlacement.HasFlag(SignaturePlacement.PrimarySignature) && VerificationUtility.IsVerificationTarget(signature.Type, settings.VerificationTarget)) { primarySummary = VerifyValidityAndTrust(signature, settings, verifySettings, certificateExtraStore); issues = issues.Concat(primarySummary.Issues); status = primarySummary.Status; } Debug.Assert(isRepositoryCountersignatureVerificationRequested != (settings.RepositoryCountersignatureVerificationBehavior == SignatureVerificationBehavior.Never)); bool shouldVerifyRepositoryCountersignature; switch (settings.RepositoryCountersignatureVerificationBehavior) { case SignatureVerificationBehavior.IfExists: shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists; break; case SignatureVerificationBehavior.IfExistsAndIsNecessary: // The repository countersignature should be evaluated if settings allow it, if a repository countersignature exists // and if either settings only allow a repository countersignature to be evaluated or the primary signature has some // validation/trust issues that may benefit from a repository countersignature fallback. shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested && repositoryCountersignatureExists && (primarySummary == null || (primarySummary != null && (HasUntrustedRoot(primarySummary) || IsSignatureExpired(primarySummary)))); break; case SignatureVerificationBehavior.Always: shouldVerifyRepositoryCountersignature = isRepositoryCountersignatureVerificationRequested; break; case SignatureVerificationBehavior.Never: shouldVerifyRepositoryCountersignature = false; break; default: throw new NotImplementedException(); } if (shouldVerifyRepositoryCountersignature) { var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(signature); if (countersignature == null) { if (settings.RepositoryCountersignatureVerificationBehavior == SignatureVerificationBehavior.Always) { issues = issues.Concat(new[] { SignatureLog.Error(NuGetLogCode.NU3038, Strings.NoRepositoryCountersignature) }); status = SignatureVerificationStatus.Disallowed; } } else { isUntrustedRootAllowed = IsUntrustedRootAllowed(countersignature); verifySettings = new SignatureVerifySettings( allowIllegal: settings.AllowIllegal, allowUntrusted: settings.AllowUntrusted || isUntrustedRootAllowed, allowUnknownRevocation: settings.AllowUnknownRevocation, reportUnknownRevocation: settings.ReportUnknownRevocation, reportUntrustedRoot: !isUntrustedRootAllowed, revocationMode: settings.RevocationMode); var countersignatureSummary = VerifyValidityAndTrust(countersignature, settings, verifySettings, certificateExtraStore); if (primarySummary == null) { status = countersignatureSummary.Status; } else { if (countersignatureSummary.Status == SignatureVerificationStatus.Valid) { if (IsSignatureExpired(primarySummary) && HasUntrustedRoot(primarySummary)) { // Exclude the issue of the primary signature being untrusted since the repository countersignature fulfills the role of a trust anchor. issues = issues.Where(log => log.Code != NuGetLogCode.NU3018); if (countersignatureSummary.Timestamp != null && Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, countersignatureSummary.Timestamp)) { // Exclude the issue of the primary signature being expired since the repository countersignature fulfills the role of a trusted timestamp. issues = issues.Where(log => log.Code != NuGetLogCode.NU3037); status = SignatureVerificationStatus.Valid; } } else if (IsSignatureExpired(primarySummary) && countersignatureSummary.Timestamp != null && Rfc3161TimestampVerificationUtility.ValidateSignerCertificateAgainstTimestamp(signature.SignerInfo.Certificate, countersignatureSummary.Timestamp)) { // Exclude the issue of the primary signature being expired since the repository countersignature fulfills the role of a trusted timestamp. issues = issues.Where(log => log.Code != NuGetLogCode.NU3037); status = SignatureVerificationStatus.Valid; } else if (HasUntrustedRoot(primarySummary)) { // Exclude the issue of the primary signature being untrusted since the repository countersignature fulfills the role of a trust anchor. issues = issues.Where(log => log.Code != NuGetLogCode.NU3018); status = SignatureVerificationStatus.Valid; } } // Both the primary signature and the repository countersignature were evaluated. // The overall status should be the more severe status of the two. status = (SignatureVerificationStatus)Math.Min((int)status, (int)countersignatureSummary.Status); } issues = issues.Concat(countersignatureSummary.Issues); } } return(new SignedPackageVerificationResult(status, signature, issues)); }