证书是要在链路上传的,太大就有问题:握手报文撑大,内存缓冲吃紧,解析成本上去,还可能被拿来做资源耗尽的攻击。所以 IEC 62351-3 允许设备声明一个最大证书尺寸,超过就不收。
这条测的就是这个上限。设备收到一张比上限还大的证书,要报Alarm: TLS certificate size exceeded,关连接。
造一张大证书
正常的 2048 位证书也就一 KB 出头,离上限还远。要把它撑大,最直接的办法是往里塞 subjectAltName。我们塞了 200 条 DNS 名:
openssl req-x509-newkeyrsa:2048-keyoutbig.key-outbig.crt\-days3650-nodes-sha256\-subj"/C=CN/O=TestLab/CN=Big Client"\-addext"subjectAltName=DNS:host1.bigcert.test.lab,DNS:host2.bigcert.test.lab,..."200 条 SAN 加上去,证书体积轻松翻好几倍,具体多少得看设备声明的上限。我们的 DUT 声明 4096 字节,那就得保证 big.crt 的 DER 编码超过这个数。
服务端配置
上限怎么配取决于 TLS 库。OpenSSL 3.x 有现成的:
SSL_CTX_set_max_cert_size(ctx,4096);1.x 没有这个接口,得自己在 verify 回调里拿i2d_X509算出 DER 长度再比。目标板上跑的是 1.0.x,所以我们的实现走的是回调这条路。
跑测试
cdcerts_keys/# 基线:正常证书openssl s_client-connect127.0.0.1:19998-tls1_2\-certclient.crt-keyclient.key-CAfileca.crt# 测试:大证书openssl s_client-connect127.0.0.1:19998-tls1_2\-certbig.crt-keybig.key-CAfileca.crt判定
| 检查项 | 通过标准 |
|---|---|
| 基线 | 成功 |
| 超大证书 | 握手失败 |
| 安全事件 | Alarm: TLS certificate size exceeded |
| 连接 | 设备主动关闭 |
一个经验
上限的判定要在解析证书之前做,理想情况是看到握手报文里 Certificate 消息的长度超了就拒,而不是等把整张证书解析完再检查。后者等于把资源消耗的活儿先干了一遍,攻击者还是能把内存耗掉。测的时候如果设备只是"解析完发现太大",功能上算过了,但防御效果打了折扣,值得记一笔。
6.3.29 是这条的重协商版本,手法一样,只是换成在重协商阶段递大证书。