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

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

[复制链接]
小萝卜啦啦啦 发布时间:2024-5-10 22:52
STM32U08是带硬件AES加解密模块的,硬件加解密的最大优势就是快。
8 M, N4 ~( @, w. o
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)

( `2 t0 C/ a2 m* Y1 ?- v+ Z) |% Y
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)

0 @- [0 f+ U1 I
最后点击右上角生成代码
3.png
2 i" I! Q. S1 z: r
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;- L" _( k, Q8 U' C+ b4 t, W7 V
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png

* G6 K$ d4 l* _* e" A( d1 m  w
8.png

- W0 T# o' w  U4 H4 Z" u
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)
, M: A# o; w6 f% G! F
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png

5 w9 {( J1 U$ Y( W" q+ n; \
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    9 S( F3 h+ f9 w5 t0 p
  2.                                    uint32_t Timeout);! U- i9 f: f+ b% `" b3 c  x+ k, w4 y
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    1 U) y, w0 _' F$ `" Y1 Y/ {5 g
  4.                                    uint32_t Timeout);2 r8 G+ N  x& @# {3 p
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);: i& N. U/ k9 y* j
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    % q$ J/ b1 F8 j4 j
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);+ `2 J4 [( b- l' T
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png
! B" f" V3 l6 o! F3 n3 k! i# I
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现
: c" K& y% h' A7 y
今天我们的测试的是最基础的阻塞加解密函数

, K$ x/ F: E2 d3 w5 r+ H
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */4 Y: F  G( ]2 A/ Y4 s. Y, k
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];" H( T' @. \" @
  3. /* 计算得到的明文 */( d/ e. |% G5 |1 @" L! \- K5 b
  4. uint32_t Computed_plainText[AES_DATA_SIZE];
    # z7 w7 ]" x) _" p* o6 c! U
  5.   v/ `& p6 s/ Y) e
  6. /* 用户自定义128bit秘钥 */( w! q! R, F/ A8 q' g- s  Q% v
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =
    3 x( B) U0 f  r4 N' w# Z& @& ]
  8. {: F1 {4 |* f# S: f9 |0 K& O+ @
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff5 C( u5 d9 n8 f) j5 ?- l
  10. };
    ' ~$ ?, e8 S1 b3 d( u( z
  11. /* 加密前的明文 */* [3 P: y9 W- M& [. }% K0 U
  12. uint32_t AES_plainText[AES_DATA_SIZE] =
    : w! w2 F. N. \2 |0 `/ A
  13. {% p5 s: T0 V5 X- f5 O
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f
    . m& H  p/ i8 ?) J. c
  15. };$ O+ k4 O. M; f, q' ?4 W

  16. / b9 i' i2 G: U% t, V$ B( ^" e0 }
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */
    5 W. v, p* y0 p3 W, z0 D' |
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =- w( G  b0 Y) ^1 s
  19. {
    ( w9 D9 t' [9 h0 {
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE003
    9 f) U, k: i( V( |. x: S
  21. };
    # @# H, o9 Q/ I5 Z5 S8 m
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */; g' Z8 y) q" r3 O6 I8 c7 v5 e1 [
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =: j1 z# |7 C  U+ c7 j/ T/ ], v
  24. {$ o6 f1 ]0 E+ `1 N. ?% c5 y/ g& h+ h7 r" n
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A282
    5 U. P0 S4 S0 q/ }/ }! {
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的

1 p  r# i6 }0 P! g+ O* j% B
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */
    , A! d" D4 L/ n+ {0 D) h* ^+ _. {
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说3 D! z  J2 j$ v2 F: C$ Y
  3. /* AES加解密数据的长度(byte) */
    ) X; N% {& @8 ?4 \3 W! m: u9 x
  4. #define AES_DATA_SIZE_BYTE 16: r' a& E! T% M: d" x0 ^5 d2 g
  5. /* AES加解密数据的长度(uint32_t) */
    6 i# ]( r! X: c( X- W) ~+ ^4 s
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4)3 a" i% v3 |8 ~' Y  s
  7. /* AES加解密秘钥的长度(bit) */
    % o8 c) t; T3 s( s/ M$ ~+ x
  8. #define AES_KEY_SIZE_BIT 128
    $ u- f) A- |5 N8 m6 l; V; c
  9. /* AES加解密数据的长度(uint32_t) */
    0 W( F9 Q9 E0 e2 e
  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)
    ( m  Y! K) M5 V4 ]$ W( E
  2. {+ K2 E; s( T+ R7 G. R% |$ F6 m, s
  3.   for (uint8_t i = 0; i < Size; i++)
    6 |* M- b! j9 Z
  4.   {& s3 X/ D# |9 C, }+ D; L( D- C
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));5 a/ u  m- \5 b3 i+ b3 I
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));
    ( P& G5 f; {, `
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));9 R! F6 a% i* u9 y8 c+ u
  8.     printf("%02X ", ((*pData & 0x000000FF)));
    # x6 s; B: V6 _7 m# u4 g; |
  9.     pData++;3 Q# ~6 Y7 p  A
  10.   }
    3 h+ l9 k5 [& P. ?
  11.   printf("\r\n");/ O1 }& P% l/ z4 c
  12. }1 c) p* U1 X7 {8 `- |

  13. : ]  D9 }& g6 n- ~
  14. void AES_encrypt_test(uint32_t *plainText)
    9 @! n; @5 Y1 w4 S& f
  15. {1 K# P2 d4 V2 N! n
  16.   printf("plainText = ");2 C& r5 }) S8 S8 A0 [  O6 f* m
  17.   dump_data(plainText, AES_DATA_SIZE);9 @$ s4 m* E' U8 `

  18. / }! K2 r1 M; d, g, n3 G
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)
    ) u7 f* |, t" K4 k$ S/ m& b2 Y) J
  20.   {: @! \0 }! G3 Z. Y' |1 f2 h
  21.     printf("AES encrypt success\r\n");# _& b6 r1 N# ?6 L9 S
  22.     printf("Computed_Ciphertext = ");
    2 C4 M% B! N4 q
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);" x( ^8 R- s0 f) Z
  24.   }
    6 A2 K- |. H& P% L$ Y! k7 j
  25.   else
    * F9 C8 c( ~" Q$ {3 O
  26.   {
    / X0 \7 G5 Q# C$ r1 N+ N& r& \* b
  27.     printf("AES encrypt error\r\n");
    " \. z. o5 R. t7 {" J& @& a
  28.     Error_Handler();
    ' }2 c# ~, Q. e* i
  29.   }
    3 M- }% f  @- ~% R0 Y3 ~
  30.   printf("\r\n");
    : R  j; {( [6 i: N+ r
  31. }$ r: t: r; r9 d4 @3 ]9 n

  32. ( F4 f- h4 a) b4 \
  33. void AES_dencrypt_test(uint32_t *cipherText)
    # a; C0 W& ^8 p. T/ e- P% a  M9 r
  34. {1 f- R* L' X1 i- Q
  35.   printf("cipherText = ");
    + @% d3 X$ d( V* K" f9 |3 h
  36.   dump_data(cipherText, AES_DATA_SIZE);
    ! p, e/ L" Z5 z' `* b

  37. ' Z. M( o1 j+ I. y  E$ o+ J, {9 X3 ~! i
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)
      M; ^' |, k2 p: T
  39.   {' N$ O7 V9 W9 p5 R- V6 v: P
  40.     printf("AES dencrypt success\r\n");
    2 l1 T, n6 V/ h9 x/ E
  41.     printf("Computed_plainText = ");
    ' O/ w: J; r0 L( s+ s& U2 K8 o1 d6 M
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);
    * _$ ^7 k' e6 \3 k( `9 {/ p
  43.   }
    * T9 M( j2 \( `
  44.   else4 ]  ?! M" @3 L: T9 t! m, @
  45.   {2 [2 W) ?; M8 v/ ^" g7 N2 M
  46.     printf("AES dencrypt error\r\n");; j# V& Z* n; ~
  47.     Error_Handler();+ x5 @9 }+ s! t- D7 R
  48.   }
    % Q1 O8 F. ?3 w3 G1 n
  49.   printf("\r\n");
    9 [. `2 m& N! d. l% S
  50. }
复制代码
11.png
+ f% w. T/ ?# ~. V; u
8 a- h0 a+ W: T5 l! N
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");9 y$ G  ^$ k! }6 i( S* o& M
  2.   AES_encrypt_test(&AES_plainText[0]);
    0 I+ }; [+ [! p0 B9 R
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");6 H) R8 F- \! _! y# m, ?2 j
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png

" h$ ~4 }2 I6 f- u/ I: G
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。
3 g7 v3 C/ m9 M; E0 G+ Q7 U
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()! Y+ R0 R( h( n/ b! K* }
  2. {
    $ T; q- ?& w8 ~4 V% D9 R& A
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");
    1 A/ z& `" |& J. ?& ]
  4.   /* 先去初始化 */
    0 F0 O  s6 }  s7 W
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)! O+ U9 U& w- ]( v" x+ E' n* J  B
  6.   {' {+ @! O( |1 j9 l
  7.     printf("HAL_CRYP_DeInit error\r\n");
    / F7 L3 b# ?- |. W/ Q9 |
  8.     Error_Handler();  W( d- z7 f0 |. V& c% Z1 d
  9.   }
    % m; K: g9 _- q" U
  10. * p! z( s- K8 W0 l
  11.   /* 修改使用的秘钥 */* U& F- ~1 j1 M1 p, D0 Z
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;
    - A' O- \2 |$ a9 o6 L' f

  13. & k. H7 |+ j: u! h) T: E. k' b* w% ^. v
  14.   /* 再次初始化 */
    & v4 M- X7 \& @" f1 E+ Y2 s
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)/ D4 |" F) K& m. V, j
  16.   {  [4 F$ s: |4 t! g$ k
  17.     printf("HAL_CRYP_Init error\r\n");+ B1 y3 p  Q# b4 h
  18.     Error_Handler();
    $ ~4 s& {) G3 j1 q$ j3 `* q% D1 z
  19.   }4 U5 |. s; G6 C' y
  20.   printf("\r\n");
    # E5 J% U0 R4 |0 o+ J
  21. }
复制代码
15.png

" N0 n4 M, M4 v6 m( a: x" v  q9 ^" }% m+ m* A& N' f
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();
    ; K# s- @5 a5 p+ S/ ?" [
  2. 8 K" x( D: i# P* v( z
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");6 A) d/ z5 c0 w
  4.   AES_encrypt_test(&AES_plainText[0]);/ Y0 ?: G' }1 _8 U% m& q9 e: V) v
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");
    " K5 K, A1 x# }! Q3 V
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png

8 f8 Z& Z( ]4 ^6 z6 |: S
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */
    6 X8 R. z; ^) \1 _6 W
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =3 P% y0 u8 [4 q' I7 a0 Q
  3. {
    - Z& N( x/ A- q, i4 P* v* z& S% b$ g8 k
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E783
    7 G! @9 ]# N# U6 E$ k: o
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode(); ?2 M# z) x% l
  2. {5 y8 X9 ?7 W6 V4 w* \
  3.   printf("change to AES CBC mode\r\n");" M& ]+ o6 h+ n# Z& K
  4.   /* 先去初始化 */
    ( D( d' L# [  w: A( L
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    ( o6 Z  m/ J; U6 u8 B7 _
  6.   {9 T/ L) G0 ~( j# S: R
  7.     printf("HAL_CRYP_DeInit error\r\n");/ t+ d0 h  E0 P' y" t' \/ w/ Q
  8.     Error_Handler();& X8 D: d) _' |6 K: d8 S; N
  9.   }  T2 ?5 w" |9 o- E% C( U

  10. 6 E' }4 b* O* C% K
  11.   /* 修改为CBC模式 */
    * t+ C# }* f4 Z$ b; m
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;
    / T7 ~* a* B1 r$ N
  13.   /* 设置IV */4 k) O! s% u2 N# u/ E
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;. w/ T( M1 _: ^7 P# }* n6 o
  15. / X1 B8 i/ r# v0 N
  16.   /* 再次初始化 */
    . U8 E  Q& f$ W5 j  n
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    , y$ N/ O5 p/ j3 P5 J5 Y
  18.   {
    - E5 l+ |$ E) t! `; J
  19.     printf("HAL_CRYP_Init error\r\n");
    2 ?" x. ~6 [* d2 y
  20.     Error_Handler();! ~0 E. S( |! z8 F3 R
  21.   }: y" P$ ?$ K. I- Q# o  u# x( p# A
  22.   printf("\r\n");; [5 n3 j* _9 ]; @3 o
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();+ v: C+ O9 S* `0 {' [3 H

  2. # [( M: H0 E; r3 U" _
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");
    : G% d9 O1 H% x0 i* A, F
  4.   AES_encrypt_test(&AES_plainText[0]);. K$ M4 c  ^, r# T
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");6 b8 S( P6 u' [+ s6 q& f2 W% ~
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。

& X  S. J$ z4 {本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 3)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了0 X. Q2 a3 Z0 z  L+ `4 I
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

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