(1)关于PolarSSL
4 {% C0 V5 {1 \9 q+ I6 R' o' xmbed TLS(以前称为PolarSSL)是TLS和SSL协议的实现,并且需要相应的加密算法和支持代码。这是双重许可与Apache许可证 2.0版(与GPLv2许可也可)。1 L" B$ F$ @* Y% G" ?: T
核心SSL库用C编程语言编写,并实现SSL模块,基本加密功能并提供各种实用功能。与OpenSSL和TLS的其他实现不同,mbed TLS设计为适合小型嵌入式设备,最小完整的TLS堆栈需要60KB的程序空间和64KB的RAM。它也是高度模块化的:每个组件,如加密函数,可以独立于框架的其余部分使用。因为mbed TLS是用C编程语言编写的,没有外部依赖,现在叫MbedTSL,PolarSSL源码,也许是最小巧的ssl代码库。高效、便于移植和集成。尤其适合嵌入式应用。
7 C3 J" W* F" H% g! X A$ Y1 D, L, c( {1 B" W; Z1 w# b- n/ t/ U, f
本章就基于STM32移植mbedtls-2.24.0版本进行测试与使用!
% p- G* K# M/ g5 x
" h, W( K. t+ |& z0 x- ]+ b注意:因为本章节只是用了加解密的API,没有使用网络进行SSL认证操作,如果要使用mbedtls的SSL认证,最低的硬件环境最低需要60K的FLASH以及64K的SRAM(内存),如果你使用的比较低端的STM32,那么无解,没法用embedtls。。。1 R, ]; Y: I) c9 `' g7 i
0 e8 z _; _5 r( C
(2)mbedtls移植
! }9 a( H8 g, \首先使用STM32CubeMX建立裸机工程,我使用的是STM32F103RB,配置了串口一当作信息输出的端口,这里注意,mbedtls所使用的栈空间是比较大的,所以在STM32CubeMX输出工程的时候将栈空间调大,如下图:
, U! Y( R% N7 A) X- z- w! q
3 |. j9 }; d4 j/ j( r
% x! A' t" z9 N
$ M' V( [8 C" N" Z
下载解压mbedtls源码目录如下:% n8 x3 w5 M+ m C, x
% l: b5 `* v& s d4 T! I
6 B& C8 x; y1 p- Z8 W- l
" D2 q9 O0 P/ \( a而我们需要的仅仅是configs(配置头文件)、include(头文件)、library(源码)。
2 n1 C: t" b3 i# O$ |configs,该文件夹内的是配置头文件,可以根据不同需求进行选择,例如我们本次是在嵌入式系统上使用,资源有限,所以就选择config-mini-tls1_1.h这个配置文件,复制该文件内的内容替换mbedtls的默认配置头文件mbedtls/config.h即可。include,所有头文件
% q. H1 X; C r5 |. u1 P7 Glibrary,所有源代码) D2 `! B% R3 U
3 i1 k7 o) q; a1 Y" v- a, M, t首先在STM32 工程目录下建立文件夹mbedtls,并将mbedtls源码目录下的include和library两个文件夹复制过来,复制config-mini-tls1_1.h文件中的内容替换include/config.h。(注:include/config.h文件是只读的,需要先修改权限为读写)。% Y2 A4 @( N/ j% W4 Y
( K5 X" o" \( t# T" b打开keil工程将源码添加进来:8 ^5 f8 ?1 g# N0 E5 w: c( U0 }
7 o* X" w8 Y4 v* |9 T/ L4 V
! Z0 c/ r( R* }6 N
2 t% D8 s- C0 b5 X+ W5 {7 z x G' u+ ?添加头文件包含:
5 E0 I! Q! N' L$ k3 S' v
% j% V2 ?! m! A
& s& u# W& ]: {% r: [
0 H4 G5 w" o& |0 J, F" T修改include/config.h配置文件:7 {* f/ L8 U" p
注释掉宏定义MBEDTLS_HAVE_TIME,因为我们目前没有用到时间相关的
1 U% _9 |7 r$ `2 z注释掉宏定义MBEDTLS_NET_C,因为没有用到网络
0 R- \- h$ M# t8 w注释掉宏定义MBEDTLS_FS_IO,这是带系统时候需要用到的标准系统调用IO,例如linux下的系统调用函数read、write等,裸机我们没有用到
+ ]* n, v+ I$ {, d2 Y添加一个宏定义MBEDTLS_NO_PLATFORM_ENTROPY,单片机无系统所以需要添加该宏。1 Q9 P z0 c; } W- m8 x
: i" J+ M; o `; Y" K; R% d; {
然后编译工程即可~!
, X- x U, o, u/ c8 L! |3 c. P% ]' T& M& B/ Q
(3)移植测试
+ A* v/ S/ O6 b/ D W将printf函数重定向到串口一输出:
. F2 D, U* G" v" p7 b7 Q6 `4 J6 U+ r. w, K, g% p" |% }
- /// 重定向printf函数到串口一: Y: c2 Q6 c, C3 q3 h# L! q1 d
- int fputc(int ch, FILE* fp)
: \( x2 w7 ~, M% _4 c3 x - {& n( A& V" R- ]! U* K
- while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TXE) != SET);, f$ b% H9 ^9 E8 q0 M$ a5 P7 r
- huart1.Instance->DR = (uint8_t)(ch & 0XFF);9 e+ x0 z6 V X: w8 q
- return ch;
: Z0 K$ Z2 Z% ~) P9 h - }
复制代码
3 f. Z0 {8 Y/ F下面我们开始编写代码测试,测试两个,一个是base64编码的,另一个是AES加解密的,
! T; \. A$ \2 |4 V& J# I# `% G需要添加头文件:
0 v S# w1 P" N5 }7 {
0 x+ {7 x z+ @; H. A- K& f- #include "mbedtls/config.h"
& q9 |* O2 ~* I2 M - #include "mbedtls/aes.h"
& E, w9 b. M F9 ]* Q3 _4 q - #include "mbedtls/base64.h"
复制代码
2 `+ A w5 h% N2 v& abase64编解码测试代码:
* s* O4 s+ p% G- d& E4 H1 V
- J3 v1 c3 ~% L% s" [- void mbedtls_base64_demo(void)
( r* S3 ]! @ ^- M5 @ - {
0 n8 C2 z+ x2 ^6 ? - int i = 0;! P/ k, T2 p, `, @
- % a" x( B/ {5 J# h2 |% f
- // 原始数据& I; y3 Z6 b# v& F
- uint8_t plaintext[16] = {'A','B','C','D','E','F','G','H','I','J', 'K', 'L', 'M', 'N', 'O', 'P'};0 Z m' @: V% S7 V6 }
- 9 ~: z1 s- E' K& x+ y0 h( @
- // base64编码和解码输出数据的长度, p& o! {4 \ g: L2 o6 `, A0 b
- size_t enclen = 0, declen = 0;
4 C p5 O9 @) P$ U* T - 1 z! I4 z+ m6 C6 I& m
- // 存放base64编码输出9 c' Z$ u2 f6 Z
- uint8_t encode[32];
3 ~# r4 z% m+ Q: b- I% \. q, u G$ i
- Y6 r4 V& z: ?- g3 l- // 存放base64解码输出4 t( I+ W" {6 X1 I5 ]! F
- uint8_t decode[32];7 P+ ^( w/ ?7 ?0 E, D
- * p" s7 C! C' j% R, V$ p
- // 编码
8 r; B7 g4 N8 U$ m7 K/ m9 } - mbedtls_base64_encode(encode, sizeof(encode), &enclen, plaintext, sizeof(plaintext));, x$ B/ U y% z c& \% y! ]
- % M. B+ Y% v8 T! l6 T
- // 解码7 I7 B9 g6 L# a
- mbedtls_base64_decode(decode, sizeof(decode), &declen, encode, enclen);
& ~9 R/ S, R# b9 \5 l% ]7 f
3 L) C- E& {& G5 H- printf("- enclen:%d\r\n", enclen); f C8 ^7 n" s
- printf("- encode:%s\r\n", encode);! @5 v: e) _: D* s( O0 c& \
- printf("- declen:%d\r\n", declen);
& J7 ]% E* [1 {( [ - printf("- decode:");' d& A, o1 J2 ^: N4 }6 H) Q- N
- for(i = 0; i < declen; i++)) Q H, ?% S9 H4 E! h
- {# J- [) n* e- Q) a+ I
- printf("%c", (char)decode<i>);
9 d) @. m x: D/ M4 H - }
! t, Q, f1 I% D( c7 m$ p4 K( e8 I - printf("\r\n");
* s: s& D, E" g0 |7 T* h4 {% q - }</i>
复制代码 8 A; ^$ B- z8 s
AES加解密测试代码(ECB模式):
0 B" J* Z9 ~: E
" h8 b; D2 S+ T( P% [# u- void mbedtls_aes_ecb_demo(void)
( D+ \$ C" }! E" }' C, w - {
/ P X* |3 X$ H" x - int i = 0;3 q4 B ]" r0 @# ^
- mbedtls_aes_context ctx;
" t8 T$ E8 Z" f }8 X -
, b) G5 M0 ?& e1 `5 m9 ^) y( l- U - // 要加密的数据' t+ G/ E; r. ^: R/ v
- uint8_t plaintext[16] = {'A','B','C','D','E','F','G','H','I','J', 'K', 'L', 'M', 'N', 'O', 'P'};: y6 M+ F# q+ }( Y* v4 l/ K8 W
- ) w* g; T! Z. ?& L! ?( C; {7 S# o
- // 密码1 `/ ?9 q1 l5 H' V
- const uint8_t passwd[32] = "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDD";- K6 e5 q0 J- U; k
-
0 ?% p6 U6 q m$ ]" P( k - // 加密输出- e) L: |; z& J. Q" q# R
- uint8_t encrypt[16];' P C8 b9 q6 l) o2 F) S
-
k( W" E4 L. @ - // 解密输出
$ x* ^+ m! \! K% w% L2 K+ J - uint8_t decrypt[16];! l+ f D6 T- N: w) i0 _$ M
- 7 S$ v: S q: c$ O, D7 }$ L
- // 初始化/ ?. X. C: m+ }1 u3 x# ?/ q1 Z
- mbedtls_aes_init(&ctx);/ L t2 K' a ?6 E
- + j) U8 e) g1 m
- // 设置加密密钥
& |/ r+ m8 `+ F$ s+ V - mbedtls_aes_setkey_enc(&ctx, passwd, 256);1 k( h/ ~% M' r1 X. j; T
- ! S2 L: L7 L7 B9 x% o
- // 加密0 X: B% K5 `2 ]8 E
- mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, plaintext, encrypt);3 ~% `* ]( l }! a* H/ ?
-
# j! h( A: I* V* y2 H" g' {+ C3 H - // 设置解密密钥
0 [7 w3 g$ [& K* U m$ ~( M9 K1 O' Q# k9 N - mbedtls_aes_setkey_dec(&ctx, passwd, 256);1 n/ R' G4 e+ N; ?' ]
-
. \% w2 N+ o& n2 M" o' t+ q - // 解密
0 G4 r- b0 e: P# P1 Y0 N. x! u* n$ [( G6 U - mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, encrypt, decrypt);7 F9 A& @5 |5 ?& ]7 E7 v) O2 S
- 3 z( O: P2 t5 x6 ?. y3 i: X; U
- // 清理
1 P- u$ B% n/ Q* y* v- ^& g, h: e - mbedtls_aes_free(&ctx);
. B- K. n6 w' G4 u ^ -
Z7 g5 }" ^8 m/ ? - printf("encrypt:");( p4 z! [ E& ~; Y; v. n. |* e1 {
- for(i = 0; i < 16; i++)( J/ y. N ~% O. @+ @4 X; W
- {+ M/ S# | Y- b, g, \
- <i> printf("%02X", encrypt);! V1 F2 F7 U2 Z1 i- M3 |- S
- }& Q8 {( g$ q, w5 X- E: O
- printf("\r\n");
& {2 S% @/ Z2 h: N" i8 o
6 L: y( _' J" G1 ~! }. C* K3 u- printf("decrypt:");/ D _$ A/ E8 p
- for(i = 0; i < 16; i++)
* Y* N7 O' B f0 F+ I) I - {
: U* h7 `- \7 F3 N) \ - printf("%c", decrypt);
" q9 G D$ J( _ - }
8 i" u; C0 ~* z' P" k - printf("\r\n");
0 `9 ]2 Y! z* ~* B0 f - }</i>
复制代码 ' X$ W4 A" X# x4 b5 x0 ?6 _
AES加解密测试代码(CBC模式):
7 u5 L# k6 O: S# X8 x( {6 z+ V* K" Q7 X9 F- x
- void mbedtls_aes_cbc_demo(void)
* D5 T4 A, x' D7 l7 F8 G - {* U3 e; l# | s. G; N
- int i = 0;
8 W0 g/ b1 y+ S4 O
3 [7 M- R: g3 T' e1 s- mbedtls_aes_context ctx;1 o' j- @5 d% y& I$ x3 O! e
$ a8 ~$ [% M3 o9 b& ~; G# w- // 密码5 M" w! i0 y' i. W" u: P0 d
- uint8_t passwd[16] = "AAAAAAAAAACCCCDD";
+ e6 A( P0 L* _4 b - # U) J- H" L- ~7 u; c+ v9 x$ z( {* m
- // 用于加密的向量表
( T! z$ I4 P1 N1 z0 u - uint8_t iv_encrypt[16] = { 0X00, 0X01, 0X02, 0X03, 0X10, 0X11, 0X12, 0X13, 0X20, 0X21, 0X22, 0X23, 0X30, 0X31, 0X32, 0X33 };
" E' o' v4 {- e. Y3 ~ - - c p8 i( R! ]0 R' `1 B0 M
- // 用于解密的向量表
- h) c: z1 E+ _$ G( [$ V - uint8_t iv_decrypt[16] = { 0X00, 0X01, 0X02, 0X03, 0X10, 0X11, 0X12, 0X13, 0X20, 0X21, 0X22, 0X23, 0X30, 0X31, 0X32, 0X33 };
1 R& H) {2 u. Y; m# s) m
f U' i+ ?& J) r+ {! }1 p+ l9 L- // 待加密的数据, i" @6 n7 ]. w
- 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' };+ j8 u S {8 |2 k; i
- ! ?' \; P- l2 _
- // 存储加密后的输出
, l+ A/ C: e4 N0 x! B8 ?$ c - uint8_t encrypt[sizeof(plaintext)];. V" s1 S6 {( v, [
( S% \& e6 @( n4 \7 C- // 存储解密后的输出; D2 t9 Q. P6 U
- uint8_t decrypt[sizeof(plaintext)];
/ R. z4 `, J: m# |+ c1 ?, \. }) ? - # I3 m% v9 a- l& P& O
- // 加密
- Y; G, i8 P4 z& z p - mbedtls_aes_setkey_enc(&ctx, passwd, 128);
# g3 B; ?8 S- z" d2 X$ S - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, sizeof(plaintext), iv_encrypt, plaintext, encrypt);9 C- K$ j/ q# t, |. O8 C
6 C+ F+ w8 H% u- // 解密9 i6 d) P8 M6 V/ ] {& l$ ?4 R
- mbedtls_aes_setkey_dec(&ctx, passwd, 128);
% Z5 l5 ~0 b8 F' @ - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, sizeof(plaintext), iv_decrypt, encrypt, decrypt);7 i! l5 I* Q: p+ U g5 V
- 2 B9 W5 ?8 R5 r# K
- // 打印出加入后的结果+ |7 [+ R: s" q5 | f
- for (i = 0; i < sizeof(plaintext); i++)
+ y+ q- c' n$ k7 o0 N& S - {7 m) z* T+ |) B4 T
- printf("%02X", encrypt);
; R2 \. i+ `# i* n' s+ O - }5 c/ G/ ]( l/ n( v7 l
- printf("\r\n"); u( i$ i m' e+ C) P9 ?: M- z
- 3 _7 z( D& w# `, w7 k8 ]
- // 打印处解密后的结果
7 p, {( @ K9 ?) k1 @ - for (i = 0; i < sizeof(plaintext); i++)
0 F$ M. Q2 ]7 m" W - {' m; p5 Y6 `/ q
- printf("%c", decrypt);
5 } b) x* b' R1 V, D! M7 Y$ W! v - }2 K4 ~4 z" y: r! a! O# p
- printf("\r\n");' Q$ w! g" _, `# n) k R
- }
+ h5 R! u6 i' g" x5 t# s1 o% B
9 y A* Y' @- [
复制代码 + @. h% P3 f) x# \
main函数如下:
: W: ?+ J. l' f. g3 S$ Q0 \) z y; b2 n7 o7 U$ k* f
( K- r0 D6 [& ]
6 x, b* \ A5 \5 B) K# V2 U; k% @
程序运行效果: y3 H3 n1 k8 H' k3 y
7 l& ]! g ]7 z
4 Q( C& C) V- X/ _; Y, K
- e1 G3 ~3 y' {7 j
网上有很多在线AES、BASE64加解密测试平台,可以去做验证移植测试的准确性!: R p* p5 o# ^. k: X
! b6 a* e- V' `, H8 x9 v! ?6 I, Z# p7 r& k
' l9 E& h9 r* Z5 ^- s |