private async Task <PackageSignature> InitializePackageSignatureAsync( int packageKey, PackageSignatureType type, HashedCertificate signatureEndCertificate, IReadOnlyDictionary <string, EndCertificate> thumbprintToEndCertificate, bool replacePackageSignature) { var packageSignatures = await _validationEntitiesContext .PackageSignatures .Include(x => x.TrustedTimestamps) .Include(x => x.EndCertificate) .Where(x => x.PackageKey == packageKey && x.Type == type) .ToListAsync(); if (packageSignatures.Count > 1) { _logger.LogError( "There are {Count} package signatures for package key {PackageKey} and type {Type}. There should be either zero or one.", packageSignatures.Count, packageKey, type); throw new InvalidOperationException("There should never be more than one package signature per package and signature type."); } PackageSignature packageSignature; if (packageSignatures.Count == 0) { packageSignature = InitializePackageSignature( packageKey, type, signatureEndCertificate, thumbprintToEndCertificate); } else { packageSignature = packageSignatures.Single(); if (packageSignature.EndCertificate.Thumbprint != signatureEndCertificate.Thumbprint) { if (replacePackageSignature) { _logger.LogWarning( "The signature end certificate thumbprint has changed for package {PackageKey} and type " + "{Type}. The previous signature end certificate is {ExistingThumbprint}. The new thumprint " + "is {NewThumbprint}. The previous record with key {PackageSignatureKey} will be removed.", packageKey, type, packageSignature.EndCertificate.Thumbprint, signatureEndCertificate.Thumbprint, packageSignature.Key); // Remove the child trusted timestamps. This should be handled by cascading delete but to be // explicit and to facilitate unit testing, we explicitly remove them. foreach (var trustedTimestamp in packageSignature.TrustedTimestamps) { _validationEntitiesContext.TrustedTimestamps.Remove(trustedTimestamp); } _validationEntitiesContext.PackageSignatures.Remove(packageSignature); packageSignature = InitializePackageSignature( packageKey, type, signatureEndCertificate, thumbprintToEndCertificate); } else { _logger.LogError( "The signature end certificate thumbprint cannot change for package {PackageKey} and type " + "{Type}. The existing signature end certificate is {ExistingThumbprint}. The new thumprint " + "is {NewThumbprint}.", packageKey, type, packageSignature.EndCertificate.Thumbprint, signatureEndCertificate.Thumbprint); throw new InvalidOperationException("The thumbprint of the signature end certificate cannot change."); } } } return(packageSignature); }
public async Task RevokedResultDoesNotInvalidateDependentNonAuthorSignaturesSignatures(PackageSignatureType type) { // Arrange var revocationTime = DateTime.UtcNow; var verificationResult = new CertificateVerificationResult( status: EndCertificateStatus.Revoked, statusFlags: X509ChainStatusFlags.Revoked, revocationTime: revocationTime); var signingState = new PackageSigningState { SigningStatus = PackageSigningStatus.Valid }; var signature2 = new PackageSignature { Key = 12, Status = PackageSignatureStatus.Valid, Type = type }; var timestamp2 = new TrustedTimestamp { Value = revocationTime.AddDays(1), Status = TrustedTimestampStatus.Valid }; signingState.PackageSignatures = new[] { signature2 }; signature2.PackageSigningState = signingState; signature2.EndCertificate = _certificate1; signature2.TrustedTimestamps = new[] { timestamp2 }; timestamp2.PackageSignature = signature2; timestamp2.EndCertificate = _certificate2; _certificate1.Use = EndCertificateUse.CodeSigning; _certificate2.Use = EndCertificateUse.Timestamping; _certificate1.PackageSignatures = new[] { signature2 }; _certificate2.TrustedTimestamps = new[] { timestamp2 }; _context.Mock( packageSigningStates: new[] { signingState }, packageSignatures: new[] { signature2 }, trustedTimestamps: new[] { timestamp2 }, endCertificates: new[] { _certificate1, _certificate2 }); var result = await _target.TrySaveResultAsync(_certificateValidation1, verificationResult); Assert.True(result); Assert.Equal(EndCertificateStatus.Revoked, _certificateValidation1.Status); Assert.Equal(EndCertificateStatus.Revoked, _certificate1.Status); Assert.Equal(0, _certificate1.ValidationFailures); Assert.Equal(revocationTime, _certificate1.RevocationTime); Assert.Equal(PackageSignatureStatus.Valid, signature2.Status); Assert.Equal(PackageSigningStatus.Valid, signingState.SigningStatus); _telemetryService.Verify(a => a.TrackUnableToValidateCertificateEvent(It.IsAny <EndCertificate>()), Times.Never); _telemetryService.Verify(a => a.TrackPackageSignatureShouldBeInvalidatedEvent(It.IsAny <PackageSignature>()), Times.Never); _telemetryService.Verify(a => a.TrackUnableToValidateCertificateEvent(It.IsAny <EndCertificate>()), Times.Never); _context.Verify(c => c.SaveChangesAsync(), Times.Once); }