Introduction
In 2021, Microsoft ended support for signing kernel mode device drivers with a cross-signed root certificate. This caused a failure for the Oracle Linux team to install the cross-signed internal builds of the Windows VirtIO drivers on x64 Windows systems. Three options were left to us to avoid this driver installation failure:
-
WHQL certificate This requires running Windows Hardware Lab Kit (HLK)/Windows Hardware Certification (HCK) tests. This is the route to produce drivers that can be distributed through Windows Update. Only drivers certified by WHQL can be used for production purposes or released to customers. However, this is overkill for drivers being built for internal testing.
-
Test signing This option does not require running HLK/HCK tests. However, it requires generating test certificates to be added to the Trusted Root Certification Authorities certificate store. The TESTSIGNING boot configuration needs to be enabled on each system where the drivers are installed.
-
Attestation signing This does not require HLK/HCK tests but requires drivers to be signed by an EV certificate for submissions. Attestation signing only works on Windows 10 Desktop and later versions of Windows. Drivers signed this way are trusted by Windows, but their functionality is not guaranteed.
This blog focuses on attestation signing, the approach the Oracle Linux team uses to sign device drivers for internal testing and development. Attestation signing can be done manually via Microsoft’s Partner Center for Windows Hardware website by uploading driver binaries and downloading the signed versions. This manual process doesn’t integrate well with automated build processes since it requires user interaction. So we’ve developed an open source command line utility that uses Microsoft APIs to perform the signing. In this blog, I’ll cover Microsoft attestation signing, the implementation of automatic attestation signing, and how to use the command line utility to do automatic attestation signing.
Preparation for attestation signing
Register an account
To start, the user has to register for the Microsoft Windows Hardware Developer Program, which creates an account enabling the user to submit drivers for attestation signing.
Prepare the cabinet file
The Microsoft Partner Center accepts packages generated for WHQL certification or a cabinet file. For attestation signing, the cabinet file is required. Windows provides an inbox Cabinet Maker tool, makecab.exe
, for users to pack multiple driver files into a single cabinet file. The files required for attestation signing are:
- the driver binary file(
*.sys
) - the driver installation file(
*.inf
) - the driver catalog file(
*.cat
) - a DDF file
The following is an example of a DDF file generated for the viogpudorc
driver, all these files are located in the folder C:\viogpudorc
.
;*** viogpudorc.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=viogpudorc.cab ; Specify the subdirectory for the files. ; Your cab file should not have files at the root level, ; and each driver package must be in a separate subfolder. .Set DestinationDir=viogpudorc ;Specify files to be included in cab file C:\viogpudorc\viogpudorc.inf C:\viogpudorc\viogpudorc.sys C:\viogpudorc\viogpudorc.cat
The following command needs to be run to create the cabinet file
C:\viogpudorc> MakeCab /f "C:\viogpudorc\viogpudorc.ddf"
Sign the CAB file
The CAB file needs to be signed with the EV Certificate before it is submitted for attestation signing. Otherwise, the attestation signing process will fail with the following error when the Hardware Center prepares for the signing.
Cab Signature validation failed with error: 0x800B0100
Attestation signing submission
Every submission for attestation signing requires users to submit new hardware information and configure the product name in the Partner Center. It is recommended to keep the product name unique, for example, tag the name with platform, version, or timestamp information to differentiate it from other submissions. The test-signing box should be unchecked for attestation signing. With the signed CAB file uploaded and the signature for the Windows version configured, the attestation signing request is ready for submission.
The entire attestation signing process encompasses several stages:
- Package Acceptance
- Preparation
- Scanning
- Validation
- Catalog Creation
- Sign
- Finalize
If something goes wrong at any stage, the attestation signing process throws an error and the user can download the error report to view the error code and root cause. The Complete
status means that the attestation signing has been done. All signed files are compressed into a zip file under Packages and signing properties
, users can download the signed binaries directly there.
Automatic attestation signing
Microsoft provides Hardware APIs for users to create and query attestation signing submissions for their products. Users can call the HTTP GET and POST methods to communicate with the Hardware Dev Center for product submissions.
Attestation Signing Application
The Oracle attestation signing application is implemented with Microsoft Hardware APIs. It accepts 9 command line parameters. Details of every parameter are explained in the AttestationSigning.exe
command help output:
AttestationSigning.exe Usage: AttestationSigning.exe [-c value] [-cs value] [-t value] [-pn value] [-pt value] [-a value] [-v value] [-f value] [-SignedFile value] Options: -c value ClientId, this Id is the Application ID in Azure portal. Azure Active Directory => App registrations => the application -cs value ClientSecret, please find it in the Azure portal - Azure Active Directory => App registrations => the application => Settings => Keys => add a Key -t value TenantId, please find it in the Azure portal - Azure Active Directory => Properties => Tenant ID section -pn value ProductName - double-quoted string -pt value ProductType - double-quoted string, value please refer to https://learn.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-product-data#list-of-product-types -a value architecture - x86 or x64 or ARM -v value driver version -f value The name of the file to be signed, for example, viogpudorc.cab The file for signing has to a CAB file that packs necessary driver binaries Please follow 'Create the CAB file' in the following link to generate a CAB file https://learn.microsoft.com/en-us/windows-hardware/drivers/dashboard/code-signing-attestation Note: the CAB file has to be signed by your own EV code-signing certificate, otherwise, the attestation signing may run into following error: Cab Signature validation failed with error: 0x800B0100 -sf value The name of the file signed, the file format is ZIP, for example, viogpudorc.zip
Access token
Initially, the attestation signing application requests a token from the Azure AD token issuance endpoint. With this token, the application authenticates to the secure resource of the Partner Center for further operations. This token expires in 60 minutes. This application automatically renews the token once, which extends the token validation time to two hours. Within this two-hour window, the application creates new submissions and queries the status of submissions, uploads and downloads files, etc.
Create Product
A product needs to be configured before a submission. The configuration of the product contains details about the device type, signature type, product name, etc. The options -pn
, -pt
, -a
and -v
allow users to specify the definition of the product such as product name, product type, architecture and product version. The application provides default values for all other product info, for example, the requested signature, etc. By default, this application does attestation signing for all available Windows 10 versions.
The following is an example of the response received when creating the product for the virtio-gpu
x64 driver:
{ "id": 13529589753860784, "sharedProductId": 401361760, "links": [ { "href": "https://manage.devcenter.microsoft.com/v2.0/my/hardware/products/13529589753860784", "rel": "self", "method": "GET" }, { "href": "https://manage.devcenter.microsoft.com/v2.0/my/hardware/products/13529589753860784/submissions", "rel": "get_submissions", "method": "GET" } ], "isCommitted": false, "isExtensionInf": false, "originType": "author", "sourceProductId": 0, "sourcePublisherId": 0, "isRetpolineCompiled": false, "message": "", "driverType": "desktop", "announcementDate": "2023-06-06T08:56:25.8387716-07:00", "deviceMetadataIds": [], "deviceType": "internal", "isTestSign": false, "isFlightSign": false, "marketingNames": [ "Oracle Windows VirtIO GPU Driver-x64-2.1.0" ], "productName": "Oracle Windows VirtIO GPU Driver-x64-2.1.0", "selectedProductTypes": { "Windows_v100": "Graphics Adapter WDDM1.2", "Windows_v100_RS1": "Graphics Adapter WDDM1.2", "Windows_v100_RS2": "Graphics Adapter WDDM1.2", "Windows_v100_RS3": "Graphics Adapter WDDM1.2", "Windows_v100_RS4": "Graphics Adapter WDDM1.2", "Windows_v100_RS5": "Graphics Adapter WDDM1.2", "Windows_v100_19H1": "Graphics Adapter WDDM1.2", "Windows_v100_VB": "Graphics Adapter WDDM1.2", "Windows_v100_CO": "Graphics Adapter WDDM1.2", "Windows_v100_NI": "Graphics Adapter WDDM1.2" }, "requestedSignatures": [ "WINDOWS_v100_X64_TH2_FULL", "WINDOWS_v100_X64_RS1_FULL", "WINDOWS_v100_X64_RS2_FULL", "WINDOWS_v100_X64_RS3_FULL", "WINDOWS_v100_X64_RS4_FULL", "WINDOWS_v100_X64_RS5_FULL", "WINDOWS_v100_X64_19H1_FULL", "WINDOWS_v100_X64_VB_FULL", "WINDOWS_v100_X64_CO_FULL", "WINDOWS_v100_X64_NI_FULL" ], "additionalAttributes": {}, "testHarness": "attestation" }
The id
field (13529589753860784
) in the response above is the key product reference for subsequent submission operations on the created product.
Manage submissions
The application continues to create the submission with the product ID returned by the above response. Inside the response from the creation of the submission, a URL is available and tagged as initialPackage
. This URL is the location where the cabinet file is uploaded for attestation signing. Every submission has a unique identifier, the URL ends with a string formatted as initial_
followed by the submission ID.
Both product ID and submission ID are necessary for committing a submission and querying submission status. Together these identifiers differentiate any specific submission from other submissions.
The state Completed
indicates the submission has been processed, and the binaries have been signed for attestation successfully. In such cases, the response to querying the submission provides the URL for downloading the signed binaries. The URL type is tagged as signedPackage
.
The following is an example response to a completed submission:
{ "id": 1152921505695792751, "productId": 14502174112127424, "workflowStatus": { "currentStep": "finalizeIngestion", "state": "completed", "messages": [] }, "downloads": { "items": [ { "type": "initialPackage", "url": "https://ingestionpackagesprod1.blob.core.windows.net/ingestion/41bd21b5-b17d-44bf-bde5-dae5399a6da2?sv=2018-03-28&sr=b&sig=qz9zIB8ncdWtir%2Fz5tHWQQHX6i0juMaMRxMki1pMY1w%3D&se=2023-01-18T00%3A53%3A22Z&sp=rl&rscd=attachment%3B filename%3Dinitial_1152921505695792751.cab" }, { "type": "signedPackage", "url": "https://ingestionpackagesprod1.blob.core.windows.net/ingestion/b620b311-c45e-42ee-ae82-7f1434b34855?sv=2018-03-28&sr=b&sig=9zo%2F9%2BHk%2BtNY9PC8eA6qSmSZOlqolAXTGjRqTL%2B84WE%3D&se=2023-01-18T00%3A53%3A22Z&sp=rl&rscd=attachment%3B filename%3DSigned_1152921505695792751.zip" }, { "type": "driverMetadata", "url": "https://prodingestionimage1.blob.core.windows.net/ingestion/43dd8d62-9b57-4396-98a4-bed58c8fdc7b?sv=2018-03-28&sr=b&sig=vZ2eP9u7eYLvuQdB3f1QHTf%2F41mAsT6zSXQGT38PzJ8%3D&se=2023-01-18T00%3A53%3A22Z&sp=rl&rscd=attachment%3B filename%3DdriverMetadata_1152921505695792751.json" } ], "messages": [] }, "links": [ { "href": "https://manage.devcenter.microsoft.com/v2.0/my/hardware/products/14502174112127424/submissions/1152921505695792751", "rel": "self", "method": "GET" }, { "href": "https://manage.devcenter.microsoft.com/v2.0/my/hardware/products/14502174112127424/submissions/1152921505695792751", "rel": "update_submission", "method": "PATCH" } ], "commitStatus": "commitComplete", "isExtensionInf": false, "isUniversal": true, "isDeclarativeInf": true, "isInbox": false, "isSystem": false, "name": "Oracle Windows VirtIO GPU Driver01/17/2023 16:13:10", "type": "initial" }
The signed package name is in the format of Signed_
followed by the submission ID. The attestation signing application automatically downloads the package after the signing is complete. It also provides the parameter -sf
for the user to set a preferred downloaded package name.
Check the signature
The attestation signature can be verified by the SignTool.exe
as follows:
SignTool.exe verify /pa /v viogpudorc.sys Verifying: viogpudorc.sys Hash of file (sha256): E16E2F52C9CF9D5D18876990794A57181098C88C524A52DE4C131FDD39B88506 Signing Certificate Chain: Issued to: Microsoft Root Certificate Authority 2010 Issued by: Microsoft Root Certificate Authority 2010 Expires: Sat Jun 23 17:04:01 2035 SHA1 hash: 3B1EFD3A66EA28B16697394703A72CA340A05BD5 Issued to: Microsoft Windows Third Party Component CA 2014 Issued by: Microsoft Root Certificate Authority 2010 Expires: Mon Oct 15 15:41:27 2029 SHA1 hash: 1906DCF62629B563252C826FDD874EFCEB6856C6 Issued to: Microsoft Windows Hardware Compatibility Publisher Issued by: Microsoft Windows Third Party Component CA 2014 Expires: Thu Jun 01 13:08:05 2023 SHA1 hash: DD691DF1501B597630AB6C8BAC2A8105FF8D1470 The signature is timestamped: Tue Mar 28 15:02:51 2023 Timestamp Verified by: Issued to: Microsoft Root Certificate Authority 2010 Issued by: Microsoft Root Certificate Authority 2010 Expires: Sat Jun 23 17:04:01 2035 SHA1 hash: 3B1EFD3A66EA28B16697394703A72CA340A05BD5 Issued to: Microsoft Time-Stamp PCA 2010 Issued by: Microsoft Root Certificate Authority 2010 Expires: Mon Sep 30 13:32:25 2030 SHA1 hash: 36056A5662DCADECF82CC14C8B80EC5E0BCC59A6 Issued to: Microsoft Time-Stamp Service Issued by: Microsoft Time-Stamp PCA 2010 Expires: Thu Dec 14 15:22:03 2023 SHA1 hash: 718B44E896DD1E12A5C2425E2A8095D492240E61 Successfully verified: viogpudorc.sys Number of files successfully Verified: 1 Number of warnings: 0 Number of errors: 0
Users can also open the catalog file (.cat
) and view the signature there.
Signing time
In our experience, the time consumed by the entire signing process varies. Most attestation signing processes take around ten minutes to complete. However, it has happened that some signing processes have taken more than an hour. This is most likely due to the workload in Microsoft’s Partner Center.