216 lines
7.6 KiB
C++
216 lines
7.6 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
#ifndef CRYINCLUDE_CRYCOMMON_ICRYPTO_H
|
|
#define CRYINCLUDE_CRYCOMMON_ICRYPTO_H
|
|
#pragma once
|
|
|
|
#include "ISerialize.h"
|
|
|
|
typedef void* TCipher;
|
|
|
|
class IRijndael;
|
|
class IStreamCipher;
|
|
|
|
struct StreamCipherState
|
|
{
|
|
uint8 m_StartS[256];
|
|
uint8 m_S[256];
|
|
int m_StartI;
|
|
int m_I;
|
|
int m_StartJ;
|
|
int m_J;
|
|
};
|
|
|
|
class ICrypto
|
|
{
|
|
public:
|
|
//Need an empty virtual destructor to address a compiler error with GCC which doesn't allow delete to be called on incomplete types
|
|
virtual ~ICrypto() {};
|
|
|
|
// Exposed block encryption
|
|
virtual void EncryptBuffer(uint8* pOutput, const uint8* pInput, uint32 bufferLength, const uint8* pKey, uint32 keyLength) = 0;
|
|
virtual void DecryptBuffer(uint8* pOutput, const uint8* pInput, uint32 bufferLength, const uint8* pKey, uint32 keyLength) = 0;
|
|
|
|
// Crypto implementations
|
|
virtual IRijndael* GetRijndael() = 0;
|
|
virtual IStreamCipher* GetStreamCipher() = 0;
|
|
|
|
virtual void InitWhirlpoolHash(uint8* hash) = 0;
|
|
virtual void InitWhirlpoolHash(uint8* hash, const string& str) = 0;
|
|
virtual void InitWhirlpoolHash(uint8* hash, const uint8* input, size_t length) = 0;
|
|
};
|
|
|
|
#define _MAX_KEY_COLUMNS (256 / 32)
|
|
#define _MAX_ROUNDS 14
|
|
#define MAX_IV_SIZE 16
|
|
|
|
// Error codes
|
|
#define RIJNDAEL_SUCCESS 0
|
|
#define RIJNDAEL_UNSUPPORTED_MODE -1
|
|
#define RIJNDAEL_UNSUPPORTED_DIRECTION -2
|
|
#define RIJNDAEL_UNSUPPORTED_KEY_LENGTH -3
|
|
#define RIJNDAEL_BAD_KEY -4
|
|
#define RIJNDAEL_NOT_INITIALIZED -5
|
|
#define RIJNDAEL_BAD_DIRECTION -6
|
|
#define RIJNDAEL_CORRUPTED_DATA -7
|
|
|
|
enum class RijndaelDirection
|
|
{
|
|
Encrypt, Decrypt
|
|
};
|
|
enum class RijndaelMode
|
|
{
|
|
ECB, CBC, CFB1
|
|
};
|
|
enum class RijndaelKeyLength
|
|
{
|
|
Key16Bytes, Key24Bytes, Key32Bytes
|
|
};
|
|
|
|
struct RijndaelState
|
|
{
|
|
enum State
|
|
{
|
|
Valid, Invalid
|
|
};
|
|
|
|
State m_state;
|
|
RijndaelMode m_mode;
|
|
RijndaelDirection m_direction;
|
|
uint8 m_initVector[MAX_IV_SIZE];
|
|
uint32 m_uRounds;
|
|
uint8 m_expandedKey[_MAX_ROUNDS + 1][4][4];
|
|
};
|
|
|
|
class IRijndael
|
|
{
|
|
public:
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// API
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// init(): Initializes the crypt session
|
|
// Returns RIJNDAEL_SUCCESS or an error code
|
|
// mode : Rijndael::ECB, Rijndael::CBC or Rijndael::CFB1
|
|
// You have to use the same mode for encrypting and decrypting
|
|
// dir : Rijndael::Encrypt or Rijndael::Decrypt
|
|
// A cipher instance works only in one direction
|
|
// (Well , it could be easily modified to work in both
|
|
// directions with a single init() call, but it looks
|
|
// useless to me...anyway , it is a matter of generating
|
|
// two expanded keys)
|
|
// key : array of unsigned octets , it can be 16 , 24 or 32 bytes long
|
|
// this CAN be binary data (it is not expected to be null terminated)
|
|
// keyLen : Rijndael::Key16Bytes , Rijndael::Key24Bytes or Rijndael::Key32Bytes
|
|
// initVector: initialization vector, you will usually use 0 here
|
|
virtual int init(RijndaelState& state, RijndaelMode mode, RijndaelDirection dir, const uint8* key, RijndaelKeyLength keyLen, uint8* initVector = 0) = 0;
|
|
// Encrypts the input array (can be binary data)
|
|
// The input array length must be a multiple of 16 bytes, the remaining part
|
|
// is DISCARDED.
|
|
// so it actually encrypts inputLen / 128 blocks of input and puts it in outBuffer
|
|
// Input len is in BITS!
|
|
// outBuffer must be at least inputLen / 8 bytes long.
|
|
// Returns the encrypted buffer length in BITS or an error code < 0 in case of error
|
|
virtual int blockEncrypt(RijndaelState& state, const uint8* input, int inputLen, uint8* outBuffer) = 0;
|
|
// Encrypts the input array (can be binary data)
|
|
// The input array can be any length , it is automatically padded on a 16 byte boundary.
|
|
// Input len is in BYTES!
|
|
// outBuffer must be at least (inputLen + 16) bytes long
|
|
// Returns the encrypted buffer length in BYTES or an error code < 0 in case of error
|
|
virtual int padEncrypt(RijndaelState& state, const uint8* input, int inputOctets, uint8* outBuffer) = 0;
|
|
// Decrypts the input vector
|
|
// Input len is in BITS!
|
|
// outBuffer must be at least inputLen / 8 bytes long
|
|
// Returns the decrypted buffer length in BITS and an error code < 0 in case of error
|
|
virtual int blockDecrypt(RijndaelState& state, const uint8* input, int inputLen, uint8* outBuffer) = 0;
|
|
// Decrypts the input vector
|
|
// Input len is in BYTES!
|
|
// outBuffer must be at least inputLen bytes long
|
|
// Returns the decrypted buffer length in BYTES and an error code < 0 in case of error
|
|
virtual int padDecrypt(RijndaelState& state, const uint8* input, int inputOctets, uint8* outBuffer) = 0;
|
|
};
|
|
|
|
class IStreamCipher
|
|
{
|
|
public:
|
|
virtual StreamCipherState BeginCipher(const uint8* pKey, uint32 keyLength) = 0;
|
|
virtual void Init(StreamCipherState& state, const uint8* key, int keyLen) = 0;
|
|
virtual void Encrypt(StreamCipherState& state, const uint8* input, int inputLen, uint8* output) = 0;
|
|
virtual void Decrypt(StreamCipherState& state, const uint8* input, int inputLen, uint8* output) = 0;
|
|
virtual void EncryptStream(StreamCipherState& state, const uint8* input, int inputLen, uint8* output) = 0;
|
|
virtual void DecryptStream(StreamCipherState& state, const uint8* input, int inputLen, uint8* output) = 0;
|
|
};
|
|
|
|
class CWhirlpoolHash
|
|
{
|
|
public:
|
|
static const int DIGESTBYTES = 64;
|
|
static const int STRING_SIZE = DIGESTBYTES * 2 + 1;
|
|
|
|
ILINE CWhirlpoolHash()
|
|
{
|
|
gEnv->pSystem->GetCrypto()->InitWhirlpoolHash(m_hash);
|
|
}
|
|
|
|
ILINE CWhirlpoolHash(const string& str)
|
|
{
|
|
gEnv->pSystem->GetCrypto()->InitWhirlpoolHash(m_hash, str);
|
|
}
|
|
|
|
ILINE CWhirlpoolHash(const uint8* input, size_t length)
|
|
{
|
|
gEnv->pSystem->GetCrypto()->InitWhirlpoolHash(m_hash, input, length);
|
|
}
|
|
|
|
ILINE CryFixedStringT<STRING_SIZE> GetHumanReadable() const
|
|
{
|
|
static const char* hexchars = "0123456789ABCDEF";
|
|
CRY_ASSERT(strlen(hexchars) == 16);
|
|
|
|
char buffer[DIGESTBYTES * 2 + 1];
|
|
for (int i = 0; i < DIGESTBYTES; i++)
|
|
{
|
|
buffer[2 * i + 0] = hexchars[m_hash[i] >> 4];
|
|
buffer[2 * i + 1] = hexchars[m_hash[i] & 15];
|
|
}
|
|
buffer[DIGESTBYTES * 2] = 0;
|
|
return buffer;
|
|
}
|
|
|
|
ILINE void SerializeWith(TSerialize ser)
|
|
{
|
|
for (int i = 0; i < DIGESTBYTES; i++)
|
|
{
|
|
char name[] = {'w', 'p', 0, 0, 0};
|
|
sprintf_s(name + 2, sizeof(name), "%.2i", i);
|
|
ser.Value(name, m_hash[i]);
|
|
}
|
|
}
|
|
|
|
ILINE bool operator==(const CWhirlpoolHash& rhs) const
|
|
{
|
|
return 0 == memcmp(m_hash, rhs.m_hash, DIGESTBYTES);
|
|
}
|
|
|
|
ILINE bool operator!=(const CWhirlpoolHash& rhs) const
|
|
{
|
|
return !this->operator==(rhs);
|
|
}
|
|
|
|
const uint8* operator()() const { return m_hash; }
|
|
|
|
private:
|
|
uint8 m_hash[DIGESTBYTES];
|
|
};
|
|
|
|
#endif // CRYINCLUDE_CRYCOMMON_ICRYPTO_H
|