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

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

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

; f. {5 _- P5 }
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)
) s/ I5 V0 ]6 D3 e( N5 L) h6 V& U
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)

! `2 k* U% f9 U  ^3 h+ d
最后点击右上角生成代码
3.png
. R, N* a' ~4 ~
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;7 Q2 D( z$ t  x( i$ P/ h
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png
; R: z( ^" H+ K) o
8.png

' s5 @- I+ C. Y" V, d- p. I
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)

2 y* g7 S, u) A: J8 f: F0 }4 s
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png
% g2 r# m( }. W# ]/ y
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    # }% t9 c6 ~4 m/ `. S
  2.                                    uint32_t Timeout);
      |2 d; Y. Z$ x5 e* s
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
      T/ z, u% `2 F$ |* |
  4.                                    uint32_t Timeout);
    7 ^( B; c* s9 }5 x' w
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);* C0 N2 M; `8 r( G; K& L+ h9 R
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);. B: U3 ]# v3 a- l# N0 E2 W
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    7 X% m: N2 [# O5 p7 i
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png

3 V% Q# f2 }& N: `
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现
! b) w/ E8 K2 A' Y8 H
今天我们的测试的是最基础的阻塞加解密函数

; S0 X) W0 Y6 O6 A+ T5 \& J
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */
    , H2 x6 ?% i0 u
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];
    0 S2 e( D- P" D" [& B$ ]
  3. /* 计算得到的明文 */
    / \& D/ W' q% j1 n6 G7 D# f& C8 A4 z
  4. uint32_t Computed_plainText[AES_DATA_SIZE];3 J0 a+ c. }( i4 s( U5 s# W! a7 F
  5. ) n" d& j* ?2 M; x7 M9 B, s5 P
  6. /* 用户自定义128bit秘钥 */
    0 t; B6 q, i1 ?- D% `; C9 N
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =8 a$ r( H* E) v" U% D& T; U
  8. {
    , s& \2 v% A# o
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff
    2 P& H' i: v! ^% J
  10. };
    " [' W: V; G  X9 a
  11. /* 加密前的明文 */+ ^+ k+ Q6 S) q, k% N# ^/ Y! [
  12. uint32_t AES_plainText[AES_DATA_SIZE] =  n5 t# d% g8 C$ ?+ R; E
  13. {6 o9 q% k/ \5 o4 Q2 i% S
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f
    / I8 o7 R. x1 G6 v! H" x1 c0 B
  15. };# ^2 x. ^% t  U$ r6 {

  16. # ^+ Y: j# I* ]8 V; P# A
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */
    0 t3 g! i" G2 l' J! e% H
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    4 O/ [: @! @4 W" _  h- y
  19. {) d4 x$ [/ M3 W5 Z8 [
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE003$ I1 z( w3 T# M* @
  21. };
    ! H3 G! w. h3 u& ?9 N+ r- S
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */
    ) i- O% j: I0 }/ n8 h
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =, |  d9 Y# G7 L6 Z
  24. {$ N7 h3 j2 g8 |( k: H: r
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A282" P. p# Z, h# ~3 h! L
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的

* ^6 \: L- `+ L9 ^1 ?# c9 z1 K9 g4 e
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */
    2 n$ V8 R7 q0 T% B/ x
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说
    0 O6 j( I# _0 K
  3. /* AES加解密数据的长度(byte) */$ ~! `% k9 D, x$ X. N
  4. #define AES_DATA_SIZE_BYTE 16% s* f8 D5 G' [$ ~+ S$ e4 J
  5. /* AES加解密数据的长度(uint32_t) */  s, n6 ]/ d7 B$ w
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4)
    " G$ [9 d2 r8 z
  7. /* AES加解密秘钥的长度(bit) *// G  R. y( r* z4 w
  8. #define AES_KEY_SIZE_BIT 1282 ]3 u) M# y( k" g+ R9 G
  9. /* AES加解密数据的长度(uint32_t) */% H6 s7 k" x" {; Q: @1 ?/ `
  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)* w7 p2 e7 P+ n
  2. {, z* U6 t# P5 `& `8 x, Z0 t/ ^) K
  3.   for (uint8_t i = 0; i < Size; i++)* n; F# E2 D4 \3 l% i$ t9 F
  4.   {, @+ B0 F8 h: h. m, D: ^
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));
    / b1 i+ _. @# B9 t
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));/ M0 A& Z. v5 C( y- B* q2 K6 I
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));
    6 L2 N1 c2 j! h  M2 k1 s
  8.     printf("%02X ", ((*pData & 0x000000FF)));
    7 C% g* F8 m7 G7 l+ M- v  {/ o0 P
  9.     pData++;
    ( O! g4 k8 q  f- S, {  [& a
  10.   }
    & n6 ?/ @$ I, t0 `' f
  11.   printf("\r\n");/ f: l1 e4 @3 f2 H
  12. }! W9 W8 f; V) u* S) ~5 j! h

  13. ; D* H7 o5 T$ N; F. d
  14. void AES_encrypt_test(uint32_t *plainText)
    $ H5 }: @$ F3 q0 ]
  15. {
    8 q, U* @  e$ X" Q, _0 H5 U
  16.   printf("plainText = ");
    / I( g) L3 W$ ^# @# K7 O
  17.   dump_data(plainText, AES_DATA_SIZE);+ ]4 l8 f' ]/ m+ A
  18. ' T( n9 d, @* c, F" {1 }6 c
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)# D0 k( ?0 j. B: Q. k
  20.   {
    7 v% o: D% @. {- E, R0 M4 S! K* ]
  21.     printf("AES encrypt success\r\n");+ A5 g$ }" P% ?- P! O, j" l3 R
  22.     printf("Computed_Ciphertext = ");: L1 W6 f9 \  T% l) z. z
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);! I" A6 `0 d& N& \
  24.   }
    0 k2 H7 [' a6 D7 x
  25.   else: @. [! t( q0 G4 N% s. ^
  26.   {* V; v4 c0 i& r3 z
  27.     printf("AES encrypt error\r\n");
    $ v6 c2 `" J6 P' _+ c
  28.     Error_Handler();
    & i6 y, T6 T5 p6 d5 q  S
  29.   }
    2 _8 e* x5 |9 ^, T7 i3 o
  30.   printf("\r\n");
    * L" l0 b5 R; ?* A4 j" y
  31. }
    8 E7 R, V9 n/ C* [% T3 f' s" e+ [7 B

  32. 5 z  ^' l2 {. X: _8 ]0 b
  33. void AES_dencrypt_test(uint32_t *cipherText)
    * a6 ^5 r8 N% \6 @' c; S
  34. {4 S5 ]4 o: S6 D2 p5 k
  35.   printf("cipherText = ");
    ) y" w, ~+ s) t9 `5 n, O4 d& G
  36.   dump_data(cipherText, AES_DATA_SIZE);
    - J2 t! [7 S$ [& M3 A4 Z1 P

  37. $ v1 C1 X0 b2 v1 ^+ T9 E
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK), y3 ~8 _  P% K: |
  39.   {/ q; D; F) A7 G5 t5 X2 M
  40.     printf("AES dencrypt success\r\n");) r# m+ j: P' i) Y+ W3 x* z
  41.     printf("Computed_plainText = ");6 u3 X0 I9 Q1 v
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);- O8 |0 V! Y- E" `
  43.   }' G8 F6 B9 f" B6 f7 O4 v" i; ~
  44.   else0 `. j, Y& G' b% _# u+ x
  45.   {
    " U4 p  q: l" b! j1 g5 N
  46.     printf("AES dencrypt error\r\n");
    9 n2 B# a' r' r/ H0 n& y
  47.     Error_Handler();9 u3 Y8 m) X9 G2 ?0 N( q  e
  48.   }, c! d* [) Q% M. S& |# U8 c+ `' {
  49.   printf("\r\n");
    1 g1 ?. @5 X5 E* p+ [* G
  50. }
复制代码
11.png
6 C' z, c( b' T4 A1 S, F

1 y3 o0 o+ B0 M1 i. ?: {, E( o
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");/ A1 g9 y8 ?. o) s+ V6 T
  2.   AES_encrypt_test(&AES_plainText[0]);$ F. R7 ^/ r+ R2 O0 P9 G9 M
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");+ f- D1 U1 T+ D
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png
! e  o9 }% Z8 R! Y1 U( F6 t' v
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。
9 c) x7 \- M3 L
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()6 W1 G$ _4 R* N6 ^4 _
  2. {* e# t6 [/ U5 b. N1 W
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");: s9 V* G! w* I
  4.   /* 先去初始化 */8 ^% q% l$ J1 n5 I4 a
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    % {" v6 J5 z- r
  6.   {1 Q% n2 M- x. `# e1 a* B
  7.     printf("HAL_CRYP_DeInit error\r\n");! F9 }4 x% `, T3 Y
  8.     Error_Handler();6 T4 ]) P" o  H2 V2 I3 N
  9.   }' o2 u( @4 _, X
  10. 8 E) a! p" d+ i/ G; G, @
  11.   /* 修改使用的秘钥 */+ @& K6 [1 k5 O2 _  g
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;2 b3 l. Z  Y/ f/ x' l7 u' R6 a
  13. " L7 q$ f" u3 O# d( K7 f- N
  14.   /* 再次初始化 */
    0 d- i1 M  ], F2 N& `) f
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK), P8 f. Y- U/ ?6 L/ C* _7 o7 J
  16.   {
    5 r3 f. u% E7 ^. f  k: J
  17.     printf("HAL_CRYP_Init error\r\n");  \# ^0 p- Y' J* h- B2 N& p3 c
  18.     Error_Handler();; ^$ m! o2 y$ j" E% O* B
  19.   }  G. X+ o2 r: r
  20.   printf("\r\n");- D9 \7 W: S* G) [1 Z! U& ]' I
  21. }
复制代码
15.png

1 N% v: `4 n6 M0 y9 D, C; @. t% Q4 n; t: G$ V
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();/ X3 S, h7 A, u* x' p* i5 s
  2. ! |9 K+ K8 f* W0 F! S
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");9 m$ k  A/ y9 w$ B; A% A( |
  4.   AES_encrypt_test(&AES_plainText[0]);
    ; g3 ?. M' v: X, E3 n) R
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");: h7 G& Q+ G2 W
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png
; u) ?6 {5 a+ A- L5 X. C% M3 w, W
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */
    . D! a+ ]+ P) l3 e: O
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    - y( N- R# @$ q2 B, N
  3. {
    + e, V( @' C  T! u' {. T
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E783/ H6 b3 w1 ?) f$ X7 f; @7 T$ o/ |
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode()8 S4 F$ m+ q! B# ~% J2 O. J) n
  2. {
    5 @% e( i+ |6 J
  3.   printf("change to AES CBC mode\r\n");0 b1 }) ^! {% Z  ^. I9 s" x+ D* @
  4.   /* 先去初始化 */
    5 [6 e; n+ p, s& @/ w6 e
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    4 ]# _) l/ x% X3 B/ Z
  6.   {  \5 G8 a) h, ]0 N, J  X
  7.     printf("HAL_CRYP_DeInit error\r\n");  z8 a/ J9 C5 A8 {  `  B
  8.     Error_Handler();3 \( L/ |8 K- r% S; V
  9.   }% h! |* Y. M2 ]2 F) c4 g

  10. . H6 q- {0 @. X& H6 p4 R, Z. I
  11.   /* 修改为CBC模式 */
    " V+ |/ M# u3 c: J0 O; L0 C, h' A( ]9 O
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;
    3 ]4 o% Y" G: w" c. \
  13.   /* 设置IV */2 t& f5 N! k" ~' j5 p
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;
    8 `# ?0 d/ h0 {8 c8 E
  15. 6 s, |! A: \0 s+ B) P
  16.   /* 再次初始化 */0 q! h( g% ]' x) [
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    ; s3 c$ X, p3 G4 n0 g3 E
  18.   {( a, ^6 \9 g; s8 J: ^6 i. r* E- k
  19.     printf("HAL_CRYP_Init error\r\n");: c" p& ~! Z( L& }, D2 g# I
  20.     Error_Handler();  E2 B/ |  T( y  m1 o
  21.   }
    0 Y5 G# R! h# D
  22.   printf("\r\n");  J% j' j6 X) r) C
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();
    / L6 L( g0 g  G5 B& k3 Y
  2. & z: {, l) ~, f7 `, H1 L
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");- N. I7 N& N8 K
  4.   AES_encrypt_test(&AES_plainText[0]);( L3 y; a+ M6 i- E3 N
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");' x. j# I2 s( M! ~7 g. U
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。

! B0 r2 w) B. @2 D7 s7 y3 `' q: e本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 1)
收藏 评论1 发布时间:2024-5-10 22:52

举报

1个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了
* q1 o; v( ~; A* b" d) M
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版