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+tianoc...@kernel.org>
Cc: Leif Lindholm <quic_llind...@quicinc.com>
Cc: Gerd Hoffmann <kra...@redhat.com>
Signed-off-by: Sami Mujawar <sami.muja...@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/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to