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