WHQL Signing - Do I need it for an internal driver that is not distributed?

I think this is probably a really quick question for people here, but there isnt a lot of info I could find for an internal scenario. If I am writing a filter driver that would only ever be used internally and not distributed to anyone; do I need to go through the EV process or can I sign with an internal trusted Certificate Authority to deploy? I know Windows has built in protections for driver signing and I’m not sure if the OS would let me deploy outside of enabling test signing on all machines which I wouldnt do.

Thoughts? Thanks in advance!

no. You can just use attestation signing for internal (and external if you want) distribution.

Thanks!

Both “WHQL signing” and “Attestation signing” require obtaining an EV certificate; they are no different in that regard. The difference is just in the number of tests your drivers are required to pass before Microsoft agrees to sign them. You still had to prove who you were to Microsoft via the EV certificate in order to use either approach.

The only way I’m aware of to make Windows accept “any signature” rather than a Microsoft kernel-policy signature – such as a signature using a certificate from the internal CA you installed as a trusted root CA – is to enable “Test Mode” via BCDEDIT. Which as you apparently know, will be advertised on the desktop of each machine where this mode is enabled.

Microsoft discontinued cross-signing support, which would have provided the other alternative to sign a driver “without Microsoft.” Using “Test Mode” is the only scenario I’m aware of where your own non-Microsoft signature would be accepted for loading the driver at runtime. Aside from the even more disruptive options, like F8 “Disable driver signature enforcement” or having a kernel-mode debugger attached to the system, of course.

The difference is just in the number of tests your drivers are required to pass before Microsoft agrees to sign them.

As in there are zero tests required for attestation signing. As release signing has been abolished, attestation signing is really the only feasible route for deployment without test signing and without going through WHQL. But yes, you do have to get an EV cert to set up an account.

1 Like

The only way I’m aware of to make Windows accept “any signature” rather than a Microsoft kernel-policy signature – such as a signature using a certificate from the internal CA you installed as a trusted root CA – is to enable “Test Mode” via BCDEDIT.

I believe this is not exactly true. libwdi method is working without enable “Test Mode” for Windows 11 (other than some inside build version).
Reference: https://community.osr.com/discussion/293115/windows-11-and-alternative-driver-installation-method-in-libwdi#latest
Reference: https://github.com/pbatard/libwdi/wiki/FAQ#Running_libwdi

But it may or may not help the OP if the “.sys” kernel driver has not been signed.

@Alan_Adams said:
The only way I’m aware of to make Windows accept “any signature” rather than a Microsoft kernel-policy signature – such as a signature using a certificate from the internal CA you installed as a trusted root CA –

Are you sure adding a internal CA to the trusted root will cause Windows to load drivers that are signed with it, even with Secure boot on? Because last time i checked i think adding something to the trusted root will not help in loading drivers, but please correct me if I’m wrong.

@Xiaofan_Chen said:

The only way I’m aware of to make Windows accept “any signature” rather than a Microsoft kernel-policy signature – such as a signature using a certificate from the internal CA you installed as a trusted root CA – is to enable “Test Mode” via BCDEDIT.

I believe this is not exactly true. libwdi method is working without enable “Test Mode” for Windows 11 (other than some inside build version).
Reference: https://community.osr.com/discussion/293115/windows-11-and-alternative-driver-installation-method-in-libwdi#latest
Reference: https://github.com/pbatard/libwdi/wiki/FAQ#Running_libwdi

But it may or may not help the OP if the “.sys” kernel driver has not been signed.

I thought that didn’t work in Windows 11?

https://github.com/pbatard/libwdi/issues/155#issuecomment-918883668

@brad_H said:
I thought that didn’t work in Windows 11?

https://github.com/pbatard/libwdi/issues/155#issuecomment-918883668

If you read the further comments, it works with official version of Windows 11, but not for some insider release versions.

@Xiaofan_Chen said:

@brad_H said:
I thought that didn’t work in Windows 11?

https://github.com/pbatard/libwdi/issues/155#issuecomment-918883668

If you read the further comments, it works with official version of Windows 11, but not for some insider release versions.

Yes but doesn’t that make it an unstable approach? Considering that it won’t work on some insider versions, and most probably that means that the upcoming versions of Windows 11 will no longer support that?

@Xiaofan_Chen said:

@brad_H said:
I thought that didn’t work in Windows 11?

https://github.com/pbatard/libwdi/issues/155#issuecomment-918883668

If you read the further comments, it works with official version of Windows 11, but not for some insider release versions.

And I’m still not sure how they are loading drivers by adding their self signed cert to the trusted root? Because i manually did it with my self signed cert and added it to my certificate store’s trusted root, and still the driver doesn’t load, even in Win7?

@brad_H said:
And I’m still not sure how they are loading drivers by adding their self signed cert to the trusted root? Because i manually did it with my self signed cert and added it to my certificate store’s trusted root, and still the driver doesn’t load, even in Win7?

libwdi is open source so you can look at the codes here. There is also a FAQ. Take note the .sys file needs to have the correct digital signauture as libwdi deals with libusb0.sys, libusbk.sys and WinUSB. It can be used for other driver as well as long as the .sys driver is already signed properly.
https://github.com/pbatard/libwdi/tree/master/libwdi
https://github.com/pbatard/libwdi/wiki/FAQ

You can also ignore libwdi’s codes related to USB, just look at the signing part here in the libusbk project’s dpscat utility, which can be used with any driver package as long as the core .sys driver is already signed, perfectly for use cases like the OP mentioned here (using inf to cover different VID/PID combination).
https://github.com/mcuee/libusbk/tree/master/libusbK/src/dpscat

Example of using dpscat with Cypress cyusb3 driver (just for testing purpose):
https://github.com/pbatard/libwdi/issues/191#issuecomment-883457515

@brad_H said:
Yes but doesn’t that make it an unstable approach? Considering that it won’t work on some insider versions, and most probably that means that the upcoming versions of Windows 11 will no longer support that?

It has been working from Windows 7 to Windows 11 official release. Not all Windows Insider build features make to the official release anyway.

But if Microsoft finally decides to close the door, then that is it.

Anyway, I will recommend users to switch to WinUSB driver and use Windows WinUSB Compatable ID for generic USB driver to avoid using libwdi/Zadig.
Ref: https://github.com/pbatard/libwdi/wiki/WCID-Devices

Example for Raspberry Pi PicoProbe.
https://github.com/raspberrypi/picoprobe/issues/15
https://github.com/raspberrypi/picoprobe/pull/17

Are you sure adding a internal CA to the trusted root will cause Windows to load drivers that are signed with it, even with Secure boot on? Because last time i checked i think adding something to the trusted root will not help in loading drivers, but please correct me if I’m wrong.

The statement is that you have to enable Test Mode in order to expect “just any signature” to be accepted for the kernel-mode driver loading.

You cannot have both Test Mode and Secure Boot enabled at the same time; Windows will require that you disable Secure Boot in order to enable Test Mode.

So no, on a normal retail machine without Test Mode enabled, you cannot add your own private CA as a trusted root CA and expect kernel-mode drivers signed with a certificate issued by that CA to be loaded by Windows. Because “Test Mode” has not been enabled on that machine.

Yes, I am sure this works with Test Mode enabled, because this has been the required approach for making non-Microsoft-signed test builds ever since Microsoft deprecated cross-signing. Instead of making a cross-signed build for internal testing, we now create a build signed with a certificate from an internal CA. The installer for the internal builds first enables Test Signing mode, and installs the internal CA as a trusted root CA.

“So no, on a normal retail machine without Test Mode enabled, you cannot add your own private CA as a trusted root CA and expect kernel-mode >drivers signed with a certificate issued by that CA to be loaded by Windows. Because “Test Mode” has not been enabled on that machine.”

But note that this is not what libwdi and zadig do: they replace one correctly signed driver with another correctly signed driver, but update the inf (and sign the cat file) using a selfsigned cert installed in the local root.

That said, this is obviously not supported, although a lot of us who do embedded projects use the related zadig tool to put the right driver on our usb serial devices.

@Mark_Roddy said:

“So no, on a normal retail machine without Test Mode enabled, you cannot add your own private CA as a trusted root CA and expect kernel-mode >drivers signed with a certificate issued by that CA to be loaded by Windows. Because “Test Mode” has not been enabled on that machine.”

But note that this is not what libwdi and zadig do: they replace one correctly signed driver with another correctly signed driver, but update the inf (and sign the cat file) using a selfsigned cert installed in the local root.

That said, this is obviously not supported, although a lot of us who do embedded projects use the related zadig tool to put the right driver on our usb serial devices.

I apologize for asking a rookie question, but how are they actually updating the INF?
For example lets say you have an NDIS LWF installed, i always thought you have to first uninstall the previous version then install the new one with the updated INF. So how is libwdi updating the INF file? which part of their code base is the implementation of this?
Because when you for example install an NDIS LWF, there will be a lot of registry keys set based on your config, so I’m not sure how does updating it instead of uninstall/install work?

@Mark_Roddy said:
But note that this is not what libwdi and zadig do: they replace one correctly signed driver with another correctly signed driver, but update the inf (and sign the cat file) using a selfsigned cert installed in the local root.

That is a good summary. The .sys file needs to be signed (libusb0.sys, libusbk.sys and winusb.sys). That is the base requirements. Then libwdi can be useful to sign the driver package (inf and then cat file).

The main meat of the libwdi library is the pki.c file.
https://github.com/pbatard/libwdi/blob/master/libwdi/pki.c

dpscat from libusbk project may be simpler to look at based on the above pki.c. It creates self-signed .cat files from .inf files.
https://github.com/mcuee/libusbk/tree/master/libusbK/src/dpscat

That said, this is obviously not supported, although a lot of us who do embedded projects use the related zadig tool to put the right driver on our usb serial devices.

Indeed Zadig is popular in the embedded world.

@Richard_M said:
I apologize for asking a rookie question, but how are they actually updating the INF?
For example lets say you have an NDIS LWF installed, i always thought you have to first uninstall the previous version then install the new one with the updated INF. So how is libwdi updating the INF file? which part of their code base is the implementation of this?
Because when you for example install an NDIS LWF, there will be a lot of registry keys set based on your config, so I’m not sure how does updating it instead of uninstall/install work?

Not so sure if libwdi will work for you or not. libwdi uses its own installer but you can use dpinst as well if you like. The driver installer will take care of the inf file updates.
Ref: https://github.com/pbatard/libwdi/wiki/FAQ#why-doesnt-libwdi-use-dpinstexe-instead-of-a-custom-installer

In fact libusbk project’s installer is based on libwdi but using dpinst.
https://github.com/mcuee/libusbk/tree/master/libusbK/src