Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

macOS System Extension: Entitlements and Signing with Provisioning Profile

I have a macOS System Extension for a USB device driver. It works when I disable SIP and manually sign using my codesign identity (generated from my Apple ID using "security find-identity" from Terminal) - as described here: https://github.com/knightsc/USBApp/issues/1

I can activate and deactivate the dext and use it with a device when activated - examples of what I did and ended up with are here:

Migrating a codeless KEXT to a codeless DEXT

and here:

Getting OSSystemExtensionErrorCodeSignatureInvalid After Codeless DEXT is Activated

I was granted an entitlement by Apple and followed the steps they outlined to create a provisioning profile, then downloaded and installed it. I then followed the steps referenced in the entitlement email from Apple for manually signing an app: https://help.apple.com/xcode/mac/current/#/dev1bf96f17e

I rebuilt my app and deactivated all existing instances of my driver. When I try to activate the new driver, the activation request fails with the entitlements error: "Error Domain=OSSystemExtensionErrorDomain Code=8", which I know is an indication of an entitlements/signing problem.

  • What is the proper way to use the provisioning profile from Apple to sign my app and driver?

  • Do I need to update my entitlements file? Here are my existing files:

App

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-only</key>
    <true/>
    <key>com.apple.developer.system-extension.install</key>
    <true/>
    <key>com.apple.developer.system-extension.uninstall</key>
    <true/>
</dict>
</plist>

Dext

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.driverkit</key>
    <true/>
    <key>com.apple.developer.driverkit.transport.usb</key>
    <array>
        <dict>
            <key>idVendor</key>
            <integer>LEGACY VID</integer>
            <key>idProductArray</key>
            <array>
                <integer>PID1</integer>
                <integer>PID2</integer>
                <integer>PID3</integer>
                <integer>PID4</integer>
                <integer>PID5</integer>
            </array>
        </dict>
        <dict>
            <key>idVendor</key>
            <integer>NEW VID</integer>
            <key>idProductArray</key>
            <array>
                <integer>PID6</integer>
            </array>
        </dict>
    </array>
    <key>com.apple.security.app-sandbox</key>
    <true/>
</dict>
</plist>

Any help would be appreciated.

Update:

The App ID for the application has the System Extension capability, but not the additional DriverKit capability.

The App ID for the dext has the additional DriverKit capability.

The provisioning profile for the App has

- com.apple.developer.driverkit set true
- com.apple.application-identifier set to <Team ID>.<App Bundle Identifier>
- keychain-access-groups set to <Team ID>.*
- com.apple.developer.system-extension.install set to true
- com.apple.developer.team-identifier set to Team ID

The provisioning profile for the Dext has

- com.apple.developer.driverkit set true
- com.apple.application-identifier set to <Team ID>.<Driver Bundle Identifier>
- keychain-access-groups set to <Team ID>.*
- com.apple.developer.team-identifier set to Team ID

Update 2:

Here is the process I am following to generate a provisioning profile:

  1. Register an New Provisioning Profile - I select "Developer ID" under "Distribution", at the very bottom. That is also what my generated certificate is for.

  2. Generate a Provisioning Profile - Profile type "Mac" and I select an App ID.

  3. Select Certificates - Select a certificate that is compatible with the distribution mode.

  4. Additional Entitlements - Select entitlement "DriverKit and System Extension Template for Mac Dev ID profile/Mac Direct Dist Profile" That causes "Extended Entitlements" to show up with "com.apple.developer.driverkit" set to "true"

  5. Review, Name and Generate. - Provisioning Profile Name - Select a name and generate, then download and install.

Update 3:

I filed a support request, and finally got the response "we have contacted the DriverKit entitlement screener to have your entitlement template updated to include the USB Transport entitlement" Hopefully that is progress!

like image 300
GTAE86 Avatar asked Sep 16 '20 20:09

GTAE86


2 Answers

General answer:

Provisioning profile

  • You will need to create an "App ID" in the developer account "Certificates, Identifiers & Profiles" area for both the dext and the app containing it. Yes, the dext is not an app but it still needs an app ID.
    • For the dext, ensure the "DriverKit…" item is ticked under "Additional Capabilities"
    • For the app, ensure "System Extension" is ticked.
    • Make sure you get the bundle IDs right
  • Once you have the App IDs set up, you will need to generate provisioning profiles for each signing mechanism you are planning to use (development, distribution via Developer ID or for app store) and for both the app and the dext.
    • Make sure you select the correct "template" under the Entitlements section for each profile. It seems like these "templates" are manually generated by whoever processed your entitlement request at Apple, so they don't seem to have a consistent naming, but they'll normally contain "System Extension" and "DriverKit". If you don't get a dropdown, you probably weren't granted the entitlement for this type of code signing.

Xcode can download the provisioning profiles itself, but I additionally recommend downloading them to a file locally. This is because you can use "QuickLook" on the provisioning profile files to check that they contain the entitlements you are expecting! Select the file in the Finder and press the space bar. I strongly recommend you check that all your provisioning profiles match the entitlements for the targets in question this way before doing any other troubleshooting. Every entitlement listed in your entitlements file, except those starting with com.apple.security., must be present in the provisioning profile or it will not work.

Entitlements

The app into which your dext is embedded will need to include the following entitlement:

<key>com.apple.developer.system-extension.install</key>
<true/>

I've been told (in a WWDC labs appointment) you should also include the com.apple.application-identifier entitlement and set this to your App ID you generated above, which is the 10-character prefix, followed by a dot, followed by the bundle ID. (The prefix is normally your team ID)

The dext will need the base DriverKit entitlement, plus entitlements for whatever other driverkit subsystems your driver uses, etc.. dexts are also sandboxed. E.g.

<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.usb</key>
<array>
    <dict>
        <key>idVendor</key>
        <integer>1452</integer>
    </dict>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>

Again, you should apparently include com.apple.application-identifier as well.

Specific answer:

As the question has now been updated with the specific contents of the entitlements files and provisioning profiles, I can find the following problems:

  1. The provisioning profile does not contain the DriverKit USB entitlement. Perhaps you were only granted it for development, not distribution? Either way, you will need to ask Apple to fix this. The provisioning profile for a USB dext should look something like this in QuickLook: com.apple.developer.driverkit.transport.usb entitlement as it appears in a provisioning profile opened using quicklook. Note that vendor IDs are explicitly listed.
  2. Don't include product IDs in your USB (or PCI) entitlements unless Apple has explicitly issued you with a provisioning profile containing them. I don't think that's something they currently do, however, so leave them out.
  3. I'm not sure what the original source for the com.apple.developer.system-extension.uninstall entitlement is, but it seems to turn up in a bunch of places on the web. It does not actually seem to be necessary though, and Apple does not grant it. I'm not sure why your app is launching with it included, do you perhaps have amfi_get_out_of_my_way=1 enabled in your boot-args?
  4. Surplus entitlements in the provisioning profile which you don't claim in your entitlements file are fine. Xcode may warn about it but there's no actual problem with it.

If you are still encountering problems after fixing all that, I recommend trying to capture some more detailed logging at the instant the error occurs. The following command line may help:

log stream --info --predicate='process=="taskgated-helper" || process=="kernel" || process=="trustd" || process=="syspolicyd" || process=="amfid" || process=="sysextd"'

Feel free to update the question with any useful-looking diagnostic information you obtain and I'll do my best to help out with working out what's wrong.

Additional information:

The following might also be helpful:

  • https://developer.apple.com/forums/thread/22943
  • https://developer.apple.com/library/archive/technotes/tn2415/_index.html
like image 101
pmdj Avatar answered Sep 20 '22 12:09

pmdj


I use the entitlements that are embedded in the provisionprofile generated in the Certificates, Identifiers and Profiles page in the apple developer account.

For both the app and dext I create an "identifier", with the correct entitlement ("System Extension" for the app and from the Additional Capabilities the DriverKit "USB Transport - VendorID" for the dext.)

Then, generate two profiles, one for the app and one for the dext. Download those.

You can then generate a plist for the app and the dext with this makefile rule:

%.plist: %.provisionprofile
        security cms -D -i $< | plutil - extract Entitlements xml1 - -o $@

This guarantees that the entitlements you use will match what your provisionprofile specifies.

If you don't have the correct entitlements in your provisionprofile you either did not select the correct ones. Or you have not been granted the correct entitlements by Apple (and therefore they are not available to select when creating the Identifier.)

like image 29
Stuart Lynne Avatar answered Sep 19 '22 12:09

Stuart Lynne