Initial commit

This commit is contained in:
Xoro-1337
2025-11-06 15:36:24 -05:00
parent a738b93280
commit b24c1ddcbc
45 changed files with 65790 additions and 0 deletions

809
xbdm/imp/XeCrypt.h Normal file
View File

@@ -0,0 +1,809 @@
// ---------------------------------------------------------------------------------------
// xecrypt.h
//
// Copyright (C) Microsoft Corporation
// ---------------------------------------------------------------------------------------
#ifndef _XECRYPT_H_
#define _XECRYPT_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned __int64 QWORD;
#define XECRYPTAPI __stdcall
// ---------------------------------------------------------------------------------------
// DES Cipher
//
// These functions implement symmetric encryption and decryption with the DES cipher.
//
// The DES block size is 8 bytes and the DES key size is 8 bytes.
//
// XeCryptDesKey initializes an XECRYPT_DES_STATE structure from a DES key.
//
// XeCryptDesEcb encrypts or decrypts a single DES block.
//
// XeCryptDesCbc encrypts or decrypts a contiguous series of blocks using cipher block
// chaining. On input the pbFeed parameter is the initialization vector. On output the
// pbFeed parameter is filled with the final ciphertext block.
// ---------------------------------------------------------------------------------------
typedef struct {
unsigned long keytab[16][2];
} XECRYPT_DES_STATE;
#define XECRYPT_DES_BLOCK_SIZE (8)
#define XECRYPT_DES_KEY_SIZE (8)
void XECRYPTAPI XeCryptDesParity(const BYTE * pbInp, DWORD cbInp, BYTE * pbOut);
void XECRYPTAPI XeCryptDesKey(XECRYPT_DES_STATE * pDesState, const BYTE * pbKey);
void XECRYPTAPI XeCryptDesEcb(const XECRYPT_DES_STATE * pDesState, const BYTE * pbInp, BYTE * pbOut, BOOL fEncrypt);
void XECRYPTAPI XeCryptDesCbc(const XECRYPT_DES_STATE * pDesState, const BYTE * pbInp, DWORD cbInp, BYTE * pbOut, BYTE * pbFeed, BOOL fEncrypt);
// ---------------------------------------------------------------------------------------
// DES3 Cipher
//
// These functions implement symmetric encryption and decryption with the DES3 cipher.
//
// The DES3 block size is 8 bytes and the DES3 key size is 24 bytes.
//
// XeCryptDes3Key initializes an XECRYPT_DES3_STATE structure from a DES3 key.
//
// XeCryptDes3Ecb encrypts or decrypts a single DES block.
//
// XeCryptDes3Cbc encrypts or decrypts a contiguous series of blocks using cipher block
// chaining. On input the pbFeed parameter is the initialization vector. On output the
// pbFeed parameter is filled with the final ciphertext block.
// ---------------------------------------------------------------------------------------
typedef struct {
XECRYPT_DES_STATE aDesState[3];
} XECRYPT_DES3_STATE;
#define XECRYPT_DES3_KEY_SIZE (24)
void XECRYPTAPI XeCryptDes3Key(XECRYPT_DES3_STATE * pDes3State, const BYTE * pbKey);
void XECRYPTAPI XeCryptDes3Ecb(const XECRYPT_DES3_STATE * pDes3State, const BYTE * pbInp, BYTE * pbOut, BOOL fEncrypt);
void XECRYPTAPI XeCryptDes3Cbc(const XECRYPT_DES3_STATE * pDes3State, const BYTE * pbInp, DWORD cbInp, BYTE * pbOut, BYTE * pbFeed, BOOL fEncrypt);
// ---------------------------------------------------------------------------------------
// AES Cipher
//
// These functions implement symmetric encryption and decryption with the AES cipher.
//
// The AES block size is 16 bytes and the AES key size is 16 bytes.
//
// XeCryptAesKey initializes an XECRYPT_AES_STATE structure from an AES key.
//
// XeCryptAesEcb encrypts or decrypts a single AES block.
//
// XeCryptAesCbc encrypts or decrypts a contiguous series of blocks using cipher block
// chaining. On input the pbFeed parameter is the initialization vector. On output the
// pbFeed parameter is filled with the final ciphertext block.
// ---------------------------------------------------------------------------------------
typedef struct {
BYTE keytabenc[11][4][4];
BYTE keytabdec[11][4][4];
} XECRYPT_AES_STATE;
#define XECRYPT_AES_BLOCK_SIZE (16)
#define XECRYPT_AES_KEY_SIZE (16)
void XECRYPTAPI XeCryptAesKey(XECRYPT_AES_STATE * pAesState, const BYTE * pbKey);
void XECRYPTAPI XeCryptAesEcb(const XECRYPT_AES_STATE * pAesState, const BYTE * pbInp, BYTE * pbOut, BOOL fEncrypt);
void XECRYPTAPI XeCryptAesCbc(const XECRYPT_AES_STATE * pAesState, const BYTE * pbInp, DWORD cbInp, BYTE * pbOut, BYTE * pbFeed, BOOL fEncrypt);
// ---------------------------------------------------------------------------------------
// RC4 Stream Cipher
//
// These functions implement the RC4 stream cipher.
//
// The RC4 key size can be anywhere from zero to 256 bytes long.
//
// XeCryptRc4Key initializes an XECRYPT_RC4_STATE from an RC4 key.
//
// XeCryptRc4Ecb encrypts or decrypts a stream of bytes.
//
// XeCryptRc4 combines both of the previous functions for convenience.
// ---------------------------------------------------------------------------------------
typedef struct {
BYTE S[256];
BYTE i,j;
} XECRYPT_RC4_STATE;
void XECRYPTAPI XeCryptRc4Key(XECRYPT_RC4_STATE * pRc4State, const BYTE * pbKey, DWORD cbKey);
void XECRYPTAPI XeCryptRc4Ecb(XECRYPT_RC4_STATE * pRc4State, BYTE * pbInpOut, DWORD cbInpOut);
void XECRYPTAPI XeCryptRc4(const BYTE * pbKey, DWORD cbKey, BYTE * pbInpOut, DWORD cbInpOut);
// ---------------------------------------------------------------------------------------
// SHA
//
// These functions implement the SHA-1 one-way hash algorithm. The result of the hash of
// any number of bytes is a digest of 20 bytes.
//
// XeCryptShaInit initializes an XECRYPT_SHA_STATE structure.
//
// Next, for each block of bytes that are to be hashed, call XeCryptShaUpdate. There is
// no limit to the size of the block, and it doesn't matter how the blocks are divided.
//
// Finally, call XeCryptShaFinal to compute the digest. Note that after calling this
// function the digest is available in the "state". The cbOut parameter can be less
// than 20 if only a prefix of the resulting digest is needed. It can be zero if the
// resulting digest will be read directly from the state structure.
//
// For convenience, all of these operations are combined by a single call to XeCryptSha.
// ---------------------------------------------------------------------------------------
typedef struct {
DWORD count;
DWORD state[5];
BYTE buffer[64];
} XECRYPT_SHA_STATE;
#define XECRYPT_SHA_DIGEST_SIZE (20)
void XECRYPTAPI XeCryptShaInit(XECRYPT_SHA_STATE * pShaState);
void XECRYPTAPI XeCryptShaUpdate(XECRYPT_SHA_STATE * pShaState, const BYTE * pbInp, DWORD cbInp);
void XECRYPTAPI XeCryptShaFinal(XECRYPT_SHA_STATE * pShaState, BYTE * pbOut, DWORD cbOut);
void XECRYPTAPI XeCryptSha(const BYTE * pbInp1, DWORD cbInp1, const BYTE * pbInp2, DWORD cbInp2, const BYTE * pbInp3, DWORD cbInp3, BYTE * pbOut, DWORD cbOut);
void XECRYPTAPI XeCryptRotSumSha(const BYTE * pbInp1, DWORD cbInp1, const BYTE * pbInp2, DWORD cbInp2, BYTE * pbOut, DWORD cbOut);
// ---------------------------------------------------------------------------------------
// HMAC-SHA
//
// These functions implement the keyed HMAC-SHA-1 algorithm. The result is a digest of
// 20 bytes.
//
// First, initialize an XECRYPT_HMACSHA_STATE structure by calling XeCryptHmacShaInit with
// a key of up to 64 bytes.
//
// Next, for each block of bytes that are to be hashed, call XeCryptHmacShaUpdate. There
// is no limit to the size of the block, and it doesn't matter how the blocks are divided.
//
// Finally, call XeCryptHmacShaFinal to compute the digest. The cbOut parameter can be
// less than 20 if only a prefix of the resulting digest is needed.
//
// For convenience, all of these operations are combined by a single call to XeCryptSha.
//
// The XeCryptHmacShaVerify function computes the digest just like a single call to
// XeCryptHmacSha, then compares the resulting digest to the expected digest passed in
// through the pbVer/cbVer arguments. Note that cbVer can be less than 20 if only a
// prefix of the resulting digest should be compared. The result is TRUE if the
// computed and expected digests match, and FALSE otherwise.
// ---------------------------------------------------------------------------------------
typedef struct {
XECRYPT_SHA_STATE ShaState[2];
} XECRYPT_HMACSHA_STATE;
void XECRYPTAPI XeCryptHmacShaInit(XECRYPT_HMACSHA_STATE * pHmacShaState, const BYTE * pbKey, DWORD cbKey);
void XECRYPTAPI XeCryptHmacShaUpdate(XECRYPT_HMACSHA_STATE * pHmacShaState, const BYTE * pbInp, DWORD cbInp);
void XECRYPTAPI XeCryptHmacShaFinal(XECRYPT_HMACSHA_STATE * pHmacShaState, BYTE * pbOut, DWORD cbOut);
void XECRYPTAPI XeCryptHmacSha(const BYTE * pbKey, DWORD cbKey, const BYTE * pbInp1, DWORD cbInp1, const BYTE * pbInp2, DWORD cbInp2, const BYTE * pbInp3, DWORD cbInp3, BYTE * pbOut, DWORD cbOut);
BOOL XECRYPTAPI XeCryptHmacShaVerify(const BYTE * pbKey, DWORD cbKey, const BYTE * pbInp1, DWORD cbInp1, const BYTE * pbInp2, DWORD cbInp2, const BYTE * pbInp3, DWORD cbInp3, const BYTE * pbVer, DWORD cbVer);
// ---------------------------------------------------------------------------------------
// MD5
//
// These functions implement the MD5 one-way hash algorithm. The result of the hash of
// any number of bytes is a digest of 16 bytes.
//
// First, initialize an XECRYPT_MD5_STATE structure by calling XeCryptMd5Init.
//
// Next, for each block of bytes that are to be hashed, call XeCryptMd5Update. There is
// no limit to the size of the block, and it doesn't matter how the blocks are divided.
//
// Finally, call XeCryptMd5Final to compute the digest. Note that after calling this
// function the digest is available in the "state". The cbOut parameter can be less
// than 16 if only a prefix of the resulting digest is needed. It can be zero if the
// resulting digest will be read directly from the state structure.
//
// For convenience, all of these operations are combined by a single call to XeCryptMd5.
// ---------------------------------------------------------------------------------------
typedef struct {
DWORD count;
DWORD buf[4];
BYTE in[64];
} XECRYPT_MD5_STATE;
#define XECRYPT_MD5_DIGEST_SIZE (16)
void XECRYPTAPI XeCryptMd5Init(XECRYPT_MD5_STATE * pMd5State);
void XECRYPTAPI XeCryptMd5Update(XECRYPT_MD5_STATE * pMd5State, const BYTE * pbInp, DWORD cbInp);
void XECRYPTAPI XeCryptMd5Final(XECRYPT_MD5_STATE * pMd5State, BYTE * pbOut, DWORD cbOut);
void XECRYPTAPI XeCryptMd5(const BYTE * pbInp1, DWORD cbInp1, const BYTE * pbInp2, DWORD cbInp2, const BYTE * pbInp3, DWORD cbInp3, BYTE * pbOut, DWORD cbOut);
// ---------------------------------------------------------------------------------------
// HMAC-MD5
//
// These functions implement the keyed HMAC-MD5 algorithm. The result is a digest of
// 16 bytes.
//
// First, initialize an XECRYPT_HMACMD5_STATE structure by calling XeCryptHmacMd5Init with
// a key of up to 64 bytes.
//
// Next, for each block of bytes that are to be hashed, call XeCryptHmacMd5Update. There
// is no limit to the size of the block, and it doesn't matter how the blocks are divided.
//
// Finally, call XeCryptHmacMd5Final to compute the digest. The cbOut parameter can be
// less than 20 if only a prefix of the resulting digest is needed.
//
// For convenience, all of these operations are combined by a single call to XeCryptMd5.
// ---------------------------------------------------------------------------------------
typedef struct {
XECRYPT_MD5_STATE Md5State[2];
} XECRYPT_HMACMD5_STATE;
void XECRYPTAPI XeCryptHmacMd5Init(XECRYPT_HMACMD5_STATE * pHmacMd5State, const BYTE * pbKey, DWORD cbKey);
void XECRYPTAPI XeCryptHmacMd5Update(XECRYPT_HMACMD5_STATE * pHmacMd5State, const BYTE * pbInp, DWORD cbInp);
void XECRYPTAPI XeCryptHmacMd5Final(XECRYPT_HMACMD5_STATE * pHmacMd5State, BYTE * pbOut, DWORD cbOut);
void XECRYPTAPI XeCryptHmacMd5(const BYTE * pbKey, DWORD cbKey, const BYTE * pbInp1, DWORD cbInp1, const BYTE * pbInp2, DWORD cbInp2, const BYTE * pbInp3, DWORD cbInp3, BYTE * pbOut, DWORD cbOut);
// ---------------------------------------------------------------------------------------
// Big Number Representations
//
// Multiple precision numbers are arranged as an array of digits, with the least
// significant digit coming first ("little-endian digit ordering"), regardless
// of the word size or byte ordering of the digit itself.
//
// A single digit is either a DWORD (4 bytes) or a QWORD (8 bytes). A bignum that
// consists of a series of DWORD digits is tagged "BnDw", whereas a bignum that
// consists of a series of QWORD digits is tagged "BnQw". A bignum function
// is tagged with one of these two to specify the digit size it expects, and it
// takes a length parameter that specifies the number of digits in the number.
//
// Consider a 8-byte number written in radix 256 notation. Here R=256.
//
// b7*(R^7)+b6*(R^6)+b5*(R^5)+b4*(R^5)+b3*(R^3)+b2*(R^2)+b1*(R^1)+b0*(R^0)
//
// A BnDw bignum consists of a series of DWORD digits. The DWORD can be encoded
// in either little-endian or big-endian byte ordering. Thus there are two
// possible formats for these digits.
//
// DwLe [b0 b1 b2 b3][b4 b5 b6 b7]
// DwBe [b3 b2 b1 b0][b7 b6 b5 b4]
//
// A BnQw bignum consists of a series of QWORD digits. The QWORD can be encoded
// in either little-endian or big-endian byte ordering. Thus there are two
// possible formats for these digits.
//
// QwLe [b0 b1 b2 b3 b4 b5 b6 b7]
// QwBe [b7 b6 b5 b4 b3 b2 b1 b0]
//
// A particular platform has a natural byte order (Le or Be). We use the tag Ne
// to mean the natural byte order.
//
// Most low level bignum routines require inputs that are in QwNe format. That
// is, QWORD digits in natural byte order for the platform. They take an array
// of QWORD digits and a count of digits. The caller is responsible for converting
// the bignum into the expected format.
//
// A full complement of conversion functions is available. The BnDw functions
// will convert a bignum made up of a series of DWORD digits between DwLe, DwBe,
// and DwNe formats. The BnQw functions will convert a bignum made up of a series
// of QWORD digits between QwLe, QwBe, and QwNe formats. The BnQw functions can
// also convert between BnDw and BnQw bignum formats, but since the length parameter
// specifies the number of QWORD digits, the BnDw bignum must contain an even number
// of DWORD digits.
//
// When a bignum is to be stored or used on multiple platforms, the application
// must choose a concrete representation for the number. In the case of digital
// signatures, we choose to store them in QwBe format. This was chosen to match
// the natural word size and byte ordering of the Xenon console, so that the
// signature checking code would be as small and fast as possible on that platform.
// ---------------------------------------------------------------------------------------
void XECRYPTAPI XeCryptBnDw_Zero(DWORD * pdw, DWORD cdw);
void XECRYPTAPI XeCryptBnDw_Copy(const DWORD * pdwInp, DWORD * pdwOut, DWORD cdw);
void XECRYPTAPI XeCryptBnDw_SwapLeBe(const DWORD * pdwInp, DWORD * pdwOut, DWORD cdw);
void XECRYPTAPI XeCryptBnQw_Zero(QWORD * pqw, DWORD cqw);
void XECRYPTAPI XeCryptBnQw_Copy(const QWORD * pqwInp, QWORD * pqwOut, DWORD cqw);
void XECRYPTAPI XeCryptBnQw_SwapLeBe(const QWORD * pqwInp, QWORD * pqwOut, DWORD cqw);
void XECRYPTAPI XeCryptBnQw_SwapDwQw(const QWORD * pqwInp, QWORD * pqwOut, DWORD cqw);
void XECRYPTAPI XeCryptBnQw_SwapDwQwLeBe(const QWORD * pqwInp, QWORD * pqwOut, DWORD cqw);
#define XeCryptBnDw_DwLeToDwLe XeCryptBnDw_Copy
#define XeCryptBnDw_DwLeToDwBe XeCryptBnDw_SwapLeBe
#define XeCryptBnDw_DwBeToDwLe XeCryptBnDw_SwapLeBe
#define XeCryptBnDw_DwBeToDwBe XeCryptBnDw_Copy
#define XeCryptBnQw_DwLeToDwLe XeCryptBnQw_Copy
#define XeCryptBnQw_DwLeToDwBe XeCryptBnQw_SwapLeBe
#define XeCryptBnQw_DwLeToQwLe XeCryptBnQw_Copy
#define XeCryptBnQw_DwLeToQwBe XeCryptBnQw_SwapDwQwLeBe
#define XeCryptBnQw_DwBeToDwLe XeCryptBnQw_SwapLeBe
#define XeCryptBnQw_DwBeToDwBe XeCryptBnQw_Copy
#define XeCryptBnQw_DwBeToQwLe XeCryptBnQw_SwapLeBe
#define XeCryptBnQw_DwBeToQwBe XeCryptBnQw_SwapDwQw
#define XeCryptBnQw_QwLeToDwLe XeCryptBnQw_Copy
#define XeCryptBnQw_QwLeToDwBe XeCryptBnQw_SwapLeBe
#define XeCryptBnQw_QwLeToQwLe XeCryptBnQw_Copy
#define XeCryptBnQw_QwLeToQwBe XeCryptBnQw_SwapDwQwLeBe
#define XeCryptBnQw_QwBeToDwLe XeCryptBnQw_SwapDwQwLeBe
#define XeCryptBnQw_QwBeToDwBe XeCryptBnQw_SwapDwQw
#define XeCryptBnQw_QwBeToQwLe XeCryptBnQw_SwapDwQwLeBe
#define XeCryptBnQw_QwBeToQwBe XeCryptBnQw_Copy
#ifdef _M_PPCBE
#define XeCryptBnDw_DwLeToDwNe XeCryptBnDw_DwLeToDwBe
#define XeCryptBnDw_DwBeToDwNe XeCryptBnDw_DwBeToDwBe
#define XeCryptBnDw_DwNeToDwLe XeCryptBnDw_DwBeToDwLe
#define XeCryptBnDw_DwNeToDwBe XeCryptBnDw_DwBeToDwBe
#define XeCryptBnQw_DwLeToDwNe XeCryptBnQw_DwLeToDwBe
#define XeCryptBnQw_DwLeToQwNe XeCryptBnQw_DwLeToQwBe
#define XeCryptBnQw_DwBeToDwNe XeCryptBnQw_DwBeToDwBe
#define XeCryptBnQw_DwBeToQwNe XeCryptBnQw_DwBeToQwBe
#define XeCryptBnQw_QwLeToDwNe XeCryptBnQw_QwLeToDwBe
#define XeCryptBnQw_QwLeToQwNe XeCryptBnQw_QwLeToQwBe
#define XeCryptBnQw_QwBeToDwNe XeCryptBnQw_QwBeToDwBe
#define XeCryptBnQw_QwBeToQwNe XeCryptBnQw_QwBeToQwBe
#define XeCryptBnQw_DwNeToDwLe XeCryptBnQw_DwBeToDwLe
#define XeCryptBnQw_DwNeToDwBe XeCryptBnQw_DwBeToDwBe
#define XeCryptBnQw_DwNeToQwLe XeCryptBnQw_DwBeToQwLe
#define XeCryptBnQw_DwNeToQwBe XeCryptBnQw_DwBeToQwBe
#define XeCryptBnQw_QwNeToDwLe XeCryptBnQw_QwBeToDwLe
#define XeCryptBnQw_QwNeToDwBe XeCryptBnQw_QwBeToDwBe
#define XeCryptBnQw_QwNeToQwLe XeCryptBnQw_QwBeToQwLe
#define XeCryptBnQw_QwNeToQwBe XeCryptBnQw_QwBeToQwBe
#else
#define XeCryptBnDw_DwLeToDwNe XeCryptBnDw_DwLeToDwLe
#define XeCryptBnDw_DwBeToDwNe XeCryptBnDw_DwBeToDwLe
#define XeCryptBnDw_DwNeToDwLe XeCryptBnDw_DwLeToDwLe
#define XeCryptBnDw_DwNeToDwBe XeCryptBnDw_DwLeToDwBe
#define XeCryptBnQw_DwLeToDwNe XeCryptBnQw_DwLeToDwLe
#define XeCryptBnQw_DwLeToQwNe XeCryptBnQw_DwLeToQwLe
#define XeCryptBnQw_DwBeToDwNe XeCryptBnQw_DwBeToDwLe
#define XeCryptBnQw_DwBeToQwNe XeCryptBnQw_DwBeToQwLe
#define XeCryptBnQw_QwLeToDwNe XeCryptBnQw_QwLeToDwLe
#define XeCryptBnQw_QwLeToQwNe XeCryptBnQw_QwLeToQwLe
#define XeCryptBnQw_QwBeToDwNe XeCryptBnQw_QwBeToDwLe
#define XeCryptBnQw_QwBeToQwNe XeCryptBnQw_QwBeToQwLe
#define XeCryptBnQw_DwNeToDwLe XeCryptBnQw_DwLeToDwLe
#define XeCryptBnQw_DwNeToDwBe XeCryptBnQw_DwLeToDwBe
#define XeCryptBnQw_DwNeToQwLe XeCryptBnQw_DwLeToQwLe
#define XeCryptBnQw_DwNeToQwBe XeCryptBnQw_DwLeToQwBe
#define XeCryptBnQw_QwNeToDwLe XeCryptBnQw_QwLeToDwLe
#define XeCryptBnQw_QwNeToDwBe XeCryptBnQw_QwLeToDwBe
#define XeCryptBnQw_QwNeToQwLe XeCryptBnQw_QwLeToQwLe
#define XeCryptBnQw_QwNeToQwBe XeCryptBnQw_QwLeToQwBe
#endif
// ---------------------------------------------------------------------------------------
// XeCryptBnQwNeCompare
//
// This function compares two multiple precision numbers in BnQwNe format and returns:
//
// -1 if aqwA[] < aqwB[]
// 0 if aqwA[] = aqwB[]
// +1 if aqwA[] > aqwB[]
// ---------------------------------------------------------------------------------------
int XECRYPTAPI XeCryptBnQwNeCompare(const QWORD * pqwA, const QWORD * pqwB, DWORD cqw);
// ---------------------------------------------------------------------------------------
// XeCryptBnQwNeModInv
//
// This function computes the 2-adic inverse of a QWORD (mod 2^64).
// ---------------------------------------------------------------------------------------
QWORD XECRYPTAPI XeCryptBnQwNeModInv(QWORD qw);
// ---------------------------------------------------------------------------------------
// XeCryptBnQwNeModMul
//
// This function performs Montgomery multiplication.
//
// All numbers must be in BnQwNe format and have cqw digits.
//
// The result of this function is:
//
// aqwA[] * aqwB[]
// aqwC[] = --------------- MOD aqwM[]
// 2^(cqw*64)
// ---------------------------------------------------------------------------------------
void XECRYPTAPI XeCryptBnQwNeModMul(const QWORD * pqwA, const QWORD * pqwB, QWORD * pqwC, QWORD qwMI, const QWORD * pqwM, DWORD cqw);
// ---------------------------------------------------------------------------------------
// XeCryptBnQwNeModExp
//
// This function performs modular exponentiation.
//
// All numbers must be in BnQwNe format and have cqw digits.
//
// The result of this function is:
//
// aqwA[] = (aqwB[] ^ aqwC[]) MOD aqwM[]
//
// This function returns FALSE if there was not enough memory to allocate storage for
// intermediate results, or if one or more of the inputs is invalid (such as zero modulus),
// otherwise TRUE is returned.
// ---------------------------------------------------------------------------------------
BOOL XECRYPTAPI XeCryptBnQwNeModExp(QWORD * pqwA, const QWORD * pqwB, const QWORD * pqwC, const QWORD * pqwM, DWORD cqw);
// ---------------------------------------------------------------------------------------
// XeCryptBnQwNeModExpRoot
//
// This function performs modular exponentiation to an exponent and modulus given by its
// prime factors and coefficients. This is a support routine for exponentiating to a
// private RSA key. It is more efficient than exponentiating to the private exponent
// directly, but the result is otherwise the same.
//
// All numbers must be in BnQwNe format. The pqwA and pqwB numbers have cqw * 2 digits.
// All of the other numbers have cqw digits.
//
// The result of this function is:
//
// aqwA[] = (aqwB[] ^ aqwC[]) MOD aqwM[]
//
// where aqwC[] and aqwM[] are implicitly provided by their constituent parts.
//
// This function returns FALSE if there was not enough memory to allocate storage for
// intermediate results, or if one or more of the inputs is invalid (such as a zero modulus),
// otherwise TRUE is returned.
// ---------------------------------------------------------------------------------------
BOOL XECRYPTAPI XeCryptBnQwNeModExpRoot(QWORD * pqwA, const QWORD * pqwB, const QWORD * pqwPP, const QWORD * pqwQQ, const QWORD * pqwDP, const QWORD * pqwDQ, const QWORD * pqwCR, DWORD cqw);
// ---------------------------------------------------------------------------------------
// XeCryptBnQwNeRsaPubCrypt
// XeCryptBnQwNeRsaPrvCrypt
//
// These functions performs modular exponentiation of a message to the public or private
// exponent of the given RSA key.
//
// The aqwA[] parameter must be in BnQwNe format and have cqw digits. It's value must
// be less than the modulus.
//
// The result of this function is:
//
// aqwB[] = (aqwA[] ^ dwPubExp) MOD aqwM[] (XeCryptBnQwNeRsaPubCrypt)
// aqwB[] = (aqwA[] ^ aqwPrvExp[]) MOD aqwM[] (XeCryptBnQwNeRsaPrvCrypt)
// ---------------------------------------------------------------------------------------
typedef struct {
DWORD cqw; // Number of QWORD digits in modulus
DWORD dwPubExp; // Public exponent
QWORD qwReserved; // Reserved (was qwMI)
// QWORD aqwM[cqw]; // [BnQwNe] Modulus
// QWORD aqwP[cqw/2]; // [BnQwNe] Private prime P
// QWORD aqwQ[cqw/2]; // [BnQwNe] Private prime Q
// QWORD aqwDP[cqw/2]; // [BnQwNe] Private exponent P
// QWORD aqwDQ[cqw/2]; // [BnQwNe] Private exponent Q
// QWORD aqwCR[cqw/2]; // [BnQwNe] Private coefficient
} XECRYPT_RSA;
typedef struct {
XECRYPT_RSA Rsa; // Common header
QWORD aqwM[16]; // [BnQwNe] Modulus
} XECRYPT_RSAPUB_1024;
typedef struct {
XECRYPT_RSA Rsa; // Common header
QWORD aqwM[24]; // [BnQwNe] Modulus
} XECRYPT_RSAPUB_1536;
typedef struct {
XECRYPT_RSA Rsa; // Common header
QWORD aqwM[32]; // [BnQwNe] Modulus
} XECRYPT_RSAPUB_2048;
typedef struct {
XECRYPT_RSA Rsa; // Common header
QWORD aqwM[64]; // [BnQwNe] Modulus
} XECRYPT_RSAPUB_4096;
typedef struct {
XECRYPT_RSA Rsa; // Common header
QWORD aqwM[16]; // [BnQwNe] Modulus
QWORD aqwP[8]; // [BnQwNe] Private prime P
QWORD aqwQ[8]; // [BnQwNe] Private prime Q
QWORD aqwDP[8]; // [BnQwNe] Private exponent P
QWORD aqwDQ[8]; // [BnQwNe] Private exponent Q
QWORD aqwCR[8]; // [BnQwNe] Private coefficient
} XECRYPT_RSAPRV_1024;
typedef struct {
XECRYPT_RSA Rsa; // Common header
QWORD aqwM[24]; // [BnQwNe] Modulus
QWORD aqwP[12]; // [BnQwNe] Private prime P
QWORD aqwQ[12]; // [BnQwNe] Private prime Q
QWORD aqwDP[12]; // [BnQwNe] Private exponent P
QWORD aqwDQ[12]; // [BnQwNe] Private exponent Q
QWORD aqwCR[12]; // [BnQwNe] Private coefficient
} XECRYPT_RSAPRV_1536;
typedef struct {
XECRYPT_RSA Rsa; // Common header
QWORD aqwM[32]; // [BnQwNe] Modulus
QWORD aqwP[16]; // [BnQwNe] Private prime P
QWORD aqwQ[16]; // [BnQwNe] Private prime Q
QWORD aqwDP[16]; // [BnQwNe] Private exponent P
QWORD aqwDQ[16]; // [BnQwNe] Private exponent Q
QWORD aqwCR[16]; // [BnQwNe] Private coefficient
} XECRYPT_RSAPRV_2048;
typedef struct {
XECRYPT_RSA Rsa; // Common header
QWORD aqwM[64]; // [BnQwNe] Modulus
QWORD aqwP[32]; // [BnQwNe] Private prime P
QWORD aqwQ[32]; // [BnQwNe] Private prime Q
QWORD aqwDP[32]; // [BnQwNe] Private exponent P
QWORD aqwDQ[32]; // [BnQwNe] Private exponent Q
QWORD aqwCR[32]; // [BnQwNe] Private coefficient
} XECRYPT_RSAPRV_4096;
BOOL XECRYPTAPI XeCryptBnQwNeRsaPubCrypt(const QWORD * pqwA, QWORD * pqwB, const XECRYPT_RSA * pRsa);
BOOL XECRYPTAPI XeCryptBnQwNeRsaPrvCrypt(const QWORD * pqwA, QWORD * pqwB, const XECRYPT_RSA * pRsa);
// ---------------------------------------------------------------------------------------
// XeCryptBnQwNeRsaKeyGen
//
// This function generates a random RSA key pair.
//
// The cbits parameter specifies the number of bits in the modulus. It must be a multiple
// of 128, and must be between 512 and 4096.
//
// The dwPubExp parameter specifies the public exponent.
//
// The pRsaPub and pRsaPrv parameters must point to XECRYPT_RSA structures that are large
// enough to hold the public and private keys requested. The public key structure needs
// to be at least sizeof(XECRYPT_RSA) + (cbits / 8) bytes big. The private key structure
// needs to be at least sizeof(XECRYPT_RSA) + (((cbits / 2) * 7) / 8) bytes big.
// ---------------------------------------------------------------------------------------
BOOL XECRYPTAPI XeCryptBnQwNeRsaKeyGen(DWORD cbits, DWORD dwPubExp, XECRYPT_RSA * pRsaPub, XECRYPT_RSA * pRsaPrv);
// ---------------------------------------------------------------------------------------
// XeCryptBnQwBeSigFormat
// XeCryptBnQwBeSigCreate
// XeCryptBnQwBeSigVerify
//
// These functions format, create, and verify digital signatures using an RSA key pair.
//
// The size of the RSA key must be 2048 bits and the public exponent must be 3 or 65537.
// The size of a digital signature is 256 bytes. The signature is represented as a bignum
// in BnQwBe format. This allows for processing digital signatures on platforms with
// different byte orders.
//
// The XeCryptBnQwBeSigFormat function takes a 20 byte hash and a 10 byte fixed salt value
// and generates a digital signature using the PKCS #1 v2.1 RSASSA-PSS algorithm. The
// hash function is SHA and the MGF function is RC4. The resulting digital signature
// is stored in the XECRYPT_SIG structure.
//
// The XeCryptBnQwBeSigCreate function takes a 20 byte hash and a 10 byte fixed salt
// value, generates a digital signature, and then pre-compensates it by multiplying the
// signature by a scale factor derived from the modulus in the public key. This
// pre-compensation is used to simplify verification later.
//
// The XeCryptQwBeSigVerify function takes an encrypted digital signature, a 20 byte hash
// a 10 byte fixed salt value, and an RSA public key. It returns TRUE if the digital
// signature, when decrypted with the RSA public key, matches the result of formatting
// a digital signature with the 20 byte hash and 10 byte salt value, and FALSE otherwise.
// ---------------------------------------------------------------------------------------
typedef struct { // [BnQwBe]
QWORD aqwPad[28]; // Padding
BYTE bOne; // 0x01
BYTE abSalt[10]; // Salt
BYTE abHash[20]; // Hash
BYTE bEnd; // 0xBC
} XECRYPT_SIG;
void XECRYPTAPI XeCryptBnQwBeSigFormat(XECRYPT_SIG * pSig, const BYTE * pbHash, const BYTE * pbSalt);
BOOL XECRYPTAPI XeCryptBnQwBeSigCreate(XECRYPT_SIG * pSig, const BYTE * pbHash, const BYTE * pbSalt, const XECRYPT_RSA * pRsa);
BOOL XECRYPTAPI XeCryptBnQwBeSigVerify(XECRYPT_SIG * pSig, const BYTE * pbHash, const BYTE * pbSalt, const XECRYPT_RSA * pRsa);
// ---------------------------------------------------------------------------------------
// XeCryptBnDwLePkcs1Format
// XeCryptBnDwLePkcs1Verify
//
// These functions format and verify a SHA digest in PKCS#1 format and BnDwLe bignum
// representation. This format matches what was used on Xbox 1 and what is normally
// produced by nCipher devices.
//
// The pbHash argument specifies the digest to format or verify.
//
// When formatting, the dwType argument selects one of three encoding formats, as follows.
//
// 0: [HashReversed][140400051A02030E2B05060930213000][FF ... FF][0100]
// 1: [HashReversed][14041A02030E2B050607301F3000][FF ... FF][0100]
// >1: [HashReversed][00][FF ... FF][0100]
//
// On Xbox 1, signatures would always be encoded using format 0, but any of these formats
// were accepted by the verification routine. We follow the same rules when calling
// XeCryptBnDwLePkcs1Verify.
//
// The pbSig argument specifies the buffer to place the formatted signature, or the buffer
// containing the signature to verify.
//
// The cbSig argument specifies the size of the signature buffer. It should be equal to
// the number of bytes in the RSA key modulus. For example, if this siguature is used
// with an RSA key whose modulus is 1024 bits, you would specify 128 for this argument.
// ---------------------------------------------------------------------------------------
void XECRYPTAPI XeCryptBnDwLePkcs1Format(const BYTE * pbHash, DWORD dwType, BYTE * pbSig, DWORD cbSig);
BOOL XECRYPTAPI XeCryptBnDwLePkcs1Verify(const BYTE * pbHash, const BYTE * pbSig, DWORD cbSig);
// ---------------------------------------------------------------------------------------
// XeCryptBnDwLeDhModExp
//
// These functions perform Diffie-Hellman modular exponentiation.
//
// The inputs and outputs are in BnDwLe format for compatibility with legacy applications.
// Note, however, that the XECRYPT_DH structure is always BnQwNe format.
//
// The pDh argument can be NULL in any of these functions, in which case the standard
// 768-bit Oakley Group 1 constants will be used.
//
// The XeCryptBnDwLeDhModExp function performs modular exponentiation. The pdwA argument
// specifies the base to be exponentiated. If it is NULL, then the generator in the
// XECRYPT_DH structure is used as the base.
//
// The pdwB argument specifies the exponent.
//
// The result is stored in the pdwC argument.
//
// aqwC[] = ((pqwA ? pqwA[] : pDh->aqwG[]) ^ aqwB[]) MOD pDh->aqwM[]
//
// The XeCryptBnDwLeDhInvalBase function returns TRUE if the pdwA argument is an invalid
// base for exponentiation. A valid base is 1 < aqwA[] < (aqwM[]-1).
//
// The XeCryptBnDwLeDhEqualBase function returns TRUE if the pdwA argument is equal to
// the pDh->aqwG[].
// ---------------------------------------------------------------------------------------
typedef struct {
DWORD cqw; // Number of QWORD digits in modulus
DWORD dwReserved; // Reserved
// QWORD aqwM[cqw]; // [BnQwNe] Modulus
// QWORD aqwG[cqw]; // [BnQwNe] Generator
} XECRYPT_DH;
typedef struct {
XECRYPT_DH Dh; // Common header
QWORD aqwM[12]; // [BnQwNe] Modulus
QWORD aqwG[12]; // [BnQwNe] Generator
} XECRYPT_DH_768;
typedef struct {
XECRYPT_DH Dh; // Common header
QWORD aqwM[16]; // [BnQwNe] Modulus
QWORD aqwB[16]; // [BnQwNe] Generator
} XECRYPT_DH_1024;
BOOL XECRYPTAPI XeCryptBnDwLeDhModExp(const DWORD * pdwA, const DWORD * pdwB, DWORD * pdwC, const XECRYPT_DH * pDh);
BOOL XECRYPTAPI XeCryptBnDwLeDhInvalBase(const DWORD * pdwA, const XECRYPT_DH * pDh);
BOOL XECRYPTAPI XeCryptBnDwLeDhEqualBase(const DWORD * pdwA, const XECRYPT_DH * pDh);
// ---------------------------------------------------------------------------------------
// XeCryptBnQwNeEcSigVerify
//
// This function uses eliptic curve exponentiation to verify a digital signature.
//
// The pEcPub argument specifies the public key to use when verifying the signature.
//
// The pbMsg argument is the same sequence of bytes that was used when the signature
// was generated.
//
// The cbMsg argument specifies the number of byte in pbMsg.
//
// The pbSig argument is the sequence of bytes that make up the signature. The size of
// this signature is defined by the sum of the cbitR, cbitS, and cbitA fields of the
// public key, rounded up to the next byte.
//
// If the public key fails to verify the supplied signature, FALSE is returned. If the
// public key successfully verifies the signature, then the sequence number that was
// encoded in the signature is returned in the pqwSeq out argument. The number of bits
// in the sequence number is given by the cbitN field of the public key.
// ---------------------------------------------------------------------------------------
typedef struct {
DWORD cqw; // Number of QWORD digits in modulus
BYTE cbitR; // This many bits of signature form R
BYTE cbitS; // This many bits of signature form S (after R)
BYTE cbitA; // This many bits of signature form A (after S)
BYTE cbitN; // This many bits of sequence number are returned
// QWORD aqwM[cqw]; // [BnQwNe] Modulus
// QWORD aqwC[cqw*2]; // [BnQwNe] Curve
// QWORD aqwG[cqw*2]; // [BnQwNe] Generator
// QWORD aqwGX[cqw*2]; // [BnQwNe] Generator ^ X (private exponent)
} XECRYPT_ECPUB;
typedef struct {
XECRYPT_ECPUB EcPub; // Common header
QWORD aqwM[8]; // [BnQwNe] Modulus
QWORD aqwC[16]; // [BnQwNe] Curve
QWORD aqwG[16]; // [BnQwNe] Generator
QWORD aqwGP[16]; // [BnQwNe] Generator ^ X (private exponent)
} XECRYPT_ECPUB_512;
BOOL XECRYPTAPI XeCryptBnQwNeEcSigVerify(const XECRYPT_ECPUB * pEcPub, const BYTE * pbMsg, DWORD cbMsg, const BYTE * pbSig, QWORD * pqwSeq);
// ---------------------------------------------------------------------------------------
// XeCryptRandom
//
// This function generates a series of cryptographically strong random bits.
// ---------------------------------------------------------------------------------------
void XECRYPTAPI XeCryptRandom(BYTE * pb, DWORD cb);
// ---------------------------------------------------------------------------------------
// Parve Cipher
//
// These functions implement symmetric encryption and CBC MAC generation using the Parve
// cipher. There is no support for symmetric decryption.
//
// The Parve block size is 8 bytes and the key size is 8 bytes.
//
// XeCryptParveEcb encrypts a single Parve block with the given key and the given Sbox.
// The pbKey parameter points to an 8 byte key. The pbSbox parameter points to a 256
// "private key" array. The pbInp parameter points to the 8 bytes to be encrypted. The
// pbOut parameter points to a location to store the encrypted 8 bytes. The pbInp and
// pbOut parameters can point to the same location.
//
// XeCryptParveCbcMac computes an 8 byte MAC from a contiguous series of Parve blocks
// using cipher block chaining. The pbKey parameter specifies the key to use. The
// pbSbox parameter points to a 256 "private key" array. The pbIv argument specifies the
// 8 byte initialization vector to use. The pbOut parameter specifies the location to
// store the 8 byte MAC result.
// ---------------------------------------------------------------------------------------
#define XECRYPT_PARVE_BLOCK_SIZE (8)
#define XECRYPT_PARVE_KEY_SIZE (8)
#define XECRYPT_PARVE_SBOX_SIZE (256)
#define XECRYPT_PARVE_MAC_SIZE (8)
void XECRYPTAPI XeCryptParveEcb(const BYTE * pbKey, const BYTE * pbSbox, const BYTE * pbInp, BYTE * pbOut);
void XECRYPTAPI XeCryptParveCbcMac(const BYTE * pbKey, const BYTE * pbSbox, const BYTE * pbIv, const BYTE * pbInp, DWORD cbInp, BYTE * pbOut);
// ---------------------------------------------------------------------------------------
// XeCryptChainAndSumMac
//
// This function implements the Chain & Sum MAC algorithm.
//
// The pdwCD parameter points to a pair of DWORD values that will be used as the C and D
// constants of the algorithm.
//
// The pdwAB parameter points to a pair of DWORD values that will be used as the A and B
// constants of the algorithm.
//
// The pdwInp parameter points to a series of DWORD values to be consumed as input to
// the algorithm. The cdwInp parameter specifies the number of DWORD values in this
// array. It must be a multiple of two, as the input is consumed in pairs. If it is
// an odd number, it will be truncated.
//
// The pdwOut parameter points to a location in which a pair of DWORD results are stored.
// ---------------------------------------------------------------------------------------
void XECRYPTAPI XeCryptChainAndSumMac(const DWORD * pdwCD, const DWORD * pdwAB, const DWORD * pdwInp, DWORD cdwInp, DWORD * pdwOut);
#ifdef __cplusplus
};
#endif
#endif