The data protection keychain, which is the only keychain on iOS and its child platforms [1], enforces access control via entitlements. If you don’t have appropriate entitlements, you get this -34018 (errSecMissingEntitlement
) error.
Entitlements on the simulator are weird. We can’t use real entitlement, because then macOS would refuse to run the app [2]. So, instead we simulate the entitlements.
You can see this with codesign
. Consider an iOS app built for the simulator:
% codesign -d --entitlements - Debug-iphonesimulator/Test733449.app
…
[Dict]
[Key] com.apple.security.get-task-allow
[Value]
[Bool] true
The only entitlement present is com.apple.security.get-task-allow
, which is an unrestricted entitlement that tells macOS it’s OK for the debugger to attach to a process running this program.
To see the simulated entitlements you have to use otool
to dump the __TEXT
/ __entitlements
section:
% otool -s __TEXT __entitlements -V Debug-iphonesimulator/Test733449.app/Test733449
…
100007d24 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 |<?xml version="1|
100007d34 2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 |.0" encoding="UT|
100007d44 46 2d 38 22 3f 3e 0a 3c 21 44 4f 43 54 59 50 45 |F-8"?>.<!DOCTYPE|
100007d54 20 70 6c 69 73 74 20 50 55 42 4c 49 43 20 22 2d | plist PUBLIC "-|
100007d64 2f 2f 41 70 70 6c 65 2f 2f 44 54 44 20 50 4c 49 |//Apple//DTD PLI|
100007d74 53 54 20 31 2e 30 2f 2f 45 4e 22 20 22 68 74 74 |ST 1.0//EN" "htt|
100007d84 70 3a 2f 2f 77 77 77 2e 61 70 70 6c 65 2e 63 6f |p://www.apple.co|
100007d94 6d 2f 44 54 44 73 2f 50 72 6f 70 65 72 74 79 4c |m/DTDs/PropertyL|
100007da4 69 73 74 2d 31 2e 30 2e 64 74 64 22 3e 0a 3c 70 |ist-1.0.dtd">.<p|
100007db4 6c 69 73 74 20 76 65 72 73 69 6f 6e 3d 22 31 2e |list version="1.|
100007dc4 30 22 3e 0a 3c 64 69 63 74 3e 0a 09 3c 6b 65 79 |0">.<dict>..<key|
100007dd4 3e 61 70 70 6c 69 63 61 74 69 6f 6e 2d 69 64 65 |>application-ide|
100007de4 6e 74 69 66 69 65 72 3c 2f 6b 65 79 3e 0a 09 3c |ntifier</key>..<|
100007df4 73 74 72 69 6e 67 3e 53 4b 4d 4d 45 39 45 32 59 |string>SKMME9E2Y|
100007e04 38 2e 63 6f 6d 2e 65 78 61 6d 70 6c 65 2e 61 70 |8.com.example.ap|
100007e14 70 6c 65 2d 73 61 6d 70 6c 65 63 6f 64 65 2e 54 |ple-samplecode.T|
100007e24 65 73 74 37 33 33 34 34 39 42 3c 2f 73 74 72 69 |est733449B</stri|
100007e34 6e 67 3e 0a 3c 2f 64 69 63 74 3e 0a 3c 2f 70 6c |ng>.</dict>.</pl|
100007e44 69 73 74 3e 0a |ist>.|
Now let’s repeat this for a visionOS app:
% codesign -d --entitlements - Debug-xrsimulator/Test733449.app
Executable=/Users/quinn/Library/Developer/Xcode/DerivedData/Test733449-ctnnvrkrshlpujatshmzduejqgwr/Build/Products/Debug-xrsimulator/Test733449.app/Test733449
Again, there are no entitlements [3], so we need to look at the simulated ones:
% otool -s __TEXT __entitlements -V Debug-xrsimulator/Test733449.app/Test733449
Debug-xrsimulator/Test733449.app/Test733449:
Yikes! There are no simulated entitlement either. This is explains why the keychain is grumpy.
AFAIK this is a bug in Xcode — it should apply simulated entitlements to apps built for the visionOS simulator — and I encourage you to file a bug report about it. Please post your bug number, just for the record.
You can temporarily work around this issue by using Siging & Capabilities to add a keychain access group to your app. This causes Xcode to generate the simulated entitlements:
% otool -s __TEXT __entitlements -V Debug-xrsimulator/Test733449.app/Test733449
…
10000673c 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 |<?xml version="1|
10000674c 2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 |.0" encoding="UT|
10000675c 46 2d 38 22 3f 3e 0a 3c 21 44 4f 43 54 59 50 45 |F-8"?>.<!DOCTYPE|
10000676c 20 70 6c 69 73 74 20 50 55 42 4c 49 43 20 22 2d | plist PUBLIC "-|
10000677c 2f 2f 41 70 70 6c 65 2f 2f 44 54 44 20 50 4c 49 |//Apple//DTD PLI|
10000678c 53 54 20 31 2e 30 2f 2f 45 4e 22 20 22 68 74 74 |ST 1.0//EN" "htt|
10000679c 70 3a 2f 2f 77 77 77 2e 61 70 70 6c 65 2e 63 6f |p://www.apple.co|
1000067ac 6d 2f 44 54 44 73 2f 50 72 6f 70 65 72 74 79 4c |m/DTDs/PropertyL|
1000067bc 69 73 74 2d 31 2e 30 2e 64 74 64 22 3e 0a 3c 70 |ist-1.0.dtd">.<p|
1000067cc 6c 69 73 74 20 76 65 72 73 69 6f 6e 3d 22 31 2e |list version="1.|
1000067dc 30 22 3e 0a 3c 64 69 63 74 3e 0a 09 3c 6b 65 79 |0">.<dict>..<key|
1000067ec 3e 6b 65 79 63 68 61 69 6e 2d 61 63 63 65 73 73 |>keychain-access|
1000067fc 2d 67 72 6f 75 70 73 3c 2f 6b 65 79 3e 0a 09 3c |-groups</key>..<|
10000680c 61 72 72 61 79 3e 0a 09 09 3c 73 74 72 69 6e 67 |array>...<string|
10000681c 3e 67 72 6f 75 70 2e 77 6f 72 6b 61 72 6f 75 6e |>group.workaroun|
10000682c 64 3c 2f 73 74 72 69 6e 67 3e 0a 09 3c 2f 61 72 |d</string>..</ar|
10000683c 72 61 79 3e 0a 3c 2f 64 69 63 74 3e 0a 3c 2f 70 |ray>.</dict>.</p|
10000684c 6c 69 73 74 3e 0a |list>.|
The keychain access group search list rules (see Sharing Access to Keychain Items Among a Collection of Apps) mean that this keychain access group becomes your default keychain access group, and so the keychain starts to work.
The obvious problem here is that your keychain items go into this group rather than into your standard App ID group. So, this workaround is fine for testing in the simulator but you need to remove it before you ship anything. Hopefully Xcode will be fixed by then (-:
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
[1] macOS is different in this regard. If you’re curious, see TN3137 On Mac keychain APIs and implementations.
[2] Without a macOS provisioning profile. For more backstory, see TN3125 Inside Code Signing: Provisioning Profiles.
[3] Not even com.apple.security.get-task-allow
. This is a bit weird, but it doesn’t cause problems because macOS only checks for this entitlement if the hardened runtime is enabled, which isn’t the case for apps built for the simulator.