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

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

[复制链接]
小萝卜啦啦啦 发布时间:2024-5-10 22:52
STM32U08是带硬件AES加解密模块的,硬件加解密的最大优势就是快。
6 i: m' ?* r7 n' I& ~
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)

+ o3 c4 x- k4 ?' n, V7 C
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)
+ V8 ?  t9 I* y* c7 X+ a+ }3 m
最后点击右上角生成代码
3.png

5 G0 b% G' S8 m/ |. j0 @$ Q8 q! b
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;
    9 j  N5 x( S0 Y# P, V% f
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png

: H1 Q, O3 `& h& r5 w* g
8.png
2 p' j; ~. a, L6 o
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)

7 _0 `4 W% d0 l
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png

% H( w3 Z8 Y- t0 O/ |  l% {( c0 j
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    1 [4 O1 B% p4 w6 T. {# X8 G/ p5 P
  2.                                    uint32_t Timeout);
    5 m, c% y7 E+ C( u5 A6 p
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    0 Y! X- z% V; e2 F
  4.                                    uint32_t Timeout);
    / R# q  J7 c# ?; `- n
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    6 L+ A5 G% r' l5 N9 r0 C- q
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    * ^% l7 A! r! w
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    , Y0 c& S( C1 E" }6 f9 M$ @& A
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png

2 u& u% Z; u5 V- {9 J& m
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现
% i3 U4 p5 q, N9 [7 T
今天我们的测试的是最基础的阻塞加解密函数

7 {$ f9 {) _5 E, t
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */1 H9 f9 t- `* |; O
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];+ t  f9 e& V/ W, J
  3. /* 计算得到的明文 */% O1 f3 J" r6 C' t! C
  4. uint32_t Computed_plainText[AES_DATA_SIZE];* v, y$ {  @' u' m, S

  5. * F  a% k( i' T8 d1 z( s& w
  6. /* 用户自定义128bit秘钥 *// g  Q, d' D6 e4 p9 o; z4 g5 }  [
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =5 L# W0 j$ x. F- y
  8. {# j+ x* N$ s! M& j. \, e8 X5 N
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff% a; U5 I0 ~/ y# B
  10. };
    6 @4 a( \0 e8 Q* h% x4 ~7 e
  11. /* 加密前的明文 */9 J. u  a, S) E/ K) j) M
  12. uint32_t AES_plainText[AES_DATA_SIZE] =- A) N# B* h1 u, |  b8 C6 p
  13. {
    * x# T; J" N' l: ^' O9 T+ O  s
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f0 K* Y4 \2 f6 C3 K* |4 N. p# X& `
  15. };
    2 r& t5 S9 j  F  h3 y, W) N
  16. & z9 ^8 z6 B5 ^. e; }: x
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */
    % r; b3 {* T, S: x1 K
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    4 G8 W# Q$ b. u$ ?3 b
  19. {
    & Z! l" n* c7 r3 ~$ R
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE003
    " W# t! O4 L' ?; T8 k/ x$ k
  21. };
    , B/ p' `  f1 C5 {9 z
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */
    * g. N6 Q$ ~6 U7 e: Z1 s
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =, e) G, H$ R! W; `, c
  24. {
    ( e" |. n7 p2 V' o
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A282
    , `( \9 M+ S/ T7 {+ x( Q" h
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的
2 c% f5 K4 O  f3 M
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */- f: O7 A0 [# n* k1 y2 w0 r
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说$ K" F6 W/ `1 X; s( f4 [
  3. /* AES加解密数据的长度(byte) */, s2 i- q3 L( ~; Z- [. ^/ _
  4. #define AES_DATA_SIZE_BYTE 16, _5 F* I& N% }4 v) c& G! C1 [# l
  5. /* AES加解密数据的长度(uint32_t) */" h# G0 E% Z9 \) q
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4)
    + L+ X( a5 o( W$ {/ a  w: P6 c
  7. /* AES加解密秘钥的长度(bit) */& {' p/ z# g# @
  8. #define AES_KEY_SIZE_BIT 1281 u' T9 r1 L# ?( Z* y
  9. /* AES加解密数据的长度(uint32_t) */  u" a; ^. L* v+ F- k, X3 Z
  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)0 a; v, |' t& l& h" @: n
  2. {2 M4 Y& x! u! z: M- Q. |' g
  3.   for (uint8_t i = 0; i < Size; i++)
    1 K/ D8 o! o1 I9 R3 z$ N" w7 _
  4.   {
    % G: e& ^' C* w6 V7 F/ t" P5 O/ {
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));+ r# V; n7 i) r/ v
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));
    $ N  O1 e5 Q  L$ Q6 U" {% s
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));
    ! Q6 P" q) m1 W$ U
  8.     printf("%02X ", ((*pData & 0x000000FF)));
    % r0 F6 u/ ~  T, |0 b+ t" d
  9.     pData++;
    - v# L3 h1 w$ v% j& x+ T* |
  10.   }
    / o" ?0 e% f  H4 H7 Q7 t' P5 d
  11.   printf("\r\n");3 z- t" }% p( F" F3 m
  12. }# A( ~. I  V0 E: z+ z& X/ `1 P4 ?. K

  13. + ]* w5 k, k( V
  14. void AES_encrypt_test(uint32_t *plainText)
    . f+ k8 R& S6 F+ G, g
  15. {0 E3 o6 }* _4 s, f
  16.   printf("plainText = ");" z3 O( J6 S9 P$ u6 c; y6 ^
  17.   dump_data(plainText, AES_DATA_SIZE);
    0 d  a+ z( ~. w! }3 f6 S' i+ `; \

  18. 3 ?4 j% v5 y% b* v
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)
    4 P# B* L8 f% Y3 |" Z2 e( ~% X
  20.   {8 D- o" j( `' k1 ?# u
  21.     printf("AES encrypt success\r\n");
    1 V" F* g0 `" R6 C1 W' @. l
  22.     printf("Computed_Ciphertext = ");: N- d5 ~" x8 o
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);
    ( L2 @  L- a, ^
  24.   }
    ( Y  M  O1 D- R" W* k( B$ s  a  z
  25.   else
    & B; H* U6 \. R
  26.   {
    2 h9 b6 x$ }  r! Z% M7 M
  27.     printf("AES encrypt error\r\n");! t& c; A2 u/ l
  28.     Error_Handler();
    : Y% f' Y  Z& B
  29.   }, Y3 X  z; W# R; j4 b  m; T
  30.   printf("\r\n");2 ?3 N* U; m8 n7 z. |& J
  31. }. t- {, p- B" y  e. {# t  b
  32. 5 q: f. J2 Z! L5 W9 B, O
  33. void AES_dencrypt_test(uint32_t *cipherText)* S0 h& O7 t6 @( }
  34. {
    9 G7 b( _4 ]* `$ m+ F
  35.   printf("cipherText = ");: P" L' t5 k+ U* u1 ^
  36.   dump_data(cipherText, AES_DATA_SIZE);
    ' s* X8 d7 x- q
  37. ; d: w/ y  S, W. ~1 |' i, b
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)% y0 c! Z" J6 N1 D  |& B
  39.   {0 D9 z5 {  g8 n7 ~  j
  40.     printf("AES dencrypt success\r\n");
    + s3 y4 A- t0 U) r& ~" A
  41.     printf("Computed_plainText = ");
    ) x/ }: D* ~8 `9 m5 [
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);; a$ L8 w4 Z' T5 i$ a
  43.   }
    & {) c7 M4 X6 N  g+ I9 P
  44.   else
    8 G, F7 L4 j) G; g+ o5 |7 ]1 u; {
  45.   {; N" h9 D0 L$ l9 R6 |
  46.     printf("AES dencrypt error\r\n");
    : s4 ~7 c8 U$ V" o& x
  47.     Error_Handler();
    0 o! n3 v: }, `9 L
  48.   }
    . i, Q$ o' X! s8 \2 x7 @; h. v
  49.   printf("\r\n");
    9 R) b( E" r" l6 D" w0 w- ]/ l
  50. }
复制代码
11.png
& F8 ~% U& W) c2 G- u
8 H# T* J/ o# n" Y# I) W; w# W
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");: y% ?& R* i' K; N/ v% ^3 W
  2.   AES_encrypt_test(&AES_plainText[0]);
    - _- G* ]6 x7 K0 ^3 B
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");5 V9 w. X* |4 P" D! Y
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png
) X1 G3 J1 ^3 H) A9 C. ?
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。
9 [9 T; `" q+ f1 o' y4 s  j+ J! b
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()0 W1 c4 n  b: }( ~* ]7 t1 q
  2. {6 Y6 f/ |" h% B+ C
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");5 w7 k. Q: t: S9 @9 H
  4.   /* 先去初始化 */5 {: S7 u- K; R7 p0 p$ m
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    1 V1 q  n+ @  v+ h  ~0 U
  6.   {
    & a* c! G/ t( @. S; z1 S2 R
  7.     printf("HAL_CRYP_DeInit error\r\n");  C+ m5 N1 U% E) h; W8 Y3 d
  8.     Error_Handler();
    ! i- x. t+ o; ~5 Y
  9.   }
    8 r9 C4 X- R$ m* T2 h: {& s9 S
  10. ( N) `1 o; S  n2 `/ V0 E
  11.   /* 修改使用的秘钥 */0 |9 K, @# y5 M
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;
    0 N+ s3 F6 U+ p4 I( }9 c" B' D
  13. + M3 B/ v. z9 g' @. |3 c* `
  14.   /* 再次初始化 */
    1 d3 i' d5 z+ J0 t
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)7 A, E& L( `4 g) C9 o4 y% m
  16.   {
    ( Z: I5 D# A4 q. p! p
  17.     printf("HAL_CRYP_Init error\r\n");5 d* M- \+ v9 D; b2 V
  18.     Error_Handler();
    , \! M! S! N3 A+ Q8 ^1 z
  19.   }: n( B7 {8 i+ n/ G5 J& Z( M8 L' x& v
  20.   printf("\r\n");
    * \, j3 Y; E. c
  21. }
复制代码
15.png
4 J% I- d1 o6 _. n

0 F0 w8 ?: q1 R& n& A
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();7 O, j' \# z4 B8 n* R' m
  2. / N. A) O3 w; e8 P6 W
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");
    % `: J$ G5 |0 m" y
  4.   AES_encrypt_test(&AES_plainText[0]);9 D1 S  o6 \  M& d# C
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");
    1 c/ N" U8 O/ M
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png

4 C- T5 g4 ~8 O  L+ e
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */- W/ v$ D- m6 g9 q& ~3 w
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =; y! t9 G" `0 Q7 n  @" |
  3. {7 P" L. y  b+ @+ d
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E783
    : F% F9 X: c& y1 T; C( }' u$ b
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode()8 G) W6 n* s: V" c
  2. {# N2 c! d* n7 X0 d% q
  3.   printf("change to AES CBC mode\r\n");
    4 G7 l3 ^% ^9 L8 q4 u2 f  A& p
  4.   /* 先去初始化 */- U, g$ O, h8 H8 g
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)$ N1 l9 ~' U5 A3 A6 }# s* w
  6.   {/ |2 O) Q  ]& h& @5 d+ j
  7.     printf("HAL_CRYP_DeInit error\r\n");* b# U$ u1 E9 n- q1 c
  8.     Error_Handler();
    ( }* \, t6 w; s. f/ o
  9.   }
    2 u7 R* W+ E+ ^1 {! g& G! d% ~
  10. + z% Z7 L6 ?2 ]. z
  11.   /* 修改为CBC模式 */
    " F2 R, K1 v/ `$ s# D
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;
    " O( G( W# C: W  e
  13.   /* 设置IV */+ [9 W4 n9 m6 ]2 B6 C* _
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;
    8 A. o$ z; z  N6 G/ X

  15. & W- l1 n, J+ E# {7 [5 g
  16.   /* 再次初始化 */- J, z' m* E# j9 M9 @& l
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)" E5 ]+ P  H$ y2 K0 I9 q" Y
  18.   {
    , c6 q% A& S  A1 T$ a
  19.     printf("HAL_CRYP_Init error\r\n");
    - \5 M9 i* D! }! P) T! w/ L9 M
  20.     Error_Handler();
    . N. G$ }4 }7 t# ?/ g. Y
  21.   }6 C; j4 G( j9 ~9 `+ F
  22.   printf("\r\n");
    5 z9 n1 C" f, ~2 S4 b& S9 m, f* K
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();' P5 S* p+ f* @; O! ^

  2. ; ^$ s1 y0 _( X+ o7 G. I  r
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");
    5 T2 W9 Y5 w; ]& w. b( |' E
  4.   AES_encrypt_test(&AES_plainText[0]);7 Y* O& S7 G9 k# r4 ^
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");; B) ?% G# E  O- o4 R4 E+ ]
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。

- \9 J* a" D: c" q本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 5)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了
) X  _: S, X% t/ P! b
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

所属标签

相似技术帖

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