• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • mbedtls學習2.mbedtls從0使用指南

    標簽: # 應用協議  linux

    1.使用指南

    這里主要介紹 mbedtls 程序的基本使用流程,并針對使用過程中經常涉及到的結構體和重要 API 進行簡要說明。

    mbedtls 的基本工作流程如下所示:

    • 初始化 SSL/TLS 上下文
    • 建立 SSL/TLS 握手
    • 發送、接收數據
    • 交互完成,關閉連接

    menuconfig 配置說明

    獲取 mbedtls 軟件包或者修改用戶配置都需要使用 menuconfig。需要用戶打開 ENV 工具,并將目錄切換到您所用的 BSP 目錄,使用 menuconfig 命令打開配置界面。

    RT-Thread online packages → security packages 中選擇 mbedtls 軟件包,操作界面如下圖所示:

    在這里插入圖片描述

    詳細的配置介紹如下所示:

    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 # 配置數據幀大小
        [*]   Enable a mbedtls client example  # 開啟 mbedtls 測試例程
        [ ]   Enable Debug log output          # 開啟調試 log 輸出
              version (latest)  --->           # 選擇軟件包版本,默認為最新版本
    
    • Using all default CA 配置選項會將 certs/default 目錄下的所有預置證書加入編譯,將占用很大的內存
    • Using user CA 配置選項允許用戶將自己需要的證書文件加入編譯,需要用戶將證書文件拷貝到 certs 根目錄

    選擇合適的配置項后,使用 pkgs --update 命令下載軟件包并更新用戶配置。

    功能配置說明

    mbedtls 功能模塊的開啟與關閉定義在 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 配置到合適的尺寸。

    證書配置說明

    • 預置的 CA 證書文件存放在 certs/default 目錄中
    • 用戶增加的 CA 證書文件存放在 certs 根目錄中

    certs/default 目錄中已經包含了大多數 CA 根證書,如果您使用的根證書不在該文件夾內,需要用戶將自己的 PEM 格式的 CA 證書拷貝 certs 根目錄下。(僅支持 PEM 格式證書,不支持 DER 格式證書)。

    該證書文件中已經包含了大多數 CA 根證書,,參考后邊的 添加新證書 章節。

    初始化 TLS 會話

    typedef struct MbedTLSSession
    {
        char* host;
        char* port;
    
        unsigned char *buffer;               // 公用數據緩沖區
        size_t buffer_len;                   // 緩沖區大小
    
        mbedtls_ssl_context ssl;             // 保存 ssl 基本數據
        mbedtls_ssl_config conf;             // 保存 ssl 配置信息
        mbedtls_entropy_context entropy;     // 保存 ssl 熵配置
        mbedtls_ctr_drbg_context ctr_drbg;   // 保存隨機字節發生器配置
        mbedtls_net_context server_fd;       // 保存文件描述符
        mbedtls_x509_crt cacert;             // 保存認證信息
    } MbedTLSSession;
    

    MbedTLSSession 用于保存建立 TLS 會話連接時的配置信息,在 TLS 上下文中傳遞使用。用戶在使用建立 TLS 會話前,必須定義一個存儲會話內容的結構體,如下所示:

    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);
    

    這里需要設置 SSL/TLS 服務器的 host 和 port,以及數據接收 buffer 等配置。

    初始化 SSL/TLS 客戶端

    應用程序使用 mbedtls_client_init 函數初始化 TLS 客戶端。

    初始化階段按照 API 參數定義傳入相關參數即可,主要用來初始化網絡接口、證書、SSL 會話配置等 SSL 交互必須的一些配置,以及設置相關的回調函數。

    示例代碼如下所示:

    char *pers = "hello_world"; // 設置隨機字符串種子
    if((ret = mbedtls_client_init(tls_session, (void *)pers, strlen(pers))) != 0)
    {
        rt_kprintf("MbedTLSClientInit err return : -0x%x\n", -ret);
        goto __exit;
    }
    

    實際調用的 mbedtls 庫函數如下所示:

    初始化 SSL/TLS 客戶端上下文

    應用程序使用 mbedtls_client_context 函數配置客戶端上下文信息,包括證書解析、設置主機名、設置默認 SSL 配置、設置認證模式(默認 MBEDTLS_SSL_VERIFY_OPTIONAL)等。

    示例代碼如下所示:

    if((ret = mbedtls_client_context(tls_session)) < 0)
    {
        rt_kprintf("MbedTLSCLlientContext err return : -0x%x\n", -ret);
        goto __exit;
    }
    

    建立 SSL/TLS 連接

    使用 mbedtls_client_connect 函數為 SSL/TLS 連接建立通道。這里包含整個的握手連接過程,以及證書校驗結果。

    示例代碼如下所示:

    if((ret = mbedtls_client_connect(tls_session)) != 0)
    {
        rt_kprintf("MbedTLSCLlientConnect err return : -0x%x\n", -ret);
        goto __exit;
    }
    

    讀寫數據

    向 SSL/TLS 中寫入數據

    示例代碼如下所示:

    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;
        }
    }
    

    從 SSL/TLS 中讀取數據

    示例代碼如下所示:

    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;
    }
    

    注意,如果讀寫接口返回了一個錯誤,必須關閉連接。

    關閉 SSL/TLS 客戶端連接

    客戶端主動關閉連接或者因為異常錯誤關閉連接,都需要使用 mbedtls_client_close 關閉連接并釋放資源。

    示例代碼如下所示:

    mbedtls_client_close(tls_session);
    
    

    mbedtls 使用范式

    參考示例程序 samples/tls_app_test.c

    添加新證書

    CA 證書有兩種常用格式 PEM 格式DER 格式,目前 RT-Thread mbedtls 僅支持 PEM 格式 的證書文件。

    • PEM 格式證書

      PEM 格式證書 通常是以 .pem.cer 后綴名結尾的文件。

      使用文本編輯器打開后,文件內容以 -----BEGIN CERTIFICATE----- 開頭,以 -----END CERTIFICATE----- 結尾。

    • DER 格式證書

      DER 格式證書 是二進制文件類型。

    根證書樣式

    雙擊 .cer 后綴名結尾的 CA 文件(Windows系統)可以看到證書的簽發機構和有效期,如下圖所示:

    在這里插入圖片描述

    PEM 格式 格式的證書文件內容內容樣式如下所示:

    -----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-----
    
    

    獲取根證書

    • 直接向服務商索取

      向服務商索取 base64 編碼 X.509 編碼的 PEM 格式 證書文件。

    • 從服務商網站導出

      • 瀏覽器打開服務商網站,以 https://www.rt-thread.org/ 為例

      • 點擊瀏覽器地址欄的 安全,然后點擊證書
        在這里插入圖片描述

      • 查看證書詳細信息
        在這里插入圖片描述

      • 根證書導出向導
        在這里插入圖片描述

      • 選擇導出 Base64 編碼證書
        在這里插入圖片描述

      • 選擇證書存儲位置
        在這里插入圖片描述

      • 完成證書文件導出
        在這里插入圖片描述
        完成證書導出,假設證書文件名為 USER_ROOT_CA.cer

    導入證書

    • 使用文本編輯器打開上個步驟導出的根證書文件 USER_ROOT_CA.cer
    • 拷貝 USER_ROOT_CA.cer 文件到 certs 根目錄
    • 使用 scons 命令重新編譯

    注:

    scons 命令編譯后,會自動將證書文件拷貝到 const char mbedtls_root_certificate[] 數組中。

    2.工作原理

    mbedtls** 軟件包是對 SSL/TLS 協議的實現。SSL(安全套接層)和 TLS(傳輸安全層)均是為了保證傳輸過程中信息的安全,是在明文傳輸基礎上進行的加密,然后以密文的形式傳輸數據。

    mbedTLS 建立安全通信連接需要經過以下幾個步驟:

    • 初始化 SSL/TLS 上下文
    • 建立 SSL/TLS 握手
    • 發送、接收數據
    • 交互完成,關閉連接

    其中,最關鍵的步驟就是 SSL/TLS 握手 連接的建立,這里需要進行證書校驗。
    SSL/TLS 握手流程
    在這里插入圖片描述

    DTLS 握手流程

    為了避免拒絕服務攻擊,DTLS采用和IKE一樣的無狀態 cookie 技術。當客戶端發送 client hello 消息后,服務器發送 HelloVerifyRequest 消息,這個消息包含了無狀態 cookie。客戶端收到之后必須重傳添加上了 cookie 的 clienthello。

    DTLS 握手流程如下圖所示:
    在這里插入圖片描述

    3.示例程序

    該示例程序提供了一個簡單的 TLS client,與測試網站建立 TLS 連接并獲取加密數據。

    示例文件

    示例程序路徑 說明
    samples/tls_app_test.c TLS 測試例程
    例程工作流程
    本例程使用了 RT-Thread 官方 TLS 測試網站 www.rt-thread.org,使用 mbedtls_client_write 函數發送 HTTP 測試請求,成功后,該網站會返回文本數據,測試例程將解析后的數據輸出到控制臺。

    例程使用的 HTTP 請求數據如下所示?

    "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";
    

    mbedTLS 測試例程的基本工作流程如下所示

    client連接測試網站 www.rt-thread.org

    client 和 server 握手成功

    client 發送請求

    server 回應請求

    TLS 測試成功/失敗

    同步設備時間

    SSL/TLS 服務器進行證書校驗的過程中,會對當前發起校驗請求的時間進行認證,如果時間不滿足服務器的要求,就會校驗證書失敗。因此,我們需要為設備同步本地時間。

    • 方式一: 使用 date 命令

      未同步過時間的設備輸入 date 命令后如下所示:

    msh />date
    Thu Jan  1 00:00:06 1970
    

    使用 date 設置當前時間,如下所示:

    msh />date 2018 08 02 12 23 00
    msh />date
    Thu Aug  2 12:23:01 2018
    msh />
    
    • 方式二: 使用 NTP 同步網絡時間

      該方式需要依賴 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
    

    使用命令 ntp_sync 同步網絡時間

    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
    

    啟動例程

    在 MSH 中使用命令 tls_test 執行示例程序,成功建立 TLS 連接后,設備會從服務器拿到一組密碼套件,設備 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.
    

    4.常見問題

    證書驗證失敗

    [tls]verification info: ! The CRL is not correctly signed by the trusted CA
    
    
    • 原因

      mbedtls 包中支持多種主流 CA 機構根證書,部分 CA 機構未支持

    • 解決方法

      若測試其他 TLS 網站證書驗證失敗,手動獲取測試網站根證書(Root Cerificate)添加到mbedtls/tls_cerificate.c文件中

    證書時間錯誤

    [tls]verify peer certificate fail....
    [tls]verification info:   ! The certificate validity starts in the future
    
    
    • 原因

      TLS 握手是證書驗證需要時間的驗證,本地時間獲取有誤導致

    • 解決方式

      檢查 RTC 設備是否支持,檢查 RT_USING_RTC 宏是否打開,校準設備時間。建議使用 NTP 同步本地時間。

    證書 CN 錯誤

        verification info: ! The certificate Common Name (CN) does not match with the expected CN
    
    
    • 原因

      測試其他 TLS 網站時,若輸入域名不符合證書的 Common Name(CN)出現 CN 驗證失敗問題

    • 解決方法

      檢查輸入域名和證書中 CN 是否匹配或輸入 IP 地址

    0x7200 錯誤

    • 原因

      部分原因是因為 mbedTls 收到了大于緩沖區大小的數據包

    • 解決方法

      menuconfig 配置增加數據幀大小 ( 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 # 配置數據幀大小(0x7200 錯誤可嘗試增加該大小)
            [*]   Enable a mbedtls client example
                  version (latest)  --->
    
    

    參考

    • mbedTLS官方網站:https://tls.mbed.org/
    • ARMmbed GitHub:mbedtls
    版權聲明:本文為weixin_37571125原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/weixin_37571125/article/details/106354680

    智能推薦

    cmake安裝mbedtls詳細步驟

    上一篇講了怎樣安裝cmake,當然,最終目的還是要安裝上mbedtls,以下為詳細步驟。 新建repo文件夾,我已經建好了,所以直接進入。 2. 克隆代碼,也可以直接去官網下載 我是都已經執行了此命令了,又發現這里面并沒有我需要的,所以有自己去官網下載。 切換到某個分支 根據自己的需要進行切換,我組長直接把有關文件直接copy給我了,所以我也省掉了很多麻煩 4.進入mbedtls目錄 5.生成ma...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    猜你喜歡

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    精品国产乱码久久久久久蜜桃不卡