Since the first 64-bit version of Windows Vista it is necessary to digital sign any kernel mode driver. Without a proper code signing the driver isn’t loaded by the system. Although it is also possible to sign drivers and applications for the 32-bit versions of Windows (as far as I know starting with Windows XP) it became mandatory in the 64-bit versions for any kernel mode driver. A serious software provider always sign its own software to make sure the user can rely on the authenticity of the package he e.g. downloaded from the Internet. It also prevent a question about installing a driver from an untrusted source which could be denied by the user and therefore makes the own software unusable. In any case the user has to confirm an installation of a driver, even if this driver is correctly signed, if the driver isn’t Windows Hardware Quality Labs (WHQL) certificated. In the following post I will not explain the basics of how to sign Windows drivers, there are many articles out there like the one from Microsoft itself, but I will look at changes which have to be made to correctly code sign drivers with a certificate signed by the VeriSign Class 3 Primary CA – G5 root certificate, which is in use by the end of 2010.
Chain of trust
To ensure the validity of every component in a computer system (hardware or software) a chain of trust is build. This basically means there is some root institution (in computer cryptography this is called Certificate Authority (CA)) which is trusted per se. Any following part in this hierarchy is signed by the parent authority. This allows a flexible mechanism where only the connected parties have to make sure they trust each other to make the full chain trustworthy. This concept is also used for code signing, cause it allows to be trustworthy in the eyes of Microsoft without ever being in touch with them. As Microsoft don’t trust (for code signing) every root CA they have in their certificate store, they explicit allow only a handful of root CA’s to be in this trust of chain. They archive this by cross signing root CA’s with their own CA. The full concept is described in this article. It basically means the software maker certificate has to be trusted by an official CA included in every Windows version and this root CA has to be cross signed by Microsoft for code signing. This is the point where the problems start with the new VeriSign Primary CA.
Finding the little differences
The old code signing CA is the VeriSign Class 3 Public Primary CA, available since 1996. This certificate uses an 1024 bit key, which isn’t considered save anymore in the future. Therefor VeriSign decided to replace this root CA with a stronger one, which uses an 2048 bit key. If you simply replace an old software maker certificate (signed with the old root CA) with one which is signed by the new CA you get a surprise. Installing a kernel mode driver signed with the new certificate ends up with a message like this:
A look into the security log of the event viewer shows this error message:
Code integrity determined that the image hash of a file is not valid. The file could be corrupt due to unauthorized modification or the invalid hash could indicate a potential disk device error.
To be honest: This information doesn’t contain any useful hint. If you compare the old signed driver with the new signed driver you will not see any difference. Both could be successful verified as shown next:
Even if you compare all the sub-dialogs side by side you will not find any difference, beside the different root CA of course. So whats the difference? Well, you can’t rely on the graphical representation of this trust of chain. When you invoke the signtool
of the Windows Driver Kit (WDK) with the verify
option, you will see the difference:
C:Program FilesOracleVirtualBox_Sun>signtool.exe verify /v /kp drivers/vboxdrv/VBoxDrv.sys Verifying: drivers/vboxdrv/VBoxDrv.sys SHA1 hash of file: 9E58611C764D5AE04140E4CC7782B3229D1BCB8A Signing Certificate Chain: Issued to: Microsoft Code Verification Root Issued by: Microsoft Code Verification Root Expires: 01.11.2025 14:54:03 SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3 Issued to: Class 3 Public Primary Certification Authority Issued by: Microsoft Code Verification Root Expires: 23.05.2016 18:11:29 SHA1 hash: 58455389CF1D0CD6A08E3CE216F65ADFF7A86408 Issued to: VeriSign Class 3 Code Signing 2004 CA Issued by: Class 3 Public Primary Certification Authority Expires: 16.07.2014 00:59:59 SHA1 hash: 197A4AEBDB25F0170079BB8C73CB2D655E0018A4 Issued to: Sun Microsystems, Inc. Issued by: VeriSign Class 3 Code Signing 2004 CA Expires: 12.06.2011 00:59:59 SHA1 hash: 1D4458051589B47A06260125F6EC6BBB6C24472E The signature is timestamped: 08.02.2011 00:23:54 Timestamp Verified by: Issued to: Thawte Timestamping CA Issued by: Thawte Timestamping CA Expires: 01.01.2021 00:59:59 SHA1 hash: BE36A4562FB2EE05DBB3D32323ADF445084ED656 Issued to: VeriSign Time Stamping Services CA Issued by: Thawte Timestamping CA Expires: 04.12.2013 00:59:59 SHA1 hash: F46AC0C6EFBB8C6A14F55F09E2D37DF4C0DE012D Issued to: VeriSign Time Stamping Services Signer - G2 Issued by: VeriSign Time Stamping Services CA Expires: 15.06.2012 00:59:59 SHA1 hash: ADA8AAA643FF7DC38DD40FA4C97AD559FF4846DE Successfully verified: drivers/vboxdrv/VBoxDrv.sys Number of files successfully Verified: 1 Number of warnings: 0 Number of errors: 0 C:Program FilesOracleVirtualBox_Sun>
and
C:Program FilesOracleVirtualBox_Oracle_Wrong>signtool.exe verify /v /kp drivers/vboxdrv/VBoxDrv.sys Verifying: drivers/vboxdrv/VBoxDrv.sys SHA1 hash of file: F398B7124B0A8C32DBFB262343AC1180807505D0 Signing Certificate Chain: Issued to: VeriSign Class 3 Public Primary Certification Authority - G5 Issued by: VeriSign Class 3 Public Primary Certification Authority - G5 Expires: 17.07.2036 00:59:59 SHA1 hash: 4EB6D578499B1CCF5F581EAD56BE3D9B6744A5E5 Issued to: VeriSign Class 3 Code Signing 2010 CA Issued by: VeriSign Class 3 Public Primary Certification Authority - G5 Expires: 08.02.2020 00:59:59 SHA1 hash: 495847A93187CFB8C71F840CB7B41497AD95C64F Issued to: Oracle Corporation Issued by: VeriSign Class 3 Code Signing 2010 CA Expires: 08.02.2014 00:59:59 SHA1 hash: A88FD9BDAA06BC0F3C491BA51E231BE35F8D1AD5 The signature is timestamped: 10.02.2011 09:30:08 Timestamp Verified by: Issued to: Thawte Timestamping CA Issued by: Thawte Timestamping CA Expires: 01.01.2021 00:59:59 SHA1 hash: BE36A4562FB2EE05DBB3D32323ADF445084ED656 Issued to: VeriSign Time Stamping Services CA Issued by: Thawte Timestamping CA Expires: 04.12.2013 00:59:59 SHA1 hash: F46AC0C6EFBB8C6A14F55F09E2D37DF4C0DE012D Issued to: VeriSign Time Stamping Services Signer - G2 Issued by: VeriSign Time Stamping Services CA Expires: 15.06.2012 00:59:59 SHA1 hash: ADA8AAA643FF7DC38DD40FA4C97AD559FF4846DE Successfully verified: drivers/vboxdrv/VBoxDrv.sys Number of files successfully Verified: 1 Number of warnings: 0 Number of errors: 0 C:Program FilesOracleVirtualBox_Oracle_Wrong>
As you can see, the chain of trust of the old certificate contains the Microsoft Code Verification Root, the new signed driver not. As Microsoft released the cross certificate somewhere in 2006, it makes sense that the new VeriSign certificate isn’t signed by them. So first of all, we have to blame the signtool
for silently ignoring a cross certificate which, obviously, doesn’t trust the root certificate. When you have this information you can search for additional information and probably find an advisory of VeriSign. There you learn you need intermediate certificates for the new root CA.
Installing the right certificates on the build machine
The rest is easy. The certificate store of any Windows installation contains the new VeriSign Root CA as shown here:
Delete this root CA and replace it by the intermediate certificates you fetched from the website shown above. Just place the certificate in a text file, add the extension .der
and double-click to install it. Make sure to replace really all versions of this certificate, even the one in the global store. When you now sign your driver with your new certificate the Microsoft Code Verification Root is in the trust of chain, as shown in the following:
C:Program FilesOracleVirtualBox_Oracle_Correct>signtool.exe verify /v /kp drivers/vboxdrv/VBoxDrv.sys Verifying: drivers/vboxdrv/VBoxDrv.sys SHA1 hash of file: 201B7F97473D7F015A104D7841371C5AE4F22FF2 Signing Certificate Chain: Issued to: Microsoft Code Verification Root Issued by: Microsoft Code Verification Root Expires: 01.11.2025 14:54:03 SHA1 hash: 8FBE4D070EF8AB1BCCAF2A9D5CCAE7282A2C66B3 Issued to: Class 3 Public Primary Certification Authority Issued by: Microsoft Code Verification Root Expires: 23.05.2016 18:11:29 SHA1 hash: 58455389CF1D0CD6A08E3CE216F65ADFF7A86408 Issued to: VeriSign Class 3 Public Primary Certification Authority - G5 Issued by: Class 3 Public Primary Certification Authority Expires: 08.11.2021 00:59:59 SHA1 hash: 32F30882622B87CF8856C63DB873DF0853B4DD27 Issued to: VeriSign Class 3 Code Signing 2010 CA Issued by: VeriSign Class 3 Public Primary Certification Authority - G5 Expires: 08.02.2020 00:59:59 SHA1 hash: 495847A93187CFB8C71F840CB7B41497AD95C64F Issued to: Oracle Corporation Issued by: VeriSign Class 3 Code Signing 2010 CA Expires: 08.02.2014 00:59:59 SHA1 hash: A88FD9BDAA06BC0F3C491BA51E231BE35F8D1AD5 The signature is timestamped: 10.02.2011 15:03:30 Timestamp Verified by: Issued to: Thawte Timestamping CA Issued by: Thawte Timestamping CA Expires: 01.01.2021 00:59:59 SHA1 hash: BE36A4562FB2EE05DBB3D32323ADF445084ED656 Issued to: VeriSign Time Stamping Services CA Issued by: Thawte Timestamping CA Expires: 04.12.2013 00:59:59 SHA1 hash: F46AC0C6EFBB8C6A14F55F09E2D37DF4C0DE012D Issued to: VeriSign Time Stamping Services Signer - G2 Issued by: VeriSign Time Stamping Services CA Expires: 15.06.2012 00:59:59 SHA1 hash: ADA8AAA643FF7DC38DD40FA4C97AD559FF4846DE Successfully verified: drivers/vboxdrv/VBoxDrv.sys Number of files successfully Verified: 1 Number of warnings: 0 Number of errors: 0 C:Program FilesOracleVirtualBox_Oracle_Correct>
You see the old certificate (which is trusted by Microsoft) is the parent of the new certificate, which completes the trust of chain again. I guess this is only some temporary solution as long as Microsoft doesn’t release a new cross certificate (that’s why it is called intermediate). Luckily, you only need the intermediate certificates on the build machine. For your end users nothing has to be changed.
Conclusion
This article shows how a service provider make an easy task hard to do. Signing a kernel mode driver with the new certificate isn’t hard, but finding the right information is. Although there is an advisory from VeriSign, it doesn’t really explain what to do. As I believe in the future many other people will be in the same situation, I hope this article will save them from some sleepless nights.