Skip to content

Implement sign support for OPC based file formats.#291

Closed
tmittet wants to merge 8 commits into
vcsjones:mainfrom
tmittet:add_hlkx_sign_support
Closed

Implement sign support for OPC based file formats.#291
tmittet wants to merge 8 commits into
vcsjones:mainfrom
tmittet:add_hlkx_sign_support

Conversation

@tmittet
Copy link
Copy Markdown

@tmittet tmittet commented Dec 4, 2024

The main purpose is to allow signing .hlkx (Windows Hardware Lab Kit) files, but it might work for other OPC based file formats. Unit tests focus on signing and validating the signatures of .hlkx files only.

The implementation relies on System.IO.Packaging and the PackageDigitalSignatureManager from the .NET Desktop SDK WPF assemblies.

How it works:

  1. The OPC file is loaded using System.IO.Packaging.Package.Open()
  2. A self signed certificate (with private key) is generated with the same hash algorithm and key size as provided from Azure
  3. The OPC file is signed with the self signed certificate
  4. The OPC file certificate and signatures are patched using the certificate pubic key and RSA algorithm provided from Azure
  5. The OPC file certificate and signatures are validated using the System.IO.Packaging.PackageDigitalSignatureManager

Why not simply use the System.IO.Packaging.PackageDigitalSignatureManager?

The PackageDigitalSignatureManager does not support using a custom RSA instance to sign the package part hashes, it
can only sign with a certificate that contains a private key.

Why use the System.IO.Packaging.PackageDigitalSignatureManager at all?

The purpose of self-signing with PackageDigitalSignatureManager is to avoid implementing the package signing and signature validation logic myself. IMO: relying on a Microsoft library, especially for the signature validation part, is a good way to ensure that the signature is applied correctly.

The downside of using the PackageDigitalSignatureManager is that it's not yet part of .NET core, it relies on WPF assemblies and must target windows-desktop.

The main purpose is to allow signing .hlkx (Windows Hardware Lab Kit)
files, but it might work for other OPC based file formats. Unit tests
focus on signing and validating the signatures of .hlkx files only.

The implementation relies on System.IO.Packaging and the
PackageDigitalSignatureManager from the .NET Desktop SDK WPF assemblies.
@tmittet tmittet force-pushed the add_hlkx_sign_support branch from 1df37b9 to a7630cf Compare December 4, 2024 08:35
and return through SignatureVerificationResult with
VerificationStatus.Failed
and:
- VerificationException to OpcVerifyException
- VerificationOptions to OpcVerifyOptions
- VerificationStatus to OpcVerifyStatus
and return through OpcSignResult with
OpcSignStatus.Failed
that occur when Sign and Verify are called for files that
are invalid, don't exist or when the file path is invalid.
@tmittet tmittet marked this pull request as ready for review December 4, 2024 20:48
@tmittet
Copy link
Copy Markdown
Author

tmittet commented Dec 4, 2024

@vcsjones, not sure how familiar you are with Hardware Lab Kit files?

TLDR: .hlkx is a container format used to package drivers and driver test sets before sending to Microsoft for approval, and eventually to be allowed to publish drivers on Windows Update. The .hlkx files must be signed with an EV certificate before they can be sent to Microsoft for approval. To enable use in a modern CI environment it's a requirement to store these in an Azure Key Vault HSM.

I've added some test files to the unit test project that verify that the basics work as expected and I've tested signing a real .hlkx file (165 MB file size) locally using the AzureSignTool with our Azure EV HSM certificate. So far everything checks out.

I have not yet published a file to Microsoft for approval, to check if it passes their test pipeline as well, but I'm planning to do so later this week. The code is based on a tool a colleague and I wrote about a year ago, we use it in our CI and have had no issues getting files approved by Microsoft so far.

In the meantime, it would be great to get some review on the implementation and some feedback on how it was incorporated into the existing code in AzureSignTool Program.cs.

@vcsjones
Copy link
Copy Markdown
Owner

vcsjones commented Dec 4, 2024

Thanks for the pull request. You put a lot of work in to this, and it does something that others have asked, so I am interested and excited about it.

However I am a worried about the UseWPF. This breaks dotnet pack and dotnet publish.

For dotnet pack

PackAsTool does not support TargetPlatformIdentifier being set. For example, TargetFramework cannot be net5.0-windows, only net5.0. PackAsTool also does not support UseWPF or UseWindowsForms when targeting .NET 5 and higher.

For dotnet publish -c Release -r win-x64

WPF is not supported or recommended with trimming enabled. Please go to https://aka.ms/dotnet-illink/wpf for more details.

So while your changes work for framework dependent deployments, I don't see a straight-forward way to get this work, in a supported fashion, to an actually releasable state.

@tmittet
Copy link
Copy Markdown
Author

tmittet commented Dec 4, 2024

I assumed that wouldn't be a problem for this project since you rely heavily on Windows APIs/assemblies anyway. But I didn't know about the dotnet pack limitation, that's a bummer 😄 I only have very limited experience with PackAsTool.

We build our internal tool with msbuild and do PublishSingleFile, SelfContained and we also use PublishTrimmed IIRC.

I assume the PackAsTool limitation is a complete showstopper. In which case I'll push the changes to my fork for whoever might find it useful.

@tmittet
Copy link
Copy Markdown
Author

tmittet commented Dec 4, 2024

Closing, since PackAsTool does not support UseWPF 🤦

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants