"Signing certificate" and post-installation assignment fail due to IOPCIPrimaryMatch

I'm having trouble configuring the "IOPCIPrimaryMatch" entitlement.

I'm currently developing using "sign to run locally" and have been able to confirm the expected behavior. I was considering signing with "Developer ID Application" for future distribution to customers, but after finding the following forum, I'm now aiming to sign with "Apple Development." https://developer.apple.com/forums/thread/743021

I'm currently having trouble with the IOPCIPrimaryMatch value. The "signing certificate" status in Xcode changes depending on the value, as follows:

Successful if the value is as follows: <key>IOPCIPrimaryMatch</key> <string>0xFFFFFFFF&0x00161916</string>

An error occurs if the value is as follows: <key>IOPCIPrimaryMatch</key> <string>0xFFFFFFFF&amp;0x00161916</string>

So I tried building and installing using "0xFFFFFFFF&0x00161916", but this time the driver was not assigned to the PCI device.

By the way, when I used "sign to run locally", both the installation and assignment were successful with the following: <key>IOPCIPrimaryMatch</key> <string>0xFFFFFFFF&amp;0x00161916</string>

Could you please tell me the correct way to write this?

I'm currently developing using "sign to run locally" and have been able to confirm the expected behavior. I was considering signing with "Developer ID Application" for future distribution to customers, but after finding the following forum, I'm now aiming to sign with "Apple Development." https://developer.apple.com/forums/thread/743021

I've already replied on that post and my advice to you is going to be the same ("Switch everything to automatic"!) with one addition. Looking at you account, you entitlement.plist configuration should be:

<key>com.apple.developer.driverkit.transport.pci</key>
<array>
	<dict>
		<key>IOPCIPrimaryMatch</key>
		<string>0x00001916&amp;0x0000FFFF</string>
	</dict>
</array>

...which matches what you were approved for. That value will display in Xcode as:

0x00001916&0x0000FFFF

By the way, when I used "sign to run locally", both the installation and assignment were successful with the following: <key>IOPCIPrimaryMatch</key> <string>0xFFFFFFFF&amp;0x00161916</string>

Unfortunately, signing locally can be deeply misleading, as it basically works by disabling exactly the validation that's failing here. There's a similar issue when you switch from "Automatic" to "Manual" code-signing. It's possible using "Manual" to get Xcode to sign configurations it wouldn't sign with "Automatic"... and, in most cases, all you've done there is convert a build time error into a runtime failure. That's not progress.

On the topic of those errors, quoting myself:

"...One thing to be aware of here is that Xcode has a "bias" in the way it presents codesign errors where it assumes the Entitlement.plist is "correct" and the profile is "wrong". However, in practice that's basically "never" the case with DriverKit entitlements and tends to lead to a lot of "flailing" trying to somehow "fix" the provisioning profile...."

The rest of that post has more details on this process, but the key idea here is that you fix code signing issues by changing the configuration of the "data" (either your entitlement.plist or your portal configuration), NOT by changing the configuration of your project.

Finally, for reference, I have two posts on describing how to validate the entitlement configuration of a DEXT build. This post outlines the "theory", while the following post has a detailed example from an actual DEXT.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Your answer is helpful. My previous question was strange because I didn't consider posting it in HTML. As a result, I wasn't able to properly communicate what I wanted to say.

The symptoms I'm experiencing are as follows:

  1. With the following settings, the "signing certificate" status in Xcode shows as failed.
<key>IOPCIPrimaryMatch</key> <string>0x00001916&amp;0x0000FFFF</string>

The error message is as follows: doesn't include the com.apple.developer.driverkit.allow-any-userclient-access entitlement and doesn't match the entitlements file's value for the com.apple.developer.driverkit.transport.pci entitlement.

  1. With the following settings, the "signing certificate" status error in Xcode disappears, and building and driver installation succeed. However, the driver cannot be assigned to the device.
<key>IOPCIPrimaryMatch</key> <string>0x00001916&0x0000FFFF</string>

To check for any minor errors in my work, I reverted to a "sign to run locally" environment and tried the following values. All errors disappeared, and my drivers and software worked correctly.

<key>IOPCIPrimaryMatch</key> <string>0x00001916&amp;0x0000FFFF</string>

What I wanted to convey in my previous post was that I think I should include this "amp;", but when I do, the "signing certificate" status in Xcode shows as failed. Why is that?

I tried the values ​​you provided, and the problem was exactly the same as before, so I'd really appreciate an answer.

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:

  1. Your Entitlement.plist -> This is used to create the actual code-signature "attached" to your app bundle.

  2. 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 "&amp;" happens because the "right" answer depends on how you're looking at the file.

  1. If you open a plist file as plain text, you'll see the value "&amp;". That's because the standalone character "&" is a reserved XML character, and "&amp;" is its escaped variant.

  2. 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&amp;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:

  1. 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.

  2. 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

"Signing certificate" and post-installation assignment fail due to IOPCIPrimaryMatch
 
 
Q