/**
* @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
*/