public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Zurcher, Christopher J" <christopher.j.zurcher@intel.com>
To: devel@edk2.groups.io
Cc: Jiewen Yao <jiewen.yao@intel.com>,
	Jian J Wang <jian.j.wang@intel.com>,
	Xiaoyu Lu <xiaoyux.lu@intel.com>,
	Guomin Jiang <guomin.jiang@intel.com>,
	Sung-Uk Bin <sunguk-bin@hp.com>
Subject: [PATCH 1/1] CryptoPkg/BaseCryptLib: Add EVP implementation for CryptAes.c
Date: Wed, 28 Oct 2020 11:42:54 -0700	[thread overview]
Message-ID: <20201028184254.6923-2-christopher.j.zurcher@intel.com> (raw)
In-Reply-To: <20201028184254.6923-1-christopher.j.zurcher@intel.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2507

The EVP interface is required to access the assembly-optimized AES
implementation.
This file alone will not provide assembly-optimized code; it must be
combined with an architecture-specific implementation of OpensslLib.

This is a drop-in replacement for CryptAes.c.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyux.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Sung-Uk Bin <sunguk-bin@hp.com>
Signed-off-by: Christopher J Zurcher <christopher.j.zurcher@intel.com>
---
 CryptoPkg/Library/BaseCryptLib/Cipher/CryptAesEvp.c | 262 ++++++++++++++++++++
 1 file changed, 262 insertions(+)

diff --git a/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAesEvp.c b/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAesEvp.c
new file mode 100644
index 0000000000..e243228c43
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Cipher/CryptAesEvp.c
@@ -0,0 +1,262 @@
+/** @file
+  AES Wrapper Implementation over OpenSSL EVP (Envelope) interface.
+
+Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <openssl/evp.h>
+
+typedef struct {
+  CONST UINT8       *Key;
+  CONST EVP_CIPHER  *EvpCipher;
+} AES_CONTEXT;
+
+/**
+  Retrieves the size, in bytes, of the context buffer required for AES operations.
+
+  @return  The size, in bytes, of the context buffer required for AES operations.
+
+**/
+UINTN
+EFIAPI
+AesGetContextSize (
+  VOID
+  )
+{
+  //
+  // Store Key locally to provide it to the worker functions
+  //
+  return (UINTN) sizeof (AES_CONTEXT);
+}
+
+/**
+  Initializes user-supplied memory as AES context for subsequent use.
+
+  This function initializes user-supplied memory pointed by AesContext as AES context.
+  In addition, it sets up all AES key materials for subsequent encryption and decryption
+  operations.
+  There are 3 options for key length, 128 bits, 192 bits, and 256 bits.
+
+  If AesContext is NULL, then return FALSE.
+  If Key is NULL, then return FALSE.
+  If KeyLength is not valid, then return FALSE.
+
+  @param[out]  AesContext  Pointer to AES context being initialized.
+  @param[in]   Key         Pointer to the user-supplied AES key.
+  @param[in]   KeyLength   Length of AES key in bits.
+
+  @retval TRUE   AES context initialization succeeded.
+  @retval FALSE  AES context initialization failed.
+
+**/
+BOOLEAN
+EFIAPI
+AesInit (
+  OUT  VOID         *AesContext,
+  IN   CONST UINT8  *Key,
+  IN   UINTN        KeyLength
+  )
+{
+  AES_CONTEXT *Context = AesContext;
+
+  //
+  // Check input parameters.
+  //
+  if (AesContext == NULL || Key == NULL || (KeyLength != 128 && KeyLength != 192 && KeyLength != 256)) {
+    return FALSE;
+  }
+
+  //
+  // Store AES Key and EVP Cipher inside the user-provided Context
+  //
+  Context->Key = Key;
+
+  switch (KeyLength) {
+    case 128:
+      Context->EvpCipher = EVP_aes_128_cbc();
+      break;
+    case 192:
+      Context->EvpCipher = EVP_aes_192_cbc();
+      break;
+    case 256:
+      Context->EvpCipher = EVP_aes_256_cbc();
+      break;
+    default:
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Performs AES encryption on a data buffer of the specified size in CBC mode.
+
+  This function performs AES encryption on data buffer pointed by Input, of specified
+  size of InputSize, in CBC mode.
+  InputSize must be multiple of block size (16 bytes). This function does not perform
+  padding. Caller must perform padding, if necessary, to ensure valid input data size.
+  Initialization vector should be one block size (16 bytes).
+  AesContext should be already correctly initialized by AesInit(). Behavior with
+  invalid AES context is undefined.
+
+  If AesContext is NULL, then return FALSE.
+  If Input is NULL, then return FALSE.
+  If InputSize is not multiple of block size (16 bytes), then return FALSE.
+  If Ivec is NULL, then return FALSE.
+  If Output is NULL, then return FALSE.
+
+  @param[in]   AesContext  Pointer to the AES context.
+  @param[in]   Input       Pointer to the buffer containing the data to be encrypted.
+  @param[in]   InputSize   Size of the Input buffer in bytes.
+  @param[in]   Ivec        Pointer to initialization vector.
+  @param[out]  Output      Pointer to a buffer that receives the AES encryption output.
+
+  @retval TRUE   AES encryption succeeded.
+  @retval FALSE  AES encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+AesCbcEncrypt (
+  IN   VOID         *AesContext,
+  IN   CONST UINT8  *Input,
+  IN   UINTN        InputSize,
+  IN   CONST UINT8  *Ivec,
+  OUT  UINT8        *Output
+  )
+{
+  AES_CONTEXT     *Context = AesContext;
+  EVP_CIPHER_CTX  *EvpContext;
+  INT32           OutputSize;
+  INT32           TempSize;
+
+  //
+  // Check input parameters.
+  //
+  if (AesContext == NULL || Input == NULL || (InputSize % AES_BLOCK_SIZE) != 0) {
+    return FALSE;
+  }
+
+  if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) {
+    return FALSE;
+  }
+
+  EvpContext = EVP_CIPHER_CTX_new();
+  if (EvpContext == NULL) {
+    return FALSE;
+  }
+
+  //
+  // Perform AES data encryption with CBC mode
+  //
+  if (EVP_EncryptInit_ex(EvpContext, Context->EvpCipher, NULL, Context->Key, Ivec) != 1) {
+    EVP_CIPHER_CTX_free(EvpContext);
+    return FALSE;
+  }
+
+  //
+  // Disable padding to match the software-based implementation
+  //
+  EVP_CIPHER_CTX_set_padding (EvpContext, 0);
+
+  if (EVP_EncryptUpdate(EvpContext, Output, &OutputSize, Input, (INT32) InputSize) != 1) {
+    EVP_CIPHER_CTX_free(EvpContext);
+    return FALSE;
+  }
+
+  if (EVP_EncryptFinal_ex(EvpContext, Output + OutputSize, &TempSize) != 1) {
+    EVP_CIPHER_CTX_free(EvpContext);
+    return FALSE;
+  }
+
+  EVP_CIPHER_CTX_free(EvpContext);
+  return TRUE;
+}
+
+/**
+  Performs AES decryption on a data buffer of the specified size in CBC mode.
+
+  This function performs AES decryption on data buffer pointed by Input, of specified
+  size of InputSize, in CBC mode.
+  InputSize must be multiple of block size (16 bytes). This function does not perform
+  padding. Caller must perform padding, if necessary, to ensure valid input data size.
+  Initialization vector should be one block size (16 bytes).
+  AesContext should be already correctly initialized by AesInit(). Behavior with
+  invalid AES context is undefined.
+
+  If AesContext is NULL, then return FALSE.
+  If Input is NULL, then return FALSE.
+  If InputSize is not multiple of block size (16 bytes), then return FALSE.
+  If Ivec is NULL, then return FALSE.
+  If Output is NULL, then return FALSE.
+
+  @param[in]   AesContext  Pointer to the AES context.
+  @param[in]   Input       Pointer to the buffer containing the data to be encrypted.
+  @param[in]   InputSize   Size of the Input buffer in bytes.
+  @param[in]   Ivec        Pointer to initialization vector.
+  @param[out]  Output      Pointer to a buffer that receives the AES encryption output.
+
+  @retval TRUE   AES decryption succeeded.
+  @retval FALSE  AES decryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+AesCbcDecrypt (
+  IN   VOID         *AesContext,
+  IN   CONST UINT8  *Input,
+  IN   UINTN        InputSize,
+  IN   CONST UINT8  *Ivec,
+  OUT  UINT8        *Output
+  )
+{
+  AES_CONTEXT     *Context = AesContext;
+  EVP_CIPHER_CTX  *EvpContext;
+  INT32           OutputSize;
+  INT32           TempSize;
+
+  //
+  // Check input parameters.
+  //
+  if (AesContext == NULL || Input == NULL || (InputSize % AES_BLOCK_SIZE) != 0) {
+    return FALSE;
+  }
+
+  if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) {
+    return FALSE;
+  }
+
+  EvpContext = EVP_CIPHER_CTX_new();
+  if (EvpContext == NULL) {
+    return FALSE;
+  }
+
+  //
+  // Perform AES data encryption with CBC mode
+  //
+  if (EVP_DecryptInit_ex(EvpContext, Context->EvpCipher, NULL, Context->Key, Ivec) != 1) {
+    EVP_CIPHER_CTX_free(EvpContext);
+    return FALSE;
+  }
+
+  //
+  // Disable padding to match the software-based implementation
+  //
+  EVP_CIPHER_CTX_set_padding (EvpContext, 0);
+
+  if (EVP_DecryptUpdate(EvpContext, Output, &OutputSize, Input, (INT32) InputSize) != 1) {
+    EVP_CIPHER_CTX_free(EvpContext);
+    return FALSE;
+  }
+
+  if (EVP_DecryptFinal_ex(EvpContext, Output + OutputSize, &TempSize) != 1) {
+    EVP_CIPHER_CTX_free(EvpContext);
+    return FALSE;
+  }
+
+  EVP_CIPHER_CTX_free(EvpContext);
+  return TRUE;
+}
-- 
2.28.0.windows.1


  reply	other threads:[~2020-10-28 18:42 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-28 18:42 [PATCH 0/1] CryptoPkg/BaseCryptLib: Add EVP implementation for CryptAes.c Zurcher, Christopher J
2020-10-28 18:42 ` Zurcher, Christopher J [this message]
2020-10-31  1:10 ` Yao, Jiewen
2020-11-02 22:36   ` Zurcher, Christopher J
2020-11-03  1:13     ` Yao, Jiewen
2020-11-03  1:22       ` Bret Barkelew
2020-11-03 21:54         ` Zurcher, Christopher J
2020-11-03 23:03           ` Yao, Jiewen
2020-11-03  7:51     ` Ard Biesheuvel
2020-11-03 19:15       ` Zurcher, Christopher J

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=20201028184254.6923-2-christopher.j.zurcher@intel.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