// ---------------------------------------------------------------------------------------
// 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);

void    XECRYPTAPI XeCryptChainAndSumMac(const DWORD * pdwCD, const DWORD * pdwAB, const DWORD * pdwInp, DWORD cdwInp, DWORD * pdwOut);
 
#ifdef __cplusplus
};
#endif
 
#endif