uvg266/src/extras/crypto.cpp
Arttu Ylä-Outinen 4b24cd03a2 Update for crypto++ 6.0.0 compatibility
Changes the crypto module to use unsigned char instead of byte. The byte
typedef is no longer included in the global namespace in crypto++ 6.0.0.
See https://github.com/weidai11/cryptopp/issues/442.

Fixes #184.
2018-02-05 13:35:03 +02:00

141 lines
3.4 KiB
C++

#include <extras/crypto.h>
#ifndef KVZ_SEL_ENCRYPTION
int kvz_make_vs_ignore_crypto_not_having_symbols = 0;
#else
#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <cryptopp/osrng.h>
#if AESEncryptionStreamMode
typedef CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption cipher_t;
#else
typedef CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption cipher_t;
#endif
struct crypto_handle_t {
cipher_t *cipher;
unsigned char key[CryptoPP::AES::DEFAULT_KEYLENGTH];
unsigned char iv[CryptoPP::AES::BLOCKSIZE];
unsigned char out_stream_counter[CryptoPP::AES::BLOCKSIZE];
unsigned char counter[CryptoPP::AES::BLOCKSIZE];
int couter_avail;
int counter_index;
int counter_index_pos;
};
static uint8_t default_IV[16] = {201, 75, 219, 152, 6, 245, 237, 107, 179, 194, 81, 29, 66, 98, 198, 0};
static uint8_t default_key[16] = {16, 213, 27, 56, 255, 127, 242, 112, 97, 126, 197, 204, 25, 59, 38, 30};
crypto_handle_t* kvz_crypto_create(const kvz_config *cfg)
{
crypto_handle_t* hdl = (crypto_handle_t*)calloc(1, sizeof(crypto_handle_t));
uint8_t *key;
if(cfg->optional_key!=NULL)
key = cfg->optional_key;
else
key = default_key;
for (int i = 0; i < 16; i++) {
hdl->iv [i] = default_IV[i];
hdl->counter[i] = (i<11)? default_IV[5+i] : key[i-11];
hdl->key[i] = key[i];
}
hdl->cipher = new cipher_t(hdl->key, CryptoPP::AES::DEFAULT_KEYLENGTH, hdl->iv);
hdl->couter_avail = 0;
hdl->counter_index = 0;
hdl->counter_index_pos = 0;
return hdl;
}
void kvz_crypto_delete(crypto_handle_t **hdl)
{
if (*hdl) {
delete (*hdl)->cipher;
(*hdl)->cipher = NULL;
}
FREE_POINTER(*hdl);
}
void kvz_crypto_decrypt(crypto_handle_t* hdl,
const uint8_t *in_stream,
int size_bits,
uint8_t *out_stream)
{
int num_bytes = ceil((double)size_bits/8);
hdl->cipher->ProcessData(out_stream, in_stream, num_bytes);
if (size_bits & 7) {
hdl->cipher->SetKeyWithIV(hdl->key, CryptoPP::AES::DEFAULT_KEYLENGTH, hdl->iv);
}
}
#if AESEncryptionStreamMode
static void increment_counter(unsigned char *counter)
{
counter[0]++;
}
static void decrypt_counter(crypto_handle_t *hdl)
{
hdl->cipher->ProcessData(hdl->out_stream_counter, hdl->counter, 16);
hdl->couter_avail = 128;
hdl->counter_index = 15;
hdl->counter_index_pos = 8;
increment_counter(hdl->counter);
}
unsigned kvz_crypto_get_key(crypto_handle_t *hdl, int nb_bits)
{
unsigned key = 0;
if (nb_bits > 32) {
fprintf(stderr, "The generator cannot generate %d bits (max 32 bits)\n", nb_bits);
return 0;
}
if (nb_bits == 0) return 0;
if (!hdl->couter_avail) {
decrypt_counter(hdl);
}
if(hdl->couter_avail >= nb_bits) {
hdl->couter_avail -= nb_bits;
} else {
hdl->couter_avail = 0;
}
int nb = 0;
while (nb_bits) {
if (nb_bits >= hdl->counter_index_pos) {
nb = hdl->counter_index_pos;
} else {
nb = nb_bits;
}
key <<= nb;
key += hdl->out_stream_counter[hdl->counter_index] & ((1 << nb) - 1);
hdl->out_stream_counter[hdl->counter_index] >>= nb;
nb_bits -= nb;
if (hdl->counter_index && nb == hdl->counter_index_pos) {
hdl->counter_index--;
hdl->counter_index_pos = 8;
} else {
hdl->counter_index_pos -= nb;
if (nb_bits) {
decrypt_counter(hdl);
hdl->couter_avail -= nb_bits;
}
}
}
return key;
}
#endif // AESEncryptionStreamMode
#endif // KVZ_SEL_ENCRYPTION