/*
+ * Copyright (C) 2024 Tobias Brunner
+ *
* Copyright (C) 2018 René Korthaus
* Copyright (C) 2018 Konstantinos Kolelis
* Copyright (C) 2018 Tobias Hommel
*/
chunk_t key;
+ /**
+ * Algorithm identifier
+ */
+ encryption_algorithm_t alg;
+
/**
* The cipher name
*/
};
/**
- * Do the actual en/decryption
+ * Do the actual en/decryption in ECB, which requires a separate "raw" API.
*/
-static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
- chunk_t *dst, uint32_t init_flag)
+static bool crypt_ecb(private_botan_crypter_t *this, 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;
- uint8_t *in, *out;
+ botan_block_cipher_t cipher;
+ size_t blocks = len / AES_BLOCK_SIZE;
bool success = FALSE;
- in = data.ptr;
- if (dst)
+ if (len % AES_BLOCK_SIZE)
{
- *dst = chunk_alloc(data.len);
- out = dst->ptr;
+ 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
{
- out = data.ptr;
+ 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))
{
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) &&
+ len, &output_written, in, len, &input_consumed) &&
(output_written == input_consumed))
{
success = TRUE;
return success;
}
+/**
+ * Do the actual en/decryption
+ */
+static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
+ chunk_t *dst, uint32_t init_flag)
+{
+ uint8_t *in, *out;
+
+ in = data.ptr;
+ if (dst)
+ {
+ *dst = chunk_alloc(data.len);
+ out = dst->ptr;
+ }
+ else
+ {
+ out = data.ptr;
+ }
+
+ if (this->alg == ENCR_AES_ECB)
+ {
+ return crypt_ecb(this, in, out, data.len, init_flag);
+ }
+ return crypt_modes(this, iv, in, out, data.len, init_flag);
+}
+
METHOD(crypter_t, decrypt, bool,
private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_DECRYPT);
}
-
METHOD(crypter_t, encrypt, bool,
private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
{
METHOD(crypter_t, get_iv_size, size_t,
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,
.destroy = _destroy,
},
},
+ .alg = 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:
switch (key_size)
{
#endif
/* crypters */
-#if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_MODE_CBC)
+#if defined(BOTAN_HAS_AES)
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
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CFB, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CFB, 32),
#endif
-#endif
#endif
/* AEAD */