Newer
Older
AMI-Aptio-BIOS-Reversed / CryptoPPI / CryptoPPI.c
@Ajax Dong Ajax Dong 2 days ago 16 KB Init
/**
 * @file CryptoPPI.c
 * @brief AMI Crypto PEIM - Cryptographic services for PEI phase
 *
 *Source: AmiCryptoPkg/CryptoProtocols/CryptoPPI
 *Module: CryptoPPI.efi (PE32+, IA32)
 *Size: 0x11a20 bytes
 *MD5: d76c39fb5d3d3f3266494a6e32d0f470
 *
 *This PEIM provides a PPI (PEI-to-PEI Interface) for cryptographic
 *operations during the PEI (Pre-EFI Initialization) phase.
 *
 *Services provided:
 * - RSA key generation, signing, verification, encryption/decryption
 * - RSA-PSS and RSA-OAEP padding schemes
 * - X.509 certificate parsing
 * - PKCS7 signature verification (SignedData, SignerInfo, CRL sets)
 * - ASN.1 DER encoding/decoding
 * - SHA-1 hashing
 * - Big number arithmetic with Montgomery reduction
 * - Cryptographic random number generation
 * - Key derivation
 */

#include <PiPei.h>
#include <Ppi/AmiCrypto.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>

/*===========================================================================
 *AMI Crypto PPI GUID
 *===========================================================================*/
#define AMI_CRYPTO_PPI_GUID \
 { 0x868A0FE7, 0xF17E, 0x3190, \
 { 0x83, 0xC2, 0xF9, 0xF4, 0xBB, 0xF0, 0x61, 0x63 } }

/*===========================================================================
 *Memory Manager (Mmgr) - Internal heap management routines
 *
 *The memory manager provides a simple heap allocator for PEI phase.
 *It manages descriptor-based allocation with write-back tracking.
 *===========================================================================*/

typedef struct {
 UINT32 HeapStart; /* +0x00: Start of heap */
 UINT32 HeapSize; /* +0x04: Total heap size */
 UINT32 DescStart; /* +0x08: Start of descriptors */
 UINT32 HeapUsed; /* +0x0C: Current heap usage pointer */
 UINT32 DescriptorFree; /* +0x10: Free descriptor chain start */
} MMGR_HEAP_STATE;

/*Initialize or reset the memory manager heap */
CHAR8 MmgrInitHeap(VOID);

/*Allocate pointer from memory manager */
INTN MmgrAllocPointer(UINTN Size);

/*Free a pointer allocated by memory manager */
VOID MmgrFreePointer(INTN Pointer);

/*Reallocate memory */
INTN MmgrRealloc(INTN OldPtr, UINTN NewSize);

/*Allocate zeroed memory (wrapper around MmgrAllocPointer) */
INTN MmgrAllocZeroed(UINTN Size);

/*Get allocation base address */
INTN MmgrGetAllocBase(INTN Pointer);

/*Allocate a descriptor block */
INTN MmgrAllocDescriptor(UINTN Size, UINTN Count);

/*Allocate pages */
INTN MmgrAllocPages(UINTN Start, UINTN Size, UINTN Count);

/*Check if address is within allocated range */
BOOLEAN MmgrIsAllocated(INTN Addr);

/*Mark memory as allocated */
VOID MmgrMarkAllocated(INTN Addr);

/*Get allocation size */
UINTN MmgrGetAllocSize(INTN Pointer);

/*Write-back memory changes to ensure consistency */
INTN MmgrWriteBack(UINTN Flags);

/*Check if memory manager is initialized */
BOOLEAN MmgrIsInitialized(VOID);

/*Check if debug is enabled for given level */
BOOLEAN MmgrIsDebugEnabled(UINTN DebugLevel);

/*Debug check for memory manager state */
INTN MmgrDebugCheck(INTN a1, UINT16 **a2);

/*Zero memory region */
VOID *MmgrZeroMemory(UINTN Address, UINTN Size, UINTN Flags);

/*===========================================================================
 *Big Number (BN) Arithmetic
 *===========================================================================*/

/*Allocate a big number */
INTN BnAlloc(INTN Value, INTN Size);

/*Free a big number */
UINTN BnFree(DWORD *Bn);

/*Check if big number equals 1 */
INTN BnIsOne(INTN *Bn);

/*Montgomery square */
INTN BnMontSqr(DWORD *Result, INTN Modulus, INTN *Param, INTN Bn);

/*Normalize big number */
INTN BnNormalize(INTN Dst, INTN Src, INTN Bn);

/*Compare two big numbers (-1, 0, 1) */
INTN BnCompare(INTN *A, INTN *B);

/*Set big number to an integer value */
INTN BnSetInt(INTN Bn, UINTN Value);

/*Check if bit is set in big number */
INTN BnCheckBit(DWORD *Result, DWORD *Bn);

/*Get RSA public exponent from a key */
INTN BnRsaPublicExp(INTN *Exp);

/*===========================================================================
 *Big Number Internal Operations (Intn)
 *===========================================================================*/

/*Montgomery reduction */
INTN IntnMontReduce(INTN A, INTN B, INTN N, INTN M);

/*Multiply and add */
DWORD *IntnMulAdd(UINT8 *A, INTN Size);

/*Multiply two big numbers */
INTN IntnMultiply(UINT8 *A, UINTN Size, UINT8 *Buf, INTN BufSize);

/*Check if all components are zero */
VOID *IntnIsZero(INTN Count, UINT8 **Values, INTN Sizes, INTN OutBuf);

/*Subtract two big numbers */
INTN IntnSubtract(INTN Count, INTN *Values, INTN Sizes, INTN OutBuf);

/*Check if a specific bit is set */
INTN IntnIsBitSet(INTN Count, CHAR8 *Values, INTN *Sizes, UINT8 *OutBuf);

/*Shift left operation (for modulus calculation) */
INTN IntnShiftLeft(UINTN A, INTN Count, UINT8 *Data, UINTN Length);

/*Modulo operation */
INTN IntnMod(UINT8 *Data, INTN Count, UINT8 *Modulus, INTN ModSize,
 UINTN BitLen, UINTN KeyBits);

/*===========================================================================
 *SHA-1 Hashing
 *===========================================================================*/

#define SHA1_DIGEST_SIZE 20
#define SHA1_BLOCK_SIZE 64

/*SHA-1 context structure */
typedef struct {
 UINT32 State[5]; /*A, B, C, D, E */
 UINT32 Count[2]; /*Bit count */
 UINT8 Buffer[64]; /*Data buffer */
} SHA1_CTX;

/*Initialize SHA-1 context */
VOID Sha1Init(INTN Ctx, INTN InitData);

/*Update SHA-1 with data */
VOID Sha1Update(INTN Ctx, UINTN Data, UINTN Length);

/*Process a single 64-byte block */
DWORD *Sha1BlockTransform(DWORD *State);

/*Pad message to block boundary */
VOID *Sha1PadMessage(INTN BlockCount, CHAR8 *Blocks, INTN *Counts, INTN Buf);

/*Finalize SHA-1 hash (debug wrapper) */
INTN Sha1Final(INTN a1, INTN a2, UINTN Buf, UINTN *BufSize,
 DWORD *Ctx, INTN Flags);

/*Compute SHA-1 result */
UINTN Sha1Result(INTN Ctx);

/*Simple SHA-1 result computation */
INTN Sha1ResultSimple(INTN Ctx);

/*===========================================================================
 *RSA Operations
 *===========================================================================*/

/*RSA key pair generation */
INTN RsaGenerateKeyPair(INTN *N, INTN *E, INTN *D);

/*RSA signing */
INTN RsaSign(DWORD *Message, INTN MsgLen, INTN *Signature);

/*RSA encryption */
INTN RsaEncrypt(INTN Bn, INTN KeySize);

/*RSA decryption with private key */
INTN RsaDecryptWithPrivKey(INTN Ciphertext, INTN CipherLen,
 INTN *Plaintext, INTN *PlainLen,
 INTN *N, INTN *E, INTN *D);

/*RSA key generation */
INTN RsaGenerateKey(INTN KeySize, INTN *N, INTN *E, INTN *D);

/*RSA key pair sanity check */
INTN RsaCheckKeyPair(INTN *N, INTN *E, INTN *D);

/*RSA-PSS signing */
VOID RsaPssSign(INTN *Input, INTN InputLen);

/*RSA-PSS verification */
DWORD *RsaPssVerify(INTN Input, INTN InputLen);

/*RSA-OAEP padding */
INTN RsaOaepPad(INTN *Input, INTN *InputLen, INTN Output);

/*RSA-OAEP encryption */
INTN RsaOaepEncrypt(INTN *A, INTN *B, INTN *C);

/*RSA PKCS1 v1.5 verify */
INTN RsaPkcs1Verify(INTN *Signature, UINTN *SigSize, INTN *PublicKey);

/*===========================================================================
 *ASN.1 / X.509 / PKCS7 Parsing
 *===========================================================================*/

/*Parse a TLV (Tag-Length-Value) ASN.1 element */
INTN Asn1ParseTLV(INTN Data, INTN Length, INTN *Tag, INTN *Value,
 INTN *ValueLen);

/*Parse an AlgorithmIdentifier from ASN.1 data */
INTN Asn1ParseAlgorithmIdentifier(INTN Data, INTN Length);

/*DER encode data */
INTN Asn1DerEncode(INTN *Input, INTN *Output, INTN *OutputLen);

/*Parse X.509 certificate */
DWORD *X509ParseCertificate(UINT8 *CertData, INTN CertLen);

/*Parse PKCS7 SignedData */
INTN Pkcs7ParseSignedData(INTN *Data, INTN *DataLen, INTN *Out, INTN MaxLen);

/*Parse PKCS7 SignerInfo */
INTN Pkcs7ParseSignerInfo(INTN *Data, INTN *DataLen, INTN *Out, UINTN Flags);

/*Parse PKCS7 CRL Set */
INTN Pkcs7ParseCrlSet(INTN *A, INTN *B, INTN *C);

/*===========================================================================
 *Random Number Generation & Key Derivation
 *===========================================================================*/

/*Seed the RNG */
INTN AmiCryptoRngSeed(DWORD *State, DWORD *SeedData, INTN *OutLen);

/*Generate random bytes */
INTN AmiCryptoRngGenerate(DWORD *State, INTN Count, INTN Params,
 INTN *OutLen);

/*Derive key from shared secret */
INTN AmiCryptoDeriveKey(DWORD *KeyMaterial, INTN KeyLen,
 UINT8 **DerivedKey, INTN *DerivedLen);

/*Initialize internal crypto state */
INTN AmiCryptoInternalInit(VOID);

/*Initialize hash context for crypto operations */
INTN CryptoInitHashContext(INTN Ctx, INTN Type, INTN Data, INTN DataLen);

/*===========================================================================
 *Debug Output Functions
 *===========================================================================*/

/*Debug printf */
INTN CryptoDebugPrintf(INTN Level, CHAR8 *Format, ...);

/*Debug print hex dump */
INTN CryptoDebugPrintHex(INTN Level, CHAR8 *Label, UINTN Addr, UINTN Len);

/*Write a debug string to output */
INTN CryptoDebugWriteString(VOID);

/*VPrintf for debug */
INTN CryptoDebugVPrintf(INTN Ctx, CHAR8 *Format, ...);

/*Write a single character to debug output */
INTN CryptoDebugWriteChar(INTN Ctx);

/*Format an integer for debug output */
INTN CryptoDebugFormatInt(INTN Ctx, INTN Value, UINTN *OutLen);

/*Check if debug is enabled */
INTN CryptoDebugIsEnabled(INTN Level, INTN Ctx);

/*Get current debug level */
INTN CryptoDebugGetLevel(INTN Ctx, DWORD *State, INTN Level, INTN Flags);

/*Set debug level */
UINTN CryptoDebugSetLevel(INTN Level);

/*===========================================================================
 *PEI Services
 *===========================================================================*/

/*PEI entry point */
EFI_STATUS EFIAPI PeiCryptLibEntryPoint(
 IN EFI_PEI_FILE_HANDLE FileHandle,
 IN CONST EFI_PEI_SERVICES **PeiServices
 );

/*PEIM constructor */
INTN PeiCryptLibConstructor(DWORD *Context);

/*PEIM destructor */
INTN PeiCryptLibDestructor(INTN a1, INTN a2, INTN a3, INTN a4,
 INTN a5, INTN a6);

/*Driver initialization - called from entry point */
INTN PeiCryptLibDriverInit(EFI_HANDLE ImageHandle,
 EFI_SYSTEM_TABLE *SystemTable);

/*Initialize protocols/heap */
INTN PeiCryptLibInitProtocols(EFI_SYSTEM_TABLE *SystemTable);

/*Register a cryptographic service */
INTN PeiCryptLibRegisterCrypto(CHAR8 *Name, INTN NameLen,
 INTN Data, INTN DataLen);

/*Install a PPI for cryptographic operations */
UINTN PeiCryptLibInstallPpi(INTN a1, INTN a2, INTN a3, INTN a4,
 INTN a5, CHAR8 Flags);

/*Register a PPI with key material */
UINTN PeiCryptLibRegisterPpi(INTN a1, UINT8 *Key, INTN KeyLen,
 UINT8 *Cert, INTN CertLen, INTN N,
 DWORD *Params1, DWORD *Params2);

/*Unregister a cryptographic PPI */
UINTN PeiCryptLibUnregisterPpi(INTN a1, UINT8 *Key, INTN KeyLen,
 INTN Flags);

/*PPI notification handler */
INTN PeiCryptLibPpiHandler(INTN a1, INTN a2, INTN Context);

/*Notify consumers of available crypto PPI */
INTN PeiCryptLibNotifyPpi(INTN a1, INTN a2, DWORD *PpiTable);

/*Get current boot mode */
INTN PeiGetBootMode(VOID);

/*PEI Stall */
INTN PeiStall(CHAR8 *Message);

/*Get PPI pointer from PEI services */
INTN PeiGetPpiPointer(VOID);

/*PEI debug print */
INTN PeiDebugPrint(UINTN ErrorLevel, CHAR8 *Format, ...);

/*===========================================================================
 *Memory Support Functions
 *===========================================================================*/

/*Copy memory with overlap handling */
INTN CopyMemWrapper(INTN Dst, INTN Src, INTN Len);

/*Copy memory (wchar aware) */
INTN CopyMemOrWchar(INTN Dst, INTN Src, INTN Len);

/*Set memory to value */
VOID SetMem(INTN Buf, INTN Len, UINT8 Val);

/*Set 32-bit values */
VOID SetMem32(INTN Buf, INTN Len, UINT32 Val);

/*Set 16-bit values */
VOID SetMem16(INTN Buf, INTN Len, UINT16 Val);

/*Zero memory (standard) */
VOID ZeroMem(INTN Buf, INTN Len);

/*===========================================================================
 *Function Index
 *===========================================================================
 *
 *0x260 CopyMemOrWchar - Copy memory with overlap handling
 *0x2a0 SetMem - Set memory region
 *0x2c0 SetMem32 - Set 32-bit aligned memory
 *0x300 ZeroMem - Zero memory region
 *0x320 SetMem16 - Set 16-bit aligned memory
 *0x340 PeiCryptLibEntryPoint - PEIM entry point
 *0x3bb PeiCryptLibConstructor - PEIM constructor (allocates context)
 *0x491 PeiCryptLibDestructor - PEIM destructor
 *0x53c PeiCryptLibInstallPpi - Install crypto PPI
 *0x644 PeiCryptLibRegisterPpi - Register crypto PPI with key
 *0x739 PeiCryptLibUnregisterPpi - Unregister crypto PPI
 *0x790 PeiCryptLibNotifyPpi - Notify crypto PPI availability
 *0x7f1 PeiCryptLibPpiHandler - Handle PPI callbacks
 *0x99b PeiGetBootMode - Get current boot mode
 *0xa6b PeiGetPpiPointer - Get PPI pointer from services
 *0xa9c PeiDebugPrint - PEI phase debug print
 *0xac6 PeiStall - PEI stall function
 *0xae4 MmgrIsInitialized - Check mmgr state
 *0xae7 MmgrIsDebugEnabled - Check debug enable
 *0xaf0 MmgrDebugCheck - Debug state check
 *0xb27 MmgrWriteBack - Flush memory changes
 *0xcff MmgrAllocDescriptor - Alloc descriptor block
 *0xe5b MmgrZeroMemory - Zero memory via mmgr
 *0xe9f MmgrAllocPages - Alloc pages
 *0xfaf MmgrIsAllocated - Check allocation
 *0xfb7 MmgrMarkAllocated - Mark memory allocated
 *0xfea MmgrGetAllocSize - Get allocation size
 *0x108b AmiCryptoInternalInit - Init internal crypto state
 *0x1e9e PeiCryptLibInitProtocols - Init protocols & heap
 *0x1f53 PeiCryptLibDriverInit - Driver init entry
 *0x1fc0 PeiCryptLibRegisterCrypto - Register crypto service
 *0x207a RsaDecryptWithPrivKey - RSA decrypt with private key
 *0x21df RsaGenerateKey - RSA key generation
 *0x246a RsaCheckKeyPair - Validate RSA key pair
 *0x2726 IntnMontReduce - Montgomery reduction
 *0x29c3 CryptoInitHashContext - Init hash context
 *0x2a8d IntnMulAdd - Big num multiply-add
 *0x4571 AmiCryptoRngSeed - Seed RNG
 *0x458a AmiCryptoRngGenerate - Generate random bytes
 *0x4a23 AmiCryptoDeriveKey - Key derivation
 *0x500a Sha1Init - SHA-1 init
 *0x50fe Sha1BlockTransform - SHA-1 block transform
 *0x5145 Sha1Update - SHA-1 update
 *0x51fc Sha1PadMessage - SHA-1 message padding
 *0x525a Sha1Final - SHA-1 finalize (debug)
 *0x5330 Sha1Result - SHA-1 result
 *0x5354 Sha1ResultSimple - SHA-1 result (simple)
 *0x6a0c IntnMultiply - Big num multiply
 *0x6895 IntnIsZero - Big num zero check
 *0x69b6 IntnSubtract - Big num subtract
 *0x6b13 IntnMod - Big num modulo
 *0x6da0 IntnShiftLeft - Big num shift left
 *0x744a IntnIsBitSet - Big num bit test
 *0x7578 MmgrInitHeap - Init/reset heap
 *0x76c0 MmgrFreePointer - Free pointer
 *0x771b MmgrAllocPointer - Alloc pointer
 *0x7800 MmgrGetAllocBase - Get alloc base
 *0x7850 MmgrAllocZeroed - Alloc zeroed
 *0x7855 MmgrRealloc - Realloc memory
 *0x78d0 X509ParseCertificate - Parse X.509 cert
 *0x9372 CryptoDebugPrintHex - Debug hex dump
 *0x94f0 CryptoDebugPrintf - Debug printf
 *0x9575 CryptoDebugIsEnabled - Debug level check
 *0x957a CryptoDebugSetLevel - Set debug level
 *0x9591 CryptoDebugGetLevel - Get debug level
 *0x95f5 CryptoDebugFormatInt - Format debug int
 *0x965b CryptoDebugWriteChar - Write debug char
 *0x9679 CryptoDebugWriteString - Write debug string
 *0x96a2 CryptoDebugVPrintf - Debug vprintf
 *0x9c3a BnNormalize - BN normalize
 *0x9cb3 BnFree - BN free
 *0x9ce8 BnAlloc - BN alloc
 *0x9d17 BnSetInt - BN set int
 *0x9cd PeiGetPeiServices - Get PEI services pointer
 *0x9d3c BnCompare - BN compare
 *0x9ded BnIsOne - BN is one
 *0x9e13 BnMontMul - BN Montgomery multiplication
 *0xa29b BnMontSqr - BN Montgomery square
 *0xa40d BnExpMod - BN modular exponentiation
 *0xa94d BnRsaPrivateExp - BN RSA private exponent op
 *0xa9aa BnRsaPublicExp - BN RSA public exponent
 *0xaa04 BnCheckBit - BN check bit
 *0xaac9 RsaEncrypt - RSA encrypt
 *0xabaa RsaSign - RSA sign
 *0xacb5 RsaGenerateKeyPair - RSA key pair gen
 *0xadaf RsaParsePrivateKey - Parse RSA private key
 *0xaf82 RsaPkcs1Verify - RSA PKCS1 verify
 *0xb0bc RsaOaepEncrypt - RSA OAEP encrypt
 *0xb1b6 RsaPssSign - RSA PSS sign
 *0xb207 RsaPssVerify - RSA PSS verify
 *0xb269 RsaOaepPad - RSA OAEP pad
 *0xb35c Asn1DerEncode - ASN.1 DER encode
 *0xb457 RsaPkcs1VerifyEx - RSA PKCS1 verify extended
 *0xb968 Pkcs7ParseSignedData - PKCS7 parse
 *0xbabc Pkcs7ParseSignerInfo - PKCS7 signer info
 *0xbd4a Pkcs7ParseCrlSet - PKCS7 CRL set
 *0xbe56 Pkcs7ParseContentType - PKCS7 content type
 *0xbf31 Pkcs7VerifySignerInfo - PKCS7 verify signer info
 *0xc12c Pkcs7VerifySignedData - PKCS7 verify signed data
 *0xc862 Pkcs7GetDigest - PKCS7 get digest
 *0xc8b2 Asn1ReadTag - ASN.1 read tag
 *0xc93a Asn1ParseTLV - ASN.1 TLV parse
 *0xca77 Asn1ParseAlgorithmIdentifier - ASN.1 parse AlgID
 *0xcbd5 Asn1ParseOid - ASN.1 parse OID
 *0xcc5c Asn1ParseGeneralizedTime - ASN.1 parse GeneralizedTime
 *0x10838 [data] Crypto PPI interface table
 *0x11420 [data] String data
 *0x11590 [data] PPI GUID descriptor
 */