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

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

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

6 z5 S5 c' S" j3 @  e
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)

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

1 Q/ B0 S/ R2 \5 B
最后点击右上角生成代码
3.png
. R: J9 F+ c+ R" d* l: r
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;% I. s5 C4 L* Y3 m+ g- ^
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png
* G4 @4 N! l  r& o4 e
8.png

3 x: J% q& s( w3 A2 x' g% \
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)

! S- i1 I* {. u/ T
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png
% \  p2 v: `9 h
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,- q0 |; {" _3 F" x
  2.                                    uint32_t Timeout);, s( C1 I3 K# V& x2 _
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,( K0 v- D% W* R7 A- u
  4.                                    uint32_t Timeout);
    6 ^' C5 L2 S* _. T6 a# ~
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);4 ]" f7 h, i1 j7 c5 F
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);9 Q# M- @2 [$ b* S! U) t' D: A
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    ( M1 b" U9 |1 y
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png

; M5 q/ W- A3 J0 a. k
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现

; f- N2 X/ @$ U. S, [, ~, m
今天我们的测试的是最基础的阻塞加解密函数

: ]- k* B" w. E/ W5 r- V7 X
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */
    & i3 s3 ]7 I# \! ]8 n! F1 e  s
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];
    5 m3 p  _- |& Q; f1 b4 ~# V" g6 ?
  3. /* 计算得到的明文 */1 l/ ]' |. Z) ~1 Q( P8 |
  4. uint32_t Computed_plainText[AES_DATA_SIZE];
    & P! D1 i+ Z6 X1 h; a
  5. ( F+ }' I& J& l! j: p
  6. /* 用户自定义128bit秘钥 */# X& A+ H3 Z, o, Q+ H
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =
    0 y& l' q: D; \+ ^; r
  8. {
    ' j! c. ?1 J7 P1 h0 h4 G
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff
    ) r6 M  c4 X0 A. _" {6 v
  10. };- e; H  c$ D' M0 v: a1 m
  11. /* 加密前的明文 */
    ; S- ~" {2 p8 m* t( _: O( I, T) p
  12. uint32_t AES_plainText[AES_DATA_SIZE] =+ u6 w( v, t/ ]% D, T
  13. {
    9 I( J% \$ u  R4 Q
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f; ?1 `8 t/ Y7 a) Y3 i8 G
  15. };
    $ {) f' T/ p% K1 a' b* D* \

  16. ' P* a( W; Q9 R+ B" _" g! [* S! o
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */
    ) ~& z/ f$ Q) d$ b/ S
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =# k% F6 b- }$ v# d1 G
  19. {/ h, D* t7 u, j
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE003
    ' z# g) @, X1 q6 y3 ?% \4 E, A
  21. };
      H! o' b& ^6 ?: W! _
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */
    2 u1 e9 J5 s$ f$ S5 \
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =
    ; W1 v, o6 D/ A& \0 |
  24. {
    4 V' ~( ^4 x: I" e
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A282. x1 l, Z; v- l  A2 w5 F# N# {
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的
5 N9 q0 f$ [) J( _7 b. E+ C
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */
    + a8 l7 }0 h' @
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说- \- H0 H5 j7 B/ S" ?
  3. /* AES加解密数据的长度(byte) */
    4 P0 U" q' j, L3 w* {! A
  4. #define AES_DATA_SIZE_BYTE 16
    / B9 p9 Z9 x& c
  5. /* AES加解密数据的长度(uint32_t) */
    * w+ c& o; Q% V  x- j) Q
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4)$ u( T! Q/ n) T$ N
  7. /* AES加解密秘钥的长度(bit) */
    / s6 O6 O, @4 Y; }/ G0 Y
  8. #define AES_KEY_SIZE_BIT 128
      w% o; d: F! F* v# c% o
  9. /* AES加解密数据的长度(uint32_t) */
    & K% J& w8 w  z  l
  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)
    " g) O. B6 Z2 S' W0 `
  2. {6 K& W* c7 a$ P: Q$ E. m! P
  3.   for (uint8_t i = 0; i < Size; i++)5 @4 R% J# W# ~# g, ?5 w2 b8 R
  4.   {
    & a- [5 w4 }; U+ J* Q
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));
    9 q( ?4 H! B/ N0 s0 K; }) l0 q$ ?
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));! r+ G% v+ l' p* b9 @( A4 w9 @, Y
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));
    ' k# s) c7 I9 n) B
  8.     printf("%02X ", ((*pData & 0x000000FF)));1 D  J' S" I* z- q' J
  9.     pData++;
    7 y- ]1 D& Z5 U  {( _7 |% [2 h
  10.   }
    : q8 c/ R4 ]6 F7 A- E
  11.   printf("\r\n");
    ) t6 o7 k  ^; o  D) \$ _
  12. }) Z( Y8 X5 A! Z2 q3 |
  13. 0 g/ }( Z) M! a$ V0 B; {
  14. void AES_encrypt_test(uint32_t *plainText)' b% l' F; t7 h; d; c  C
  15. {4 f/ [: m/ H; S1 I
  16.   printf("plainText = ");
    + n1 T6 b# R* Y/ R
  17.   dump_data(plainText, AES_DATA_SIZE);
    4 \  l0 Y, G+ A* W: l
  18. 9 u6 L. i0 m1 O" Y  b6 [- H
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)
    , ^7 D; H, H& S$ K* \
  20.   {
    - b! h! l# W$ j# s/ X
  21.     printf("AES encrypt success\r\n");
    ! f( A% A& d9 Y2 [' z: a; f  w
  22.     printf("Computed_Ciphertext = ");
    + F" @6 l* A8 m; [  i& L
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);- r$ a& r" t6 G. s8 k: H+ M; s
  24.   }6 j' V  g) p/ k% Q; s9 R0 E
  25.   else6 m2 h3 W7 m! _- w5 ~. y( G
  26.   {! Z0 m( r" V5 H$ |: ~) h! n! r2 m
  27.     printf("AES encrypt error\r\n");5 k/ n% _0 L+ h$ H1 k
  28.     Error_Handler();* |! z* l: [8 a- A8 ?2 T
  29.   }5 x1 Z1 n0 \' r, a3 y  \' G
  30.   printf("\r\n");
    % Z) o0 |  a; c- O! L1 K2 ~
  31. }5 y9 Q' J: A2 a' b

  32. ! b+ a4 x' s  s! x3 |' w
  33. void AES_dencrypt_test(uint32_t *cipherText)
    * _( \1 B5 A, m
  34. {
    ! }8 {/ v' b* K; J' c8 [4 ]
  35.   printf("cipherText = ");3 y( ?8 R1 z2 o7 _/ s4 _; x% f, z
  36.   dump_data(cipherText, AES_DATA_SIZE);- [5 @+ u) k# A) _* v2 r6 K1 r

  37. : W# [% T5 L' r3 e6 p
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)# F1 M5 z4 A0 G) n7 p2 l3 r2 M% j) q) J
  39.   {' P% H' K& [: |  i# W+ \+ P
  40.     printf("AES dencrypt success\r\n");) n' f) e* x! Y# w! B! ]# W
  41.     printf("Computed_plainText = ");1 y$ y# ^$ |: d, K* M6 @
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);
    7 b1 [- g, }' B( V
  43.   }
    2 n2 Y. t) y' U: Y
  44.   else; @0 M. g6 h, |! f
  45.   {
    ! D/ J" `, A7 z6 U; d6 F0 d
  46.     printf("AES dencrypt error\r\n");
    + t9 }# B3 X6 a) ?: v, t; J
  47.     Error_Handler();
    - Z; A$ z& C) C' O( _0 N. w' l
  48.   }: @* D( Y& w* k
  49.   printf("\r\n");  J( |- i0 |+ ^2 J0 `1 F- M% t
  50. }
复制代码
11.png

4 h' H- b0 ]( ?* e+ g  e/ \, ^1 ?) d5 h9 _
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");
    ( [; H) _5 q) @1 C9 ?1 p
  2.   AES_encrypt_test(&AES_plainText[0]);
    ; ]( h) X; m! D' O0 [6 m
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");
    : U+ r  V+ u! G, P: s5 G6 f& Y
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png
7 U7 Y9 j) c# N5 q1 Y
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。

) b. z: S3 X5 a2 e
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()2 F, M4 p, B; S
  2. {8 G9 B% x' Q- Q6 X4 n
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");
    ( Y+ H$ P  h$ E: K5 T: }8 g
  4.   /* 先去初始化 */
    / [! r. `$ n) F( x9 U7 L+ V
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    ) U5 l" V. `" F8 O4 J4 Y8 M0 C
  6.   {: V$ B- R* P* i
  7.     printf("HAL_CRYP_DeInit error\r\n");8 a4 ?4 r4 ?1 z) P. k
  8.     Error_Handler();7 d7 X; r" Z! Q# w
  9.   }
    ! x4 p$ r2 m+ F
  10. / t6 I3 d9 S2 Z% F4 t
  11.   /* 修改使用的秘钥 */* i7 z4 @% \3 x; P# P3 \
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;/ X7 p4 v; t- X  E/ _; v$ o2 d
  13. 4 Z( m, \  G# \
  14.   /* 再次初始化 */
    1 |% D, o+ h9 C$ @1 I
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    6 e4 s( o- Y# [2 b2 |' N" B
  16.   {
    + A7 Z, V& F( h" _+ g/ e: B
  17.     printf("HAL_CRYP_Init error\r\n");
    7 A8 y2 l! m, t2 _" i% S% k$ q
  18.     Error_Handler();+ o' e$ {8 S  u6 r( R
  19.   }8 {" U/ y+ `& ~( R
  20.   printf("\r\n");
    # U! o( @. y. {$ b) J/ y. T
  21. }
复制代码
15.png
6 q; h( f) ?8 D
& m5 D4 b7 Q3 q
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();' C4 o4 V' m& l7 t" Q0 P8 }/ E

  2. & S* S* \+ _8 @5 D- l
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");- Z3 w' K1 C) W1 X) j+ Y% r  q6 ~
  4.   AES_encrypt_test(&AES_plainText[0]);
    ' {' z) L- j; p
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");, x5 J& J; f8 u
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png

# o0 I5 O! F% s/ y7 U
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */0 N- `+ G4 X5 O" x! P  x3 o
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =2 S5 z: [1 O2 a# y! q# s
  3. {' q8 X$ L' z5 C' A' |7 B3 W
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E783( Z# L+ S8 f; }: J& H; ~0 s
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode()
    - p) O+ r3 `8 D: m
  2. {; R' l4 u5 }  M4 D8 t) ~8 W" W$ T
  3.   printf("change to AES CBC mode\r\n");3 n$ ], S$ |1 o) w( I% j
  4.   /* 先去初始化 *// h5 a% a8 \" Q1 V8 e) X
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    0 A: e* q  f+ \- a; x' z
  6.   {) B5 n. [7 ?1 w! M, E" Q
  7.     printf("HAL_CRYP_DeInit error\r\n");
    3 x- Y, W# P6 C$ ?
  8.     Error_Handler();
    + y0 C- e/ w0 l) \: A
  9.   }/ q- G& C5 h9 Q! o8 j; T4 E

  10. " ?9 o# \# R- N$ G/ I# ~2 x
  11.   /* 修改为CBC模式 */$ b& I6 C" s2 F' O" O# ^
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;
    / E" l& N6 w+ I) v8 S
  13.   /* 设置IV */
    , T. ]) r; c  C+ R
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;
    + a$ W" r$ w) p1 E- w. k

  15. + i3 N- ]/ h( R1 Q
  16.   /* 再次初始化 */$ L, C) a) X0 K: P; |
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    , h$ u. E% C$ h* _7 \
  18.   {
    ( l, R8 z* U- j, y/ T$ z. z) h
  19.     printf("HAL_CRYP_Init error\r\n");+ B3 P, q# t. K
  20.     Error_Handler();8 l5 _; P  _, }* j# o
  21.   }
    $ _: r, w7 N; z6 Q6 V6 M
  22.   printf("\r\n");* p3 J8 I* J; g, k( ~8 x3 ?
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();9 n0 V% ?* D" M2 e( Y! ?3 b
  2. + G. M7 U9 r5 t, M0 }8 K' @4 y3 }
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");
    7 Q6 m! S2 a7 r4 [5 e
  4.   AES_encrypt_test(&AES_plainText[0]);; }( Q8 t: E- w$ C
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");/ _7 N$ b8 F9 O  m! \* ^
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。

/ C! c* W3 m' a: l- d' D本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 1)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了2 `. |+ X$ g' J
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

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