[[TOC(inline, depth=1)]] = Introduction = Generic build instructions for tap-windows6 [https://github.com/OpenVPN/tap-windows6/blob/master/README.rst are available] in it's Git repo. This page contains additional information that is more generic and not really suitable for inclusion in the main documentation. = Generic requirements = Getting the [https://msdn.microsoft.com/en-us/library/windows/hardware/ff686697%28v=vs.85%29.aspx Authenticode signatures] right so that all Windows versions detect them can be quite tricky. This seems to be particularly true for kernel-mode driver packages. The Authenticode signatures have a few requirements: 1. The Certificate path needs to be complete. This can be achieved by including [https://msdn.microsoft.com/en-us/library/windows/hardware/dn170454%28v=vs.85%29.aspx cross-certificate of your CA] (e.g. Digicert) in the signed files. At least for Digicert non-EV and EV code-signing certificates have different CAs. 1. The signature needs to be timestamped, or the driver will stop functioning when the code-signing certificate expires. It is not clear if signtool's digest algorithm (/fd SHA|SHA256) affects the acceptability of the signature in Windows 7 and beyond, or if the only important thing is the hash algorithm of the actual certificate. Cross-signing is possible for Windows 7/8/8.1/Server 2012r2 as long as the certification authority's cross-certificate is valid. Beyond that point an actual Microsoft signature is required in all drivers. Windows 10 already requires these Microsoft signatures - they're called [https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/attestation-signing-a-kernel-driver-for-public-release attestation signatures] in MS jargon. These signatures can be created in [https://developer.microsoft.com/en-us/windows Windows Dev Center] once you've cleared all the bureaucratic obstacles like signing in to development programs and registering your EV hardware token with your account. Here are the general prequisites for building and signing, regardless of signature type: * On build computer * [https://github.com/OpenVPN/tap-windows6 tap-windows6] source directory is up-to-date * [https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/using-the-enterprise-wdk Enterprise Windows Drive Kit] ISO image is installed and mounted as a system drive * tap-windows6 build system is configured properly (file paths etc.) * Clone [https://github.com/Microsoft/Windows-driver-samples/ Windows-driver-samples] under the tap-windows6 directory * Clone [https://github.com/mattock/sign-tap6 sign-tap6] under the tap-windows6 directory * On signing computer * An EV token is visible in the Windows Certificate Store * [https://github.com/mattock/sign-tap6 Sign-Tap6] source directory is up-to-date * A correct cross-certificate from your CA is installed into the sign-tap6 directory * Sign-Tap6 is configured properly (see Sign-Tap6.conf.ps1) * Optionally relax the [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy Powershell execution policy] to remove some extra warnings when signing * Your workstation * You are able to transfer files (e.g. via SSH) from and to the build and signing computers In the documentation below it is assumed that all Windows commands are executed from within a Powershell session. = Modifying the Visual Studio project file = Many tap-windows6 build settings come from the Visual studio project file, src\tap-windows6.vcxproj. That file is generated by buildtap.py from src\tap-windows6.vcxproj.in. There does not seem to be any easily available reference for vcxproj files. This means that the safest and possibly the only realistic way to modify them is by using Visual Studio itself. The Visual Studio + WDK installation process is fairly well documented [https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk here], but for sake of completeness the requirements are: * Visual Studio 2019 Community * Install workload "Desktop Development with C++" * Install component "Windows 10 SDK" * Windows Driver Kit (WDK) * Version must match that of "Windows 10 SDK" * Copy of tap-windows6.vcxproj under src * This file can be generated elsewhere with buildtap.py and copied over to the Visual Studio computer After you've installed the above components launch Visual Studio 2019 and open tap-windows6.vcxproj file. Then you can modify the project properties as you want using the GUI. Your changes will not affect tap-windows6.vcxproj, but will create a new file called tap-windows6.vcxproj.user. Its contents look something like this: {{{ TestSign Off }}} Once you've figured out what the GUI does you can port those changes to tap-windows6.vcxproj.in and they will get applied to all subsequent builds. = Setting up the SMB share = If the building and signing computers are separate you are ''strongly encouraged'' to share the build directory on the build computer with the signing computer, e.g. using SMB); this removes the need for doing error-prone file copying, archive extraction, etc. In the instructions below it is assumed that this is the case. You can create new shares on the build computer in various ways. Here's an example on how to do it with Puppet using Powershell DSC resources: {{{ dsc_windowsfeature { 'File server': dsc_ensure => 'present', dsc_name => 'FS-FileServer', } dsc_xsmbshare { 'tap-windows6-build-directory': dsc_ensure => 'present', dsc_name => 'tap6build', dsc_description => 'tap-windows6 build directory', dsc_path => 'C:\\Users\\build\\opt\\tap-windows6', dsc_folderenumerationmode => 'AccessBased', dsc_fullaccess => 'tapbuilder\build', } }}} This code can be mapped almost 1:1 to Powershell DSC. Alternatively you can use raw Powershell commands [https://ss64.com/ps/add-windowsfeature.html Add-Windowsfeature] and [https://docs.microsoft.com/en-us/powershell/module/smbshare/new-smbshare?view=win10-ps New-Smbshare] to do the same. Or just create the share via Windows GUI somehow. Remember to open port 445 in the firewall. Once the share is up, mount it on a Powershell session: {{{ $ net use W: \\tapbuilder.example.org\tap6build /user:build 'password-here' }}} Note that this mount is session-specific, so you need to do it from the session you use to sign the files from. = Building an unsigned driver and tapinstall.exe = Regardless of the signature type you need to build unsigned tap-windows6 driver first: '''On build computer''' {{{ $ cd tap-windows6 $ python.exe buildtap.py -c -b --ti=Windows-driver-samples\setup\devcon }}} = Building for Windows Vista = **NOTE:** It is generally a bad idea to support Windows Vista. But if you must, please look [wiki:SigningForWindowsVista here]. = Building and signing for Windows 7/8/8.1/Server 2012r2 = Any relatively recent Windows 7 installation supports SHA2 Authenticode signatures. This means that the laborious and fragile [wiki:SigningForWindowsVista dual-signature process] can be avoided. You only need the EV SHA2 kernel-mode code-signing certificate, which probably comes in the form of a dongle that integrates with Windows certificate store. The tap-windows6 ''installer'' may optionally signed with a different, non-EV SHA2 code-signing certificate. '''On build computer''' Build an unsigned driver (see above) '''On signing computer''' Sign the build files using the EV token: {{{ $ cd W:\tap-windows6\sign-tap6 $ .\Sign-Tap6.ps1 -SourceDir ..\dist -Force }}} If tap-windows6 build directory is shared via SMB you will get warnings about running scripts from the Internet. Unfortunately it is not possible to make this problem go away, even with the [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/unblock-file?view=powershell-6 Unblock-File] CmdLet when working with SMB shares, unless you modify the global Powershell execution policy with [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy Set-ExecutionPolicy] CmdLet. Once you're past the script warnings the EV dongle will probably prompt you twice per architecture (x86, x64, arm64) as it signs the catalog file and tapinstall.exe for each. Note that the -Force switch ''is required'' or the file hashes in the .cat files will be incorrect and the driver will not install. '''On build computer''' Package the signed files: {{{ $ cd tap-windows6 $ python.exe buildtap.py -p --ti=Windows-driver-samples\setup\devcon $ cd sign-tap6 $ .\Sign-File -SourceFile ..\ }}} '''On signing computer''' Sign the installer: {{{ $ ... }}} = Building and signing for Windows 10 = On top of the generic requirements listed above there are a few extra requirements when doing attestation signing: * You need to register your EV dongle with your organization's account in the Windows Dev Center ([https://developer.microsoft.com/en-us/dashboard/account/managecertificates direct link]). * INF file syntax needs to be valid, as MS backend servers will check it at submission time. Use the latest version of !InfVerif (see footer in Hardware Dev Center) to validate the syntax before submission. The building and signing process is as follows '''On build computer''' Build an unsigned driver (see above) '''On workstation''' Copy the tap6.tar.gz from the build computer to the signing computer. '''On signing computer''' {{{ $ cd sign-tap6 $ tar -zxf tap6.tar.gz }}} Next you need to create three DDF files, one for each architecture (x86, x64, arm64), which are used to create the cabined files. Here's an example for amd64: {{{ ; tap-windows6-amd64.ddf ; .OPTION EXPLICIT ; Generate errors .Set CabinetFileCountThreshold=0 .Set FolderFileCountThreshold=0 .Set FolderSizeThreshold=0 .Set MaxCabinetSize=0 .Set MaxDiskFileCount=0 .Set MaxDiskSize=0 .Set CompressionType=MSZIP .Set Cabinet=on .Set Compress=on ;Specify file name for new cab file .Set CabinetNameTemplate=tap-windows6-amd64.cab ;Specify files to be included in cab file .Set DestinationDir=amd64 C:\users\sign\opt\sign-tap6\tap6\amd64\tap0901.sys C:\users\sign\opt\sign-tap6\tap6\amd64\OemVista.inf }}} Generate the cabinet file: {{{ makecab.exe /f "C:\Users\sign\opt\sign-tap6\tap-windows6-amd64.ddf" }}} This puts the cabinet file to a subdirectory called "disk1". Then sign the cabinet file, adapting the parameters as needed: {{{ SignTool sign /ac "C:\Users\sign\opt\sign-tap6\digicert-high-assurance-ev.crt" /s MY /n "OpenVPN" /fd sha256 /tr http://timestamp.digicert.com /td sha256 /v "C:\Users\sign\opt\sign-tap6\disk1\tap-windows6-amd64.cab" }}} For other platforms just replace "amd64" with "i386" or "arm64". After this process you have three signed cabined files. Now submit each one individually to Windows Dev Center for attestation signing. Make sure to check only the applicable platforms in the "Requested signatures" section. If all goes well, you can click "More" at the right of your submission below "Package and signing properties" and download a ZIP file with signed driver files. Once you have the signed driver files you may want to wrap them into an installer. For more generic instructions and more details please refer to the [https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/attestation-signing-a-kernel-driver-for-public-release official MS documentation] on attestation signing. = Useful commands = == Installing certificates == Installing a PFX file to the Currentuser certificate store using Powershell: {{{ Import-PfxCertificate –FilePath cert:\CurrentUser\My -Password (ConvertTo-SecureString -String -Force –AsPlainText) }}} If you're not accustomed to Powershell you can just use ''mmc.exe'' and the certificate snap-ins to install the certificate. == Querying the certificate store == To list all certificates in ''Currentuser\My'' store using Powershell: {{{ Get-ChildItem cert:\CurrentUser\My }}} Or alternatively: {{{ Set-Location cert:\CurrentUser\My dir }}} The ''dir'' command is just an alias for ''Get-!ChildItem'' == Creating catalog files with inf2cat == To create a catalog file for a 32-bit driver: {{{ Inf2Cat.exe /driver: /os:Vista_x86,Server2008_X86,7_X86 }}} To create a catalog file for a 64-bit driver: {{{ Inf2Cat.exe /driver: /os:Vista_X64,Server2008_X64,Server2008R2_X64,7_X64 }}} Example: {{{ Inf2Cat.exe /driver:C:\Users\John\tap6\amd64 /os:Vista_X64,Server2008_X64,Server2008R2_X64,7_X64 }}} '''NOTE:''' According to Microsoft Inf2Cat requires a full path to the driver directory. == Signing files with signtool.exe == '''NOTE:''' signtool seems to expect absoluete paths to certificate files. Below only the filenames are given for clarity. Sign a file using a (non-EV) certificate stored in a pfx file. Note that this process is not suitable for EV certificates, which are probably all stored in some sort of dongle and thus only visible through the Windows Certificate Store: {{{ signtool.exe sign /v /ac /t /f /p }}} Sign a driver with the "best" certificate found from the certificate store. This should work if there is only code-signing certificate in the store: {{{ signtool.exe sign /v /ac /t /a }}} Sign a driver using a certificate under ''Currentuser\My'', selecting the right certificate based on a substring of the certificate's subjectname: {{{ signtool.exe sign /v /ac /t /s My /n }}} Example of adding two signatures and timestamps. This requires a relatively recent signtool.exe (e.g. from Windows Kit 10): {{{ # Create primary (SHA1) signature (certificate in a pfx file) signtool.exe sign /v /f digicert-sha1.pfx /p /ac digicert-assured-id.crt /t http://timestamp.digicert.com /fd SHA1 tap6/amd64/tap0901.cat # Add secondary (SHA2) signature (certificate in the certificate store) signtool.exe sign /v /s My /n OpenVPN /ac digicert-high-assurance-ev.crt /as /fd SHA256 tap6/amd64/tap0901.cat signtool.exe timestamp /tr http://timestamp.digicert.com /td SHA256 /tp 1 tap6/amd64/tap0901.cat }}} Signing a file (e.g. the installer) directly with Signtool using a certificate from local PFX file. {{{ signtool.exe sign /v /ac digicert-assured-id.crt /f digicert-user-mode-2019.pfx /p password /t http://timestamp.digicert.com tap-windows-9.22.1-I601.exe }}} == Validating signatures == Verifying the Authenticode signature of a file using Powershell: {{{ Get-AuthenticodeSignature }}} Note that even if the above command says that the file's certificate is valid, there is absolutely no guarantee that various Windows versions will accept it. It is unclear whether the Cmdlet checks the entire certificate path or not: it does hang for long periods of time occasionally doing ''something''. Using signtool.exe to verify a driver's signature probably gives more reliable results than the Get-!AuthenticodeSignature Cmdlet: {{{ signtool.exe verify /v /kp /c .cat .sys }}} Signatures can also be validated by looking at "File properties" of the ''tap0901.cat'' file. The publisher should show up correctly in some places (not necessarily all), there should be a timestamp counter-certificate, and an unbroken certification path should be present. = External links = '''General information''' * [http://www.osr.com/blog/2015/07/24/questions-answers-windows-10-driver-signing/ Questions and Answers: Windows 10 Driver Signing] * [https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/attestation-signing-a-kernel-driver-for-public-release Attestation signing a kernel driver for public release] * [http://www.davidegrayson.com/signing/ Practical Windows Code and Driver Signing] * [https://msdn.microsoft.com/en-us/library/windows/hardware/ff686697%28v=vs.85%29.aspx Authenticode Digital Signatures] * [https://msdn.microsoft.com/en-us/library/windows/hardware/dn170454%28v=vs.85%29.aspx Cross-Certificates for Kernel Mode Code Signing] * [https://bugzilla.mozilla.org/show_bug.cgi?id=1079858 Bug 1079858 - Deal with deprecation of SHA1 (SHA-1) Authenticode signatures for Windows signing] (from Mozilla.org) '''Practical guides''' * [https://technet.microsoft.com/en-us/library/dd919238%28v=ws.10%29.aspx Steps for Signing a Device Driver Package] * [https://github.com/pbatard/libwdi/wiki/Signed-Driver-Walkthrough Signed Driver Walkthrough] (from libwdi project) * [http://www.microsoft.com/whdc/driver/install/drvsign/kmcs-walkthrough.mspx Microsoft's Kernel-Mode Code Signing Walkthrough] (in doc format) '''References''' * [https://msdn.microsoft.com/en-us/library/windows/hardware/ff553618%28v=vs.85%29.aspx Inf2Cat] * [https://msdn.microsoft.com/en-us/library/windows/desktop/aa387764%28v=vs.85%29.aspx Signtool] * [https://technet.microsoft.com/en-us/library/hh849805.aspx Get-AuthenticodeSignature] * [https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-authenticodesignature?view=powershell-6 Set-AuthenticodeSignature] * [https://technet.microsoft.com/en-us/library/hh848625.aspx Import-PfxCertificate]