|
@ -15,317 +15,69 @@ |
|
|
static const int CRYPT_ENCRYPT = 1; |
|
|
static const int CRYPT_ENCRYPT = 1; |
|
|
static const int CRYPT_DECRYPT = 0; |
|
|
static const int CRYPT_DECRYPT = 0; |
|
|
|
|
|
|
|
|
class Encrypter { |
|
|
|
|
|
public: |
|
|
|
|
|
virtual ~Encrypter() {} |
|
|
|
|
|
|
|
|
|
|
|
virtual Crypt_result Encrypt(const uchar* plaintext, |
|
|
|
|
|
int plaintext_size, |
|
|
|
|
|
uchar* ciphertext, |
|
|
|
|
|
int* ciphertext_used) = 0; |
|
|
|
|
|
virtual Crypt_result GetTag(uchar* tag, int tag_size) = 0; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class Decrypter { |
|
|
|
|
|
public: |
|
|
|
|
|
virtual ~Decrypter() {} |
|
|
|
|
|
|
|
|
|
|
|
virtual Crypt_result SetTag(const uchar* tag, int tag_size) = 0; |
|
|
|
|
|
virtual Crypt_result Decrypt(const uchar* ciphertext, |
|
|
|
|
|
int ciphertext_size, |
|
|
|
|
|
uchar* plaintext, |
|
|
|
|
|
int* plaintext_used) = 0; |
|
|
|
|
|
virtual Crypt_result CheckTag() = 0; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class Crypto { |
|
|
|
|
|
public: |
|
|
|
|
|
virtual ~Crypto(); |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result Crypt(const uchar* input, int input_size, |
|
|
|
|
|
uchar* output, int* output_used); |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
Crypto(); |
|
|
|
|
|
|
|
|
C_MODE_START |
|
|
|
|
|
|
|
|
|
|
|
static int do_crypt(const EVP_CIPHER *cipher, int mode, |
|
|
|
|
|
const uchar* source, uint32 source_length, |
|
|
|
|
|
uchar* dest, uint32* dest_length, |
|
|
|
|
|
const unsigned char* key, uint8 key_length, |
|
|
|
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
|
|
|
uint noPadding) |
|
|
|
|
|
{ |
|
|
|
|
|
int res= AES_OPENSSL_ERROR; |
|
|
EVP_CIPHER_CTX ctx; |
|
|
EVP_CIPHER_CTX ctx; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Various crypto implementations */ |
|
|
|
|
|
|
|
|
|
|
|
class Aes128CtrCrypto : public Crypto { |
|
|
|
|
|
public: |
|
|
|
|
|
virtual Crypt_result Init(const uchar* key, const uchar* iv, |
|
|
|
|
|
int iv_size); |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
Aes128CtrCrypto() {} |
|
|
|
|
|
|
|
|
|
|
|
virtual int mode() = 0; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class Aes128CtrEncrypter : public Aes128CtrCrypto, public Encrypter { |
|
|
|
|
|
public: |
|
|
|
|
|
Aes128CtrEncrypter() {} |
|
|
|
|
|
virtual Crypt_result Encrypt(const uchar* plaintext, |
|
|
|
|
|
int plaintext_size, |
|
|
|
|
|
uchar* ciphertext, |
|
|
|
|
|
int* ciphertext_used); |
|
|
|
|
|
|
|
|
|
|
|
virtual Crypt_result GetTag(uchar* tag, int tag_size) { |
|
|
|
|
|
DBUG_ASSERT(false); |
|
|
|
|
|
return AES_INVALID; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
virtual int mode() { |
|
|
|
|
|
return CRYPT_ENCRYPT; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
Aes128CtrEncrypter(const Aes128CtrEncrypter& o); |
|
|
|
|
|
Aes128CtrEncrypter& operator=(const Aes128CtrEncrypter& o); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class Aes128CtrDecrypter : public Aes128CtrCrypto, public Decrypter { |
|
|
|
|
|
public: |
|
|
|
|
|
Aes128CtrDecrypter() {} |
|
|
|
|
|
virtual Crypt_result Decrypt(const uchar* ciphertext, |
|
|
|
|
|
int ciphertext_size, |
|
|
|
|
|
uchar* plaintext, |
|
|
|
|
|
int* plaintext_used); |
|
|
|
|
|
|
|
|
|
|
|
virtual Crypt_result SetTag(const uchar* tag, int tag_size) { |
|
|
|
|
|
DBUG_ASSERT(false); |
|
|
|
|
|
return AES_INVALID; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
virtual Crypt_result CheckTag() { |
|
|
|
|
|
DBUG_ASSERT(false); |
|
|
|
|
|
return AES_INVALID; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
virtual int mode() { |
|
|
|
|
|
return CRYPT_DECRYPT; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
Aes128CtrDecrypter(const Aes128CtrDecrypter& o); |
|
|
|
|
|
Aes128CtrDecrypter& operator=(const Aes128CtrDecrypter& o); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class Aes128EcbCrypto : public Crypto { |
|
|
|
|
|
public: |
|
|
|
|
|
virtual Crypt_result Init(const unsigned char* key); |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
Aes128EcbCrypto() {} |
|
|
|
|
|
|
|
|
|
|
|
virtual int mode() = 0; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class Aes128EcbEncrypter : public Aes128EcbCrypto, public Encrypter { |
|
|
|
|
|
public: |
|
|
|
|
|
Aes128EcbEncrypter() {} |
|
|
|
|
|
virtual Crypt_result Encrypt(const unsigned char* plaintext, |
|
|
|
|
|
int plaintext_size, |
|
|
|
|
|
unsigned char* ciphertext, |
|
|
|
|
|
int* ciphertext_used); |
|
|
|
|
|
|
|
|
|
|
|
virtual Crypt_result GetTag(unsigned char* tag, int tag_size) { |
|
|
|
|
|
DBUG_ASSERT(false); |
|
|
|
|
|
return AES_INVALID; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
virtual int mode() { |
|
|
|
|
|
return CRYPT_ENCRYPT; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
Aes128EcbEncrypter(const Aes128EcbEncrypter& o); |
|
|
|
|
|
Aes128EcbEncrypter& operator=(const Aes128EcbEncrypter& o); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class Aes128EcbDecrypter : public Aes128EcbCrypto, public Decrypter { |
|
|
|
|
|
public: |
|
|
|
|
|
Aes128EcbDecrypter() {} |
|
|
|
|
|
virtual Crypt_result Decrypt(const unsigned char* ciphertext, |
|
|
|
|
|
int ciphertext_size, |
|
|
|
|
|
unsigned char* plaintext, |
|
|
|
|
|
int* plaintext_used); |
|
|
|
|
|
|
|
|
|
|
|
virtual Crypt_result SetTag(const unsigned char* tag, int tag_size) { |
|
|
|
|
|
DBUG_ASSERT(false); |
|
|
|
|
|
return AES_INVALID; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
virtual Crypt_result CheckTag() { |
|
|
|
|
|
DBUG_ASSERT(false); |
|
|
|
|
|
return AES_INVALID; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
virtual int mode() { |
|
|
|
|
|
return CRYPT_DECRYPT; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
Aes128EcbDecrypter(const Aes128EcbDecrypter& o); |
|
|
|
|
|
Aes128EcbDecrypter& operator=(const Aes128EcbDecrypter& o); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Crypto::~Crypto() { |
|
|
|
|
|
EVP_CIPHER_CTX_cleanup(&ctx); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Crypto::Crypto() { |
|
|
|
|
|
EVP_CIPHER_CTX_init(&ctx); |
|
|
EVP_CIPHER_CTX_init(&ctx); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
WARNING: It is allowed to have output == NULL, for special cases like AAD |
|
|
|
|
|
support in AES GCM. output_used however must never be NULL. |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result Crypto::Crypt(const uchar* input, int input_size, |
|
|
|
|
|
uchar* output, int* output_used) { |
|
|
|
|
|
DBUG_ASSERT(input != NULL); |
|
|
|
|
|
DBUG_ASSERT(output_used != NULL); |
|
|
|
|
|
if (!EVP_CipherUpdate(&ctx, output, output_used, input, input_size)) { |
|
|
|
|
|
return AES_OPENSSL_ERROR; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return AES_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result Aes128CtrCrypto::Init(const uchar* key, |
|
|
|
|
|
const uchar* iv, |
|
|
|
|
|
int iv_size) { |
|
|
|
|
|
if (iv_size != 16) { |
|
|
|
|
|
DBUG_ASSERT(false); |
|
|
|
|
|
return AES_BAD_IV; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!EVP_CipherInit_ex(&ctx, EVP_aes_128_ctr(), NULL, key, iv, mode())) { |
|
|
|
|
|
return AES_OPENSSL_ERROR; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return AES_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result Aes128CtrEncrypter::Encrypt(const uchar* plaintext, |
|
|
|
|
|
int plaintext_size, |
|
|
|
|
|
uchar* ciphertext, |
|
|
|
|
|
int* ciphertext_used) { |
|
|
|
|
|
Crypt_result res = Crypt(plaintext, plaintext_size, ciphertext, |
|
|
|
|
|
ciphertext_used); |
|
|
|
|
|
DBUG_ASSERT(*ciphertext_used == plaintext_size); |
|
|
|
|
|
return res; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result Aes128CtrDecrypter::Decrypt(const uchar* ciphertext, |
|
|
|
|
|
int ciphertext_size, |
|
|
|
|
|
uchar* plaintext, |
|
|
|
|
|
int* plaintext_used) { |
|
|
|
|
|
Crypt_result res = Crypt(ciphertext, ciphertext_size, plaintext, |
|
|
|
|
|
plaintext_used); |
|
|
|
|
|
DBUG_ASSERT(*plaintext_used == ciphertext_size); |
|
|
|
|
|
return res; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Crypt_result Aes128EcbCrypto::Init(const unsigned char* key) { |
|
|
|
|
|
if (!EVP_CipherInit_ex(&ctx, EVP_aes_128_ecb(), NULL, key, NULL, mode())) { |
|
|
|
|
|
return AES_OPENSSL_ERROR; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return AES_OK; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result Aes128EcbEncrypter::Encrypt(const unsigned char* plaintext, |
|
|
|
|
|
int plaintext_size, |
|
|
|
|
|
unsigned char* ciphertext, |
|
|
|
|
|
int* ciphertext_used) { |
|
|
|
|
|
Crypt_result res = Crypt(plaintext, plaintext_size, |
|
|
|
|
|
ciphertext, ciphertext_used); |
|
|
|
|
|
DBUG_ASSERT(*ciphertext_used == plaintext_size); |
|
|
|
|
|
return res; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result Aes128EcbDecrypter::Decrypt(const unsigned char* ciphertext, |
|
|
|
|
|
int ciphertext_size, |
|
|
|
|
|
unsigned char* plaintext, |
|
|
|
|
|
int* plaintext_used) { |
|
|
|
|
|
Crypt_result res = Crypt(ciphertext, ciphertext_size, |
|
|
|
|
|
plaintext, plaintext_used); |
|
|
|
|
|
DBUG_ASSERT(*plaintext_used == ciphertext_size); |
|
|
|
|
|
|
|
|
if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, mode)) |
|
|
|
|
|
goto err; |
|
|
|
|
|
if (!EVP_CipherUpdate(&ctx, dest, (int*)dest_length, source, source_length)) |
|
|
|
|
|
goto err; |
|
|
|
|
|
res= AES_OK; |
|
|
|
|
|
err: |
|
|
|
|
|
EVP_CIPHER_CTX_cleanup(&ctx); |
|
|
return res; |
|
|
return res; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
C_MODE_START |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Encrypt and decrypt according to Aes128Ctr */ |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result my_aes_encrypt_ctr(const uchar* source, uint32 source_length, |
|
|
|
|
|
|
|
|
int my_aes_encrypt_ctr(const uchar* source, uint32 source_length, |
|
|
uchar* dest, uint32* dest_length, |
|
|
uchar* dest, uint32* dest_length, |
|
|
const unsigned char* key, uint8 key_length, |
|
|
const unsigned char* key, uint8 key_length, |
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
uint noPadding) |
|
|
uint noPadding) |
|
|
{ |
|
|
{ |
|
|
Aes128CtrEncrypter encrypter; |
|
|
|
|
|
Crypt_result res = encrypter.Init(key, iv, iv_length); |
|
|
|
|
|
if (res != AES_OK) |
|
|
|
|
|
return res; |
|
|
|
|
|
return encrypter.Encrypt(source, source_length, dest, (int*)dest_length); |
|
|
|
|
|
|
|
|
return do_crypt(EVP_aes_128_ctr(), CRYPT_ENCRYPT, source, source_length, |
|
|
|
|
|
dest, dest_length, key, key_length, iv, iv_length, noPadding); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Crypt_result my_aes_decrypt_ctr(const uchar* source, uint32 source_length, |
|
|
|
|
|
|
|
|
int my_aes_decrypt_ctr(const uchar* source, uint32 source_length, |
|
|
uchar* dest, uint32* dest_length, |
|
|
uchar* dest, uint32* dest_length, |
|
|
const unsigned char* key, uint8 key_length, |
|
|
const unsigned char* key, uint8 key_length, |
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
uint noPadding) |
|
|
uint noPadding) |
|
|
{ |
|
|
{ |
|
|
Aes128CtrDecrypter decrypter; |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result res = decrypter.Init(key, iv, iv_length); |
|
|
|
|
|
if (res != AES_OK) |
|
|
|
|
|
return res; |
|
|
|
|
|
return decrypter.Decrypt(source, source_length, dest, (int*)dest_length); |
|
|
|
|
|
|
|
|
return do_crypt(EVP_aes_128_ctr(), CRYPT_DECRYPT, source, source_length, |
|
|
|
|
|
dest, dest_length, key, key_length, iv, iv_length, noPadding); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Crypt_result my_aes_encrypt_ecb(const uchar* source, uint32 source_length, |
|
|
|
|
|
|
|
|
int my_aes_encrypt_ecb(const uchar* source, uint32 source_length, |
|
|
uchar* dest, uint32* dest_length, |
|
|
uchar* dest, uint32* dest_length, |
|
|
const unsigned char* key, uint8 key_length, |
|
|
const unsigned char* key, uint8 key_length, |
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
uint noPadding) |
|
|
uint noPadding) |
|
|
{ |
|
|
{ |
|
|
Aes128EcbEncrypter encrypter; |
|
|
|
|
|
Crypt_result res = encrypter.Init(key); |
|
|
|
|
|
if (res != AES_OK) |
|
|
|
|
|
return res; |
|
|
|
|
|
return encrypter.Encrypt(source, source_length, dest, (int*)dest_length); |
|
|
|
|
|
|
|
|
return do_crypt(EVP_aes_128_ecb(), CRYPT_ENCRYPT, source, source_length, |
|
|
|
|
|
dest, dest_length, key, key_length, iv, iv_length, noPadding); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Crypt_result my_aes_decrypt_ecb(const uchar* source, uint32 source_length, |
|
|
|
|
|
|
|
|
int my_aes_decrypt_ecb(const uchar* source, uint32 source_length, |
|
|
uchar* dest, uint32* dest_length, |
|
|
uchar* dest, uint32* dest_length, |
|
|
const unsigned char* key, uint8 key_length, |
|
|
const unsigned char* key, uint8 key_length, |
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
const unsigned char* iv, uint8 iv_length, |
|
|
uint noPadding) |
|
|
uint noPadding) |
|
|
{ |
|
|
{ |
|
|
Aes128EcbDecrypter decrypter; |
|
|
|
|
|
|
|
|
|
|
|
Crypt_result res = decrypter.Init(key); |
|
|
|
|
|
|
|
|
|
|
|
if (res != AES_OK) |
|
|
|
|
|
return res; |
|
|
|
|
|
return decrypter.Decrypt(source, source_length, dest, (int*)dest_length); |
|
|
|
|
|
|
|
|
return do_crypt(EVP_aes_128_ecb(), CRYPT_DECRYPT, source, source_length, |
|
|
|
|
|
dest, dest_length, key, key_length, iv, iv_length, noPadding); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
C_MODE_END |
|
|
C_MODE_END |
|
@ -338,7 +90,7 @@ C_MODE_END |
|
|
|
|
|
|
|
|
C_MODE_START |
|
|
C_MODE_START |
|
|
|
|
|
|
|
|
Crypt_result my_random_bytes(uchar* buf, int num) |
|
|
|
|
|
|
|
|
int my_random_bytes(uchar* buf, int num) |
|
|
{ |
|
|
{ |
|
|
TaoCrypt::RandomNumberGenerator rand; |
|
|
TaoCrypt::RandomNumberGenerator rand; |
|
|
rand.GenerateBlock((TaoCrypt::byte*) buf, num); |
|
|
rand.GenerateBlock((TaoCrypt::byte*) buf, num); |
|
@ -353,7 +105,7 @@ C_MODE_END |
|
|
|
|
|
|
|
|
C_MODE_START |
|
|
C_MODE_START |
|
|
|
|
|
|
|
|
Crypt_result my_random_bytes(uchar* buf, int num) |
|
|
|
|
|
|
|
|
int my_random_bytes(uchar* buf, int num) |
|
|
{ |
|
|
{ |
|
|
/*
|
|
|
/*
|
|
|
Unfortunately RAND_bytes manual page does not provide any guarantees |
|
|
Unfortunately RAND_bytes manual page does not provide any guarantees |
|
|