转:mbedtls学习2.mbedtls从0使用指南
1.使用指南
這里主要介紹 mbedtls 程序的基本使用流程,并針對使用過程中經(jīng)常涉及到的結(jié)構(gòu)體和重要 API 進行簡要說明。
mbedtls 的基本工作流程如下所示:
- 初始化 SSL/TLS 上下文
- 建立 SSL/TLS 握手
- 發(fā)送、接收數(shù)據(jù)
- 交互完成,關(guān)閉連接
menuconfig 配置說明
獲取 mbedtls 軟件包或者修改用戶配置都需要使用 menuconfig。需要用戶打開 ENV 工具,并將目錄切換到您所用的 BSP 目錄,使用 menuconfig 命令打開配置界面。
在 RT-Thread online packages → security packages 中選擇 mbedtls 軟件包,操作界面如下圖所示:
詳細(xì)的配置介紹如下所示:
RT-Thread online packages --->security packages --->Select Root Certificate ---> # 選擇證書文件[*] mbedtls: An portable and flexible SSL/TLS library # 打開 mbedtls 軟件包[*] Store the AES tables in ROM # 將 AES 表存儲在 ROM 中(2) Maximum window size used # 用于點乘的最大“窗口”大小(2-7)(3584) Maxium fragment length in bytes # 配置數(shù)據(jù)幀大小[*] Enable a mbedtls client example # 開啟 mbedtls 測試?yán)蘙 ] Enable Debug log output # 開啟調(diào)試 log 輸出version (latest) ---> # 選擇軟件包版本,默認(rèn)為最新版本
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Using all default CA配置選項會將certs/default目錄下的所有預(yù)置證書加入編譯,將占用很大的內(nèi)存Using user CA配置選項允許用戶將自己需要的證書文件加入編譯,需要用戶將證書文件拷貝到certs根目錄
選擇合適的配置項后,使用 pkgs --update 命令下載軟件包并更新用戶配置。
功能配置說明
mbedtls 功能模塊的開啟與關(guān)閉定義在 mbedtls/config.h 和 ports/inc/tls_config.h 文件中
mbedtls/config.h 是 mbedtls 源碼里提供的配置文件,ports/inc/tls_config.h 是 RT-Thread 基于 mbedtls 源碼中的配置文件進行的裁剪和適配。
最終,用戶使用的是 RT-Thread 提供的配置文件 ports/inc/tls_config.h。
用戶可以通過文件中的宏來使能或失能部分不需要使用的功能模塊,從而將 mbedtls 配置到合適的尺寸。
證書配置說明
- 預(yù)置的 CA 證書文件存放在
certs/default目錄中 - 用戶增加的 CA 證書文件存放在
certs根目錄中
certs/default 目錄中已經(jīng)包含了大多數(shù) CA 根證書,如果您使用的根證書不在該文件夾內(nèi),需要用戶將自己的 PEM 格式的 CA 證書拷貝 certs 根目錄下。(僅支持 PEM 格式證書,不支持 DER 格式證書)。
該證書文件中已經(jīng)包含了大多數(shù) CA 根證書,,參考后邊的 添加新證書 章節(jié)。
初始化 TLS 會話
typedef struct MbedTLSSession {char* host;char* port;<span class="token keyword cye-lm-tag">unsigned</span> <span class="token keyword cye-lm-tag">char</span> <span class="token operator cye-lm-tag">*</span>buffer<span class="token punctuation cye-lm-tag">;</span> <span class="token comment cye-lm-tag">// 公用數(shù)據(jù)緩沖區(qū)</span> size_t buffer_len<span class="token punctuation cye-lm-tag">;</span> <span class="token comment cye-lm-tag">// 緩沖區(qū)大小</span>mbedtls_ssl_context ssl<span class="token punctuation cye-lm-tag">;</span> <span class="token comment cye-lm-tag">// 保存 ssl 基本數(shù)據(jù)</span> mbedtls_ssl_config conf<span class="token punctuation cye-lm-tag">;</span> <span class="token comment cye-lm-tag">// 保存 ssl 配置信息</span> mbedtls_entropy_context entropy<span class="token punctuation cye-lm-tag">;</span> <span class="token comment cye-lm-tag">// 保存 ssl 熵配置</span> mbedtls_ctr_drbg_context ctr_drbg<span class="token punctuation cye-lm-tag">;</span> <span class="token comment cye-lm-tag">// 保存隨機字節(jié)發(fā)生器配置</span> mbedtls_net_context server_fd<span class="token punctuation cye-lm-tag">;</span> <span class="token comment cye-lm-tag">// 保存文件描述符</span> mbedtls_x509_crt cacert<span class="token punctuation cye-lm-tag">;</span> <span class="token comment cye-lm-tag">// 保存認(rèn)證信息</span>} MbedTLSSession;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
MbedTLSSession 用于保存建立 TLS 會話連接時的配置信息,在 TLS 上下文中傳遞使用。用戶在使用建立 TLS 會話前,必須定義一個存儲會話內(nèi)容的結(jié)構(gòu)體,如下所示:
static MbedTLSSession *tls_session = RT_NULL;
tls_session = (MbedTLSSession *)malloc(sizeof(MbedTLSSession));
tls_session->host = strdup(MBEDTLS_WEB_SERVER);
tls_session->port = strdup(MBEDTLS_WEB_PORT);
tls_session->buffer_len = MBEDTLS_READ_BUFFER;
tls_session->buffer = malloc(tls_session->buffer_len);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
這里需要設(shè)置 SSL/TLS 服務(wù)器的 host 和 port,以及數(shù)據(jù)接收 buffer 等配置。
初始化 SSL/TLS 客戶端
應(yīng)用程序使用 mbedtls_client_init 函數(shù)初始化 TLS 客戶端。
初始化階段按照 API 參數(shù)定義傳入相關(guān)參數(shù)即可,主要用來初始化網(wǎng)絡(luò)接口、證書、SSL 會話配置等 SSL 交互必須的一些配置,以及設(shè)置相關(guān)的回調(diào)函數(shù)。
示例代碼如下所示:
char *pers = "hello_world"; // 設(shè)置隨機字符串種子
if((ret = mbedtls_client_init(tls_session, (void *)pers, strlen(pers))) != 0)
{rt_kprintf("MbedTLSClientInit err return : -0x%x\n", -ret);goto __exit;
}
- 1
- 2
- 3
- 4
- 5
- 6
實際調(diào)用的 mbedtls 庫函數(shù)如下所示:
初始化 SSL/TLS 客戶端上下文
應(yīng)用程序使用 mbedtls_client_context 函數(shù)配置客戶端上下文信息,包括證書解析、設(shè)置主機名、設(shè)置默認(rèn) SSL 配置、設(shè)置認(rèn)證模式(默認(rèn) MBEDTLS_SSL_VERIFY_OPTIONAL)等。
示例代碼如下所示:
if((ret = mbedtls_client_context(tls_session)) < 0)
{rt_kprintf("MbedTLSCLlientContext err return : -0x%x\n", -ret);goto __exit;
}
- 1
- 2
- 3
- 4
- 5
建立 SSL/TLS 連接
使用 mbedtls_client_connect 函數(shù)為 SSL/TLS 連接建立通道。這里包含整個的握手連接過程,以及證書校驗結(jié)果。
示例代碼如下所示:
if((ret = mbedtls_client_connect(tls_session)) != 0)
{rt_kprintf("MbedTLSCLlientConnect err return : -0x%x\n", -ret);goto __exit;
}
- 1
- 2
- 3
- 4
- 5
讀寫數(shù)據(jù)
向 SSL/TLS 中寫入數(shù)據(jù)
示例代碼如下所示:
static const char *REQUEST = "GET https://www.howsmyssl.com/a/check HTTP/1.0\r\n""Host: www.howsmyssl.com\r\n""User-Agent: rtthread/3.1 rtt\r\n""\r\n";
while((ret = mbedtls_client_write(tls_session, (const unsigned char *)REQUEST,strlen(REQUEST))) <= 0)
{
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
{
rt_kprintf(“mbedtls_ssl_write returned -0x%x\n”, -ret);
goto __exit;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
從 SSL/TLS 中讀取數(shù)據(jù)
示例代碼如下所示:
memset(tls_session->buffer, 0x00, tls_session->buffer_len);
ret = mbedtls_client_read(tls_session, (unsigned char *)tls_session->buffer,len);
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret ==MBEDTLS_ERR_SSL_WANT_WRITE)continue;
if(ret MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
break;
if(ret < 0)
{
rt_kprintf(“mbedtls_ssl_read returned -0x%x\n”, -ret);
break;
}
if(ret 0)
{
rt_kprintf(“connection closed\n”);
break;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
注意,如果讀寫接口返回了一個錯誤,必須關(guān)閉連接。
關(guān)閉 SSL/TLS 客戶端連接
客戶端主動關(guān)閉連接或者因為異常錯誤關(guān)閉連接,都需要使用 mbedtls_client_close 關(guān)閉連接并釋放資源。
示例代碼如下所示:
mbedtls_client_close(tls_session);
- 1
- 2
mbedtls 使用范式
參考示例程序 samples/tls_app_test.c。
添加新證書
CA 證書有兩種常用格式 PEM 格式 和 DER 格式,目前 RT-Thread mbedtls 僅支持 PEM 格式 的證書文件。
-
PEM 格式證書PEM 格式證書 通常是以 .pem 和 .cer 后綴名結(jié)尾的文件。
使用文本編輯器打開后,文件內(nèi)容以
-----BEGIN CERTIFICATE-----開頭,以-----END CERTIFICATE-----結(jié)尾。 -
DER 格式證書DER 格式證書 是二進制文件類型。
根證書樣式
雙擊 .cer 后綴名結(jié)尾的 CA 文件(Windows系統(tǒng))可以看到證書的簽發(fā)機構(gòu)和有效期,如下圖所示:
PEM 格式 格式的證書文件內(nèi)容內(nèi)容樣式如下所示:
-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
獲取根證書
-
直接向服務(wù)商索取
向服務(wù)商索取
base64 編碼 X.509編碼的 PEM 格式 證書文件。 -
從服務(wù)商網(wǎng)站導(dǎo)出
-
瀏覽器打開服務(wù)商網(wǎng)站,以
https://www.rt-thread.org/為例 -
點擊瀏覽器地址欄的
安全,然后點擊證書
-
查看證書詳細(xì)信息
-
根證書導(dǎo)出向?qū)?br />
-
選擇導(dǎo)出 Base64 編碼證書
-
選擇證書存儲位置
-
完成證書文件導(dǎo)出
完成證書導(dǎo)出,假設(shè)證書文件名為 USER_ROOT_CA.cer。
-
導(dǎo)入證書
- 使用文本編輯器打開上個步驟導(dǎo)出的根證書文件 USER_ROOT_CA.cer
- 拷貝 USER_ROOT_CA.cer 文件到
certs根目錄 - 使用
scons命令重新編譯
注:
scons 命令編譯后,會自動將證書文件拷貝到 const char mbedtls_root_certificate[] 數(shù)組中。
2.工作原理
mbedtls** 軟件包是對 SSL/TLS 協(xié)議的實現(xiàn)。SSL(安全套接層)和 TLS(傳輸安全層)均是為了保證傳輸過程中信息的安全,是在明文傳輸基礎(chǔ)上進行的加密,然后以密文的形式傳輸數(shù)據(jù)。
mbedTLS 建立安全通信連接需要經(jīng)過以下幾個步驟:
- 初始化 SSL/TLS 上下文
- 建立 SSL/TLS 握手
- 發(fā)送、接收數(shù)據(jù)
- 交互完成,關(guān)閉連接
其中,最關(guān)鍵的步驟就是 SSL/TLS 握手 連接的建立,這里需要進行證書校驗。
SSL/TLS 握手流程
DTLS 握手流程
為了避免拒絕服務(wù)攻擊,DTLS采用和IKE一樣的無狀態(tài) cookie 技術(shù)。當(dāng)客戶端發(fā)送 client hello 消息后,服務(wù)器發(fā)送 HelloVerifyRequest 消息,這個消息包含了無狀態(tài) cookie??蛻舳耸盏街蟊仨氈貍魈砑由狭?cookie 的 clienthello。
DTLS 握手流程如下圖所示:
3.示例程序
該示例程序提供了一個簡單的 TLS client,與測試網(wǎng)站建立 TLS 連接并獲取加密數(shù)據(jù)。
示例文件
示例程序路徑 說明
samples/tls_app_test.c TLS 測試?yán)?br /> 例程工作流程
本例程使用了 RT-Thread 官方 TLS 測試網(wǎng)站 www.rt-thread.org,使用 mbedtls_client_write 函數(shù)發(fā)送 HTTP 測試請求,成功后,該網(wǎng)站會返回文本數(shù)據(jù),測試?yán)虒⒔馕龊蟮臄?shù)據(jù)輸出到控制臺。
例程使用的 HTTP 請求數(shù)據(jù)如下所示
"GET /download/rt-thread.txt HTTP/1.0\r\n"
"Host: www.rt-thread.org\r\n"
"User-Agent: rtthread/3.1 rtt\r\n"
"\r\n";
- 1
- 2
- 3
- 4
mbedTLS 測試?yán)痰幕竟ぷ髁鞒倘缦滤?/p>
client連接測試網(wǎng)站 www.rt-thread.org
client 和 server 握手成功
client 發(fā)送請求
server 回應(yīng)請求
TLS 測試成功/失敗
同步設(shè)備時間
SSL/TLS 服務(wù)器進行證書校驗的過程中,會對當(dāng)前發(fā)起校驗請求的時間進行認(rèn)證,如果時間不滿足服務(wù)器的要求,就會校驗證書失敗。因此,我們需要為設(shè)備同步本地時間。
-
方式一: 使用
date命令未同步過時間的設(shè)備輸入
date命令后如下所示:
msh />date
Thu Jan 1 00:00:06 1970
- 1
- 2
使用 date 設(shè)置當(dāng)前時間,如下所示:
msh />date 2018 08 02 12 23 00
msh />date
Thu Aug 2 12:23:01 2018
msh />
- 1
- 2
- 3
- 4
-
方式二: 使用 NTP 同步網(wǎng)絡(luò)時間
該方式需要依賴 NTP 工具包,使用
menuconfig配置獲取,如下所示:
RT-Thread online packages --->IoT - internet of things --->-*- netutils: Networking utilities for RT-Thread --->-*- Enable NTP(Network Time Protocol) client(8) Timezone for calculate local time(cn.ntp.org.cn) NTP server name
- 1
- 2
- 3
- 4
- 5
- 6
使用命令 ntp_sync 同步網(wǎng)絡(luò)時間
msh />ntp_sync
Get local time from NTP server: Thu Aug 2 14:31:30 2018
The system time is updated. Timezone is 8.
msh />date
Thu Aug 2 14:31:34 2018
- 1
- 2
- 3
- 4
- 5
啟動例程
在 MSH 中使用命令 tls_test 執(zhí)行示例程序,成功建立 TLS 連接后,設(shè)備會從服務(wù)器拿到一組密碼套件,設(shè)備 log 如下所示:
msh />tls_test
MbedTLS test sample!
Memory usage before the handshake connection is established:
total memory: 33554408
used memory : 20968
maximum allocated memory: 20968
Start handshake tick:3313
[tls]mbedtls client struct init success...
[tls]Loading the CA root certificate success...
[tls]mbedtls client context init success...
msh />[tls]Connected www.rt-thread.org:443 success...
[tls]Certificate verified success...
Finish handshake tick:6592
MbedTLS connect success...
Memory usage after the handshake connection is established:
total memory: 33554408
used memory : 45480
maximum allocated memory: 50808
Writing HTTP request success...
Getting HTTP response...
HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Fri, 31 Aug 2018 08:29:24 GMT
Content-Type: text/plain
Content-Length: 267
Last-Modified: Sat, 04 Aug 2018 02:14:51 GMT
Connection: keep-alive
ETag: "5b650c1b-10b"
Strict-Transport-Security: max-age=1800; includeSubdomains; preload
Accept-Ranges: bytes
RT-Thread is an open source IoT operating system from China, which has strong scalability: from a tiny kernel running on a tiny core, for example ARM Cortex-M0, or Cortex-M3/4/7, to a rich feature system running on MIPS32, ARM Cortex-A8, ARM Cortex-A9 DualCore etc.
MbedTLS connection close success.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
4.常見問題
證書驗證失敗
[tls]verification info: ! The CRL is not correctly signed by the trusted CA
- 1
- 2
-
原因
mbedtls 包中支持多種主流 CA 機構(gòu)根證書,部分 CA 機構(gòu)未支持
-
解決方法
若測試其他 TLS 網(wǎng)站證書驗證失敗,手動獲取測試網(wǎng)站根證書(Root Cerificate)添加到
mbedtls/tls_cerificate.c文件中
證書時間錯誤
[tls]verify peer certificate fail....
[tls]verification info: ! The certificate validity starts in the future
- 1
- 2
- 3
-
原因
TLS 握手是證書驗證需要時間的驗證,本地時間獲取有誤導(dǎo)致
-
解決方式
檢查 RTC 設(shè)備是否支持,檢查
RT_USING_RTC宏是否打開,校準(zhǔn)設(shè)備時間。建議使用 NTP 同步本地時間。
證書 CN 錯誤
verification info: ! The certificate Common Name (CN) does not match with the expected CN
- 1
- 2
-
原因
測試其他 TLS 網(wǎng)站時,若輸入域名不符合證書的 Common Name(CN)出現(xiàn) CN 驗證失敗問題
-
解決方法
檢查輸入域名和證書中 CN 是否匹配或輸入 IP 地址
0x7200 錯誤
-
原因
部分原因是因為 mbedTls 收到了大于緩沖區(qū)大小的數(shù)據(jù)包
-
解決方法
menuconfig配置增加數(shù)據(jù)幀大小 (Maxium fragment length in bytes)
RT-Thread online packages --->security packages --->Select Root Certificate ---> # 選擇證書文件[*] mbedtls: An portable and flexible SSL/TLS library ---[*] Store the AES tables in ROM(2) Maximum window size used(6144) Maxium fragment length in bytes # 配置數(shù)據(jù)幀大小(0x7200 錯誤可嘗試增加該大小)[*] Enable a mbedtls client exampleversion (latest) --->
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
參考
- mbedTLS官方網(wǎng)站:https://tls.mbed.org/
- ARMmbed GitHub:mbedtls
總結(jié)
以上是生活随笔為你收集整理的转:mbedtls学习2.mbedtls从0使用指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java同步组件之CountDownLa
- 下一篇: 亚瑟大招会造成什么伤害王者荣耀