Skip to content

Adopt swift-certificates 0.6.0 #6528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
.package(url: "https://github.com/apple/swift-crypto.git", .upToNextMinor(from: "2.5.0")),
.package(url: "https://github.com/apple/swift-system.git", .upToNextMinor(from: "1.1.1")),
.package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.0.1")),
.package(url: "https://github.com/apple/swift-certificates.git", .upToNextMinor(from: "0.4.1")),
.package(url: "https://github.com/apple/swift-certificates.git", .upToNextMinor(from: "0.6.0")),
]
} else {
package.dependencies += [
Expand Down
135 changes: 60 additions & 75 deletions Sources/PackageCollectionsSigning/CertificatePolicy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ extension CertificatePolicy {
func verify(
certChain: [Certificate],
trustedRoots: [Certificate]?,
policies: [VerifierPolicy],
@PolicyBuilder policies: () -> some VerifierPolicy,
observabilityScope: ObservabilityScope,
callbackQueue: DispatchQueue,
callback: @escaping (Result<Void, Error>) -> Void
Expand All @@ -87,7 +87,7 @@ extension CertificatePolicy {
guard !certChain.isEmpty else {
return wrappedCallback(.failure(CertificatePolicyError.emptyCertChain))
}

let policies = policies()
Task {
var trustStore = CertificateStores.defaultTrustRoots
if let trustedRoots {
Expand All @@ -98,9 +98,9 @@ extension CertificatePolicy {
return wrappedCallback(.failure(CertificatePolicyError.noTrustedRootCertsConfigured))
}

let policySet = PolicySet(policies: policies)

var verifier = Verifier(rootCertificates: CertificateStore(trustStore), policy: policySet)
var verifier = Verifier(rootCertificates: CertificateStore(trustStore)) {
policies
}
let result = await verifier.validate(
leafCertificate: certChain[0],
intermediates: CertificateStore(certChain)
Expand Down Expand Up @@ -182,31 +182,26 @@ struct DefaultCertificatePolicy: CertificatePolicy {
return wrappedCallback(.failure(CertificatePolicyError.emptyCertChain))
}

var policies = [VerifierPolicy]()
policies.append(_ADPCertificatePolicy()) // included for testing
// Check if subject name matches
policies.append(
_SubjectNamePolicy(
expectedUserID: self.expectedSubjectUserID,
expectedOrganizationalUnit: self.expectedSubjectOrganizationalUnit
)
)
// Must be a code signing certificate
policies.append(_CodeSigningPolicy())
// Basic validations including expiry check
policies.append(RFC5280Policy(validationTime: validationTime))
// Must support OCSP
policies.append(
_OCSPVerifierPolicy(
httpClient: self.httpClient,
validationTime: validationTime
)
)

self.verify(
certChain: certChain,
trustedRoots: self.trustedRoots,
policies: policies,
policies: {
_ADPCertificatePolicy() // included for testing
// Check if subject name matches
_SubjectNamePolicy(
expectedUserID: self.expectedSubjectUserID,
expectedOrganizationalUnit: self.expectedSubjectOrganizationalUnit
)
// Must be a code signing certificate
_CodeSigningPolicy()
// Basic validations including expiry check
RFC5280Policy(validationTime: validationTime)
// Must support OCSP
_OCSPVerifierPolicy(
httpClient: self.httpClient,
validationTime: validationTime
)
},
observabilityScope: self.observabilityScope,
callbackQueue: self.callbackQueue,
callback: callback
Expand Down Expand Up @@ -269,33 +264,28 @@ struct ADPSwiftPackageCollectionCertificatePolicy: CertificatePolicy {
return wrappedCallback(.failure(CertificatePolicyError.emptyCertChain))
}

var policies = [VerifierPolicy]()
// Check for specific markers
policies.append(_ADPSwiftPackageCertificatePolicy())
policies.append(_ADPCertificatePolicy()) // included for testing
// Check if subject name matches
policies.append(
_SubjectNamePolicy(
expectedUserID: self.expectedSubjectUserID,
expectedOrganizationalUnit: self.expectedSubjectOrganizationalUnit
)
)
// Must be a code signing certificate
policies.append(_CodeSigningPolicy())
// Basic validations including expiry check
policies.append(RFC5280Policy(validationTime: validationTime))
// Must support OCSP
policies.append(
_OCSPVerifierPolicy(
httpClient: self.httpClient,
validationTime: validationTime
)
)

self.verify(
certChain: certChain,
trustedRoots: self.trustedRoots,
policies: policies,
policies: {
// Check for specific markers
_ADPSwiftPackageCertificatePolicy()
_ADPCertificatePolicy() // included for testing
// Check if subject name matches
_SubjectNamePolicy(
expectedUserID: self.expectedSubjectUserID,
expectedOrganizationalUnit: self.expectedSubjectOrganizationalUnit
)
// Must be a code signing certificate
_CodeSigningPolicy()
// Basic validations including expiry check
RFC5280Policy(validationTime: validationTime)
// Must support OCSP
_OCSPVerifierPolicy(
httpClient: self.httpClient,
validationTime: validationTime
)
},
observabilityScope: self.observabilityScope,
callbackQueue: self.callbackQueue,
callback: callback
Expand Down Expand Up @@ -358,33 +348,28 @@ struct ADPAppleDistributionCertificatePolicy: CertificatePolicy {
return wrappedCallback(.failure(CertificatePolicyError.emptyCertChain))
}

var policies = [VerifierPolicy]()
// Check for specific markers
policies.append(_ADPAppleDistributionCertificatePolicy())
policies.append(_ADPCertificatePolicy()) // included for testing
// Check if subject name matches
policies.append(
_SubjectNamePolicy(
expectedUserID: self.expectedSubjectUserID,
expectedOrganizationalUnit: self.expectedSubjectOrganizationalUnit
)
)
// Must be a code signing certificate
policies.append(_CodeSigningPolicy())
// Basic validations including expiry check
policies.append(RFC5280Policy(validationTime: validationTime))
// Must support OCSP
policies.append(
_OCSPVerifierPolicy(
httpClient: self.httpClient,
validationTime: validationTime
)
)

self.verify(
certChain: certChain,
trustedRoots: self.trustedRoots,
policies: policies,
policies: {
// Check for specific markers
_ADPAppleDistributionCertificatePolicy()
_ADPCertificatePolicy() // included for testing
// Check if subject name matches
_SubjectNamePolicy(
expectedUserID: self.expectedSubjectUserID,
expectedOrganizationalUnit: self.expectedSubjectOrganizationalUnit
)
// Must be a code signing certificate
_CodeSigningPolicy()
// Basic validations including expiry check
RFC5280Policy(validationTime: validationTime)
// Must support OCSP
_OCSPVerifierPolicy(
httpClient: self.httpClient,
validationTime: validationTime
)
},
observabilityScope: self.observabilityScope,
callbackQueue: self.callbackQueue,
callback: callback
Expand Down
14 changes: 8 additions & 6 deletions Sources/PackageSigning/SignatureProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,11 @@ struct CMSSignatureProvider: SignatureProviderProtocol {
// the WWDR roots are in the trust store or not, which by default
// they are but user may disable that through configuration.
additionalIntermediateCertificates: Certificates.wwdrIntermediates,
trustRoots: CertificateStore(trustRoots),
policy: self.buildPolicySet(configuration: verifierConfiguration, httpClient: self.httpClient)
)
trustRoots: CertificateStore(trustRoots)
) {
self.buildPolicySet(configuration: verifierConfiguration, httpClient: self.httpClient)
}


switch result {
case .success(let valid):
Expand Down Expand Up @@ -341,9 +343,9 @@ struct CMSSignatureProvider: SignatureProviderProtocol {
// For self-signed certificate, the signature should include intermediate(s).
untrustedIntermediates.append(contentsOf: cmsSignature.certificates)

let policySet = self.buildPolicySet(configuration: verifierConfiguration, httpClient: self.httpClient)

var verifier = Verifier(rootCertificates: CertificateStore(trustRoots), policy: policySet)
var verifier = Verifier(rootCertificates: CertificateStore(trustRoots)) {
self.buildPolicySet(configuration: verifierConfiguration, httpClient: self.httpClient)
}
let result = await verifier.validate(
leafCertificate: signingCertificate,
intermediates: CertificateStore(untrustedIntermediates)
Expand Down
69 changes: 31 additions & 38 deletions Sources/PackageSigning/VerifierPolicies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,56 +20,49 @@ import Basics
@_implementationOnly @_spi(DisableValidityCheck) import X509

extension SignatureProviderProtocol {
func buildPolicySet(configuration: VerifierConfiguration, httpClient: HTTPClient) -> PolicySet {
var policies: [VerifierPolicy] = [
_CodeSigningPolicy(),
_ADPCertificatePolicy(),
]

@PolicyBuilder
func buildPolicySet(configuration: VerifierConfiguration, httpClient: HTTPClient) -> some VerifierPolicy {
_CodeSigningPolicy()
_ADPCertificatePolicy()

let now = Date()
switch (configuration.certificateExpiration, configuration.certificateRevocation) {
case (.enabled(let expiryValidationTime), .strict(let revocationValidationTime)):
policies.append(RFC5280Policy(validationTime: expiryValidationTime ?? now))
policies
.append(_OCSPVerifierPolicy(
failureMode: .hard,
httpClient: httpClient,
validationTime: revocationValidationTime ?? now
))
RFC5280Policy(validationTime: expiryValidationTime ?? now)
_OCSPVerifierPolicy(
failureMode: .hard,
httpClient: httpClient,
validationTime: revocationValidationTime ?? now
)
case (.enabled(let expiryValidationTime), .allowSoftFail(let revocationValidationTime)):
policies.append(RFC5280Policy(validationTime: expiryValidationTime ?? now))
policies
.append(_OCSPVerifierPolicy(
failureMode: .soft,
httpClient: httpClient,
validationTime: revocationValidationTime ?? now
))
RFC5280Policy(validationTime: expiryValidationTime ?? now)
_OCSPVerifierPolicy(
failureMode: .soft,
httpClient: httpClient,
validationTime: revocationValidationTime ?? now
)
case (.enabled(let expiryValidationTime), .disabled):
policies.append(RFC5280Policy(validationTime: expiryValidationTime ?? now))
RFC5280Policy(validationTime: expiryValidationTime ?? now)
case (.disabled, .strict(let revocationValidationTime)):
// Always do expiry check (and before) if revocation check is enabled
policies.append(RFC5280Policy(validationTime: revocationValidationTime ?? now))
policies
.append(_OCSPVerifierPolicy(
failureMode: .hard,
httpClient: httpClient,
validationTime: revocationValidationTime ?? now
))
RFC5280Policy(validationTime: revocationValidationTime ?? now)
_OCSPVerifierPolicy(
failureMode: .hard,
httpClient: httpClient,
validationTime: revocationValidationTime ?? now
)
case (.disabled, .allowSoftFail(let revocationValidationTime)):
// Always do expiry check (and before) if revocation check is enabled
policies.append(RFC5280Policy(validationTime: revocationValidationTime ?? now))
policies
.append(_OCSPVerifierPolicy(
failureMode: .soft,
httpClient: httpClient,
validationTime: revocationValidationTime ?? now
))
RFC5280Policy(validationTime: revocationValidationTime ?? now)
_OCSPVerifierPolicy(
failureMode: .soft,
httpClient: httpClient,
validationTime: revocationValidationTime ?? now
)
case (.disabled, .disabled):
// We should still do basic certificate validations even if expiry check is disabled
policies.append(RFC5280Policy.withValidityCheckDisabled())
RFC5280Policy.withValidityCheckDisabled()
}

return PolicySet(policies: policies)
}
}

Expand Down
15 changes: 7 additions & 8 deletions Tests/PackageCollectionsSigningTests/Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,16 @@ struct TestCertificatePolicy: CertificatePolicy {
validationTime: Date,
callback: @escaping (Result<Void, Error>) -> Void
) {
var policies = [VerifierPolicy]()
// Must be a code signing certificate
policies.append(_CodeSigningPolicy())
// Basic validations including expiry check
policies.append(RFC5280Policy(validationTime: validationTime))
// Doesn't require OCSP

self.verify(
certChain: certChain,
trustedRoots: self.trustedRoots,
policies: policies,
policies: {
// Must be a code signing certificate
_CodeSigningPolicy()
// Basic validations including expiry check
RFC5280Policy(validationTime: validationTime)
// Doesn't require OCSP
},
observabilityScope: ObservabilitySystem.NOOP,
callbackQueue: callbackQueue,
callback: callback
Expand Down
7 changes: 5 additions & 2 deletions Tests/PackageSigningTests/SigningTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1241,15 +1241,18 @@ extension BasicOCSPResponse {
responses: [OCSPSingleResponse],
privateKey: P256.Signing.PrivateKey,
certs: [Certificate]? = [],
@ExtensionsBuilder responseExtensions: () -> Certificate.Extensions = { .init() }
@ExtensionsBuilder responseExtensions: () throws -> Result<Certificate.Extensions, any Error> = {
// workaround for rdar://108897294
Result.success(Certificate.Extensions())
}
) throws -> Self {
try .signed(
responseData: .init(
version: version,
responderID: responderID,
producedAt: producedAt,
responses: responses,
responseExtensions: responseExtensions()
responseExtensions: try .init(builder: responseExtensions)
),
privateKey: privateKey,
certs: certs
Expand Down