in src/NuGet.Core/NuGet.Packaging/Signing/Verification/SignatureTrustAndValidityVerificationProvider.cs [56:200]
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);
}