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