请选择 进入手机版 | 继续访问电脑版

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

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

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

  s% J$ i4 k) x5 a+ r. C$ L. `: ?% \
一、cube配置
首先需要在cube中开启AES模块(工程就是上一篇中创建的模板工程)

! G( I& P: X& x6 J
参数这一块主要关注的是加密模式(Data encryption type)、秘钥长度(KeySize)、秘钥(Encryption/Decryption key),其他参数保持默认就可以
1.png
其中加密模式支持如下
2.png
秘钥长度支持128位、256
秘钥的值可以在cube中配置,也可以这里保持默认值,回头在代码中重新配置(当然上述的这些参数都可以通过代码再次配置,这个待会实战部分会有介绍)

# @2 c4 }. k# O' g# V' i  a  y' e
最后点击右上角生成代码
3.png
' k) v3 C2 x. E
二、实战
2.1 AES时钟初始化及函数介绍
先来看一下CUBE自动生成的代码
首先是变量
  1. CRYP_HandleTypeDef hcryp;
    7 s* {1 }$ C  B: v9 X- T
  2. uint32_t pKeyAES[4] = {0x00000000,0x00000000,0x00000000,0x00000000};
复制代码
6.png
这边的pKeyAES就是秘钥,和之前cube中设置的一致(下面的测试中我会尝试更换秘钥)
然后就是AES模块的初始化函数
  1. MX_AES_Init();
复制代码
7.png
$ O1 _) g  Y# R0 x1 Q% R4 |
8.png

; _! S7 j" |" B& M9 ?5 y
在初始化函数中可以看到,配置了各个参数,和cube中的一致。然后就是调用了初始化,秘钥、加密模式等就是在init时配置进去的,如果需要更换,那就要调用HAL_CRYP_DeInit(),修改配置参数,然后再调用HAL_CRYP_Init()(这个待会儿我也会尝试一下)

3 ]$ ^" Q- d: {2 n2 s0 m' p
在使用加密前,需要在main函数的最一开始就开启AES的时钟
  1. __HAL_RCC_AES_CLK_ENABLE();
复制代码
4.png
4 E  ~: B( \8 h* A7 ]) L
加解密函数只提供了HAL库,对应的有三种方式:阻塞加解密、异步加解密、DMA传输的加解密
具体函数如下
  1. HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,
    : |, {* H% r2 }$ |* ?
  2.                                    uint32_t Timeout);) Z/ C+ i: f% y8 ~
  3. HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output,; D! ~, @( h; i3 C. u
  4.                                    uint32_t Timeout);
    8 d2 t- C; B" c6 G
  5. HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
      g1 ^9 B# p+ W
  6. HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);- g  x& a4 A! w0 I  _( L
  7. HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);8 C# ~5 {4 F+ D7 m  P8 H
  8. HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output);
复制代码
5.png
; Z/ l; Q. i1 F- |
这里我再插一嘴,AES是需要加解密数据为16字节的倍数才可以运行,如果你的不是16字节的倍数,那么就需要做一下填充,加解密接口是不提供填充的,需要自己实现

% j" E) C& d9 t
今天我们的测试的是最基础的阻塞加解密函数

* `3 V* i8 b/ a7 K
2.2 AES ECB 128bit加解密测试
我们刚才在cube中默认配置的就是AES ECB,那就可以直接进行加解密的测试
先准备一下明文和对应加密后的秘文,以及存储加解密后结果的数组。待会儿我还有尝试更改秘钥,那么这里就把自定义秘钥相关的也写上
  1. /* 计算得到的秘文 */
    # z0 G) Q$ \$ P6 L8 S! y
  2. uint32_t Computed_Ciphertext[AES_DATA_SIZE];
    - s9 N( G  ]8 O  |; b
  3. /* 计算得到的明文 */3 B8 J! b$ U: v9 v
  4. uint32_t Computed_plainText[AES_DATA_SIZE];
    . M$ x) D5 _- {/ q$ b
  5. & X3 z  X# ]; H8 X- B6 c, k% u& l
  6. /* 用户自定义128bit秘钥 */
      N4 r3 y/ Q# Z5 d! A
  7. uint32_t user_defined_AesKey_128bit[AES_KEY_SIZE] =+ O- s6 i, |) L+ a/ @& b0 v
  8. {
    + z" o, ?& Q% [" ?7 @$ J
  9.   0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff* Z( u4 a' I3 j
  10. };
    ( X7 Y1 W4 l3 L7 L- m( Q
  11. /* 加密前的明文 */
    " w  E  J: v( H2 I0 h1 f, j' V
  12. uint32_t AES_plainText[AES_DATA_SIZE] =' ?. ?- L) F  E# z; I, |. f6 ~
  13. {! I. X  L3 ?8 ~& b' k
  14.   0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f  y- F  E; I* a, ~3 c
  15. };
    . p5 p) N! \" a$ _; D

  16. : _: f5 r8 V! H1 S" p, Z& L
  17. /* AES ECB使用用户自定义128bit秘钥加密后的秘文 */$ Q4 _  A% G! |
  18. uint32_t AES_ECB_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    1 q$ v; f$ \1 D$ s! q
  19. {$ T8 X, B/ M1 H6 o2 b
  20.   0x279FB74A, 0x7572135E, 0x8F9B8EF6, 0xD1EEE003+ D5 J1 O% K$ I7 X* L
  21. };
    4 |- b& F$ H5 w$ f
  22. /* AES ECB使用cube默认128bit秘钥加密后的秘文 */
    : Y! v. [( v8 a% p& i( a' r
  23. uint32_t AES_ECB_Ciphertext_cubeDefault_128bitKey[AES_DATA_SIZE] =
    3 X. k3 K$ d3 g) Q+ j, [) o
  24. {
    * B% g( A- n' [% X
  25.   0x7ACA0FD9, 0xBCD6EC7C, 0x9F974666, 0x16E6A282% q: _2 ~; l! Z* o6 H
  26. };
复制代码
9.png
这里创建数组时要注意,一定要是uint32_t类型的,不然和加解密接口的入参类型不一致,不要尝试使用uint8_t再忽略编译警告,别问我是咋知道的

2 @# t( \9 d$ Q! r7 G* L2 |. W3 j) g9 U
然后在加一下宏定义
  1. /* AES加解密阻塞式函数超时时间 */6 Z0 j0 V; W$ v1 n
  2. #define AES_TIMEOUT_VALUE 0xFF  //0xFF按以往经验应该是永不超时,但是没测试过。也不清楚小于ff的值与时间的关系。就先这么设置着再说
    & b& P( x3 I( u  u, V
  3. /* AES加解密数据的长度(byte) */
    8 n+ S1 M& Z& P; I" `/ O! I7 q3 G
  4. #define AES_DATA_SIZE_BYTE 16
    2 X6 `) W- \9 V, a( o( `0 {5 t
  5. /* AES加解密数据的长度(uint32_t) */( R7 ]3 k0 G7 V1 H- R6 z) D
  6. #define AES_DATA_SIZE (AES_DATA_SIZE_BYTE / 4). m# U$ z6 A$ s9 J5 _4 i, C
  7. /* AES加解密秘钥的长度(bit) */
    ' X7 q5 |0 Q2 Y  Z5 |! ?
  8. #define AES_KEY_SIZE_BIT 128, Y4 i& h( T& K" E8 o. G4 z$ y( d
  9. /* AES加解密数据的长度(uint32_t) */3 D; M/ i5 J& S1 H0 [# x- S7 {
  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)
    * c$ U0 w" c7 g2 C- k
  2. {
    5 b( T7 {" Z5 m2 o  {  I: t' \
  3.   for (uint8_t i = 0; i < Size; i++)
    ( H5 v6 d" |2 U+ }. U
  4.   {
    ( \* s% E' _+ p4 k
  5.     printf("%02X ", ((*pData & 0xFF000000) >> 24));/ j' d9 Z( l# O$ F' k7 E. h" w
  6.     printf("%02X ", ((*pData & 0x00FF0000) >> 16));* I- ^- m+ z: U( D8 B" A: G8 s' V; h
  7.     printf("%02X ", ((*pData & 0x0000FF00) >> 8));
    & G. l  x7 o9 Y* G% y4 |/ }9 c
  8.     printf("%02X ", ((*pData & 0x000000FF)));
    . k. Z: ]% u0 R, J& z/ w
  9.     pData++;& [% b7 C7 |# \3 ~7 h5 w: ?% r4 V
  10.   }3 [6 h5 r+ c, g2 _
  11.   printf("\r\n");. M  d, q9 t7 I; w
  12. }
    & H: {* f: r' q' g% t% M- w' H

  13. - J! @* ]9 v( j' w8 I7 W
  14. void AES_encrypt_test(uint32_t *plainText). @% z8 S) s# q5 q; L1 L
  15. {
    4 M$ e" t0 L# V
  16.   printf("plainText = ");6 ?5 G. ^- D6 e( W" w7 G; ]5 r
  17.   dump_data(plainText, AES_DATA_SIZE);* n2 C4 _) ?% R6 O2 t+ e
  18. / D8 g6 F' U# @5 b5 h
  19.   if (HAL_CRYP_Encrypt(&hcryp, plainText, AES_DATA_SIZE, Computed_Ciphertext, AES_TIMEOUT_VALUE) == HAL_OK)
    4 O& \2 M* \% z/ q: M
  20.   {* U7 Y( r; i& L+ H& P; x% }0 V- @
  21.     printf("AES encrypt success\r\n");' u7 B/ D/ ~  }8 o1 f- a1 |
  22.     printf("Computed_Ciphertext = ");
    , F! C3 k1 x% N8 Z  f& C# p( N
  23.     dump_data(Computed_Ciphertext, AES_DATA_SIZE);$ Y# @" ?- c' v7 ]3 i- s% ~
  24.   }$ Z6 c- L+ R! e/ L# L7 s+ A5 x! Y
  25.   else
    3 @: v$ ~! w. F! D
  26.   {
    4 w# \9 e7 ]( Y1 K+ @! J8 _
  27.     printf("AES encrypt error\r\n");, {" r' w6 e' G& D0 j6 Z/ |
  28.     Error_Handler();" K( d4 M+ N' y# v
  29.   }( a' k8 M' T6 @- |
  30.   printf("\r\n");
    # B3 p3 h- Q- x3 [6 n. O% ~; A
  31. }
    2 I& @/ G2 O$ W4 L/ ]( Q4 R. j
  32. & h( ~2 H4 h+ K+ w
  33. void AES_dencrypt_test(uint32_t *cipherText)' m3 X: u  J2 D: Q9 j& ^- s9 r
  34. {
    7 G8 }5 K* j0 d/ X0 F! X0 S+ V+ l
  35.   printf("cipherText = ");
    & [4 F, P; ~9 q, d: c! }" O
  36.   dump_data(cipherText, AES_DATA_SIZE);6 X  x' ?2 V! I. _

  37. ! K/ v# P4 S, ^
  38.   if (HAL_CRYP_Decrypt(&hcryp, cipherText, AES_DATA_SIZE, Computed_plainText, AES_TIMEOUT_VALUE) == HAL_OK)  K) O2 l# g2 M- Q4 `
  39.   {
    : c9 W3 v. w& w8 a# Y* T9 I* u* |
  40.     printf("AES dencrypt success\r\n");
    6 _" T  V. v# V) p' v& Q
  41.     printf("Computed_plainText = ");* {9 G, A: v3 C) @1 ]& @
  42.     dump_data(Computed_plainText, AES_DATA_SIZE);
    : S. c0 A: I+ E: f0 M" Q$ @
  43.   }
    " h) j5 Q2 ]& s% j% s5 B9 e
  44.   else
    ) O" t$ ?0 e4 U& y) A
  45.   {; {- Z6 j' m0 z* j+ ]! q
  46.     printf("AES dencrypt error\r\n");: R6 J4 A. _0 ~; `/ h6 k. @
  47.     Error_Handler();4 G8 p- F# m$ e
  48.   }
    % _. X' v8 h8 }' H$ ]5 T! @) X0 C+ x
  49.   printf("\r\n");
    / _. H+ ^2 L+ f# K
  50. }
复制代码
11.png

2 ]" w( l) S: D( s' r' p6 w8 W' I/ i$ Q2 F5 B: c+ v
然后在main中调用
  1.   printf("AES ECB use cubeDefault key 128Bit encrypt test\r\n");3 ~) m) S: u4 O' F5 ]+ }3 ~3 h
  2.   AES_encrypt_test(&AES_plainText[0]);% W0 o5 Y4 o* R6 O
  3.   printf("AES ECB use cubeDefault key 128Bit dencrypt test\r\n");8 Q6 \+ G  n) G
  4.   AES_dencrypt_test(&AES_ECB_Ciphertext_cubeDefault_128bitKey[0]);
复制代码
12.png
编译运行一下,结果如下
13.png
和在线工具对比一下,结果一致
14.png
) i) J- c7 g+ E
接下来尝试更换一下秘钥,再运行加解密
更换秘钥有2种方案,第一是直接对MX_AES_Init中的内容修改,但是因为这里是cube自动生成的,后续cube再生成一次就又变回去了。所以我选择方案二:去初始化,修改参数,再初始化。
, ~! r9 T  Q: R0 T
改变秘钥函数
  1. void change_key_to_user_defined_AesKey_128bit()
    . q6 c/ ~! M3 Z* A
  2. {% u; n, ~" {* e' }7 k$ f
  3.   printf("change AES KEY to user_defined_AesKey_128bit\r\n");, B0 u2 M+ Z7 z
  4.   /* 先去初始化 */
    7 N7 l4 W2 [6 z( I
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)6 X0 ^0 V) g, ~
  6.   {  a2 m5 [- z0 G3 f$ n5 n
  7.     printf("HAL_CRYP_DeInit error\r\n");
    $ P) [  c$ g2 c$ h
  8.     Error_Handler();
    & k% d8 u( s. t) z. V8 m+ F
  9.   }
    2 B. \; g. w( q( l4 |* y; x! J' ]
  10. $ o8 o$ P4 }1 X# }
  11.   /* 修改使用的秘钥 */
    $ j- {3 G7 s/ ~
  12.   hcryp.Init.pKey = (uint32_t *)user_defined_AesKey_128bit;5 K  F  y5 m" s: Z' m+ e

  13. + u% m* g  N# o
  14.   /* 再次初始化 */
    ; a5 V* ?# X; j3 H9 O: X& L
  15.   if (HAL_CRYP_Init(&hcryp) != HAL_OK)
    , ~) C3 o* i; ^
  16.   {
    8 K5 D8 R0 y# i- z* Q2 H
  17.     printf("HAL_CRYP_Init error\r\n");
    # F" a: }- {5 Q; {
  18.     Error_Handler();* o5 ^; X* m; I
  19.   }" v* f9 o1 G- z
  20.   printf("\r\n");
    9 _* h5 {' n* B$ `) u& K
  21. }
复制代码
15.png
4 Z+ \4 ^  ]$ _3 u% b1 q
. P) O0 H7 V6 c+ j, m
然后在main中调用切换函数,并且再次进行加解密,测试一下更换秘钥是否成功
  1.   change_key_to_user_defined_AesKey_128bit();9 ?! F% b/ S: ~. @! L; _3 V6 Q
  2.   _7 e4 w' W3 ~$ A! w5 O
  3.   printf("AES ECB use user defined key 128Bit encrypt test\r\n");) a8 \4 R; k: j7 B1 u# A( Z# Q
  4.   AES_encrypt_test(&AES_plainText[0]);8 p# b8 i/ Y' W2 j4 g& r% O# r0 Q4 d
  5.   printf("AES ECB use user defined key 128Bit dencrypt test\r\n");
    9 {8 C# Z+ ~8 ?$ A% r8 M( n* U( ^. t' {
  6.   AES_dencrypt_test(&AES_ECB_Ciphertext_user_defined_128bitKey[0]);
复制代码
16.png
编译下载运行效果如下
17.png
和在线工具对比一下,结果一致
18.png

! b9 r& T& O) E% k) f' @
2.2 AES CBC 128bit加解密测试
然后我们把AES模式切换至CBC模式,来进行测试
CBC相比ECB多了一个IV参数,所以我们先把IV的数组准备一下
  1. /* AES CBC使用的IV */
复制代码
然后准备一下CBC加密后的结果的数组,回头给解密时使用
  1. /* AES CBC使用用户自定义128bit秘钥加密后的秘文 */2 w8 w  Y% `% B. o' A* S
  2. uint32_t AES_CBC_Ciphertext_user_defined_128bitKey[AES_DATA_SIZE] =
    4 V  V6 u2 S9 F5 f
  3. {/ M+ ]( w$ l! s& k2 t
  4.   0xFCDBC004, 0xEB4CA8BB, 0x60F4C4A8, 0xC2B9E7834 @" g6 b( i. J1 d
  5. };
复制代码
19.png
写一下切换至CBC模式的函数
  1. void change_to_aes_cbc_mode()" a) b  Q# N; r8 b% s" G. M' y2 E9 y
  2. {
    ) m  o% R% r+ n8 K/ m
  3.   printf("change to AES CBC mode\r\n");
    1 s; k, P! ?! @; ^& o; S
  4.   /* 先去初始化 */
    ; z1 Z) y$ P( L- ?7 s) M0 u1 Y# V
  5.   if (HAL_CRYP_DeInit(&hcryp) != HAL_OK)+ F. W$ X4 \8 M) q1 D" d
  6.   {
    5 i" ~0 ?4 i" [6 l. I( T
  7.     printf("HAL_CRYP_DeInit error\r\n");- a2 H# }- z9 }% Z0 z2 R& Q8 F
  8.     Error_Handler();
    ( x5 O4 ~: B5 H
  9.   }% j8 h  S; G' @' s% b
  10. 9 k9 `! f% L7 ^
  11.   /* 修改为CBC模式 */
    , d! a8 G3 s# i8 e4 p
  12.   hcryp.Init.Algorithm = CRYP_AES_CBC;
    7 k; l4 U* G" m
  13.   /* 设置IV */- D+ I# [; X7 L# r! Q
  14.   hcryp.Init.pInitVect  = AES_CBC_IV;" u  d1 G8 I. G6 J4 n
  15. 8 W5 t; B+ R0 C
  16.   /* 再次初始化 */* p( Z/ c0 ]: h: j  w9 Z" P; J3 f
  17.   if (HAL_CRYP_Init(&hcryp) != HAL_OK); h' [4 w9 k% `' _, {6 a
  18.   {/ h9 z3 S1 W* Z/ d- O- W* n
  19.     printf("HAL_CRYP_Init error\r\n");
    , V  c% F; O& p0 H) V* c  X
  20.     Error_Handler();
    & o2 K9 r  K" n' d
  21.   }5 d0 U% x" {' c
  22.   printf("\r\n");4 ~! _# A& r$ W, Z; |
  23. }
复制代码
20.png
在main中调用切换函数,然后进行CBC加解密测试
  1.   change_to_aes_cbc_mode();
    1 {& B+ q. E$ ^; |6 C$ v
  2. - ?3 z+ }- w0 C% E
  3.   printf("AES CBC use user defined key 128Bit encrypt test\r\n");
    8 V6 h8 t5 y0 T* W( l6 S; P
  4.   AES_encrypt_test(&AES_plainText[0]);. F9 M2 T$ M+ Y
  5.   printf("AES CBC use user defined key 128Bit dencrypt test\r\n");
    ) M$ B9 e3 P' K
  6.   AES_dencrypt_test(&AES_CBC_Ciphertext_user_defined_128bitKey[0]);
复制代码
21.png
编译下载,结果如下
22.png
和在线工具对比一下,结果一致
23.png
三、总结
今天的测试非常成功,都与在线工具结果一致。AES其实还有很多东西,例如使用256bit秘钥、CTR、GCM_GMAC、CCM加解密方式等,由于时间关系我就不一一进行测试了,基本上与就今天的改变秘钥、改变加密方式大同小异,大家可以自行研究。
" \& |5 A9 S5 h  Y3 H% |2 ?
本次工程代码: STM32U0_AES_test.rar (5.21 MB, 下载次数: 3)
1 收藏 评论2 发布时间:2024-5-10 22:52

举报

2个回答
STMCU-管管 回答时间:2024-5-11 09:03:52
赞,用心了; G% F: u. {' C! d! z" s
Yude 回答时间:2024-5-22 16:55:14

好详细啊👍

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