ESP8266 RTOS 下 wolfSSL 内存开销分析和测试方法

1. 摘要

本文主要列举实际测试的 wolfSSL 在各种配置参数下,SSL 握手的内存开销和相应的测试方法。

2. 测试版本和方法

ESP8266 SDK 版本:ESP8266_RTOS_SDK - c7b64043

git clone https://github.com/espressif/ESP8266_RTOS_SDK.git

git checkout c7b64043

wolfSSL 版本: https://github.com/wolfSSL/wolfssl/releases/tag/v3.12.2-stable

下载完毕后请参照ESP8266 wolfSSL 入门指南搭建工程。

测试思路是在每次内存分配就记录剩余的内存,并在最终打印握手过程中的最小剩余内存以及最终剩余内存。代码修改方法如下:

  1. 找到 malloc 的具体实现函数pvPortMalloc,位于 ESP8266_RTOS_SDK/third_party/freertos/heap_4.c,在里面添加全局统计变量:

    size_t s_mem_mark;
  2. 添加复位 API 和 获取 API:

    size_t get_mem_mark(void)
    {
        return s_mem_mark;
    }
    
    void reset_mem_mark(void)
    {
        s_mem_mark = (size_t)-1;
    }
  3. 添加统计功能,在 pvPortMalloc 函数的返回结果(return pvReturn)之前添加如下代码:

    if (pvReturn) {
        extern size_t system_get_free_heap_size(void);
    
        size_t mem_size = system_get_free_heap_size();
        if (mem_size < s_mem_mark)
            s_mem_mark = mem_size;
    }
  4. 直接运行位于 ESP8266_RTOS_SDK/third_party 下的脚本 make_lib.sh 生成新的 libfreertos.a,命令如下:

    ./make_lib.sh freertos

测试代码代码修改如下:

  1. 找到 esp8266-wolfssl/blob/master/user/wolfssl_client/wolfssl_client.c,添加全局API 声明:

    extern size_t get_mem_mark(void);
    extern void reset_mem_mark(void);
    extern size_t system_get_free_heap_size(void);
  2. ret = wolfSSL_Init(); 之前添加:

    reset_mem_mark();
    printf("start heap %d\n", system_get_free_heap_size());
  3. 在以下代码

    ret = wolfSSL_connect(ssl);
    if (!ret) {
        goto failed4;
    }

    下方添加:

    printf("min heap %d\n", get_mem_mark());
    printf("end heap %d\n", system_get_free_heap_size());

    SSL server 代码部分也做类似的修改。

通过以上的修改,可以统计出 SSL 握手之前的内存,握手中系统剩余的最小内存和握手结束以后的内存。为了测试方便可以用2个 ESP8266 模组进行测试,1个做 server,1个做 client,通过 user_config.h 配置 WIFI 和连接参数进行测试。

3. 测试数据

本章主要列举各种配置参数和具体测试数据,由于 wolfSSL 宏观上不需要用户自己配置 fragment,所以也就不做相关的测试了,而且默认支持最大 RSA4096 计算,所以也就不做秘钥大于4096的测试。

3.1 client 模式

本节具体列举了 client 模式下非认证,本地认证,双向认证模式下,配置各种大小证书所消耗的内存。

3.1.1 非认证证书测试

测试非认证模式下各证书加秘钥总大小和内存开销的关系。

3.1.1.1.数据

server 使用 RSA2048 — RSA8192 的秘钥和生成的证书。

证书和秘钥/B 开始 最小 最大 最大消耗/B 最后消耗/B
2936 35152 19584 31736 15568 3416
4065 35152 16944 31736 18208 3416
5195 35152 14296 31736 20856 3416

3.1.2 单向认证证书测试

测试单向认证模式下各证书加秘钥总大小和内存开销的关系。

3.1.2.1 数据

server 使用 RSA2048 - RSA8192 的秘钥和生成的证书。

证书和秘钥/B 开始 最小 最大 最大消耗/B 最后消耗/B
4197 35832 19120 32008 16712 3824
5679 35480 16480 31528 19000 3952
7155 35128 13512 31040 21616 4088

3.1.3 双向认证证书测试

测试双向认证模式下各证书加秘钥大小和内存开销的关系。

3.1.3.1 数据

server 使用 RSA2048 — RSA8192 的秘钥和生成的证书,以下表格首项为 client 和 server 端认证证书,证书和秘钥的总和。

证书和秘钥/B 开始 最小 最大 最大消耗/B 最后消耗/B
8394 35320 10192 28544 25128 6776
11358 33680 2992 25800 30688 7880

3.2 server 模式

本节具体列举了 server 模式下非认证模式,双向认证模式和配置各种大小的证书所消耗的内存。

3.2.1 非认证证书测试

测试非认证模式下各证书加秘钥大小和内存开销的关系。

3.2.1.1 数据

server 使用 RSA2048 — RSA8192 的秘钥和生成的证书,以下首项为 server 端证书和秘钥的总和。

证书和秘钥/B 开始 最小 最大 最大消耗/B 最后消耗/B
2965 36632 13368 26184 23264 10448
4097 35592 7352 23896 28240 11696

3.2.2 双向认证证书测试

测试双向认证模式下各证书加秘钥大小和内存开销的关系。

3.2.2.1 数据

server 使用 RSA2048 — RSA8192 的秘钥和生成的证书,以下首项为 server 端证书和秘钥的总和。

证书和秘钥/B 开始 最小 最大 最大消耗/B 最后消耗/B
4226 35336 11688 24488 23648 10848
5729 33848 5192 21728 28656 12120

4. 帮助

5. 附件

cert.sh

#!/bin/bash

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

ROOT_SUBJECT="/C=C1/ST=JS1/L=WX1/O=ESP1/OU=ESP1/CN=Server1 CA/emailAddress=ESP1"
LEVEL2_SUBJECT="/C=C2/ST=JS22/L=WX22/O=ESP22/OU=ESP22/CN=Server22 CA/emailAddress=ESP22"
LEVEL3_SUBJECT="/C=C3/ST=JS333/L=WX333/O=ESP333/OU=ESP333/CN=Server333 CA/emailAddress=ESP333"

SERVER_CERT_NAME="RootCA.crt"
SERVER_KEY_NAME="root-key.key"

CLIENT_CERT_NAME="RootCA.crt"
CLIENT_KEY_NAME="root-key.key"

KEY_BITS="4096"

echo "create root CA key"
openssl genrsa -out root-key.key $KEY_BITS
echo ----------------------
echo "create root cert request"
openssl req -new -key root-key.key -out root-req.csr -text -subj $ROOT_SUBJECT
echo ----------------------
echo "create root self sign cert"
openssl x509 -req -in root-req.csr -out RootCA.crt -sha1 -signkey root-key.key -days 3650 -text -extfile openssl.cnf -extensions v3_ca

echo "create 2 level cert key"
openssl genrsa -out root-mid.key $KEY_BITS
echo ----------------------
echo "create 2 level cert csr"
openssl req -new -key root-mid.key -out root-mid.csr -text -subj $LEVEL2_SUBJECT
echo ----------------------
echo "sign with root-crt"
openssl x509 -req -in root-mid.csr -CA RootCA.crt -CAkey root-key.key -CAcreateserial -days 3650 -out RootMid.crt -text -extfile openssl.cnf -extensions v3_ca

echo "create 3 level cert key"
openssl genrsa -out server.key $KEY_BITS
echo "create 3 level cert csr"
openssl req -new -key server.key -out server.csr -text -subj $LEVEL3_SUBJECT
echo "sign with level2 cert-crt"
openssl x509 -req -in server.csr -CA RootMid.crt -CAkey root-mid.key -CAcreateserial -days 3560 -out Server.crt -text -extfile openssl.cnf -extensions v3_ca

echo ""
echo ----------------------
echo "server uses certification " $SERVER_CERT_NAME " and key " $SERVER_KEY_NAME
echo "client uses certification " $CLIENT_CERT_NAME " and key " $CLIENT_KEY_NAME

rm *.csr *.srl

IFS=$SAVEIFS

openssl.cnf

################################################################ 
# openssl example configuration file. 
# This is mostly used for generation of certificate requests. 
################################################################# 
[ ca ] 
default_ca= CA_default          # The default ca section 
################################################################# 

[ CA_default ] 

dir=~/tmp/cert                   # Where everything is kept 
certs=$dir                       # Where the issued certs are kept 
crl_dir= $dir/crl                # Where the issued crl are kept 
database= $dir/index.txt         # database index file 
new_certs_dir= $dir/new_certs    # default place for new certs 
certificate=$dir/CA/OrbixCA      # The CA certificate 
serial= $dir/serial              # The current serial number 
crl= $dir/crl.pem                # The current CRL 
private_key= $dir/CA/OrbixCA.pk  # The private key 
RANDFILE= $dir/.rand             # private random number file 
default_days= 365                # how long to certify for 
default_crl_days= 30             # how long before next CRL 
default_md= md5                  # which message digest to use 
preserve= no                     # keep passed DN ordering 

# A few different ways of specifying how closely the request should 
# conform to the details of the CA 

policy= policy_match            # For the CA policy 

[ policy_match ]  
countryName= match 
stateOrProvinceName= match 
organizationName= match 
organizationalUnitName= optional 
commonName= supplied 
emailAddress= optional 

# For the `anything' policy 
# At this point in time, you must list all acceptable `object' 
# types 

[ policy_anything ] 
countryName = optional 
stateOrProvinceName= optional 
localityName= optional 
organizationName = optional 
organizationalUnitName = optional 
commonName= supplied 
emailAddress= optional 

[ req ] 
default_bits = 1024 
default_keyfile= privkey.pem 
distinguished_name = req_distinguished_name 
attributes = req_attributes 
x509_extensions = v3_ca

[ req_distinguished_name ] 
countryName= Country Name (2 letter code) 
countryName_min= 2 
countryName_max = 2 
stateOrProvinceName= State or Province Name (full name) 
localityName = Locality Name (eg, city) 
organizationName = Organization Name (eg, company) 
organizationalUnitName  = Organizational Unit Name (eg, section) 
commonName = Common Name (eg. YOUR name) 
commonName_max = 64 
emailAddress = Email Address 
emailAddress_max = 40 

[ req_attributes ] 
challengePassword = A challenge password 
challengePassword_min = 4 
challengePassword_max = 20 
unstructuredName= An optional company name

[ v3_ca ]
basicConstraints = CA:true

猜你喜欢

转载自blog.csdn.net/espressif/article/details/79603890
今日推荐