TM-SGNL-iOS/SignalServiceKit/Security/HttpSecurityPolicy.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

48 lines
1.8 KiB
Swift

//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Security
/// A simplified version of AFNetworking's AFSecurityPolicy.
public struct HttpSecurityPolicy {
public static let signalCaPinned: HttpSecurityPolicy = .init(pinnedCertificates: [Certificates.load("signal-messenger", extension: "cer")])
public static let systemDefault: HttpSecurityPolicy = .init()
private let pinnedCertificates: [SecCertificate]?
public init(pinnedCertificates: [SecCertificate]? = nil) {
self.pinnedCertificates = pinnedCertificates
}
public func evaluate(serverTrust: SecTrust, domain: String?) -> Bool {
let policies = [SecPolicyCreateSSL(true, domain as CFString?)]
guard SecTrustSetPolicies(serverTrust, policies as CFArray) == errSecSuccess else {
Logger.error("the trust policy could not be set")
return false
}
// use the default anchors if none were prvided in pinnedCertificates
if let pinnedCertificates, !pinnedCertificates.isEmpty {
guard SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray) == errSecSuccess else {
Logger.error("the anchor certificates could not be set")
return false
}
}
return Self.isValid(serverTrust: serverTrust)
}
private static func isValid(serverTrust: SecTrust) -> Bool {
guard SecTrustEvaluateWithError(serverTrust, nil) else {
return false
}
var result: SecTrustResultType = .otherError // initialize to a value that would fail if SecTrustGetTrustResult doesn't overwrite it
guard SecTrustGetTrustResult(serverTrust, &result) == errSecSuccess else {
return false
}
return result == .unspecified || result == .proceed
}
}