import Foundation
import Security
public struct CodeIdentity {
private let requirement: SecRequirement
public init(referenceURL: URL? = nil) throws {
var reference: SecStaticCode?
if let referenceURL {
guard SecStaticCodeCreateWithPath(referenceURL as CFURL, [], &reference) == errSecSuccess else {
throw Failure("Cannot inspect trusted helper")
}
} else {
var running: SecCode?
guard SecCodeCopySelf([], &running) == errSecSuccess, let running,
SecCodeCopyStaticCode(running, [], &reference) == errSecSuccess else {
throw Failure("Cannot inspect running helper identity")
}
}
var designated: SecRequirement?
guard let reference,
SecStaticCodeCheckValidity(reference, SecCSFlags(rawValue: kSecCSStrictValidate | kSecCSCheckAllArchitectures), nil) == errSecSuccess,
SecCodeCopyDesignatedRequirement(reference, [], &designated) == errSecSuccess, let designated else {
throw Failure("Trusted helper has no valid code identity")
}
requirement = designated
}
public func validate(_ candidate: URL) throws {
var code: SecStaticCode?
guard SecStaticCodeCreateWithPath(candidate as CFURL, [], &code) == errSecSuccess, let code,
SecStaticCodeCheckValidity(code, SecCSFlags(rawValue: kSecCSStrictValidate | kSecCSCheckAllArchitectures), requirement) == errSecSuccess else {
throw Failure("Guest helper update is invalid or has a different signing identity")
}
}
}