6

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?

Community
  • 1
  • 1
Mouse
  • 542
  • 6
  • 9
  • 1
    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 Nov 09 '14 at 22:50
  • Thanks, but I'm not sure I understand. [Developer Member Center](https://developer.apple.com/membercenter/index.action) does not allow one to request a certificate until/unless one enrolls in the specific developer program. [Mac Developer Program](https://developer.apple.com/programs/mac/) 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 Nov 09 '14 at 23:59
  • 1
    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 Nov 10 '14 at 09:10

3 Answers3

5

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

Colin Valliant
  • 1,899
  • 1
  • 13
  • 20
  • 1
    The only problem with this answer is that it requires one to pay the annual fee of $99 as a Mac Developer. And this is precisely what I want to avoid, as my original question stated. – Mouse Nov 30 '14 at 20:46
  • 2
    Sure, but this question is much easier to find than that form: I found this quite a while before the form. – Colin Valliant Dec 06 '14 at 04:48
3

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

Alexander O'Mara
  • 58,688
  • 18
  • 163
  • 171
  • Does it mean that I cannot create a certificate with an extension whose OID starts with 1.2.840.113635, and sign that certificate with my own CA that is marked as trusted in my keychain? It would not be signed by Apple CA, but aren't all the trusted CA equal as long as they're marked as "trusted"? I realize that such a cert wouldn't allow me to _distribute_ that given kext, but that's not needed. – Mouse Nov 09 '14 at 23:49
  • @Mouse I believe that OSX will only recognize Apple's CA for kernel extensions. [Gatebreak](http://www.tonymacx86.com/mavericks-desktop-support/112306-gatebreak-signed-kexts-everyone.html) briefly talks about this. I would love to be proven wrong about this though. – Alexander O'Mara Nov 10 '14 at 02:52
  • I doubt that only apple can generate certs with a specific OID. I think that all you need to do is hack OpenSSL to add the OID that you want and openssl will happily generate a certificate with that OID. I know this because I worked on RPKI and the certificates had a new OID for BGP and IP resources... – Lmwangi Nov 11 '14 at 08:30
  • @Lmwangi Unfortunately, according to Gatebreak's documentation, OS X will only recognize Apple's CA for kernel extensions. I've updated my answer to include this information. – Alexander O'Mara Nov 11 '14 at 18:07
1

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/

Lmwangi
  • 2,486
  • 1
  • 19
  • 26