Skip to content

Instantly share code, notes, and snippets.

@oozoofrog
Last active April 9, 2017 02:49
Show Gist options
  • Save oozoofrog/a3e321a6b0d0288045f3620818f8c6ae to your computer and use it in GitHub Desktop.
Save oozoofrog/a3e321a6b0d0288045f3620818f8c6ae to your computer and use it in GitHub Desktop.
swift Security status
import Foundation
import Security
public struct SwiftSecurity {
public enum SwiftSecurityError: Error {
case error(SecStatus)
}
public static func del<KEY: Hashable>(query: [KEY : Any]) throws {
guard let status = SecStatus.from(status: SecItemDelete(query as CFDictionary)), status != .Success else {
return
}
throw SwiftSecurityError.error(status)
}
public static func add<KEY: Hashable>(item: [KEY : Any]) throws {
var result: CFTypeRef?
defer {
print(result ?? "result none")
}
guard let status = SecStatus.from(status: SecItemAdd(item as CFDictionary, &result)), status != .Success else {
return
}
throw SwiftSecurityError.error(status)
}
public static func get<KEY: Hashable>(query: [KEY : Any]) throws -> CFTypeRef? {
var value: CFTypeRef?
let status = SecStatus.from(status: SecItemCopyMatching(query as CFDictionary, &value))
if value == nil {
throw SwiftSecurityError.error(.ItemNotFound)
} else if let status = status, status != .Success {
throw SwiftSecurityError.error(status)
}
return value
}
}
public struct SecStatus: CustomStringConvertible, Hashable, Equatable {
public static func ==(lhs: SecStatus, rhs: SecStatus) -> Bool {
return lhs.hashValue == rhs.hashValue
}
public static let Success = SecStatus(status: errSecSuccess)
public static let Unimplemented = SecStatus(status: errSecUnimplemented)
public static let DskFull = SecStatus(status: errSecDskFull)
public static let IO = SecStatus(status: errSecIO)
public static let Param = SecStatus(status: errSecParam)
public static let WrPerm = SecStatus(status: errSecWrPerm)
public static let Allocate = SecStatus(status: errSecAllocate)
public static let UserCanceled = SecStatus(status: errSecUserCanceled)
public static let BadReq = SecStatus(status: errSecBadReq)
public static let InternalComponent = SecStatus(status: errSecInternalComponent)
public static let CoreFoundationUnknown = SecStatus(status: errSecCoreFoundationUnknown)
public static let NotAvailable = SecStatus(status: errSecNotAvailable)
public static let ReadOnly = SecStatus(status: errSecReadOnly)
public static let AuthFailed = SecStatus(status: errSecAuthFailed)
public static let NoSuchKeychain = SecStatus(status: errSecNoSuchKeychain)
public static let InvalidKeychain = SecStatus(status: errSecInvalidKeychain)
public static let DuplicateKeychain = SecStatus(status: errSecDuplicateKeychain)
public static let DuplicateCallback = SecStatus(status: errSecDuplicateCallback)
public static let InvalidCallback = SecStatus(status: errSecInvalidCallback)
public static let DuplicateItem = SecStatus(status: errSecDuplicateItem)
public static let ItemNotFound = SecStatus(status: errSecItemNotFound)
public static let BufferTooSmall = SecStatus(status: errSecBufferTooSmall)
public static let DataTooLarge = SecStatus(status: errSecDataTooLarge)
public static let NoSuchAttr = SecStatus(status: errSecNoSuchAttr)
public static let InvalidItemRef = SecStatus(status: errSecInvalidItemRef)
public static let InvalidSearchRef = SecStatus(status: errSecInvalidSearchRef)
public static let NoSuchClass = SecStatus(status: errSecNoSuchClass)
public static let NoDefaultKeychain = SecStatus(status: errSecNoDefaultKeychain)
public static let InteractionNotAllowed = SecStatus(status: errSecInteractionNotAllowed)
public static let ReadOnlyAttr = SecStatus(status: errSecReadOnlyAttr)
public static let WrongSecVersion = SecStatus(status: errSecWrongSecVersion)
public static let KeySizeNotAllowed = SecStatus(status: errSecKeySizeNotAllowed)
public static let NoStorageModule = SecStatus(status: errSecNoStorageModule)
public static let NoCertificateModule = SecStatus(status: errSecNoCertificateModule)
public static let NoPolicyModule = SecStatus(status: errSecNoPolicyModule)
public static let InteractionRequired = SecStatus(status: errSecInteractionRequired)
public static let DataNotAvailable = SecStatus(status: errSecDataNotAvailable)
public static let DataNotModifiable = SecStatus(status: errSecDataNotModifiable)
public static let CreateChainFailed = SecStatus(status: errSecCreateChainFailed)
public static let ACLNotSimple = SecStatus(status: errSecACLNotSimple)
public static let PolicyNotFound = SecStatus(status: errSecPolicyNotFound)
public static let InvalidTrustSetting = SecStatus(status: errSecInvalidTrustSetting)
public static let NoAccessForItem = SecStatus(status: errSecNoAccessForItem)
public static let InvalidOwnerEdit = SecStatus(status: errSecInvalidOwnerEdit)
public static let TrustNotAvailable = SecStatus(status: errSecTrustNotAvailable)
public static let UnsupportedFormat = SecStatus(status: errSecUnsupportedFormat)
public static let UnknownFormat = SecStatus(status: errSecUnknownFormat)
public static let KeyIsSensitive = SecStatus(status: errSecKeyIsSensitive)
public static let MultiplePrivKeys = SecStatus(status: errSecMultiplePrivKeys)
public static let PassphraseRequired = SecStatus(status: errSecPassphraseRequired)
public static let InvalidPasswordRef = SecStatus(status: errSecInvalidPasswordRef)
public static let InvalidTrustSettings = SecStatus(status: errSecInvalidTrustSettings)
public static let NoTrustSettings = SecStatus(status: errSecNoTrustSettings)
public static let Pkcs12VerifyFailure = SecStatus(status: errSecPkcs12VerifyFailure)
public static let Decode = SecStatus(status: errSecDecode)
public let status: OSStatus
public var message: String { return statusMessage(status: self.status) }
public var code: String { return statusCode(status: self.status) }
public var description: String { return "SecStatus: \(self.code), \(self.message)"}
private static let statuses: [SecStatus] = [Success, Unimplemented, DskFull, IO, Param, WrPerm, Allocate, UserCanceled, BadReq, InternalComponent, CoreFoundationUnknown, NotAvailable, ReadOnly, AuthFailed, NoSuchKeychain, InvalidKeychain, DuplicateKeychain, DuplicateCallback, InvalidCallback, DuplicateItem, ItemNotFound, BufferTooSmall, DataTooLarge, NoSuchAttr, InvalidItemRef, InvalidSearchRef, NoSuchClass, NoDefaultKeychain, InteractionNotAllowed, ReadOnlyAttr, WrongSecVersion, KeySizeNotAllowed, NoStorageModule, NoCertificateModule, NoPolicyModule, InteractionRequired, DataNotAvailable, DataNotModifiable, CreateChainFailed, ACLNotSimple, PolicyNotFound, InvalidTrustSetting, NoAccessForItem, InvalidOwnerEdit, TrustNotAvailable, UnsupportedFormat, UnknownFormat, KeyIsSensitive, MultiplePrivKeys, PassphraseRequired, InvalidPasswordRef, InvalidTrustSettings, NoTrustSettings, Pkcs12VerifyFailure, Decode]
private init() { fatalError("Don't use init") }
private init(status _status: OSStatus) {
status = _status
}
public var hashValue: Int { return Int(self.status) }
public static func from(status: OSStatus) -> SecStatus? {
return statuses.filter{ $0.status == status }.first
}
func statusCode(status: OSStatus) -> String {
switch status {
case errSecSuccess: return "errSecSuccess"
case errSecUnimplemented: return "errSecUnimplemented"
case errSecDskFull: return "errSecDskFull"
case errSecIO: return "errSecIO"
case errSecParam: return "errSecParam"
case errSecWrPerm: return "errSecWrPerm"
case errSecAllocate: return "errSecAllocate"
case errSecUserCanceled: return "errSecUserCanceled"
case errSecBadReq: return "errSecBadReq"
case errSecInternalComponent: return "errSecInternalComponent"
case errSecCoreFoundationUnknown: return "errSecCoreFoundationUnknown"
case errSecNotAvailable: return "errSecNotAvailable"
case errSecReadOnly: return "errSecReadOnly"
case errSecAuthFailed: return "errSecAuthFailed"
case errSecNoSuchKeychain: return "errSecNoSuchKeychain"
case errSecInvalidKeychain: return "errSecInvalidKeychain"
case errSecDuplicateKeychain: return "errSecDuplicateKeychain"
case errSecDuplicateCallback: return "errSecDuplicateCallback"
case errSecInvalidCallback: return "errSecInvalidCallback"
case errSecDuplicateItem: return "errSecDuplicateItem"
case errSecItemNotFound: return "errSecItemNotFound"
case errSecBufferTooSmall: return "errSecBufferTooSmall"
case errSecDataTooLarge: return "errSecDataTooLarge"
case errSecNoSuchAttr: return "errSecNoSuchAttr"
case errSecInvalidItemRef: return "errSecInvalidItemRef"
case errSecInvalidSearchRef: return "errSecInvalidSearchRef"
case errSecNoSuchClass: return "errSecNoSuchClass"
case errSecNoDefaultKeychain: return "errSecNoDefaultKeychain"
case errSecInteractionNotAllowed: return "errSecInteractionNotAllowed"
case errSecReadOnlyAttr: return "errSecReadOnlyAttr"
case errSecWrongSecVersion: return "errSecWrongSecVersion"
case errSecKeySizeNotAllowed: return "errSecKeySizeNotAllowed"
case errSecNoStorageModule: return "errSecNoStorageModule"
case errSecNoCertificateModule: return "errSecNoCertificateModule"
case errSecNoPolicyModule: return "errSecNoPolicyModule"
case errSecInteractionRequired: return "errSecInteractionRequired"
case errSecDataNotAvailable: return "errSecDataNotAvailable"
case errSecDataNotModifiable: return "errSecDataNotModifiable"
case errSecCreateChainFailed: return "errSecCreateChainFailed"
case errSecACLNotSimple: return "errSecACLNotSimple"
case errSecPolicyNotFound: return "errSecPolicyNotFound"
case errSecInvalidTrustSetting: return "errSecInvalidTrustSetting"
case errSecNoAccessForItem: return "errSecNoAccessForItem"
case errSecInvalidOwnerEdit: return "errSecInvalidOwnerEdit"
case errSecTrustNotAvailable: return "errSecTrustNotAvailable"
case errSecUnsupportedFormat: return "errSecUnsupportedFormat"
case errSecUnknownFormat: return "errSecUnknownFormat"
case errSecKeyIsSensitive: return "errSecKeyIsSensitive"
case errSecMultiplePrivKeys: return "errSecMultiplePrivKeys"
case errSecPassphraseRequired: return "errSecPassphraseRequired"
case errSecInvalidPasswordRef: return "errSecInvalidPasswordRef"
case errSecInvalidTrustSettings: return "errSecInvalidTrustSettings"
case errSecNoTrustSettings: return "errSecNoTrustSettings"
case errSecPkcs12VerifyFailure: return "errSecPkcs12VerifyFailure"
case errSecDecode: return "errSecDecode"
default: return ""
}
}
func statusMessage(status: OSStatus) -> String {
switch status {
case errSecSuccess: return "No error."
case errSecUnimplemented: return "Function or operation not implemented."
case errSecDskFull: return "Disk Full error."
case errSecIO: return "I/O error."
case errSecParam: return "One or more parameters passed to a function were not valid."
case errSecWrPerm: return " Write permissions error."
case errSecAllocate: return "Failed to allocate memory."
case errSecUserCanceled: return "User canceled the operation."
case errSecBadReq: return "Bad parameter or invalid state for operation."
case errSecInternalComponent: return "errSecInternalComponent"
case errSecCoreFoundationUnknown: return "errSecCoreFoundationUnknown"
case errSecNotAvailable: return "No keychain is available."
case errSecReadOnly: return "Read only error."
case errSecAuthFailed: return "Authorization/Authentication failed."
case errSecNoSuchKeychain: return "The keychain does not exist."
case errSecInvalidKeychain: return "The keychain is not valid."
case errSecDuplicateKeychain: return "A keychain with the same name already exists."
case errSecDuplicateCallback: return "The specified callback is already installed."
case errSecInvalidCallback: return "The specified callback is not valid."
case errSecDuplicateItem: return "The item already exists."
case errSecItemNotFound: return "The item cannot be found."
case errSecBufferTooSmall: return "The buffer is too small."
case errSecDataTooLarge: return "The data is too large."
case errSecNoSuchAttr: return "The attribute does not exist."
case errSecInvalidItemRef: return "The item reference is invalid."
case errSecInvalidSearchRef: return "The search reference is invalid."
case errSecNoSuchClass: return "The keychain item class does not exist."
case errSecNoDefaultKeychain: return "A default keychain does not exist."
case errSecInteractionNotAllowed: return "User interaction is not allowed."
case errSecReadOnlyAttr: return "The attribute is read only."
case errSecWrongSecVersion: return "The version is incorrect."
case errSecKeySizeNotAllowed: return "The key size is not allowed."
case errSecNoStorageModule: return "There is no storage module available."
case errSecNoCertificateModule: return "There is no certificate module available."
case errSecNoPolicyModule: return "There is no policy module available."
case errSecInteractionRequired: return "User interaction is required."
case errSecDataNotAvailable: return "The data is not available."
case errSecDataNotModifiable: return "The data is not modifiable."
case errSecCreateChainFailed: return "The attempt to create a certificate chain failed."
case errSecACLNotSimple: return "The access control list is not in standard simple form."
case errSecPolicyNotFound: return "The policy specified cannot be found."
case errSecInvalidTrustSetting: return "The specified trust setting is invalid."
case errSecNoAccessForItem: return "The specified item has no access control."
case errSecInvalidOwnerEdit: return "Invalid attempt to change the owner of this item."
case errSecTrustNotAvailable: return "No trust results are available."
case errSecUnsupportedFormat: return "Import/Export format unsupported."
case errSecUnknownFormat: return "Unknown format in import."
case errSecKeyIsSensitive: return "Key material must be wrapped for export."
case errSecMultiplePrivKeys: return "An attempt was made to import multiple private keys."
case errSecPassphraseRequired: return "Passphrase is required for import/export."
case errSecInvalidPasswordRef: return "The password reference was invalid."
case errSecInvalidTrustSettings: return "The Trust Settings Record was corrupted."
case errSecNoTrustSettings: return "No Trust Settings were found."
case errSecPkcs12VerifyFailure: return "MAC verification failed during PKCS12 Import."
case errSecDecode: return "Unable to decode the provided data."
default: return ""
}
}
}
public protocol CFStringHashable: Hashable, Equatable {}
extension CFStringHashable where Self: CFString {
public var hashValue: Int {
guard let string = self as? String else { return 0 }
return string.hashValue
}
public static func ==(lhs: Self, rhs: Self) -> Bool {
guard let lhsString = lhs as? String else { return false }
guard let rhsString = rhs as? String else { return false }
return lhsString == rhsString
}
}
extension CFString : CFStringHashable {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment