botan: Add support for AES in ECB mode to support DRBG_CTR_AES
This DRBG is used to test ML-KEM.
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2024 Tobias Brunner
|
||||||
|
*
|
||||||
* Copyright (C) 2018 René Korthaus
|
* Copyright (C) 2018 René Korthaus
|
||||||
* Copyright (C) 2018 Konstantinos Kolelis
|
* Copyright (C) 2018 Konstantinos Kolelis
|
||||||
* Copyright (C) 2018 Tobias Hommel
|
* Copyright (C) 2018 Tobias Hommel
|
||||||
@@ -48,23 +50,86 @@ struct private_botan_crypter_t {
|
|||||||
*/
|
*/
|
||||||
chunk_t key;
|
chunk_t key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Algorithm identifier
|
||||||
|
*/
|
||||||
|
encryption_algorithm_t alg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The cipher name
|
* The cipher name
|
||||||
*/
|
*/
|
||||||
const char* cipher_name;
|
const char* cipher_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the actual en/decryption in ECB, which requires a separate "raw" API.
|
||||||
|
*/
|
||||||
|
static bool crypt_ecb(private_botan_crypter_t *this, uint8_t *in, uint8_t *out,
|
||||||
|
size_t len, uint32_t init_flag)
|
||||||
|
{
|
||||||
|
botan_block_cipher_t cipher;
|
||||||
|
size_t blocks = len / AES_BLOCK_SIZE;
|
||||||
|
bool success = FALSE;
|
||||||
|
|
||||||
|
if (len % AES_BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botan_block_cipher_init(&cipher, this->cipher_name) ||
|
||||||
|
botan_block_cipher_set_key(cipher, this->key.ptr, this->key.len))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init_flag == BOTAN_CIPHER_INIT_FLAG_ENCRYPT)
|
||||||
|
{
|
||||||
|
success = !botan_block_cipher_encrypt_blocks(cipher, in, out, blocks);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = !botan_block_cipher_decrypt_blocks(cipher, in, out, blocks);
|
||||||
|
}
|
||||||
|
botan_block_cipher_destroy(cipher);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the actual en/decryption for modes other than ECB.
|
||||||
|
*/
|
||||||
|
static bool crypt_modes(private_botan_crypter_t *this, chunk_t iv, uint8_t *in,
|
||||||
|
uint8_t *out, size_t len, uint32_t init_flag)
|
||||||
|
{
|
||||||
|
botan_cipher_t cipher;
|
||||||
|
size_t output_written = 0;
|
||||||
|
size_t input_consumed = 0;
|
||||||
|
bool success = FALSE;
|
||||||
|
|
||||||
|
if (botan_cipher_init(&cipher, this->cipher_name, init_flag))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!botan_cipher_set_key(cipher, this->key.ptr, this->key.len) &&
|
||||||
|
!botan_cipher_start(cipher, iv.ptr, iv.len) &&
|
||||||
|
!botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL, out,
|
||||||
|
len, &output_written, in, len, &input_consumed) &&
|
||||||
|
(output_written == input_consumed))
|
||||||
|
{
|
||||||
|
success = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
botan_cipher_destroy(cipher);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do the actual en/decryption
|
* Do the actual en/decryption
|
||||||
*/
|
*/
|
||||||
static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
|
static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
|
||||||
chunk_t *dst, uint32_t init_flag)
|
chunk_t *dst, uint32_t init_flag)
|
||||||
{
|
{
|
||||||
botan_cipher_t cipher;
|
|
||||||
size_t output_written = 0;
|
|
||||||
size_t input_consumed = 0;
|
|
||||||
uint8_t *in, *out;
|
uint8_t *in, *out;
|
||||||
bool success = FALSE;
|
|
||||||
|
|
||||||
in = data.ptr;
|
in = data.ptr;
|
||||||
if (dst)
|
if (dst)
|
||||||
@@ -77,23 +142,11 @@ static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
|
|||||||
out = data.ptr;
|
out = data.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (botan_cipher_init(&cipher, this->cipher_name, init_flag))
|
if (this->alg == ENCR_AES_ECB)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return crypt_ecb(this, in, out, data.len, init_flag);
|
||||||
}
|
}
|
||||||
|
return crypt_modes(this, iv, in, out, data.len, init_flag);
|
||||||
if (!botan_cipher_set_key(cipher, this->key.ptr, this->key.len) &&
|
|
||||||
!botan_cipher_start(cipher, iv.ptr, iv.len) &&
|
|
||||||
!botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL, out,
|
|
||||||
data.len, &output_written, in, data.len,
|
|
||||||
&input_consumed) &&
|
|
||||||
(output_written == input_consumed))
|
|
||||||
{
|
|
||||||
success = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
botan_cipher_destroy(cipher);
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(crypter_t, decrypt, bool,
|
METHOD(crypter_t, decrypt, bool,
|
||||||
@@ -102,7 +155,6 @@ METHOD(crypter_t, decrypt, bool,
|
|||||||
return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_DECRYPT);
|
return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_DECRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
METHOD(crypter_t, encrypt, bool,
|
METHOD(crypter_t, encrypt, bool,
|
||||||
private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
|
private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
|
||||||
{
|
{
|
||||||
@@ -118,7 +170,7 @@ METHOD(crypter_t, get_block_size, size_t,
|
|||||||
METHOD(crypter_t, get_iv_size, size_t,
|
METHOD(crypter_t, get_iv_size, size_t,
|
||||||
private_botan_crypter_t *this)
|
private_botan_crypter_t *this)
|
||||||
{
|
{
|
||||||
return AES_BLOCK_SIZE;
|
return this->alg == ENCR_AES_ECB ? 0 : AES_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(crypter_t, get_key_size, size_t,
|
METHOD(crypter_t, get_key_size, size_t,
|
||||||
@@ -161,10 +213,31 @@ botan_crypter_t *botan_crypter_create(encryption_algorithm_t algo,
|
|||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
.alg = algo,
|
||||||
);
|
);
|
||||||
|
|
||||||
switch (algo)
|
switch (algo)
|
||||||
{
|
{
|
||||||
|
case ENCR_AES_ECB:
|
||||||
|
switch (key_size)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
/* AES 128 */
|
||||||
|
this->cipher_name = "AES-128";
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
/* AES-192 */
|
||||||
|
this->cipher_name = "AES-192";
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
/* AES-256 */
|
||||||
|
this->cipher_name = "AES-256";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
free(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ENCR_AES_CBC:
|
case ENCR_AES_CBC:
|
||||||
switch (key_size)
|
switch (key_size)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -104,9 +104,11 @@ METHOD(plugin_t, get_features, int,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* crypters */
|
/* crypters */
|
||||||
#if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_MODE_CBC)
|
#if defined(BOTAN_HAS_AES)
|
||||||
PLUGIN_REGISTER(CRYPTER, botan_crypter_create),
|
PLUGIN_REGISTER(CRYPTER, botan_crypter_create),
|
||||||
#ifdef BOTAN_HAS_AES
|
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 16),
|
||||||
|
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 24),
|
||||||
|
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 32),
|
||||||
#ifdef BOTAN_HAS_MODE_CBC
|
#ifdef BOTAN_HAS_MODE_CBC
|
||||||
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 16),
|
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 16),
|
||||||
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24),
|
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24),
|
||||||
@@ -117,7 +119,6 @@ METHOD(plugin_t, get_features, int,
|
|||||||
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CFB, 24),
|
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CFB, 24),
|
||||||
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CFB, 32),
|
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CFB, 32),
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* AEAD */
|
/* AEAD */
|
||||||
|
|||||||
Reference in New Issue
Block a user