3 Commits

Author SHA1 Message Date
Bram Kolkman
a7cdef977b SecItem
* Added a SecItem enum to wrap existing security API functions
* Updated the SecError to easily create an error from an OSStatus
* Updated the SecError.Code to be more future proof and performant
* Removed the unused Keychain.swift file
2026-02-23 14:09:05 +01:00
af8a434577 SecError
* Added the SecError to throw when interacting with the Keychain
* Added the SecError.Code to wrap the status codes thrown by interacting
  with the Keychain

Co-authored-by: Bram Kolkman <bramkolkman@thinkerium.nl>
Reviewed-on: #2
2026-02-23 13:03:28 +00:00
b57041f0f7 Swift package
* Added the Keychain package
* Added a Makefile to easily build the package
* Added a Gitea pull request action
* Updated the README with additional information

Co-authored-by: Bram Kolkman <bramkolkman@thinkerium.com>
Reviewed-on: #1
2026-02-23 09:11:09 +00:00
9 changed files with 1032 additions and 3 deletions

18
.gitea/workflows/pr.yml Normal file
View File

@@ -0,0 +1,18 @@
name: Build
on:
pull_request:
jobs:
build:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Resolve dependencies
run: make resolve
- name: Build package
run: make build

5
.gitignore vendored
View File

@@ -9,7 +9,8 @@ xcuserdata/
.LSOverride .LSOverride
# Icon must end with two \r # Icon must end with two \r
Icon Icon
# Thumbnails # Thumbnails
._* ._*
@@ -60,7 +61,7 @@ playground.xcworkspace
# #
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project # hence it is not needed unless you have added a package configuration file to your project
# hence it is not needed unless you have added a package configuration file to your project .swiftpm
.build/ .build/

15
Keychain/Package.resolved Normal file
View File

@@ -0,0 +1,15 @@
{
"originHash" : "60d3d428473214be2374da47614464243c913251a95cfad9c1f8331314114aba",
"pins" : [
{
"identity" : "swiftlintplugins",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SimplyDanny/SwiftLintPlugins",
"state" : {
"revision" : "8a4640d14777685ba8f14e832373160498fbab92",
"version" : "0.63.2"
}
}
],
"version" : 3
}

29
Keychain/Package.swift Normal file
View File

@@ -0,0 +1,29 @@
// swift-tools-version: 6.2
import PackageDescription
let package = Package(
name: "Keychain",
platforms: [
.macOS(.v12)
],
products: [
.library(
name: "Keychain",
targets: [
"Keychain"
]
)
],
dependencies: [
.package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", from: "0.63.2")
],
targets: [
.target(
name: "Keychain",
plugins: [
.plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLintPlugins")
]
)
]
)

View File

@@ -0,0 +1,772 @@
//
// SecError+Code.swift
// Keychain
//
// Created by Bram Kolkman on 23/02/2026.
//
import Security
extension SecError {
/// Security error codes.
public struct Code: RawRepresentable, Hashable, Sendable { // swiftlint:disable:this type_body_length
/// The raw error status.
public let rawValue: OSStatus
/// Create the code from the raw error status.
/// - Parameter rawValue: The raw error status.
public init(rawValue: OSStatus) {
self.rawValue = rawValue
}
/// Function or operation not implemented.
@inlinable public static var unimplemented: Self { Code(rawValue: -4) }
/// The disk is full.
@inlinable public static var diskFull: Self { Code(rawValue: -34) }
/// I/O error.
@inlinable public static var io: Self { Code(rawValue: -36) } // swiftlint:disable:this identifier_name
/// File already open with write permission.
@inlinable public static var opWr: Self { Code(rawValue: -49) }
/// One or more parameters passed to a function were not valid.
@inlinable public static var param: Self { Code(rawValue: -50) }
/// Write permissions error.
@inlinable public static var wrPerm: Self { Code(rawValue: -61) }
/// Failed to allocate memory.
@inlinable public static var allocate: Self { Code(rawValue: -108) }
/// User canceled the operation.
@inlinable public static var userCanceled: Self { Code(rawValue: -128) }
/// Bad parameter or invalid state for operation.
@inlinable public static var badReq: Self { Code(rawValue: -909) }
@inlinable public static var internalComponent: Self { Code(rawValue: -2070) }
@inlinable public static var coreFoundationUnknown: Self { Code(rawValue: -4960) }
/// A required entitlement isn't present.
@inlinable public static var missingEntitlement: Self { Code(rawValue: -34018) }
/// Client is restricted and is not permitted to perform this operation.
@inlinable public static var restrictedAPI: Self { Code(rawValue: -34020) }
/// No keychain is available. You may need to restart your computer.
@inlinable public static var notAvailable: Self { Code(rawValue: -25291) }
/// This keychain cannot be modified.
@inlinable public static var readOnly: Self { Code(rawValue: -25292) }
/// The user name or passphrase you entered is not correct.
@inlinable public static var authFailed: Self { Code(rawValue: -25293) }
/// The specified keychain could not be found.
@inlinable public static var noSuchKeychain: Self { Code(rawValue: -25294) }
/// The specified keychain is not a valid keychain file.
@inlinable public static var invalidKeychain: Self { Code(rawValue: -25295) }
/// A keychain with the same name already exists.
@inlinable public static var duplicateKeychain: Self { Code(rawValue: -25296) }
/// The specified callback function is already installed.
@inlinable public static var duplicateCallback: Self { Code(rawValue: -25297) }
/// The specified callback function is not valid.
@inlinable public static var invalidCallback: Self { Code(rawValue: -25298) }
/// The specified item already exists in the keychain.
@inlinable public static var duplicateItem: Self { Code(rawValue: -25299) }
/// The specified item could not be found in the keychain.
@inlinable public static var itemNotFound: Self { Code(rawValue: -25300) }
/// There is not enough memory available to use the specified item.
@inlinable public static var bufferTooSmall: Self { Code(rawValue: -25301) }
/// This item contains information which is too large or in a format that cannot be displayed.
@inlinable public static var dataTooLarge: Self { Code(rawValue: -25302) }
/// The specified attribute does not exist.
@inlinable public static var noSuchAttr: Self { Code(rawValue: -25303) }
/// The specified item is no longer valid. It may have been deleted from the keychain.
@inlinable public static var invalidItemRef: Self { Code(rawValue: -25304) }
/// Unable to search the current keychain.
@inlinable public static var invalidSearchRef: Self { Code(rawValue: -25305) }
/// The specified item does not appear to be a valid keychain item.
@inlinable public static var noSuchClass: Self { Code(rawValue: -25306) }
/// A default keychain could not be found.
@inlinable public static var noDefaultKeychain: Self { Code(rawValue: -25307) }
/// User interaction is not allowed.
@inlinable public static var interactionNotAllowed: Self { Code(rawValue: -25308) }
/// The specified attribute could not be modified.
@inlinable public static var readOnlyAttr: Self { Code(rawValue: -25309) }
/// This keychain was created by a different version of the system software and cannot be opened.
@inlinable public static var wrongSecVersion: Self { Code(rawValue: -25310) }
/// This item specifies a key size which is too large or too small.
@inlinable public static var keySizeNotAllowed: Self { Code(rawValue: -25311) }
/// A required component (data storage module) could not be loaded. You may need to restart your computer.
@inlinable public static var noStorageModule: Self { Code(rawValue: -25312) }
/// A required component (certificate module) could not be loaded. You may need to restart your computer.
@inlinable public static var noCertificateModule: Self { Code(rawValue: -25313) }
/// A required component (policy module) could not be loaded. You may need to restart your computer.
@inlinable public static var noPolicyModule: Self { Code(rawValue: -25314) }
/// User interaction is required, but is currently not allowed.
@inlinable public static var interactionRequired: Self { Code(rawValue: -25315) }
/// The contents of this item cannot be retrieved.
@inlinable public static var dataNotAvailable: Self { Code(rawValue: -25316) }
/// The contents of this item cannot be modified.
@inlinable public static var dataNotModifiable: Self { Code(rawValue: -25317) }
/// One or more certificates required to validate this certificate cannot be found.
@inlinable public static var createChainFailed: Self { Code(rawValue: -25318) }
/// The specified preferences domain is not valid.
@inlinable public static var invalidPrefsDomain: Self { Code(rawValue: -25319) }
/// In dark wake, no UI possible.
@inlinable public static var inDarkWake: Self { Code(rawValue: -25320) }
/// The specified access control list is not in standard (simple) form.
@inlinable public static var aclNotSimple: Self { Code(rawValue: -25240) }
/// The specified policy cannot be found.
@inlinable public static var policyNotFound: Self { Code(rawValue: -25241) }
/// The specified trust setting is invalid.
@inlinable public static var invalidTrustSetting: Self { Code(rawValue: -25242) }
/// The specified item has no access control.
@inlinable public static var noAccessForItem: Self { Code(rawValue: -25243) }
/// Invalid attempt to change the owner of this item.
@inlinable public static var invalidOwnerEdit: Self { Code(rawValue: -25244) }
/// No trust results are available.
@inlinable public static var trustNotAvailable: Self { Code(rawValue: -25245) }
/// Import/Export format unsupported.
@inlinable public static var unsupportedFormat: Self { Code(rawValue: -25256) }
/// Unknown format in import.
@inlinable public static var unknownFormat: Self { Code(rawValue: -25257) }
/// Key material must be wrapped for export.
@inlinable public static var keyIsSensitive: Self { Code(rawValue: -25258) }
/// An attempt was made to import multiple private keys.
@inlinable public static var multiplePrivKeys: Self { Code(rawValue: -25259) }
/// Passphrase is required for import/export.
@inlinable public static var passphraseRequired: Self { Code(rawValue: -25260) }
/// The password reference was invalid.
@inlinable public static var invalidPasswordRef: Self { Code(rawValue: -25261) }
/// The Trust Settings Record was corrupted.
@inlinable public static var invalidTrustSettings: Self { Code(rawValue: -25262) }
/// No Trust Settings were found.
@inlinable public static var noTrustSettings: Self { Code(rawValue: -25263) }
/// MAC verification failed during PKCS12 import (wrong password?)
@inlinable public static var pkcs12VerifyFailure: Self { Code(rawValue: -25264) }
/// A certificate was not signed by its proposed parent.
@inlinable public static var notSigner: Self { Code(rawValue: -26267) }
/// Unable to decode the provided data.
@inlinable public static var decode: Self { Code(rawValue: -26275) }
/// The required service is not available.
@inlinable public static var serviceNotAvailable: Self { Code(rawValue: -67585) }
/// The client ID is not correct.
@inlinable public static var insufficientClientID: Self { Code(rawValue: -67586) }
/// A device reset has occurred.
@inlinable public static var deviceReset: Self { Code(rawValue: -67587) }
/// A device failure has occurred.
@inlinable public static var deviceFailed: Self { Code(rawValue: -67588) }
/// Adding an application ACL subject failed.
@inlinable public static var appleAddAppACLSubject: Self { Code(rawValue: -67589) }
/// The public key is incomplete.
@inlinable public static var applePublicKeyIncomplete: Self { Code(rawValue: -67590) }
/// A signature mismatch has occurred.
@inlinable public static var appleSignatureMismatch: Self { Code(rawValue: -67591) }
/// The specified key has an invalid start date.
@inlinable public static var appleInvalidKeyStartDate: Self { Code(rawValue: -67592) }
/// The specified key has an invalid end date.
@inlinable public static var appleInvalidKeyEndDate: Self { Code(rawValue: -67593) }
/// A conversion error has occurred.
@inlinable public static var conversionError: Self { Code(rawValue: -67594) }
/// A SSLv2 rollback error has occurred.
@inlinable public static var appleSSLv2Rollback: Self { Code(rawValue: -67595) }
/// The quota was exceeded.
@inlinable public static var quotaExceeded: Self { Code(rawValue: -67596) }
/// The file is too big.
@inlinable public static var fileTooBig: Self { Code(rawValue: -67597) }
/// The specified database has an invalid blob.
@inlinable public static var invalidDatabaseBlob: Self { Code(rawValue: -67598) }
/// The specified database has an invalid key blob.
@inlinable public static var invalidKeyBlob: Self { Code(rawValue: -67599) }
/// The specified database has an incompatible blob.
@inlinable public static var incompatibleDatabaseBlob: Self { Code(rawValue: -67600) }
/// The specified database has an incompatible key blob.
@inlinable public static var incompatibleKeyBlob: Self { Code(rawValue: -67601) }
/// A host name mismatch has occurred.
@inlinable public static var hostNameMismatch: Self { Code(rawValue: -67602) }
/// There is an unknown critical extension flag.
@inlinable public static var unknownCriticalExtensionFlag: Self { Code(rawValue: -67603) }
/// No basic constraints were found.
@inlinable public static var noBasicConstraints: Self { Code(rawValue: -67604) }
/// No basic CA constraints were found.
@inlinable public static var noBasicConstraintsCA: Self { Code(rawValue: -67605) }
/// The authority key ID is not valid.
@inlinable public static var invalidAuthorityKeyID: Self { Code(rawValue: -67606) }
/// The subject key ID is not valid.
@inlinable public static var invalidSubjectKeyID: Self { Code(rawValue: -67607) }
/// The key usage is not valid for the specified policy.
@inlinable public static var invalidKeyUsageForPolicy: Self { Code(rawValue: -67608) }
/// The extended key usage is not valid.
@inlinable public static var invalidExtendedKeyUsage: Self { Code(rawValue: -67609) }
/// The ID linkage is not valid.
@inlinable public static var invalidIDLinkage: Self { Code(rawValue: -67610) }
/// The path length constraint was exceeded.
@inlinable public static var pathLengthConstraintExceeded: Self { Code(rawValue: -67611) }
/// The root or anchor certificate is not valid.
@inlinable public static var invalidRoot: Self { Code(rawValue: -67612) }
/// The CRL has expired.
@inlinable public static var crlExpired: Self { Code(rawValue: -67613) }
/// The CRL is not yet valid.
@inlinable public static var crlNotValidYet: Self { Code(rawValue: -67614) }
/// The CRL was not found.
@inlinable public static var crlNotFound: Self { Code(rawValue: -67615) }
/// The CRL server is down.
@inlinable public static var crlServerDown: Self { Code(rawValue: -67616) }
/// The CRL has a bad Uniform Resource Identifier.
@inlinable public static var crlBadURI: Self { Code(rawValue: -67617) }
/// An unknown certificate extension was encountered.
@inlinable public static var unknownCertExtension: Self { Code(rawValue: -67618) }
/// An unknown CRL extension was encountered.
@inlinable public static var unknownCRLExtension: Self { Code(rawValue: -67619) }
/// The CRL is not trusted.
@inlinable public static var crlNotTrusted: Self { Code(rawValue: -67620) }
/// The CRL policy failed.
@inlinable public static var crlPolicyFailed: Self { Code(rawValue: -67621) }
/// The issuing distribution point was not valid.
@inlinable public static var idpFailure: Self { Code(rawValue: -67622) }
/// An email address mismatch was encountered.
@inlinable public static var smimeEmailAddressesNotFound: Self { Code(rawValue: -67623) }
/// The appropriate extended key usage for SMIME was not found.
@inlinable public static var smimeBadExtendedKeyUsage: Self { Code(rawValue: -67624) }
/// The key usage is not compatible with SMIME.
@inlinable public static var smimeBadKeyUsage: Self { Code(rawValue: -67625) }
/// The key usage extension is not marked as critical.
@inlinable public static var smimeKeyUsageNotCritical: Self { Code(rawValue: -67626) }
/// No email address was found in the certificate.
@inlinable public static var smimeNoEmailAddress: Self { Code(rawValue: -67627) }
/// The subject alternative name extension is not marked as critical.
@inlinable public static var smimeSubjAltNameNotCritical: Self { Code(rawValue: -67628) }
/// The appropriate extended key usage for SSL was not found.
@inlinable public static var sslBadExtendedKeyUsage: Self { Code(rawValue: -67629) }
/// The OCSP response was incorrect or could not be parsed.
@inlinable public static var ocspBadResponse: Self { Code(rawValue: -67630) }
/// The OCSP request was incorrect or could not be parsed.
@inlinable public static var ocspBadRequest: Self { Code(rawValue: -67631) }
/// OCSP service is unavailable.
@inlinable public static var ocspUnavailable: Self { Code(rawValue: -67632) }
/// The OCSP server did not recognize this certificate.
@inlinable public static var ocspStatusUnrecognized: Self { Code(rawValue: -67633) }
/// An end-of-data was detected.
@inlinable public static var endOfData: Self { Code(rawValue: -67634) }
/// An incomplete certificate revocation check occurred.
@inlinable public static var incompleteCertRevocationCheck: Self { Code(rawValue: -67635) }
/// A network failure occurred.
@inlinable public static var networkFailure: Self { Code(rawValue: -67636) }
/// The OCSP response was not trusted to a root or anchor certificate.
@inlinable public static var ocspNotTrustedToAnchor: Self { Code(rawValue: -67637) }
/// The record was modified.
@inlinable public static var recordModified: Self { Code(rawValue: -67638) }
/// The OCSP response had an invalid signature.
@inlinable public static var ocspSignatureError: Self { Code(rawValue: -67639) }
/// The OCSP response had no signer.
@inlinable public static var ocspNoSigner: Self { Code(rawValue: -67640) }
/// The OCSP responder was given a malformed request.
@inlinable public static var ocspResponderMalformedReq: Self { Code(rawValue: -67641) }
/// The OCSP responder encountered an internal error.
@inlinable public static var ocspResponderInternalError: Self { Code(rawValue: -67642) }
/// The OCSP responder is busy, try again later.
@inlinable public static var ocspResponderTryLater: Self { Code(rawValue: -67643) }
/// The OCSP responder requires a signature.
@inlinable public static var ocspResponderSignatureRequired: Self { Code(rawValue: -67644) }
/// The OCSP responder rejected this request as unauthorized.
@inlinable public static var ocspResponderUnauthorized: Self { Code(rawValue: -67645) }
/// The OCSP response nonce did not match the request.
@inlinable public static var ocspResponseNonceMismatch: Self { Code(rawValue: -67646) }
/// Code signing encountered an incorrect certificate chain length.
@inlinable public static var codeSigningBadCertChainLength: Self { Code(rawValue: -67647) }
/// Code signing found no basic constraints.
@inlinable public static var codeSigningNoBasicConstraints: Self { Code(rawValue: -67648) }
/// Code signing encountered an incorrect path length constraint.
@inlinable public static var codeSigningBadPathLengthConstraint: Self { Code(rawValue: -67649) }
/// Code signing found no extended key usage.
@inlinable public static var codeSigningNoExtendedKeyUsage: Self { Code(rawValue: -67650) }
/// Code signing indicated use of a development-only certificate.
@inlinable public static var codeSigningDevelopment: Self { Code(rawValue: -67651) }
/// Resource signing has encountered an incorrect certificate chain length.
@inlinable public static var resourceSignBadCertChainLength: Self { Code(rawValue: -67652) }
/// Resource signing has encountered an error in the extended key usage.
@inlinable public static var resourceSignBadExtKeyUsage: Self { Code(rawValue: -67653) }
/// The trust setting for this policy was set to Deny.
@inlinable public static var trustSettingDeny: Self { Code(rawValue: -67654) }
/// An invalid certificate subject name was encountered.
@inlinable public static var invalidSubjectName: Self { Code(rawValue: -67655) }
/// An unknown qualified certificate statement was encountered.
@inlinable public static var unknownQualifiedCertStatement: Self { Code(rawValue: -67656) }
@inlinable public static var mobileMeRequestQueued: Self { Code(rawValue: -67657) }
@inlinable public static var mobileMeRequestRedirected: Self { Code(rawValue: -67658) }
@inlinable public static var mobileMeServerError: Self { Code(rawValue: -67659) }
@inlinable public static var mobileMeServerNotAvailable: Self { Code(rawValue: -67660) }
@inlinable public static var mobileMeServerAlreadyExists: Self { Code(rawValue: -67661) }
@inlinable public static var mobileMeServerServiceErr: Self { Code(rawValue: -67662) }
@inlinable public static var mobileMeRequestAlreadyPending: Self { Code(rawValue: -67663) }
@inlinable public static var mobileMeNoRequestPending: Self { Code(rawValue: -67664) }
@inlinable public static var mobileMeCSRVerifyFailure: Self { Code(rawValue: -67665) }
@inlinable public static var mobileMeFailedConsistencyCheck: Self { Code(rawValue: -67666) }
/// A function was called without initializing CSSM.
@inlinable public static var notInitialized: Self { Code(rawValue: -67667) }
/// The CSSM handle does not match with the service type.
@inlinable public static var invalidHandleUsage: Self { Code(rawValue: -67668) }
/// A reference to the calling module was not found in the list of authorized callers.
@inlinable public static var pvcReferentNotFound: Self { Code(rawValue: -67669) }
/// A function address was not within the verified module.
@inlinable public static var functionIntegrityFail: Self { Code(rawValue: -67670) }
/// An internal error has occurred.
@inlinable public static var internalError: Self { Code(rawValue: -67671) }
/// A memory error has occurred.
@inlinable public static var memoryError: Self { Code(rawValue: -67672) }
/// Invalid data was encountered.
@inlinable public static var invalidData: Self { Code(rawValue: -67673) }
/// A Module Directory Service error has occurred.
@inlinable public static var mdsError: Self { Code(rawValue: -67674) }
/// An invalid pointer was encountered.
@inlinable public static var invalidPointer: Self { Code(rawValue: -67675) }
/// Self-check has failed.
@inlinable public static var selfCheckFailed: Self { Code(rawValue: -67676) }
/// A function has failed.
@inlinable public static var functionFailed: Self { Code(rawValue: -67677) }
/// A module manifest verification failure has occurred.
@inlinable public static var moduleManifestVerifyFailed: Self { Code(rawValue: -67678) }
/// An invalid GUID was encountered.
@inlinable public static var invalidGUID: Self { Code(rawValue: -67679) }
/// An invalid handle was encountered.
@inlinable public static var invalidHandle: Self { Code(rawValue: -67680) }
/// An invalid DB list was encountered.
@inlinable public static var invalidDBList: Self { Code(rawValue: -67681) }
/// An invalid passthrough ID was encountered.
@inlinable public static var invalidPassthroughID: Self { Code(rawValue: -67682) }
/// An invalid network address was encountered.
@inlinable public static var invalidNetworkAddress: Self { Code(rawValue: -67683) }
/// The certificate revocation list is already signed.
@inlinable public static var crlAlreadySigned: Self { Code(rawValue: -67684) }
/// An invalid number of fields were encountered.
@inlinable public static var invalidNumberOfFields: Self { Code(rawValue: -67685) }
/// A verification failure occurred.
@inlinable public static var verificationFailure: Self { Code(rawValue: -67686) }
/// An unknown tag was encountered.
@inlinable public static var unknownTag: Self { Code(rawValue: -67687) }
/// An invalid signature was encountered.
@inlinable public static var invalidSignature: Self { Code(rawValue: -67688) }
/// An invalid name was encountered.
@inlinable public static var invalidName: Self { Code(rawValue: -67689) }
/// An invalid certificate reference was encountered.
@inlinable public static var invalidCertificateRef: Self { Code(rawValue: -67690) }
/// An invalid certificate group was encountered.
@inlinable public static var invalidCertificateGroup: Self { Code(rawValue: -67691) }
/// The specified tag was not found.
@inlinable public static var tagNotFound: Self { Code(rawValue: -67692) }
/// The specified query was not valid.
@inlinable public static var invalidQuery: Self { Code(rawValue: -67693) }
/// An invalid value was detected.
@inlinable public static var invalidValue: Self { Code(rawValue: -67694) }
/// A callback has failed.
@inlinable public static var callbackFailed: Self { Code(rawValue: -67695) }
/// An ACL delete operation has failed.
@inlinable public static var aclDeleteFailed: Self { Code(rawValue: -67696) }
/// An ACL replace operation has failed.
@inlinable public static var aclReplaceFailed: Self { Code(rawValue: -67697) }
/// An ACL add operation has failed.
@inlinable public static var aclAddFailed: Self { Code(rawValue: -67698) }
/// An ACL change operation has failed.
@inlinable public static var aclChangeFailed: Self { Code(rawValue: -67699) }
/// Invalid access credentials were encountered.
@inlinable public static var invalidAccessCredentials: Self { Code(rawValue: -67700) }
/// An invalid record was encountered.
@inlinable public static var invalidRecord: Self { Code(rawValue: -67701) }
/// An invalid ACL was encountered.
@inlinable public static var invalidACL: Self { Code(rawValue: -67702) }
/// An invalid sample value was encountered.
@inlinable public static var invalidSampleValue: Self { Code(rawValue: -67703) }
/// An incompatible version was encountered.
@inlinable public static var incompatibleVersion: Self { Code(rawValue: -67704) }
/// The privilege was not granted.
@inlinable public static var privilegeNotGranted: Self { Code(rawValue: -67705) }
/// An invalid scope was encountered.
@inlinable public static var invalidScope: Self { Code(rawValue: -67706) }
/// The PVC is already configured.
@inlinable public static var pvcAlreadyConfigured: Self { Code(rawValue: -67707) }
/// An invalid PVC was encountered.
@inlinable public static var invalidPVC: Self { Code(rawValue: -67708) }
/// The EMM load has failed.
@inlinable public static var emmLoadFailed: Self { Code(rawValue: -67709) }
/// The EMM unload has failed.
@inlinable public static var emmUnloadFailed: Self { Code(rawValue: -67710) }
/// The add-in load operation has failed.
@inlinable public static var addinLoadFailed: Self { Code(rawValue: -67711) }
/// An invalid key was encountered.
@inlinable public static var invalidKeyRef: Self { Code(rawValue: -67712) }
/// An invalid key hierarchy was encountered.
@inlinable public static var invalidKeyHierarchy: Self { Code(rawValue: -67713) }
/// The add-in unload operation has failed.
@inlinable public static var addinUnloadFailed: Self { Code(rawValue: -67714) }
/// A library reference was not found.
@inlinable public static var libraryReferenceNotFound: Self { Code(rawValue: -67715) }
/// An invalid add-in function table was encountered.
@inlinable public static var invalidAddinFunctionTable: Self { Code(rawValue: -67716) }
/// An invalid service mask was encountered.
@inlinable public static var invalidServiceMask: Self { Code(rawValue: -67717) }
/// A module was not loaded.
@inlinable public static var moduleNotLoaded: Self { Code(rawValue: -67718) }
/// An invalid subservice ID was encountered.
@inlinable public static var invalidSubServiceID: Self { Code(rawValue: -67719) }
/// An attribute was not in the context.
@inlinable public static var attributeNotInContext: Self { Code(rawValue: -67720) }
/// A module failed to initialize.
@inlinable public static var moduleManagerInitializeFailed: Self { Code(rawValue: -67721) }
/// A module was not found.
@inlinable public static var moduleManagerNotFound: Self { Code(rawValue: -67722) }
/// An event notification callback was not found.
@inlinable public static var eventNotificationCallbackNotFound: Self { Code(rawValue: -67723) }
/// An input length error was encountered.
@inlinable public static var inputLengthError: Self { Code(rawValue: -67724) }
/// An output length error was encountered.
@inlinable public static var outputLengthError: Self { Code(rawValue: -67725) }
/// The privilege is not supported.
@inlinable public static var privilegeNotSupported: Self { Code(rawValue: -67726) }
/// A device error was encountered.
@inlinable public static var deviceError: Self { Code(rawValue: -67727) }
/// The CSP handle was busy.
@inlinable public static var attachHandleBusy: Self { Code(rawValue: -67728) }
/// You are not logged in.
@inlinable public static var notLoggedIn: Self { Code(rawValue: -67729) }
/// An algorithm mismatch was encountered.
@inlinable public static var algorithmMismatch: Self { Code(rawValue: -67730) }
/// The key usage is incorrect.
@inlinable public static var keyUsageIncorrect: Self { Code(rawValue: -67731) }
/// The key blob type is incorrect.
@inlinable public static var keyBlobTypeIncorrect: Self { Code(rawValue: -67732) }
/// The key header is inconsistent.
@inlinable public static var keyHeaderInconsistent: Self { Code(rawValue: -67733) }
/// The key header format is not supported.
@inlinable public static var unsupportedKeyFormat: Self { Code(rawValue: -67734) }
/// The key size is not supported.
@inlinable public static var unsupportedKeySize: Self { Code(rawValue: -67735) }
/// The key usage mask is not valid.
@inlinable public static var invalidKeyUsageMask: Self { Code(rawValue: -67736) }
/// The key usage mask is not supported.
@inlinable public static var unsupportedKeyUsageMask: Self { Code(rawValue: -67737) }
/// The key attribute mask is not valid.
@inlinable public static var invalidKeyAttributeMask: Self { Code(rawValue: -67738) }
/// The key attribute mask is not supported.
@inlinable public static var unsupportedKeyAttributeMask: Self { Code(rawValue: -67739) }
/// The key label is not valid.
@inlinable public static var invalidKeyLabel: Self { Code(rawValue: -67740) }
/// The key label is not supported.
@inlinable public static var unsupportedKeyLabel: Self { Code(rawValue: -67741) }
/// The key format is not valid.
@inlinable public static var invalidKeyFormat: Self { Code(rawValue: -67742) }
/// The vector of buffers is not supported.
@inlinable public static var unsupportedVectorOfBuffers: Self { Code(rawValue: -67743) }
/// The input vector is not valid.
@inlinable public static var invalidInputVector: Self { Code(rawValue: -67744) }
/// The output vector is not valid.
@inlinable public static var invalidOutputVector: Self { Code(rawValue: -67745) }
/// An invalid context was encountered.
@inlinable public static var invalidContext: Self { Code(rawValue: -67746) }
/// An invalid algorithm was encountered.
@inlinable public static var invalidAlgorithm: Self { Code(rawValue: -67747) }
/// A key attribute was not valid.
@inlinable public static var invalidAttributeKey: Self { Code(rawValue: -67748) }
/// A key attribute was missing.
@inlinable public static var missingAttributeKey: Self { Code(rawValue: -67749) }
/// An init vector attribute was not valid.
@inlinable public static var invalidAttributeInitVector: Self { Code(rawValue: -67750) }
/// An init vector attribute was missing.
@inlinable public static var missingAttributeInitVector: Self { Code(rawValue: -67751) }
/// A salt attribute was not valid.
@inlinable public static var invalidAttributeSalt: Self { Code(rawValue: -67752) }
/// A salt attribute was missing.
@inlinable public static var missingAttributeSalt: Self { Code(rawValue: -67753) }
/// A padding attribute was not valid.
@inlinable public static var invalidAttributePadding: Self { Code(rawValue: -67754) }
/// A padding attribute was missing.
@inlinable public static var missingAttributePadding: Self { Code(rawValue: -67755) }
/// A random number attribute was not valid.
@inlinable public static var invalidAttributeRandom: Self { Code(rawValue: -67756) }
/// A random number attribute was missing.
@inlinable public static var missingAttributeRandom: Self { Code(rawValue: -67757) }
/// A seed attribute was not valid.
@inlinable public static var invalidAttributeSeed: Self { Code(rawValue: -67758) }
/// A seed attribute was missing.
@inlinable public static var missingAttributeSeed: Self { Code(rawValue: -67759) }
/// A passphrase attribute was not valid.
@inlinable public static var invalidAttributePassphrase: Self { Code(rawValue: -67760) }
/// A passphrase attribute was missing.
@inlinable public static var missingAttributePassphrase: Self { Code(rawValue: -67761) }
/// A key length attribute was not valid.
@inlinable public static var invalidAttributeKeyLength: Self { Code(rawValue: -67762) }
/// A key length attribute was missing.
@inlinable public static var missingAttributeKeyLength: Self { Code(rawValue: -67763) }
/// A block size attribute was not valid.
@inlinable public static var invalidAttributeBlockSize: Self { Code(rawValue: -67764) }
/// A block size attribute was missing.
@inlinable public static var missingAttributeBlockSize: Self { Code(rawValue: -67765) }
/// An output size attribute was not valid.
@inlinable public static var invalidAttributeOutputSize: Self { Code(rawValue: -67766) }
/// An output size attribute was missing.
@inlinable public static var missingAttributeOutputSize: Self { Code(rawValue: -67767) }
/// The number of rounds attribute was not valid.
@inlinable public static var invalidAttributeRounds: Self { Code(rawValue: -67768) }
/// The number of rounds attribute was missing.
@inlinable public static var missingAttributeRounds: Self { Code(rawValue: -67769) }
/// An algorithm parameters attribute was not valid.
@inlinable public static var invalidAlgorithmParms: Self { Code(rawValue: -67770) }
/// An algorithm parameters attribute was missing.
@inlinable public static var missingAlgorithmParms: Self { Code(rawValue: -67771) }
/// A label attribute was not valid.
@inlinable public static var invalidAttributeLabel: Self { Code(rawValue: -67772) }
/// A label attribute was missing.
@inlinable public static var missingAttributeLabel: Self { Code(rawValue: -67773) }
/// A key type attribute was not valid.
@inlinable public static var invalidAttributeKeyType: Self { Code(rawValue: -67774) }
/// A key type attribute was missing.
@inlinable public static var missingAttributeKeyType: Self { Code(rawValue: -67775) }
/// A mode attribute was not valid.
@inlinable public static var invalidAttributeMode: Self { Code(rawValue: -67776) }
/// A mode attribute was missing.
@inlinable public static var missingAttributeMode: Self { Code(rawValue: -67777) }
/// An effective bits attribute was not valid.
@inlinable public static var invalidAttributeEffectiveBits: Self { Code(rawValue: -67778) }
/// An effective bits attribute was missing.
@inlinable public static var missingAttributeEffectiveBits: Self { Code(rawValue: -67779) }
/// A start date attribute was not valid.
@inlinable public static var invalidAttributeStartDate: Self { Code(rawValue: -67780) }
/// A start date attribute was missing.
@inlinable public static var missingAttributeStartDate: Self { Code(rawValue: -67781) }
/// An end date attribute was not valid.
@inlinable public static var invalidAttributeEndDate: Self { Code(rawValue: -67782) }
/// An end date attribute was missing.
@inlinable public static var missingAttributeEndDate: Self { Code(rawValue: -67783) }
/// A version attribute was not valid.
@inlinable public static var invalidAttributeVersion: Self { Code(rawValue: -67784) }
/// A version attribute was missing.
@inlinable public static var missingAttributeVersion: Self { Code(rawValue: -67785) }
/// A prime attribute was not valid.
@inlinable public static var invalidAttributePrime: Self { Code(rawValue: -67786) }
/// A prime attribute was missing.
@inlinable public static var missingAttributePrime: Self { Code(rawValue: -67787) }
/// A base attribute was not valid.
@inlinable public static var invalidAttributeBase: Self { Code(rawValue: -67788) }
/// A base attribute was missing.
@inlinable public static var missingAttributeBase: Self { Code(rawValue: -67789) }
/// A subprime attribute was not valid.
@inlinable public static var invalidAttributeSubprime: Self { Code(rawValue: -67790) }
/// A subprime attribute was missing.
@inlinable public static var missingAttributeSubprime: Self { Code(rawValue: -67791) }
/// An iteration count attribute was not valid.
@inlinable public static var invalidAttributeIterationCount: Self { Code(rawValue: -67792) }
/// An iteration count attribute was missing.
@inlinable public static var missingAttributeIterationCount: Self { Code(rawValue: -67793) }
/// A database handle attribute was not valid.
@inlinable public static var invalidAttributeDLDBHandle: Self { Code(rawValue: -67794) }
/// A database handle attribute was missing.
@inlinable public static var missingAttributeDLDBHandle: Self { Code(rawValue: -67795) }
/// An access credentials attribute was not valid.
@inlinable public static var invalidAttributeAccessCredentials: Self { Code(rawValue: -67796) }
/// An access credentials attribute was missing.
@inlinable public static var missingAttributeAccessCredentials: Self { Code(rawValue: -67797) }
/// A public key format attribute was not valid.
@inlinable public static var invalidAttributePublicKeyFormat: Self { Code(rawValue: -67798) }
/// A public key format attribute was missing.
@inlinable public static var missingAttributePublicKeyFormat: Self { Code(rawValue: -67799) }
/// A private key format attribute was not valid.
@inlinable public static var invalidAttributePrivateKeyFormat: Self { Code(rawValue: -67800) }
/// A private key format attribute was missing.
@inlinable public static var missingAttributePrivateKeyFormat: Self { Code(rawValue: -67801) }
/// A symmetric key format attribute was not valid.
@inlinable public static var invalidAttributeSymmetricKeyFormat: Self { Code(rawValue: -67802) }
/// A symmetric key format attribute was missing.
@inlinable public static var missingAttributeSymmetricKeyFormat: Self { Code(rawValue: -67803) }
/// A wrapped key format attribute was not valid.
@inlinable public static var invalidAttributeWrappedKeyFormat: Self { Code(rawValue: -67804) }
/// A wrapped key format attribute was missing.
@inlinable public static var missingAttributeWrappedKeyFormat: Self { Code(rawValue: -67805) }
/// A staged operation is in progress.
@inlinable public static var stagedOperationInProgress: Self { Code(rawValue: -67806) }
/// A staged operation was not started.
@inlinable public static var stagedOperationNotStarted: Self { Code(rawValue: -67807) }
/// A cryptographic verification failure has occurred.
@inlinable public static var verifyFailed: Self { Code(rawValue: -67808) }
/// The query size is unknown.
@inlinable public static var querySizeUnknown: Self { Code(rawValue: -67809) }
/// A block size mismatch occurred.
@inlinable public static var blockSizeMismatch: Self { Code(rawValue: -67810) }
/// The public key was inconsistent.
@inlinable public static var publicKeyInconsistent: Self { Code(rawValue: -67811) }
/// A device verification failure has occurred.
@inlinable public static var deviceVerifyFailed: Self { Code(rawValue: -67812) }
/// An invalid login name was detected.
@inlinable public static var invalidLoginName: Self { Code(rawValue: -67813) }
/// The user is already logged in.
@inlinable public static var alreadyLoggedIn: Self { Code(rawValue: -67814) }
/// An invalid digest algorithm was detected.
@inlinable public static var invalidDigestAlgorithm: Self { Code(rawValue: -67815) }
/// An invalid CRL group was detected.
@inlinable public static var invalidCRLGroup: Self { Code(rawValue: -67816) }
/// The certificate cannot operate.
@inlinable public static var certificateCannotOperate: Self { Code(rawValue: -67817) }
/// An expired certificate was detected.
@inlinable public static var certificateExpired: Self { Code(rawValue: -67818) }
/// The certificate is not yet valid.
@inlinable public static var certificateNotValidYet: Self { Code(rawValue: -67819) }
/// The certificate was revoked.
@inlinable public static var certificateRevoked: Self { Code(rawValue: -67820) }
/// The certificate was suspended.
@inlinable public static var certificateSuspended: Self { Code(rawValue: -67821) }
/// Insufficient credentials were detected.
@inlinable public static var insufficientCredentials: Self { Code(rawValue: -67822) }
/// The action was not valid.
@inlinable public static var invalidAction: Self { Code(rawValue: -67823) }
/// The authority was not valid.
@inlinable public static var invalidAuthority: Self { Code(rawValue: -67824) }
/// A verify action has failed.
@inlinable public static var verifyActionFailed: Self { Code(rawValue: -67825) }
/// The certificate authority was not valid.
@inlinable public static var invalidCertAuthority: Self { Code(rawValue: -67826) }
/// The CRL authority was not valid.
@inlinable public static var invalidCRLAuthority: Self { Code(rawValue: -67827) }
/// The CRL encoding was not valid.
@inlinable public static var invalidCRLEncoding: Self { Code(rawValue: -67828) }
/// The CRL type was not valid.
@inlinable public static var invalidCRLType: Self { Code(rawValue: -67829) }
/// The CRL was not valid.
@inlinable public static var invalidCRL: Self { Code(rawValue: -67830) }
/// The form type was not valid.
@inlinable public static var invalidFormType: Self { Code(rawValue: -67831) }
/// The ID was not valid.
@inlinable public static var invalidID: Self { Code(rawValue: -67832) }
/// The identifier was not valid.
@inlinable public static var invalidIdentifier: Self { Code(rawValue: -67833) }
/// The index was not valid.
@inlinable public static var invalidIndex: Self { Code(rawValue: -67834) }
/// The policy identifiers are not valid.
@inlinable public static var invalidPolicyIdentifiers: Self { Code(rawValue: -67835) }
/// The time specified was not valid.
@inlinable public static var invalidTimeString: Self { Code(rawValue: -67836) }
/// The trust policy reason was not valid.
@inlinable public static var invalidReason: Self { Code(rawValue: -67837) }
/// The request inputs are not valid.
@inlinable public static var invalidRequestInputs: Self { Code(rawValue: -67838) }
/// The response vector was not valid.
@inlinable public static var invalidResponseVector: Self { Code(rawValue: -67839) }
/// The stop-on policy was not valid.
@inlinable public static var invalidStopOnPolicy: Self { Code(rawValue: -67840) }
/// The tuple was not valid.
@inlinable public static var invalidTuple: Self { Code(rawValue: -67841) }
/// Multiple values are not supported.
@inlinable public static var multipleValuesUnsupported: Self { Code(rawValue: -67842) }
/// The certificate was not trusted.
@inlinable public static var notTrusted: Self { Code(rawValue: -67843) }
/// No default authority was detected.
@inlinable public static var noDefaultAuthority: Self { Code(rawValue: -67844) }
/// The trust policy had a rejected form.
@inlinable public static var rejectedForm: Self { Code(rawValue: -67845) }
/// The request was lost.
@inlinable public static var requestLost: Self { Code(rawValue: -67846) }
/// The request was rejected.
@inlinable public static var requestRejected: Self { Code(rawValue: -67847) }
/// The address type is not supported.
@inlinable public static var unsupportedAddressType: Self { Code(rawValue: -67848) }
/// The service is not supported.
@inlinable public static var unsupportedService: Self { Code(rawValue: -67849) }
/// The tuple group was not valid.
@inlinable public static var invalidTupleGroup: Self { Code(rawValue: -67850) }
/// The base ACLs are not valid.
@inlinable public static var invalidBaseACLs: Self { Code(rawValue: -67851) }
/// The tuple credentials are not valid.
@inlinable public static var invalidTupleCredentials: Self { Code(rawValue: -67852) }
/// The encoding was not valid.
@inlinable public static var invalidEncoding: Self { Code(rawValue: -67853) }
/// The validity period was not valid.
@inlinable public static var invalidValidityPeriod: Self { Code(rawValue: -67854) }
/// The requestor was not valid.
@inlinable public static var invalidRequestor: Self { Code(rawValue: -67855) }
/// The request descriptor was not valid.
@inlinable public static var requestDescriptor: Self { Code(rawValue: -67856) }
/// The bundle information was not valid.
@inlinable public static var invalidBundleInfo: Self { Code(rawValue: -67857) }
/// The CRL index was not valid.
@inlinable public static var invalidCRLIndex: Self { Code(rawValue: -67858) }
/// No field values were detected.
@inlinable public static var noFieldValues: Self { Code(rawValue: -67859) }
/// The field format is not supported.
@inlinable public static var unsupportedFieldFormat: Self { Code(rawValue: -67860) }
/// The index information is not supported.
@inlinable public static var unsupportedIndexInfo: Self { Code(rawValue: -67861) }
/// The locality is not supported.
@inlinable public static var unsupportedLocality: Self { Code(rawValue: -67862) }
/// The number of attributes is not supported.
@inlinable public static var unsupportedNumAttributes: Self { Code(rawValue: -67863) }
/// The number of indexes is not supported.
@inlinable public static var unsupportedNumIndexes: Self { Code(rawValue: -67864) }
/// The number of record types is not supported.
@inlinable public static var unsupportedNumRecordTypes: Self { Code(rawValue: -67865) }
/// Too many fields were specified.
@inlinable public static var fieldSpecifiedMultiple: Self { Code(rawValue: -67866) }
/// The field format was incompatible.
@inlinable public static var incompatibleFieldFormat: Self { Code(rawValue: -67867) }
/// The parsing module was not valid.
@inlinable public static var invalidParsingModule: Self { Code(rawValue: -67868) }
/// The database is locked.
@inlinable public static var databaseLocked: Self { Code(rawValue: -67869) }
/// The data store is open.
@inlinable public static var datastoreIsOpen: Self { Code(rawValue: -67870) }
/// A missing value was detected.
@inlinable public static var missingValue: Self { Code(rawValue: -67871) }
/// The query limits are not supported.
@inlinable public static var unsupportedQueryLimits: Self { Code(rawValue: -67872) }
/// The number of selection predicates is not supported.
@inlinable public static var unsupportedNumSelectionPreds: Self { Code(rawValue: -67873) }
/// The operator is not supported.
@inlinable public static var unsupportedOperator: Self { Code(rawValue: -67874) }
/// The database location is not valid.
@inlinable public static var invalidDBLocation: Self { Code(rawValue: -67875) }
/// The access request is not valid.
@inlinable public static var invalidAccessRequest: Self { Code(rawValue: -67876) }
/// The index information is not valid.
@inlinable public static var invalidIndexInfo: Self { Code(rawValue: -67877) }
/// The new owner is not valid.
@inlinable public static var invalidNewOwner: Self { Code(rawValue: -67878) }
/// The modify mode is not valid.
@inlinable public static var invalidModifyMode: Self { Code(rawValue: -67879) }
/// A required certificate extension is missing.
@inlinable public static var missingRequiredExtension: Self { Code(rawValue: -67880) }
/// The extended key usage extension was not marked critical.
@inlinable public static var extendedKeyUsageNotCritical: Self { Code(rawValue: -67881) }
/// A timestamp was expected but was not found.
@inlinable public static var timestampMissing: Self { Code(rawValue: -67882) }
/// The timestamp was not valid.
@inlinable public static var timestampInvalid: Self { Code(rawValue: -67883) }
/// The timestamp was not trusted.
@inlinable public static var timestampNotTrusted: Self { Code(rawValue: -67884) }
/// The timestamp service is not available.
@inlinable public static var timestampServiceNotAvailable: Self { Code(rawValue: -67885) }
/// An unrecognized or unsupported Algorithm Identifier in timestamp.
@inlinable public static var timestampBadAlg: Self { Code(rawValue: -67886) }
/// The timestamp transaction is not permitted or supported.
@inlinable public static var timestampBadRequest: Self { Code(rawValue: -67887) }
/// The timestamp data submitted has the wrong format.
@inlinable public static var timestampBadDataFormat: Self { Code(rawValue: -67888) }
/// The time source for the Timestamp Authority is not available.
@inlinable public static var timestampTimeNotAvailable: Self { Code(rawValue: -67889) }
/// The requested policy is not supported by the Timestamp Authority.
@inlinable public static var timestampUnacceptedPolicy: Self { Code(rawValue: -67890) }
/// The requested extension is not supported by the Timestamp Authority.
@inlinable public static var timestampUnacceptedExtension: Self { Code(rawValue: -67891) }
/// The additional information requested is not available.
@inlinable public static var timestampAddInfoNotAvailable: Self { Code(rawValue: -67892) }
/// The timestamp request cannot be handled due to system failure.
@inlinable public static var timestampSystemFailure: Self { Code(rawValue: -67893) }
/// A signing time was expected but was not found.
@inlinable public static var signingTimeMissing: Self { Code(rawValue: -67894) }
/// A timestamp transaction was rejected.
@inlinable public static var timestampRejection: Self { Code(rawValue: -67895) }
/// A timestamp transaction is waiting.
@inlinable public static var timestampWaiting: Self { Code(rawValue: -67896) }
/// A timestamp authority revocation warning was issued.
@inlinable public static var timestampRevocationWarning: Self { Code(rawValue: -67897) }
/// A timestamp authority revocation notification was issued.
@inlinable public static var timestampRevocationNotification: Self { Code(rawValue: -67898) }
/// The requested policy is not allowed for this certificate.
@inlinable public static var certificatePolicyNotAllowed: Self { Code(rawValue: -67899) }
/// The requested name is not allowed for this certificate.
@inlinable public static var certificateNameNotAllowed: Self { Code(rawValue: -67900) }
/// The validity period in the certificate exceeds the maximum allowed.
@inlinable public static var certificateValidityPeriodTooLong: Self { Code(rawValue: -67901) }
/// The verified certificate is a CA rather than an end-entity.
@inlinable public static var certificateIsCA: Self { Code(rawValue: -67902) }
/// The certificate contains multiple extensions with the same extension ID.
@inlinable public static var certificateDuplicateExtension: Self { Code(rawValue: -67903) }
/// A qualified certificate statement was expected but missing.
@inlinable public static var missingQualifiedCertStatement: Self { Code(rawValue: -67904) }
}
}
// swiftlint:disable:this file_length

View File

@@ -0,0 +1,30 @@
//
// SecError.swift
// Keychain
//
// Created by Bram Kolkman on 22/02/2026.
//
import Foundation
/// Describes errors within the security error domain.
public struct SecError: Error, Hashable, Sendable {
/// The error code.
public let code: Code
/// The description of the error.
@inlinable public var errorDescription: String? {
SecCopyErrorMessageString(code.rawValue, nil) as? String
}
/// Create the error.
/// - Parameter code: The error code.
init(_ code: Code) {
self.code = code
}
/// Create the error.
/// - Parameter status: The raw status code.
init(_ status: OSStatus) {
self.init(Code(rawValue: status))
}
}

View File

@@ -0,0 +1,115 @@
//
// SecItem.swift
// Keychain
//
// Created by Bram Kolkman on 23/02/2026.
//
import Security
public enum SecItem {
/// Adds an item to the keychain.
///
/// Use this function to store credentials, keys, certificates, and other secure data in the keychain.
/// The keychain automatically encrypts the data and manages access control.
///
/// - Parameter attributes: A dictionary containing the attributes of the item to add. At minimum,
/// include `kSecClass` to specify the item class and `kSecValueData` or `kSecValueRef` for the item's value.
/// Additional attributes control access, persistence, and synchronization behavior.
///
/// - Returns: If you include the `kSecReturnAttributes`, `kSecReturnData`, `kSecReturnRef`, or
/// `kSecReturnPersistentRef` key with a value of `true` in the attributes dictionary, this function
/// returns the requested data. Otherwise, it returns `nil`.
///
/// - Throws: A `SecError` if the item could not be added. Common errors include duplicate items
/// (`errSecDuplicateItem`) or invalid parameters (`errSecParam`).
@discardableResult
public static func add(_ attributes: [CFString: Any]) throws -> CFTypeRef? {
var result: CFTypeRef?
let status = SecItemAdd(attributes as CFDictionary, &result)
switch status {
case errSecSuccess:
return result
default:
throw SecError(status)
}
}
/// Searches for and retrieves items from the keychain.
///
/// Use this function to find keychain items that match specified search criteria. You can retrieve
/// the item's data, attributes, or a persistent reference that you can use for later access.
///
/// - Parameter query: A dictionary containing the search criteria. At minimum, include `kSecClass`
/// to specify the item class. Add search attributes like `kSecAttrAccount` or `kSecAttrService`
/// to narrow results. Include return type keys (`kSecReturnData`, `kSecReturnAttributes`,
/// `kSecReturnRef`, or `kSecReturnPersistentRef`) to specify what data to return.
///
/// - Returns: The requested keychain item data, attributes, or reference as specified by the return
/// type keys in the query. Returns `nil` if no matching item is found (`errSecItemNotFound`).
///
/// - Throws: A `SecError` if the search fails for reasons other than the item not being found.
/// Common errors include invalid parameters (`errSecParam`) or user interaction cancelled
/// (`errSecUserCanceled`).
public static func copy(matching query: [CFString: Any]) throws (SecError) -> CFTypeRef? {
var result: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &result)
switch status {
case errSecSuccess:
return result
case errSecItemNotFound:
return nil
default:
throw SecError(status)
}
}
/// Modifies items in the keychain that match a search query.
///
/// Use this function to change the attributes or data of existing keychain items. The function
/// finds items matching the search criteria and applies the specified updates to them.
///
/// - Parameter query: A dictionary containing the search criteria for items to update. At minimum,
/// include `kSecClass` to specify the item class. Add search attributes to identify specific items.
/// Do not include return type keys in the query dictionary.
///
/// - Parameter updates: A dictionary containing the attributes to modify. Include only the attributes
/// you want to change. You cannot modify the `kSecClass` attribute.
///
/// - Throws: A `SecError` if the update fails. Common errors include item not found (`errSecItemNotFound`),
/// invalid parameters (`errSecParam`), or attempting to create a duplicate item.
public static func update(matching query: [CFString: Any], with updates: [CFString: Any]) throws {
let status = SecItemUpdate(query as CFDictionary, updates as CFDictionary)
switch status {
case errSecSuccess:
break
default:
throw SecError(status)
}
}
/// Removes items from the keychain that match a search query.
///
/// Use this function to delete keychain items that are no longer needed. The function finds all items
/// matching the search criteria and removes them from the keychain. If no matching items exist,
/// the function succeeds without error.
///
/// - Parameter query: A dictionary containing the search criteria for items to delete. At minimum,
/// include `kSecClass` to specify the item class. Add search attributes to identify specific items.
/// To delete all items of a class, specify only `kSecClass`.
///
/// - Throws: A `SecError` if the deletion fails for reasons other than the item not being found.
/// Common errors include invalid parameters (`errSecParam`) or user interaction required
/// (`errSecInteractionNotAllowed`).
public static func delete(matching query: [CFString: Any]) throws {
let status = SecItemDelete(query as CFDictionary)
switch status {
case errSecSuccess, errSecItemNotFound:
break
default:
throw SecError(status)
}
}
}

13
Makefile Normal file
View File

@@ -0,0 +1,13 @@
.PHONY: build resolve clean
build:
@echo "Building Swift package 'Keychain'"
@swift build --package-path Keychain --scratch-path .build
resolve:
@echo "Resolving Swift package dependencies..."
@swift package resolve --package-path Keychain --scratch-path .build
clean:
@echo "Cleaning build artifacts..."
@rm -rf .build Keychain/.swiftpm

View File

@@ -1,3 +1,39 @@
# Keychain # Keychain
A Swift package for the Keychain A Swift package for interacting with the Keychain.
## Requirements
- macOS 12+
- Swift 6.2+
## Package Structure
```
Keychain/
├── Package.swift
├── Package.resolved
└── Sources/
└── Keychain/
└── Keychain.swift
```
## Dependencies
- [SwiftLintPlugins](https://github.com/SimplyDanny/SwiftLintPlugins) (≥ 0.63.2) — enforces Swift style and conventions at build time.
## Usage
Add the package to your `Package.swift` dependencies and import `Keychain` in your Swift files.
## Makefile
A `Makefile` is provided at the root of the repository to simplify common tasks.
| Command | Description |
|----------------|------------------------------------------|
| `make build` | Builds the Swift package |
| `make resolve` | Resolves package dependencies |
| `make clean` | Removes build artifacts and `.swiftpm` |
Build artifacts are placed in `.build/` at the repository root (outside the package directory).