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

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

[复制链接]
小萝卜啦啦啦 发布时间:2024-5-10 22:52
STM32U08是带硬件AES加解密模块的,硬件加解密的最大优势就是快。
2 j- D4 o) [, R+ f2 p
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)
4 F+ d: h: m, P2 V- p
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)
0 F5 Y! p: d" L' f% s0 O
最后点击右上角生成代码
3.png
# t+ ^% f' b8 o% T. U# V
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;
    # l: n% i# `- v" A3 t( v! `
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png

+ J$ ]9 n$ r+ i; w- O& {
8.png

8 {5 _8 N5 X  e" Q8 E! I, e, a1 Z
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)
, S7 p. i6 [7 D5 a; ^
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png
4 g. e, _7 @2 K; h; w0 R; M% E
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,8 Y$ r0 s2 e8 X* k
  2.                                    uint32_t Timeout);3 I, w4 D% N1 Q' E/ Q' Z1 ]
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,1 v5 S2 g1 V" u  T
  4.                                    uint32_t Timeout);
    ) M" F& F" k8 S3 b9 L
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    7 D) b5 j$ F% A) O
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);) z9 }! J5 y" Q7 i
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);% h4 R  @9 I6 t& Q
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png
" B/ Q# R; v& E: F* C7 z# A* I
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现

2 t' L0 z  c2 @0 R
今天我们的测试的是最基础的阻塞加解密函数

& G1 Q% F8 `( _; U8 E3 i% N1 v3 O
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */- U4 r; z$ N# k7 K, K
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];
    : }' R# u! d! f8 B$ f
  3. /* 计算得到的明文 */
    + M8 ]" ?) Q4 _2 w) T* T
  4. uint32_t Computed_plainText[AES_DATA_SIZE];
    ) ]# ^& b% D$ V: p1 G% k0 Z
  5. ( E. F8 l  L4 K  O" ~4 m! [+ z
  6. /* 用户自定义128bit秘钥 */9 Y; A: \6 F; \. B9 Q5 h3 Y- E. ?
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =1 G6 n$ h* |7 p3 E' ]3 s
  8. {3 |7 f$ \9 C3 h! H! ^
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff) o* A4 E0 h( y  l& q9 ^
  10. };
    5 i6 w7 m3 e. h
  11. /* 加密前的明文 */
    * Z) h! K( g, P8 h
  12. uint32_t AES_plainText[AES_DATA_SIZE] =! n& J5 P1 C9 _5 ^
  13. {
      n2 F0 D8 j) y- S2 y; J8 _. J) }
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f7 Q" h. R8 {  O5 f6 E% z: p2 @
  15. };# [" s+ ^; Q! L, b- T. ?! P

  16. 9 H( l$ C) E, @
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */( z6 \6 T) N4 h2 x
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    - u8 f3 f4 f0 V* t& `
  19. {( w2 I8 _2 y, M
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE003( K% c3 Z  {+ [
  21. };+ I$ l! @* v- e( D' l
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */: j" U; `$ P) o; P
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =
    + _$ y; f& W, V$ g1 R( u
  24. {) R2 B  C# V" A: U* o( X+ n: l
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A2827 s% ?& X3 ?$ i/ i
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的

$ P1 I  B+ q* a  w) U8 @
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */
    & N0 n0 G/ v; e* p
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说- n  D$ ~. f3 f6 x
  3. /* AES加解密数据的长度(byte) */6 {, D. a3 s6 o. r0 b: n: o* S
  4. #define AES_DATA_SIZE_BYTE 165 L. p0 N+ S% l  t% Z
  5. /* AES加解密数据的长度(uint32_t) */
    + Q2 b5 X% L( M; l
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4)
    3 j( n6 L+ I/ h
  7. /* AES加解密秘钥的长度(bit) */
      q, P1 d$ B, Q5 v
  8. #define AES_KEY_SIZE_BIT 128
    * {8 K5 ?* D) F+ B
  9. /* AES加解密数据的长度(uint32_t) */
    1 L' q" ^  e+ N6 [; ]: Q" Y
  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)
    6 ]6 {6 v6 h% L& I
  2. {
    * v& r/ }7 B0 p3 o% z! u
  3.   for (uint8_t i = 0; i < Size; i++)2 O1 I$ f* s  Q! r$ ^) O/ T
  4.   {/ j' H$ @2 k0 V) v6 |% E
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));# D: r4 p( u2 Y1 C9 w; F
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));4 m/ V' A) L# N+ c1 ?% r& r
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));
    ; }1 K/ ~- D( T' \, z/ x# X# y
  8.     printf("%02X ", ((*pData & 0x000000FF)));
    ! I2 F: }* A& _/ n; x2 a5 g
  9.     pData++;
    ) F. p4 g' G0 Y0 H+ `
  10.   }1 ^5 C( j! z  X0 i
  11.   printf("\r\n");
    8 B& G$ P0 G' H! I4 l. Y( u
  12. }
    & H) l9 ?  ^, H5 N
  13. ' h! Q7 v9 x0 b7 i0 P. d1 i
  14. void AES_encrypt_test(uint32_t *plainText)
    ; x+ T, j9 D6 @  o$ a
  15. {
    2 z! u& `9 |0 O: r$ `3 O
  16.   printf("plainText = ");
    ! C/ Z4 w  \! C2 R& O( b4 m
  17.   dump_data(plainText, AES_DATA_SIZE);
    ' [+ W# s8 z  ~8 N8 w8 U% a

  18. : ^- @1 A/ q) c/ @; A& O6 Q" B
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)
    8 `* E6 R9 v" o  u9 n6 \
  20.   {
    $ I# `# X2 o/ B+ A5 Q' @
  21.     printf("AES encrypt success\r\n");2 {& w, L6 z5 ~( s1 n
  22.     printf("Computed_Ciphertext = ");
    8 X1 R6 F2 x& O1 s" m
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);
    1 N' _  f; o; r) F7 {
  24.   }, M% l" ~! @7 N0 I0 O5 b- p$ S
  25.   else
    $ J/ G4 s# c0 f+ M  s2 x8 k* I( |
  26.   {
    % L( s; n; v, {8 S- q. g
  27.     printf("AES encrypt error\r\n");. R% i( O+ f9 ?- h/ p7 E4 e: O/ W& a6 g
  28.     Error_Handler();
    & k6 T# ]; E( i) I5 E& Q( o
  29.   }
    3 ?3 D% U5 w1 j& K2 Z
  30.   printf("\r\n");! k' `8 C( S0 Y/ d0 }
  31. }
    0 j# d6 F- e; h$ Z/ Q5 Y; R
  32. % L: [3 d* {# \/ E& Q+ K
  33. void AES_dencrypt_test(uint32_t *cipherText)1 }$ V* N  Q% {7 q2 _$ C0 X
  34. {: V8 e+ K+ E4 W3 v' S+ q4 L
  35.   printf("cipherText = ");9 ]6 ^$ r8 D3 W9 p. n* p
  36.   dump_data(cipherText, AES_DATA_SIZE);7 K7 q; {5 y; R0 z3 z  P) \8 Q

  37. % K7 Y$ j% W1 W
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)
    8 O5 [" V0 v3 J% W3 I! T0 g
  39.   {
    & P2 B2 C7 u+ S: l* H
  40.     printf("AES dencrypt success\r\n");+ g6 j2 A2 d* K; s& R: v
  41.     printf("Computed_plainText = ");0 A4 M2 w/ C" m* K
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);& r7 T) W# I; E' U- O. J# |, O
  43.   }4 T3 E/ M+ i& m! Y1 D
  44.   else* V& ^7 A7 o$ q% H
  45.   {
    & K" m" s- c  m6 r: M3 |* `0 r
  46.     printf("AES dencrypt error\r\n");6 I9 \& D$ n" ^- F& O" B: Y
  47.     Error_Handler();
    - R' _. U* r! `$ Q$ r- F
  48.   }
    ) X, Z1 L9 _6 M" i# s. ~
  49.   printf("\r\n");
    $ ?3 c3 e' i7 I0 f: `
  50. }
复制代码
11.png

4 P: ~+ ~4 X! v) l
& c/ |2 `& K% ]1 N$ Q. i* a2 V
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");
    # D+ g/ }) W* U
  2.   AES_encrypt_test(&AES_plainText[0]);- f9 m: B2 K& X% w' R5 S2 E9 W
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");
    7 J- t9 r4 G" J* f
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png

! E  l) A3 x" A2 X0 y8 [
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。
- E- J  Z" M1 C1 Q- O$ h
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()
      S" `6 T4 [2 p9 i3 B" q3 _# T
  2. {, a1 |' Z! S* f' z( G- W' N
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");7 |9 T4 C5 y1 c8 e1 Z5 _
  4.   /* 先去初始化 */( s* ]3 _% Z* J8 w7 |7 ^
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)% ~, A2 x9 I6 f. p* d5 U
  6.   {6 ^- Z" f  h  F" j
  7.     printf("HAL_CRYP_DeInit error\r\n");
      c) h. v* a! v5 R& @! Q
  8.     Error_Handler();
    % X1 J8 `1 ]4 T) r; ]3 U
  9.   }# y# X& P. o. f, w

  10.   o- Y& ?4 i* w2 ^
  11.   /* 修改使用的秘钥 */
    1 a9 G1 ~8 ?4 P8 U
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;
      n/ `& A; h6 W4 V* G1 g" m

  13. % H* Z0 \' x- a$ ~7 J
  14.   /* 再次初始化 *// X* k, [4 C( B/ P
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    ' h+ N/ `- `6 A; g6 p
  16.   {, D" M1 ]5 z- N
  17.     printf("HAL_CRYP_Init error\r\n");% y5 M8 M# r! G# X/ F( W& Y8 M
  18.     Error_Handler();
    : e- Y" f* ?% ~& v; j% _+ a* d
  19.   }
    - P2 y: E( R: b. e
  20.   printf("\r\n");
    / w2 w9 |, h& |+ T+ l' k) z6 ?
  21. }
复制代码
15.png

. Z$ ?  `4 f% a- L
2 q, K3 s8 F# i7 E( ]8 \
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();
    0 b; _8 w+ z5 r
  2. , K$ X( K  U& x# e  I3 H4 R% i+ [
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");
    0 H+ }6 n$ S  `" z% p" h
  4.   AES_encrypt_test(&AES_plainText[0]);
    + C* d2 A, q, z0 _6 K. Z
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");
    2 r$ v- D( W! y2 \1 g# s
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png
9 N: ]' N6 C% d; S: x9 K
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */' m& @; M' f9 u  G
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =: ^" m9 K- K: a* [
  3. {4 S% g  p- t! G4 X& @& w% |# e
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E783
    ) L; ]6 f# c* |$ n# n1 r+ ]! s
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode()7 d4 i" C9 Q/ K& Q! Z
  2. {
    * u  u& m( A% H, {7 Z. @
  3.   printf("change to AES CBC mode\r\n");  {& S" |0 [! v) O; K% K
  4.   /* 先去初始化 */
    & H$ c4 m) g9 @' Z, A: @/ O
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)) q; P" B! _# a1 w3 t2 O
  6.   {1 Y9 A- @# }* t: p' U# y7 D& d
  7.     printf("HAL_CRYP_DeInit error\r\n");
    3 I- r. O3 E% b! J- l* }; W
  8.     Error_Handler();. l7 U4 w3 A" X5 x
  9.   }. X8 J  S9 N/ e- i" \
  10. 4 w  ^- o: \2 L* g0 B2 q% \
  11.   /* 修改为CBC模式 */, K# E7 _( p" z% F) g/ q! c
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;
    0 u; G# i( `4 g; j5 H
  13.   /* 设置IV */( S3 m* h# C! r8 B) E
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;
      ^$ l  g9 u' `

  15. ) E( N( m+ |& g: a# h5 d% f: A/ N
  16.   /* 再次初始化 */
    & q' f9 D# u2 k
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    4 X4 l# ~  k* ~) W: _$ Q5 R
  18.   {
    4 o: [) E5 W" B( }5 b
  19.     printf("HAL_CRYP_Init error\r\n");0 L6 z; J! a" `$ j5 V" K
  20.     Error_Handler();$ @, i: `4 E5 I8 U  P# E$ H9 P  @
  21.   }
      f) o$ s1 o# n$ P  ^
  22.   printf("\r\n");9 `, Q9 P$ O. @* X1 Y' \
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();
    / T0 _& b1 m9 N, n- c1 H" u. y
  2. * W; y& ^) ?9 ]/ q
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");
    / v& p8 v- O' B2 {) w9 F0 o0 @
  4.   AES_encrypt_test(&AES_plainText[0]);5 H# Q4 g: d! f6 J6 L( b3 ~
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");
    8 m6 u  L1 m+ U1 H
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。
8 D. k# B; c+ R* L
本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 3)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了
8 {) e* c6 X, j; V. d7 q% e
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

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