[PUBLISHER] Merge #21

This commit is contained in:
wangzipai 2024-11-28 12:36:10 +08:00 committed by GitHub
parent af4d343b13
commit 0c330cdfdb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -0,0 +1,192 @@
---
date created: 2024-11-28 10:54
date updated: 2024-11-28 12:35
tags:
- BUG
- mbedtls
share: "true"
link: "false"
---
# 解决过程
## MBEDTLS_SSL_VERIFY_NONE
客户平台使用自签名的证书导致无法连接。按正常的思路将服务器的证书校验关闭就可以了。如下在连接中将参数设置为`MBEDTLS_SSL_VERIFY_NONE`
```c
mbedtls_ssl_conf_authmode(&session->conf, MBEDTLS_SSL_VERIFY_NONE);
```
但是很奇怪的事情发生了经过测试发现上面的设置好像没有什么帮助。使用wireshark抓包可以看到提示证书损坏。
![image.png](https://raw.githubusercontent.com/wangzipai/my_ob_pic/main/20241128110449.png)
## LIBRWS_USING_MBED_TLS
既然已经关闭证书校验了为什么还会去验证证书呢。看了使用的rws库发现了宏`LIBRWS_USING_MBED_TLS`没有使用于是怀疑是因为rws库没有关联mbedtls导致mbedtls中的证书校验关了但是rws使用了另外的接口又去验证了平台的证书。打开这个宏发现编译报错因为迭代了太多次导致这个宏无法使用了。于是继续从rws的`connect`函数进入发现rws的`connect`关联到了`sal_connect`。
![image.png|450](https://raw.githubusercontent.com/wangzipai/my_ob_pic/main/20241128111457.png)
而sal_connect又注册了mbedtls的connect接口。
![image.png](https://raw.githubusercontent.com/wangzipai/my_ob_pic/main/20241128112006.png)
所以说饶了一圈又回到了原来的地方,`LIBRWS_USING_MBED_TLS`的开关并不影响wss的连接。
## MBEDTLS_SSL_ALERT_MSG_BAD_CERT
抓包的bad certificate 对应mbedtls中的的宏`MBEDTLS_SSL_ALERT_MSG_BAD_CERT`,这个宏在项目中只有在一下两个地方有使用到。
![image.png](https://raw.githubusercontent.com/wangzipai/my_ob_pic/main/20241128113615.png)
往上层找,可以看到这个两个函数都是在`mbedtls_ssl_parse_certificate`中被调用的,他的上层函数`mbedtls_ssl_handshake_client_step`是tls层中客户端的交互流程`mbedtls_ssl_parse_certificate`本身则是ServerHello后的Certificate步骤。
![image.png](https://raw.githubusercontent.com/wangzipai/my_ob_pic/main/20241128114116.png)
观察这个函数可以看到他是有对`authmode`这个参数做处理的,这个参数就是上面的[[客户平台无法连接问题#MBEDTLS_SSL_VERIFY_NONE|MBEDTLS_SSL_VERIFY_NONE]]传进来的。
```c
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
{
int ret = 0;
int crt_expected;
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
? ssl->handshake->sni_authmode
: ssl->conf->authmode;
#else
const int authmode = ssl->conf->authmode;
#endif
void *rs_ctx = NULL;
mbedtls_x509_crt *chain = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
crt_expected = ssl_parse_certificate_coordinate( ssl, authmode );
if( crt_expected == SSL_CERTIFICATE_SKIP )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
goto exit;
}
...
}
```
但是函数`ssl_parse_certificate_coordinate`中又完全不对这个入参做处理,按照逻辑应该判断这个入参是否为`MBEDTLS_SSL_VERIFY_NONE`来判断是否需要返回跳过这里应该是mbedtls库的一个BUG。
![image.png](https://raw.githubusercontent.com/wangzipai/my_ob_pic/main/20241128115053.png)
尝试在这里让他返回跳过这个证书的步骤直接到下一个状态。使用抓包工具发现bad certificate的提示消失了但是出现了新的报错`MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR`重复上面的过程发现这次在ServerKeyExchange、CertificateRequest、ServerHelloDone都需要相应的手动跳过流程。对mbedtls库的改动过大应该还有其他的方法可以控制。
## MBEDTLS_MPI_MAX_SIZE
观察客户的自签名证书:
```sh
# wyq @ wangyq in ~ [0:19:37]
$ openssl x509 -in /mnt/d/cert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
79:8c:ac:87:c3:92:46:8d:0d:6d:19:16:e7:36:01:47:05:57:25:5f
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=my, ST=ev, L=kl, O=ev, OU=ev
Validity
Not Before: Nov 18 14:19:18 2024 GMT
Not After : Nov 18 14:19:18 2025 GMT
Subject: C=my, ST=ev, L=kl, O=ev, OU=ev
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:b7:63:d6:ef:50:65:04:a1:24:67:b3:24:7d:6f:
45:6e:16:f6:40:ca:3c:c5:a7:9b:86:5f:42:b9:6f:
73:68:06:89:cb:7f:3d:c4:51:c3:c9:0d:c2:68:5b:
c9:f1:a1:22:6c:0f:39:5a:51:9e:ed:de:0a:83:11:
0f:96:14:e2:7f:b4:92:1d:0a:97:e8:32:c7:60:f9:
ad:cb:87:bc:0f:e5:05:8b:4b:6b:71:5f:5a:82:69:
b5:09:8e:41:98:9f:de:af:26:d7:2b:db:60:b6:39:
7c:e2:0f:98:51:c9:6c:ad:0e:7a:5d:61:5e:6e:4d:
fc:49:62:23:92:10:81:ec:23:cb:38:50:b7:b6:b0:
b7:77:0d:1d:59:4c:0f:f4:0e:e6:ae:d8:d2:da:51:
41:54:86:a1:91:1d:74:7c:a1:00:29:62:25:0e:fd:
e8:c5:4a:f1:53:7b:56:01:6f:67:02:ab:6b:77:c0:
be:b3:57:75:50:c3:db:6d:03:e8:db:a7:54:2f:bc:
2a:94:88:5f:3e:47:b9:61:c6:5b:0d:68:a4:18:f1:
3f:df:0d:ab:54:1a:05:8c:25:0b:5c:ce:b2:80:39:
ac:fe:94:2f:64:c2:bb:f7:1c:42:e7:08:15:30:b8:
33:ba:4e:13:56:1f:82:2a:74:98:e3:5c:8b:4d:6a:
8f:14:1e:84:49:01:48:9c:14:3d:46:be:56:87:68:
8b:db:5f:79:b4:11:ce:5e:da:d5:ab:53:9e:3b:9b:
8e:03:e6:46:50:43:32:70:5a:db:08:5d:83:9f:16:
37:4b:62:be:d3:d9:ae:ad:59:92:79:cd:0c:d8:e6:
5b:b3:94:c9:03:a0:0c:d4:2c:0c:bb:d0:6d:d4:42:
61:c1:11:2c:88:63:d4:70:e4:e7:6d:f3:8b:0e:97:
14:c8:28:6a:25:07:de:75:36:27:91:71:65:84:bb:
c0:fe:8b:89:bb:bd:f2:d4:bd:a2:18:de:2d:fa:eb:
14:cb:f8:b4:63:2d:d3:58:ab:93:89:26:f9:d2:db:
cf:75:a3:8c:02:22:d5:7f:2a:2e:12:50:34:90:87:
ae:9b:b0:44:d7:9f:4d:98:47:e2:cf:8b:2b:a6:23:
77:c1:e8:0c:32:48:79:64:0c:c7:b9:b5:c3:d6:72:
d3:e9:01:c9:0e:06:01:b4:f3:ac:99:e5:b0:d0:12:
04:39:60:ee:e2:e0:4d:05:ed:70:02:22:24:c9:96:
01:59:66:ed:4b:b6:2c:e2:d3:3d:c2:52:32:84:1b:
08:db:f5:6b:6f:22:09:f0:bb:2a:54:35:c2:09:68:
c9:ab:56:19:5a:73:62:7a:a7:06:3c:43:86:ff:69:
8c:3d:27
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
34:91:00:5B:0B:15:EF:EB:E6:FC:7D:8A:85:AB:63:B4:C6:EA:3D:1E
X509v3 Authority Key Identifier:
34:91:00:5B:0B:15:EF:EB:E6:FC:7D:8A:85:AB:63:B4:C6:EA:3D:1E
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
10:2e:4c:59:e0:50:39:a6:30:b4:cf:d9:0e:8d:d9:3d:7c:04:
08:b4:fd:2d:cf:0f:eb:32:ae:21:e2:7d:83:85:68:60:20:ed:
f5:8c:bc:f2:52:8c:bd:c9:ee:2a:96:4f:9a:fd:2c:5d:59:dc:
13:d9:68:30:cc:b8:27:46:35:10:eb:87:6c:56:4c:a8:60:78:
65:f0:1f:73:b9:80:f5:5c:c6:7c:85:75:26:10:46:48:99:d2:
87:32:eb:a2:61:1e:ff:2d:7b:15:8d:e4:1e:36:9b:78:56:06:
8c:a9:13:01:49:f5:be:50:c3:cb:62:64:66:2d:1e:2f:5a:2d:
2d:fc:62:ef:89:5a:91:53:87:67:51:69:9b:c0:5c:43:04:0d:
48:2a:12:17:3d:97:ef:9a:9b:be:11:ab:0d:74:6c:44:34:a8:
d8:2d:7b:28:be:2c:ff:06:b5:69:14:39:10:96:c0:a8:43:1f:
c5:32:8b:79:92:95:19:30:b9:e4:4a:d0:35:7d:ff:ff:24:75:
1e:82:d1:7a:e4:c1:4b:11:e2:2b:b3:a3:91:c3:08:40:1e:52:
ef:af:14:ad:f0:c7:39:ca:5d:b6:6b:fc:fa:ed:2c:ed:e1:8f:
84:e7:9a:a6:21:20:60:e9:aa:cf:a9:cd:37:fc:5a:90:7a:bc:
8d:56:77:e5:1f:25:30:fb:4d:ef:fa:c2:ae:34:ac:d1:f4:0b:
4d:d0:9c:ba:86:67:1c:9e:fd:4c:8a:c2:3d:f4:91:93:45:59:
51:75:b6:0c:63:94:a0:ac:37:dc:b4:28:4f:cb:cb:43:f7:b1:
98:87:f7:3c:26:59:71:a3:ea:0e:25:10:b0:32:a0:35:34:73:
8a:da:bb:4e:0b:f8:36:d4:2a:86:98:0d:44:0c:9e:5c:59:c7:
19:13:3a:2b:ae:91:13:f9:27:5a:89:38:a0:c5:ed:e0:4a:d0:
a2:4f:c9:ee:6c:04:14:72:f3:36:73:ae:4c:9f:0d:9b:48:52:
30:3b:fd:2f:99:13:3f:e5:23:c7:31:36:16:1c:d1:6c:0a:37:
0e:ee:25:03:b1:b1:ac:03:33:10:fd:67:18:1f:b5:64:9d:51:
67:b9:d1:5a:c9:ba:90:0d:30:cd:3e:4b:a6:3a:6c:87:5d:48:
2b:4a:eb:7e:dc:d7:f9:a3:28:24:cc:47:86:9b:58:cf:bd:e6:
fa:cc:95:27:5c:47:2d:a1:e8:3b:61:d4:da:b1:2c:2c:e1:26:
a7:40:8b:86:45:c4:84:20:4f:cb:30:29:7c:1b:d5:87:82:38:
52:2c:ac:c7:55:ae:98:23:79:ed:2b:b0:1e:99:27:d9:1b:bd:
48:dd:61:6c:1e:45:a3:6d
```
发现客户使用的是一个 X.509 第三版的证书,使用 `SHA-256` 哈希算法和 `RSA` 加密算法签名证书,==公钥长度为 4096 位==。
问题出现了,正经人谁用这么长的公钥?
根据 [NIST SP 800-57](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf) 的建议,不同算法的安全性级别如下:
| **安全性级别** | **RSA 密钥长度** | **ECC 密钥长度** |
| --------- | ------------ | ------------ |
| 112 位 | 2048 位 | 224 位 |
| 128 位 | 3072 位 | 256 位 |
| 192 位 | 7680 位 | 384 位 |
| 256 位 | 15360 位 | 512 位 |
从表中可以看出RSA 4096 位位于 ECC 384 位和 512 位之间明明用ecc算法384位就能搞定的事情非得增加mcu的负担。
修改`MBEDTLS_MPI_MAX_SIZE`宏从384到512。
```c
#define MBEDTLS_MPI_MAX_SIZE 512
```
# 总结
这次的无法连接平台的问题主要是mbedtls中对于tls的握手处理把是否跳过验证的处理放到了解析证书的后面。导致即使使用`MBEDTLS_SSL_VERIFY_NONE`关闭了验证,实际上却因为`MBEDTLS_MPI_MAX_SIZE`大小不够而导致证书解析失败从而导致无法连接平台。还有就是对客户平台的不了解一开始以为客户无法提供自签名的证书也没有想到客户不是使用主流的2048位的公钥的RSA签名。