From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from alexa-out-sd-02.qualcomm.com (alexa-out-sd-02.qualcomm.com [199.106.114.39]) by mx.groups.io with SMTP id smtpd.web11.22489.1664970233975670597 for ; Wed, 05 Oct 2022 04:43:54 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@quicinc.com header.s=qcdkim header.b=DA1EorSG; spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: quicinc.com, ip: 199.106.114.39, mailfrom: quic_llindhol@quicinc.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1664970233; x=1696506233; h=date:from:to:cc:subject:message-id:references: mime-version:in-reply-to; bh=F3AiedJWhIXX8M5cuPW/61v0MZrtPvge/knw0aoFvZ8=; b=DA1EorSGeiwKglycNJ29PKrZtUkC77YNYIxDMoSV3XAhkrUYLdzu9wJm rUG+XBzACqT38wAHyDkDxV/qZhKBp/D54YxlSMiDgHB5rWOopxkQaRWLb jxtvgGwdTx0k33zZRGGoI2RBLPeQLThbiuEjrSgl83dO91PWSrteLM+hM U=; Received: from unknown (HELO ironmsg04-sd.qualcomm.com) ([10.53.140.144]) by alexa-out-sd-02.qualcomm.com with ESMTP; 05 Oct 2022 04:43:53 -0700 X-QCInternal: smtphost Received: from nasanex01c.na.qualcomm.com ([10.45.79.139]) by ironmsg04-sd.qualcomm.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Oct 2022 04:43:51 -0700 Received: from qc-i7.hemma.eciton.net (10.80.80.8) by nasanex01c.na.qualcomm.com (10.45.79.139) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.29; Wed, 5 Oct 2022 04:43:48 -0700 Date: Wed, 5 Oct 2022 12:43:46 +0100 From: "Leif Lindholm" To: , CC: Sami Mujawar , Ard Biesheuvel , Rebecca Cran , Michael D Kinney , Liming Gao , Jiewen Yao , Jian J Wang Subject: Re: [edk2-devel] [PATCH v7 09/19] ArmPkg/TrngLib: Add Arm Firmware TRNG library Message-ID: References: <20221003073503.2937059-1-Pierre.Gondois@arm.com> <20221003073503.2937059-10-Pierre.Gondois@arm.com> MIME-Version: 1.0 In-Reply-To: <20221003073503.2937059-10-Pierre.Gondois@arm.com> Return-Path: quic_llindhol@quicinc.com X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nasanex01c.na.qualcomm.com (10.45.79.139) Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline On Mon, Oct 03, 2022 at 09:34:53 +0200, PierreGondois wrote: > From: Sami Mujawar > > Bugzilla: 3668 (https://bugzilla.tianocore.org/show_bug.cgi?id=3668) > > The Arm True Random Number Generator Firmware, Interface 1.0, > Platform Design Document > (https://developer.arm.com/documentation/den0098/latest/) > defines an interface between an Operating System (OS) executing > at EL1 and Firmware (FW) exposing a conditioned entropy source > that is provided by a TRNG back end. > > The conditioned entropy, that is provided by the TRNG FW interface, > is commonly used to seed deterministic random number generators. > > This patch adds a TrngLib library that implements the Arm TRNG > firmware interface. > > Signed-off-by: Pierre Gondois Acked-by: Leif Lindholm / Leif > --- > ArmPkg/ArmPkg.dsc | 1 + > ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h | 50 +++ > ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c | 388 +++++++++++++++++++ > ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf | 29 ++ > 4 files changed, 468 insertions(+) > create mode 100644 ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h > create mode 100644 ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c > create mode 100644 ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf > > diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc > index 11b473974463..8726989bc73d 100644 > --- a/ArmPkg/ArmPkg.dsc > +++ b/ArmPkg/ArmPkg.dsc > @@ -131,6 +131,7 @@ [Components.common] > ArmPkg/Library/ArmGenericTimerPhyCounterLib/ArmGenericTimerPhyCounterLib.inf > ArmPkg/Library/ArmGenericTimerVirtCounterLib/ArmGenericTimerVirtCounterLib.inf > > + ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf > ArmPkg/Library/ArmHvcLib/ArmHvcLib.inf > ArmPkg/Library/ArmHvcLibNull/ArmHvcLibNull.inf > ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf > diff --git a/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h > new file mode 100644 > index 000000000000..150c89fe7969 > --- /dev/null > +++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngDefs.h > @@ -0,0 +1,50 @@ > +/** @file > + Arm Firmware TRNG definitions. > + > + Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Reference(s): > + - [1] Arm True Random Number Generator Firmware, Interface 1.0, > + Platform Design Document. > + (https://developer.arm.com/documentation/den0098/latest/) > + > + @par Glossary: > + - TRNG - True Random Number Generator > + - FID - Function ID > +**/ > + > +#ifndef ARM_FW_TRNG_DEFS_H_ > +#define ARM_FW_TRNG_DEFS_H_ > + > +#include > + > +// Firmware TRNG revision mask and shift > +#define TRNG_REV_MAJOR_MASK 0x7FFF > +#define TRNG_REV_MINOR_MASK 0xFFFF > +#define TRNG_REV_MAJOR_SHIFT 16 > + > +#if defined (MDE_CPU_ARM) > + > +/** FID to use on AArch32 platform to request entropy. > +*/ > +#define FID_TRNG_RND FID_TRNG_RND_AARCH32 > + > +/** Maximum bits of entropy supported on AArch32. > +*/ > +#define MAX_ENTROPY_BITS 96 > +#elif defined (MDE_CPU_AARCH64) > + > +/** FID to use on AArch64 platform to request entropy. > +*/ > +#define FID_TRNG_RND FID_TRNG_RND_AARCH64 > + > +/** Maximum bits of entropy supported on AArch64. > +*/ > +#define MAX_ENTROPY_BITS 192 > +#else > + #error "Firmware TRNG not supported. Unknown chipset." > +#endif > + > +#endif // ARM_FW_TRNG_DEFS_H_ > diff --git a/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c > new file mode 100644 > index 000000000000..df4c59ce7736 > --- /dev/null > +++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.c > @@ -0,0 +1,388 @@ > +/** @file > + Arm Firmware TRNG interface library. > + > + Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + @par Reference(s): > + - [1] NIST Special Publication 800-90B, Recommendation for the Entropy > + Sources Used for Random Bit Generation. > + (https://csrc.nist.gov/publications/detail/sp/800-90b/final) > + - [2] Arm True Random Number Generator Firmware, Interface 1.0, > + Platform Design Document. > + (https://developer.arm.com/documentation/den0098/latest/) > + > + @par Glossary: > + - TRNG - True Random Number Generator > + - FID - Function ID > +**/ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "ArmFwTrngDefs.h" > + > +/** Convert TRNG status codes to RETURN status codes. > + > + @param [in] TrngStatus TRNG status code. > + > + @retval RETURN_SUCCESS Success. > + @retval RETURN_UNSUPPORTED Function not implemented or > + negative return code. > + @retval RETURN_INVALID_PARAMETER A parameter is invalid. > + @retval RETURN_NOT_READY No Entropy available. > +**/ > +STATIC > +RETURN_STATUS > +TrngStatusToReturnStatus ( > + IN INT32 TrngStatus > + ) > +{ > + switch (TrngStatus) { > + case TRNG_STATUS_NOT_SUPPORTED: > + return RETURN_UNSUPPORTED; > + > + case TRNG_STATUS_INVALID_PARAMETER: > + return RETURN_INVALID_PARAMETER; > + > + case TRNG_STATUS_NO_ENTROPY: > + return RETURN_NOT_READY; > + > + case TRNG_STATUS_SUCCESS: > + return RETURN_SUCCESS; > + > + default: > + if (TrngStatus < 0) { > + return RETURN_UNSUPPORTED; > + } > + > + return RETURN_SUCCESS; > + } > +} > + > +/** Get the version of the TRNG backend. > + > + A TRNG may be implemented by the system firmware, in which case this > + function shall return the version of the TRNG backend. > + The implementation must return NOT_SUPPORTED if a Back end is not present. > + > + @param [out] MajorRevision Major revision. > + @param [out] MinorRevision Minor revision. > + > + @retval RETURN_SUCCESS The function completed successfully. > + @retval RETURN_INVALID_PARAMETER Invalid parameter. > + @retval RETURN_UNSUPPORTED Backend not present. > +**/ > +RETURN_STATUS > +EFIAPI > +GetTrngVersion ( > + OUT UINT16 *MajorRevision, > + OUT UINT16 *MinorRevision > + ) > +{ > + RETURN_STATUS Status; > + ARM_MONITOR_ARGS Parameters; > + INT32 Revision; > + > + if ((MajorRevision == NULL) || (MinorRevision == NULL)) { > + return RETURN_INVALID_PARAMETER; > + } > + > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + Parameters.Arg0 = FID_TRNG_VERSION; > + ArmMonitorCall (&Parameters); > + > + Revision = (INT32)Parameters.Arg0; > + Status = TrngStatusToReturnStatus (Revision); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + > + *MinorRevision = (Revision & TRNG_REV_MINOR_MASK); > + *MajorRevision = ((Revision >> TRNG_REV_MAJOR_SHIFT) & TRNG_REV_MAJOR_MASK); > + return RETURN_SUCCESS; > +} > + > +/** Get the features supported by the TRNG backend. > + > + The caller can determine if functions defined in the TRNG ABI are > + present in the ABI implementation. > + > + @param [in] FunctionId Function Id. > + @param [out] Capability Function specific capability if present. > + > + @retval RETURN_SUCCESS The function completed successfully. > + @retval RETURN_INVALID_PARAMETER Invalid parameter. > + @retval RETURN_UNSUPPORTED Function not implemented. > +**/ > +STATIC > +RETURN_STATUS > +EFIAPI > +GetTrngFeatures ( > + IN CONST UINT32 FunctionId, > + OUT UINT32 *Capability OPTIONAL > + ) > +{ > + ARM_MONITOR_ARGS Parameters; > + RETURN_STATUS Status; > + > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + Parameters.Arg0 = FID_TRNG_FEATURES; > + Parameters.Arg1 = FunctionId; > + ArmMonitorCall (&Parameters); > + > + Status = TrngStatusToReturnStatus (Parameters.Arg0); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + > + if (Capability != NULL) { > + *Capability = (UINT32)Parameters.Arg0; > + } > + > + return RETURN_SUCCESS; > +} > + > +/** Get the UUID of the TRNG backend. > + > + A TRNG may be implemented by the system firmware, in which case this > + function shall return the UUID of the TRNG backend. > + Returning the TRNG UUID is optional and if not implemented, RETURN_UNSUPPORTED > + shall be returned. > + > + Note: The caller must not rely on the returned UUID as a trustworthy TRNG > + Back end identity > + > + @param [out] Guid UUID of the TRNG backend. > + > + @retval RETURN_SUCCESS The function completed successfully. > + @retval RETURN_INVALID_PARAMETER Invalid parameter. > + @retval RETURN_UNSUPPORTED Function not implemented. > +**/ > +RETURN_STATUS > +EFIAPI > +GetTrngUuid ( > + OUT GUID *Guid > + ) > +{ > + ARM_MONITOR_ARGS Parameters; > + > + if (Guid == NULL) { > + return RETURN_INVALID_PARAMETER; > + } > + > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + Parameters.Arg0 = FID_TRNG_GET_UUID; > + ArmMonitorCall (&Parameters); > + > + // Only invalid value is TRNG_STATUS_NOT_SUPPORTED (-1). > + if ((INT32)Parameters.Arg0 == TRNG_STATUS_NOT_SUPPORTED) { > + return TrngStatusToReturnStatus ((INT32)Parameters.Arg0); > + } > + > + Guid->Data1 = (Parameters.Arg0 & MAX_UINT32); > + Guid->Data2 = (Parameters.Arg1 & MAX_UINT16); > + Guid->Data3 = ((Parameters.Arg1 >> 16) & MAX_UINT16); > + > + Guid->Data4[0] = (Parameters.Arg2 & MAX_UINT8); > + Guid->Data4[1] = ((Parameters.Arg2 >> 8) & MAX_UINT8); > + Guid->Data4[2] = ((Parameters.Arg2 >> 16) & MAX_UINT8); > + Guid->Data4[3] = ((Parameters.Arg2 >> 24) & MAX_UINT8); > + > + Guid->Data4[4] = (Parameters.Arg3 & MAX_UINT8); > + Guid->Data4[5] = ((Parameters.Arg3 >> 8) & MAX_UINT8); > + Guid->Data4[6] = ((Parameters.Arg3 >> 16) & MAX_UINT8); > + Guid->Data4[7] = ((Parameters.Arg3 >> 24) & MAX_UINT8); > + > + DEBUG ((DEBUG_INFO, "FW-TRNG: UUID %g\n", Guid)); > + > + return RETURN_SUCCESS; > +} > + > +/** Returns maximum number of entropy bits that can be returned in a single > + call. > + > + @return Returns the maximum number of Entropy bits that can be returned > + in a single call to GetTrngEntropy(). > +**/ > +UINTN > +EFIAPI > +GetTrngMaxSupportedEntropyBits ( > + VOID > + ) > +{ > + return MAX_ENTROPY_BITS; > +} > + > +/** Returns N bits of conditioned entropy. > + > + See [1] Section 2.3.1 GetEntropy: An Interface to the Entropy Source > + GetEntropy > + Input: > + bits_of_entropy: the requested amount of entropy > + Output: > + entropy_bitstring: The string that provides the requested entropy. > + status: A Boolean value that is TRUE if the request has been satisfied, > + and is FALSE otherwise. > + > + @param [in] EntropyBits Number of entropy bits requested. > + @param [in] BufferSize Size of the Buffer in bytes. > + @param [out] Buffer Buffer to return the entropy bits. > + > + @retval RETURN_SUCCESS The function completed successfully. > + @retval RETURN_INVALID_PARAMETER Invalid parameter. > + @retval RETURN_UNSUPPORTED Function not implemented. > + @retval RETURN_BAD_BUFFER_SIZE Buffer size is too small. > + @retval RETURN_NOT_READY No Entropy available. > +**/ > +RETURN_STATUS > +EFIAPI > +GetTrngEntropy ( > + IN UINTN EntropyBits, > + IN UINTN BufferSize, > + OUT UINT8 *Buffer > + ) > +{ > + RETURN_STATUS Status; > + ARM_MONITOR_ARGS Parameters; > + UINTN EntropyBytes; > + UINTN LastValidBits; > + UINTN BytesToClear; > + UINTN EntropyData[3]; > + > + if ((EntropyBits == 0) || > + (EntropyBits > MAX_ENTROPY_BITS) || > + (Buffer == NULL)) > + { > + return RETURN_INVALID_PARAMETER; > + } > + > + EntropyBytes = (EntropyBits + 7) >> 3; > + if (EntropyBytes > BufferSize) { > + return RETURN_BAD_BUFFER_SIZE; > + } > + > + ZeroMem (Buffer, BufferSize); > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + Parameters.Arg0 = FID_TRNG_RND; > + Parameters.Arg1 = EntropyBits; > + ArmMonitorCall (&Parameters); > + > + Status = TrngStatusToReturnStatus ((INT32)Parameters.Arg0); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + > + // The entropy data is returned in the Parameters.Arg<3..1> > + // With the lower order bytes in Parameters.Arg3 and the higher > + // order bytes being stored in Parameters.Arg1. > + EntropyData[0] = Parameters.Arg3; > + EntropyData[1] = Parameters.Arg2; > + EntropyData[2] = Parameters.Arg1; > + > + CopyMem (Buffer, EntropyData, EntropyBytes); > + > + // Mask off any unused top bytes, in accordance with specification. > + BytesToClear = BufferSize - EntropyBytes; > + if (BytesToClear != 0) { > + ZeroMem (&Buffer[EntropyBytes], BytesToClear); > + } > + > + // Clear the unused MSB bits of the last byte. > + LastValidBits = EntropyBits & 0x7; > + if (LastValidBits != 0) { > + Buffer[EntropyBytes - 1] &= (0xFF >> (8 - LastValidBits)); > + } > + > + return Status; > +} > + > +/** The constructor checks that the FW-TRNG interface is supported > + by the host firmware. > + > + It will ASSERT() if FW-TRNG is not supported. > + It will always return RETURN_SUCCESS. > + > + @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS. > +**/ > +RETURN_STATUS > +EFIAPI > +ArmFwTrngLibConstructor ( > + VOID > + ) > +{ > + ARM_MONITOR_ARGS Parameters; > + RETURN_STATUS Status; > + UINT16 MajorRev; > + UINT16 MinorRev; > + GUID Guid; > + > + ZeroMem (&Parameters, sizeof (Parameters)); > + > + Parameters.Arg0 = SMCCC_VERSION; > + ArmMonitorCall (&Parameters); > + Status = TrngStatusToReturnStatus ((INT32)Parameters.Arg0); > + if (RETURN_ERROR (Status)) { > + ASSERT_RETURN_ERROR (Status); > + goto ErrorHandler; > + } > + > + // Cf [1] s2.1.3 'Caller responsibilities', > + // SMCCC version must be greater or equal than 1.1 > + if ((INT32)Parameters.Arg0 < 0x10001) { > + ASSERT_RETURN_ERROR (RETURN_UNSUPPORTED); > + goto ErrorHandler; > + } > + > + Status = GetTrngVersion (&MajorRev, &MinorRev); > + if (RETURN_ERROR (Status)) { > + ASSERT_RETURN_ERROR (Status); > + goto ErrorHandler; > + } > + > + // Check that the required features are present. > + Status = GetTrngFeatures (FID_TRNG_RND, NULL); > + if (RETURN_ERROR (Status)) { > + ASSERT_RETURN_ERROR (Status); > + goto ErrorHandler; > + } > + > + // Check if TRNG UUID is supported and if so trace the GUID. > + Status = GetTrngFeatures (FID_TRNG_GET_UUID, NULL); > + if (RETURN_ERROR (Status)) { > + ASSERT_RETURN_ERROR (Status); > + goto ErrorHandler; > + } > + > + DEBUG_CODE_BEGIN (); > + > + Status = GetTrngUuid (&Guid); > + if (RETURN_ERROR (Status)) { > + ASSERT_RETURN_ERROR (Status); > + goto ErrorHandler; > + } > + > + DEBUG (( > + DEBUG_INFO, > + "FW-TRNG: Version %d.%d, GUID {%g}\n", > + MajorRev, > + MinorRev, > + Guid > + )); > + > + DEBUG_CODE_END (); > + > + return RETURN_SUCCESS; > + > +ErrorHandler: > + DEBUG ((DEBUG_ERROR, "ArmFwTrngLib could not be correctly initialized.\n")); > + return RETURN_SUCCESS; > +} > diff --git a/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf > new file mode 100644 > index 000000000000..ae3eb9bcfe7d > --- /dev/null > +++ b/ArmPkg/Library/ArmFwTrngLib/ArmFwTrngLib.inf > @@ -0,0 +1,29 @@ > +## @file > +# Arm Firmware TRNG interface library. > +# > +# Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION = 1.29 > + BASE_NAME = ArmFwTrngLib > + FILE_GUID = 10DE97C9-28E4-4C9B-A53E-8D7D1B0DD4E0 > + VERSION_STRING = 1.0 > + MODULE_TYPE = BASE > + LIBRARY_CLASS = TrngLib > + CONSTRUCTOR = ArmFwTrngLibConstructor > + > +[Sources] > + ArmFwTrngDefs.h > + ArmFwTrngLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + ArmMonitorLib > + BaseLib > + BaseMemoryLib > -- > 2.25.1 > > > > > >