请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
小萝卜啦啦啦 发布时间:2024-5-10 22:52
STM32U08是带硬件AES加解密模块的,硬件加解密的最大优势就是快。
1 A. o9 H* j, V3 J9 o" ~
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)
& ~7 _; b5 c: j  n7 D3 f
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)

" d1 x) ~& `9 m4 O6 k! R# w  B
最后点击右上角生成代码
3.png
" Z4 U. n( y8 l% @* M; A
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;
    ' Y. S3 C# a; D2 P. O
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png
1 Z8 e! x: l6 q/ A% K
8.png
" l- V$ a' \+ e5 |: d) D5 B
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)

) A3 a; w. z/ C+ A) C
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png
, E; K7 _% r  D$ u9 {/ y3 S
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    + H2 h8 u" @; q' f
  2.                                    uint32_t Timeout);! F. ~' D4 F+ \3 n! }4 h9 A) @) S* I
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,. P) t: T" L' I+ m& O! I' I
  4.                                    uint32_t Timeout);
    8 F' m6 i# b% V, j/ f
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);; x: \% X" h  W4 i$ t# q$ E0 _7 A
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    . v) D4 ^& F7 @3 i0 Q6 j
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);- t' |  L" e4 }; L2 ~& J( L
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png
: e9 c1 J9 a, y2 d- j) \
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现

4 P# G5 X  Y, ~6 t
今天我们的测试的是最基础的阻塞加解密函数
1 u( p, y8 ^: y2 D2 H# e$ _
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */* Z6 ]. M; ]9 m$ e
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];
    6 q4 _/ ^% r) U2 `
  3. /* 计算得到的明文 */7 J* ?. K4 N( G7 c: l. n
  4. uint32_t Computed_plainText[AES_DATA_SIZE];8 t: \5 k1 k8 o  y& Q
  5. - |: n, l) O: E( d
  6. /* 用户自定义128bit秘钥 */
    : e# |8 W+ `! _+ Z6 M8 d8 v
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =: L% V7 I8 d  j4 N
  8. {
    6 i: d9 B6 ]3 t  h# Z" O0 m: x
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff, i9 j& E  _3 T$ F6 L. l7 j, S* h
  10. };0 m- y, i& q# R7 p1 G, T3 ^& f6 e
  11. /* 加密前的明文 */! {$ \* {0 @/ ]
  12. uint32_t AES_plainText[AES_DATA_SIZE] =/ I4 U1 a/ ^) W4 c. {
  13. {
    6 O( _9 X0 E% P0 T0 H4 B
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f
    7 H% [0 E% }4 W- G1 G) D
  15. };8 y, @/ x' K5 g3 f

  16. 4 X% C1 k# @& L" t
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */
    * @6 F& @3 X; B8 B
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    ; T/ h5 o' I. `# E6 a/ g& d4 z
  19. {6 t# K: T) G5 L3 Q, H. r3 O
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE003
    % [) N( I/ |3 h  u3 D5 ^
  21. };
    : w. b! @8 l5 ]9 M0 v; q
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */- z( _6 _9 e# ~% t  n
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =
    3 a+ v+ I# x8 ]% t0 q
  24. {4 |% t8 N2 s' _
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A282/ Z$ X- }" Z8 a" P5 G2 L! A
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的

; D5 F. |& v7 C5 m7 R
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */
    ( T3 Z9 B' O4 l* J
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说, d! \) k) X- h" c
  3. /* AES加解密数据的长度(byte) */, g- \% ?7 k9 r- h5 |6 ~9 l
  4. #define AES_DATA_SIZE_BYTE 16
    . P) |1 o" Z: m) [, V) b
  5. /* AES加解密数据的长度(uint32_t) */
    & d# \$ B% O7 M' P, ~+ }
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4)+ q, L" V, x/ H/ A9 \) _! z! u4 p; j
  7. /* AES加解密秘钥的长度(bit) */5 b9 k1 b& I# t& e6 b' @: q4 q; |
  8. #define AES_KEY_SIZE_BIT 128
    - a2 d- R1 |' I# a- T! g3 C; B1 W
  9. /* AES加解密数据的长度(uint32_t) */
    9 s8 Q# M" c! q
  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)
    % w1 N+ C$ @! p3 j
  2. {
    ( `1 E+ `) U' Q5 p' D- `
  3.   for (uint8_t i = 0; i < Size; i++)
    ' U8 F- K. `8 t
  4.   {3 R2 U3 Q- V+ ?  `2 p- L
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));; }% [7 F; H. k5 I  i; t
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));
    % o6 i- c/ G. `$ n! [8 _- c; I& K( h
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));. U0 `8 I$ B7 F0 _% T1 Y
  8.     printf("%02X ", ((*pData & 0x000000FF)));$ N4 \$ C  ]( D! o# p* b
  9.     pData++;
    : Y- S! l9 L' F* O1 \: \4 H; z
  10.   }. y- N: y! Z' B7 D1 A) H7 l- w& b
  11.   printf("\r\n");1 q( t. a. `5 o. M' c
  12. }
    ! W# B; ^; u( W. A$ o- M

  13. 8 T! E7 j  N, R. I: O7 W( ]5 u7 ?- `
  14. void AES_encrypt_test(uint32_t *plainText)  H# x4 x6 b  o$ n  e' C
  15. {
    + \1 |: j; N. m& i/ R; m
  16.   printf("plainText = ");! s# q% _0 m  \# z* `
  17.   dump_data(plainText, AES_DATA_SIZE);
    - ?4 k; H4 K1 i: L  T6 u

  18. 3 F1 r% A( W" M3 p/ ]1 H7 v
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK); k. @* P/ W3 h2 e
  20.   {
    1 J' F" d0 V8 `* U) U1 o1 J
  21.     printf("AES encrypt success\r\n");" I; @! O) E$ Z
  22.     printf("Computed_Ciphertext = ");
    " E# \& m, U/ _: g
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);1 v+ b% Q$ e0 e. j& j
  24.   }
    7 t# ]2 n6 ^- x3 b% y  U8 M
  25.   else
    / o. n& x" m) d4 X1 O# w. w
  26.   {2 b. ]; ^8 \. r' w6 P: C
  27.     printf("AES encrypt error\r\n");
    ( Q+ s) U% j5 z' o5 I8 z8 B
  28.     Error_Handler();
    ; ]8 ]1 z' P' G- v' s* t  x7 @
  29.   }
    6 R/ X2 \1 F& k, C# d) s1 A4 |' o
  30.   printf("\r\n");
      ]) e( b4 a, z, |
  31. }* Z4 }1 a0 R9 |* B- k

  32. + s; U3 d+ I. [& I
  33. void AES_dencrypt_test(uint32_t *cipherText): Q. V8 }0 J: V, U- a* U
  34. {/ W& g7 `! F1 W
  35.   printf("cipherText = ");( {6 e6 a4 }# s/ w  F4 f) p$ [
  36.   dump_data(cipherText, AES_DATA_SIZE);* ~5 U3 o# S- Q3 O* ?
  37. . |+ \  R$ X3 n( [
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)
    , m" g5 U0 c6 ]- |( y
  39.   {
    9 l7 P. M% u  s  F9 ]0 z: l4 O4 M  J
  40.     printf("AES dencrypt success\r\n");
    : S1 y+ L1 o0 L# U+ l
  41.     printf("Computed_plainText = ");
    8 R6 ~" S: [- w7 {) l# `
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);
    9 t4 e9 ^3 i9 }
  43.   }, L: |7 @/ s6 E
  44.   else1 q/ H4 B* y/ j+ c5 h
  45.   {
    ) s* f/ x  m4 r4 H% X
  46.     printf("AES dencrypt error\r\n");
    ! ]- ]' q) O* U* c% n& q% }$ R; N
  47.     Error_Handler();
    ) J% F: n4 }0 d  H6 T
  48.   }8 g3 ]' Y2 w: i) I4 y/ x
  49.   printf("\r\n");
    + u4 ~  B0 e1 \8 q8 V4 Z  o6 _/ T
  50. }
复制代码
11.png
2 N7 M5 w  I# Q# ^* @/ H9 s
9 x: R/ ^( {+ r! [+ P- _# b
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");" c5 k* o8 y, H0 E+ l( L
  2.   AES_encrypt_test(&AES_plainText[0]);
    , C: m7 S% z# i3 F/ }8 g
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");* {3 D& g: m" O# N6 v
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png

8 D6 j" g# Q' H* u+ K
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。

! N; X6 d% ?5 d$ I
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()
    1 x' D- u8 h7 O9 A4 r3 }% r
  2. {% i2 [  `; D$ x% u
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");
    ; W+ w- Q( M5 P
  4.   /* 先去初始化 */) l# u) H: z. u8 `0 o% D, N
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    % Z' F: T9 Y# }- ?0 n/ W% L$ H
  6.   {
    0 D$ q) T7 `, C! g) r; M
  7.     printf("HAL_CRYP_DeInit error\r\n");& \+ r2 c$ D; j! ~$ b
  8.     Error_Handler();8 d/ V- z6 \0 _. J+ {2 X
  9.   }
    & \7 B$ e5 I$ ?- q# i$ e' K7 a3 B' m! Y

  10. 7 l3 O: {% ?2 I; k- h# f
  11.   /* 修改使用的秘钥 */# L0 w/ D9 O, O  y: }' W- Q+ b& b
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;1 L: o4 i! T9 G; z( n+ g
  13. 7 x1 }9 h6 I5 m1 T6 q
  14.   /* 再次初始化 */9 J( F! y& ?/ v1 n! l# M
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    - s% P/ @0 g& u: \8 b( ], c1 l
  16.   {: E% j; B2 z4 ~, b+ u" D, t
  17.     printf("HAL_CRYP_Init error\r\n");
    ' G7 `# z& z( L3 v7 u; w( a3 `1 S2 n
  18.     Error_Handler();
    , M7 P  ?8 r$ p: {9 z
  19.   }
    % K, \" ]& f$ c/ m0 T- Z+ z
  20.   printf("\r\n");5 {2 I* S/ b. |0 A4 c+ z4 q/ h
  21. }
复制代码
15.png
  Z! c8 f. q9 J1 ?9 l
* M9 \& J/ l9 W& j' w
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();% y& H3 ~1 G, B1 x) O

  2. & p# K' e( W: p% L# z& X
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");4 a  c/ b- `6 p7 n
  4.   AES_encrypt_test(&AES_plainText[0]);
    / ^$ A" u9 U2 f$ K  I0 L
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");$ k% p9 g" _7 J3 m; N5 p
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png

/ `# l* Q/ U2 C. _# s/ t# \
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */$ |  @8 a& R/ T! [
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    - Q  s  s% d: g4 M" N/ l% H& R
  3. {
    7 C$ S6 b. u5 _
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E7833 ]0 y" h- u! n' \& d
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode()
    ( H- e; u& Z; N
  2. {
    ( K3 g" N1 ^4 `+ i
  3.   printf("change to AES CBC mode\r\n");- [+ E3 f# |8 ~( a" Q
  4.   /* 先去初始化 */
    - ~9 O7 F" |0 x$ F& [
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    ' ^2 E+ L, ~% G: B- _# u! M
  6.   {
    # ?( S1 G# O4 a8 W
  7.     printf("HAL_CRYP_DeInit error\r\n");
    4 Z( A9 C' l5 f, e. ^
  8.     Error_Handler();5 [. W( v0 o7 \* {! a, ~
  9.   }+ t$ S/ p" S; W

  10. ( Q! C1 d* A- s, r$ I7 |
  11.   /* 修改为CBC模式 */0 T1 a5 c3 Z7 N6 F- H/ I
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;! F/ m3 W& q, h$ O6 S: T
  13.   /* 设置IV */
    1 R0 k! g9 W" D5 j( R
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;: V8 s3 [. n7 }2 }, `5 m

  15. * \+ F- q" |# q, D% B1 \: i7 e
  16.   /* 再次初始化 */& H/ W2 t. c7 z
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)8 U! J& l1 \9 C, U
  18.   {$ l9 q, j9 N' \7 i
  19.     printf("HAL_CRYP_Init error\r\n");
    + w! m0 V+ L3 B- @8 q" `
  20.     Error_Handler();
    6 a. ]0 z% ^. E" S
  21.   }
    ' G* n, {7 Y* j- J9 h# }
  22.   printf("\r\n");( }" m* k7 U8 X
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();
    " d& `2 R4 c6 L+ a# g0 i

  2. : S; f, L$ O+ u' B2 e
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");9 k2 k6 u4 i- ?: v$ {+ d  {
  4.   AES_encrypt_test(&AES_plainText[0]);# R2 q/ }) r: F: p: g+ g
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");
    : C7 i8 l, ]+ x/ x9 l
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。
+ S2 U1 n/ d0 x1 P; k
本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 1)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了
! h& O: [7 S* {9 R  B
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版