]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
botan: Add support for AES in ECB mode to support DRBG_CTR_AES
authorTobias Brunner <tobias@strongswan.org>
Wed, 23 Oct 2024 15:14:56 +0000 (17:14 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 22 Nov 2024 13:03:17 +0000 (14:03 +0100)
This DRBG is used to test ML-KEM.

src/libstrongswan/plugins/botan/botan_crypter.c
src/libstrongswan/plugins/botan/botan_plugin.c

index d3ccb4bb9b03dc9d4974c26115835320095ecc8a..708c7727ad32e96e66c8b65844c449ca425184b8 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2024 Tobias Brunner
+ *
  * Copyright (C) 2018 RenĂ© Korthaus
  * Copyright (C) 2018 Konstantinos Kolelis
  * Copyright (C) 2018 Tobias Hommel
@@ -48,6 +50,11 @@ struct private_botan_crypter_t {
         */
        chunk_t key;
 
+       /**
+        * Algorithm identifier
+        */
+       encryption_algorithm_t alg;
+
        /**
         * The cipher name
         */
@@ -55,27 +62,48 @@ struct private_botan_crypter_t {
 };
 
 /**
- * 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))
        {
@@ -85,8 +113,7 @@ static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
        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;
@@ -96,13 +123,38 @@ static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv,
        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)
 {
@@ -118,7 +170,7 @@ METHOD(crypter_t, get_block_size, size_t,
 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,
@@ -161,10 +213,31 @@ botan_crypter_t *botan_crypter_create(encryption_algorithm_t algo,
                                .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)
                        {
index 3fe32976581684c228024924288fdd8bf825d725..30a6dcce68e5166aa48d17099079cc5b0c6766f4 100644 (file)
@@ -104,9 +104,11 @@ METHOD(plugin_t, get_features, int,
 #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),
@@ -117,7 +119,6 @@ METHOD(plugin_t, get_features, int,
                        PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CFB, 24),
                        PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CFB, 32),
        #endif
-#endif
 #endif
 
                /* AEAD */