Search code examples
ioscode-signingsignkernel-extensionosx-gatekeeper

Is my kernel extension correctly signed for Yosemite?


I am trying to sign a kernel extension file "abc.kext". I have a kext enabled certificate and tried to sign my "abc.kext" using:

codesign --sign "Developer ID Application: MyCompany (XXXXXXXX)" -a "x86_64" abc.kext

To verify that the signing is successful I run:

codesign --verify -vvvv abc.kext 

and the output is:

abc.kext: code object is not signed at all

Also run:

spct -a -v --type install abc.kext 

and the output is:

abc.kext:rejected
source: no usable signature

If I run:

kextutil -tn abc.kext

output is:

abc.kext appears to be loadable (including linkage for on-disk libraries).

Can somebody help me to find what I am doing wrong?


Solution

  • You don't explicitly say so, but from the outputs you're getting, it looks like you're trying to codesign a multi-architecture kext? If so, don't do that!

    The command codesign --verify -vvvv abc.kext works for kexts I've built and signed, no explicit architecture required. kextutil -n is a very good indicator on any incompatibilities, including code signing, but it only applies to the running version of OS X, so you need to check it with all versions you plan to support.

    If for some reason you need to create a signed version of a kext based on not source code but an existing universal binary, you will need to extract the 64-bit portion of the binary, create a kext bundle from that and sign that. Your installer can then place this signed 64-bit kext in /Library/Extensions, and if the installer detects it is installing on a volume containing OS X 10.8 or older, additionally place the existing universal kext in /System/Library/Extensions. (Additionally so that if/when an upgrade happens, the kext won't suddenly stop working or generate signing warnings.)

    To extract the 64-bit binary, use:

    lipo -thin x86_64 abc.kext/Contents/MacOS/abc -output ./abc-64.kext/Contents/MacOS/abc
    

    where abc.kext is the original universal kext and abc-64.kext is the new kext that you'll be signing. You should give the signed kext the same bundle identifier, but a higher bundle version number than the universal one, even though they're functionally identical. The higher-versioned one will be chosen if it's loadable by the OS.

    An overview of kext requirements in different OS X versions:

    Signed kexts will only load on OS X 10.8 and newer, and those versions all ship with 64-bit only kernels. If you want to support older versions of OS X, you'll need a separate kext for those versions. OS X 10.6 and 10.7 kernels can be either 32 or 64-bit, so if you want to support those versions, use an unsigned universal kext. A kext where the 64-bit portion is signed might load in a 32-bit kernel, but definitely will not load on a 64-bit 10.6/10.7 kernel. 10.5 and earlier only have 32-bit kernels, although of course they exist as both PowerPC and i386 variants (the latter from 10.4 on only). I don't know if it's possible to create a 3-architecture kext, but I suspect it is. Just don't sign it.

    Signing is only required on 10.9 and newer, so you have a little bit of flexibility on what versions each kext covers. (10.8 will also happily load the 64-bit portion of an unsigned universal kext)

    By the way, when building kexts, use the OS X SDK corresponding to the oldest supported OS X version of that build. The deployment target mechanism doesn't work for kexts. (for the most part)