你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【NUCLEO-U083RC评测】③AES加解密测试

[复制链接]
小萝卜啦啦啦 发布时间:2024-5-10 22:52
STM32U08是带硬件AES加解密模块的,硬件加解密的最大优势就是快。

2 p4 H2 w7 \' m* I7 p& b6 m" z
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)

( Q; u9 U1 a+ y( N; X
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)
& W, P; G+ [. G
最后点击右上角生成代码
3.png

6 v) N, C0 l( e
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;' j9 x  J6 V' w2 {% {) c0 S
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png

, T3 z& F- F7 t- I) s- m
8.png

0 F5 y% S& Y; P3 F% m
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)
( }3 v; V. K( b# L4 n
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png

) h3 k$ U& i& |2 l( D: ~
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    % Z4 l9 Q1 t7 S% @" W
  2.                                    uint32_t Timeout);! ~+ [) G3 v( o8 \4 K  [7 f. q
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    ! n1 y. R" x/ \- ]
  4.                                    uint32_t Timeout);
    - j) V6 X+ b. k8 U( Y
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    : b  t4 K2 C+ n. a7 B$ D) f5 F
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    / m  r0 c. T" D9 D9 ]' L; z9 c7 _
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    # q6 Y6 Y6 f5 f0 Z5 D
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png

& s' i$ x3 Q. |" M* E
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现

. u) Z# m( B( h( h
今天我们的测试的是最基础的阻塞加解密函数

3 ~" U3 `! ^8 o! D$ n2 J
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */3 Q" U0 q1 E  |5 t- |
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];
    1 z0 t$ W$ A5 G8 d) F, U& |
  3. /* 计算得到的明文 */" t5 ~- u/ S+ }# q8 A6 Q6 B! g
  4. uint32_t Computed_plainText[AES_DATA_SIZE];
    ) Q' c7 U0 m" [; H
  5. 0 v% n/ R7 r, ~. w0 c% e
  6. /* 用户自定义128bit秘钥 */6 e- M. ~% a3 |
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =
    7 s8 D# L+ p4 Z" a
  8. {) h4 B9 u) E- a" A# O. C
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff/ R* W$ n  f* ~( q
  10. };# d8 C" x9 Z; c# _3 Y  G2 U
  11. /* 加密前的明文 */: V9 |. \& R1 ^  q# n7 x/ Z
  12. uint32_t AES_plainText[AES_DATA_SIZE] =( E1 u0 n5 u( P9 O3 M' @' Z# e
  13. {3 k8 {, p1 T" J' x  C
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f1 u0 P% e9 J0 `' Y  S' Y6 K
  15. };1 r4 [5 Y# |+ K: b  P

  16. 8 I( j" |$ }5 @* ^- C
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */% J) }7 ^' |( e8 r. a% I7 x
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    8 I% q2 R4 L9 v, X% L# `( Z! j1 @
  19. {, i5 y$ F8 W6 W# \8 T: R
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE0039 U. Z2 D& l8 o0 w/ }
  21. };4 p# |5 _, O  B5 v; \
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */
    ' K" {* k( i/ L$ C6 c, a9 `8 B3 P
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =7 `- W$ P. N5 U4 P2 G7 f! {/ @5 A) ]
  24. {- f* R% {/ u* C7 Q4 s
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A2826 o" Z% Q  q+ a- @
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的
% ?  |5 A# a8 B, n2 y
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */' c1 H- r( T( ~7 w" S
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说( M0 v. A3 V* H2 F( @; d* A
  3. /* AES加解密数据的长度(byte) */& ]% \" a; O8 c; T
  4. #define AES_DATA_SIZE_BYTE 161 @3 [2 h8 a6 b$ Y
  5. /* AES加解密数据的长度(uint32_t) */
    / u: {0 f+ t1 S
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4). e* v9 j4 @, b9 q/ T8 r
  7. /* AES加解密秘钥的长度(bit) */7 n7 I% X( d" c
  8. #define AES_KEY_SIZE_BIT 1283 c* ~- {4 y% d/ }6 [7 T  U
  9. /* AES加解密数据的长度(uint32_t) */; c+ \/ p' M  f' F0 n
  10. #define AES_KEY_SIZE (AES_KEY_SIZE_BIT / 4)
复制代码
10.png
然后写一下AES ECB 128bit秘钥的加解密测试函数以及dump函数
  1. void dump_data(uint32_t *pData, uint8_t Size)
    ; u5 v2 _8 L( l$ k
  2. {
    ( [) U6 |* R) c7 n9 {
  3.   for (uint8_t i = 0; i < Size; i++)5 P. a3 r6 [- ], W0 e9 G/ B* p+ y
  4.   {- d/ B& R5 g2 @' l) D0 z" i/ E4 t
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));! l2 {' m# @; s; P5 b
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));
    5 I( n& I( `4 V
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));
    - e+ g) ]% m& P  D0 s7 t! T
  8.     printf("%02X ", ((*pData & 0x000000FF)));
    ) V1 u* ~. F( |* N
  9.     pData++;
    0 _9 `: K* N8 d/ T3 ^+ d
  10.   }* h2 \! ]6 f" {8 W
  11.   printf("\r\n");, P* Y& [$ y6 E$ s6 |! t& N4 d: F
  12. }
    + i7 a& k: X7 H; z; a& a+ g8 i

  13. . x7 V% m7 [% E
  14. void AES_encrypt_test(uint32_t *plainText)
    - j( o9 E# U6 z3 b6 E& Y
  15. {
    / G. n7 H9 y/ H1 m: c: ]
  16.   printf("plainText = ");/ D! C5 i4 g5 ]. @
  17.   dump_data(plainText, AES_DATA_SIZE);6 j* g7 a+ A7 z' P

  18. / g8 K& q1 |1 o# K
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)+ M) Y2 d7 p0 i! a, S( Q  y
  20.   {- ~' l9 A4 F6 O3 d
  21.     printf("AES encrypt success\r\n");& U3 o# U4 K5 u& G2 M5 c
  22.     printf("Computed_Ciphertext = ");
    ' v5 f+ E$ }6 E: P# v
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);' e/ f( z2 R, }$ s6 u2 p: g, B
  24.   }- C8 ?3 L6 \8 ^1 b) f: K
  25.   else
    % e4 F/ i" s$ P" f' S: T! ]
  26.   {
    0 P9 c0 ]( L  m9 X1 t8 A$ Z8 l
  27.     printf("AES encrypt error\r\n");
    : f8 T% k2 `: V$ k" U* [
  28.     Error_Handler();& v! y$ O. g4 C# R0 s. \) n3 R
  29.   }9 M' Q" p$ @2 k( M
  30.   printf("\r\n");6 F9 P- Y% i# t. P- P
  31. }) V7 p4 w" c3 C6 S- d5 A
  32. # j7 `: f$ D& @, r$ c7 x
  33. void AES_dencrypt_test(uint32_t *cipherText)
    3 [8 y5 g4 n+ R- V7 f% g
  34. {
    & H6 M: c, i! L7 G5 z" d5 `" h5 X
  35.   printf("cipherText = ");) ^" V* E4 |" `6 _7 s
  36.   dump_data(cipherText, AES_DATA_SIZE);
    6 ?6 T' c9 D% j/ Q7 ]8 m

  37. , @* O& v, F6 Y: R* k
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)& K0 e5 B+ T/ z4 i! s
  39.   {' [0 w: Z9 Z+ s- N
  40.     printf("AES dencrypt success\r\n");
    - O, Z2 l$ i& t0 m: A$ x$ O5 |/ R9 E
  41.     printf("Computed_plainText = ");
    ' S; d- E7 x5 C7 q( u4 H
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);$ \% E; n+ c5 c9 L
  43.   }
    # q$ G) _* e! r- w7 I+ o! \
  44.   else
    5 s6 U% L6 V% q2 q: P/ Z' x- F
  45.   {
    " `" W' h9 O+ Z* T& Z
  46.     printf("AES dencrypt error\r\n");
    1 u2 t( ?* Q, I" P9 i
  47.     Error_Handler();) z+ H5 d! R# c  `3 D
  48.   }
    % O& a1 E8 X7 Y
  49.   printf("\r\n");+ r& c# W. U5 t3 G- J, B
  50. }
复制代码
11.png
/ w6 b5 {( L* R1 r/ t

% _) h4 a# R& \& x
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");( S$ c+ D+ b1 n5 w
  2.   AES_encrypt_test(&AES_plainText[0]);9 [0 J* t" ^+ L1 c7 M7 P9 j; T0 X
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");
    9 A& t) \" z: N# m' x3 g9 M  X
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png

: S5 d/ r# @; p, M/ F+ u: x
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。
! M2 a2 {0 q( R6 B9 @
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()
    , `2 w" \9 I1 [! a# G
  2. {9 A" x$ x* e$ w/ r* h; K
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");
    8 J8 g% b2 F7 S% b
  4.   /* 先去初始化 */
    * U4 w1 S, i$ T& T/ g
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)( |5 p8 N7 f6 W% q4 b: e7 c
  6.   {
    , \0 v4 Q4 Z5 ]" b& {- ^
  7.     printf("HAL_CRYP_DeInit error\r\n");' y, f) r9 s6 r9 O
  8.     Error_Handler();
    7 _" Y, K: n4 `: R5 h/ E% g  L
  9.   }/ r4 `) p/ h1 G2 W5 F. z

  10. % [& G/ H" t, i% C- f
  11.   /* 修改使用的秘钥 */
    ; {7 X' R9 M2 L7 Q% ]
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;3 q- _, l- A% c/ |+ n
  13. ; F7 A5 n+ B; D* u% L, ]/ h9 z
  14.   /* 再次初始化 */
    " i" h2 F5 J' J: ]9 K+ N
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)! g* ]3 Z3 P# y' Y. s1 C# b7 t' L
  16.   {
    4 i! c8 K/ Q. T5 W2 Z" p0 g, p& {
  17.     printf("HAL_CRYP_Init error\r\n");* Q0 r& r( F1 o" f) C! Y
  18.     Error_Handler();2 k2 k% s( d% c: x3 ~; H/ U
  19.   }4 S. u( Q) r; z+ v& i: D: S
  20.   printf("\r\n");
    9 M: q+ \* B+ ^) o$ I4 C  g
  21. }
复制代码
15.png

- G& j! }  n" a  t0 a. Y  ]8 D" |/ x, N0 H2 s1 ?: B7 c1 _
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();( }1 n( y$ q1 N# N9 G

  2. 9 N/ b; v5 u3 g( v
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");
    + h/ g+ V5 X$ a" s2 o9 d9 T
  4.   AES_encrypt_test(&AES_plainText[0]);) Y/ X  f- S- x2 c0 i6 U7 O8 x
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");2 S" L! O* [2 ]" M9 @+ D9 g1 [
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png
2 v$ L9 w& s. y1 H) V
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */
    : y( v% a' P; x
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =  ?7 ?& g+ L8 j0 G
  3. {& m+ O8 ?+ o& v/ s* b1 v; w+ \: [
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E783
    ( F$ b6 H* o$ p
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode()
    ! y( x$ _. X% L  y
  2. {
    : O% c0 v* Z2 K1 R7 E5 K
  3.   printf("change to AES CBC mode\r\n");4 F1 I' a/ ]! V* [' }$ G
  4.   /* 先去初始化 */
    5 t2 l6 W4 d" E$ M# D9 p
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    8 {! X1 S* I$ `; Q  N1 g4 G: T! [, T) Y
  6.   {
    * d4 S( ]' g4 h) t' q+ c
  7.     printf("HAL_CRYP_DeInit error\r\n");( @) W# Q; B& L+ |. ]; ]( W
  8.     Error_Handler();
    1 N) Z# i" l( w" j* v- G1 ^$ W- x
  9.   }8 Y  X% j, m2 D; d5 J

  10. 6 @1 b/ b  O  p% S' ]% M; T! \! T
  11.   /* 修改为CBC模式 */
    5 P. z3 [+ d2 y% \% V7 K  f+ J
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;
    # C1 C$ I# |0 u9 i. P: R; ^3 q
  13.   /* 设置IV */
    6 Q+ f6 R% q: `
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;+ Z7 W# |, y5 ~6 \+ \% ?
  15. ' h5 G% h9 F6 @: c$ @# N
  16.   /* 再次初始化 */
    9 R8 [, N3 h6 `+ C
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)4 `3 K% z0 N; N: ?' K
  18.   {/ y3 [; H" N1 k& k+ k2 U
  19.     printf("HAL_CRYP_Init error\r\n");% U- Z. q+ H% H' ?9 z! [
  20.     Error_Handler();
    % B1 l! P; c2 q& _9 G! N  U% p" x6 e
  21.   }
    6 Y9 J1 b! e3 G) r& h! B" I6 ^
  22.   printf("\r\n");
    ; F$ d$ |) Q7 b% Y+ ]
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();
    ; B- {& ?# M- r

  2. ( y0 ~. L5 K' M: E) z* |
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");9 {: y$ ~+ H+ N* c. o; [5 Q5 i
  4.   AES_encrypt_test(&AES_plainText[0]);( [- f0 y0 M3 r* J" j+ [; z4 _
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");
    5 V' g! N3 ^: I* w' Q
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。

& B% m, E) m  N+ S8 R5 G本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 3)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了
+ c) ~* p( K/ \8 o- ]
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版