wiki:libwdi/signed_driver_walkthrough

Version 8 (modified by pbatard, 2 years ago) (diff)

--

(Previous) (Back to Table of Content)

Signed Driver Walkthrough

This section documents the use of a driver signing digital credential and libwdi to create a driver installer application that allows the installation of a Windows driver without prompts.

Prerequisites

  1. A set of driver binaries, along with a static inf file matching the devices you plan to support (the inf that libwdi generates cannot work, as it would then need to be signed on the fly, meaning that that you would have to embed the private key used for signing in your application, with is not something you should ever do)
  2. A valid driver signing certificate (see "Obtaining a driver signing certificate")
  3. The latest libwdi source, and one of the supported libwdi development environments. Since you will also need the latest WDK below, it might be a good idea to use it as your development environment
  4. The latest WDK

For the purpose of this exercise, I will be using libusb-win32_ft2232_driver files from the latest OpenOCD-dev 0.5.0 as well as driver signing credentials obtained from GlobalSign (this would be a .pfx, along with the private key password). The development toolchain will be WDK 7.0.0.

Obtaining a driver signing certificate

To be able to digitally sign a Windows driver, you need a Microsoft Authenticode code signing credential. A credential consists of a public key, embedded in a public certificate, containing your trusted third party verified information, as well as the matching private key, which is used to encrypt what is meant to be decrypted using the public key.

Most of the driver signing credentials I am aware of seem to originate either from VeriSign or GlobalSign. Other Certification Authorities providing these services also exist, but Verisign and GlobalSign are the two that appear to be most commonly used.

An important point to be aware of is that that driver signing certificates can only be delivered to registered companies, which the Certification Authority will check, therefore individual users, who don't have their own registered company, cannot usually purchase driver signing certificate. Of course, you can check with the Certification Authority to find out what their delivery requirements are.

Verisign

  • 1st year driver signing credentials can be obtained for $99
  • A lot more expensive than GlobalSign outside of the 1st year promo: $499/year

Globalsign

  • More expensive the first year, but cheaper in the long run: $229/year
  • More friendly to non-US based customers (based in Belgium)

From the date of registration, delivery of your certificate can take from a few days, to a few weeks.

Signing the driver binaries

After downloading either one of the openocd[-x64]-0.5.0-dev windows binaries, one can find the libusb-win32_ft2232_driver-101028.zip archive in the drivers/ directory. After further extracting that archive, you will find that it contains an inf file, along with the amd64/ and x86/ containing the the actual driver binaries. If you look at the binaries' properties, on the Digital Signatures tab, you will find that they have already been signed by the libusb-win32 developers (so that they can be installed on Windows outside of test mode). This is not a problem as the signature we are going to create is going to replace any existing one. If you were to recompile the libusb-win32 drivers from source, you would of course have no signature. And of course, since there is no signed .cat, the inf is also not signed.

Timestamping

While using a trusted time source for signature creation or validation is something you should always consider when using PKI, the reason you want to use timestamping from a trusted timestamping authority when signing your drivers is because it ensures that they can still be used in Windows after the code signing certificate expires. If you don't use timestamping when signing your driver files, then you will have to provide all your users with updated drivers if your original certificate expired. For instance, if you purchased a one year certificate and didn't timestamp, your drivers will cease functioning after one year.

Windows Authenticode Certifications Authorities usually provide a timestamping service (usually a dll) that you can reference when signing. Currently these URLs are:

Additional Certificate

While the Windows certificate store has both the GlobalSign and Verisign root CA certificates as Trusted Root Certification Authorities, these CA certificates are not the ones used for driver code signing. Instead Microsoft have their own "Microsoft Code Verification Root" certificate (which, curiously, will not appear at the top of the certification chain for signed code certificates), which they used to sign the root certificate used by the Certification Authorities they entrusted to provide Authenticode credentials to customers. Microsoft calls that a cross certificate.

By default however, Windows platforms only have the Microsoft Code Verification Root certificate installed, not the the ones from subsidiaries, therefore, to be able to validate the trust chain, the CA's Authenticode root certificate must also be provided.

In short, this means that you will also need to download the root Authenticode certificate from, GlobalSign, Verisign or your other third party authority, so that it can be embedded in the signature. Currently, these certificates can be obtained from:

For the record, all the certificates above seem set to expire on 2016.05.23. What happens to Windows signed driver users past that date is something that probably warrants some testing... [TODO]

Hint: For some weird reasons, Microsoft thought it was a good idea to provide these certificates in the form of an executable. If you want to extract certificate without running the exe, just open it in 7-Zip, then open the _winzip_ file you'll find there, and you'll get to the MSCV-GlobalSign?.cer or MSCV-VSClass3.cer certificates.

Signing process

With your driver signing .pfx file, the corresponding private key password, the MSVC-#### certificate above and the timestamp URL, you are now good to sign your driver files. It is probably a good idea to place the CA certificate along with your pfx in an easily accessible directory. In the example below, we will use the akeo.pfx driver signing credentials, obtained from GlobalSign, as well as MSCV-GlobalSign?.cer from the D:codesign directory. The timestamping authority will also be the one from GlobalSign. Preferably you want to sign all the driver files, including the DLLs, but technically, only the .sys should be required.

To sign the file, open one of the WDK dos prompts (eg. Windows XP x86 Free Build Environment), then navigate to the directory containing the driver files you want to sign (eg "libusb-win32_ft2232_driver-101028amd64libusb0.sys" and issue the following:

D:libusb-win32_ft2232_driver-101028amd64>signtool sign /v /ac D:codesignMSCV-GlobalSign.cer /f D:codesignakeo.pfx /p "<YOUR_PASSWORD>" /t http://timestamp.globalsign.com/scripts/timstamp.dll libusb0.sys
The following certificate was selected:
    Issued to: Akeo Consulting
    Issued by: GlobalSign ObjectSign CA
    Expires:   Sun Jun 26 10:05:35 2011
    SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8

Cross certificate chain (using machine store):
    Issued to: Microsoft Code Verification Root
    Issued by: Microsoft Code Verification Root
    Expires:   Sat Nov 01 13:54:03 2025
    SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3

        Issued to: GlobalSign Root CA
        Issued by: Microsoft Code Verification Root
        Expires:   Mon May 23 17:10:51 2016
        SHA1 hash: 3EEB2750A199F5E7B6A8952430BE5062FE04E9E5

            Issued to: GlobalSign Primary Object Publishing CA
            Issued by: GlobalSign Root CA
            Expires:   Fri Jan 27 12:00:00 2017
            SHA1 hash: 1AAF4DF10D36215E09E4EEFD70E340C2E4DECF38

                Issued to: GlobalSign ObjectSign CA
                Issued by: GlobalSign Primary Object Publishing CA
                Expires:   Fri Jan 27 11:00:00 2017
                SHA1 hash: B859853EF366AC9335763C340A87BD208113055F

                    Issued to: Akeo Consulting
                    Issued by: GlobalSign ObjectSign CA
                    Expires:   Sun Jun 26 10:05:35 2011
                    SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8

Done Adding Additional Store
Successfully signed and timestamped: libusb0.sys

Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0

For details on what each of the option above does, though they should be fairly explicit, you can issue: signtool sign /?.

Checking the signed driver files

Optional, but probably a good idea, as you will get the timestamping info as well.

D:libusb-win32_ft2232_driver-101028amd64>signtool verify /kp /v libusb0.sys

Verifying: libusb0.sys
Hash of file (sha1): B4C09901487067EB10454F6CFFCFA3C64988EE86

Signing Certificate Chain:
    Issued to: GlobalSign Root CA
    Issued by: GlobalSign Root CA
    Expires:   Fri Jan 28 12:00:00 2028
    SHA1 hash: B1BC968BD4F49D622AA89A81F2150152A41D829C

        Issued to: GlobalSign Primary Object Publishing CA
        Issued by: GlobalSign Root CA
        Expires:   Fri Jan 27 12:00:00 2017
        SHA1 hash: 1AAF4DF10D36215E09E4EEFD70E340C2E4DECF38

            Issued to: GlobalSign ObjectSign CA
            Issued by: GlobalSign Primary Object Publishing CA
            Expires:   Fri Jan 27 11:00:00 2017
            SHA1 hash: B859853EF366AC9335763C340A87BD208113055F

                Issued to: Akeo Consulting
                Issued by: GlobalSign ObjectSign CA
                Expires:   Sun Jun 26 10:05:35 2011
                SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8

The signature is timestamped: Tue Feb 08 13:54:32 2011
Timestamp Verified by:
    Issued to: GlobalSign Root CA
    Issued by: GlobalSign Root CA
    Expires:   Fri Jan 28 12:00:00 2028
    SHA1 hash: B1BC968BD4F49D622AA89A81F2150152A41D829C

        Issued to: GlobalSign Timestamping CA
        Issued by: GlobalSign Root CA
        Expires:   Fri Jan 28 12:00:00 2028
        SHA1 hash: 958D23902D5448314F2F811034356A58255CDC9B

            Issued to: GlobalSign Time Stamping Authority
            Issued by: GlobalSign Timestamping CA
            Expires:   Tue Dec 22 09:32:56 2020
            SHA1 hash: AEDF7DF76BBA2410D67DBAF18F5BA15B417E496C

Cross Certificate Chain:
    Issued to: Microsoft Code Verification Root
    Issued by: Microsoft Code Verification Root
    Expires:   Sat Nov 01 13:54:03 2025
    SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3

        Issued to: GlobalSign Root CA
        Issued by: Microsoft Code Verification Root
        Expires:   Mon May 23 17:10:51 2016
        SHA1 hash: 3EEB2750A199F5E7B6A8952430BE5062FE04E9E5

            Issued to: GlobalSign Primary Object Publishing CA
            Issued by: GlobalSign Root CA
            Expires:   Fri Jan 27 12:00:00 2017
            SHA1 hash: 1AAF4DF10D36215E09E4EEFD70E340C2E4DECF38

                Issued to: GlobalSign ObjectSign CA
                Issued by: GlobalSign Primary Object Publishing CA
                Expires:   Fri Jan 27 11:00:00 2017
                SHA1 hash: B859853EF366AC9335763C340A87BD208113055F

                    Issued to: Akeo Consulting
                    Issued by: GlobalSign ObjectSign CA
                    Expires:   Sun Jun 26 10:05:35 2011
                    SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8

Successfully verified: libusb0.sys

Number of files successfully Verified: 1
Number of warnings: 0
Number of errors: 0

Creating a signed cat file

Why would you want a signed cat?

What we did above allows the installation of drivers in a Windows environment outside of test mode, which is fine and all, but unless you sign the inf as well, you will get the following prompt on Vista and later versions of Windows during driver installation:

One way to avoid this prompt is to go through WHQL. However, this is an expensive and time-consuming process, and Microsoft are currently abusing their position to prevent GPL licensed drivers (both GPLv2 and GPLv3) from being accepted through the WHQL process (for the record, at the time of this post, the libusb-win32 driver is GPLv2) The other solution is to use your driver signing credentials to sign the inf, and create a cat file.

The only drawback of doing that your users may get a prompt about trusting the company identified by the certificate as a trusted publisher [TODO: pic] unless: 1 they previously checked "Always trust software from company X" when previously prompted with a similar query 1 you installed your certificate in the Trusted Publisher system store In essence, the end result from both of the options above is that your certificate ends up as a Trusted Publisher on the user system. As we will see later on, libwdi provides an API for option 2.

Signing a cat file

Since we're using the WDK, we have access to the inf2cat tool, which is the most convenient way to create a cat out of an inf file. Before you can use inf2cat, you must ensure that your .inf contains a CatalogFile? entry in the [Version] section, that provides the name of the .cat to be created. The libusb-win32_ft2232_driver.inf file we use is missing it, so we add it:

CatalogFile = "libusb-win32_ft2232_driver.cat"

Then, you can simply run:

D:libusb-win32_ft2232_driver-101028>inf2cat /v /driver:. /os:XP_X86,XP_X64,Vista_X86,Vista_X64,7_X86,7_X64
Processing directory (D:libusb-win32_ft2232_driver-101028) file (info.txt)
Processing directory (D:libusb-win32_ft2232_driver-101028) file (libusb-win32_ft2232_driver.inf)
Processing directory (D:libusb-win32_ft2232_driver-101028amd64) file (libusb0.dll)
Processing directory (D:libusb-win32_ft2232_driver-101028amd64) file (libusb0.sys)
Processing directory (D:libusb-win32_ft2232_driver-101028x86) file (libusb0.sys)
Processing directory (D:libusb-win32_ft2232_driver-101028x86) file (libusb0_x86.dll)
Parsing INF: D:libusb-win32_ft2232_driver-101028libusb-win32_ft2232_driver.inf
Finished parsing INFs
Processing INF: D:libusb-win32_ft2232_driver-101028libusb-win32_ft2232_driver.inf
Finished processing INFs
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...
Testing driver package...

Signability test complete.

Errors:
None

Warnings:
None

Catalog generation complete.

After that, you would sign the generated .cat as follows:

D:libusb-win32_ft2232_driver-101028>signtool sign /v /ac D:codesignMSCV-GlobalSign.cer /f D:codesignakeo.pfx /p "<YOUR_PASSWORD>" /t http://timestamp.globalsign.com/scripts/timestamp.dll libusb-win32_ft2232_driver.cat
The following certificate was selected:
    Issued to: Akeo Consulting
    Issued by: GlobalSign ObjectSign CA
    Expires:   Sun Jun 26 10:05:35 2011
    SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8

Cross certificate chain (using machine store):
    Issued to: Microsoft Code Verification Root
    Issued by: Microsoft Code Verification Root
    Expires:   Sat Nov 01 13:54:03 2025
    SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3

        Issued to: GlobalSign Root CA
        Issued by: Microsoft Code Verification Root
        Expires:   Mon May 23 17:10:51 2016
        SHA1 hash: 3EEB2750A199F5E7B6A8952430BE5062FE04E9E5

            Issued to: GlobalSign Primary Object Publishing CA
            Issued by: GlobalSign Root CA
            Expires:   Fri Jan 27 12:00:00 2017
            SHA1 hash: 1AAF4DF10D36215E09E4EEFD70E340C2E4DECF38

                Issued to: GlobalSign ObjectSign CA
                Issued by: GlobalSign Primary Object Publishing CA
                Expires:   Fri Jan 27 11:00:00 2017
                SHA1 hash: B859853EF366AC9335763C340A87BD208113055F

                    Issued to: Akeo Consulting
                    Issued by: GlobalSign ObjectSign CA
                    Expires:   Sun Jun 26 10:05:35 2011
                    SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8

Done Adding Additional Store
Successfully signed and timestamped: libusb-win32_ft2232_driver.cat

Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0

Packaging the signed files in libwdi

Since we went the trouble of creating a fully signed driver package, that can install without prompts, we might as well deliver the whole thing in a package that is attractive for end users. Also, if you want to avoid the need for users to add your certificate as a Trusted Publisher, libwdi can help you out.

Installing the certificate as a Trusted Publisher using libwdi

Testing the installation