原文链接:http://blog.csdn.net/ppdyhappy/article/details/64127332
mbedtls下载:
https://github.com/ARMmbed/mbedtls
移植源文件:
1)拿出解压后的mbedtls-development目录下的include文件和library文件
2)拿出mbedtls-development\programs\ssl下的demo,如ssl_client1.c(客户端代码)
程序处理:
1)随机数生成器
若芯片不支持随机数发生器可在config.h中打开宏 MBEDTLS_TEST_NULL_ENTROPY 并屏蔽宏 MBEDTLS_HAVEGE_C ,这样并不安全
若芯片支持随机数发生器则在config.h中关闭宏 MBEDTLS_TEST_NULL_ENTROPY 并打开宏 MBEDTLS_HAVEGE_C
问题可在 mbedtls论坛上查询
2)程序裁剪:
为节省ROM和RAM,在config.h中注释如下宏定义
MBEDTLS_SELF_TEST //自测
MBEDTLS_VERSION_FEATURES //disable run-time checking and save ROM space
其他根据宏定义的说明适当打开或屏蔽,如:MBEDTLS_BLOWFISH_C//实际不适用这个算法,可注释以节省空间
3)time接口:
在platform_time.h中
重定向 mbedtls_time宏,根据当前平台重新实现time接口,如这里实现如下
platform_time.h中:
#define mbedtls_time new_time
new_time 接口实现如下,这里使用RTC寄存器
- time_t new_time(time_t * parm)
- {
- struct tm* p;
- RTC_QuickInit();
- time_t timep = (time_t)RTC_GetTSR();
- if(timep <= 1000)
- {
- timep = 0x95272759;
- }
- p = localtime(&timep);
- timep = mktime(p);
- return timep;
- }
证书部分:
证书制作参照 openssl+tomcat7使用简明笔记(http://blog.csdn.net/ppdyhappy/article/details/56019429)
if( ( ret = mbedtls_ssl_set_hostname( &ssl, "host_name") ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\r\n", ret );
goto exit;
}
这里host_name对应服务器证书中的common name
使用openssl公钥最短为512bit,如此可降低芯片处理难度,对应要在x509_crt.c中修改公钥长度,修改部分如下:
- const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
- {
- /* Hashes from SHA-1 and above */
- MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
- MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) |
- MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
- MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
- MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
- MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
- 0xFFFFFFF, /* Any PK alg */
- 0xFFFFFFF, /* Any curve */
- 512, // 2048 修改这里
- };
这边实测mbedtls大概占用RAM 16kb左右
mbedtls论坛:https://tls.mbed.org/discussions
植接口及测试部分代码:
ssl_interface.h
//*******************************************************************//
- #ifndef _SSL_INTERFACE_H_
- #define _SSL_INTERFACE_H_
- int ssl_create( void );
- int ssl_close( void );
- int ssl_write( const unsigned char *buf, uint32_t len );
- int ssl_read( unsigned char *buf, uint32_t len );
- #endif
ssl_interface.c //rt-thread 操作系统,代码还未完善
//*******************************************************************//
- #if !defined(MBEDTLS_CONFIG_FILE)
- #include "mbedtls/config.h"
- #else
- #include MBEDTLS_CONFIG_FILE
- #endif
- #if defined(MBEDTLS_PLATFORM_C)
- #include "mbedtls/platform.h"
- #else
- #include <stdio.h>
- #include <stdlib.h>
- #define mbedtls_time mktime
- #define mbedtls_time_t time_t
- #define mbedtls_fprintf fprintf
- //#define mbedtls_printf rt_kprintf
- #endif
- #include "mbedtls/net_sockets.h"
- #include "mbedtls/debug.h"
- #include "mbedtls/ssl.h"
- #include "mbedtls/entropy.h"
- #include "mbedtls/ctr_drbg.h"
- #include "mbedtls/error.h"
- #include "mbedtls/certs.h"
- #include <string.h>
- #include "socket.h" //socket接口用
- #include "ssl_interface.h"
- #include "common.h" //
- #define SERVER_PORT 8080
- #define SERVER_NAME "www.baidu.com" //
- #define SERVER_HOSTNAME "hello" //server's certificate common name
- #define DEBUG_LEVEL 1
- static void my_debug( void *ctx, int level,
- const char *file, int line,
- const char *str )
- {
- ((void) level);
- mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
- fflush( (FILE *) ctx );
- }
- static int32_t ssl_socketID = 0;
- static void ssl_socket_recive_data(char * recv_buff, rt_uint32_t len);
- static int ssl_connect_net(void)
- {
- int32_t aswResult;
- SockAddr addr;
- memcpy(addr.g_u8_socket_connect_host,SERVER_NAME,sizeof(SERVER_NAME));
- addr.g_u16_socket_connect_port = SERVER_PORT;
- addr.g_vd_socket_rtcp_data_cb = ssl_socket_recive_data;
- if (0 == ssl_socketID)
- {
- ssl_socketID = g_s32_NET_socket();
- }
- if(ssl_socketID < 0)
- {
- return -1;
- }
- if(g_s32_NET_connect(ssl_socketID,&addr,sizeof(SockAddr)) != 0)
- {
- return -1;
- }
- return 0;
- }
- static char ssl_rec_buf[500] = {0};
- /*
- ssl_rec_flag:-2 receive action is error
- ssl_rec_flag:-1 no receive action
- ssl_rec_flag:0 have receive action
- ssl_rec_flag:1 have read action
- ssl_rec_flag:2 read over
- */
- //#define
- static int ssl_rec_flag = -1;
- static uint32_t ssl_rec_len = 0;
- static void ssl_socket_recive_data(char * recv_buff, uint32_t len)
- {
- if((ssl_rec_flag != -1) || (ssl_rec_flag != 2))
- {
- ssl_rec_flag = -2;
- }
- if(ssl_rec_flag == 1)
- {
- }
- else
- {
- ssl_rec_len = len;
- memcpy(ssl_rec_buf, recv_buff, len);
- ssl_rec_flag = 0;
- }
- }
- //int32_t g_s32_NET_write(int32_t sockfd, void *buf, uint32_t count)
- //MBEDTLS_ERR_NET_SEND_FAILED
- static int wrap_ssl_send( void *ctx, unsigned char *buf, size_t len )
- {
- ctx = ctx;
- if(g_s32_NET_write(ssl_socketID, (void*)buf, (uint32_t)len) == -1)
- {
- return MBEDTLS_ERR_NET_SEND_FAILED;
- }
- return (int)len;
- }
- static void wait_socket_rev(uint32_t count)
- {
- }
- //MBEDTLS_ERR_NET_RECV_FAILED
- static int wrap_ssl_recv( void *ctx, unsigned char *buf, size_t len )
- {
- static size_t get_len = 0;
- static size_t sum_len = 0;
- size_t temp_len = 0;
- uint32_t k = 0;
- ctx = ctx;
- if(-2 == ssl_rec_flag)
- {
- return MBEDTLS_ERR_NET_RECV_FAILED;
- }
- // have read action
- if(ssl_rec_flag == 1)
- {
- // do nothing
- }
- else
- {
- while(ssl_rec_flag != 0)
- {
- DelayMs(1);
- k += 1;
- if(k == 10000)
- {
- return MBEDTLS_ERR_NET_RECV_FAILED;
- }
- }
- sum_len = (size_t)ssl_rec_len;
- get_len = 0;
- }
- // have receive action
- if(ssl_rec_flag == 0)
- {
- ssl_rec_flag = 1;
- }
- if(sum_len >= (len + get_len))
- {
- temp_len = len;
- }
- else
- {
- temp_len = sum_len - get_len;
- }
- if(0 == temp_len)
- {
- return MBEDTLS_ERR_NET_RECV_FAILED;
- }
- memcpy(buf, ssl_rec_buf + get_len, temp_len);
- get_len += temp_len;
- if(get_len == sum_len)
- {
- ssl_rec_flag = 2;
- }
- else if(get_len > sum_len)
- {
- //
- }
- else
- {
- }
- return (int)temp_len;
- }
- //0:no close action 1:have close action
- static uint8_t close_socket_flag = 0;
- static int close_socket_ret = 0;
- static int ssl_close_socket(void)
- {
- int ret = 0;
- if(1 == close_socket_flag)
- return close_socket_ret;
- ssl_socketID = 0;
- if((close_socket_ret = g_s32_NET_close(ssl_socketID)) != 0)
- {
- mbedtls_printf("close ssl socket[%d] fail!\r\n", ssl_socketID);
- }
- else
- {
- mbedtls_printf("close ssl socket[%d] success!\r\n", ssl_socketID);
- }
- close_socket_flag = 1;
- return close_socket_ret;
- }
- //0:no clean 1:have clean
- static uint8_t clean_flag = 0;
- static void ssl_clean_up(void);
- mbedtls_net_context server_fd;
- mbedtls_entropy_context entropy;
- mbedtls_ctr_drbg_context ctr_drbg;
- mbedtls_ssl_context ssl;
- mbedtls_ssl_config conf;
- mbedtls_x509_crt cacert;
- int ssl_create( void )
- {
- int ret;
- uint32_t flags;
- unsigned char buf[1024];
- const char *pers = "bj";
- //Æô¶¯µ÷ÊÔ¹¦ÄÜ
- #if defined(MBEDTLS_DEBUG_C)
- mbedtls_debug_set_threshold( DEBUG_LEVEL );
- #endif
- clean_flag = 0;
- close_socket_flag = 0;
- close_socket_ret = 0;
- /*
- * 0. Initialize the RNG and the session data
- */
- // ÓÃsocket ÅäÖÃ
- // mbedtls_net_init( &server_fd ); // ignore ysw
- mbedtls_ssl_init( &ssl );
- mbedtls_ssl_config_init( &conf );
- mbedtls_x509_crt_init( &cacert );
- mbedtls_ctr_drbg_init( &ctr_drbg );
- mbedtls_printf( "\n . Seeding the random number generator..." );
- fflush( stdout );
- // ìØ³õʼ»¯
- mbedtls_entropy_init( &entropy );
- //DRBG---->Deterministic Random Bit Generators Î±Ëæ»úÊý²úÉúÆ÷
- if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
- (const unsigned char *) pers,
- strlen( pers ) ) ) != 0 )
- {
- mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
- goto exit_no_socket;
- }
- mbedtls_printf( " ok\n" );
- /*
- * 0. Initialize certificates
- */
- mbedtls_printf( " . Loading the CA root certificate ..." );
- fflush( stdout );
- //±¾µØÖ¤Êé´¦Àí£¬ÓÃÓÚУÑé·þÎñÆ÷Ö¤ÊéÓ㬿ɼò»¯´¦Àí
- //mbedtls_test_cas_pem ´æ·ÅÖ¤ÊéÊý¾ÝµÄbuf
- ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
- mbedtls_test_cas_pem_len );
- if( ret < 0 )
- {
- mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\r\n", -ret );
- goto exit_no_socket;
- }
- mbedtls_printf( " ok (%d skipped)\n", ret );
- /*
- * 1. Start the connection
- */
- mbedtls_printf( " . Connecting to tcp/%s/%d...", SERVER_NAME, SERVER_PORT );
- fflush( stdout );
- //ÏÖÔÚ socket Á¬½Ó½Ó¿ÚºÜ¼òµ¥£¬Ö±½Óµ÷Óü´¿É
- #if 0
- if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME,
- SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
- {
- mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\r\n", ret );
- goto exit;
- }
- #endif
- if( ( ret = ssl_connect_net() ) != 0 )
- {
- mbedtls_printf( " failed\n ! ssl_connect_net returned %d\r\n", ret );
- goto exit;
- }
- mbedtls_printf( " ok\n" );
- /*
- * 2. Setup stuff
- */
- mbedtls_printf( " . Setting up the SSL/TLS structure..." );
- fflush( stdout );
- //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 )
- {
- mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\r\n", ret );
- goto exit;
- }
- mbedtls_printf( " ok\n" );
- /* OPTIONAL is not optimal for security,
- * but makes interop easier in this simplified example */
- // ÉèÖÃÊý×ÖÖ¤Êé¼ì²éģʽ
- // MBEDTLS_SSL_VERIFY_OPTIONAL ÔÚclientģʽϲ»ÍƼöʹÓã¬ÒòΪ²»¹»°²È«
- /*
- * 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_OPTIONAL );
- // Ö¤ÊéÁ´£¬Ô¤ÏÈ´æ·ÅÔÚ±¾µØµÄ
- mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
- // ÅäÖÃËæ»úÊýÉú³ÉÆ÷µÄ»Øµ÷º¯Êý
- 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 %d\r\n", ret );
- goto exit;
- }
- // ÉèÖÃhost name Óõ½¶¯Ì¬ÄÚ´æ·ÖÅä
- if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_HOSTNAME ) ) != 0 )
- {
- mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\r\n", ret );
- goto exit;
- }
- // ÉèÖ÷¢ËͺͽÓÊÕ½Ó¿Ú
- // mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
- mbedtls_ssl_set_bio( &ssl, &server_fd, wrap_ssl_send, wrap_ssl_recv, NULL );
- /*
- * 4. Handshake
- */
- mbedtls_printf( " . Performing the SSL/TLS handshake..." );
- fflush( stdout );
- while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
- {
- if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
- {
- mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\r\n", -ret );
- goto exit;
- }
- }
- mbedtls_printf( " ok\n" );
- /*
- * 5. Verify the server certificate
- */
- mbedtls_printf( " . Verifying peer X.509 certificate..." );
- /* In real life, we probably want to bail out when ret != 0 */
- if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 )
- {
- char vrfy_buf[512];
- mbedtls_printf( " failed\n" );
- mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
- mbedtls_printf( "%s\n", vrfy_buf );
- }
- else
- mbedtls_printf( " ok\n" );
- return (ret);
- exit:
- #ifdef MBEDTLS_ERROR_C
- if( ret != 0 )
- {
- char error_buf[100];
- mbedtls_strerror( ret, error_buf, 100 );
- mbedtls_printf("Last error was: %d - %s\r\n", ret, error_buf );
- }
- #endif
- ssl_close_socket();
- exit_no_socket:
- ssl_clean_up();
- #if defined(_WIN32)
- mbedtls_printf( " + Press Enter to exit this program.\n" );
- fflush( stdout ); getchar();
- #endif
- return( ret );
- }
- //#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
- // MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
- // MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C &&
- // MBEDTLS_X509_CRT_PARSE_C */
- // return 0:success
- // return -1:fail
- int ssl_write( const unsigned char *buf, uint32_t len )
- {
- int ret;
- while( ( ret = mbedtls_ssl_write( &ssl, buf, (size_t)len ) ) <= 0 )
- {
- if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
- {
- mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\r\n", ret );
- ssl_close_socket();
- ssl_clean_up();
- return -1;
- }
- }
- return 0;
- }
- int ssl_read( unsigned char *buf, uint32_t len )
- {
- int ret;
- do
- {
- ret = mbedtls_ssl_read( &ssl, buf, len );
- if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
- continue;
- if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
- mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret );
- mbedtls_ssl_close_notify( &ssl );
- ssl_clean_up();
- return -1;
- if( ret < 0 )
- {
- mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret );
- ssl_clean_up();
- return -1;
- }
- // if( ret == 0 )
- // {
- // mbedtls_printf( "\n\nEOF\n\n" );
- // break;
- // }
- len = ret;
- mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf );
- }
- while( 1 );
- return ret;
- }
- //clean up
- static void ssl_clean_up(void)
- {
- if(1 == clean_flag)
- return;
- mbedtls_printf(" ssl clean up\r\n");
- mbedtls_x509_crt_free( &cacert );
- mbedtls_ssl_free( &ssl );
- mbedtls_ssl_config_free( &conf );
- mbedtls_ctr_drbg_free( &ctr_drbg );
- mbedtls_entropy_free( &entropy );
- clean_flag = 1;
- }
- //ssl close
- int ssl_close( void )
- {
- mbedtls_printf(" ssl close\r\n");
- ssl_clean_up();
- return( ssl_close_socket() );
- }
测试代码
//*******************************************************************//
- unsigned char t_buff[] = {"GET /dispatcher?user=dididada HTTP/1.1\r\nHost: www.baidu.com:8080\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n"};
- unsigned char rec_buf[300] = {0};
- void mbedtls_test(void * parameter)
- {
- int flag = 0;
- flag = ssl_create();
- ssl_write(t_buff, sizeof(t_buff));
- flag = ssl_read(rec_buf, sizeof(rec_buf));
- ssl_close();
- }