驱动签名与部署:测试签名、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 认证的流程大致如下:
- 注册 Windows 硬件开发中心账号
- 提交驱动进行 HLK(Hardware Lab Kit)测试
- 测试通过后,上传到微软门户
- 微软审核通过,签发数字签名
- 下载签名后的驱动文件
这个过程说起来简单,做起来挺繁琐的。HLK 测试要跑几十项,有些测试项对硬件有特定要求。我记得有一次提交一个存储驱动,HLK 测试里有个「磁盘压力测试」跑了整整 12 个小时才通过。
HLK 测试的关键点
| 测试类别 | 说明 | 常见问题 |
|---|---|---|
| 功能测试 | 验证驱动的基本功能是否正常 | IOCTL 处理不当导致蓝屏 |
| 压力测试 | 高负载下驱动的稳定性 | 内存泄漏、资源死锁 |
| 兼容性测试 | 不同 Windows 版本下的表现 | API 在不同版本中行为不一致 |
| 安全测试 | 检查是否存在安全漏洞 | 缓冲区溢出、权限提升 |
注意:HLK 测试环境必须干净。我建议用一台专门的测试机,装好 Windows 后不要装其他软件。否则测试结果可能被污染,微软那边不认账。
安全启动:绕不过的坎
从 Windows 8 开始,支持 UEFI 安全启动(Secure Boot)的机器越来越多。安全启动会校验 bootloader 和内核驱动的签名。
如果你的驱动要在安全启动环境下运行,必须满足两个条件:
- 驱动必须使用 WHQL 签名(测试签名不行)
- 签名链必须能追溯到 UEFI 固件中内置的证书
说白了,安全启动就是给驱动加了一道「硬件级」的校验。我有个朋友开发了一个虚拟化驱动,在普通机器上跑得好好的,结果在 Surface Pro 上死活加载不了。查了半天,就是安全启动在作怪。
如何兼容安全启动
如果你的驱动需要兼容安全启动,建议:
- 尽早走 WHQL 认证流程
- 在测试时,开启安全启动进行验证
- 如果只是内部使用,可以在 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 里都加上了注册表清理的逻辑。
知识体系总览
下面这张图,把驱动签名与部署的核心流程串起来了:
总结
驱动签名与部署,说白了就是让你的驱动能被 Windows 信任、能被用户顺利装上。测试签名解决开发阶段的燃眉之急,WHQL 签名是正式发布的必经之路,安全启动是未来趋势,安装卸载则关系到用户体验。
我做了这么多年驱动开发,最大的体会就是:签名这件事,越早规划越好。别等到要发布了才发现签名没搞定,那时候就抓瞎了。
最后提醒:每次修改驱动后,记得重新签名。我见过有人改了驱动代码,忘了重新签名,结果测试时加载的还是旧版本,白白浪费了半天调试时间。
公众号:蓝海资料掘金营,微信deep3321