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

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

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

& l6 X) l5 z; e6 l# |; h) X! z
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)
) J( A, Q: ]& {( \& R+ n
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)

* C' \1 `/ {; U9 T
最后点击右上角生成代码
3.png
$ ^1 B  t1 Z, a( Y* K/ }" T
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;
    . J- g) b& N2 K4 `" z9 X
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png
2 x( J2 @6 A; a, t
8.png

& q; e  M: c7 R; G# N& F
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)
) y% {7 G( v$ Z+ t  |
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png
' r) |4 N3 S1 }3 h1 z( }) n" @
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    5 M% V- V6 Y9 j$ @" Y1 b
  2.                                    uint32_t Timeout);
    * |, A* y2 Q' F. |% x
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,1 B" S- Q, d2 F1 Q1 ]5 z
  4.                                    uint32_t Timeout);5 i) ]  K1 n+ |6 N: f
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    6 P+ y; k3 y$ I6 T& E
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    9 Q- |7 l4 u, ~+ L- c* d: p
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    * x# ?  k# H3 X5 T3 }
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png

+ j2 p$ y" _- m2 X( |: O
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现
8 n3 G) {3 ^' }
今天我们的测试的是最基础的阻塞加解密函数

5 T$ @- F. D: W/ S. e' f
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */
    " Q* T7 m4 F5 Q
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];- f, q5 n! _2 k4 L7 b  _7 g0 y& ~0 O
  3. /* 计算得到的明文 */
    & [$ D) h3 l+ h+ P+ j
  4. uint32_t Computed_plainText[AES_DATA_SIZE];" b: Q6 t% q0 f7 i3 k

  5. 4 s4 m8 |( F' K8 e) G+ s  x1 @$ Q
  6. /* 用户自定义128bit秘钥 */9 M, F5 X, K# H/ U2 v2 `
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =* O2 k3 X! P) y2 r. F8 @  r/ z
  8. {' e. V0 |. K% L. f
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff
    ' ~3 q! y2 L+ B0 ?8 H8 Q4 H8 z& C( l/ I
  10. };7 N$ q# q( A* I% _6 l2 O' |4 y
  11. /* 加密前的明文 */& x7 r$ f* [- Q0 Y+ ^5 F: f. _
  12. uint32_t AES_plainText[AES_DATA_SIZE] =
    ( p( {# j: s& @9 m
  13. {
    1 A# y, S% |  A5 n
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f: X) y' |: s8 g4 g9 J
  15. };/ h: q  G" C; S( T) y, N
  16. * ?2 N9 T$ N  I* d' E/ `
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */
    9 V+ K! |2 o0 H. g
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =$ P6 `( G3 z- `$ r( a: H6 A$ h
  19. {
    ) o0 i) V! m: @0 G- ~
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE0036 h; k9 \! s5 g8 A! G5 D$ c( Q0 C
  21. };
    4 F" G3 N. B+ }. j# p
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */
    & S  x, j9 K# Q, T( W1 H
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =0 @' P" K5 B! e* d) x
  24. {0 D, X& B  ]1 {# Z& ?& l4 J. @
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A282
    & ?. Z* _; ^5 x9 M1 \6 r
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的

# M+ G0 X+ n+ y" \& Y  u
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */) \8 }' n8 c4 C
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说
    - Q# D( x9 i" J: t  l6 |% ?' d
  3. /* AES加解密数据的长度(byte) */6 Y3 |1 e  J  r! D2 C, M/ S+ z7 {9 Q5 W
  4. #define AES_DATA_SIZE_BYTE 168 c$ A) J' f" f7 q
  5. /* AES加解密数据的长度(uint32_t) */( w( m1 c4 z4 p+ H, z# n( M. F
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4)! g& e  o" p" Y% Y  T1 p- w
  7. /* AES加解密秘钥的长度(bit) */
    & w) @' A" S8 s6 G0 j$ ?  m
  8. #define AES_KEY_SIZE_BIT 128
    8 o  O1 L$ ^1 N# v( @, {( @
  9. /* AES加解密数据的长度(uint32_t) */; v$ S+ o" {) G; }; i1 J6 G; F
  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)
    1 j& P* Z, y+ s" o2 V0 \/ a
  2. {
    4 E+ z) G0 h2 D4 q+ |9 ?
  3.   for (uint8_t i = 0; i < Size; i++)
    4 x  `! g4 L/ o* h* R3 {- v
  4.   {
    , v5 Z# @0 K/ p2 g
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));+ S7 O0 _2 J( [4 ^$ T5 o
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));6 f+ O! W# |6 Z& a
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));
    ) G1 \! D' A( D3 |! ^
  8.     printf("%02X ", ((*pData & 0x000000FF)));
    ; A3 `) z( [3 D) i. K* L" @
  9.     pData++;; K( b  w7 q& o
  10.   }
    + ?+ G5 O% @1 ]) A) M3 {$ k9 ^
  11.   printf("\r\n");' f2 V) b: T+ \8 O6 T4 }! U
  12. }
    ( {" l" d0 Y1 ~+ Z( n7 i. o3 T! H

  13. 4 B" K; s- j* G0 z2 a8 j
  14. void AES_encrypt_test(uint32_t *plainText)
    3 f8 m( B- M2 G0 Y# z  e! o
  15. {
    9 L2 K$ ]: `) F
  16.   printf("plainText = ");
    / J% |3 H. A! P7 C7 p: X) J2 E
  17.   dump_data(plainText, AES_DATA_SIZE);
    1 |+ N( U$ m# j, ?

  18. ) @8 K( O" V/ u1 k$ E
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)
    ' p4 u% z1 d0 R  w3 q3 v
  20.   {
      O( p; Y2 P1 S' S! T
  21.     printf("AES encrypt success\r\n");: j: S; B6 a, d1 O7 N3 g
  22.     printf("Computed_Ciphertext = ");4 ?5 x5 G/ \9 S  h
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);  _8 _( {( k& }1 a
  24.   }- h, x0 n: r  G7 {! S! ]- j' h
  25.   else
    ; R. L  c+ Z' u4 u: o
  26.   {
    3 a# {" ~. r8 I% G) [7 X
  27.     printf("AES encrypt error\r\n");
    : g( }" M8 z6 s: ^* L: Z& R! ^
  28.     Error_Handler();
    - S3 t! v# m. L
  29.   }- z+ |% h2 @2 b: S6 P/ k8 f; Z
  30.   printf("\r\n");% j( D$ D- e( J% Z& c4 N# g( A
  31. }/ O8 j% v7 N9 x8 T

  32. ( p* d( j. V4 p4 f# Y  `4 C
  33. void AES_dencrypt_test(uint32_t *cipherText)
    2 K) W" D$ s" H6 S
  34. {+ m/ n& }  L6 j. q
  35.   printf("cipherText = ");, ], `& e0 _5 q  ]/ O- H8 U
  36.   dump_data(cipherText, AES_DATA_SIZE);; K6 [# ^8 x) e
  37. / I; q( q$ B2 r. Z- C- U5 `
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)' P6 W+ B( n9 G8 l2 T# l7 q
  39.   {7 x. L8 w, M, u, e, _
  40.     printf("AES dencrypt success\r\n");* w0 o8 ?. q8 p' ^; W- p
  41.     printf("Computed_plainText = ");
    - o/ k- H1 e' R1 o) c, @
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);% F  ^2 Z" T9 d3 O3 V# @& u
  43.   }/ }! W9 H. ~! Z) X0 \! L# E
  44.   else
    4 R& K+ m8 `! X! u' r# H; j# P
  45.   {+ z, L1 k/ f) g' g1 ?  X
  46.     printf("AES dencrypt error\r\n");
    * j' m5 ?6 L6 M4 [
  47.     Error_Handler();
    4 P  A' f; Z( x8 ~" N
  48.   }
    5 S3 @! K' P! [# I2 d- s
  49.   printf("\r\n");
    1 f! n# U+ D2 Y0 |5 x1 K
  50. }
复制代码
11.png

2 O8 `# Y/ u: u7 q1 }# K
8 c$ t! Y; ]0 ~: f( B, g3 J
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");9 S9 J: o6 A+ e) X# w
  2.   AES_encrypt_test(&AES_plainText[0]);6 h6 p0 i+ \5 U; m* ~
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");  d, D! [  f& p& b
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png

3 V7 |/ H( j9 m, K3 [4 y! ~' G) r% A
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。
2 u" E; L  o+ X  G
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()
    ( k8 m: F9 r1 L, _( X& v" x
  2. {
    9 B" `$ U; L& L7 A& [% ~
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");- l0 j. K9 M6 l, U8 V
  4.   /* 先去初始化 */
    / H9 [8 t6 A+ M2 A+ g
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    ( s* M1 [" x" |! u2 [% I5 T
  6.   {, u$ q4 p/ K+ R1 M! T
  7.     printf("HAL_CRYP_DeInit error\r\n");* ?: O* v& z+ v3 e0 c: g/ y; D
  8.     Error_Handler();0 W3 s; w" T: C* L- f' @: n
  9.   }
    9 {( L3 }9 c; Y: S0 @' O* D* M! q/ |

  10. 0 b" {5 `4 D) ~% d' G9 _1 O& n
  11.   /* 修改使用的秘钥 */5 [% m; M( j' h* t4 [
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;5 H1 s6 G1 s  W

  13. . J* ~6 G) y7 @
  14.   /* 再次初始化 */, E4 z& f, n/ N2 c/ Z5 D
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)4 E: L% t  p& t/ x$ o2 X) A2 W- y2 `
  16.   {
    $ c6 p3 i. X' c* @' I1 h4 C
  17.     printf("HAL_CRYP_Init error\r\n");
      o0 F2 m( p" B4 K
  18.     Error_Handler();
    3 q4 l$ ]( T0 s& P7 ^: w
  19.   }2 L6 b* I8 \, d1 ~
  20.   printf("\r\n");' _- r7 _  Y& x
  21. }
复制代码
15.png
0 p9 B1 i9 B6 u: z
% I; Z, [. A: `; n& Z7 h3 S: b
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();
    * X- P+ Q& f% h* u" q6 N6 I5 S
  2. ! V5 N0 k6 G+ @+ |9 a) F% H$ |2 ~
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");, ^4 j) ^# K8 X. l% C
  4.   AES_encrypt_test(&AES_plainText[0]);
    + o3 M+ f9 w4 u% k' N. A. h
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");
    " h7 n9 z8 x) G; k: T
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png

1 f, }1 `: a2 p0 Z  m4 |8 d
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */7 \5 k9 k" e- |
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =2 Q. Y0 Q! M+ f1 ~9 I, ~
  3. {# r5 F) _1 Q" I3 d& m; ]
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E7838 P3 ~. G+ p3 Y- m. P# f
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode(), `9 s3 t8 Q! h. m) G* d! b% p
  2. {+ t$ [8 ?: X- D
  3.   printf("change to AES CBC mode\r\n");
    0 i3 v; y1 g8 V+ Q6 e
  4.   /* 先去初始化 */
    . j$ U0 Z1 X* h" t/ \  f
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)$ q9 T8 G0 I$ q7 Q  h# |
  6.   {3 |: j8 n+ g) H0 a" i% G# s6 R
  7.     printf("HAL_CRYP_DeInit error\r\n");
    3 u( S) r- s* c5 M, Z+ C- z, G; S
  8.     Error_Handler();6 `" [2 u# P' ?
  9.   }) A& o* w  @7 \# L

  10. % @) w6 h$ g5 ^4 J5 D$ z, }
  11.   /* 修改为CBC模式 *// p/ |7 C# r. B" q! B0 v2 B
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;# ^  A" G" w9 J! n
  13.   /* 设置IV */
    2 b! D$ b7 J& E0 o7 a  ]
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;
    6 n* ^; t! S- Z9 M  Y0 m4 P
  15. * @. Z: ^! Q6 W
  16.   /* 再次初始化 */
    9 y: e7 t+ w2 n* b- \% T9 \
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)/ E3 ~: o2 `# @, d4 q" B
  18.   {
    . B, z1 ~, o/ b, ?$ a
  19.     printf("HAL_CRYP_Init error\r\n");
    ) M4 F8 X4 Q$ y4 K8 u' U% s2 a0 L
  20.     Error_Handler();$ v% Y8 F" s6 a0 y& V
  21.   }' _* `8 g8 U5 e
  22.   printf("\r\n");7 @2 u2 N& {6 C; s6 L" A& e4 E
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();
    3 e" }; s3 a6 V6 D3 ^) m
  2. 8 V& G! R( M& e' i; S: D
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");
      n7 y& \* e" h4 H3 g' D
  4.   AES_encrypt_test(&AES_plainText[0]);& U3 b$ f+ |0 n, x& V) w2 ^
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");; B+ x, V4 P. @/ Z  d
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。

* ?7 U( o1 i$ U9 T9 Y& ~$ _本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 1)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了
9 H' J0 e8 X& J: t5 B3 K
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

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