mbedtls(not finished)
mbedtls
mbedTLS 建立安全通信连接需要经过以下几个步骤:
- 初始化 SSL/TLS 上下文
- 建立 SSL/TLS 握手
- 发送、接收数据
- 交互完成,关闭连接
其中,最关键的步骤就是 SSL/TLS 握手 连接的建立,这里需要进行证书校验。
#define SERVER_HOST "example.com" // 目标服务器
#define SERVER_PORT "443" // HTTPS 端口
int ret;mbedtls_net_context server_fd;mbedtls_entropy_context entropy;mbedtls_ctr_drbg_context ctr_drbg;mbedtls_ssl_context ssl;mbedtls_ssl_config conf;mbedtls_x509_crt cacert;// 初始化 mbedTLS 组件mbedtls_net_init(&server_fd);mbedtls_ssl_init(&ssl);mbedtls_ssl_config_init(&conf);mbedtls_x509_crt_init(&cacert);mbedtls_ctr_drbg_init(&ctr_drbg);mbedtls_entropy_init(&entropy);// 1. 设置随机数生成器// &ctr_drbg &entropyif ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, nullptr, 0)) != 0) {std::cerr << "mbedtls_ctr_drbg_seed failed: " << ret << std::endl;return -1;}// 2. 加载 CA 证书//&cacertret = mbedtls_x509_crt_parse_file(&cacert, "ca_cert.pem");if (ret < 0) {std::cerr << "Failed to load CA certificate: " << ret << std::endl;return -1;}// 3. 连接服务器 只是初始化tcp连接,还没有进行握手捏std::cout << "Connecting to " << SERVER_HOST << ":" << SERVER_PORT << "..." << std::endl;if ((ret = mbedtls_net_connect(&server_fd, SERVER_HOST, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {std::cerr << "Connection failed: " << ret << std::endl;return -1;}// 4. 配置 SSL// mbedtls_ssl_config_defaults(&conf, // MBEDTLS_SSL_IS_CLIENT, // 1. 角色// MBEDTLS_SSL_TRANSPORT_STREAM, // 2. 传输类型// MBEDTLS_SSL_PRESET_DEFAULT); // 3. 预设配置if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {std::cerr << "SSL config failed: " << ret << std::endl;return -1;}// &conf mbedtls_ssl_conf_authmode() 设置证书验证模式 mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); // 必须验证证书//mbedtls_ssl_conf_rng() 绑定随机数生成器mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);// mbedtls_ssl_conf_ca_chain() 绑定 CA 证书mbedtls_ssl_conf_ca_chain(&conf, &cacert, nullptr);// 5. 绑定 SSL 到连接// 把conf绑定到ssl中mbedtls_ssl_setup(&ssl, &conf);// 开始握手,使用ssl和server_fdmbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, nullptr);// 6. SSL/TLS 握手std::cout << "Performing SSL/TLS handshake..." << std::endl;while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {std::cerr << "Handshake failed: " << ret << std::endl;return -1;}// 7. 验证服务器证书if ((ret = mbedtls_ssl_get_verify_result(&ssl)) != 0) {std::cerr << "Certificate verification failed!" << std::endl;return -1;}std::cout << "Certificate verification successful!" << std::endl;// 8. 发送 HTTP 请求const char *http_request = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";ret = mbedtls_ssl_write(&ssl, (const unsigned char *)http_request, strlen(http_request));if (ret < 0) {std::cerr << "Failed to send data: " << ret << std::endl;return -1;}// 9. 读取服务器响应char buffer[4096];memset(buffer, 0, sizeof(buffer));ret = mbedtls_ssl_read(&ssl, (unsigned char *)buffer, sizeof(buffer) - 1);if (ret < 0) {std::cerr << "Failed to receive data: " << ret << std::endl;return -1;}std::cout << "Server response:\n" << buffer << std::endl;// 10. 关闭连接mbedtls_ssl_close_notify(&ssl);mbedtls_net_free(&server_fd);mbedtls_ssl_free(&ssl);mbedtls_ssl_config_free(&conf);mbedtls_x509_crt_free(&cacert);mbedtls_ctr_drbg_free(&ctr_drbg);mbedtls_entropy_free(&entropy);return 0;
}
嵌入式设备的资源限制(如 RAM、Flash、CPU 性能)通常要求精简 mbedTLS。以下是常见的修改方向:
- 禁用不必要的加密算法
禁用 RSA(如果只用 ECC)
- 减少协议版本支持
默认支持 TLS 1.0、1.1、1.2、1.3,但嵌入式设备可能只用特定版本。
- 内存优化
调整缓冲区大小:如 #define MBEDTLS_SSL_MAX_CONTENT_LEN(默认 16KB,可减到 4KB 或更小,视应用需求)。禁用动态内存分配:启用 #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS 和 #define MBEDTLS_PLATFORM_MEMORY,使用自定义内存分配函数。
- 调整缓冲区大小:如 #define MBEDTLS_SSL_MAX_CONTENT_LEN(默认 16KB,可减到 4KB 或更小,视应用需求)。
- 禁用动态内存分配:启用 #define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS 和 #define MBEDTLS_PLATFORM_MEMORY,使用自定义内存分配函数。
- 调试与日志
https的修改:
定义MBEDTLS_PLATFORM_MEMORY,采用动态自定义的PLATFORM
启用 MBEDTLS_PLATFORM_MEMORY 并定义宏
- 宏定义:
- MBEDTLS_PLATFORM_CALLOC_MACRO:指定自定义的 calloc 函数。
- MBEDTLS_PLATFORM_FREE_MACRO:指定自定义的 free 函数。
- 效果:
在编译时静态绑定你的自定义内存分配函数,而不是在运行时设置。
仅启用 MBEDTLS_PLATFORM_MEMORY(不定义宏)
- 效果:
mbedTLS 会提供一个运行时接口 mbedtls_platform_set_calloc_free(),让你在程序运行时动态设置自定义的 calloc() 和 free() 函数指针。 - 使用场景:
如果你的系统需要在运行时根据条件选择不同的内存分配策略(例如在不同硬件或模式下切换内存池),这种方式很合适。