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

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

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

3 D$ ~3 o! q( ~* K8 J$ p
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)
+ L  a4 `/ Z, P- H0 R
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)

8 J0 E  l: |/ F) f) Z1 Y! s
最后点击右上角生成代码
3.png

) g9 }( P% @% b! E5 u* ?
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;: `! H# M4 |+ \7 J
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png
. L% x9 }! h/ q, m) x4 P
8.png

" A0 ?7 y) t; P* ~' A- N
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)

2 e! H: F1 h6 R6 b* R  r+ _( q
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png
% A, a/ q$ I6 [0 |4 @5 L
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,1 Z* i' v2 b0 ]' l7 k
  2.                                    uint32_t Timeout);% k9 R% R: \: v" P; z! a7 a
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    + M8 P- V$ \+ ~8 l3 s
  4.                                    uint32_t Timeout);
    ; l+ h6 a. ?! J" K* @! s0 ?
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    0 _7 K: i$ r/ \% x
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
    2 W) a$ v, A' ?! J
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);3 U3 H4 e9 X2 V, ]) I
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png

1 t1 F4 |3 k: ?
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现

( R. t' [' \! M9 m
今天我们的测试的是最基础的阻塞加解密函数
7 r; X* f) Q/ @& z) r
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */: F8 t1 u! K9 l9 V' M7 {! Z
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];, r3 l, g: q: Y
  3. /* 计算得到的明文 */) `: J3 g$ F+ l! v7 u. N. I, e
  4. uint32_t Computed_plainText[AES_DATA_SIZE];
    ' K- p7 K4 {1 K/ a$ X8 f
  5. / T3 ]9 L) n7 M3 E
  6. /* 用户自定义128bit秘钥 */
    % s3 E0 |7 c+ c) {3 `
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =4 e# T6 \" s" g! H8 D( n
  8. {' Y6 R) J+ c$ [- O
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff" s4 z9 x& P* `# g# |, r/ {
  10. };, x$ J* p1 c3 F
  11. /* 加密前的明文 */) H$ Q2 i- i: {5 }  f0 J
  12. uint32_t AES_plainText[AES_DATA_SIZE] =- Q- Y+ _9 s% ?- ~$ K
  13. {
    : f& ~# K" R1 i5 E
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f
    # @0 l& o$ ?- H+ \
  15. };
    : B1 y. B; D3 |4 \2 l

  16. 2 R& }3 t1 V* R& x( }! R
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */
    # P; m; ^; b2 M- `% @- N; V8 y. \
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =" q" a7 l. a- F! T* O+ T5 o# {
  19. {9 A9 R& F7 V: F9 y+ P
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE003
    ( p5 a# a6 ]# D. Q' Z9 I
  21. };5 H" D& c0 R' }- S; y# Q& L# A' q
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */
    3 o3 P7 f' Z8 K- s  Z
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =
    # n0 ]; y/ s0 w* ^2 l# U6 _" f% l
  24. {
    4 u/ N! B2 L7 L/ W
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A282
    % l: b* S6 E7 k- t
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的
# q% H8 v+ u# g* `1 c3 j
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */8 h, P# {: ~* [/ e! x) P* q
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说6 g# u! R. Q/ [' y
  3. /* AES加解密数据的长度(byte) */
    % k8 ]8 K: j7 b
  4. #define AES_DATA_SIZE_BYTE 16* z4 z* P2 u8 J/ Q
  5. /* AES加解密数据的长度(uint32_t) */
    0 q# t& N9 p4 a0 A% K* M: _
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4)
    . ?$ T$ A( t. P: m6 q( D7 U/ ]/ I8 S
  7. /* AES加解密秘钥的长度(bit) */- `! u: W) c# H) g& Y) x
  8. #define AES_KEY_SIZE_BIT 1289 O1 z; r& w+ |6 E+ B) R, s
  9. /* AES加解密数据的长度(uint32_t) */
    # A9 w" \! A. A
  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)
    * Q$ F5 s) q1 A& H$ p8 H
  2. {0 h9 l6 z$ X$ y6 M" A
  3.   for (uint8_t i = 0; i < Size; i++)
    + [4 V+ W" q: n$ R
  4.   {7 O1 d% i5 }( M- |
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));+ o3 H* M( `3 B3 a! I% Y6 o
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));6 Z6 [2 t; Y" R5 p$ o9 b
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));
    ( N: c; R7 X, g# {* m
  8.     printf("%02X ", ((*pData & 0x000000FF)));
    , ~! m# l2 J6 |2 q3 E! O( L
  9.     pData++;
    ( h6 k. |5 |! w6 l# Q
  10.   }% f! [8 |) Q9 s' ]; E/ z
  11.   printf("\r\n");* {" t# Q. }1 k" W+ Z
  12. }. t- }3 X6 m- N% ~
  13. ' p! Y" z$ ~6 q3 }0 M& S* F0 F
  14. void AES_encrypt_test(uint32_t *plainText)
    4 r. ^% c; p$ W8 c, T0 u) x+ @; g
  15. {
    ( C; X& T; A) J' Z
  16.   printf("plainText = ");
    9 O% x. N' @- v+ x3 T# V6 {) J* j
  17.   dump_data(plainText, AES_DATA_SIZE);
    1 w# `1 @0 X7 T3 I' a

  18. % P1 s& o( l  X# p$ k- u
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)
    * W" l# v2 S8 Q. }. M0 H$ |! R5 i( ^
  20.   {
    6 {% C3 @  ^  F/ B
  21.     printf("AES encrypt success\r\n");
    * w; F- s" D9 t1 @
  22.     printf("Computed_Ciphertext = ");# g$ V/ B# y. l! x; o# m( i3 Z+ X
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);
    " Z. i9 P; e& ~  m4 p) P
  24.   }
      S9 |( `! W1 T2 J* w
  25.   else0 i7 j6 e! Y8 m
  26.   {9 c; x  l8 x* n1 J3 W8 }8 w( m
  27.     printf("AES encrypt error\r\n");: |/ y, ~. P! ?7 u6 P" ~# @- r' V# h
  28.     Error_Handler();! n* n! X0 R3 U$ c- o
  29.   }
    8 ?: _/ S9 ~4 W' H9 L0 f& k
  30.   printf("\r\n");4 \6 I" _  i3 U
  31. }
    2 W! N' E6 b  n+ ]. _
  32. 1 U2 V% X4 |# l7 @3 m
  33. void AES_dencrypt_test(uint32_t *cipherText)
    ; X3 q9 T1 Z/ y: R
  34. {
    3 U( z* n4 D9 G4 @# O, f0 \
  35.   printf("cipherText = ");
    & J3 d- p4 E" w7 H, @8 |5 q0 _# {
  36.   dump_data(cipherText, AES_DATA_SIZE);
    " J5 `) j( |4 Z8 i" y4 n

  37. ( n% R: W& L3 X4 Q, @, k3 |7 @
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)/ \. l9 z, a$ b" e. _& f% P2 @0 o
  39.   {( b- }' L0 w1 ~) o5 I3 ]$ ~
  40.     printf("AES dencrypt success\r\n");
    ; T* i1 k$ B& l
  41.     printf("Computed_plainText = ");* ~% X3 S5 d7 g# P) _' E
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);
    # l* V1 O( E  T4 u# E2 y( L
  43.   }! R5 _# C! ?# C9 m/ C
  44.   else
    ( @# _( Y0 ]0 V7 X; j
  45.   {
    & ^% \' p2 y! S7 ~& H
  46.     printf("AES dencrypt error\r\n");
    ) x. }% ]/ _5 x. Q/ o2 [$ r: v
  47.     Error_Handler();
    1 R; H( a& L4 y. }/ g
  48.   }
    0 Z0 j" C/ \: L! O+ d
  49.   printf("\r\n");- z* A2 P& G/ K1 _
  50. }
复制代码
11.png
+ H  k6 Q, w1 b! v6 P  d# h! Y
) W$ s1 ^: X# b/ P
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");# T  d/ L- O& o7 r4 G5 u
  2.   AES_encrypt_test(&AES_plainText[0]);
    0 z) U; U; h- l. e3 Z
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");( ]/ S9 Q8 B" ], z0 K/ a
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png

1 P. t; R4 M4 H! i; z8 f7 a
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。
) V% P0 E  T+ f9 z
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()& i( j2 Z& y3 K
  2. {
    - L7 \! `( h, ?# _
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");
    & T! s1 _( s, G: ?5 ], J- Q8 M
  4.   /* 先去初始化 */+ K. {, G* K0 w/ ?  ?: f
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)0 u( t( I* I: k8 S; N( \. ~
  6.   {
    3 Z7 S: ]) d% n' A  J" P, S, s8 S  |" j
  7.     printf("HAL_CRYP_DeInit error\r\n");& W, w% K7 t( W6 Y9 [1 c
  8.     Error_Handler();
    9 W; w/ W- _6 D; D- Y0 E
  9.   }
    + Z9 O: Z7 X6 Z0 s0 k& ^
  10. % J3 b) z0 N2 K6 Y7 C% U5 {
  11.   /* 修改使用的秘钥 */
    ' x$ b: N0 @) R) u6 n. X! F- `
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;
    5 m$ R; d. b. k5 U
  13. / g; h/ [- y! Y) }* `, P
  14.   /* 再次初始化 */
    6 }" A4 |1 _7 S9 |2 w
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK); z( S6 H1 O% s. S5 P6 h
  16.   {
    - Q# c# f- A5 [( N
  17.     printf("HAL_CRYP_Init error\r\n");
    + p4 I! x" E2 {& U8 T; g1 j
  18.     Error_Handler();' F$ }1 _% |7 Q; i+ n& x2 i) w+ F1 V* c$ A
  19.   }  a. }/ q* J6 F/ ^2 F. E) B" }
  20.   printf("\r\n");
    3 Z3 }3 ?5 p0 ?' A3 l% L
  21. }
复制代码
15.png
0 K- X1 ?' |! r, a6 h6 A
# Z+ d% M+ M' T1 s0 ?
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();
    5 }4 _4 f8 A* B2 l, k" S
  2. . v5 q, {1 ]/ H% V
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");
    / S* P. O) _# S% d
  4.   AES_encrypt_test(&AES_plainText[0]);; E2 _! Q- y( J7 A( B. F5 F/ L; r
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");
    0 `) Q2 u8 p! O3 k
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png
" M! H# V- @" [" K$ n( z
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */
    $ L0 e- E& a% t# A, C1 j) g
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =2 B* `. E8 |: y& t4 N
  3. {
    6 a, C" p5 m2 V% A$ [+ h+ [! h
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E783& n5 ~, o: [* H" [
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode()5 r. k2 v4 q/ n$ [1 X
  2. {1 n4 ?% e" S- }9 @/ a7 H. ^
  3.   printf("change to AES CBC mode\r\n");
    . M; `& a! w; o* ^& x9 e) y
  4.   /* 先去初始化 */; l/ D- ~' I$ T( I- e+ z% O
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)
    7 M( g: y' f5 L6 E- S7 z
  6.   {2 `! j  u0 T+ j. [9 A3 r. P
  7.     printf("HAL_CRYP_DeInit error\r\n");
    ' x! ^; ]1 K: P* D, A' D
  8.     Error_Handler();$ A2 `9 m$ @# f7 k) R- W/ g4 K
  9.   }9 r# D- x1 t1 ^# v

  10. 0 g4 ]* E. w2 p' O- i3 D" D+ X
  11.   /* 修改为CBC模式 */: A6 K, u$ |5 n/ h& T
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;3 ]% Y3 r: ~, t8 j$ Y" O$ c* v
  13.   /* 设置IV */
    8 |" _$ E. G- {0 x0 w7 b6 ^" ?
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;
    + J4 t* q4 N+ v  K/ |
  15. ! e9 x* a! a$ u2 p$ Z
  16.   /* 再次初始化 */
    1 r! ^+ k/ w6 h
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    1 t, U' C+ D% z
  18.   {2 Z# J5 `2 {4 _* E4 G6 E
  19.     printf("HAL_CRYP_Init error\r\n");
    : Z3 a  }5 q$ e3 H0 z
  20.     Error_Handler();
    $ N+ S0 T" {% X
  21.   }8 M3 j; ~& s7 C  y) {
  22.   printf("\r\n");) P& n% S- v/ R6 o! n- r3 l
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();
    / p3 q$ V$ N; c2 c) `3 v( e  h

  2.   g5 ?+ D2 W0 s7 X' z0 A8 w
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");
    : T1 j, N- N3 Z3 m# X+ \0 h
  4.   AES_encrypt_test(&AES_plainText[0]);# Z2 Y; X7 w6 {8 s; e
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");
    4 {; g4 A7 I  L% `9 T1 C# C5 J
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。
" V" j6 |+ K. X1 U1 p7 M0 |
本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 1)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了
2 ~. F  [( t  ^/ M+ \1 O
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

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