By Community Contributor, Tim Roberts
I find an enormous amount of confusion and a fair amount of misinformation about driver signing in Windows. It’s a topic that hasn’t traditionally had a lot of attention, because in the past, many of us just ignored driver signing. Those of us who had to learn it did so once, and then used that recipe repeatedly.
The most important point to realize is that there are two very different signature checks that Windows performs. It’s easy to miss this point, as evidenced by many newsgroup and forum postings, but it’s important to remember because the two checks require different handling.
Check 1: Signature Check for Trusted Vendor
The first signature check occurs to determine if the vendor supplying the driver is known and trusted. This check occurs once, when your driver is installed. Specifically, the check occurs when your driver is copied into the driver store, or when a new device is detected that requires your INF to be executed. This check happens on all Windows versions since Windows 2000. It occurs on all architectures, so it is not one of those checks that only apply to x64-based platforms. However, it’s important to note that this check applies only to plug-and-play devices.
This signature check only involves the catalog (CAT) file. If you do not have a CAT file, or if your CAT file is not signed, you get the dreaded red-flag “unsigned driver” warning. If your CAT is signed with a non-WHQL signature, you get a “do you trust this publisher” warning shown in Figure 1 (on Vista and beyond). In either case, the user can simply proceed with the installation with the appropriate mouse click. Once you have passed this check, you can disable, enable, unplug and replug forever, and the signature will not be rechecked, unless there is a new device that matches your INF file. Your CAT can be signed with any valid code-signing certificate.
Check 2: KMCS Check
The second signature check is the kernel-mode code signing (KMCS) check. This happens only on x64 architecture systems, but it happens every time the driver is loaded, and it applies to all kernel modules. In other words, unlike the check for the WHQL signature or known publisher described previously, this check occurs regardless of whether the driver being loaded is plug-and-play. During driver installation, and each time thereafter when the system is booted, the check is performed. When you unplug/replug, the driver is checked again. Even if your driver package is correctly installed, the driver will not be loaded unless it passes the KMCS check. Attaching a kernel debugger disables the KMCS check.
The KMCS signature can be present either in your SYS file, or in your CAT file. Non-plug-and-play drivers usually won’t have a CAT file, so the SYS file must be signed. If you sign the CAT file only, you cannot replace the SYS file (for example, during debugging). The CAT file contains a checksum of the matching SYS file. For this reason, I usually sign both the CAT and the SYS. For drivers used during system boot, Microsoft strongly suggests that you sign the SYS file, because it can take too long to locate the corresponding CAT file with the limited disk driver stack used during boot.
Kernel-mode code signing check requires a very specific type of signature, and that the driver be signed in a very particular way. Specifically:
- You must use a valid Class 3 Code Signing Certificate – an ordinary certificate, such as used for SSL, is not acceptable
- The Class 3 Code Signing Certificate must be issued by a Microsoft-approved Certification Authority (see [1] at the conclusion of the article for a list)
- At the time of signing, you must reference the “cross-certificate” for the specific Certification Authority that issued the Class 3 Code Signing Certificate you’re using.
When you sign your SYS and/or CAT file, you must select both your code-signing certificate, and the associated cross certificate (using the /ac parameter of signtool). This produces a certificate “chain” that ends at the “Microsoft Code Verification Root”. That certificate chain must be present either in the SYS file or the CAT file or both, but wherever it exists, it must be a complete chain with cross-certificate.
My “signtool” command line looks like this:
signtool sign
/v
/ac MSVC-GlobalSign.cer
/sha1 xxxxxxxxxx
/t http://timestamp.verisign.com/scripts/timestamp.dll
objfre_wlh_amd64\amd64\mydriver.sys
Where:
/v – verbose output
/ac – to select the cross certificate
/sha1 – to identify your code signing certificate’s thumbprint
/t to embed a timestamp so the signature does not expire
Where to Go from Here?
Hopefully, this short article has help clarify some of the more confusing aspects of driver signing.
Microsoft has published a thorough hands-on tutorial describing the KMCS process on the WHDC web site (see [2] further below). By carefully following the steps outlined in this document, you’re guaranteed to be able to successfully sign your driver. Of course, this assumes you have the correct certificate (as described above)!
[1] http://msdn.microsoft.com/en-us/library/windows/hardware/dn170454(v=vs.85).aspx
[2] http://msdn.microsoft.com/en-us/library/windows/hardware/dn653569(v=vs.85).aspx
Tim Roberts (timr@probo.com) is a developer with Providenza & Boekelheide, Inc., a consulting firm in beautiful Tigard, Oregon. He’s been programming for 35 years, and living in the Windows world since version 3.0. Tim spends way too much time with computers.