347 lines
10 KiB
C
347 lines
10 KiB
C
/** @file
|
|
|
|
This module provides password relative functions.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2020, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "InternalUtilityLib.h"
|
|
#include "String.h"
|
|
#include <KernelSetupConfig.h>
|
|
|
|
#include <Protocol/SysPasswordService.h>
|
|
#include <Protocol/H2ODialog.h>
|
|
|
|
/**
|
|
This function uses to check password.
|
|
|
|
@retval TRUE Insyde password is in locked state.
|
|
@retval FALSE Insyde password is in unloced state.
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsPasswordExist (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_SYS_PASSWORD_SERVICE_PROTOCOL *SysPasswordService;
|
|
EFI_STATUS Status;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiSysPasswordServiceProtocolGuid,
|
|
NULL,
|
|
(VOID **) &SysPasswordService
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Status = SysPasswordService->GetStatus (SysPasswordService, SystemSupervisor);
|
|
|
|
return (BOOLEAN) (Status == EFI_SUCCESS ? TRUE : FALSE);
|
|
}
|
|
|
|
/**
|
|
Check if need to do system password check.
|
|
|
|
@retval TRUE Need to do system password check.
|
|
@retval FALSE No need to do system password check.
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
NeedSysPasswordCheck (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SYS_PASSWORD_SETUP_INFO_DATA SetupInfoBuffer;
|
|
EFI_SYS_PASSWORD_SERVICE_PROTOCOL *SysPasswordService;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiSysPasswordServiceProtocolGuid, NULL, (VOID **) &SysPasswordService);
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Status = SysPasswordService->GetSysPswdSetupInfoData (SysPasswordService, &SetupInfoBuffer);
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return SetupInfoBuffer.HaveSysPasswordCheck;
|
|
}
|
|
|
|
/**
|
|
Clear flag to indicate that no need to do system password check.
|
|
|
|
@retval EFI_SUCCESS Success to disable system password check.
|
|
@retval Other Failed to find system password protocol instance or get/set setup info data.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisableSysPasswordCheck (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SYS_PASSWORD_SERVICE_PROTOCOL *SysPasswordService;
|
|
SYS_PASSWORD_SETUP_INFO_DATA SetupInfoBuffer;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiSysPasswordServiceProtocolGuid, NULL, (VOID **) &SysPasswordService);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = SysPasswordService->GetSysPswdSetupInfoData (SysPasswordService, &SetupInfoBuffer);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
SetupInfoBuffer.HaveSysPasswordCheck = FALSE;
|
|
Status = SysPasswordService->SetSysPswdSetupInfoData(
|
|
SysPasswordService,
|
|
&SetupInfoBuffer,
|
|
(UINT32) SYS_PASSWORD_CHECK_BIT
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Change password state from unlocked state to locked state.
|
|
|
|
@retval EFI_SUCCESS Change password state to locked state.
|
|
@retval EFI_UNSUPPORTED The password doesn't saved in variable storage.
|
|
@retval EFI_ALREADY_STARTED The password state is already in locked state.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LockPasswordState (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_SYS_PASSWORD_SERVICE_PROTOCOL *SysPasswordService;
|
|
EFI_STATUS Status;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiSysPasswordServiceProtocolGuid,
|
|
NULL,
|
|
(VOID **) &SysPasswordService
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = SysPasswordService->LockPassword (SysPasswordService);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
/**
|
|
Change the Insyde password state to unlocked state.
|
|
|
|
@param[in] Password The null-terminated string that is the input password.
|
|
@param[in] PasswordLength The password length in bytes of PasswordPtr.
|
|
|
|
@retval EFI_SUCCESS Change password state to unlocked state.
|
|
@retval EFI_UNSUPPORTED The password doesn't saved in variable storage.
|
|
@retval EFI_ALREADY_STARTED The password state is already in unlocked state.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
UnlockPasswordState (
|
|
IN CHAR16 *Password,
|
|
IN UINTN PasswordLength
|
|
)
|
|
{
|
|
EFI_SYS_PASSWORD_SERVICE_PROTOCOL *SysPasswordService;
|
|
EFI_STATUS Status;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiSysPasswordServiceProtocolGuid,
|
|
NULL,
|
|
(VOID **) &SysPasswordService
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = SysPasswordService->UnlockPassword (SysPasswordService, Password, PasswordLength);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get the length of system password support.
|
|
|
|
@param[in] SysPasswordService system password service protocol
|
|
|
|
@retval The length of system password support
|
|
**/
|
|
UINTN
|
|
SysPasswordMaxNum (
|
|
EFI_SYS_PASSWORD_SERVICE_PROTOCOL *SysPasswordService OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SYS_PASSWORD_SETUP_INFO_DATA SetupInfoBuffer;
|
|
|
|
|
|
if (SysPasswordService == NULL) {
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiSysPasswordServiceProtocolGuid,
|
|
NULL,
|
|
(VOID **) &SysPasswordService
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
Status = SysPasswordService->GetSysPswdSetupInfoData(
|
|
SysPasswordService,
|
|
&SetupInfoBuffer
|
|
);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
return 0;
|
|
}
|
|
|
|
return SetupInfoBuffer.MaxSysPasswordLength;
|
|
}
|
|
|
|
/**
|
|
Check the input password is valid or invalid.
|
|
|
|
If input password is valid, it will unlock password state and return EFI_SUCCESS.
|
|
If input password is invalid and exceed retry times, it will show error message and do a dead loop.
|
|
If system doesn't have password, return EFI_SUCCESS directly.
|
|
|
|
@retval EFI_SUCCESS Check input password is valid and change password state to unloced.
|
|
@retval EFI_NOT_FOUND gH2ODialogProtocolGuid protocol doesn't exist
|
|
@retval EFI_ALREADY_STARTED Input password is invalid.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CheckPassword (
|
|
VOID
|
|
)
|
|
{
|
|
H2O_DIALOG_PROTOCOL *H2ODialog;
|
|
EFI_SYS_PASSWORD_SERVICE_PROTOCOL *SysPasswordService;
|
|
EFI_STATUS Status;
|
|
CHAR16 *CheckPasswordStr;
|
|
CHAR16 *InvalidPasswordStr;
|
|
CHAR16 *Password;
|
|
CHAR16 *ErrorStatusMsg;
|
|
CHAR16 *ThreeIncorrectMsg;
|
|
CHAR16 *RebootMsg;
|
|
EFI_INPUT_KEY Key;
|
|
UINTN TryPasswordTimes;
|
|
UINTN SysPasswordMaximumNumber;
|
|
|
|
if (!IsPasswordExist ()) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiSysPasswordServiceProtocolGuid,
|
|
NULL,
|
|
(VOID **) &SysPasswordService
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (&gH2ODialogProtocolGuid, NULL, (VOID **) &H2ODialog);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
CheckPasswordStr = GenericUtilityLibGetStringById (STRING_TOKEN (STR_CHECK_PASSWORD_STRING));
|
|
InvalidPasswordStr = GenericUtilityLibGetStringById (STRING_TOKEN (STR_INVALID_PASSWORD));
|
|
gST->ConOut->ClearScreen (gST->ConOut);
|
|
TryPasswordTimes = 0;
|
|
|
|
SysPasswordMaximumNumber = SysPasswordMaxNum (SysPasswordService);
|
|
|
|
Password = AllocatePool ((SysPasswordMaximumNumber + 1) * sizeof (CHAR16));
|
|
if (Password == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
do {
|
|
ZeroMem (Password, (SysPasswordMaximumNumber + 1) * sizeof (CHAR16));
|
|
H2ODialog->PasswordDialog (
|
|
0,
|
|
FALSE,
|
|
(UINT32) (SysPasswordMaximumNumber + 1),
|
|
Password,
|
|
&Key,
|
|
CheckPasswordStr
|
|
);
|
|
Status = SysPasswordService->CheckPassword (
|
|
SysPasswordService,
|
|
Password,
|
|
(SysPasswordMaximumNumber + 1) * sizeof(CHAR16),
|
|
SystemSupervisor
|
|
);
|
|
if (Status == EFI_SUCCESS) {
|
|
SysPasswordService->UnlockPassword (
|
|
SysPasswordService,
|
|
Password,
|
|
(SysPasswordMaximumNumber + 1) * sizeof(CHAR16)
|
|
);
|
|
}
|
|
TryPasswordTimes++;
|
|
if (Status != EFI_SUCCESS && TryPasswordTimes < 3) {
|
|
H2ODialog->ConfirmDialog (
|
|
2,
|
|
FALSE,
|
|
40,
|
|
NULL,
|
|
&Key,
|
|
InvalidPasswordStr
|
|
);
|
|
}
|
|
} while (Status != EFI_SUCCESS && TryPasswordTimes < 3);
|
|
|
|
//
|
|
// Display check password failed and do a dead loop in this function, if user inputs password is invalid.
|
|
//
|
|
if (Status != EFI_SUCCESS) {
|
|
ErrorStatusMsg = GenericUtilityLibGetStringById (STRING_TOKEN (STR_ERROR_STATUS));
|
|
ThreeIncorrectMsg = GenericUtilityLibGetStringById (STRING_TOKEN (STR_THREE_ERRORS));
|
|
RebootMsg = GenericUtilityLibGetStringById (STRING_TOKEN (STR_RESTART_MSG));
|
|
H2ODialog->CreateMsgPopUp (
|
|
40,
|
|
3,
|
|
ErrorStatusMsg,
|
|
ThreeIncorrectMsg,
|
|
RebootMsg
|
|
);
|
|
|
|
FreePool (CheckPasswordStr);
|
|
FreePool (Password);
|
|
CpuDeadLoop ();
|
|
}
|
|
FreePool (InvalidPasswordStr);
|
|
FreePool (CheckPasswordStr);
|
|
FreePool (Password);
|
|
return Status;
|
|
}
|
|
|