The Practical Truth About x64 Kernel Driver Signing
For a number of reasons, starting with Vista x64, Microsoft requires digital signatures on any and all code loaded into the kernel.
There tends to be quite a bit of confusion about the signing process itself, probably due to the fact that Microsoft changed its policies a few times. See the introduction and the demise of Microsoft-issued Publisher Identity Certificates as an example: http://www.osronline.com/article.cfm?article=465 (free registration required)
No surprise then that even makers of otherwise excellent software tend to miss a beat here and there – for example, the recently published VMWare Workstation 6.0 Release Candidate contains x64 drivers that do not have proper signatures. When you install the software on an x64 Vista host computer you get ugly warnings from the device installer, but the drivers themselves function: this indicates valid signatures on the drivers but the lack of properly signed catalog files.
Invalid or missing catalog file
(click to enlarge)
This document is meant to be a straightforward, non-nonsense guide to signing your x64 drivers. For the gory details grab the 50-page Microsoft document on the subject: http://www.microsoft.com/whdc/winlogo/drvsign/kmcs_walkthrough.mspx.
First, you will need a code-signing certificate. It’s easily obtained from Verisign or another CA approved by Microsoft for kernel signing. Import the certificate and the corresponding private key into your computer’s registry.
Next, you will need the Microsoft-issued cross-certificate for your CA’s root. It can be obtained from http://www.microsoft.com/whdc/winlogo/drvsign/crosscert.mspx. Cross-certificates make life easier for the kernel when it needs to load and verify signed code. They make it possible to have a single trusted root entity (Microsoft), and from here, form a chain of trust to your code signing certificate. If the CA that issued your Authenticode certificate is not listed here you’re out of luck. You will need a code signing certificate from one of these six CAs.
You will also need a couple of tools from the Windows Driver Kit (version 5370 or newer): signtool.exe and makecat.exe. Older versions of signtool will not work because they don't understand cross-certificates. (No current version of signtool will handle cross-certs via the signwizard GUI either. For kernel-mode code signing you will have to resort to the command line.)
As an example, I’m going to sign the x64 audio drivers distributed with VMWare Workstation 5. Signing these drivers (originally intended for use with XP x64 and Windows Server 2003 x64) will enable us to use them in a Vista x64 guest. The drivers can be obtained from here: http://download3.vmware.com/software/wkst/vmaudio-18.104.22.16800.zip
Signing the binaries
You are going to sign the driver binaries (.sys and .dll files) just like you would sign a PE file with an Authenticode signature while also telling signtool to use the proper cross-certificate:
signtool.exe sign /ac mscv-vsclass3.cer /sha1 ca40385b9971ab32d1ad4c93225688dbc168c867 vmaudio.sys
The mscv-vsclass3.cer file refers to the Microsoft-issued cross-certificate (this will be different for you if you're not using a Verisign SPC), the SHA1 thumbprint tells signtool to locate the correct certificate in the registry (this will definitely be different for you), and vmaudio.sys is, of course, the binary to be signed.
In real life you will also want to timestamp the file and maybe provide a brief description:
signtool.exe sign /ac mscv-vsclass3.cer /sha1 ca40385b9971ab32d1ad4c93225688dbc168c867 /t "http://timestamp.verisign.com/scripts/timestamp.dll" /d "VMWare Audio Driver" vmaudio.sys
If your driver installs via CreateService (has no .inf file) or you don’t mind scaring your users with a big, red, intimidating message you can stop here.
Otherwise we have one step left.
The .cat file
You will need to create and distribute a .cat file with your driver. The easiest way to do this is through a .cdf (catalog defition) file that – in its simplest incarnation - looks like this:
[CatalogHeader] Name=vmaudio.cat ResultDir=.\ PublicVersion=0x00000001 [CatalogFiles] <HASH>vmaudio.sys=.\vmaudio.sys <HASH>vmaudio.inf=.\vmaudio.inf
"Name" specifies the output file. Under [CatalogFiles] you will need to list the files packaged with your driver. This includes the binaries signed in the previous step and your .inf file.
The .inf must also refer to the catalog file in its [Version] section. Something like this:
[Version] Signature="$Windows NT$" DriverVer =12/29/2005,22.214.171.12400 CatalogFile = vmaudio.cat ...etc...
When this is done you simply run makecat:
Finally, sign the catalog:
signtool.exe sign /ac mscv-vsclass3.cer /sha1 ca40385b9971ab32d1ad4c93225688dbc168c867 /t "http://timestamp.verisign.com/scripts/timestamp.dll" /d "VMWare Audio Driver" vmaudio.cat
Installing this driver will produce a friendly message:
Properly signed catalog file
(click to enlarge)
If you’re providing an .inf and a .cat file with your driver it is worth noting that the binary signing process is not a hard requirement. The kernel loader can understand the signature embedded in the .cat file. For performance reasons however it is recommended that you sign the binary components as well.
Strangely enough, the user-mode device installer is not as smart as the kernel and can not get by on signatures embedded in the driver binaries alone. If your driver does not have a valid catalog file it does not have a valid signature, as far as the device installer is concerned. This doesn’t mean that the kernel will not load your software perfectly happily – but it does mean that the user will be presented with a rather intimidating message at install-time. To a certain degree there’s some logic in this: the .cat file is the only way to sign the .inf file itself, and the .inf alone can make pretty drastic changes to the system – so maybe it is a good idea to require it to be signed.
The signed driver can be downloaded from here: http://codefromthe70s.org/files/vmaudio-126.96.36.19900-signed.zip