| 1 | | [http://libusb.org/wiki/libwdi/usage (Previous)] [http://libusb.org/wiki/libwdi#Documentation (Back to Table of Content)] |
| 2 | | |
| 3 | | = Signed Driver Walkthrough = |
| 4 | | [[PageOutline(2-5, Signed Driver Walkthrough)]] |
| 5 | | |
| 6 | | 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.[[BR]] |
| 7 | | |
| 8 | | == Prerequisites == |
| 9 | | |
| 10 | | 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) |
| 11 | | 1. A valid driver signing certificate (see "Obtaining a driver signing certificate") |
| 12 | | 1. 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 |
| 13 | | 1. The [http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&FamilyID=36a2630f-5d56-43b5-b996-7633f2ec14ff latest WDK] |
| 14 | | |
| 15 | | For the purpose of this exercise, I will be using libusb-win32_ft2232_driver files from the latest [http://www.freddiechopin.info/index.php/en/download/category/10-openocd-dev 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. |
| 16 | | |
| 17 | | == Obtaining a driver signing certificate == |
| 18 | | |
| 19 | | 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. |
| 20 | | |
| 21 | | Most of the driver signing credentials I am aware of seem to originate either from [http://www.verisign.com/ VeriSign] or [http://www.globalsign.com/ GlobalSign]. Other Certification Authorities providing these services [http://www.microsoft.com/whdc/driver/install/drvsign/crosscert.mspx also exist], but Verisign and !GlobalSign are the two that appear to be most commonly used. |
| 22 | | |
| 23 | | '''Verisign''' |
| 24 | | * 1st year driver signing credentials [https://winqual.microsoft.com/help/why_is_a_digital_certificate_required_for_winqual_membership.htm can be obtained for $99] |
| 25 | | * A lot more expensive than !GlobalSign in the long run: $499/year |
| 26 | | * Might not provide credentials for non registered companies |
| 27 | | |
| 28 | | '''Globalsign''' |
| 29 | | * More competitive on pricing compared to Verisign |
| 30 | | * Even if non affiliated to a registered company, individual developers can obtain certificates for [http://www.globalsign.com/code-signing/code-signing-for-individual-developers.html $99 (US & Canada)] / [http://www.globalsign.eu/code-signing/buy-code-signing-for-individual-developers.html €79 (EU)] (promotional offer) |
| 31 | | * More friendly to non-US based customers (based in Belgium) |
| 32 | | |
| 33 | | From the date of registration, delivery of your certificate can take from a few days, to a few weeks. |
| 34 | | |
| 35 | | == Signing the driver binaries == |
| 36 | | |
| 37 | | 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. |
| 38 | | 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 [https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/ 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. |
| 39 | | |
| 40 | | '''Timestamping''' |
| 41 | | |
| 42 | | 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. |
| 43 | | |
| 44 | | Windows Authenticode Certifications Authorities usually provide a timestamping service (usually a dll) that you can reference when signing. Currently these URLs are: |
| 45 | | * http://timestamp.verisign.com/scripts/timstamp.dll (Verisign) |
| 46 | | * http://timestamp.globalsign.com/scripts/timstamp.dll (!GlobalSign) |
| 47 | | |
| 48 | | '''Additional Certificate''' |
| 49 | | |
| 50 | | 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. |
| 51 | | |
| 52 | | 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. |
| 53 | | |
| 54 | | 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: |
| 55 | | * http://www.microsoft.com/whdc/driver/install/drvsign/crosscert.mspx#EWAAC (Verisign) |
| 56 | | * http://www.microsoft.com/whdc/driver/install/drvsign/crosscert.mspx#EMG (!GlobalSign) |
| 57 | | 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] |
| 58 | | |
| 59 | | 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 [http://www.7-zip.org/ 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. |
| 60 | | |
| 61 | | '''Signing process''' |
| 62 | | |
| 63 | | 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. |
| 64 | | 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. |
| 65 | | Preferably you want to sign all the driver files, including the DLLs, but technically, only the .sys should be required. |
| 66 | | |
| 67 | | 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: |
| 68 | | |
| 69 | | {{{ |
| 70 | | 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 |
| 71 | | The following certificate was selected: |
| 72 | | Issued to: Akeo Consulting |
| 73 | | Issued by: GlobalSign ObjectSign CA |
| 74 | | Expires: Sun Jun 26 10:05:35 2011 |
| 75 | | SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8 |
| 76 | | |
| 77 | | Cross certificate chain (using machine store): |
| 78 | | Issued to: Microsoft Code Verification Root |
| 79 | | Issued by: Microsoft Code Verification Root |
| 80 | | Expires: Sat Nov 01 13:54:03 2025 |
| 81 | | SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3 |
| 82 | | |
| 83 | | Issued to: GlobalSign Root CA |
| 84 | | Issued by: Microsoft Code Verification Root |
| 85 | | Expires: Mon May 23 17:10:51 2016 |
| 86 | | SHA1 hash: 3EEB2750A199F5E7B6A8952430BE5062FE04E9E5 |
| 87 | | |
| 88 | | Issued to: GlobalSign Primary Object Publishing CA |
| 89 | | Issued by: GlobalSign Root CA |
| 90 | | Expires: Fri Jan 27 12:00:00 2017 |
| 91 | | SHA1 hash: 1AAF4DF10D36215E09E4EEFD70E340C2E4DECF38 |
| 92 | | |
| 93 | | Issued to: GlobalSign ObjectSign CA |
| 94 | | Issued by: GlobalSign Primary Object Publishing CA |
| 95 | | Expires: Fri Jan 27 11:00:00 2017 |
| 96 | | SHA1 hash: B859853EF366AC9335763C340A87BD208113055F |
| 97 | | |
| 98 | | Issued to: Akeo Consulting |
| 99 | | Issued by: GlobalSign ObjectSign CA |
| 100 | | Expires: Sun Jun 26 10:05:35 2011 |
| 101 | | SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8 |
| 102 | | |
| 103 | | Done Adding Additional Store |
| 104 | | Successfully signed and timestamped: libusb0.sys |
| 105 | | |
| 106 | | Number of files successfully Signed: 1 |
| 107 | | Number of warnings: 0 |
| 108 | | Number of errors: 0 |
| 109 | | }}} |
| 110 | | For details on what each of the option above does, though they should be fairly explicit, you can issue: {{{signtool sign /?}}}. |
| 111 | | |
| 112 | | '''Checking the signed driver files''' |
| 113 | | |
| 114 | | Optional, but probably a good idea, as you will get the timestamping info as well. |
| 115 | | {{{ |
| 116 | | D:libusb-win32_ft2232_driver-101028amd64>signtool verify /kp /v libusb0.sys |
| 117 | | |
| 118 | | Verifying: libusb0.sys |
| 119 | | Hash of file (sha1): B4C09901487067EB10454F6CFFCFA3C64988EE86 |
| 120 | | |
| 121 | | Signing Certificate Chain: |
| 122 | | Issued to: GlobalSign Root CA |
| 123 | | Issued by: GlobalSign Root CA |
| 124 | | Expires: Fri Jan 28 12:00:00 2028 |
| 125 | | SHA1 hash: B1BC968BD4F49D622AA89A81F2150152A41D829C |
| 126 | | |
| 127 | | Issued to: GlobalSign Primary Object Publishing CA |
| 128 | | Issued by: GlobalSign Root CA |
| 129 | | Expires: Fri Jan 27 12:00:00 2017 |
| 130 | | SHA1 hash: 1AAF4DF10D36215E09E4EEFD70E340C2E4DECF38 |
| 131 | | |
| 132 | | Issued to: GlobalSign ObjectSign CA |
| 133 | | Issued by: GlobalSign Primary Object Publishing CA |
| 134 | | Expires: Fri Jan 27 11:00:00 2017 |
| 135 | | SHA1 hash: B859853EF366AC9335763C340A87BD208113055F |
| 136 | | |
| 137 | | Issued to: Akeo Consulting |
| 138 | | Issued by: GlobalSign ObjectSign CA |
| 139 | | Expires: Sun Jun 26 10:05:35 2011 |
| 140 | | SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8 |
| 141 | | |
| 142 | | The signature is timestamped: Tue Feb 08 13:54:32 2011 |
| 143 | | Timestamp Verified by: |
| 144 | | Issued to: GlobalSign Root CA |
| 145 | | Issued by: GlobalSign Root CA |
| 146 | | Expires: Fri Jan 28 12:00:00 2028 |
| 147 | | SHA1 hash: B1BC968BD4F49D622AA89A81F2150152A41D829C |
| 148 | | |
| 149 | | Issued to: GlobalSign Timestamping CA |
| 150 | | Issued by: GlobalSign Root CA |
| 151 | | Expires: Fri Jan 28 12:00:00 2028 |
| 152 | | SHA1 hash: 958D23902D5448314F2F811034356A58255CDC9B |
| 153 | | |
| 154 | | Issued to: GlobalSign Time Stamping Authority |
| 155 | | Issued by: GlobalSign Timestamping CA |
| 156 | | Expires: Tue Dec 22 09:32:56 2020 |
| 157 | | SHA1 hash: AEDF7DF76BBA2410D67DBAF18F5BA15B417E496C |
| 158 | | |
| 159 | | Cross Certificate Chain: |
| 160 | | Issued to: Microsoft Code Verification Root |
| 161 | | Issued by: Microsoft Code Verification Root |
| 162 | | Expires: Sat Nov 01 13:54:03 2025 |
| 163 | | SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3 |
| 164 | | |
| 165 | | Issued to: GlobalSign Root CA |
| 166 | | Issued by: Microsoft Code Verification Root |
| 167 | | Expires: Mon May 23 17:10:51 2016 |
| 168 | | SHA1 hash: 3EEB2750A199F5E7B6A8952430BE5062FE04E9E5 |
| 169 | | |
| 170 | | Issued to: GlobalSign Primary Object Publishing CA |
| 171 | | Issued by: GlobalSign Root CA |
| 172 | | Expires: Fri Jan 27 12:00:00 2017 |
| 173 | | SHA1 hash: 1AAF4DF10D36215E09E4EEFD70E340C2E4DECF38 |
| 174 | | |
| 175 | | Issued to: GlobalSign ObjectSign CA |
| 176 | | Issued by: GlobalSign Primary Object Publishing CA |
| 177 | | Expires: Fri Jan 27 11:00:00 2017 |
| 178 | | SHA1 hash: B859853EF366AC9335763C340A87BD208113055F |
| 179 | | |
| 180 | | Issued to: Akeo Consulting |
| 181 | | Issued by: GlobalSign ObjectSign CA |
| 182 | | Expires: Sun Jun 26 10:05:35 2011 |
| 183 | | SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8 |
| 184 | | |
| 185 | | Successfully verified: libusb0.sys |
| 186 | | |
| 187 | | Number of files successfully Verified: 1 |
| 188 | | Number of warnings: 0 |
| 189 | | Number of errors: 0 |
| 190 | | }}} |
| 191 | | |
| 192 | | == Creating a signed cat file == |
| 193 | | |
| 194 | | '''Why would you want a signed cat?''' |
| 195 | | |
| 196 | | 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: |
| 197 | | |
| 198 | | [[Image(libwdi/zadig:zadig_05.png)]] |
| 199 | | |
| 200 | | 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) |
| 201 | | The other solution is to use your driver signing credentials to sign the inf, and create a cat file. |
| 202 | | |
| 203 | | 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: |
| 204 | | 1. they previously checked "Always trust software from company X" when previously prompted with a similar query |
| 205 | | 1. you installed your certificate in the Trusted Publisher system store |
| 206 | | 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. |
| 207 | | |
| 208 | | '''Signing a cat file''' |
| 209 | | |
| 210 | | 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. |
| 211 | | 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: |
| 212 | | {{{ |
| 213 | | CatalogFile = "libusb-win32_ft2232_driver.cat" |
| 214 | | }}} |
| 215 | | Then, you can simply run: |
| 216 | | {{{ |
| 217 | | D:libusb-win32_ft2232_driver-101028>inf2cat /v /driver:. /os:XP_X86,XP_X64,Vista_X86,Vista_X64,7_X86,7_X64 |
| 218 | | Processing directory (D:libusb-win32_ft2232_driver-101028) file (info.txt) |
| 219 | | Processing directory (D:libusb-win32_ft2232_driver-101028) file (libusb-win32_ft2232_driver.inf) |
| 220 | | Processing directory (D:libusb-win32_ft2232_driver-101028amd64) file (libusb0.dll) |
| 221 | | Processing directory (D:libusb-win32_ft2232_driver-101028amd64) file (libusb0.sys) |
| 222 | | Processing directory (D:libusb-win32_ft2232_driver-101028x86) file (libusb0.sys) |
| 223 | | Processing directory (D:libusb-win32_ft2232_driver-101028x86) file (libusb0_x86.dll) |
| 224 | | Parsing INF: D:libusb-win32_ft2232_driver-101028libusb-win32_ft2232_driver.inf |
| 225 | | Finished parsing INFs |
| 226 | | Processing INF: D:libusb-win32_ft2232_driver-101028libusb-win32_ft2232_driver.inf |
| 227 | | Finished processing INFs |
| 228 | | Testing driver package... |
| 229 | | Testing driver package... |
| 230 | | Testing driver package... |
| 231 | | Testing driver package... |
| 232 | | Testing driver package... |
| 233 | | Testing driver package... |
| 234 | | Testing driver package... |
| 235 | | Testing driver package... |
| 236 | | Testing driver package... |
| 237 | | Testing driver package... |
| 238 | | Testing driver package... |
| 239 | | Testing driver package... |
| 240 | | Testing driver package... |
| 241 | | Testing driver package... |
| 242 | | |
| 243 | | Signability test complete. |
| 244 | | |
| 245 | | Errors: |
| 246 | | None |
| 247 | | |
| 248 | | Warnings: |
| 249 | | None |
| 250 | | |
| 251 | | Catalog generation complete. |
| 252 | | }}} |
| 253 | | |
| 254 | | After that, you would sign the generated .cat as follows: |
| 255 | | {{{ |
| 256 | | 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 |
| 257 | | The following certificate was selected: |
| 258 | | Issued to: Akeo Consulting |
| 259 | | Issued by: GlobalSign ObjectSign CA |
| 260 | | Expires: Sun Jun 26 10:05:35 2011 |
| 261 | | SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8 |
| 262 | | |
| 263 | | Cross certificate chain (using machine store): |
| 264 | | Issued to: Microsoft Code Verification Root |
| 265 | | Issued by: Microsoft Code Verification Root |
| 266 | | Expires: Sat Nov 01 13:54:03 2025 |
| 267 | | SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3 |
| 268 | | |
| 269 | | Issued to: GlobalSign Root CA |
| 270 | | Issued by: Microsoft Code Verification Root |
| 271 | | Expires: Mon May 23 17:10:51 2016 |
| 272 | | SHA1 hash: 3EEB2750A199F5E7B6A8952430BE5062FE04E9E5 |
| 273 | | |
| 274 | | Issued to: GlobalSign Primary Object Publishing CA |
| 275 | | Issued by: GlobalSign Root CA |
| 276 | | Expires: Fri Jan 27 12:00:00 2017 |
| 277 | | SHA1 hash: 1AAF4DF10D36215E09E4EEFD70E340C2E4DECF38 |
| 278 | | |
| 279 | | Issued to: GlobalSign ObjectSign CA |
| 280 | | Issued by: GlobalSign Primary Object Publishing CA |
| 281 | | Expires: Fri Jan 27 11:00:00 2017 |
| 282 | | SHA1 hash: B859853EF366AC9335763C340A87BD208113055F |
| 283 | | |
| 284 | | Issued to: Akeo Consulting |
| 285 | | Issued by: GlobalSign ObjectSign CA |
| 286 | | Expires: Sun Jun 26 10:05:35 2011 |
| 287 | | SHA1 hash: 0BF5319EE093F9234D8504527D63CFAFEADEECF8 |
| 288 | | |
| 289 | | Done Adding Additional Store |
| 290 | | Successfully signed and timestamped: libusb-win32_ft2232_driver.cat |
| 291 | | |
| 292 | | Number of files successfully Signed: 1 |
| 293 | | Number of warnings: 0 |
| 294 | | Number of errors: 0 |
| 295 | | }}} |
| 296 | | |
| 297 | | == Packaging the signed files in libwdi == |
| 298 | | |
| 299 | | 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. |
| 300 | | |
| 301 | | == Installing the certificate as a Trusted Publisher using libwdi == |
| 302 | | |
| 303 | | == Testing the installation == |
| 304 | | |
| 305 | | == Links == |
| 306 | | |
| 307 | | * [http://www.microsoft.com/whdc/driver/install/drvsign/kmcs-walkthrough.mspx Microsoft's Kernel-Mode Code Signing Walkthrough] (in Microsoft Office 2007 .docx format) |
| 308 | | * [http://www.globalsign.com/support/code-signing/codesign_vista64.php GlobalSign's code signing page] |
| 309 | | |
| 310 | | |