驱动签名与部署:测试签名、WHQL签名、安全启动、驱动安装与卸载

驱动开发完了,代码也调通了,接下来怎么办?

直接扔给用户?不行。你想想看,Windows 从 Vista 开始就对驱动签名有严格要求。没签名的驱动,系统根本不让你装。我早年刚做驱动时,就吃过这个亏——写了个很完美的键盘过滤驱动,结果在客户的 Win7 机器上死活装不上,折腾了两天才发现是签名问题。

这一章,我就把驱动签名和部署的整个流程给你捋清楚。包括测试签名、WHQL 正式签名、安全启动的兼容性,以及驱动的安装与卸载。

为什么驱动必须签名?

说白了,签名就是给驱动打上一个「身份证明」。系统通过这个证明来判断:

  • 驱动是谁发布的
  • 驱动有没有被篡改过
  • 驱动是否通过了微软的认证

没有签名的驱动,在 64 位 Windows 上默认是禁止加载的。32 位系统虽然宽松一些,但也会弹出警告。

核心原则:驱动签名不是可选项,而是必选项。除非你只在调试模式下工作,否则必须处理签名问题。

测试签名:开发阶段的必备技能

开发阶段,我们不可能每次编译都去申请正式签名。这时候就需要测试签名。测试签名说白了就是自己给自己签一个名,让系统在「测试模式」下信任你的驱动。

启用测试模式

首先,让系统进入测试模式。以管理员身份打开 CMD,执行:

bcdedit /set testsigning on

重启后,桌面右下角会出现「测试模式」的水印。嗯,这个水印虽然有点碍眼,但习惯就好。

生成测试证书

用 Visual Studio 自带的工具,或者用 MakeCert 工具生成一个测试证书:

makecert -r -pe -ss PrivateCertStore -n "CN=MyTestCert" -eku 1.3.6.1.5.5.7.3.3 MyTestCert.cer

我个人习惯把证书放在项目目录下的 cert 文件夹里,方便管理。

给驱动文件签名

使用 SignTool 工具进行签名:

signtool sign /v /s PrivateCertStore /n MyTestCert /t http://timestamp.digicert.com mydriver.sys

这里要注意时间戳服务器。不加时间戳的话,证书过期后驱动就失效了。我遇到过这种情况——开发时好好的,过了几个月客户反馈驱动装不上,就是因为证书过期了。

安装测试证书到信任根

签名完还不够,你得把证书安装到「受信任的根证书颁发机构」里。否则系统还是不认。

certmgr.msc

打开证书管理器,导入 MyTestCert.cer 到「受信任的根证书颁发机构」和「受信任的发布者」两个位置。

小技巧:可以用批处理脚本把签名和安装证书的步骤自动化。我每次编译完驱动,直接跑一个 sign_and_install.bat,省心省力。

WHQL 签名:正式发布的通行证

测试签名只能在开发机和测试机上用。要正式发布,必须走 WHQL(Windows Hardware Quality Labs)认证。

WHQL 流程概览

WHQL 认证的流程大致如下:

  1. 注册 Windows 硬件开发中心账号
  2. 提交驱动进行 HLK(Hardware Lab Kit)测试
  3. 测试通过后,上传到微软门户
  4. 微软审核通过,签发数字签名
  5. 下载签名后的驱动文件

这个过程说起来简单,做起来挺繁琐的。HLK 测试要跑几十项,有些测试项对硬件有特定要求。我记得有一次提交一个存储驱动,HLK 测试里有个「磁盘压力测试」跑了整整 12 个小时才通过。

HLK 测试的关键点

测试类别 说明 常见问题
功能测试 验证驱动的基本功能是否正常 IOCTL 处理不当导致蓝屏
压力测试 高负载下驱动的稳定性 内存泄漏、资源死锁
兼容性测试 不同 Windows 版本下的表现 API 在不同版本中行为不一致
安全测试 检查是否存在安全漏洞 缓冲区溢出、权限提升

注意:HLK 测试环境必须干净。我建议用一台专门的测试机,装好 Windows 后不要装其他软件。否则测试结果可能被污染,微软那边不认账。

安全启动:绕不过的坎

从 Windows 8 开始,支持 UEFI 安全启动(Secure Boot)的机器越来越多。安全启动会校验 bootloader 和内核驱动的签名。

如果你的驱动要在安全启动环境下运行,必须满足两个条件:

  • 驱动必须使用 WHQL 签名(测试签名不行)
  • 签名链必须能追溯到 UEFI 固件中内置的证书

说白了,安全启动就是给驱动加了一道「硬件级」的校验。我有个朋友开发了一个虚拟化驱动,在普通机器上跑得好好的,结果在 Surface Pro 上死活加载不了。查了半天,就是安全启动在作怪。

如何兼容安全启动

如果你的驱动需要兼容安全启动,建议:

  1. 尽早走 WHQL 认证流程
  2. 在测试时,开启安全启动进行验证
  3. 如果只是内部使用,可以在 BIOS 中关闭安全启动(但不推荐)

我的建议:即使你现在不需要安全启动,也尽量用 WHQL 签名。因为未来 Windows 对安全启动的支持只会越来越严格。早做准备,免得后面被动。

驱动安装与卸载:别让用户骂娘

驱动写得好,安装体验差,用户一样会骂你。安装和卸载的流程必须设计得干净利落。

安装方式

常见的驱动安装方式有三种:

  • INF 文件安装:最标准的方式。用户右键点击 INF 文件,选择「安装」即可。
  • PnP 自动安装:设备插入时,系统自动查找并安装驱动。
  • 安装程序:用 SetupAPI 编写自定义安装程序,适合需要额外配置的场景。

我个人最推荐 INF 文件安装。简单、可靠、用户容易理解。除非你的驱动需要安装额外的服务或配置,否则没必要搞复杂的安装程序。

INF 文件示例

一个典型的 INF 文件长这样:

[Version]
Signature="$WINDOWS NT$"
Class=Sample
ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}
Provider=%ProviderName%
DriverVer=09/28/2023,1.0.0.0

[Manufacturer]
%ManufacturerName%=Standard,NTamd64

[Standard.NTamd64]
%DeviceDesc%=MyDevice_Install, PCI\VEN_1234&DEV_5678

[MyDevice_Install]
CopyFiles=MyDevice.CopyFiles

[MyDevice.CopyFiles]
mydriver.sys

[DestinationDirs]
MyDevice.CopyFiles=12,System32\drivers

这里要注意 ClassGuid 必须正确。不同的设备类型有不同的 GUID,用错了会导致设备管理器里分类错误。

驱动卸载

卸载驱动时,要确保:

  • 驱动没有正在被使用
  • 所有资源都被正确释放
  • 注册表中的残留项被清理

在设备管理器中,右键设备 -> 卸载设备,勾选「删除此设备的驱动程序软件」,就能彻底卸载。

避坑指南:我曾经写过一个驱动,卸载时没有清理注册表中的配置项。结果用户重装驱动后,旧配置和新驱动不兼容,导致蓝屏。后来我学乖了,在 DriverEntry 和 DriverUnload 里都加上了注册表清理的逻辑。

知识体系总览

下面这张图,把驱动签名与部署的核心流程串起来了:

驱动签名与部署核心流程 驱动开发与调试 测试签名 测试部署验证 通过测试? 返回修改 WHQL 认证 安全启动兼容 正式发布部署 驱动安装与卸载 安装方式 • INF 文件安装 • PnP 自动安装 • 自定义安装程序 • 卸载清理

总结

驱动签名与部署,说白了就是让你的驱动能被 Windows 信任、能被用户顺利装上。测试签名解决开发阶段的燃眉之急,WHQL 签名是正式发布的必经之路,安全启动是未来趋势,安装卸载则关系到用户体验。

我做了这么多年驱动开发,最大的体会就是:签名这件事,越早规划越好。别等到要发布了才发现签名没搞定,那时候就抓瞎了。

最后提醒:每次修改驱动后,记得重新签名。我见过有人改了驱动代码,忘了重新签名,结果测试时加载的还是旧版本,白白浪费了半天调试时间。


公众号:蓝海资料掘金营,微信deep3321