ESP8266 RTOS 下 openssl 证书及使用和 fragment 介绍

1 简介

本文主要介绍基于 ESP8266_RTOS_SDK 的 SSL 加密使用方法,将分别介绍 ESP8266 作为 SSL client 和 SSL server 的使用方法。

SSL 功能需要占用大量内存,请开发者在上层应用程序确保内存足够。在将 SSL fragment 设置为 8KB 以及证书用 private key RSA2048 的情况下, SSL 双向认证功能需要 30KB 的空间,由于服务器的证书大小不同,所需空间可能更大。

为使 SSL/TLS 更加安全,ESP8266_RTOS_SDK openssl 默认仅支持 RSA2048 以及以上的 private key 生成的证书。 见Asymmetric algorithm key lengths。

本文所用的 SDK:ESP8266_RTOS_SDK: Version 1.5.0

2 准备工作

2.1 openssl 库

本示例可以用两块 ESP8266 分别作为 openssl client 以及 server,也可以用一块 ESP8266 作为 client/server, 用电脑作为 server/client。如果用电脑作为 client/server,需安装 openssl 库:

sudo apt-get install openssl

2.2 证书生成

本文中所用的证书脚本为gencrt.sh genheader.sh,这两个脚本会生成 ca.crt,client.crt,client.key,server.crt,server.key,ssl_client_crt.h,ssl_server_crt.h。

ca.crt 为 CA 证书,用于校验 server.crt 以及 client.crt。
ssl_client_crt.h 为 ca.crt、client.crt、client.key 生成的数组文件。
ssl_server_crt.h 为 ca.crt、server.crt、server.key 生成的数组文件。

如果用户想使用自己的证书,请先阅读SSL-TLS 双向认证(一) – SSL-TLS工作原理。

3 ESP8266 作为 SSL client

在 Ubuntu 端运行 openssl s_server -CAfile ca.crt -cert server.crt -key server.key -verify 1 -tls1_1 -accept 443 其中 ca.crt、server.crt 以及 server.key 为附件 gencrt.sh 生成的证书。

下载源码。

修改 openssl_demo.c 的以下两行,将地址改为电脑 IP 地址:

#define OPENSSL_DEMO_TARGET_NAME "192.168.3.196"

#define OPENSSL_DEMO_TARGET_TCP_PORT 443

修改 user_config.h 的以下两行,改为本地可用 Wi-Fi:

#define SSID "HUAWEI001"

#define PASSWORD ""

让电脑与 ESP8266 处于同一局域网内,编译下载固件。

4 ESP8266 作为 SSL server

下载源码。

修改 user_config.h 的以下两行,改为本地可用 Wi-Fi:

#define SSID "HUAWEI001"

#define PASSWORD ""

编译下载固件,并让电脑与 ESP8266 处于同一局域网内。

根据 ESP8266 串口 log 获得 ESP8266 的 IP 地址 192.168.3.6。

在Ubuntu端运行 openssl s_client -CAfile ca.crt -cert client.crt -key client.key -verify 1 -tls1_1 -host 192.168.3.6 -port 443

192.168.3.6 为 ESP8266 的 IP 地址 ca.crt client.crt ca.key 为附件 gencrt.sh 生成的证书。

5 软件接口

本节主要介绍 openssl 证书认证相关接口,更多软件接口介绍,请参考 ESP8266 编程手册 ESP8266__RTOS_SDK_API Reference.pdf。

5.1 头文件

#include "openssl/ssl.h"

5.2 函数

5.2.1 SSL_CTX* SSL_CTX_new(const SSL_METHOD *method)

功能:根据用户所需要的 SSL/TLS 协议版本创建 SSL context。

返回:已经设定好的 SSL context。

参数: const SSL_METHOD *method

    设置用于数据交换协议版本。

    TLSv1_client_method
    TLSv1_1_client_method
    SSLv3_client_method
    SSLv23_client_method
    TLSv1_server_method
    TLSv1_1_server_method
    SSLv3_server_method
    SSLv23_server_method

5.2.2 X509* d2i_X509(X509 **cert, const unsigned char *buffer, long len)

功能:将crt证书文件转换为 _x509_ctx 格式的结构体。

返回:crt文件转换后的 X509 结构指针。

参数:

X509 **cert: crt 文件转换后的 X509 格式的 context ,需要在外部分配存储空间,建议传入 NULL。。

const unsigned char *buffer: 字符串数组,crt 文件原始格式。

long len: buffer 长度。

5.2.3 int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)

功能:添加用于校验对端的 CA 证书,ESP8266 作为 server 时也是用此函数添加 CA 证书。

返回:0-失败, 1-成功

参数:

SSL_CTX *ctx: SSL context。

X509 *x: CA 证书转换后的 X509 结构指针。

5.2.4 int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d)

功能:添加 client/server 本地证书。

返回:0-失败, 1-成功

参数:

SSL_CTX *ctx: SSL context。

len: cert长度。

const unsigned char *d: cert 数据。

5.2.5 int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d, long len)

功能:添加对应 4.4 节证书的本地私钥。

返回:0-失败, 1-成功

参数:

type: 未使用,可传入 NULL。

SSL_CTX *ctx: SSL context。

len: private key 长度。

const unsigned char *d: private key 数据。

5.2.6 void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *))

功能:设定是否校验方式,比如是否校验对端证书。

参数:

SSL_CTX *ctx: SSL context。

int mode: 校验方式,可以设置为 SSL_VERIFY_NONESSL_VERIFY_PEER

int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx): 校验结果,用户自定义回调函数。

5.2.7 void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len)

功能:设定SSL fragment 长度,参见第 6 节 fragment 介绍。

参数:

SSL_CTX *ctx: SSL context。

size_t len: 根据证书长度以及传递秘文长度设定。

6 fragment 介绍

fragment 是指 openssl 在建立SSL/TLS连接握手过程中证书验证以及交换数据时加解密数据的缓存大小。

TLS 协议支持的 fragment 最大是 16K(RFC2246)。由于嵌入式系统RAM资源比较珍贵(ESP8266 本身 RAM 空间比较小),以及嵌入式系统在正常使用时很少用到大文件加解密,所以 ESP8266_RTOS_SDK 以及 ESP8266_NONOS_SDK 中开放 fragment 设定接口 SSL_CTX_set_default_read_buffer_len 和 espconn_secure_set_size,以节省资源。

fragment 大小主要由芯片 RAM 大小、证书、传输单笔数据(对这笔数据整体进行加密)的最大长度决定(传输单笔数据的最大长度 < fragment < RAM 大小)。

ESP8266_RTOS_SDK(openssl lib) 中设定范围为 2048 - 8192 Bytes

在传输的单笔数据较小的情况下,证书大小主要由私钥长度决定,使用不同的私钥长度生成的证书所需的 fragment 大小建议值:

私钥长度 fragment 推荐值
RSA2048 2048
RSA3072 3072
RSA4096 4096

你可能感兴趣的:(SSL/TLS)