xcode-simulator-cert/Sources/XcodeSimulatorKit/Trust Store/Certificate.swift

90 lines
2.7 KiB
Swift

//
// Copyright © 2019 Simon Kågedal Reimer. See LICENSE.
//
import Foundation
import Security
struct Certificate {
enum Error: LocalizedError {
case invalidDERX509
case importError(OSStatus)
case notACertficate
case unknown
var errorDescription: String? {
switch self {
case .invalidDERX509:
return "Given data was not a valid DER encoded X.509 certificate"
case .importError(let status):
return "Error from SecItemImport: \(status)"
case .notACertficate:
return "SecItemImport gave something else than a certificate"
case .unknown:
return "Operation completed with an unknown error from the Security framework"
}
}
}
private let certificate: SecCertificate
init(_ data: Data) throws {
guard let certificate = SecCertificateCreateWithData(nil, data as CFData) else {
throw Error.invalidDERX509
}
self.certificate = certificate
}
var subjectSummary: String? {
return SecCertificateCopySubjectSummary(certificate) as String?
}
func normalizedSubjectSequence() throws -> Data {
var error: Unmanaged<CFError>?
guard let data = SecCertificateCopyNormalizedSubjectContent(certificate, &error) else {
guard let error = error else {
throw Error.unknown
}
throw error.takeRetainedValue()
}
return data as Data
}
func normalizedSubjectContent() throws -> Data {
var error: Unmanaged<CFError>?
guard let data = SecCertificateCopyNormalizedSubjectContent(certificate, &error) else {
guard let error = error else {
throw Error.unknown
}
throw error.takeRetainedValue()
}
return data as Data
}
func printInfo() {
if let summary = subjectSummary {
print(summary)
} else {
print("<unknown certificate>")
}
}
static func load(from url: URL) throws -> SecCertificate {
let data = try Data(contentsOf: url)
var cfitems: CFArray?
var format = SecExternalFormat.formatUnknown
var type = SecExternalItemType.itemTypeUnknown
let status = SecItemImport(data as CFData, url.lastPathComponent as CFString, &format, &type, [], nil, nil, &cfitems)
guard status == errSecSuccess else {
throw Error.importError(status)
}
guard type == .itemTypeCertificate, let items = cfitems as? [SecCertificate], let item = items.first else {
throw Error.notACertficate
}
return item
}
}