Skip to content

Commit 15b2f4e

Browse files
authored
Merge pull request #108 from niscy-eudiw/feature/x509-updates
x509 verification addtion and updates.
2 parents fcabc28 + 20699e3 commit 15b2f4e

File tree

13 files changed

+153
-9
lines changed

13 files changed

+153
-9
lines changed

Sources/Entities/Trust/X509CertificateChainVerifier.swift

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ public enum ChainTrustResult: Equatable {
2323
case failure
2424
}
2525

26+
enum CertificateValidationError: Error {
27+
case invalidCertificateData
28+
case insufficientCertificates
29+
case signatureValidationFailed
30+
case certificateExpired
31+
case untrustedRoot
32+
case invalidChain([VerificationResult.PolicyFailure])
33+
}
34+
2635
public enum DataConversionError: Error {
2736
case conversionFailed(String)
2837
}
@@ -96,7 +105,7 @@ public struct X509CertificateChainVerifier {
96105
// Evaluate the trust
97106
var trustResult: SecTrustResultType = .invalid
98107
if SecTrustEvaluate(trust!, &trustResult) == errSecSuccess {
99-
if trustResult == .proceed || trustResult == .unspecified {
108+
if trustResult == .proceed || trustResult == .unspecified || trustResult == .recoverableTrustFailure {
100109
return true
101110
} else if trustResult == .deny || trustResult == .fatalTrustFailure {
102111
return false
@@ -173,3 +182,69 @@ private extension X509CertificateChainVerifier {
173182
}
174183
}
175184
}
185+
186+
public extension X509CertificateChainVerifier {
187+
188+
/// Converts a `SecCertificate` to `X509.Certificate`
189+
private func convertToX509Certificate(_ secCert: SecCertificate) throws -> Certificate {
190+
let derData = SecCertificateCopyData(secCert) as Data
191+
return try Certificate(derEncoded: [UInt8](derData))
192+
}
193+
194+
func verifyChain(
195+
rootBase64Certificates: [Base64Certificate],
196+
intermediateBase64Certificates: [Base64Certificate] = [],
197+
leafBase64Certificate: Base64Certificate,
198+
date: Date = Date(),
199+
showDiagnostics: Bool = false
200+
) async throws -> ChainTrustResult {
201+
202+
func decodeBase64Certificates(
203+
_ base64s: [Base64Certificate]
204+
) throws -> [Certificate] {
205+
return try convertStringsToData(base64Strings: base64s)
206+
.compactMap { SecCertificateCreateWithData(nil, $0 as CFData) }
207+
.compactMap { SecCertificateContainer(certificate: $0).certificate }
208+
.map { try convertToX509Certificate($0) }
209+
}
210+
211+
let rootX509Certs = try decodeBase64Certificates(rootBase64Certificates)
212+
let intermediateX509Certs = try decodeBase64Certificates(intermediateBase64Certificates)
213+
let leafX509Certs = try decodeBase64Certificates([leafBase64Certificate])
214+
215+
guard let leafCert = leafX509Certs.first else {
216+
throw CertificateValidationError.insufficientCertificates
217+
}
218+
219+
let roots = CertificateStore(rootX509Certs)
220+
var verifier = Verifier(
221+
rootCertificates: roots
222+
) {
223+
AnyPolicy {
224+
RFC5280Policy(
225+
validationTime: date
226+
)
227+
}
228+
}
229+
230+
let result = await verifier.validate(
231+
leafCertificate: leafCert,
232+
intermediates: .init(
233+
intermediateX509Certs
234+
)
235+
) { diagnostic in
236+
if showDiagnostics {
237+
print(diagnostic.multilineDescription)
238+
}
239+
}
240+
241+
switch result {
242+
case .validCertificate:
243+
return .success
244+
case .couldNotValidate(let policyFailures):
245+
throw CertificateValidationError.invalidChain(
246+
policyFailures
247+
)
248+
}
249+
}
250+
}

Sources/Entities/Trust/X509CertificateTrust.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Foundation
1717

1818
public typealias Base64Certificate = String
1919

20-
public typealias CertificateTrust = ([Base64Certificate]) -> Bool
20+
public typealias CertificateTrust = ([Base64Certificate]) async -> Bool
2121

2222
public protocol X509CertificateTrustType {
2323
func isTrusted(chain: [Base64Certificate]) -> Bool

Sources/Main/Validators/AccessValidator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public actor AccessValidator: AccessValidating {
113113
switch supportedClientIdScheme {
114114
case .x509SanDns(let trust),
115115
.x509SanUri(let trust):
116-
let trust = trust(chain)
116+
let trust = await trust(chain)
117117
if !trust {
118118
throw ValidationError.validationError("Could not trust certificate chain")
119119
}
727 Bytes
Binary file not shown.
726 Bytes
Binary file not shown.
727 Bytes
Binary file not shown.
727 Bytes
Binary file not shown.
726 Bytes
Binary file not shown.
738 Bytes
Binary file not shown.
737 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)