Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ba4efe9
feat: introduce sign mode for driver packaging, allowing skipping of …
svasista-ms Apr 27, 2026
c3a080e
refactor: remove Authenticode signature checks from sign mode off tests
svasista-ms Apr 27, 2026
490f323
test: add verification skip test for sign mode off with signature ver…
svasista-ms Apr 27, 2026
a13c7e3
Merge branch 'main' into sign-mode-off
svasista-ms May 6, 2026
1c1374a
refactor: sign mode variant names to lowercase and clean up related t…
svasista-ms May 7, 2026
d7a17ae
refactor(tests): remove build help test
svasista-ms May 12, 2026
37b8d2d
refactor(package_task): enforce signature verification rules and upda…
svasista-ms May 12, 2026
13e2280
Merge branch 'microsoft:main' into sign-mode-off
svasista-ms May 13, 2026
b32d8f9
refactor: move SignMode enum to cli layer and introduce SignConfig fo…
svasista-ms May 18, 2026
317e2d3
refactor: update documentation for SignConfig and SignMode enums
svasista-ms May 18, 2026
844306e
refactor(package_task): simplify sign_and_verify method documentation
svasista-ms May 18, 2026
e4c0622
refactor(main): update main function to return ExitCode and improve e…
svasista-ms May 19, 2026
3edac63
refactor(README): add --sign-mode option to build command and update …
svasista-ms May 19, 2026
148356e
refactor: rename SignConfig to SignMode
svasista-ms May 19, 2026
d5b0ee1
refactor(README): usage of --sign-mode flag in build command
svasista-ms May 21, 2026
55ca56f
refactor(package_task): simplify documentation for SignMode Off and u…
svasista-ms May 21, 2026
d793ec5
refactor: improve tests and documentation for --sign-mode flag
svasista-ms May 22, 2026
d536fd8
refactor(README): update build command sign-mode example
svasista-ms May 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions crates/cargo-wdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,17 @@ Usage: cargo wdk build [OPTIONS]
Options:
--profile <PROFILE> Build artifacts with the specified profile
--target-arch <TARGET_ARCH> Build for the target architecture
--sign-mode <SIGN_MODE> Driver signing mode [default: test] [possible values: off, test]
--verify-signature Verify the signature
--sample Build sample class driver project
-h, --help Print help
-h, --help Print help (see more with '--help')
Comment thread
gurry marked this conversation as resolved.
Outdated

Verbosity:
-v, --verbose... Increase logging verbosity
-q, --quiet... Decrease logging verbosity
```

`build` takes a number of inputs specifying build profile (`dev` or `release`), target architecture (`amd64` or `arm64`), a flag enabling signature verification and a flag indicating a sample driver along with verbosity flags.
`build` takes a number of inputs specifying build profile (`dev` or `release`), target architecture (`amd64` or `arm64`), the driver signing mode, a flag enabling signature verification and a flag indicating a sample driver along with verbosity flags.

When the command completes the packaged driver artifacts are emitted at the path `target\<profile>\<project-name>-package`.

Expand All @@ -90,9 +91,14 @@ If you have a workspace with a mix of sample and non-sample driver projects, the

#### Signing and Verification

To sign driver artifacts `build` looks for a certificate called `WDRLocalTestCert` in a store called `WDRTestCertStore`. Make sure you place your signing certificate there with that name. If no certificate is found, `build` will automatically generate a new self-signed one and add it for you.
The `--sign-mode` flag controls how driver artifacts are signed. It accepts the following values:
Comment thread
gurry marked this conversation as resolved.
Outdated

If the `--verify-signature` flag is provided, the signatures are verified after signing. For verification to work, make sure you add a copy of the signing certificate in the `Trusted Root Certification Authorities` store. For security reasons `build` does not automatically do this even when it automatically generates the cert. You will have to always perform this step manually.
- `test` (default): Sign with an auto-generated self-signed certificate. `build` looks for a certificate called `WDRLocalTestCert` in a store called `WDRTestCertStore`. Make sure you place your signing certificate there with that name. If no certificate is found, `build` will automatically generate a new self-signed one and add it for you.
Comment thread
gurry marked this conversation as resolved.
Outdated
- `off`: Skip signing entirely. No signing or signature verification steps are performed. This is useful when you intend to sign the driver later with your own toolchain (for example, HLK certification). Note that an unsigned driver cannot be installed on Windows without first enabling [test signing](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/the-testsigning-boot-configuration-option) or otherwise loading it through a signed mechanism.
Comment thread
gurry marked this conversation as resolved.
Outdated

If the `--verify-signature` flag is provided, the signatures are verified after signing. For verification to work, make sure you add a copy of the signing certificate in the `Trusted Root Certification Authorities` store. For security reasons `build` does not automatically do this even when it automatically generates the cert. You will have to always perform this step manually.

`--verify-signature` cannot be combined with `--sign-mode=off` because there is no signature to verify. Passing both will cause `build` to fail with an error.
Comment thread
gurry marked this conversation as resolved.
Outdated

#### Examples

Expand All @@ -113,3 +119,9 @@ If the `--verify-signature` flag is provided, the signatures are verified after
```pwsh
cargo wdk build --target-arch amd64
```

- To build a driver project and skip signing (for example, to sign later with a production certificate), run:
Comment thread
gurry marked this conversation as resolved.
Outdated

```pwsh
cargo wdk build --sign-mode off
Comment thread
gurry marked this conversation as resolved.
```
9 changes: 5 additions & 4 deletions crates/cargo-wdk/src/actions/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use build_task::BuildTask;
use cargo_metadata::{CrateType, Message, Metadata as CargoMetadata, Package, TargetKind};
use error::BuildActionError;
use mockall_double::double;
pub use package_task::SignConfig;
use package_task::{PackageTask, PackageTaskParams};
use tracing::{debug, error as err, info, trace, warn};
use wdk_build::{
Expand All @@ -37,7 +38,7 @@ pub struct BuildActionParams<'a> {
pub working_dir: &'a Path,
pub profile: Option<&'a Profile>,
pub target_arch: Option<CpuArchitecture>,
pub verify_signature: bool,
pub sign_config: SignConfig,
pub is_sample_class: bool,
pub verbosity_level: clap_verbosity_flag::Verbosity,
}
Expand All @@ -48,7 +49,7 @@ pub struct BuildAction<'a> {
working_dir: PathBuf,
profile: Option<&'a Profile>,
target_arch: Option<CpuArchitecture>,
verify_signature: bool,
sign_config: SignConfig,
is_sample_class: bool,
verbosity_level: clap_verbosity_flag::Verbosity,

Expand Down Expand Up @@ -93,7 +94,7 @@ impl<'a> BuildAction<'a> {
working_dir: absolute(params.working_dir)?,
profile: params.profile,
target_arch: params.target_arch,
verify_signature: params.verify_signature,
sign_config: params.sign_config,
is_sample_class: params.is_sample_class,
verbosity_level: params.verbosity_level,
wdk_build,
Expand Down Expand Up @@ -386,7 +387,7 @@ impl<'a> BuildAction<'a> {
working_dir,
target_dir: &target_dir,
target_arch: &target_arch,
verify_signature: self.verify_signature,
sign_config: self.sign_config,
sample_class: self.is_sample_class,
driver_model,
},
Expand Down
63 changes: 52 additions & 11 deletions crates/cargo-wdk/src/actions/build/package_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ use windows::{
use crate::providers::{exec::CommandExec, fs::Fs, wdk_build::WdkBuild};
use crate::{actions::build::error::PackageTaskError, providers::error::FileError};

/// Signing configuration.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignConfig {
Comment thread
gurry marked this conversation as resolved.
Outdated
/// Skip certificate generation, signing, and signature verification
/// entirely.
Off,
/// Sign with an auto-generated self-signed certificate.
Test {
/// When `true`, run `signtool verify` on the signed driver binary and
/// catalog file after signing.
verify_signature: bool,
},
}

// FIXME: This range is inclusive of 25798. Update with range end after /sample
// flag is added to InfVerif CLI
const MISSING_SAMPLE_FLAG_WDK_BUILD_NUMBER_RANGE: RangeFrom<u32> = 25798..;
Expand All @@ -43,15 +57,15 @@ pub struct PackageTaskParams<'a> {
pub working_dir: &'a Path,
pub target_dir: &'a Path,
pub target_arch: &'a CpuArchitecture,
pub verify_signature: bool,
pub sign_config: SignConfig,
pub sample_class: bool,
pub driver_model: DriverConfig,
}

/// Supports low level driver packaging operations
pub struct PackageTask<'a> {
package_name: String,
verify_signature: bool,
sign_config: SignConfig,
sample_class: bool,

// src paths
Expand Down Expand Up @@ -161,7 +175,7 @@ impl<'a> PackageTask<'a> {

Self {
package_name,
verify_signature: params.verify_signature,
sign_config: params.sign_config,
sample_class: params.sample_class,
src_inx_file_path,
src_driver_binary_file_path,
Expand Down Expand Up @@ -236,6 +250,20 @@ impl<'a> PackageTask<'a> {
self.copy(&self.src_map_file_path, &self.dest_map_file_path)?;
self.run_stampinf()?;
self.run_inf2cat()?;
self.run_infverif()?;
Comment thread
krishnakumar4a4 marked this conversation as resolved.
self.sign_and_verify()?;
Ok(())
}

/// Signs the driver binary and catalog file according to `self.sign_config`
/// and optionally verifies the resulting signatures. Returns a variant of
/// `PackageTaskError` if any step of the process fails.
fn sign_and_verify(&self) -> Result<(), PackageTaskError> {
let SignConfig::Test { verify_signature } = self.sign_config else {
info!("Sign mode is 'off'; skipping certificate generation, signing, and verification");
Comment thread
gurry marked this conversation as resolved.
Outdated
return Ok(());
};

self.generate_certificate()?;
self.copy(&self.src_cert_file_path, &self.dest_cert_file_path)?;
self.run_signtool_sign(
Expand All @@ -248,13 +276,13 @@ impl<'a> PackageTask<'a> {
WDR_TEST_CERT_STORE,
WDR_LOCAL_TEST_CERT,
)?;
self.run_infverif()?;
// Verify signatures only when --verify-signature flag = true is passed
if self.verify_signature {

if verify_signature {
info!("Verifying signatures for driver binary and cat file using signtool");
self.run_signtool_verify(&self.dest_driver_binary_path)?;
self.run_signtool_verify(&self.dest_cat_file_path)?;
}

Ok(())
}

Expand Down Expand Up @@ -635,7 +663,9 @@ mod tests {
target_arch: &arch,
driver_model: DriverConfig::Kmdf(KmdfConfig::default()),
sample_class: false,
verify_signature: false,
sign_config: SignConfig::Test {
verify_signature: false,
},
};
let dest_root = target_dir.join(format!("{package_name}_package"));

Expand All @@ -644,7 +674,12 @@ mod tests {
let fs = Fs::default();
let task = PackageTask::new(package_task_params, &wdk_build, &command_exec, &fs);
assert_eq!(task.package_name, package_name.replace('-', "_"));
assert!(!task.verify_signature);
assert_eq!(
task.sign_config,
SignConfig::Test {
verify_signature: false,
}
);
assert!(!task.sample_class);
assert_eq!(task.src_inx_file_path, working_dir.join("test_package.inx"));
assert_eq!(
Expand Down Expand Up @@ -698,7 +733,9 @@ mod tests {
target_arch: &arch,
driver_model: DriverConfig::Kmdf(KmdfConfig::default()),
sample_class: false,
verify_signature: false,
sign_config: SignConfig::Test {
verify_signature: false,
},
};

let command_exec = CommandExec::default();
Expand All @@ -724,7 +761,9 @@ mod tests {
target_arch: &arch,
driver_model: DriverConfig::Kmdf(KmdfConfig::default()),
sample_class: false,
verify_signature: false,
sign_config: SignConfig::Test {
verify_signature: false,
},
};

let command_exec = CommandExec::default();
Expand Down Expand Up @@ -759,7 +798,9 @@ mod tests {
target_arch: &arch,
driver_model: DriverConfig::Kmdf(KmdfConfig::default()),
sample_class: false,
verify_signature: false,
sign_config: SignConfig::Test {
verify_signature: false,
},
};

let wdk_build = WdkBuild::default();
Expand Down
Loading
Loading