如何编写mbedTLS最小DTLS代码?握手返回-0x7100错误求助
问题排查与修复方案
核心问题分析
返回错误 -0x7100(MBEDTLS_ERR_SSL_BAD_INPUT_DATA)是由于传入函数的参数无效或配置顺序错误导致的,具体问题如下:
1. 配置函数调用顺序错误
mbedtls_ssl_config_defaults 会重置整个配置结构体为默认值,因此在它之前调用的配置函数(如mbedtls_ssl_conf_ciphersuites、mbedtls_ssl_conf_transport)都会被覆盖,导致配置无效。
2. mbedtls_ssl_set_client_transport_id 参数错误
该函数需要传入二进制格式的客户端传输标识(如IPv4地址是4字节的二进制数据),而不是字符串形式的IP地址。传入字符串"192.168.8.201"和长度13属于无效参数,直接触发错误。
3. mbedtls_ssl_conf_ca_chain 使用错误
conf_ca_chain 用于指定验证客户端证书的可信CA链,而非服务器自身证书。你设置的srvcert.next是服务器证书的后续链(通常为NULL),这属于无效输入。
修复后的代码
修正后的 initDtls 函数
int initDtls(void) { int i; printf("InitDtls\r\n"); mbedtls_ssl_config_init(&conf); // 先调用默认配置,再覆盖自定义设置 i = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT); if(i) printf("mbedtls_ssl_config_defaults, error %d\r\n", i); // 设置加密套件 mbedtls_ssl_conf_ciphersuites(&conf, mbedtls_ssl_list_ciphersuites()); // 设置客户端验证模式(可选) mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); // 初始化并加载服务器证书和私钥 mbedtls_x509_crt_init(&srvcert); mbedtls_pk_init(&pkey); i = mbedtls_x509_crt_parse_file(&srvcert, "server.crt"); if(i) printf("mbedtls_x509_crt_parse_file, error %d\r\n", i); i = mbedtls_pk_parse_keyfile(&pkey, "server.key", NULL); if(i) printf("mbedtls_pk_parse_keyfile, error %d\r\n", i); // 设置服务器自身证书(正确用法) i = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey); if(i) printf("mbedtls_ssl_conf_own_cert, error %d\r\n", i); // 若不需要验证客户端证书,可省略ca_chain配置;若需要,传入可信CA证书链 // mbedtls_ssl_conf_ca_chain(&conf, trusted_ca_chain, NULL); // 设置DTLS握手超时和重试次数(必须配置,否则握手可能失败) mbedtls_ssl_conf_dtls_timeout(&conf, 5000); // 5秒超时 mbedtls_ssl_conf_dtls_retries(&conf, 3); // 重试3次 return 0; }
修正后的 acceptDtlsClient 函数
void* acceptDtlsClient(Session* session) { int i; printf("Accept\r\n"); mbedtls_ssl_context* ssl = new mbedtls_ssl_context; mbedtls_ssl_init(ssl); i = mbedtls_ssl_setup(ssl, &conf); if(i) printf("mbedtls_ssl_setup: %d\r\n", i); // 移除错误的set_client_transport_id调用,或改为传入二进制IP(示例) // 正确的二进制IPv4地址示例:192.168.8.201 -> 0xC0 0xA8 0x08 0xC9 // uint8_t client_ip[] = {0xC0, 0xA8, 0x08, 0xC9}; // i = mbedtls_ssl_set_client_transport_id(ssl, client_ip, sizeof(client_ip)); // if(i) printf("mbedtls_ssl_set_client_transport_id: %d\r\n", i); // 设置BIO,Session包含客户端地址,由dataSend/Recv处理发送目标 mbedtls_ssl_set_bio(ssl, session, dataSend, dataRecv, NULL); // DTLS服务器握手需要先收到客户端的ClientHello,确保你的Session已经接收到初始报文 i = mbedtls_ssl_handshake(ssl); printf("Handshake2: %d\r\n", i); return (void*)ssl; }
额外注意事项
- DTLS服务器握手流程:DTLS服务器必须先接收客户端发送的
ClientHello报文,再创建SSL上下文并执行握手。如果你的代码在未收到任何客户端数据时就调用mbedtls_ssl_handshake,会导致握手无法进行(但当前错误是参数问题,修复后需确保这一点)。 - BIO函数实现:
dataSend和dataRecv需要正确处理UDP报文的发送和接收,确保数据能正确传递到客户端和从客户端获取。 - 资源释放:使用完SSL上下文后,记得调用
mbedtls_ssl_free释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Anna
相关产品推荐
相关产品推荐

