(1)关于PolarSSL
6 Z1 w# `: t1 Qmbed TLS(以前称为PolarSSL)是TLS和SSL协议的实现,并且需要相应的加密算法和支持代码。这是双重许可与Apache许可证 2.0版(与GPLv2许可也可)。, E9 C( ]# f8 O" \0 k: Q
核心SSL库用C编程语言编写,并实现SSL模块,基本加密功能并提供各种实用功能。与OpenSSL和TLS的其他实现不同,mbed TLS设计为适合小型嵌入式设备,最小完整的TLS堆栈需要60KB的程序空间和64KB的RAM。它也是高度模块化的:每个组件,如加密函数,可以独立于框架的其余部分使用。因为mbed TLS是用C编程语言编写的,没有外部依赖,现在叫MbedTSL,PolarSSL源码,也许是最小巧的ssl代码库。高效、便于移植和集成。尤其适合嵌入式应用。: Z7 o9 @/ Y2 O* X9 q; C% Y3 B
1 z$ c4 ^4 x: S W% A# U2 R本章就基于STM32移植mbedtls-2.24.0版本进行测试与使用!
$ I7 S+ A( ~5 e( a/ o2 L) {$ c
8 j; |/ I4 ?: ]1 F8 `$ [" J注意:因为本章节只是用了加解密的API,没有使用网络进行SSL认证操作,如果要使用mbedtls的SSL认证,最低的硬件环境最低需要60K的FLASH以及64K的SRAM(内存),如果你使用的比较低端的STM32,那么无解,没法用embedtls。。。# b6 U; z2 N& z
& F! Z) s. T3 ~* q
(2)mbedtls移植2 x! n g5 v) g% G
首先使用STM32CubeMX建立裸机工程,我使用的是STM32F103RB,配置了串口一当作信息输出的端口,这里注意,mbedtls所使用的栈空间是比较大的,所以在STM32CubeMX输出工程的时候将栈空间调大,如下图:0 w9 \9 K+ [. D8 x+ N6 Y" O; A
$ Z5 L7 p2 L) J
, E8 p/ P0 z0 a' ~0 i) Q3 E- @8 H! w2 w4 T
下载解压mbedtls源码目录如下:, |. Q ` N( i0 c; M3 N4 B
& M- x. _ z! z
8 u/ O0 z# F0 _* Q) o) K4 E
# G6 h% L4 i7 X/ {0 |2 N% R
而我们需要的仅仅是configs(配置头文件)、include(头文件)、library(源码)。' e6 `+ ~( t5 c: l
configs,该文件夹内的是配置头文件,可以根据不同需求进行选择,例如我们本次是在嵌入式系统上使用,资源有限,所以就选择config-mini-tls1_1.h这个配置文件,复制该文件内的内容替换mbedtls的默认配置头文件mbedtls/config.h即可。include,所有头文件0 g9 E, G' k5 n8 \+ V* J) K
library,所有源代码# o0 g% E7 H; D$ [' o5 R6 W' P
0 l. r3 X# X$ s& E首先在STM32 工程目录下建立文件夹mbedtls,并将mbedtls源码目录下的include和library两个文件夹复制过来,复制config-mini-tls1_1.h文件中的内容替换include/config.h。(注:include/config.h文件是只读的,需要先修改权限为读写)。3 ]4 N( ~+ q4 l: j4 z/ j+ r6 b$ H
# ?1 F- M, }* y0 V z
打开keil工程将源码添加进来:
; J3 \( m% g9 ~+ E/ Z
K4 J z4 i# A' u' t: C
( ^# V# A8 }( A0 A8 r! k' ?6 J: Z6 ]2 w' W9 f
添加头文件包含:
9 R: b( V1 q3 |7 ~+ f% G( y
8 w; J' G1 z0 x1 q# U
& @, i. z+ M$ |/ l3 o2 ~
! L+ t* L8 |7 f& X- F修改include/config.h配置文件: m9 A4 {/ U) ], @+ E9 k6 x
注释掉宏定义MBEDTLS_HAVE_TIME,因为我们目前没有用到时间相关的
# m5 g& }6 {/ T/ q6 q6 ]注释掉宏定义MBEDTLS_NET_C,因为没有用到网络( C5 H8 c; ?: I( g7 j. w
注释掉宏定义MBEDTLS_FS_IO,这是带系统时候需要用到的标准系统调用IO,例如linux下的系统调用函数read、write等,裸机我们没有用到
& ]1 G) L( E# l& s5 i添加一个宏定义MBEDTLS_NO_PLATFORM_ENTROPY,单片机无系统所以需要添加该宏。# O3 Y" D7 p" P# L I5 l
- K: E- R6 A& @! N; c: C然后编译工程即可~!
; ^8 T$ N6 G5 [: c& x& I* g# s+ [% Q$ Q* o- |! e4 f4 |+ M: Z* ^2 {) r
(3)移植测试" l: a ^$ A( V& V+ i. f
将printf函数重定向到串口一输出:
0 C7 o# U2 O1 v4 \
* Z& ^( F6 |0 `5 W4 v" X- /// 重定向printf函数到串口一
: y9 j+ N, {7 q* a' C - int fputc(int ch, FILE* fp)' X' L6 J4 H( C; o
- {) e- g4 H3 N! m3 L2 c/ O
- while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE) != SET);
% o/ t _; t& n* u - huart1.Instance->DR = (uint8_t)(ch & 0XFF);- R: r, M, E% L+ x
- return ch;
: b; [% Y5 O6 t' L1 P# W6 h - }
复制代码
0 L( {7 D' h# d4 m2 U N2 O- E/ y3 A下面我们开始编写代码测试,测试两个,一个是base64编码的,另一个是AES加解密的,
# p1 q0 B7 o5 |& G需要添加头文件:
- U1 ]/ C& K' o+ t4 ?2 L8 x% I" p
' M' S% c/ g3 [* Z- #include "mbedtls/config.h"1 r( _0 k* {- e# X* \7 @
- #include "mbedtls/aes.h". i* y$ e; Y- Q& `5 U
- #include "mbedtls/base64.h"
复制代码
: r) t& l! V. ^+ \# n; j( d& ~! M! m) ~base64编解码测试代码:
# l5 s+ I5 t1 D4 v
& m% b2 G) G( X, u0 n- d3 ~- void mbedtls_base64_demo(void)7 ?+ v: g6 e0 ]; t7 P7 }: m
- {; Z1 _1 i0 i9 Y. x
- int i = 0;
% g' l$ t1 n/ G3 D( g) D* @5 E - * Q9 W3 T) P% k: B9 M
- // 原始数据
8 a- s$ v0 l5 h7 n4 @ - uint8_t plaintext[16] = {'A','B','C','D','E','F','G','H','I','J', 'K', 'L', 'M', 'N', 'O', 'P'};9 q; Y7 ` U: @0 ?4 [4 ~8 a
3 B6 G6 D. l( d, D- // base64编码和解码输出数据的长度, u' P0 J, t$ l+ F. y) L
- size_t enclen = 0, declen = 0;% l2 ~! K9 _/ N* z8 ^
6 Q! y$ ?" ~ E1 |0 n' ~: h. [- // 存放base64编码输出4 O( h. l# v1 l: m8 x
- uint8_t encode[32];% D: e$ p1 B3 R0 }# t
& Y' G! ^+ v6 d1 d- // 存放base64解码输出
6 |3 u4 a- Y# L$ C# O: E! w - uint8_t decode[32];
1 c- g* Y+ {. r, k$ e
. A0 d- o0 W- @# b0 D/ u- // 编码
5 v% z9 c! x& ^' s$ f3 N& L - mbedtls_base64_encode(encode, sizeof(encode), &enclen, plaintext, sizeof(plaintext));1 H: z0 M# q2 h) @; z
1 x+ @+ E. y% W, M1 C( G9 A$ n( i; C- // 解码
& u W+ y( w7 N4 j* c! y - mbedtls_base64_decode(decode, sizeof(decode), &declen, encode, enclen);
% p0 ]3 |- q: p Z+ E; d! w# q
) B$ H+ B+ j: @9 C8 X _; _- printf("- enclen:%d\r\n", enclen);
! W( U5 b& ~# I K( W$ G4 x - printf("- encode:%s\r\n", encode); h) J0 f, u3 R( _# d; l
- printf("- declen:%d\r\n", declen);
) R5 }) k0 h8 W - printf("- decode:");
6 i7 V) V: f' a5 ] - for(i = 0; i < declen; i++)
: G4 ?, u- w5 f - {
5 n2 J. D+ b% u1 ^$ a. C# n9 g6 s - printf("%c", (char)decode<i>);
+ y; U K& B; H2 C# _ - }
8 r7 x; } T' C" I& R2 Y7 ] - printf("\r\n");: m# u( |1 _# D1 n4 D
- }</i>
复制代码 + d. W* w# [4 ~
AES加解密测试代码(ECB模式):; X3 A6 F* _7 l/ @8 a! L( ^& ~8 s% h
' L+ U3 C; R+ m2 z9 b5 `- void mbedtls_aes_ecb_demo(void)
- @ b5 f- h% q! W) q" Y! l - {
* T+ w' O# B, p - int i = 0;5 d$ K7 [( i2 w# `, d
- mbedtls_aes_context ctx;
8 K/ z1 X: k( W - ; Q: m E) |9 q; n& D& Q
- // 要加密的数据- R% @* \ {; Y. a2 j
- uint8_t plaintext[16] = {'A','B','C','D','E','F','G','H','I','J', 'K', 'L', 'M', 'N', 'O', 'P'}; h% j' g* Y: _) u
- / a. h" i; \' ~* X: i
- // 密码
2 H E& ^+ ^8 g0 q" d8 N- V - const uint8_t passwd[32] = "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDD";7 i9 W& e4 @' C; s
- ' ^3 E- f+ N7 h2 i* Z% d0 G& S
- // 加密输出4 v( e. u4 N0 S9 y
- uint8_t encrypt[16];
3 P" z7 J0 G! X) [0 j; B5 w& d -
$ g' J: h2 b; t: _1 l# r, ^6 h - // 解密输出7 p& ^3 o* n3 ]8 i, M! A7 L
- uint8_t decrypt[16];
& l+ \% |4 N3 Q* t j
9 O' f1 a+ O( N6 L! Q. N- // 初始化
: F t0 H. {2 A0 q+ e - mbedtls_aes_init(&ctx);* G: \' R9 L) [5 c
- 2 n7 u3 D9 _0 y N z8 @* q% b9 s5 c
- // 设置加密密钥
1 i# i( S" [9 y - mbedtls_aes_setkey_enc(&ctx, passwd, 256);
0 S9 C; d: i0 u4 h - 1 ?1 P+ S2 K0 M/ H! _: R" {1 }
- // 加密
' U* l4 |; e# u- \0 v% d - mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, plaintext, encrypt); R* t* M+ N q) N+ n" ~
-
7 J( X+ X) S/ R' ]' q - // 设置解密密钥
5 v) ~% L& k) g* W3 [4 F - mbedtls_aes_setkey_dec(&ctx, passwd, 256);
8 w V" k( T# |; X. q - & P! @4 H- ~8 l- g; L& _
- // 解密( w, b7 s, I5 `5 P4 K. o9 c! Q
- mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, encrypt, decrypt);
; f- u9 }4 d7 ` R z& y# j - 2 `2 [3 a G; D C; n
- // 清理
1 W8 n7 @( U" y7 i6 `3 f& J - mbedtls_aes_free(&ctx);* U# [# o( m) u- M6 T5 v
- ' K& O; D, i+ I
- printf("encrypt:");
$ @8 m) |- t8 v- k - for(i = 0; i < 16; i++)3 N" p) t6 F( h5 k
- {
1 b& @: b( U ]- D# f* ~8 k. p - <i> printf("%02X", encrypt);6 ]6 I' E! P6 T. z; E! n
- }
l/ D2 J" ^. b" q9 [/ ^" ?7 ? - printf("\r\n");+ y( W5 G, _1 N' l8 [
- ' b/ z: M( R! ]: k- U# @) X
- printf("decrypt:");" W+ Q, M* i5 F5 {& c) F8 j; y
- for(i = 0; i < 16; i++)- H* ^" a7 M6 I/ U4 b
- {6 y$ w7 z P* w! N3 x/ L5 F
- printf("%c", decrypt);+ A8 T9 p! f$ I& h- r P: z
- }' G# F) e7 q" Y+ ~2 K
- printf("\r\n");
% |( Y9 C: a4 S- @( O - }</i>
复制代码
1 j2 h1 _, V. EAES加解密测试代码(CBC模式):
! T# q$ V/ s; U, L6 B' i4 c$ e* R O
- m6 @% a+ s0 e$ f8 G7 R- void mbedtls_aes_cbc_demo(void) R# h. `8 M/ }/ a
- {
- [" K$ J2 n! T7 O( J8 `& } - int i = 0;
! {9 ]$ f" k6 B' @1 } - 2 B# q1 `7 Q: y( l
- mbedtls_aes_context ctx;
8 I- F+ X4 U+ A" S7 z4 I - # u/ o/ d+ R! h" X
- // 密码/ g5 [1 c# Y+ W2 u
- uint8_t passwd[16] = "AAAAAAAAAACCCCDD";
( g( L( U3 ` R" B4 e; x - / [ p7 t* D0 ^/ ?% U; i
- // 用于加密的向量表( e4 w8 {4 {2 J" u/ d/ p" u
- uint8_t iv_encrypt[16] = { 0X00, 0X01, 0X02, 0X03, 0X10, 0X11, 0X12, 0X13, 0X20, 0X21, 0X22, 0X23, 0X30, 0X31, 0X32, 0X33 };
* l% G# i Z3 Z, V - + F- W0 O3 e! e7 W, u- q0 P
- // 用于解密的向量表/ j ^6 p' |6 U2 {5 e
- uint8_t iv_decrypt[16] = { 0X00, 0X01, 0X02, 0X03, 0X10, 0X11, 0X12, 0X13, 0X20, 0X21, 0X22, 0X23, 0X30, 0X31, 0X32, 0X33 };
8 c0 m3 Z2 {9 n4 N3 Q - . H; C2 r: _2 `3 M9 N
- // 待加密的数据
! |7 Y, v/ \; ~/ ]3 E m5 f& m5 c - uint8_t plaintext[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' }; G9 q7 w& v9 ^
- ' s' p% e2 \- m, ^# f1 X" |
- // 存储加密后的输出' v6 ^+ N2 Q; e9 q. W' m" c5 f! i% i
- uint8_t encrypt[sizeof(plaintext)];
9 Y& Q. W1 {: s) s5 x8 }& T - : J' k0 I) C) S! q
- // 存储解密后的输出, Y$ d5 S" }- l
- uint8_t decrypt[sizeof(plaintext)];
2 q' x, X, i7 ^/ V. k
% D: R `$ c- g8 M8 M6 X P& P* {- // 加密3 y, x, X# x& \( ^4 Z
- mbedtls_aes_setkey_enc(&ctx, passwd, 128);& ~2 a8 \0 y7 \9 d* l" h( X
- mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, sizeof(plaintext), iv_encrypt, plaintext, encrypt);/ i: ^. }4 _8 h7 S
4 C& r: o q% V. Z* x q- // 解密6 w1 h9 q' o1 X- F+ |; V+ c
- mbedtls_aes_setkey_dec(&ctx, passwd, 128);
; w0 A$ L4 X2 p( n - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, sizeof(plaintext), iv_decrypt, encrypt, decrypt);
. H$ j. S, D5 k' H+ I" V - : _! I3 b* F/ G5 h
- // 打印出加入后的结果7 g/ [3 ~' U1 D7 j- N4 G7 g1 V# r7 V
- for (i = 0; i < sizeof(plaintext); i++)* b7 H- s9 l' k
- {2 o/ s: a% X- Q# Q
- printf("%02X", encrypt);
7 x* |7 P0 L1 O5 `) D: c - }; I6 Q! @+ `$ `+ r
- printf("\r\n");( e% y2 q% n* J) y- g5 B
- % N5 ]9 {+ o! Y6 C z9 E- z
- // 打印处解密后的结果
! B0 m0 F0 l4 r, E) t. x - for (i = 0; i < sizeof(plaintext); i++)
! b. h5 o! Y3 e" K4 N# F* J7 r8 h - {% b( d' h1 x ^$ j# ~4 ?
- printf("%c", decrypt);
( F# m+ ^& S, U* T5 z - }
' ?- `# F0 \2 ]6 S - printf("\r\n");
, C' s7 ^# u) c0 [: T; i& Q - }
* g% R, A% |; a" }( H1 M! a - : W. F9 I Q1 K+ `+ g. q
复制代码
2 p P% D0 `6 o: e2 |. p1 m* U' ]# Ymain函数如下:0 z' T- }* j; S8 Z5 ~: b0 ^0 j% H
6 a1 @6 y1 E- G# t* E
, [0 L) v" _2 r, i
& c0 c+ M$ y ]0 `5 ^0 q程序运行效果:
+ ^$ w B& H ~4 o, j6 ^6 A) }7 r, k0 V/ }. |
3 t/ G& u- e" P/ `0 q6 V) s. T3 x$ a
网上有很多在线AES、BASE64加解密测试平台,可以去做验证移植测试的准确性!* ~( k$ ]$ W( o) W+ @: S$ p
6 h$ G7 J }* |. ]" V! [% D! |) j( v5 N+ f3 P# r, N( k
; w) m: u7 A* L' f6 ^6 V
|