數據處理思想和程序架構: 使用Mbedtls包中的SSL,和服務器進行網絡加密通信


<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/單片機知識點總結/directory.html" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>

 

單向認證忽略認證方式

1.首先保證自己的程序已經實現了普通TCP連接通信

確保自己的單片機的程序存儲空間在60KB以上!

確保自己的單片機有至少64KB及其以上的RAM空間!

如果使用的STM32那么推薦的型號為 STM32F103RFT6/RGT6/VFT6/VGT6/ZFT6/ZGT6

為了保證此篇文章能夠讓所有人都能應用,我就假設我的程序里面已經實現了TCP連接\

然后規定:

/*假設接收網絡數據函數*/
int net_recv(char *data);
/*假設TCP發送數據函數*/
int net_send(char *data,int len);

 

 

2.按照上一節 把MBEDTLS包添加到工程

 

 

 

 

3.config.h打開以下宏

#define MBEDTLS_HAVE_ASM

#define MBEDTLS_NO_UDBL_DIVISION

#define MBEDTLS_HAVE_TIME

#define MBEDTLS_ENTROPY_HARDWARE_ALT

#define MBEDTLS_AES_ROM_TABLES

#define MBEDTLS_CIPHER_MODE_CBC

#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED

#define MBEDTLS_NO_PLATFORM_ENTROPY

#define MBEDTLS_PKCS1_V15

#define MBEDTLS_SSL_PROTO_TLS1_2

#define MBEDTLS_AES_C

#define MBEDTLS_ASN1_PARSE_C

#define MBEDTLS_ASN1_WRITE_C

#define MBEDTLS_BIGNUM_C

#define MBEDTLS_CIPHER_C

#define MBEDTLS_CTR_DRBG_C

#define MBEDTLS_ENTROPY_C

#define MBEDTLS_GCM_C

#define MBEDTLS_MD_C

#define MBEDTLS_MD5_C

#define MBEDTLS_OID_C

#define MBEDTLS_PK_C

#define MBEDTLS_PK_PARSE_C

#define MBEDTLS_PLATFORM_C

#define MBEDTLS_RSA_C

#define MBEDTLS_SHA1_C

#define MBEDTLS_SHA256_C

#define MBEDTLS_SHA512_C

#define MBEDTLS_SSL_CLI_C

#define MBEDTLS_SSL_TLS_C

#define MBEDTLS_X509_USE_C

#define MBEDTLS_X509_CRT_PARSE_C

//下面這個是自己設置的加密套件

#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256

 

 

 

4.編譯一下

 

 

 

 

5.方式1:修改一下源碼即可

 

 

 

 

 

方式2:如果不願意修改源碼可以 選擇C99模式

 

 

 

6.再編譯一下

 

 

 

7.增加自己的隨機數函數 和 時間戳返回函數

 

 

 

/*隨機數函數*/
int mbedtls_hardware_poll( void *data,
                    unsigned char *output, size_t len, size_t *olen )
{
    unsigned long randomValue = ((rand()*20) + 1000);//生成隨機數
    ((void) data);
    *olen = 0;
    
    if( len < sizeof(unsigned long) ) return( 0 );    

    memcpy( output, &randomValue, sizeof(unsigned long) );
    *olen = sizeof(unsigned long);
  return 0;
}

/**
* @brief  時間函數(SSL底層會調用時間驗證證書是否過期)
**/
//struct tm *lcTime;
//time_t startTime;
//    lcTime = localtime (&startTime);
_ARMABI time_t time(time_t *t)
{
//    time_t it;
    if (t) {
        return *t;
    }
    else
    {
//        startTime = 0;
//        lcTime = localtime (&startTime);
//        it = mktime(lcTime);
//        return it ;
        return 0;
    }
}

 

 

8.增加SSL底層獲取數據函數

咱們在后面設置好SSL接收回調函數以后, SSL底層會調用 custom_ssl_recv 函數

SSL底層要多少個數據,咱們才返回多少個數據,這是SSL底層規定的,所以為了配合SSL底層,程序寫的比較多.

SSL底層調用的時候最后一個參數 size_t len是指定要多少個數據.

 

 

 

 

 

 

 

/**
* @brief  自定義接收函數(把自己的接收函數放到此函數中)
* @param  None
* @param  None
* @param  None
* @retval None
* @example 
**/
int net_recv_data_len=0; 
int net_recv_data_len_count=0;
char net_recv_buff[2000];
static int custom_ssl_recv( void *ctx, unsigned char *buf, size_t len )
{
    int rbCanReadLen;
    
    if(net_recv_data_len ==0)
    {
        net_recv_data_len=net_recv(net_recv_buff);//調用自己的函數接收數據
        if(net_recv_data_len>0)//有數據
        {
            if(len >= net_recv_data_len)//希望讀取的數據個數大於實際的數據個數
            {
                len = net_recv_data_len;
                memcpy(buf, net_recv_buff, len);
                
                net_recv_data_len = 0;
                net_recv_data_len_count=0;
                return len;
            }
            else//實際的數據個數比希望讀取的多
            {
                memcpy(buf, net_recv_buff, len);
                net_recv_data_len_count = len;
                return len;
            }
        }
        else
        {
            return MBEDTLS_ERR_NET_RECV_FAILED;
        }
    }
    else
    {
        if(len >= net_recv_data_len - net_recv_data_len_count)//希望讀取的數據個數大於實際的數據個數
        {
            len = net_recv_data_len - net_recv_data_len_count;
            memcpy(buf, net_recv_buff+net_recv_data_len_count, len);
            net_recv_data_len = 0;
            net_recv_data_len_count=0;
            return len;
        }
        else//實際的數據個數比希望讀取的多
        {
            memcpy(buf, net_recv_buff + net_recv_data_len_count, len);
            net_recv_data_len_count = net_recv_data_len_count + len;
            return len;
        }
    }
}

 

 

9.增加發送函數以供SSL底層調用

 

 

 


/*增加發送函數*/
static int custom_ssl_send( void *ctx, unsigned char *buf, size_t len )
{
    ctx = ctx;
    net_send(buf,len);//調用自己的TCP發送函數
    return (int)len;
}

 

 

10,定義需要的變量,並初始化SSL

 

 

 

 

int ret;//
const char *pers = "ssl_client1";
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;


void ssl_int(void)
{
    mbedtls_ssl_close_notify( &ssl );
    mbedtls_ssl_free( &ssl );
    mbedtls_ssl_config_free( &conf );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );
    
    //    mbedtls_debug_set_threshold( 1 );//
    mbedtls_ssl_init( &ssl );
    mbedtls_ssl_config_init( &conf );
    mbedtls_ctr_drbg_init( &ctr_drbg );
    mbedtls_entropy_init( &entropy );

    printf( "\n  . Seeding the random number generator..." );
    //DRBG---->Deterministic Random Bit Generators 偽隨機數產生器
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                                                         (const unsigned char *) pers,
                                                         strlen( pers ) ) ) != 0 )
    {
            printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
    }
    
    
    //MBEDTLS_SSL_IS_CLIENT 表示配置為客戶端
    //MBEDTLS_SSL_TRANSPORT_STREAM 表示傳輸方式為TLS
    //設置版本, MBEDTLS_SSL_PRESET_DEFAULT 表示 TLS1.0
    if( ( ret = mbedtls_ssl_config_defaults( &conf,
                                    MBEDTLS_SSL_IS_CLIENT,
                                    MBEDTLS_SSL_TRANSPORT_STREAM,
                                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
    {
            printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\r\n", ret );
    }
 
 
    /*設置數字證書檢查模式 
    *  MBEDTLS_SSL_VERIFY_NONE:      peer certificate is not checked
    *                        (default on server)
    *                        (insecure on client)
    *
    *  MBEDTLS_SSL_VERIFY_OPTIONAL:  peer certificate is checked, however the
    *                        handshake continues even if verification failed;
    *                        mbedtls_ssl_get_verify_result() can be called after the
    *                        handshake is complete.
    *
    *  MBEDTLS_SSL_VERIFY_REQUIRED:  peer *must* present a valid certificate,
    *                        handshake is aborted if verification failed.
    *                        (default on client)
    */
    mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE );
    // 配置隨機數生成器的回調函數
    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
    // 配置調試回調函數
    //    mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
    
    // 根據conf設置ssl結構
    if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
    {
            mbedtls_printf( " failed\n  ! mbedtls_ssl_setup returned 0x%x\r\n", -ret );
    }

    // 設置host name 用到動態內存分配
    if( ( ret = mbedtls_ssl_set_hostname( &ssl, "替換自己證書的CN字段填寫的值" ) ) != 0 )
    {
            mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hostname returned %d\r\n", ret );
    }
    // 設置發送和接收接口
    mbedtls_ssl_set_bio( &ssl, NULL, custom_ssl_send, custom_ssl_recv, NULL );
}

 

 

 

11.關於 替換自己證書的CN字段

看上一節

 

 

 

 

 

 

 

 

 

12,連接上TCP以后,等待SSL握手成功

 

 

 

 

13,發送和接收數據

 

 

 

 

注意:

1.如果顯示這個..單片機不行,換個內存大點的

 

 

 

2.我堆設置的是  a000

 

 

 

 

3.如果不能連接,可以打開DEBUG

#define MBEDTLS_DEBUG_C

 

 

 

 

 

 

 

 

 

 

4.配置DEBUG

 

 

 

/*設置 debug 輸出函數*/
static void my_debug( void *ctx, int level,
                      const char *file, int line, const char *str )
{
    printf("%s:%04d: %s\r\n", file, line, str );
}

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM