6
votes

Goal: to sign my own packages, and my own kernel extensions. "My own" in the context means "that I wrote, or that I picked elsewhere, recompiled myself from their sources, and want to install on my machine.

Problem: Mavericks does not accept my signature with Code Signing Failure: code signature is invalid (but loads the kext), Yosemite won't even load it.

I have my own CA, and code-signing certs. I've been able to successfully sign code and set up policies that would allow code signed by the given certs to be installed and executed - both codesign and spctl like it, as you see in the output below. However, that does not seem to apply to kext (kernel extensions) - kextutil insists that the signature is invalid. Here's the output I'm getting:

$ codesign --verify -vvvv /opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext
/opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext: valid on disk
/opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext: satisfies its Designated Requirement

$ spctl -a -vvv -t exec /opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext
/opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext: accepted
source=XXXXXCode
origin=XXXXXCoder
$ spctl -a -vvv -t install /opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext
/opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext: accepted
source=XXXXXInstall
origin=XXXXXCoder

$ kextutil -tn /opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext
Diagnostics for /opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext:
Code Signing Failure: code signature is invalid
/opt/local/Library/Filesystems/osxfusefs.fs/Support/osxfusefs.kext appears to be loadable (including linkage for on-disk libraries).

On Mavericks this kext loads with a warning message, on Yosemite it will not.

I noticed here and in Apple CA CPS Developer ID that the cert must have the following extension: ( 1.2.840.113635.100.6.1.18 ) to designate it as kext-signing certificate. Mine does not have it. I suspect it to be the cause of my problem, but don't know how to resolve it. There does not seem to be an type option in spctl to create a policy designating a given cert as a kext-signing one.

How do I add this extension (preferably within Keychain Certificate Assist, though an OpenSSL-based solution would be fine too), short of paying Apple annual "usage fee" of $100?

3
Short of compiling your own kernel that will accept kexts signed with your certificate, you'll need to get one from Apple. On the plus side, your $100 aren't required annually if all you want are certificates for signing apps, installers and kexts - Developer ID certificates expire after 5 years, not 1.pmdj
Thanks, but I'm not sure I understand. Developer Member Center does not allow one to request a certificate until/unless one enrolls in the specific developer program. Mac Developer Program is listed at $99/year. There's no way for me to check for how long they would issue a Developer ID cert. Are you saying that one would be able to cancel (or not renew) his membership after one year, but his Developer ID cert would not expire for 4 more years?Mouse
Yes, the renewal is not automatic. The developer ID certificate, in my experience, expires 5 years after issuing. So I guess if you request a new certificate shortly before expiry, you'll get a total of almost 6 years out of it. I suspect any thusly signed software will fail gatekeeper validation once your certificate expires, so it's maybe not a great idea to publish software on the web that has only a few months before gatekeeper blocks it. Mind you, 5 years is a long time in Software. By that time, Macs might run on ARM CPUs, and third party kexts aren't allowed at all. ;-)pmdj

3 Answers

4
votes

To request a Kext signing certificate from Apple, you need to use this form.

3
votes

Only Apple can generate certificates with this OID and have it considered as valid for the kernel.

See What's New in Kext Development at tonymacx86.com for a more-detailed explanation. Here are the relevant parts.

The OID 1.2.840.113635 is Apple's company prefix, and the rest of the OID describes what specific property must exist in certificate "leaf" (the signing certificate) to allow the kernel extension to load. This means that a valid, signed kernel extension can only be created with a certificate provided by Apple as part of their $99/yr Developer program, and additionally that interested parties must fill out a special form explaining why they require the certificate; kext certificates are only provided upon request and approval.

While it is possible to generate a certificate with a specific OID and sign it with your own CA, OS X will only recognize Apple's CA for kernel extensions. Gatebreak's documentation briefly mentions this.

change the code requirements embedded in kextutil, kextd, and kextcache so they allow root certificates other than Apple's

1
votes

Anyone can generate certificates with whatever OIDs that they want. In fact, OIDs are being added all the time. You can head over to IANA, request an OID and hack gnutls/openssl source code to start generating certificates for your new fangled field. The relevant OIDs for code signing that need to be in the certificate are documented. That should take handle the generation of personal CA and intermediary certificates that can sign kexts. Have a look at the patches against OpenSSL that enable it to generate RPKI certificaes

The next task is figuring out how Apple will recognise your CA as an anchor certificate. My guess here is that you'll need to import the generated CA cert using KeyChain Access. If apple somehow hardcodes the CAs (unlikely and would be stupid), we would be doomed. Otherwise, they must be loading the certificate anchors from some filesystem resource. Use dtruss to find out. My initial investigation points at /System/Library/Keychains/