public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Nickle Wang" <nicklew@nvidia.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	"igork@ami.com" <igork@ami.com>
Cc: Abner Chang <abner.chang@amd.com>, Nick Ramirez <nramirez@nvidia.com>
Subject: Re: [edk2-devel] [PATCH v3] RedfishPkg/RedfishPlatformCredentialIpmiLib: IPMI implementation
Date: Wed, 29 Mar 2023 01:26:14 +0000	[thread overview]
Message-ID: <MW4PR12MB703181C42198621C9A25A8C3D9899@MW4PR12MB7031.namprd12.prod.outlook.com> (raw)
In-Reply-To: <BLAPR10MB5185EA2C4E7AB79EEB047DE0A8889@BLAPR10MB5185.namprd10.prod.outlook.com>

> Igor: Since we get here when Status is success, then "Data" buffer will be allocated in that case.
> Should we free that buffer before return?

Thanks for catching this issue, Igor. 

Version 4 is under CI testing. I will send it out soon.

Regards,
Nickle

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Igor
> Kulchytskyy via groups.io
> Sent: Tuesday, March 28, 2023 10:48 PM
> To: Nickle Wang <nicklew@nvidia.com>; devel@edk2.groups.io
> Cc: Abner Chang <abner.chang@amd.com>; Nick Ramirez
> <nramirez@nvidia.com>
> Subject: Re: [edk2-devel] [PATCH v3]
> RedfishPkg/RedfishPlatformCredentialIpmiLib: IPMI implementation
> 
> External email: Use caution opening links or attachments
> 
> 
> Hi Nickle,
> It looks good except one small question I would like to raise.
> Please check my comment below.
> Thank you,
> Igor
> 
> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: Monday, March 27, 2023 9:42 PM
> To: devel@edk2.groups.io
> Cc: Abner Chang <abner.chang@amd.com>; Igor Kulchytskyy <igork@ami.com>;
> Nick Ramirez <nramirez@nvidia.com>
> Subject: [EXTERNAL] [PATCH v3] RedfishPkg/RedfishPlatformCredentialIpmiLib:
> IPMI implementation
> 
> 
> **CAUTION: The e-mail below is from an external source. Please exercise
> caution before opening attachments, clicking links, or following guidance.**
> 
> This library follows Redfish Host Interface specification and use IPMI command
> to get bootstrap account credential(NetFn 2Ch, Command 02h) from BMC.
> RedfishHostInterfaceDxe will use this credential for the following
> communication between BIOS and BMC.
> 
> Signed-off-by: Nickle Wang <nicklew@nvidia.com>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Igor Kulchytskyy <igork@ami.com>
> Cc: Nick Ramirez <nramirez@nvidia.com>
> ---
>  RedfishPkg/RedfishPkg.dec                     |   7 +
>  RedfishPkg/RedfishLibs.dsc.inc                |   1 +
>  RedfishPkg/RedfishPkg.dsc                     |   2 +
>  .../RedfishPlatformCredentialIpmiLib.inf      |  42 ++
>  .../RedfishPlatformCredentialIpmiLib.h        |  89 ++++
>  .../RedfishPlatformCredentialIpmiLib.c        | 457 ++++++++++++++++++
>  6 files changed, 598 insertions(+)
>  create mode 100644
> RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCredentia
> lIpmiLib.inf
>  create mode 100644
> RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCredentia
> lIpmiLib.h
>  create mode 100644
> RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCredentia
> lIpmiLib.c
> 
> diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec index
> 42d28d6dac..f171053aec 100644
> --- a/RedfishPkg/RedfishPkg.dec
> +++ b/RedfishPkg/RedfishPkg.dec
> @@ -81,6 +81,9 @@
>  [Guids]
>    gEfiRedfishPkgTokenSpaceGuid      = { 0x4fdbccb7, 0xe829, 0x4b4c, { 0x88,
> 0x87, 0xb2, 0x3f, 0xd7, 0x25, 0x4b, 0x85 }}
> 
> +  # Redfish variable guid
> +  gEfiRedfishVariableGuid           = { 0x85ef8dd3, 0xe606, 0x4b89, { 0x8b, 0xbd,
> 0x93, 0xbf, 0x5c, 0xbe, 0x1c, 0x18 } }
> +
>  [PcdsFixedAtBuild, PcdsPatchableInModule]
>    #
>    # This PCD is the UEFI device path which is used as the Redfish host interface.
> @@ -123,3 +126,7 @@
>    # specification for that.
>    #
>    gEfiRedfishPkgTokenSpaceGuid.PcdRedfishServiceUuid|L"00000000-0000-
> 0000-0000-000000000000"|VOID*|0x00001006
> +  #
> +  # This PCD indicates that if BMC bootstrap credential service will be disabled
> by BIOS or not.
> +  #
> +
> + gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDisableBootstrapCredentialServi
> + ce|FALSE|BOOLEAN|0x00001007
> diff --git a/RedfishPkg/RedfishLibs.dsc.inc b/RedfishPkg/RedfishLibs.dsc.inc
> index 84f52d4b27..110526738c 100644
> --- a/RedfishPkg/RedfishLibs.dsc.inc
> +++ b/RedfishPkg/RedfishLibs.dsc.inc
> @@ -19,5 +19,6 @@
>    JsonLib|RedfishPkg/Library/JsonLib/JsonLib.inf
>    RedfishLib|RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
>    RedfishDebugLib|RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf
> +
> + RedfishPlatformCredentialLib|RedfishPkg/Library/RedfishPlatformCredent
> + ialIpmiLib/RedfishPlatformCredentialIpmiLib.inf
>  !endif
> 
> diff --git a/RedfishPkg/RedfishPkg.dsc b/RedfishPkg/RedfishPkg.dsc index
> 223ab72c1d..5503e65de4 100644
> --- a/RedfishPkg/RedfishPkg.dsc
> +++ b/RedfishPkg/RedfishPkg.dsc
> @@ -4,6 +4,7 @@
>  # Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>  # (C)
> Copyright 2021 Hewlett-Packard Enterprise Development LP.
>  # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
> +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
>  #
>  #    SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -59,6 +60,7 @@
> 
> RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.
> inf
> 
> RedfishPkg/Library/PlatformHostInterfaceBmcUsbNicLib/PlatformHostInterface
> BmcUsbNicLib.inf
>    RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
> +
> + RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCre
> + dentialIpmiLib.inf
> 
> RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.i
> nf
>    RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
>    RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
> diff --git
> a/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCreden
> tialIpmiLib.inf
> b/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCreden
> tialIpmiLib.inf
> new file mode 100644
> index 0000000000..5c20ea22f8
> --- /dev/null
> +++ b/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatfor
> +++ mCredentialIpmiLib.inf
> @@ -0,0 +1,42 @@
> +## @file
> +#  INF file for RedfishPlatformCredentialIpmiLib.
> +#
> +#  Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001000b
> +  BASE_NAME                      = RedfishPlatformCredentialIpmiLib
> +  FILE_GUID                      = 9C45D622-4C66-417F-814C-F76246D97233
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = RedfishPlatformCredentialIpmiLib
> +
> +[Sources]
> +  RedfishPlatformCredentialIpmiLib.c
> +  RedfishPlatformCredentialIpmiLib.h
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  RedfishPkg/RedfishPkg.dec
> +
> +[LibraryClasses]
> +  UefiLib
> +  DebugLib
> +  IpmiLib
> +  MemoryAllocationLib
> +  BaseMemoryLib
> +  UefiRuntimeServicesTableLib
> +
> +[Pcd]
> +
> +gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDisableBootstrapCredentialServic
> +e
> +
> +[Guids]
> +  gEfiRedfishVariableGuid
> +
> +[Depex]
> +  TRUE
> diff --git
> a/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCreden
> tialIpmiLib.h
> b/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCreden
> tialIpmiLib.h
> new file mode 100644
> index 0000000000..898ee88844
> --- /dev/null
> +++ b/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatfor
> +++ mCredentialIpmiLib.h
> @@ -0,0 +1,89 @@
> +/** @file
> +  Header file for RedfishPlatformCredentialIpmiLib.
> +
> +  Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef REDFISH_PLATFORM_CREDENTIAL_IPMI_LIB_H_
> +#define REDFISH_PLATFORM_CREDENTIAL_IPMI_LIB_H_
> +
> +#include <Uefi.h>
> +#include <IndustryStandard/Ipmi.h>
> +#include <IndustryStandard/RedfishHostInterfaceIpmi.h>
> +
> +#include <Protocol/EdkIIRedfishCredential.h>
> +
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/IpmiLib.h>
> +#include <Library/MemoryAllocationLib.h> #include
> +<Library/RedfishCredentialLib.h> #include <Library/UefiLib.h> #include
> +<Library/UefiRuntimeServicesTableLib.h>
> +
> +#define CREDENTIAL_VARIABLE_NAME  L"Partstooblaitnederc"
> +
> +///
> +/// The bootstrap credential keeping in UEFI variable /// typedef
> +struct {
> +  CHAR8    Username[USERNAME_MAX_SIZE];
> +  CHAR8    Password[PASSWORD_MAX_SIZE];
> +} BOOTSTRAP_CREDENTIALS_VARIABLE;
> +
> +/**
> +  Function to retrieve temporary user credentials for the UEFI redfish
> +client. This function can
> +  also disable bootstrap credential service in BMC.
> +
> +  @param[in]     DisableBootstrapControl TRUE - Tell the BMC to disable the
> bootstrap credential
> +                                                service to ensure no one else gains credentials
> +                                         FALSE  Allow the bootstrap credential service to
> continue
> +  @param[in,out] BootstrapUsername       A pointer to a Ascii encoded string
> for the credential username
> +                                         When DisableBootstrapControl is TRUE, this pointer can
> be NULL
> +  @param[in]     BootstrapUsernameSize   The size of BootstrapUsername
> including NULL terminator in bytes.
> +                                         Per specification, the size is USERNAME_MAX_SIZE.
> +  @param[in,out] BootstrapPassword       A pointer to a Ascii encoded string for
> the credential password
> +                                         When DisableBootstrapControl is TRUE, this pointer can
> be NULL
> +  @param[in]     BootstrapPasswordSize   The size of BootstrapPassword
> including NULL terminator in bytes.
> +                                         Per specification, the size is PASSWORD_MAX_SIZE.
> +
> +  @retval  EFI_SUCCESS                Credentials were successfully fetched and
> returned. When DisableBootstrapControl
> +                                      is set to TRUE, the bootstrap credential service is disabled
> successfully.
> +  @retval  EFI_INVALID_PARAMETER      BootstrapUsername or
> BootstrapPassword is NULL when DisableBootstrapControl
> +                                      is set to FALSE. BootstrapUsernameSize or
> BootstrapPasswordSize is incorrect when
> +                                      DisableBootstrapControl is set to FALSE.
> +  @retval  EFI_DEVICE_ERROR           An IPMI failure occurred
> +**/
> +EFI_STATUS
> +GetBootstrapAccountCredentials (
> +  IN     BOOLEAN DisableBootstrapControl,
> +  IN OUT CHAR8 *BootstrapUsername, OPTIONAL
> +  IN     UINTN   BootstrapUsernameSize,
> +  IN OUT CHAR8   *BootstrapPassword, OPTIONAL
> +  IN     UINTN   BootstrapPasswordSize
> +  );
> +
> +/**
> +  Function to save temporary user credentials into boot time variable.
> +When DeleteVariable is True,
> +  this function delete boot time variable.
> +
> +  @param[in] BootstrapUsername       A pointer to a Ascii encoded string for the
> credential username.
> +  @param[in] BootstrapPassword       A pointer to a Ascii encoded string for the
> credential password.
> +  @param[in] DeleteVariable          True to remove boot time variable. False
> otherwise.
> +
> +  @retval  EFI_SUCCESS                Credentials were successfully saved.
> +  @retval  EFI_INVALID_PARAMETER      BootstrapUsername or
> BootstrapPassword is NULL
> +  @retval  Others                     Error occurs
> +**/
> +EFI_STATUS
> +SetBootstrapAccountCredentialsToVariable (
> +  IN CHAR8 *BootstrapUsername, OPTIONAL
> +  IN CHAR8  *BootstrapPassword, OPTIONAL
> +  IN BOOLEAN DeleteVariable
> +  );
> +
> +#endif
> diff --git
> a/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCreden
> tialIpmiLib.c
> b/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatformCreden
> tialIpmiLib.c
> new file mode 100644
> index 0000000000..7fccf1795d
> --- /dev/null
> +++ b/RedfishPkg/Library/RedfishPlatformCredentialIpmiLib/RedfishPlatfor
> +++ mCredentialIpmiLib.c
> @@ -0,0 +1,457 @@
> +/** @file
> +  Implementation of getting bootstrap credential via IPMI.
> +
> +  Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Specification Reference:
> +  - Redfish Host Interface Specification
> +
> +(https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.
> +dmtf.org%2Fsites%2Fdefault%2Ffiles%2Fstandards%2Fdocuments%2FDSP0270
> _1.
> +3.0.pdf&data=05%7C01%7Cigork%40ami.com%7C161990c6849e4c32d2fa08d
> b2f2dae
> +cc%7C27e97857e15f486cb58e86c2b3040f93%7C1%7C1%7C638155645493575
> 932%7CUn
> +known%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik
> 1haWw
> +iLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=uFc4G56EXmukiU9OxabYXBk
> wmJnxr8C5J
> +6gcBXZYnoI%3D&reserved=0)
> +**/
> +
> +#include "RedfishPlatformCredentialIpmiLib.h"
> +
> +//
> +// Global flag of controlling credential service // BOOLEAN
> +mRedfishServiceStopped = FALSE;
> +
> +/**
> +  Notify the Redfish service provide to stop provide configuration service to this
> platform.
> +
> +  This function should be called when the platform is about to leave the safe
> environment.
> +  It will notify the Redfish service provider to abort all login
> + session, and prohibit  further login with original auth info.
> + GetAuthInfo() will return EFI_UNSUPPORTED once this  function is returned.
> +
> +  @param[in]   This                Pointer to
> EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
> +  @param[in]   ServiceStopType     Reason of stopping Redfish service.
> +
> +  @retval EFI_SUCCESS              Service has been stoped successfully.
> +  @retval EFI_INVALID_PARAMETER    This is NULL.
> +  @retval Others                   Some error happened.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibStopRedfishService (
> +  IN     EDKII_REDFISH_CREDENTIAL_PROTOCOL           *This,
> +  IN     EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE  ServiceStopType
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if ((ServiceStopType <= ServiceStopTypeNone) || (ServiceStopType >=
> ServiceStopTypeMax)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Only stop credential service after leaving BIOS  //  if
> + (ServiceStopType != ServiceStopTypeExitBootService) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Raise flag first
> +  //
> +  mRedfishServiceStopped = TRUE;
> +
> +  //
> +  // Delete cached variable
> +  //
> +  Status = SetBootstrapAccountCredentialsToVariable (NULL, NULL, TRUE);
> + if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: fail to remove bootstrap credential:
> + %r\n", __FUNCTION__, Status));  }
> +
> +  DEBUG ((DEBUG_INFO, "%a: bootstrap credential service stopped\n",
> + __FUNCTION__));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Notification of Exit Boot Service.
> +
> +  @param[in]  This    Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
> +**/
> +VOID
> +EFIAPI
> +LibCredentialExitBootServicesNotify (
> +  IN  EDKII_REDFISH_CREDENTIAL_PROTOCOL  *This
> +  )
> +{
> +  //
> +  // Stop the credential support when system is about to enter OS.
> +  //
> +  LibStopRedfishService (This, ServiceStopTypeExitBootService); }
> +
> +/**
> +  Notification of End of DXe.
> +
> +  @param[in]  This    Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
> +**/
> +VOID
> +EFIAPI
> +LibCredentialEndOfDxeNotify (
> +  IN  EDKII_REDFISH_CREDENTIAL_PROTOCOL  *This
> +  )
> +{
> +  //
> +  // Do nothing now.
> +  // We can stop credential support when system reach end-of-dxe for security
> reason.
> +  //
> +}
> +
> +/**
> +  Function to retrieve temporary user credentials for the UEFI redfish
> +client. This function can
> +  also disable bootstrap credential service in BMC.
> +
> +  @param[in]     DisableBootstrapControl TRUE - Tell the BMC to disable the
> bootstrap credential
> +                                                service to ensure no one else gains credentials
> +                                         FALSE  Allow the bootstrap credential service to
> continue
> +  @param[in,out] BootstrapUsername       A pointer to a Ascii encoded string
> for the credential username
> +                                         When DisableBootstrapControl is TRUE, this pointer can
> be NULL
> +  @param[in]     BootstrapUsernameSize   The size of BootstrapUsername
> including NULL terminator in bytes.
> +                                         Per specification, the size is USERNAME_MAX_SIZE.
> +  @param[in,out] BootstrapPassword       A pointer to a Ascii encoded string for
> the credential password
> +                                         When DisableBootstrapControl is TRUE, this pointer can
> be NULL
> +  @param[in]     BootstrapPasswordSize   The size of BootstrapPassword
> including NULL terminator in bytes.
> +                                         Per specification, the size is PASSWORD_MAX_SIZE.
> +
> +  @retval  EFI_SUCCESS                Credentials were successfully fetched and
> returned. When DisableBootstrapControl
> +                                      is set to TRUE, the bootstrap credential service is disabled
> successfully.
> +  @retval  EFI_INVALID_PARAMETER      BootstrapUsername or
> BootstrapPassword is NULL when DisableBootstrapControl
> +                                      is set to FALSE. BootstrapUsernameSize or
> BootstrapPasswordSize is incorrect when
> +                                      DisableBootstrapControl is set to FALSE.
> +  @retval  EFI_DEVICE_ERROR           An IPMI failure occurred
> +**/
> +EFI_STATUS
> +GetBootstrapAccountCredentials (
> +  IN     BOOLEAN DisableBootstrapControl,
> +  IN OUT CHAR8 *BootstrapUsername, OPTIONAL
> +  IN     UINTN   BootstrapUsernameSize,
> +  IN OUT CHAR8   *BootstrapPassword, OPTIONAL
> +  IN     UINTN   BootstrapPasswordSize
> +  )
> +{
> +  EFI_STATUS                                  Status;
> +  IPMI_BOOTSTRAP_CREDENTIALS_COMMAND_DATA     CommandData;
> +  IPMI_BOOTSTRAP_CREDENTIALS_RESULT_RESPONSE  ResponseData;
> +  UINT32                                      ResponseSize;
> +
> +  //
> +  // NULL buffer check
> +  //
> +  if (!DisableBootstrapControl && ((BootstrapUsername == NULL) ||
> (BootstrapPassword == NULL))) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((BootstrapUsernameSize != USERNAME_MAX_SIZE) ||
> (BootstrapPasswordSize != PASSWORD_MAX_SIZE)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DEBUG ((DEBUG_VERBOSE, "%a: Disable bootstrap control: 0x%x\n",
> + __FUNCTION__, DisableBootstrapControl));
> +
> +  //
> +  // IPMI callout to NetFn 2C, command 02
> +  //    Request data:
> +  //      Byte 1: REDFISH_IPMI_GROUP_EXTENSION
> +  //      Byte 2: DisableBootstrapControl
> +  //
> +  CommandData.GroupExtensionId        = REDFISH_IPMI_GROUP_EXTENSION;
> +  CommandData.DisableBootstrapControl = (DisableBootstrapControl ?
> + REDFISH_IPMI_BOOTSTRAP_CREDENTIAL_DISABLE :
> + REDFISH_IPMI_BOOTSTRAP_CREDENTIAL_ENABLE);
> +
> +  ResponseSize = sizeof (ResponseData);
> +
> +  //
> +  //    Response data:
> +  //      Byte 1    : Completion code
> +  //      Byte 2    : REDFISH_IPMI_GROUP_EXTENSION
> +  //      Byte 3-18 : Username
> +  //      Byte 19-34: Password
> +  //
> +  Status = IpmiSubmitCommand (
> +             IPMI_NETFN_GROUP_EXT,
> +             REDFISH_IPMI_GET_BOOTSTRAP_CREDENTIALS_CMD,
> +             (UINT8 *)&CommandData,
> +             sizeof (CommandData),
> +             (UINT8 *)&ResponseData,
> +             &ResponseSize
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: IPMI transaction failure. Returning\n",
> __FUNCTION__));
> +    return Status;
> +  } else {
> +    if (ResponseData.CompletionCode != IPMI_COMP_CODE_NORMAL) {
> +      if (ResponseData.CompletionCode ==
> REDFISH_IPMI_COMP_CODE_BOOTSTRAP_CREDENTIAL_DISABLED) {
> +        DEBUG ((DEBUG_ERROR, "%a: bootstrap credential support was
> disabled\n", __FUNCTION__));
> +        return EFI_ACCESS_DENIED;
> +      }
> +
> +      DEBUG ((DEBUG_ERROR, "%a: Completion code = 0x%x. Returning\n",
> __FUNCTION__, ResponseData.CompletionCode));
> +      return EFI_PROTOCOL_ERROR;
> +    } else if (ResponseData.GroupExtensionId !=
> REDFISH_IPMI_GROUP_EXTENSION) {
> +      DEBUG ((DEBUG_ERROR, "%a: Group Extension Response = 0x%x.
> Returning\n", __FUNCTION__, ResponseData.GroupExtensionId));
> +      return EFI_DEVICE_ERROR;
> +    } else {
> +      if (BootstrapUsername != NULL) {
> +        CopyMem (BootstrapUsername, ResponseData.Username,
> USERNAME_MAX_LENGTH);
> +        //
> +        // Manually append null-terminator in case 16 characters username
> returned.
> +        //
> +        BootstrapUsername[USERNAME_MAX_LENGTH] = '\0';
> +      }
> +
> +      if (BootstrapPassword != NULL) {
> +        CopyMem (BootstrapPassword, ResponseData.Password,
> PASSWORD_MAX_LENGTH);
> +        //
> +        // Manually append null-terminator in case 16 characters password
> returned.
> +        //
> +        BootstrapPassword[PASSWORD_MAX_LENGTH] = '\0';
> +      }
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "%a: get bootstrap credential via IPMI: %r\n",
> + __FUNCTION__, Status));
> +
> +  return Status;
> +}
> +
> +/**
> +  Function to retrieve temporary user credentials from cached boot time
> variable.
> +
> +  @param[in,out] BootstrapUsername     A pointer to a Ascii encoded string for
> the credential username.
> +  @param[in]     BootstrapUsernameSize The size of BootstrapUsername
> including NULL terminator in bytes.
> +                                       Per specification, the size is USERNAME_MAX_SIZE.
> +  @param[in,out] BootstrapPassword     A pointer to a Ascii encoded string for
> the credential password.
> +  @param[in]     BootstrapPasswordSize The size of BootstrapPassword
> including NULL terminator in bytes.
> +                                       Per specification, the size is PASSWORD_MAX_SIZE.
> +
> +  @retval  EFI_SUCCESS                Credentials were successfully fetched and
> returned.
> +  @retval  EFI_INVALID_PARAMETER      BootstrapUsername or
> BootstrapPassword is NULL.
> +                                      BootstrapUsernameSize or BootstrapPasswordSize is
> incorrect.
> +  @retval  EFI_NOT_FOUND              No variable found for account and
> credentials.
> +**/
> +EFI_STATUS
> +GetBootstrapAccountCredentialsFromVariable (
> +  IN OUT CHAR8  *BootstrapUsername,
> +  IN     UINTN  BootstrapUsernameSize,
> +  IN OUT CHAR8  *BootstrapPassword,
> +  IN     UINTN  BootstrapPasswordSize
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  BOOTSTRAP_CREDENTIALS_VARIABLE  *CredentialVariable;
> +  VOID                            *Data;
> +  UINTN                           DataSize;
> +
> +  if ((BootstrapUsername == NULL) || (BootstrapPassword == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((BootstrapUsernameSize != USERNAME_MAX_SIZE) ||
> (BootstrapPasswordSize != PASSWORD_MAX_SIZE)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  DataSize = 0;
> +  Status   = GetVariable2 (
> +               CREDENTIAL_VARIABLE_NAME,
> +               &gEfiRedfishVariableGuid,
> +               (VOID *)&Data,
> +               &DataSize
> +               );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  if (DataSize != sizeof (BOOTSTRAP_CREDENTIALS_VARIABLE)) {
> +    DEBUG ((DEBUG_ERROR, "%a: data corruption. returned size: %d !=
> + structure size: %d\n", __FUNCTION__, DataSize, sizeof
> + (BOOTSTRAP_CREDENTIALS_VARIABLE)));
> Igor: Since we get here when Status is success, then "Data" buffer will be
> allocated in that case.
> Should we free that buffer before return?
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  CredentialVariable = (BOOTSTRAP_CREDENTIALS_VARIABLE *)Data;
> +
> +  AsciiStrCpyS (BootstrapUsername, USERNAME_MAX_SIZE,
> + CredentialVariable->Username);  AsciiStrCpyS (BootstrapPassword,
> + PASSWORD_MAX_SIZE, CredentialVariable->Password);
> +
> +  ZeroMem (CredentialVariable->Username, USERNAME_MAX_SIZE);  ZeroMem
> + (CredentialVariable->Password, PASSWORD_MAX_SIZE);
> +
> +  FreePool (Data);
> +
> +  DEBUG ((DEBUG_INFO, "%a: get bootstrap credential from variable\n",
> + __FUNCTION__));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Function to save temporary user credentials into boot time variable.
> +When DeleteVariable is True,
> +  this function delete boot time variable.
> +
> +  @param[in] BootstrapUsername       A pointer to a Ascii encoded string for the
> credential username.
> +  @param[in] BootstrapPassword       A pointer to a Ascii encoded string for the
> credential password.
> +  @param[in] DeleteVariable          True to remove boot time variable. False
> otherwise.
> +
> +  @retval  EFI_SUCCESS                Credentials were successfully saved.
> +  @retval  EFI_INVALID_PARAMETER      BootstrapUsername or
> BootstrapPassword is NULL
> +  @retval  Others                     Error occurs
> +**/
> +EFI_STATUS
> +SetBootstrapAccountCredentialsToVariable (
> +  IN CHAR8 *BootstrapUsername, OPTIONAL
> +  IN CHAR8  *BootstrapPassword, OPTIONAL
> +  IN BOOLEAN DeleteVariable
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  BOOTSTRAP_CREDENTIALS_VARIABLE  CredentialVariable;
> +  VOID                            *Data;
> +
> +  if (!DeleteVariable && ((BootstrapUsername == NULL) ||
> (BootstrapUsername[0] == '\0'))) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!DeleteVariable && ((BootstrapPassword == NULL) ||
> (BootstrapPassword[0] == '\0'))) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Delete variable
> +  //
> +  Status = GetVariable2 (
> +             CREDENTIAL_VARIABLE_NAME,
> +             &gEfiRedfishVariableGuid,
> +             (VOID *)&Data,
> +             NULL
> +             );
> +  if (!EFI_ERROR (Status)) {
> +    FreePool (Data);
> +    gRT->SetVariable (
> +           CREDENTIAL_VARIABLE_NAME,
> +           &gEfiRedfishVariableGuid,
> +           EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +           0,
> +           NULL
> +           );
> +  }
> +
> +  //
> +  // This is request to delete credentials. We are done.
> +  //
> +  if (DeleteVariable) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  ZeroMem (CredentialVariable.Username, USERNAME_MAX_SIZE);  ZeroMem
> + (CredentialVariable.Password, PASSWORD_MAX_SIZE);
> +
> +  AsciiStrCpyS (CredentialVariable.Username, USERNAME_MAX_SIZE,
> + BootstrapUsername);  AsciiStrCpyS (CredentialVariable.Password,
> + PASSWORD_MAX_SIZE, BootstrapPassword);
> +
> +  Status = gRT->SetVariable (
> +                  CREDENTIAL_VARIABLE_NAME,
> +                  &gEfiRedfishVariableGuid,
> +                  EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +                  sizeof (BOOTSTRAP_CREDENTIALS_VARIABLE),
> +                  (VOID *)&CredentialVariable
> +                  );
> +
> +  ZeroMem (CredentialVariable.Username, USERNAME_MAX_SIZE);  ZeroMem
> + (CredentialVariable.Password, PASSWORD_MAX_SIZE);
> +
> +  return Status;
> +}
> +
> +/**
> +  Retrieve platform's Redfish authentication information.
> +
> +  This functions returns the Redfish authentication method together
> + with the user Id and  password.
> +  - For AuthMethodNone, the UserId and Password could be used for HTTP
> header authentication
> +    as defined by RFC7235.
> +  - For AuthMethodRedfishSession, the UserId and Password could be used for
> Redfish
> +    session login as defined by  Redfish API specification (DSP0266).
> +
> +  Callers are responsible for and freeing the returned string storage.
> +
> +  @param[in]   This                Pointer to
> EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
> +  @param[out]  AuthMethod          Type of Redfish authentication method.
> +  @param[out]  UserId              The pointer to store the returned UserId string.
> +  @param[out]  Password            The pointer to store the returned Password
> string.
> +
> +  @retval EFI_SUCCESS              Get the authentication information successfully.
> +  @retval EFI_ACCESS_DENIED        SecureBoot is disabled after EndOfDxe.
> +  @retval EFI_INVALID_PARAMETER    This or AuthMethod or UserId or
> Password is NULL.
> +  @retval EFI_OUT_OF_RESOURCES     There are not enough memory resources.
> +  @retval EFI_UNSUPPORTED          Unsupported authentication method is
> found.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LibCredentialGetAuthInfo (
> +  IN  EDKII_REDFISH_CREDENTIAL_PROTOCOL  *This,
> +  OUT EDKII_REDFISH_AUTH_METHOD          *AuthMethod,
> +  OUT CHAR8                              **UserId,
> +  OUT CHAR8                              **Password
> +  )
> +{
> +  EFI_STATUS  Status;
> +  BOOLEAN     DisableCredentialService;
> +
> +  if ((AuthMethod == NULL) || (UserId == NULL) || (Password == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *UserId                  = NULL;
> +  *Password                = NULL;
> +  DisableCredentialService = PcdGetBool
> + (PcdRedfishDisableBootstrapCredentialService);
> +
> +  if (mRedfishServiceStopped) {
> +    DEBUG ((DEBUG_ERROR, "%a: credential service is stopped due to security
> reason\n", __FUNCTION__));
> +    return EFI_ACCESS_DENIED;
> +  }
> +
> +  *AuthMethod = AuthMethodHttpBasic;
> +
> +  *UserId = AllocateZeroPool (sizeof (CHAR8) * USERNAME_MAX_SIZE);  if
> + (*UserId == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  *Password = AllocateZeroPool (sizeof (CHAR8) * PASSWORD_MAX_SIZE);
> + if (*Password == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Get bootstrap credential from variable first  //  Status =
> + GetBootstrapAccountCredentialsFromVariable (*UserId,
> + USERNAME_MAX_SIZE, *Password, PASSWORD_MAX_SIZE);  if (!EFI_ERROR
> (Status)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // Make a IPMI query
> +  //
> +  Status = GetBootstrapAccountCredentials (DisableCredentialService,
> + *UserId, USERNAME_MAX_SIZE, *Password, PASSWORD_MAX_SIZE);  if
> (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: fail to get bootstrap credential: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  if (DisableCredentialService) {
> +    DEBUG ((DEBUG_INFO, "%a: credential bootstrapping control
> + disabled\n", __FUNCTION__));  }
> +
> +  Status = SetBootstrapAccountCredentialsToVariable (*UserId,
> + *Password, FALSE);  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: fail to cache bootstrap credential:
> + %r\n", __FUNCTION__, Status));  }
> +
> +  return EFI_SUCCESS;
> +}
> --
> 2.40.0.windows.1
> 
> -The information contained in this message may be confidential and proprietary
> to American Megatrends (AMI). This communication is intended to be read only
> by the individual or entity to whom it is addressed or by their designee. If the
> reader of this message is not the intended recipient, you are on notice that any
> distribution of this message, in any form, is strictly prohibited. Please promptly
> notify the sender by reply e-mail or by telephone at 770-246-8600, and then
> delete or destroy all copies of the transmission.
> 
> 
> 
> 


      reply	other threads:[~2023-03-29  1:26 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-28  1:42 [PATCH v3] RedfishPkg/RedfishPlatformCredentialIpmiLib: IPMI implementation Nickle Wang
2023-03-28 14:48 ` Igor Kulchytskyy
2023-03-29  1:26   ` Nickle Wang [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=MW4PR12MB703181C42198621C9A25A8C3D9899@MW4PR12MB7031.namprd12.prod.outlook.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