A CCA attestation token is a collection of claims about the state of a Realm and of the CCA platform on which the Realm is running. A CCA attestation token consists of two parts: * Realm token - Contains attributes of the Realm, including: # Realm Initial Measurement # Realm Extensible Measurements * CCA platform token - Contains attributes of the CCA platform on which the Realm is running, including: # CCA platform identity # CCA platform life cycle state # CCA platform software component measurements
The CCA attestation token is used by a verification service to validate these claims. The Realm Service Interface defines the following interfaces to retrieve an attestation token from the Realm Management Monitor (RMM). - RSI_ATTESTATION_TOKEN_INIT - RSI_ATTESTATION_TOKEN_CONTINUE Therefore, update the ArmCcaRsiLib to add an interface to get an attestation token from the RMM. Signed-off-by: Sami Mujawar <sami.muja...@arm.com> --- ArmVirtPkg/Include/Library/ArmCcaRsiLib.h | 42 +++++ ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h | 10 +- ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c | 193 ++++++++++++++++++++ 3 files changed, 241 insertions(+), 4 deletions(-) diff --git a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h index ae798a2feb9c3c417f06b7c2dfdb49479731df52..fe176d83c4b11d3f7bb35c97ec8ef00a4f47f981 100644 --- a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h +++ b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h @@ -31,6 +31,19 @@ */ #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 + +/* Minimum recommended challenge data size in bits. +*/ +#define MIN_CHALLENGE_DATA_SIZE_BITS 256 + /** An enum describing the RSI RIPAS. See Section A5.2.2 Realm IPA state, RMM Specification, version A-bet0 */ @@ -51,6 +64,35 @@ typedef struct RealmConfig { UINT8 Reserved[SIZE_4KB - sizeof (UINT64)]; } REALM_CONFIG; +/** + Retrieve an attestation token from the RMM. + + @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 [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. + + @retval RETURN_SUCCESS Success. + @retval RETURN_INVALID_PARAMETER A parameter is invalid. + @retval RETURN_ABORTED The operation was aborted as the state + of the Realm or REC does not match the + state expected by the command. + @retval RETURN_NOT_READY The operation requested by the command + is not complete. +**/ +RETURN_STATUS +EFIAPI +RsiGetAttestationToken ( + IN CONST UINT8 *CONST ChallengeData, + IN UINT64 ChallengeDataSizeBits, + OUT UINT8 *CONST TokenBuffer, + IN OUT UINT64 *CONST TokenBufferSize + ); + /** Returns the IPA state for the page pointed by the address. diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h index 9cc12bc5a70b457367077d0b26011c3b91fa63c9..325234d06695befc840dcf37e951130dfe0550c3 100644 --- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h +++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h @@ -18,10 +18,12 @@ #define ARM_CCA_RSI_H_ // FIDs for Realm Service Interface calls. -#define FID_RSI_IPA_STATE_GET 0xC4000198 -#define FID_RSI_IPA_STATE_SET 0xC4000197 -#define FID_RSI_REALM_CONFIG 0xC4000196 -#define FID_RSI_VERSION 0xC4000190 +#define FID_RSI_ATTESTATION_TOKEN_CONTINUE 0xC4000195 +#define FID_RSI_ATTESTATION_TOKEN_INIT 0xC4000194 +#define FID_RSI_IPA_STATE_GET 0xC4000198 +#define FID_RSI_IPA_STATE_SET 0xC4000197 +#define FID_RSI_REALM_CONFIG 0xC4000196 +#define FID_RSI_VERSION 0xC4000190 /** RSI Command Return codes See Section B4.4.1, RMM Specification, version A-bet0. diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c index 546df9a94cb86533b37fef7e42fdaf7b8563052d..01ecee3a6798c0e5cefd9fb4f48788d3063c94cd 100644 --- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c +++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c @@ -82,6 +82,199 @@ AddrIsGranuleAligned ( return TRUE; } +/** + Continue the operation to retrieve an attestation token. + + @param [out] TokenBuffer Pointer to a buffer to store the + retrieved attestation token. + @param [in,out] TokenSize On input size of the token buffer, + and on output size of the token + returned if operation is successful, + otherwise 0. + + @retval RETURN_SUCCESS Success. + @retval RETURN_INVALID_PARAMETER A parameter is invalid. + @retval RETURN_ABORTED The operation was aborted as the state + of the Realm or REC does not match the + state expected by the command. + @retval RETURN_NOT_READY The operation requested by the command + is not complete. + **/ +STATIC +RETURN_STATUS +EFIAPI +RsiAttestationTokenContinue ( + OUT UINT8 *CONST TokenBuffer, + OUT UINT64 *CONST TokenSize + ) +{ + RETURN_STATUS Status; + ARM_SMC_ARGS SmcCmd; + + ZeroMem (&SmcCmd, sizeof (SmcCmd)); + SmcCmd.Arg0 = FID_RSI_ATTESTATION_TOKEN_CONTINUE; + // Set the IPA of the Granule to which the token will be written. + SmcCmd.Arg1 = (UINTN)TokenBuffer; + + ArmCallSmc (&SmcCmd); + Status = RsiCmdStatusToEfiStatus (SmcCmd.Arg0); + if (!RETURN_ERROR (Status)) { + // Update the token size + *TokenSize = SmcCmd.Arg1; + } else { + // Clear the TokenBuffer on error. + ZeroMem (TokenBuffer, *TokenSize); + *TokenSize = 0; + } + + return Status; +} + +/** + Initialize the operation to retrieve an attestation token. + + @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. + + @retval RETURN_SUCCESS Success. + @retval RETURN_INVALID_PARAMETER A parameter is invalid. + **/ +STATIC +RETURN_STATUS +EFIAPI +RsiAttestationTokenInit ( + IN CONST UINT8 *CONST ChallengeData, + IN UINT64 ChallengeDataSizeBits, + IN UINT8 *CONST TokenBuffer + ) +{ + 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 + than 64 bytes, it should be zero-padded prior to calling + RSI_ATTESTATION_TOKEN_INIT. + + Therefore, zero out the SmcCmd memory before coping the ChallengeData + bits. + */ + 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; + Data8 = ChallengeData; + + // First copy whole bytes + Count = ChallengeDataSizeBits >> 3; + CopyMem (Buffer8, Data8, Count); + + // Now copy any remaining tail bits. + TailBits = ChallengeDataSizeBits & (8 - 1); + if (TailBits > 0) { + // Advance buffer pointers. + Buffer8 += Count; + Data8 += Count; + + // Copy tail byte. + *Buffer8 = *Data8; + + // Clear unused tail bits. + *Buffer8 &= ~(0xFF << TailBits); + } + + ArmCallSmc (&SmcCmd); + return RsiCmdStatusToEfiStatus (SmcCmd.Arg0); +} + +/** + Retrieve an attestation token from the RMM. + + @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 [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. + + @retval RETURN_SUCCESS Success. + @retval RETURN_INVALID_PARAMETER A parameter is invalid. + @retval RETURN_ABORTED The operation was aborted as the state + of the Realm or REC does not match the + state expected by the command. + @retval RETURN_NOT_READY The operation requested by the command + is not complete. +**/ +RETURN_STATUS +EFIAPI +RsiGetAttestationToken ( + IN CONST UINT8 *CONST ChallengeData, + IN UINT64 ChallengeDataSizeBits, + OUT UINT8 *CONST TokenBuffer, + IN OUT UINT64 *CONST TokenBufferSize + ) +{ + RETURN_STATUS Status; + + if ((TokenBuffer == NULL) || + (TokenBufferSize == NULL) || + (ChallengeData == NULL)) + { + 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; + } + + /* See A7.2.2 Attestation token generation, RMM Specification, version A-bet0 + IWTKDD - Arm recommends that the challenge should contain at least 32 bytes + of unique data. + */ + if (ChallengeDataSizeBits < MIN_CHALLENGE_DATA_SIZE_BITS) { + DEBUG ((DEBUG_WARN, "Minimum Challenge data size should be 32 bytes\n")); + } + + Status = RsiAttestationTokenInit ( + ChallengeData, + ChallengeDataSizeBits, + TokenBuffer + ); + if (RETURN_ERROR (Status)) { + ASSERT (0); + return Status; + } + + /* Loop until the token is ready or there is an error. + */ + do { + Status = RsiAttestationTokenContinue (TokenBuffer, TokenBufferSize); + } while (Status == RETURN_NOT_READY); + + return Status; +} + /** Returns the IPA state for the page pointed by the address. -- 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)' -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#103554): https://edk2.groups.io/g/devel/message/103554 Mute This Topic: https://groups.io/mt/98495957/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-