From: "PierreGondois" <pierre.gondois@arm.com>
To: devel@edk2.groups.io
Cc: Sami Mujawar <sami.mujawar@arm.com>,
Leif Lindholm <quic_llindhol@quicinc.com>,
Ard Biesheuvel <ardb+tianocore@kernel.org>,
Rebecca Cran <rebecca@bsdio.com>,
Michael D Kinney <michael.d.kinney@intel.com>,
Liming Gao <gaoliming@byosoft.com.cn>,
Edward Pickup <Edward.Pickup@arm.com>
Subject: [PATCH RESEND v1 7/7] ArmPkg/ArmAesLib: Add ArmAesLib
Date: Wed, 29 Jun 2022 21:13:55 +0200 [thread overview]
Message-ID: <20220629191355.2618844-8-Pierre.Gondois@arm.com> (raw)
In-Reply-To: <20220629191355.2618844-1-Pierre.Gondois@arm.com>
From: Pierre Gondois <Pierre.Gondois@arm.com>
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3970
The Armv8.0 Cryptographic Extension 'FEAT_AES' provides
instructions for the acceleration of encryption and decryption.
Add an ArmAesLib relying on this feature to implement the
AES algorithm.
Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
---
ArmPkg/ArmPkg.dsc | 3 +-
.../Library/ArmAesLib/AArch64/AArch64AesLib.S | 183 ++++++++++++
ArmPkg/Library/ArmAesLib/Arm/ArmAesLib.S | 183 ++++++++++++
ArmPkg/Library/ArmAesLib/ArmAesLib.c | 261 ++++++++++++++++++
ArmPkg/Library/ArmAesLib/ArmAesLib.h | 96 +++++++
ArmPkg/Library/ArmAesLib/ArmAesLib.inf | 34 +++
6 files changed, 759 insertions(+), 1 deletion(-)
create mode 100644 ArmPkg/Library/ArmAesLib/AArch64/AArch64AesLib.S
create mode 100644 ArmPkg/Library/ArmAesLib/Arm/ArmAesLib.S
create mode 100644 ArmPkg/Library/ArmAesLib/ArmAesLib.c
create mode 100644 ArmPkg/Library/ArmAesLib/ArmAesLib.h
create mode 100644 ArmPkg/Library/ArmAesLib/ArmAesLib.inf
diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
index 02d1caa3ab40..72efeb77012e 100644
--- a/ArmPkg/ArmPkg.dsc
+++ b/ArmPkg/ArmPkg.dsc
@@ -2,7 +2,7 @@
# ARM processor package.
#
# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
-# Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
+# Copyright (c) 2011 - 2022, Arm Limited. All rights reserved.<BR>
# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
# Copyright (c) Microsoft Corporation.<BR>
# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
@@ -139,6 +139,7 @@ [Components.common]
ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf
ArmPkg/Library/OpteeLib/OpteeLib.inf
ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf
+ ArmPkg/Library/ArmAesLib/ArmAesLib.inf
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
diff --git a/ArmPkg/Library/ArmAesLib/AArch64/AArch64AesLib.S b/ArmPkg/Library/ArmAesLib/AArch64/AArch64AesLib.S
new file mode 100644
index 000000000000..07d1d30e6e91
--- /dev/null
+++ b/ArmPkg/Library/ArmAesLib/AArch64/AArch64AesLib.S
@@ -0,0 +1,183 @@
+/** @file
+ AArch64 AES implementation.
+
+ Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AsmMacroIoLibV8.h>
+
+.arch_extension crypto
+
+// Generic notes:
+// - In AArch64, the AESE/AESD/AESMC/AESIMC instructions are using registers
+// as <Vx>.16B
+// - For some CPUs, the latency of LD1 is 6, thus the unfolding.
+// - The latency of the AESE/AESMC pair is 2.
+// Cf.
+// Arm Cortex-X1 Core Revision: r1p2 Software Optimization Guide
+// Arm Cortex-X2 Core Revision: r2p0 Software Optimization Guide
+
+// /** Encrypt an AES block.
+//
+// @param [in] ExpEncKey Expanded encryption key. An array of 32-bits words
+// with the number of elements depending on the key
+// size:
+// * 128-bits: 44 words
+// * 192-bits: 52 words
+// * 256-bits: 60 words
+// @param [in] Rounds Number of rounds (depending on the key size).
+// @param [in] InBlock Input Block. The block to cipher.
+// @param [out] OutBlock Output Block. The ciphered block.
+// **/
+// VOID
+// ArmAesEncrypt (
+// IN UINT32 CONST *ExpEncKey,
+// IN UINT32 Rounds,
+// IN UINT8 CONST *InBlock,
+// OUT UINT8 *OutBlock
+// );
+ASM_FUNC(ArmAesEncrypt)
+ ld1 {v0.16b}, [x2]
+ cmp w1, #12
+ beq 0f
+
+ // Rounds = 10 or 14. Start loading the expanded key.
+ ld1 {v4.4s}, [x0], #16
+ ld1 {v1.4s}, [x0], #16
+ ld1 {v2.4s}, [x0], #16
+ adds w1, w1, #1
+ b 2f
+
+ // Rounds = 12. Start loading the expanded key.
+0: ld1 {v2.4s}, [x0], #16
+ ld1 {v3.4s}, [x0], #16
+ ld1 {v4.4s}, [x0], #16
+ subs w1, w1, #1
+ b 3f
+
+ // Start of the loop (unfolded for 4 rounds).
+1: ld1 {v4.4s}, [x0], #16
+ aese v0.16b, v1.16b
+ aesmc v0.16b, v0.16b
+3: ld1 {v1.4s}, [x0], #16
+ aese v0.16b, v2.16b
+ aesmc v0.16b, v0.16b
+ ld1 {v2.4s}, [x0], #16
+ aese v0.16b, v3.16b
+ aesmc v0.16b, v0.16b
+2: subs w1, w1, #4
+ ld1 {v3.4s}, [x0], #16
+ aese v0.16b, v4.16b
+ aesmc v0.16b, v0.16b
+ bpl 1b
+
+ // Final round.
+ aese v0.16b, v1.16b
+ eor v0.16b, v0.16b, v2.16b
+ st1 {v0.16b}, [x3]
+ ret
+
+// /** Decrypt an AES 128-bits block.
+//
+// @param [in] ExpDecKey Expanded decryption key. An array of 32-bits words
+// with the number of elements depending on the key
+// size:
+// * 128-bits: 44 words
+// * 192-bits: 52 words
+// * 256-bits: 60 words
+// @param [in] Rounds Number of rounds (depending on the key size).
+// @param [in] InBlock Input Block. The block to de-cipher.
+// @param [out] OutBlock Output Block. The de-ciphered block.
+// **/
+// VOID
+// ArmAesDecrypt (
+// IN UINT32 CONST *ExpDecKey,
+// IN UINT32 Rounds,
+// IN UINT8 CONST *InBlock,
+// OUT UINT8 *OutBlock
+// );
+ASM_FUNC(ArmAesDecrypt)
+ ld1 {v0.16b}, [x2]
+ cmp w1, #12
+ beq 0f
+
+ // Rounds = 10 or 14. Start loading the expanded key.
+ ld1 {v4.4s}, [x0], #16
+ ld1 {v1.4s}, [x0], #16
+ ld1 {v2.4s}, [x0], #16
+ adds w1, w1, #1
+ b 2f
+
+ // Rounds = 12. Start loading the expanded key.
+0: ld1 {v2.4s}, [x0], #16
+ ld1 {v3.4s}, [x0], #16
+ ld1 {v4.4s}, [x0], #16
+ subs w1, w1, #1
+ b 3f
+
+ // Start of the loop (unfolded for 4 rounds).
+1: ld1 {v4.4s}, [x0], #16
+ aesd v0.16b, v1.16b
+ aesimc v0.16b, v0.16b
+3: ld1 {v1.4s}, [x0], #16
+ aesd v0.16b, v2.16b
+ aesimc v0.16b, v0.16b
+ ld1 {v2.4s}, [x0], #16
+ aesd v0.16b, v3.16b
+ aesimc v0.16b, v0.16b
+2: subs w1, w1, #4
+ ld1 {v3.4s}, [x0], #16
+ aesd v0.16b, v4.16b
+ aesimc v0.16b, v0.16b
+ bpl 1b
+
+ // Final round.
+ aesd v0.16b, v1.16b
+ eor v0.16b, v0.16b, v2.16b
+ st1 {v0.16b}, [x3]
+ ret
+
+// /** Perform a SubWord() operation (applying AES Sbox) on a 32-bits word.
+//
+// The Arm AESE instruction performs the AddRoundKey(), ShiftRows() and
+// SubBytes() AES steps in this order.
+//
+// During key expansion, only SubBytes() should be performed, so:
+// - use a key of {0} so AddRoundKey() becomes an identity function;
+// - the dup instruction allows to have a matrix with identic rows,
+// so ShiftRows() has no effect.
+//
+// @param [in] InWord The 32-bits word to apply SubWord() on.
+//
+// @return SubWord(word).
+// **/
+// UINT32
+// ArmAesSubWord (
+// IN UINT32 InWord
+// );
+ASM_FUNC(ArmAesSubWord)
+ dup v1.4s, w0
+ movi v0.16b, #0
+ aese v0.16b, v1.16b
+ umov w0, v0.s[0]
+ ret
+
+// /** Perform a InvMixColumns() operation on an AES block (128-bits) using
+// the Arm AESIMC instruction.
+//
+// This is usefull to get decryption key for the Equivalent Inverse Cipher.
+//
+// @param [in] InBlock Input block.
+// @param [out] OutBlock Output blocked.
+// **/
+// VOID
+// ArmAesInvert (
+// IN AES_BLOCK CONST *InBlock,
+// OUT AES_BLOCK *OutBlock
+// );
+ASM_FUNC(ArmAesInvert)
+ ld1 {v0.4s}, [x1]
+ aesimc v1.16b, v0.16b
+ st1 {v1.4s}, [x0]
+ ret
diff --git a/ArmPkg/Library/ArmAesLib/Arm/ArmAesLib.S b/ArmPkg/Library/ArmAesLib/Arm/ArmAesLib.S
new file mode 100644
index 000000000000..247d7c3d9ca2
--- /dev/null
+++ b/ArmPkg/Library/ArmAesLib/Arm/ArmAesLib.S
@@ -0,0 +1,183 @@
+/** @file
+ Arm(32) AES implementation.
+
+ Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AsmMacroIoLibV8.h>
+
+.fpu crypto-neon-fp-armv8
+
+// Generic notes:
+// - In Arm32, the AESE/AESD/AESMC/AESIMC instructions are using registers
+// as qX
+// - For some CPUs, the latency of VLD1 is 6, thus the unfolding.
+// - The latency of the AESE/AESMC pair is 2.
+// Cf.
+// Arm Cortex-X1 Core Revision: r1p2 Software Optimization Guide
+// Arm Cortex-X2 Core Revision: r2p0 Software Optimization Guide
+
+// /** Encrypt an AES block.
+//
+// @param [in] ExpEncKey Expanded encryption key. An array of 32-bits words
+// with the number of elements depending on the key
+// size:
+// * 128-bits: 44 words
+// * 192-bits: 52 words
+// * 256-bits: 60 words
+// @param [in] Rounds Number of rounds (depending on the key size).
+// @param [in] InBlock Input Block. The block to cipher.
+// @param [out] OutBlock Output Block. The ciphered block.
+// **/
+// VOID
+// ArmAesEncrypt (
+// IN UINT32 CONST *ExpEncKey,
+// IN UINT32 Rounds,
+// IN UINT8 CONST *InBlock,
+// OUT UINT8 *OutBlock
+// );
+ASM_FUNC(ArmAesEncrypt)
+ vld1.8 {q0}, [r2]
+ cmp r1, #12
+ beq 0f
+
+ // Rounds = 10 or 14. Start loading the expanded key.
+ vld1.8 {q4}, [r0]!
+ vld1.8 {q1}, [r0]!
+ vld1.8 {q2}, [r0]!
+ adds r1, r1, #1
+ b 2f
+
+ // Rounds = 12. Start loading the expanded key.
+0: vld1.8 {q2}, [r0]!
+ vld1.8 {q3}, [r0]!
+ vld1.8 {q4}, [r0]!
+ subs r1, r1, #1
+ b 3f
+
+ // Start of the loop (unfolded for 4 rounds).
+1: vld1.8 {q4}, [r0]!
+ aese.8 q0, q1
+ aesmc.8 q0, q0
+3: vld1.8 {q1}, [r0]!
+ aese.8 q0, q2
+ aesmc.8 q0, q0
+ vld1.8 {q2}, [r0]!
+ aese.8 q0, q3
+ aesmc.8 q0, q0
+2: subs r1, r1, #4
+ vld1.8 {q3}, [r0]!
+ aese.8 q0, q4
+ aesmc.8 q0, q0
+ bpl 1b
+
+ // Final round.
+ aese.8 q0, q1
+ veor q0, q0, q2
+ vst1.8 {q0}, [r3]
+ bx lr
+
+// /** Decrypt an AES 128-bits block.
+//
+// @param [in] ExpDecKey Expanded decryption key. An array of 32-bits words
+// with the number of elements depending on the key
+// size:
+// * 128-bits: 44 words
+// * 192-bits: 52 words
+// * 256-bits: 60 words
+// @param [in] Rounds Number of rounds (depending on the key size).
+// @param [in] InBlock Input Block. The block to de-cipher.
+// @param [out] OutBlock Output Block. The de-ciphered block.
+// **/
+// VOID
+// ArmAesDecrypt (
+// IN UINT32 CONST *ExpDecKey,
+// IN UINT32 Rounds,
+// IN UINT8 CONST *InBlock,
+// OUT UINT8 *OutBlock
+// );
+ASM_FUNC(ArmAesDecrypt)
+ vld1.8 {q0}, [r2]
+ cmp r1, #12
+ beq 0f
+
+ // Rounds = 10 or 14. Start loading the expanded key.
+ vld1.8 {q4}, [r0]!
+ vld1.8 {q1}, [r0]!
+ vld1.8 {q2}, [r0]!
+ adds r1, r1, #1
+ b 2f
+
+ // Rounds = 12. Start loading the expanded key.
+0: vld1.8 {q2}, [r0]!
+ vld1.8 {q3}, [r0]!
+ vld1.8 {q4}, [r0]!
+ subs r1, r1, #1
+ b 3f
+
+ // Start of the loop (unfolded for 4 rounds).
+1: vld1.8 {q4}, [r0]!
+ aesd.8 q0, q1
+ aesimc.8 q0, q0
+3: vld1.8 {q1}, [r0]!
+ aesd.8 q0, q2
+ aesimc.8 q0, q0
+ vld1.8 {q2}, [r0]!
+ aesd.8 q0, q3
+ aesimc.8 q0, q0
+2: subs r1, r1, #4
+ vld1.8 {q3}, [r0]!
+ aesd.8 q0, q4
+ aesimc.8 q0, q0
+ bpl 1b
+
+ // Final round.
+ aesd.8 q0, q1
+ veor q0, q0, q2
+ vst1.8 {q0}, [r3]
+ bx lr
+
+// /** Perform a SubWord() operation (applying AES Sbox) on a 32-bits word.
+//
+// The Arm AESE instruction performs the AddRoundKey(), ShiftRows() and
+// SubBytes() AES steps in this order.
+//
+// During key expansion, only SubBytes() should be performed, so:
+// - use a key of {0} so AddRoundKey() becomes an identity function;
+// - the dup instruction allows to have a matrix with identic rows,
+// so ShiftRows() has no effect.
+//
+// @param [in] InWord The 32-bits word to apply SubWord() on.
+//
+// @return SubWord(word).
+// **/
+// UINT32
+// ArmAesSubWord (
+// IN UINT32 InWord
+// );
+ASM_FUNC(ArmAesSubWord)
+ vdup.32 q1, r0
+ vmov.i64 q0, #0
+ aese.8 q0, q1
+ vmov.f32 r0, s0
+ bx lr
+
+// /** Perform a InvMixColumns() operation on an AES block (128-bits) using
+// the Arm AESIMC instruction.
+//
+// This is usefull to get decryption key for the Equivalent Inverse Cipher.
+//
+// @param [in] InBlock Input block.
+// @param [out] OutBlock Output blocked.
+// **/
+// VOID
+// ArmAesInvert (
+// IN AES_BLOCK CONST *InBlock,
+// OUT AES_BLOCK *OutBlock
+// );
+ASM_FUNC(ArmAesInvert)
+ vld1.8 {q0}, [r1]
+ aesimc.8 q1, q0
+ vst1.8 {q1}, [r0]
+ bx lr
diff --git a/ArmPkg/Library/ArmAesLib/ArmAesLib.c b/ArmPkg/Library/ArmAesLib/ArmAesLib.c
new file mode 100644
index 000000000000..ff3cfce75b2b
--- /dev/null
+++ b/ArmPkg/Library/ArmAesLib/ArmAesLib.c
@@ -0,0 +1,261 @@
+/** @file
+ Arm AES Library
+
+ Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - FIPS 197 November 26, 2001:
+ Specification for the ADVANCED ENCRYPTION STANDARD (AES)
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/AesLib.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include "ArmAesLib.h"
+
+/** The constructor checks that the FEAT_AES extension is available.
+
+ @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS.
+**/
+RETURN_STATUS
+EFIAPI
+AesLibConstructor (
+ VOID
+ )
+{
+ if (!ArmHasAesExt ()) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "FEAT_AES extension is not available. "
+ "This library cannot be used.\n"
+ ));
+ ASSERT_RETURN_ERROR (RETURN_UNSUPPORTED);
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ AES key schedule round constants.
+*/
+STATIC
+UINT8 CONST
+mRoundConstants[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
+};
+
+/** Get the number of Rounds.
+
+ AES needs to perform a different number of rounds depending on the key size:
+ * 128-bits: 10
+ * 192-bits: 12
+ * 256-bits: 14
+ So 6 + (n/4) rounds
+
+ @param [in] AesCtx AES context struct.
+
+ @return Number of rounds.
+**/
+STATIC
+UINT32
+GetNumRounds (
+ IN AES_CTX CONST *AesCtx
+ )
+{
+ return 6 + (AesCtx->KeySize >> 2);
+}
+
+/** Encrypt an AES block.
+
+ Buffers are little-endian. Overlapping is not checked.
+
+ @param [in] AesCtx AES context.
+ AesCtx is initialized with AesInitCtx ().
+ @param [in] InBlock Input Block. The block to cipher.
+ @param [out] OutBlock Output Block. The ciphered block.
+
+ @retval RETURN_SUCCESS Success.
+ @retval RETURN_INVALID_PARAMETER Invalid parameter.
+ @retval RETURN_UNSUPPORTED Unsupported.
+**/
+RETURN_STATUS
+EFIAPI
+AesEncrypt (
+ IN AES_CTX *AesCtx,
+ IN UINT8 CONST *InBlock,
+ OUT UINT8 *OutBlock
+ )
+{
+ if ((AesCtx == NULL) ||
+ (InBlock == NULL) ||
+ (OutBlock == NULL) ||
+ (InBlock == OutBlock))
+ {
+ ASSERT (AesCtx != NULL);
+ ASSERT (InBlock != NULL);
+ ASSERT (OutBlock != NULL);
+ ASSERT (InBlock != OutBlock);
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ ArmAesEncrypt (
+ AesCtx->ExpEncKey,
+ GetNumRounds (AesCtx),
+ InBlock,
+ OutBlock
+ );
+
+ return RETURN_SUCCESS;
+}
+
+/** Decrypt an AES block.
+
+ Buffers are little-endian. Overlapping is not checked.
+
+ @param [in] AesCtx AES context.
+ AesCtx is initialized with AesInitCtx ().
+ @param [in] InBlock Input Block. The block to de-cipher.
+ @param [out] OutBlock Output Block. The de-ciphered block.
+
+ @retval RETURN_SUCCESS Success.
+ @retval RETURN_INVALID_PARAMETER Invalid parameter.
+ @retval RETURN_UNSUPPORTED Unsupported.
+**/
+RETURN_STATUS
+EFIAPI
+AesDecrypt (
+ IN AES_CTX *AesCtx,
+ IN UINT8 CONST *InBlock,
+ OUT UINT8 *OutBlock
+ )
+{
+ if ((AesCtx == NULL) ||
+ (InBlock == NULL) ||
+ (OutBlock == NULL) ||
+ (InBlock == OutBlock))
+ {
+ ASSERT (AesCtx != NULL);
+ ASSERT (InBlock != NULL);
+ ASSERT (OutBlock != NULL);
+ ASSERT (InBlock != OutBlock);
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ ArmAesDecrypt (
+ AesCtx->ExpDecKey,
+ GetNumRounds (AesCtx),
+ InBlock,
+ OutBlock
+ );
+
+ return RETURN_SUCCESS;
+}
+
+/** Initialize an AES_CTX structure.
+
+ @param [in] Key AES key. Buffer of KeySize bytes.
+ The buffer is little endian.
+ @param [in] KeySize Size of the key. Must be one of 128|192|256.
+ @param [in, out] AesCtx AES context to initialize.
+
+ @retval RETURN_SUCCESS Success.
+ @retval RETURN_INVALID_PARAMETER Invalid parameter.
+ @retval RETURN_UNSUPPORTED Unsupported.
+**/
+RETURN_STATUS
+EFIAPI
+AesInitCtx (
+ IN UINT8 *Key,
+ IN UINT32 KeySize,
+ IN OUT AES_CTX *AesCtx
+ )
+{
+ UINTN Index;
+ UINTN RevIndex;
+ UINT32 KeyWords;
+ UINT32 *KeyIn;
+ UINT32 *KeyOut;
+ AES_BLOCK *InBlock;
+ AES_BLOCK *OutBlock;
+
+ if ((Key == NULL) ||
+ ((KeySize != 8 * AES_KEY_SIZE_128) &&
+ (KeySize != 8 * AES_KEY_SIZE_192) &&
+ (KeySize != 8 * AES_KEY_SIZE_256)) ||
+ (AesCtx == NULL))
+ {
+ ASSERT (Key != NULL);
+ ASSERT (
+ !((KeySize != 8 * AES_KEY_SIZE_128) &&
+ (KeySize != 8 * AES_KEY_SIZE_192) &&
+ (KeySize != 8 * AES_KEY_SIZE_256))
+ );
+ ASSERT (AesCtx != NULL);
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ // Internally, use bytes.
+ KeySize = KeySize >> 3;
+ AesCtx->KeySize = KeySize;
+ KeyWords = KeySize >> 2;
+
+ // The first part of the expanded key is the input key.
+ for (Index = 0; Index < KeyWords; Index++) {
+ AesCtx->ExpEncKey[Index] = ReadUnaligned32 (
+ (UINT32 *)(Key + (Index * sizeof (UINT32)))
+ );
+ }
+
+ for (Index = 0; Index < sizeof (mRoundConstants); Index++) {
+ KeyIn = AesCtx->ExpEncKey + (Index * KeyWords);
+ KeyOut = KeyIn + KeyWords;
+
+ KeyOut[0] = ArmAesSubWord (RRotU32 (KeyIn[KeyWords - 1], 8));
+ KeyOut[0] ^= mRoundConstants[Index] ^ KeyIn[0];
+ KeyOut[1] = KeyOut[0] ^ KeyIn[1];
+ KeyOut[2] = KeyOut[1] ^ KeyIn[2];
+ KeyOut[3] = KeyOut[2] ^ KeyIn[3];
+
+ if (KeySize == AES_KEY_SIZE_192) {
+ if (Index >= 7) {
+ break;
+ }
+
+ KeyOut[4] = KeyOut[3] ^ KeyIn[4];
+ KeyOut[5] = KeyOut[4] ^ KeyIn[5];
+ } else if (KeySize == AES_KEY_SIZE_256) {
+ if (Index >= 6) {
+ break;
+ }
+
+ KeyOut[4] = ArmAesSubWord (KeyOut[3]) ^ KeyIn[4];
+ KeyOut[5] = KeyOut[4] ^ KeyIn[5];
+ KeyOut[6] = KeyOut[5] ^ KeyIn[6];
+ KeyOut[7] = KeyOut[6] ^ KeyIn[7];
+ }
+ }
+
+ /*
+ * Generate the decryption key for the Equivalent Inverse Cipher.
+ * First and last state of the expanded encryption key are copied
+ * to the expanded decryption key.
+ * The other ones are copied bottom up from the expanded encryption
+ * key and undergo an InvMixColumns().
+ */
+ InBlock = (AES_BLOCK *)AesCtx->ExpEncKey;
+ OutBlock = (AES_BLOCK *)AesCtx->ExpDecKey;
+ RevIndex = GetNumRounds (AesCtx);
+
+ CopyMem (&OutBlock[0], &InBlock[RevIndex], sizeof (AES_BLOCK));
+ for (Index = 1, RevIndex--; RevIndex > 0; Index++, RevIndex--) {
+ ArmAesInvert (OutBlock + Index, InBlock + RevIndex);
+ }
+
+ CopyMem (&OutBlock[Index], &InBlock[0], sizeof (AES_BLOCK));
+
+ return RETURN_SUCCESS;
+}
diff --git a/ArmPkg/Library/ArmAesLib/ArmAesLib.h b/ArmPkg/Library/ArmAesLib/ArmAesLib.h
new file mode 100644
index 000000000000..dd926491a816
--- /dev/null
+++ b/ArmPkg/Library/ArmAesLib/ArmAesLib.h
@@ -0,0 +1,96 @@
+/** @file
+ Arm AES Library
+
+ Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - FIPS 197 November 26, 2001:
+ Specification for the ADVANCED ENCRYPTION STANDARD (AES)
+**/
+
+#ifndef ARM_AES_LIB_H_
+#define ARM_AES_LIB_H_
+
+/* An AES block is 128-bits long and can be seen as a matrix of 4 * 4 bytes.
+ */
+typedef struct AesBlock {
+ /// The AES block.
+ UINT8 Block[AES_BLOCK_SIZE];
+} AES_BLOCK;
+
+/** Encrypt an AES block.
+
+ @param [in] ExpEncKey Expanded encryption key. An array of 32-bits words
+ with the number of elements depending on the key
+ size:
+ * 128-bits: 44 words
+ * 192-bits: 52 words
+ * 256-bits: 60 words
+ @param [in] Rounds Number of rounds (depending on the key size).
+ @param [in] InBlock Input Block. The block to cipher.
+ @param [out] OutBlock Output Block. The ciphered block.
+**/
+VOID
+ArmAesEncrypt (
+ IN UINT32 CONST *ExpEncKey,
+ IN UINT32 Rounds,
+ IN UINT8 CONST *InBlock,
+ OUT UINT8 *OutBlock
+ );
+
+/** Decrypt an AES 128-bits block.
+
+ @param [in] ExpDecKey Expanded decryption key. An array of 32-bits words
+ with the number of elements depending on the key
+ size:
+ * 128-bits: 44 words
+ * 192-bits: 52 words
+ * 256-bits: 60 words
+ @param [in] Rounds Number of rounds (depending on the key size).
+ @param [in] InBlock Input Block. The block to de-cipher.
+ @param [out] OutBlock Output Block. The de-ciphered block.
+**/
+VOID
+ArmAesDecrypt (
+ IN UINT32 CONST *ExpDecKey,
+ IN UINT32 Rounds,
+ IN UINT8 CONST *InBlock,
+ OUT UINT8 *OutBlock
+ );
+
+/** Perform a SubWord() operation (applying AES Sbox) on a 32-bits word.
+
+ The Arm AESE instruction performs the AddRoundKey(), ShiftRows() and
+ SubBytes() AES steps in this order.
+
+ During key expansion, only SubBytes() should be performed, so:
+ - use a key of {0} so AddRoundKey() becomes an identity function;
+ - the dup instruction allows to have a matrix with identic rows,
+ so ShiftRows() has no effect.
+
+ @param [in] InWord The 32-bits word to apply SubWord() on.
+
+ @return SubWord(word).
+**/
+UINT32
+ArmAesSubWord (
+ IN UINT32 InWord
+ );
+
+/** Perform a InvMixColumns() operation on an AES block (128-bits) using
+ the Arm AESIMC instruction.
+
+ This is usefull to get decryption key for the Equivalent Inverse Cipher.
+
+ @param [in] InBlock Input block.
+ @param [out] OutBlock Output blocked.
+**/
+VOID
+ArmAesInvert (
+ IN AES_BLOCK CONST *InBlock,
+ OUT AES_BLOCK *OutBlock
+ );
+
+#endif // ARM_AES_LIB_H_
diff --git a/ArmPkg/Library/ArmAesLib/ArmAesLib.inf b/ArmPkg/Library/ArmAesLib/ArmAesLib.inf
new file mode 100644
index 000000000000..73c664a9f888
--- /dev/null
+++ b/ArmPkg/Library/ArmAesLib/ArmAesLib.inf
@@ -0,0 +1,34 @@
+## @file
+# AES Library
+#
+# Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = ArmAesLib
+ FILE_GUID = 585599F7-DA62-44F5-BA20-3D50AEF638B4
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = AesLib
+ CONSTRUCTOR = AesLibConstructor
+
+[Sources]
+ ArmAesLib.c
+ ArmAesLib.h
+
+[Sources.ARM]
+ Arm/ArmAesLib.S
+
+[Sources.AARCH64]
+ AArch64/AArch64AesLib.S
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ ArmLib
+ BaseLib
--
2.25.1
prev parent reply other threads:[~2022-06-29 19:14 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-29 19:13 [PATCH RESEND v1 0/7] Add AesLib and ArmAesLib PierreGondois
2022-06-29 19:13 ` [PATCH RESEND v1 1/7] ArmPkg: Update Armpkg.ci.yaml PierreGondois
2022-06-29 19:13 ` [PATCH RESEND v1 2/7] ArmPkg/ArmDisassemblerLib: Replace RotateRight() PierreGondois
2022-06-29 19:13 ` [PATCH RESEND v1 3/7] ArmPkg/ArmLib: Add ArmReadIdIsaR5() helper PierreGondois
2022-06-29 19:13 ` [PATCH RESEND v1 4/7] ArmPkg/ArmLib: Add ArmHasAesExt() PierreGondois
2022-06-29 19:13 ` [PATCH RESEND v1 5/7] MdePkg/AesLib: Definition for AES library class interface PierreGondois
2022-06-30 0:29 ` [edk2-devel] " Yao, Jiewen
2022-07-01 9:48 ` PierreGondois
2022-07-01 11:55 ` Yao, Jiewen
2022-07-01 13:58 ` PierreGondois
2022-07-01 14:40 ` Yao, Jiewen
2022-07-01 15:22 ` PierreGondois
2022-07-01 16:11 ` Yao, Jiewen
2022-07-04 13:16 ` PierreGondois
2022-06-29 19:13 ` [PATCH RESEND v1 6/7] MdePkg/AesLib: Add NULL instance of AesLib PierreGondois
2022-06-29 19:13 ` PierreGondois [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220629191355.2618844-8-Pierre.Gondois@arm.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox