public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sami Mujawar" <sami.mujawar@arm.com>
To: <devel@edk2.groups.io>
Cc: Sami Mujawar <sami.mujawar@arm.com>, <ardb+tianocore@kernel.org>,
	<quic_llindhol@quicinc.com>, <kraxel@redhat.com>,
	<Matteo.Carlini@arm.com>, <Akanksha.Jain2@arm.com>,
	<Sibel.Allinson@arm.com>, <nd@arm.com>
Subject: [edk2-devel] [PATCH v2 42/45] ArmVirtPkg: RMM 1.0-eac5 - Attestation token API updates
Date: Fri, 12 Apr 2024 15:33:19 +0100	[thread overview]
Message-ID: <20240412143322.5244-43-sami.mujawar@arm.com> (raw)
In-Reply-To: <20240412143322.5244-1-sami.mujawar@arm.com>

The RMM 1.0-eac3 specification removed the restriction that
attestation token size must not exceed 4KB. Further it also
extended the RSI_ATTESTATION_TOKEN_CONTINUE command so as to
return up to a granule worth of the attestation token data.

The RMM 1.0-eac5 specification simplified the attestation
token interfaces such that, the RSI_ATTESTATION_TOKEN_INIT
command returns the upper bound of the attestation token
size. This eliminates the need for relocation of token data
buffers during attestation token retrieval.

Therefore, implement the attestation token API updates
from RMM 1.0-eac3 through to RMM 1.0-eac5 specification.

Note: The RsiGetAttestationToken() API has been modified
such that ArmCcaRsiLib allocates memory for the returned
attestation token buffer. The caller is therefore required
to call RsiFreeAttestationToken() to free the memory that
was allocated for the attestation token buffer.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Include/Library/ArmCcaRsiLib.h      |  31 ++--
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c | 160 +++++++++++++++-----
 2 files changed, 146 insertions(+), 45 deletions(-)

diff --git a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
index 8c1c0d5bc19d14fa640464c8d0d44e3ef522ba79..b768f3498314a2ea61762af65bf2668d463909a6 100644
--- a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
+++ b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
@@ -11,7 +11,7 @@
     - REM          - Realm Extensible Measurement
 
   @par Reference(s):
-   - Realm Management Monitor (RMM) Specification, version 1.0-eac4
+   - Realm Management Monitor (RMM) Specification, version 1.0-eac5
      (https://developer.arm.com/documentation/den0137/)
 **/
 
@@ -33,11 +33,6 @@
 */
 #define RIPAS_TYPE_MASK  0xFF
 
-/* Maximum attestation token size
-  RBXKKY The size of an attestation token is no larger than 4KB.
-*/
-#define MAX_ATTESTATION_TOKEN_SIZE  SIZE_4KB
-
 /* Maximum challenge data size in bits.
 */
 #define MAX_CHALLENGE_DATA_SIZE_BITS  512
@@ -185,9 +180,10 @@ typedef struct HostCallArgs {
   @param [in]       ChallengeDataSizeBits Size of the challenge data in bits.
   @param [out]      TokenBuffer           Pointer to a buffer to store the
                                           retrieved attestation token.
-  @param [in, out]  TokenBufferSize       Size of the token buffer on input and
-                                          number of bytes stored in token buffer
-                                          on return.
+  @param [out]      TokenBufferSize       Length of token data returned.
+
+  Note: The TokenBuffer allocated must be freed by the caller
+  using RsiFreeAttestationToken().
 
   @retval RETURN_SUCCESS            Success.
   @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
@@ -202,8 +198,21 @@ EFIAPI
 RsiGetAttestationToken (
   IN      CONST UINT8   *CONST  ChallengeData,
   IN            UINT64          ChallengeDataSizeBits,
-  OUT           UINT8   *CONST  TokenBuffer,
-  IN OUT        UINT64  *CONST  TokenBufferSize
+  OUT           UINT8  **CONST  TokenBuffer,
+  OUT           UINT64  *CONST  TokenBufferSize
+  );
+
+/**
+  Free the attestation token buffer.
+
+  @param [in]      TokenBuffer           Pointer to the retrieved
+                                         attestation token.
+  @param [in]      TokenBufferSize       Size of the token buffer.
+**/
+VOID
+RsiFreeAttestationToken (
+  IN           UINT8  *CONST  TokenBuffer,
+  IN           UINT64  CONST  TokenBufferSize
   );
 
 /**
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
index edd2e11f786d11191f13dd9b087cdeec4127b375..b861b2e79d5d659a0eb16206d329a0cb039eda0d 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
@@ -11,7 +11,7 @@
     - REM          - Realm Extensible Measurement
 
   @par Reference(s):
-   - Realm Management Monitor (RMM) Specification, version 1.0-eac4
+   - Realm Management Monitor (RMM) Specification, version 1.0-eac5
      (https://developer.arm.com/documentation/den0137/)
 
 **/
@@ -22,6 +22,7 @@
 #include <Library/ArmSmcLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
 #include "ArmCcaRsi.h"
 
 /**
@@ -88,6 +89,8 @@ AddrIsGranuleAligned (
 
   @param [out]     TokenBuffer      Pointer to a buffer to store the
                                     retrieved attestation token.
+  @param [in]      Offset           Offset within Token buffer granule
+                                    to start of buffer in bytes.
   @param [in,out]  TokenSize        On input size of the token buffer,
                                     and on output size of the token
                                     returned if operation is successful,
@@ -106,6 +109,7 @@ RETURN_STATUS
 EFIAPI
 RsiAttestationTokenContinue (
   OUT           UINT8   *CONST  TokenBuffer,
+  IN            UINT64   CONST  Offset,
   IN OUT        UINT64  *CONST  TokenSize
   )
 {
@@ -116,6 +120,10 @@ RsiAttestationTokenContinue (
   SmcCmd.Arg0 = FID_RSI_ATTESTATION_TOKEN_CONTINUE;
   // Set the IPA of the Granule to which the token will be written.
   SmcCmd.Arg1 = (UINTN)TokenBuffer;
+  // Set the Offset within Granule to start of buffer in bytes
+  SmcCmd.Arg2 = (UINTN)Offset;
+  // Set the size of the buffer in bytes
+  SmcCmd.Arg3 = (UINTN)*TokenSize;
 
   ArmCallSmc (&SmcCmd);
   Status = RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
@@ -137,8 +145,8 @@ RsiAttestationTokenContinue (
   @param [in]       ChallengeData         Pointer to the challenge data to be
                                           included in the attestation token.
   @param [in]       ChallengeDataSizeBits Size of the challenge data in bits.
-  @param [in]       TokenBuffer           Pointer to a buffer to store the
-                                          retrieved attestation token.
+  @param [out]      MaxTokenSize          Pointer to an integer to retrieve
+                                          the maximum attestation token size.
 
   @retval RETURN_SUCCESS            Success.
   @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
@@ -149,14 +157,15 @@ EFIAPI
 RsiAttestationTokenInit (
   IN      CONST UINT8   *CONST  ChallengeData,
   IN            UINT64          ChallengeDataSizeBits,
-  IN            UINT8   *CONST  TokenBuffer
+  OUT           UINT64  *CONST  MaxTokenSize
   )
 {
-  ARM_SMC_ARGS  SmcCmd;
-  UINT8         *Buffer8;
-  CONST UINT8   *Data8;
-  UINT64        Count;
-  UINT8         TailBits;
+  RETURN_STATUS  Status;
+  ARM_SMC_ARGS   SmcCmd;
+  UINT8          *Buffer8;
+  CONST UINT8    *Data8;
+  UINT64         Count;
+  UINT8          TailBits;
 
   /* See A7.2.2 Attestation token generation, RMM Specification, version A-bet0
      IWTKDD - If the size of the challenge provided by the relying party is less
@@ -168,11 +177,8 @@ RsiAttestationTokenInit (
   */
   ZeroMem (&SmcCmd, sizeof (SmcCmd));
   SmcCmd.Arg0 = FID_RSI_ATTESTATION_TOKEN_INIT;
-  // Set the IPA of the Granule to which the token will be written.
-  SmcCmd.Arg1 = (UINTN)TokenBuffer;
-
   // Copy challenge data.
-  Buffer8 = (UINT8 *)&SmcCmd.Arg2;
+  Buffer8 = (UINT8 *)&SmcCmd.Arg1;
   Data8   = ChallengeData;
 
   // First copy whole bytes
@@ -194,7 +200,38 @@ RsiAttestationTokenInit (
   }
 
   ArmCallSmc (&SmcCmd);
-  return RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+  Status = RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+  if (RETURN_ERROR (Status)) {
+    // Set the max token size to zero
+    *MaxTokenSize = 0;
+  } else {
+    *MaxTokenSize = SmcCmd.Arg1;
+  }
+
+  return Status;
+}
+
+/**
+  Free the attestation token buffer.
+
+  @param [in]      TokenBuffer           Pointer to the retrieved
+                                         attestation token.
+  @param [in]      TokenBufferSize       Size of the token buffer.
+**/
+VOID
+RsiFreeAttestationToken (
+  IN           UINT8  *CONST  TokenBuffer,
+  IN           UINT64  CONST  TokenBufferSize
+  )
+{
+  if (TokenBuffer != NULL) {
+    if (TokenBufferSize > 0) {
+      // Scrub the token buffer
+      ZeroMem (TokenBuffer, TokenBufferSize);
+    }
+
+    FreePool (TokenBuffer);
+  }
 }
 
 /**
@@ -205,9 +242,10 @@ RsiAttestationTokenInit (
   @param [in]       ChallengeDataSizeBits Size of the challenge data in bits.
   @param [out]      TokenBuffer           Pointer to a buffer to store the
                                           retrieved attestation token.
-  @param [in, out]  TokenBufferSize       Size of the token buffer on input and
-                                          number of bytes stored in token buffer
-                                          on return.
+  @param [out]      TokenBufferSize       Length of token data returned.
+
+  Note: The TokenBuffer allocated must be freed by the caller
+  using RsiFreeAttestationToken().
 
   @retval RETURN_SUCCESS            Success.
   @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
@@ -222,11 +260,17 @@ EFIAPI
 RsiGetAttestationToken (
   IN      CONST UINT8   *CONST  ChallengeData,
   IN            UINT64          ChallengeDataSizeBits,
-  OUT           UINT8   *CONST  TokenBuffer,
-  IN OUT        UINT64  *CONST  TokenBufferSize
+  OUT           UINT8  **CONST  TokenBuffer,
+  OUT           UINT64  *CONST  TokenBufferSize
   )
 {
   RETURN_STATUS  Status;
+  UINT8          *Granule;
+  UINT64         GranuleSize;
+  UINT64         Offset;
+  UINT8          *Token;
+  UINT64         TokenSize;
+  UINT64         MaxTokenSize;
 
   if ((TokenBuffer == NULL) ||
       (TokenBufferSize == NULL) ||
@@ -235,16 +279,6 @@ RsiGetAttestationToken (
     return RETURN_INVALID_PARAMETER;
   }
 
-  if (*TokenBufferSize < MAX_ATTESTATION_TOKEN_SIZE) {
-    *TokenBufferSize = MAX_ATTESTATION_TOKEN_SIZE;
-    return RETURN_BAD_BUFFER_SIZE;
-  }
-
-  if (!AddrIsGranuleAligned ((UINT64 *)TokenBuffer)) {
-    DEBUG ((DEBUG_ERROR, "ERROR : Token buffer not granule aligned\n"));
-    return RETURN_INVALID_PARAMETER;
-  }
-
   if (ChallengeDataSizeBits > MAX_CHALLENGE_DATA_SIZE_BITS) {
     return RETURN_INVALID_PARAMETER;
   }
@@ -260,18 +294,76 @@ RsiGetAttestationToken (
   Status = RsiAttestationTokenInit (
              ChallengeData,
              ChallengeDataSizeBits,
-             TokenBuffer
+             &MaxTokenSize
              );
   if (RETURN_ERROR (Status)) {
     ASSERT (0);
     return Status;
   }
 
-  /* Loop until the token is ready or there is an error.
-  */
+  // Allocate a granule to retrieve the attestation token chunk.
+  Granule = (UINT8 *)AllocateAlignedPages (
+                       EFI_SIZE_TO_PAGES (REALM_GRANULE_SIZE),
+                       REALM_GRANULE_SIZE
+                       );
+  if (Granule == NULL) {
+    ASSERT (0);
+    return RETURN_OUT_OF_RESOURCES;
+  }
+
+  // Alloate a buffer to store the retrieved attestation token.
+  Token = AllocateZeroPool (MaxTokenSize);
+  if (Token == NULL) {
+    ASSERT (0);
+    Status = RETURN_OUT_OF_RESOURCES;
+    goto exit_handler;
+  }
+
+  TokenSize = 0;
   do {
-    Status = RsiAttestationTokenContinue (TokenBuffer, TokenBufferSize);
-  } while (Status == RETURN_NOT_READY);
+    // Retrieve one Granule of data per loop iteration
+    ZeroMem (Granule, REALM_GRANULE_SIZE);
+    Offset = 0;
+    do {
+      // Retrieve sub-Granule chunk of data per loop iteration
+      GranuleSize = REALM_GRANULE_SIZE - Offset;
+      Status      = RsiAttestationTokenContinue (
+                      Granule,
+                      Offset,
+                      &GranuleSize
+                      );
+      Offset += GranuleSize;
+    } while ((Status == RETURN_NOT_READY) && (Offset < REALM_GRANULE_SIZE));
+
+    if (RETURN_ERROR (Status) && (Status != RETURN_NOT_READY)) {
+      ASSERT (0);
+      goto exit_handler1;
+    }
+
+    // "Offset" bytes of data are now ready for consumption from "Granule"
+    // Copy the new token data from the Granule.
+    CopyMem (&Token[TokenSize], Granule, Offset);
+    TokenSize += Offset;
+  } while ((Status == RETURN_NOT_READY) && (TokenSize < MaxTokenSize));
+
+  *TokenBuffer     = Token;
+  *TokenBufferSize = TokenSize;
+  goto exit_handler;
+
+exit_handler1:
+  if (Token != NULL) {
+    // Scrub the old Token
+    ZeroMem (Token, TokenSize);
+    FreePool (Token);
+  }
+
+  *TokenBuffer     = NULL;
+  *TokenBufferSize = 0;
+
+exit_handler:
+  // Scrub the Granule buffer
+  ZeroMem (Granule, REALM_GRANULE_SIZE);
+  FreePages (Granule, EFI_SIZE_TO_PAGES (REALM_GRANULE_SIZE));
 
   return Status;
 }
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117706): https://edk2.groups.io/g/devel/message/117706
Mute This Topic: https://groups.io/mt/105483450/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



      parent reply	other threads:[~2024-04-12 14:34 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20240412143322.5244-1-sami.mujawar@arm.com>
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 01/45] ArmPkg: Add helper function to detect RME Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 02/45] ArmPkg: Introduce SetMemoryProtectionAttribute() for Realms Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 03/45] ArmPkg: Extend number of parameter registers in SMC call Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 04/45] ArmVirtPkg: Add Arm CCA Realm Service Interface Library Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 05/45] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to manage the Realm IPA state Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 06/45] ArmVirtPkg: ArmCcaRsiLib: Add an interface to get an attestation token Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 07/45] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to get/extend REMs Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 08/45] ArmVirtPkg: ArmCcaRsiLib: Add an interface to make a RSI Host Call Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 09/45] ArmVirtPkg: Define a GUID HOB for IPA width of a Realm Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 10/45] ArmVirtPkg: Add library for Arm CCA initialisation in PEI Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 11/45] ArmVirtPkg: Add NULL instance of ArmCcaInitPeiLib Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 12/45] ArmVirtPkg: Add library for Arm CCA helper functions Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 13/45] ArmVirtPkg: Add Null instance of ArmCcaLib Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 14/45] ArmVirtPkg: Define an interface to configure MMIO regions for Arm CCA Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 15/45] ArmVirtPkg: CloudHv: Add a NULL implementation of ArmCcaConfigureMmio Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 16/45] ArmVirtPkg: Qemu: " Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 17/45] ArmVirtPkg: Xen: " Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 18/45] ArmVirtPkg: Configure the MMIO regions for Arm CCA Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 19/45] ArmVirtPkg: Kvmtool: Use Null version of DebugLib in PrePi Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 20/45] ArmVirtPkg: Introduce ArmVirtMonitorLib library Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 21/45] ArmVirtPkg: Kvmtool: Use ArmVirt instance of ArmMonitorLib Sami Mujawar
2024-04-12 14:32 ` [edk2-devel] [PATCH v2 22/45] ArmVirtPkg: Add Arm CCA libraries for Kvmtool guest firmware Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 23/45] ArmVirtPkg: Arm CCA configure system memory in early Pei Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 24/45] ArmVirtPkg: Perform Arm CCA initialisation in the Pei phase Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 25/45] ArmVirtPkg: Introduce Realm Aperture Management Protocol Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 26/45] ArmVirtPkg: IoMMU driver to DMA from Realms Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 27/45] ArmVirtPkg: Enable Virtio communication for Arm CCA Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 28/45] MdePkg: Warn if AArch64 RNDR instruction is not supported Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 29/45] ArmVirtPkg: Kvmtool: Switch to use BaseRng for AArch64 Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 31/45] ArmVirtPkg: ArmCcaRsiLib: Fix size of Imm field in HostCallArgs Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 32/45] ArmVirtPkg: RMM 1.0-bet1 - Update width of RSI host call struct Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 33/45] ArmVirtPkg: RMM 1.0-bet2 - Increase number of RSI host call args Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 34/45] ArmVirtPkg: RMM 1.0-eac0 - Update RsiSetIpaState parameter usage Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 35/45] ArmVirtPkg: RMM 1.0-eac1 - Relax alignment of RSI host call arg Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 36/45] ArmVirtPkg: RMM 1.0-eac2 - Update RsiRealmConfig structure Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 37/45] ArmVirtPkg: RMM 1.0-eac2 - Add RIPAS DESTROYED state Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 38/45] ArmVirtPkg: RMM 1.0-eac2 - Add RsiRipasChangeFlags definitions Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 39/45] ArmVirtPkg: RMM 1.0-eac2 - Add Flags to RsiSetIpaState() Sami Mujawar
2024-04-12 14:33 ` [edk2-devel] [PATCH v2 40/45] ArmVirtPkg: RMM 1.0-eac3 - Handle RsiSetIpaState() response Sami Mujawar
2024-04-12 14:33 ` Sami Mujawar [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=20240412143322.5244-43-sami.mujawar@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