Tag Archives: installer

Kernel driver code signing with the VeriSign Class 3 Primary CA – G5 certificate

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.

Understanding some of the mysteries of launchd

Have you ever wondered how Mac OS X knows which file type belongs to which application? On Windows there is the registry. An installer writes the necessary info into it. Most applications on Mac OS X doesn’t come with an installer, they are just moved from the downloaded DMG file to the /Applications folder. So a developer doesn’t have the ability to take action when the user “install” the application. Anyway there is no need to provide an installer for just this task, cause Mac OS X register file type associations on the first start of the application. In the following post, I will show how to do this, but furthermore I will show where this information is stored and how it could be reseted.

Providing the necessary information to Mac OS X

Applications on Mac OS X need some defined structure. They are so-called bundles, which means on the filesystem layer they are directories. You can prove this by checking the Applications directory within the Terminal.app. You could also right-click on an application and select “Show Package Contents”. The content of the bundle directory is usually hidden from the user when he works with the Finder or any other high level function of Mac OS X (like the open dialog). Additional to this layout on the filesystem, an application provide information about itself to the system with a plist file. This file has to be named Application.app/Content/Info.plist. The following shows exemplary the content of the Tunnelblick application:

<xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>CFBundleDevelopmentRegion</key>     <string>English</string>
 <key>CFBundleExecutable</key>            <string>Tunnelblick</string>
 <key>CFBundleIconFile</key>              <string>tunnelblick.icns</string>
 <key>CFBundleIdentifier</key>            <string>com.openvpn.tunnelblick</string>
 <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string>
 <key>CFBundlePackageType</key>           <string>APPL</string>
 <key>CFBundleShortVersionString</key>    <string>3.1beta20 (build 2132)</string>
 <key>CFBundleSignature</key>             <string>OVPN</string>
 <key>CFBundleVersion</key>               <string>2132</string>
 <key>NSMainNibFile</key>                 <string>MainMenu</string>
 <key>NSPrincipalClass</key>              <string>NSApplication</string>
 <key>NSUIElement</key>                   <string>1</string>
 <key>SUEnableSystemProfiling</key>       <true/>
 <key>SUFeedURL</key>                     <string>http://tunnelblick.net/appcast.rss</string>
 <key>SUPublicDSAKeyFile</key>            <string>dsa_pub.pem</string>
</dict>
</plist>

The keys are mostly self explaining, you can find a full list here.

To register a file type association you have to add an array of the type CFBundleDocumentTypes. Again, here is an extraction of the Tunnelblick application, which shows the registration of the tblk extension:

 <key>CFBundleDocumentTypes</key>
 <array>
  <dict>
   <key>CFBundleTypeExtensions</key>   <array><string>tblk</string></array>
   <key>CFBundleTypeIconFile</key>     <string>tunnelblick_package.icns</string>
   <key>CFBundleTypeName</key>         <string>Tunnelblick VPN Configuration</string>
   <key>CFBundleTypeRole</key>         <string>Editor</string>
   <key>LSTypeIsPackage</key>          <true/>
   <key>NSPersistentStoreTypeKey</key> <string>Binary</string>
  </dict>
 </array>

You have to provide a file extension or mime-type, can add an icon and give a hint what your application can do with this type of file (viewer, editor or nothing).

Beside this passive way of announcing this information, there is also an active way (e.g. for use in an installer). See here for further information.

Where is this information stored

Although Mac OS X hasn’t a registry like windows, some information are stored in global databases, too. Applications are registered at the launchd. The launchd is the central place for starting all kind of programs, from a background service to any common application, like Thunderbird. E.g. background services can register itself and even made their start depending on different events. VirtualBox has an example configuration included, which let launchd start the vbox webservice on activity on a certain port. Although this isn’t used by many users out there (and therefore disabled by default), it shows some generic usage of this functionality.

If you look around in Mac OS X you have the tool launchctl, which allows you to start jobs or register background services with launchd. But it seems there is no tool which is able to get some information about the knowledge of launchd. Well, there is one. It’s a little bit hidden in /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister. To be more comfortable with it, we should include it into the user path by linking it to a known path, like this:

sudo ln -s /Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister /usr/local/bin/lsregister

With this tiny tool we are able to dump the launchd database. lsregister -dump | grep -n10 Tunnelblick displays something like this for Tunnelblick:

10823---------------------------------------------------------------------------------
10824-bundle    id:            6984
10825:  path:          /Applications/Tunnelblick.app
10826-  name:
10827-  identifier:    com.openvpn.tunnelblick (0x800097b8)
10828-  version:       2132
10829-  mod date:      10/31/2010 12:37:08
10830-  reg date:      11/19/2010 11:13:39
10831-  type code:     'APPL'
10832-  creator code:  'OVPN'
10833-  sys version:   0
10834-  flags:         relative-icon-path  ui-element
10835-  item flags:    container  package  application  extension-hidden  native-app  ppc  i386
10836-  icon:          Contents/Resources/tunnelblick.icns
10837:  executable:    Contents/MacOS/Tunnelblick
10838-  inode:         3800129
10839-  exec inode:    3800213
10840-  container id:  32
10841-  library:
10842-  library items:
10843-  --------------------------------------------------------
10844-  claim   id:            17864
10845:          name:          Tunnelblick VPN Configuration
10846-          rank:          Default
10847-          roles:         Editor
10848-          flags:         relative-icon-path  package
10849-          icon:          Contents/Resources/tunnelblick_package.icns
10850-          bindings:      .tblk
10851---------------------------------------------------------------------------------

As you see, all the information provided by the plist file is registered. Beside other information, it also has the registration and modification times stored. To let launchd reread the plist file, usual its only necessary to change the modification time of the application. This could be done by simply executing touch /Applications/Application.app. Anyway, it’s sometimes necessary to reset the content of this database for the own application. This could be done by executing the following:

lsregister -u /Applications/Application.app

To register the application again, just remove the -u parameter. You should also check if your application isn’t registered more than once, with different paths, by using the -dump parameter. To fully reset the launchd database, you could use -kill. This will remove any file type association and registered application. You have been warned.

Conclusion

This article shows how Mac OS X handle informations about installed applications. With this knowledge a developer is able to register the own application into the launchd ecosystem and see how launchd interpret this information. Furthermore, the usage of lsregister allows a developer to analyze the content of the launchd database and make changes to it.