# PasswordCheck

## Function Table

| Address | Name | Description |
|---------|------|-------------|
|  | **StringLengthInChars** |  |
|  | **ModuleEntryPoint** |  |
|  | **DateTimeToEpochSeconds** |  |
|  | **GetMinPasswordLength** |  |
|  | **CheckTimeLockout** |  |
|  | **CheckPasswordHistory** |  |
|  | **SavePasswordWithHistory** |  |
|  | **GetRemainingLockoutDays** |  |
|  | **GetRemainingLockoutMinutes** |  |
|  | **GetRemainingVerifyCount** |  |
|  | **ManageVerifyCounters** |  |
|  | **DebugPrint** |  |
|  | **DebugAssertPrint** |  |
|  | **ReadUnaligned64** |  |
|  | **CompareGuid** |  |
|  | **CheckCmosReset** |  |
| Global | **variables (from .data section at 0x1B60-0x1C40)** |  |
| EFI_HANDLE | **gImageHandle       = NULL;  // 0x1BF8** |  |
| 0x1BE8 | **EFI_BOOT_SERVICES    *gBS                = NULL;  // 0x1BF0** |  |
| 0x1C00 | **EFI_BOOT_SERVICES    *BootServices_0     = NULL;  // 0x1C18** |  |
| 0x1C28 | **EFI_RUNTIME_SERVICES *RuntimeServices_0  = NULL;  // 0x1C20** |  |
| 0x1C10 | **VOID                 *gDebugProtocol     = NULL;  // 0x1C08** |  |
| Protocol | **interface installed by this module (off_1BA0 / unk_1B90)** |  |
| The | **actual interface data lives at 0x1BA0 in the binary** |  |
| GUID | **used for password-related UEFI variables (unk_1B80)** |  |
| GUID | **for the protocol installed by this module (unk_1B90)** |  |
| GUID | **for HOB list lookup (unk_1B70)** |  |
| GUID | **for debug protocol lookup (unk_1B60)** |  |
| Days | **in each month (index 1-12)** |  |
| static | **const UINT8 gDaysInMonth[13] = {** |  |
| Forward | **declarations of internal helpers** |  |
| Module | **entry point** |  |
| Store | **global service table pointers** |  |
| gImageHandle | **= (UINT64)ImageHandle;** |  |
| Locate | **the HOB list** |  |
| Cache | **local copies of the service tables** |  |
| ProtocolHandle | **= 0;** |  |
| Install | **the password check protocol** |  |
| Status | **= BootServices->InstallProtocolInterface(** |  |
| Check | **if the target year is a leap year** |  |
| if | **(((Year & 3) == 0) &&** |  |
| Accumulate | **seconds per full year from 2000 up to (but not including) Year** |  |
| for | **(Y = BASE_YEAR; Y < Year; Y++) {** |  |
| 31536000 | **} else {** |  |
| 31622400 | **}** |  |
| Accumulate | **seconds per completed month** |  |
| for | **(M = 1; M < Month; M++) {** |  |
| Add | **the day/hour/minute/second within the current month.** |  |
| The | **formula matches the decompiled binary exactly:** |  |
| TotalSeconds | **+= (UINT64)(SECONDS_PER_HOUR * Hour - SECONDS_PER_HOUR)** |  |
| Password | **policy enforcement functions** |  |
| GUID | **components for the "Setup" variable (from decompilation)** |  |
| 1270213540 | **AttributeGuid[2] = 0x3E414D61;   // 1044374945** |  |
| return | **-((UINT64)(StringLengthInChars(Password) < MinLength) & PASSWORD_STATUS_NOT_FOUND_RET);** |  |
| Read | **the Setup variable to get max lockout days** |  |
| DataSize814 | **= VAR_DATA_SETUP_SIZE;** |  |
| Determine | **max lockout days based on password type** |  |
| MaxLockoutDays | **= (PasswordType == PASSWORD_TYPE_PAP)** |  |
| Read | **the timestamp variable** |  |
| DataSize8 | **= VAR_DATA_TIMESTAMP_SIZE;** |  |
| Get | **current time via GetTime (RuntimeServices+24 = offset 0x18 = GetTime)** |  |
| Status | **= gRT->GetTime(&CurrentTime, NULL);** |  |
| If | **(now - saved) / 3600 < MaxLockoutDays, we are still in lockout** |  |
| return | **-((UINT64)((EpochNow - EpochSaved) / SECONDS_PER_HOUR < MaxLockoutDays)** |  |
| Read | **the Setup variable to get the history count** |  |
| Read | **the password history variable** |  |
| DataSize200 | **= VAR_DATA_HISTORY_SIZE;** |  |
| Walk | **each 40-byte history entry, comparing the password** |  |
| Compare | **the password string against this entry** |  |
| PwScan | **= Password;** |  |
| match | **found** |  |
| If | **we broke early (EntryIndex < HistoryCount), password was reused.** |  |
| return | **-((UINT64)(EntryIndex < HistoryCount) & PASSWORD_STATUS_NOT_FOUND_RET);** |  |
| Empty | **password => delete the timestamp variable** |  |
| if | **(*Password == 0) {** |  |
| Read | **existing history** |  |
| HistoryVarName | **= L"PapSaveHistory";** |  |
| The | **decompiled code shifts history entries by 40 bytes (one entry)** |  |
| so | **that the oldest entry is discarded and slot 0 is free.** |  |
| if | **((INT64)Status >= 0) {** |  |
| Calculate | **password length (in characters)** |  |
| Zero | **out the first entry slot, then copy the password into it** |  |
| Write | **updated history back (SET_VARIABLE, Attributes=3 = NV+BS)** |  |
| Result | **= RuntimeServices_0->RT->SetVariable(** |  |
| Get | **current time and save as timestamp** |  |
| EFI_TIME | **SaveTime;** |  |
| Read | **save timestamp** |  |
| Read | **Setup variable for max lockout days** |  |
| Get | **current time** |  |
| Read | **HaltStamp** |  |
| Read | **Setup variable** |  |
| Get | **lockout minutes from offset 0x1A in Setup variable** |  |
| MaxLockoutMinutes | **= *(UINT16 *)&SetupBuf[0x1A];** |  |
| Cooldown | **has elapsed** | delete HaltStamp |
| Read | **current verify count** |  |
| Get | **max verify count** |  |
| Reset | **mode: delete the verify counter variable** |  |
| VerifyCntVarName | **= L"PapVerifyCnt";** |  |
| Increment | **mode: read Setup variable** |  |
| Read | **current count** |  |
| Check | **against max** |  |
| Under | **limit: save incremented count** |  |
| Exceeded | **limit: record HaltStamp** |  |
| Always | **reset counter to 0 after processing** |  |
| Internal | **helper / library functions** |  |
| probe | **before calling LocateProtocol.  BootServices+0x18 = AllocatePages** |  |
| result | **is <= 0x10 pages, it proceeds with LocateProtocol.** |  |
| The | **exact pattern in the binary (from survey: no imports) suggests this** |  |
| is | **a debug/production-build discriminator baked into the assert library.** |  |
| The | **probe: gBS->AllocatePages(AllocateMaxAddress, EfiBootServicesData, 1, &Address)** |  |
| then | **gBS->FreePages(Address).  If the returned page count <= 0x10 (64KB)** |  |
| the | **system is in a "debug" configuration and the protocol is located.** |  |
| This | **pattern matches the EDK2 DebugLib initialization sequence.** |  |
| Preserve | **bit 7 of CMOS address port, then select register 0x4B** |  |
| CurrentAddr | **= IoRead8(CMOS_ADDRESS_PORT);** |  |
| If | **value > 3 and non-zero, the system may be in a specific reset state.** |  |
| If | **value == 0, read from a memory-mapped IO register to determine state.** |  |
| if | **((UINT8)RegValue > 3) {** |  |
| Valid | **range check** |  |
| if | **((UINT8)(RegValue - 1) > 0xFD) {** |  |
| Additional | **static data referenced by the module** |  |
| The | **following data items reside in the binary at the specified offsets:** |  |

---
*Generated by HR650X BIOS Decompilation Project*