From: Tobias Brunner Date: Tue, 23 Oct 2018 10:19:46 +0000 (+0200) Subject: botan: Add support for AES-CCM X-Git-Tag: 5.7.2dr1~7^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3f960e38a168668e84442bccd3c8f481a1bd9f58;p=thirdparty%2Fstrongswan.git botan: Add support for AES-CCM --- diff --git a/src/libstrongswan/plugins/botan/botan_aead.c b/src/libstrongswan/plugins/botan/botan_aead.c index 16676bde5b..40006ae77e 100644 --- a/src/libstrongswan/plugins/botan/botan_aead.c +++ b/src/libstrongswan/plugins/botan/botan_aead.c @@ -28,7 +28,8 @@ #include -#if (defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_AEAD_GCM)) || \ +#if (defined(BOTAN_HAS_AES) && \ + (defined(BOTAN_HAS_AEAD_GCM) || defined(BOTAN_HAS_AEAD_CCM))) || \ defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) #include @@ -40,8 +41,11 @@ */ #define IV_LEN 8 #define SALT_LEN 4 -#define NONCE_LEN (IV_LEN + SALT_LEN) #define CHAPOLY_KEY_LEN 32 +/** + * As defined in RFC 4309 + */ +#define CCM_SALT_LEN 3 typedef struct private_aead_t private_aead_t; @@ -60,7 +64,7 @@ struct private_aead_t { /** * Salt value */ - char salt[SALT_LEN]; + chunk_t salt; /** * Size of the integrity check value @@ -85,11 +89,8 @@ static bool do_crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, u_char *out, uint32_t init_flag) { botan_cipher_t cipher; - uint8_t nonce[NONCE_LEN]; size_t output_written = 0, input_consumed = 0; - - memcpy(nonce, this->salt, SALT_LEN); - memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN); + chunk_t nonce; if (botan_cipher_init(&cipher, this->cipher_name, init_flag)) { @@ -109,7 +110,9 @@ static bool do_crypt(private_aead_t *this, chunk_t data, chunk_t assoc, return FALSE; } - if (botan_cipher_start(cipher, nonce, NONCE_LEN)) + nonce = chunk_cata("cc", this->salt, iv); + + if (botan_cipher_start(cipher, nonce.ptr, nonce.len)) { botan_cipher_destroy(cipher); return FALSE; @@ -206,7 +209,7 @@ METHOD(aead_t, get_iv_gen, iv_gen_t*, METHOD(aead_t, get_key_size, size_t, private_aead_t *this) { - return this->key.len + SALT_LEN; + return this->key.len + this->salt.len; } METHOD(aead_t, set_key, bool, @@ -216,7 +219,7 @@ METHOD(aead_t, set_key, bool, { return FALSE; } - memcpy(this->salt, key.ptr + key.len - SALT_LEN, SALT_LEN); + memcpy(this->salt.ptr, key.ptr + key.len - this->salt.len, this->salt.len); memcpy(this->key.ptr, key.ptr, this->key.len); return TRUE; } @@ -225,77 +228,77 @@ METHOD(aead_t, destroy, void, private_aead_t *this) { chunk_clear(&this->key); + chunk_clear(&this->salt); this->iv_gen->destroy(this->iv_gen); free(this); } -#if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_AEAD_GCM) +#ifdef BOTAN_HAS_AES +#if defined(BOTAN_HAS_AEAD_GCM) || defined(BOTAN_HAS_AEAD_GCM) + +static struct { + encryption_algorithm_t algo; + size_t key_size; + char *name; + size_t icv_size; +} aes_modes[] = { + { ENCR_AES_GCM_ICV8, 16, "AES-128/GCM(8)", 8 }, + { ENCR_AES_GCM_ICV8, 24, "AES-192/GCM(8)", 8 }, + { ENCR_AES_GCM_ICV8, 32, "AES-256/GCM(8)", 8 }, + { ENCR_AES_GCM_ICV12, 16, "AES-128/GCM(12)", 12 }, + { ENCR_AES_GCM_ICV12, 24, "AES-192/GCM(12)", 12 }, + { ENCR_AES_GCM_ICV12, 32, "AES-256/GCM(12)", 12 }, + { ENCR_AES_GCM_ICV16, 16, "AES-128/GCM(16)", 16 }, + { ENCR_AES_GCM_ICV16, 24, "AES-192/GCM(16)", 16 }, + { ENCR_AES_GCM_ICV16, 32, "AES-256/GCM(16)", 16 }, + { ENCR_AES_CCM_ICV8, 16, "AES-128/CCM(8,4)", 8 }, + { ENCR_AES_CCM_ICV8, 24, "AES-192/CCM(8,4)", 8 }, + { ENCR_AES_CCM_ICV8, 32, "AES-256/CCM(8,4)", 8 }, + { ENCR_AES_CCM_ICV12, 16, "AES-128/CCM(12,4)", 12 }, + { ENCR_AES_CCM_ICV12, 24, "AES-192/CCM(12,4)", 12 }, + { ENCR_AES_CCM_ICV12, 32, "AES-256/CCM(12,4)", 12 }, + { ENCR_AES_CCM_ICV16, 16, "AES-128/CCM(16,4)", 16 }, + { ENCR_AES_CCM_ICV16, 24, "AES-192/CCM(16,4)", 16 }, + { ENCR_AES_CCM_ICV16, 32, "AES-256/CCM(16,4)", 16 }, +}; /** * Determine the cipher name and ICV size for the given algorithm and key size */ -static bool determine_gcm_params(private_aead_t *this, +static bool determine_aes_params(private_aead_t *this, encryption_algorithm_t algo, size_t key_size) { - switch (algo) + int i; + + for (i = 0; i < countof(aes_modes); i++) { - case ENCR_AES_GCM_ICV8: - switch (key_size) - { - case 16: - this->cipher_name = "AES-128/GCM(8)"; - break; - case 24: - this->cipher_name = "AES-192/GCM(8)"; - break; - case 32: - this->cipher_name = "AES-256/GCM(8)"; - break; - default: - return FALSE; - } - this->icv_size = 8; - return TRUE; - case ENCR_AES_GCM_ICV12: - switch (key_size) - { - case 16: - this->cipher_name = "AES-128/GCM(12)"; - break; - case 24: - this->cipher_name = "AES-192/GCM(12)"; - break; - case 32: - this->cipher_name = "AES-256/GCM(12)"; - break; - default: - return FALSE; - } - this->icv_size = 12; - return TRUE; - case ENCR_AES_GCM_ICV16: - switch (key_size) - { - case 16: - this->cipher_name = "AES-128/GCM"; - break; - case 24: - this->cipher_name = "AES-192/GCM"; - break; - case 32: - this->cipher_name = "AES-256/GCM"; - break; - default: - return FALSE; - } - this->icv_size = 16; + if (aes_modes[i].algo == algo && + aes_modes[i].key_size == key_size) + { + this->cipher_name = aes_modes[i].name; + this->icv_size = aes_modes[i].icv_size; return TRUE; - default: - return FALSE; + } } + return FALSE; } + +#endif #endif +/** + * Check the given salt size, set it if not set + */ +static bool check_salt_size(size_t expected, size_t *salt_size) +{ + if (*salt_size) + { + return *salt_size == expected; + } + *salt_size = expected; + return TRUE; +} + /* * Described in header */ @@ -318,15 +321,10 @@ aead_t *botan_aead_create(encryption_algorithm_t algo, size_t key_size, }, ); - if (salt_size && salt_size != SALT_LEN) - { - free(this); - return NULL; - } - switch (algo) { -#if defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_AEAD_GCM) +#ifdef BOTAN_HAS_AES +#ifdef BOTAN_HAS_AEAD_GCM case ENCR_AES_GCM_ICV8: case ENCR_AES_GCM_ICV12: case ENCR_AES_GCM_ICV16: @@ -334,21 +332,43 @@ aead_t *botan_aead_create(encryption_algorithm_t algo, size_t key_size, { key_size = 16; } - if (!determine_gcm_params(this, algo, key_size)) + if (!check_salt_size(SALT_LEN, &salt_size) || + !determine_aes_params(this, algo, key_size)) + { + free(this); + return NULL; + } + break; +#endif +#ifdef BOTAN_HAS_AEAD_CCM + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + if (!key_size) + { + key_size = 16; + } + if (!check_salt_size(CCM_SALT_LEN, &salt_size) || + !determine_aes_params(this, algo, key_size)) { free(this); return NULL; } break; #endif +#endif #ifdef BOTAN_HAS_AEAD_CHACHA20_POLY1305 case ENCR_CHACHA20_POLY1305: - if (key_size && key_size != CHAPOLY_KEY_LEN) + if (!key_size) + { + key_size = CHAPOLY_KEY_LEN; + } + if (key_size != CHAPOLY_KEY_LEN || + !check_salt_size(SALT_LEN, &salt_size)) { free(this); return NULL; } - key_size = CHAPOLY_KEY_LEN; this->cipher_name = "ChaCha20Poly1305"; this->icv_size = 16; break; @@ -359,6 +379,7 @@ aead_t *botan_aead_create(encryption_algorithm_t algo, size_t key_size, } this->key = chunk_alloc(key_size); + this->salt = chunk_alloc(salt_size); this->iv_gen = iv_gen_seq_create(); return &this->public; diff --git a/src/libstrongswan/plugins/botan/botan_plugin.c b/src/libstrongswan/plugins/botan/botan_plugin.c index 9a2d8e6c2c..205e30dc9f 100644 --- a/src/libstrongswan/plugins/botan/botan_plugin.c +++ b/src/libstrongswan/plugins/botan/botan_plugin.c @@ -122,6 +122,20 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 16), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 24), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 32), + #endif + #ifdef BOTAN_HAS_AEAD_CCM + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8, 32), #endif #endif #ifdef BOTAN_HAS_AEAD_CHACHA20_POLY1305