Skip to content

Fix: attach kSecPrivateKeyAttrs (is_permanent, access control) on iOS and other non-macOS targets - #255

Open
AdrianEddy wants to merge 1 commit into
kornelski:mainfrom
AdrianEddy:fix-ios-private-key-attrs
Open

Fix: attach kSecPrivateKeyAttrs (is_permanent, access control) on iOS and other non-macOS targets#255
AdrianEddy wants to merge 1 commit into
kornelski:mainfrom
AdrianEddy:fix-ios-private-key-attrs

Conversation

@AdrianEddy

Copy link
Copy Markdown

GenerateKeyOptions::to_dictionary builds the kSecPrivateKeyAttrs sub-dictionary (carrying kSecAttrIsPermanent and kSecAttrAccessControl) on every target, but since #221 (d139535, first released in v3.2.0) only attaches it under #[cfg(target_os = "macos")]. On iOS/tvOS/watchOS/visionOS the generated key is therefore always ephemeral — set_location(...) and set_access_control(...) are silently ignored, because kSecAttrIsPermanent defaults to false.

That cfg looks like a compile-convenience artifact of #221's AES handling (KeyType::aes() is macOS-only) rather than an intentional platform decision: before #221 (up to v3.1.0) both sub-dictionaries were attached unconditionally, and Apple documents this exact pattern for iOS:

  • "Generating New Cryptographic Keys" uses kSecPrivateKeyAttrs: [kSecAttrIsPermanent: true, ...] with SecKeyCreateRandomKey on all platforms.
  • kSecPrivateKeyAttrs is iOS 2.0+, kSecAttrIsPermanent is iOS 2.0+, kSecAttrAccessControl is iOS 8.0+.
  • The Secure Enclave guide's sample sets both kSecAttrIsPermanent and kSecAttrAccessControl inside kSecPrivateKeyAttrs at create time.

Changes:

  • Attach kSecPublicKeyAttrs/kSecPrivateKeyAttrs on all targets (the AES branch stays macOS-only via a target-gated is_symmetric bool; non-macOS has no symmetric KeyType).
  • Un-gate the location match; Location::DataProtectionKeychain now pushes kSecUseDataProtectionKeychain on non-macOS too, mirroring ItemAddOptions in item.rs. Apple: "You can safely use the key on all platforms" (it is implicit on iOS).
  • kSecUseKeychain/FileKeychain remain macOS-only.

The dictionary emitted on macOS is unchanged. Verified with the CI commands: cargo check --all-features -p security-framework --target aarch64-apple-ios and --target x86_64-apple-darwin (plus aarch64-apple-darwin, default-feature builds, and clippy: no new warnings).

🤖 Generated with Claude Code

…S targets

GenerateKeyOptions::to_dictionary builds the kSecPrivateKeyAttrs
sub-dictionary (kSecAttrIsPermanent + kSecAttrAccessControl) on every
target, but since kornelski#221 only attaches it under #[cfg(target_os = "macos")].
On iOS/tvOS/watchOS/visionOS generated keys are therefore always
ephemeral: set_location() and set_access_control() are silently ignored
because kSecAttrIsPermanent defaults to false.

Restore the pre-kornelski#221 (v3.1.0) behavior: attach the public/private attrs
on all targets (the AES branch stays macOS-only via a target-gated
is_symmetric bool - non-macOS has no symmetric KeyType), and un-gate the
location match so DataProtectionKeychain pushes
kSecUseDataProtectionKeychain on non-macOS too, mirroring ItemAddOptions.
kSecUseKeychain/FileKeychain remain macOS-only. The dictionary emitted on
macOS is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant