diff options
Diffstat (limited to 'common/crypto.h')
| -rw-r--r-- | common/crypto.h | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/common/crypto.h b/common/crypto.h new file mode 100644 index 0000000..80b25b2 --- /dev/null +++ b/common/crypto.h @@ -0,0 +1,281 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: This module is for wrapping Crypto++ functions, including crypto++ +// directly has nasty consequences polluting the global namespace, and +// conflicting with xdebug and locale stuff, so we only include it here +// and use this wrapper in the rest of our code. +// +// $NoKeywords: $ +//============================================================================= + +#ifndef CRYPTO_H +#define CRYPTO_H + +#include <tier0/dbg.h> // for Assert & AssertMsg +#include "tier1/passwordhash.h" +#include "tier1/utlmemory.h" +#include <steam/steamtypes.h> // for Salt_t + +extern void FreeListRNG(); + +const unsigned int k_cubSHA256Hash = 32; +typedef unsigned char SHA256Digest_t[ k_cubSHA256Hash ]; + +const int k_nSymmetricBlockSize = 16; // AES block size (128 bits) +const int k_nSymmetricKeyLen = 32; // length in bytes of keys used for symmetric encryption + +const int k_nRSAKeyLenMax = 1024; // max length in bytes of keys used for RSA encryption (includes DER encoding) +const int k_nRSAKeyLenMaxEncoded = k_nRSAKeyLenMax*2; // max length in bytes of hex-encoded key (hex encoding exactly doubles size) +const int k_nRSAKeyBits = 1024; // length in bits of keys used for RSA encryption +const int k_cubRSAEncryptedBlockSize = 128; +const int k_cubRSAPlaintextBlockSize = 86 + 1; // assume plaintext is text, so add a byte for the trailing \0 +const uint32 k_cubRSASignature = k_cubRSAEncryptedBlockSize; + +// Simple buffer class to encapsulate output from crypto functions with unknown output size +class CCryptoOutBuffer +{ +public: + + CCryptoOutBuffer() + { + m_pubData = NULL; + m_cubData = 0; + } + + ~CCryptoOutBuffer() + { + if ( m_pubData ) + delete[] m_pubData; + m_pubData = NULL; + m_cubData = 0; + } + + void Set( uint8 *pubData, uint32 cubData ) + { + if ( !pubData || !cubData ) + return; + + if ( m_pubData ) + delete[] m_pubData; + + m_pubData = new uint8[ cubData ]; + memcpy( m_pubData, pubData, cubData ); + m_cubData = cubData; + } + + void Allocate( uint32 cubData ) + { + if ( m_pubData ) + delete[] m_pubData; + + m_pubData = new uint8[ cubData ]; + m_cubData = cubData; + } + + void Trim( uint32 cubTrim ) + { + Assert( cubTrim <= m_cubData ); + m_cubData = cubTrim; + } + + uint8 *PubData() { return m_pubData; } + uint32 CubData() { return m_cubData; } + +private: + uint8 *m_pubData; + uint32 m_cubData; +}; + +#if !defined(_PS3) +class CCrypto +{ +public: + static uint32 GetSymmetricEncryptedSize( uint32 cubPlaintextData ); + + // this method writes the encrypted IV, then the ciphertext + static bool SymmetricEncryptWithIV( const uint8 * pubPlaintextData, uint32 cubPlaintextData, + const uint8 * pIV, uint32 cubIV, + uint8 * pubEncryptedData, uint32 * pcubEncryptedData, + const uint8 * pubKey, uint32 cubKey ); + static bool SymmetricEncrypt( const uint8 * pubPlaintextData, uint32 cubPlaintextData, + uint8 * pubEncryptedData, uint32 * pcubEncryptedData, + const uint8 * pubKey, uint32 cubKey ); + // this method assumes there is no IV before the payload - dissimilar to SymmetricEncryptWithIV + static bool SymmetricDecryptWithIV( const uint8 * pubEncryptedData, uint32 cubEncryptedData, + const uint8 * pIV, uint32 cubIV, + uint8 * pubPlaintextData, uint32 * pcubPlaintextData, + const uint8 * pubKey, uint32 cubKey ); + static bool SymmetricDecrypt( const uint8 * pubEncryptedData, uint32 cubEncryptedData, + uint8 * pubPlaintextData, uint32 * pcubPlaintextData, + const uint8 * pubKey, uint32 cubKey ); + + // symmetrically encrypt data with a text password. A SHA256 hash of the password + // is used as an AES encryption key (calls SymmetricEncrypt, above). + // An HMAC of the ciphertext is appended, for authentication. + static bool EncryptWithPasswordAndHMAC( const uint8 *pubPlaintextData, uint32 cubPlaintextData, + uint8 * pubEncryptedData, uint32 * pcubEncryptedData, + const char *pchPassword ); + + // Same as above but uses an explicit IV. The format of the ciphertext is the same. + // Be sure you know what you're doing if you use this - a random IV is much more secure in general! + static bool EncryptWithPasswordAndHMACWithIV( const uint8 *pubPlaintextData, uint32 cubPlaintextData, + const uint8 * pIV, uint32 cubIV, + uint8 * pubEncryptedData, uint32 * pcubEncryptedData, + const char *pchPassword ); + + // Symmetrically decrypt data with the given password (see above). + // If the HMAC does not match what we expect, then we know that either the password is + // incorrect or the message is corrupted. + static bool DecryptWithPasswordAndAuthenticate( const uint8 * pubEncryptedData, uint32 cubEncryptedData, + uint8 * pubPlaintextData, uint32 * pcubPlaintextData, + const char *pchPassword ); + + static bool RSAGenerateKeys( uint8 *pubPublicKey, uint32 *pcubPublicKey, uint8 *pubPrivateKey, uint32 *pcubPrivateKey ); + + static bool RSAEncrypt( const uint8 *pubPlaintextPlaintextData, const uint32 cubData, uint8 *pubEncryptedData, + uint32 *pcubEncryptedData, const uint8 *pubPublicKey, const uint32 cubPublicKey ); + static bool RSADecrypt( const uint8 *pubEncryptedData, uint32 cubEncryptedData, + uint8 *pubPlaintextData, uint32 *pcubPlaintextData, const uint8 *pubPrivateKey, const uint32 cubPrivateKey ); + + // decrypt using a public key, and no padding + static bool RSAPublicDecrypt_NoPadding( const uint8 *pubEncryptedData, uint32 cubEncryptedData, + uint8 *pubPlaintextData, uint32 *pcubPlaintextData, const uint8 *pubPublicKey, const uint32 cubPublicKey ); + + static bool RSASign( const uint8 *pubData, const uint32 cubData, + uint8 *pubSignature, uint32 *pcubSignature, + const uint8 * pubPrivateKey, const uint32 cubPrivateKey ); + static bool RSAVerifySignature( const uint8 *pubData, const uint32 cubData, + const uint8 *pubSignature, const uint32 cubSignature, + const uint8 *pubPublicKey, const uint32 cubPublicKey ); + + static bool RSASignSHA256( const uint8 *pubData, const uint32 cubData, + uint8 *pubSignature, uint32 *pcubSignature, + const uint8 * pubPrivateKey, const uint32 cubPrivateKey ); + static bool RSAVerifySignatureSHA256( const uint8 *pubData, const uint32 cubData, + const uint8 *pubSignature, const uint32 cubSignature, + const uint8 *pubPublicKey, const uint32 cubPublicKey ); + + static bool HexEncode( const uint8 *pubData, const uint32 cubData, char *pchEncodedData, uint32 cchEncodedData ); + static bool HexDecode( const char *pchData, uint8 *pubDecodedData, uint32 *pcubDecodedData ); + + static uint32 Base64EncodeMaxOutput( uint32 cubData, const char *pszLineBreakOrNull ); + static bool Base64Encode( const uint8 *pubData, uint32 cubData, char *pchEncodedData, uint32 cchEncodedData, bool bInsertLineBreaks = true ); // legacy, deprecated + static bool Base64Encode( const uint8 *pubData, uint32 cubData, char *pchEncodedData, uint32 *pcchEncodedData, const char *pszLineBreak = "\n" ); + + static uint32 Base64DecodeMaxOutput( uint32 cubData ) { return ( (cubData + 3 ) / 4) * 3 + 1; } + static bool Base64Decode( const char *pchEncodedData, uint8 *pubDecodedData, uint32 *pcubDecodedData, bool bIgnoreInvalidCharacters = true ); // legacy, deprecated + static bool Base64Decode( const char *pchEncodedData, uint32 cchEncodedData, uint8 *pubDecodedData, uint32 *pcubDecodedData, bool bIgnoreInvalidCharacters = true ); + + static bool GenerateSalt( Salt_t *pSalt ); + static bool GenerateSHA1Digest( const uint8 *pubInput, const int cubInput, SHADigest_t *pOutDigest ); + static bool GenerateSaltedSHA1Digest( const char *pchInput, const Salt_t *pSalt, SHADigest_t *pOutDigest ); + static bool GenerateRandomBlock( uint8 *pubDest, int cubDest ); + + static bool GenerateHMAC( const uint8 *pubData, uint32 cubData, const uint8 *pubKey, uint32 cubKey, SHADigest_t *pOutputDigest ); + static bool GenerateHMAC256( const uint8 *pubData, uint32 cubData, const uint8 *pubKey, uint32 cubKey, SHA256Digest_t *pOutputDigest ); + + static bool BGeneratePasswordHash( const char *pchInput, EPasswordHashAlg hashType, const Salt_t &Salt, PasswordHash_t &OutPasswordHash ); + static bool BValidatePasswordHash( const char *pchInput, EPasswordHashAlg hashType, const PasswordHash_t &DigestStored, const Salt_t &Salt, PasswordHash_t *pDigestComputed ); + static bool BGeneratePBKDF2Hash( const char *pchInput, const Salt_t &Salt, unsigned int rounds, PasswordHash_t &OutPasswordHash ); + static bool BGenerateWrappedSHA1PasswordHash( const char *pchInput, const Salt_t &Salt, unsigned int rounds, PasswordHash_t &OutPasswordHash ); + static bool BUpgradeOrWrapPasswordHash( PasswordHash_t &InPasswordHash, EPasswordHashAlg hashTypeIn, const Salt_t &Salt, PasswordHash_t &OutPasswordHash, EPasswordHashAlg &hashTypeOut ); + + static bool BGzipBuffer( const uint8 *pubData, uint32 cubData, CCryptoOutBuffer &bufOutput ); + static bool BGunzipBuffer( const uint8 *pubData, uint32 cubData, CCryptoOutBuffer &bufOutput ); + +#ifdef DBGFLAG_VALIDATE + static void ValidateStatics( CValidator &validator, const char *pchName ); +#endif +}; + +#else + +// bugbug ps3 - stub until we implement from PS3 libs +class CCrypto +{ +public: + // ps3 only + static bool Init(); + static void Shutdown(); + + //shared + static uint32 GetSymmetricEncryptedSize( uint32 cubPlaintextData ); + + static bool SymmetricEncrypt( const uint8 * pubPlaintextData, uint32 cubPlaintextData, uint8 * pubEncryptedData, uint32 * pcubEncryptedData, const uint8 * pubKey, uint32 cubKey ); + static bool SymmetricDecrypt( const uint8 * pubEncryptedData, uint32 cubEncryptedData, uint8 * pubPlaintextData, uint32 * pcubPlaintextData, const uint8 * pubKey, uint32 cubKey ); + static bool RSAGenerateKeys( uint8 *pubPublicKey, uint32 *pcubPublicKey, uint8 *pubPrivateKey, uint32 *pcubPrivateKey ) { AssertMsg( false, "RSAGenerateKeys not implemented on PS3" ); return false; } + static bool RSAEncrypt( const uint8 *pubPlaintextPlaintextData, const uint32 cubData, uint8 *pubEncryptedData, uint32 *pcubEncryptedData, const uint8 *pubPublicKey, const uint32 cubPublicKey ); + static bool RSADecrypt( const uint8 *pubEncryptedData, uint32 cubEncryptedData, uint8 *pubPlaintextData, uint32 *pcubPlaintextData, const uint8 *pubPrivateKey, const uint32 cubPrivateKey ); + static bool RSAPublicDecrypt_NoPadding( const uint8 *pubEncryptedData, uint32 cubEncryptedData, uint8 *pubPlaintextData, uint32 *pcubPlaintextData, const uint8 *pubPublicKey, const uint32 cubPublicKey ) { AssertMsg( false, "RSAPublicDecrypt_NoPadding not implemented on PS3" ); return false; } + static bool RSASign( const uint8 *pubData, const uint32 cubData, uint8 *pubSignature, uint32 *pcubSignature, const uint8 * pubPrivateKey, const uint32 cubPrivateKey ); + static bool RSAVerifySignature( const uint8 *pubData, const uint32 cubData, const uint8 *pubSignature, const uint32 cubSignature, const uint8 *pubPublicKey, const uint32 cubPublicKey ); + static bool HexEncode( const uint8 *pubData, const uint32 cubData, char *pchEncodedData, uint32 cchEncodedData ); + static bool HexDecode( const char *pchData, uint8 *pubDecodedData, uint32 *pcubDecodedData ); + static bool Base64Encode( const uint8 *pubData, const uint32 cubData, char *pchEncodedData, uint32 cchEncodedData, bool bInsertLineBreaks = true ) { AssertMsg( false, "Base64Encode not implemented on PS3" ); return false; } // cellHttpUtilBase64Encoder() + static bool Base64Decode( const char *pchData, uint8 *pubDecodedData, uint32 *pcubDecodedData, bool bIgnoreInvalidCharacters = true ) { AssertMsg( false, "Base64Decode not implemented on PS3" ); return false; } // cellHttpUtilBase64Decoder() + static bool GenerateSalt( Salt_t *pSalt ); + static bool GenerateSHA1Digest( const uint8 *pubInput, const int cubInput, SHADigest_t *pOutDigest ); + static bool GenerateSaltedSHA1Digest( const char *pchInput, const Salt_t *pSalt, SHADigest_t *pOutDigest ) { AssertMsg( false, "GenerateSaltedSHA1Digest not implemented on PS3" ); return false; } + static bool GenerateRandomBlock( uint8 *pubDest, int cubDest ); + static bool GenerateHMAC( const uint8 *pubData, uint32 cubData, const uint8 *pubKey, uint32 cubKey, SHADigest_t *pOutputDigest ) { AssertMsg( false, "GenerateHMAC not implemented on PS3" ); return false; } + static bool GenerateHMAC256( const uint8 *pubData, uint32 cubData, const uint8 *pubKey, uint32 cubKey, SHA256Digest_t *pOutputDigest ) { AssertMsg( false, "GenerateHMAC256 not implemented on PS3" ); return false; } + static bool BGzipBuffer( const uint8 *pubData, uint32 cubData, CCryptoOutBuffer &bufOutput ); + static bool BGunzipBuffer( const uint8 *pubData, uint32 cubData, CCryptoOutBuffer &bufOutput ); + +#ifdef DBGFLAG_VALIDATE + static void ValidateStatics( CValidator &validator, const char *pchName ); +#endif +}; + + +#endif //!_PS3 + + +class CSimpleBitString; + +//----------------------------------------------------------------------------- +// Purpose: Implement hex encoding / decoding using a custom lookup table. +// This is a class because the decoding is done via a generated +// reverse-lookup table, and to save time it's best to just create +// that table once. +//----------------------------------------------------------------------------- +class CCustomHexEncoder +{ +public: + CCustomHexEncoder( const char *pchEncodingTable ); + ~CCustomHexEncoder(); + + bool Encode( const uint8 *pubData, const uint32 cubData, char *pchEncodedData, uint32 cchEncodedData ); + bool Decode( const char *pchData, uint8 *pubDecodedData, uint32 *pcubDecodedData ); + +private: + bool m_bValidEncoding; + uint8 m_rgubEncodingTable[16]; + int m_rgnDecodingTable[256]; +}; + +//----------------------------------------------------------------------------- +// Purpose: Implement base32 encoding / decoding using a custom lookup table. +// This is a class because the decoding is done via a generated +// reverse-lookup table, and to save time it's best to just create +// that table once. +//----------------------------------------------------------------------------- +class CCustomBase32Encoder +{ +public: + CCustomBase32Encoder( const char *pchEncodingTable ); + ~CCustomBase32Encoder(); + + bool Encode( const uint8 *pubData, const uint32 cubData, char *pchEncodedData, uint32 cchEncodedData ); + bool Decode( const char *pchData, uint8 *pubDecodedData, uint32 *pcubDecodedData ); + + bool Encode( CSimpleBitString *pBitStringData, char *pchEncodedData, uint32 cchEncodedData ); + bool Decode( const char *pchData, CSimpleBitString *pBitStringDecodedData ); + +private: + bool m_bValidEncoding; + uint8 m_rgubEncodingTable[32]; + int m_rgnDecodingTable[256]; +}; + +#endif // CRYPTO_H |