So, let me start with the causes of these failures:
But when I do, the "signing certificate" status in Xcode shows as failed. Why is that?
This post has more detail, but in basic terms, your app’s "signing" is created from two components:
-
Your Entitlement.plist -> This is used to create the actual code-signature "attached" to your app bundle.
-
The provisioning profile -> This is a file that we've signed and which is then embedded inside your app’s bundle. (Note: not all signed apps have/need one of these, but all DEXT do).
The system "validates" the entitlement by comparing the entitlement values contained in those two files (your app’s code signature and its embedded provisioning profile). That's why the profile (#2) is signed by us - it "proves" we want your app to have the entitlement. Xcode checks that your app is properly signed by comparing the data in those values to ensure that they "match", creating this failure when they "don't match".
What I wanted to convey in my previous post was that I think I should include this "amp;",
So, the confusion around "&" vs "&" happens because the "right" answer depends on how you're looking at the file.
-
If you open a plist file as plain text, you'll see the value "&". That's because the standalone character "&" is a reserved XML character, and "&" is its escaped variant.
-
If you open the plist file in any sort of plist editor, it will show you "&". That's because that's the character you actually "wanted" to enter/display.
Making this concrete, here is the raw text of one entire entitlement.plist:
<?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.allow-any-userclient-access</key>
<true/>
<key>com.apple.developer.driverkit.allow-third-party-userclients</key>
<true/>
<key>com.apple.developer.driverkit.transport.pci</key>
<array>
<dict>
<key>IOPCIPrimaryMatch</key>
<string>0xFFFFFFFF&0x00000000</string>
</dict>
</array>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
And here is a screenshot of exactly the same file in Xcode:

Again, that's exactly the same data shown two different ways.
That leads to here:
With the following settings, the "signing certificate" status error in Xcode disappears, and building and driver installation succeed.
Going back to the two files above, only one of those (the entitlement plist) is directly editable by "you". So, from that perspective, an app is "properly signed" when you've configured your entitlement plist to match your provisioning profile. FYI, TN3125: Inside Code Signing: Provisioning Profiles has directions for viewing what's actually inside a provisioning profile file. However, the basic "game" here is pretty simple— if Xcode works with one plist configuration and errors with a slightly different plist configuration, then the first configuration is "right" and the second is "wrong"...
However, the driver cannot be assigned to the device.
...but all that means is that your DEXT has a valid signature configuration. That doesn't mean it will actually "work". DEXT matching basically relies on a two-stage process which works something like this:
-
The IOKitPersonalities dictionary is used as a standard KEXT loading dictionary by the kernel. That loads the driver specified by "IOClass" into the kernel in EXACTLY the way a standard IOKit KEXT would load.
-
After that initial match, the kernel then compares the entitlement configuration of your DEXT against the data that's in the provider you're matching against*. If configuration matches, then loading will continue. If it doesn't, then the match will be failed and your driver will be unloaded.
*One small detail here is that this matching process is actually handled by the specific family driver using its own implementation. For example, IOPCIFamily has a specific limitation around matching with "built-in" hardware that's independent of direct hardware matching. If you're curious, you can actually see the code for IOPCIFamily checks here.
Note that everything above occurs in the kernel BEFORE any of your code actually "runs" or your DEXT process actually "exists". Indeed, the next step AFTER this is when your DEXT actually starts loading.
Making that concrete, nothing prevents you from creating a DEXT with an IOKitPersonalities dictionary that matches a USB device and a signing configuration that matches PCI. The DEXT will build fine and is fully installable. However, that DEXT... won't actually "do" anything. That is, stage #1 will occur and stage #2 will always fail.
Similarly, this works:
To check for any minor errors in my work, I reverted to a "sign to run locally" environment and tried the following values.
...because it basically just skips #2 above.
In terms of next steps, a few different points:
-
IOPCIFamily does have the "Dev Only" entitlement (see the configuration above). That works by defining a match criteria that covers "any" PCI device. If you just want something to work "now" and/or you're working with development hardware (which doesn't match your final hardware config), then this is the best option.
-
Given that the local signing driver is working, it sounds like the underlying problem here is that the entitlement you've been granted doesn't have the right configuration. Fixing that is going to require applying for the entitlement again with the right values. If you go that route, please include my name ("Kevin Elliott") in the request and mention that you're correcting an incorrect grant, along with the entitlement values you actually need.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware