Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
strongswan.28069
0009-strongswan-openssl-aead-add-ccm-support.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0009-strongswan-openssl-aead-add-ccm-support.patch of Package strongswan.28069
From 546f61d3c820d0289f79cbe3228e97f75c73dd0b Mon Sep 17 00:00:00 2001 From: Tobias Brunner <tobias@strongswan.org> Date: Tue, 4 May 2021 18:19:57 +0200 References: bsc#1185363 Upstream: https://github.com/strongswan/strongswan/pull/353 Subject: [PATCH] openssl: Add support for AES in CCM mode While CCM is available in earlier versions, we only use it with OpenSSL 1.1.0 and newer because the generic control variables are not available before and we default to GCM for them. Closes strongswan/strongswan#353. diff --git a/src/libstrongswan/plugins/openssl/openssl_aead.c b/src/libstrongswan/plugins/openssl/openssl_aead.c index 52c5ac3f8..9262cfb23 100644 --- a/src/libstrongswan/plugins/openssl/openssl_aead.c +++ b/src/libstrongswan/plugins/openssl/openssl_aead.c @@ -29,10 +29,17 @@ #define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG #endif +/* not defined for older versions of BoringSSL */ +#ifndef EVP_CIPH_CCM_MODE +#define EVP_CIPH_CCM_MODE 0xffff +#endif + /** as defined in RFC 4106 */ -#define IV_LEN 8 -#define SALT_LEN 4 -#define NONCE_LEN (IV_LEN + SALT_LEN) +#define IV_LEN 8 +#define SALT_LEN 4 +#define NONCE_LEN (IV_LEN + SALT_LEN) +/** as defined in RFC 4309 */ +#define CCM_SALT_LEN 3 typedef struct private_aead_t private_aead_t; @@ -56,6 +63,11 @@ struct private_aead_t { */ char salt[SALT_LEN]; + /** + * Size of the salt + */ + size_t salt_size; + /** * Size of the integrity check value */ @@ -83,27 +95,39 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, bool success = FALSE; int len; - memcpy(nonce, this->salt, SALT_LEN); - memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN); + memcpy(nonce, this->salt, this->salt_size); + memcpy(nonce + this->salt_size, iv.ptr, IV_LEN); ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_set_padding(ctx, 0); if (!EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) || - !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, NONCE_LEN, NULL) || - !EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, nonce, enc)) + !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, + this->salt_size + IV_LEN, NULL)) { goto done; } - if (!enc && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, this->icv_size, - data.ptr + data.len)) - { /* set ICV for verification on decryption */ + if ((!enc || EVP_CIPHER_mode(this->cipher) == EVP_CIPH_CCM_MODE) && + !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, this->icv_size, + enc ? NULL : data.ptr + data.len)) + { /* set ICV for verification on decryption, CCM requires the ICV length + * when encrypting */ + goto done; + } + if (!EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, nonce, enc)) + { /* set key and nonce */ + goto done; + } + if (EVP_CIPHER_mode(this->cipher) == EVP_CIPH_CCM_MODE && + !EVP_CipherUpdate(ctx, NULL, &len, NULL, data.len)) + { /* CCM requires setting the total input length (plain or cipher+ICV) */ goto done; } if (assoc.len && !EVP_CipherUpdate(ctx, NULL, &len, assoc.ptr, assoc.len)) { /* set AAD if specified */ goto done; } - if (!EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) || + /* CCM doesn't like NULL pointers as input, make sure we don't pass one */ + if (!EVP_CipherUpdate(ctx, out, &len, data.ptr ?: out, data.len) || !EVP_CipherFinal_ex(ctx, out + len, &len)) { /* EVP_CipherFinal_ex fails if ICV is incorrect on decryption */ goto done; @@ -183,7 +207,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_size; } METHOD(aead_t, set_key, bool, @@ -193,7 +217,7 @@ METHOD(aead_t, set_key, bool, { return FALSE; } - memcpy(this->salt, key.ptr + key.len - SALT_LEN, SALT_LEN); + memcpy(this->salt, key.ptr + key.len - this->salt_size, this->salt_size); memcpy(this->key.ptr, key.ptr, this->key.len); return TRUE; } @@ -226,17 +250,21 @@ aead_t *openssl_aead_create(encryption_algorithm_t algo, .set_key = _set_key, .destroy = _destroy, }, + .salt_size = SALT_LEN, ); switch (algo) { case ENCR_AES_GCM_ICV8: + case ENCR_AES_CCM_ICV8: this->icv_size = 8; break; case ENCR_AES_GCM_ICV12: + case ENCR_AES_CCM_ICV12: this->icv_size = 12; break; case ENCR_AES_GCM_ICV16: + case ENCR_AES_CCM_ICV16: this->icv_size = 16; break; case ENCR_CHACHA20_POLY1305: @@ -247,13 +275,6 @@ aead_t *openssl_aead_create(encryption_algorithm_t algo, return NULL; } - if (salt_size && salt_size != SALT_LEN) - { - /* currently not supported */ - free(this); - return NULL; - } - switch (algo) { case ENCR_AES_GCM_ICV8: @@ -278,6 +299,31 @@ aead_t *openssl_aead_create(encryption_algorithm_t algo, return NULL; } break; +#if OPENSSL_VERSION_NUMBER >= 0x1010000fL + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + switch (key_size) + { + case 0: + key_size = 16; + /* FALL */ + case 16: + this->cipher = EVP_aes_128_ccm(); + break; + case 24: + this->cipher = EVP_aes_192_ccm(); + break; + case 32: + this->cipher = EVP_aes_256_ccm(); + break; + default: + free(this); + return NULL; + } + this->salt_size = CCM_SALT_LEN; + break; +#endif /* OPENSSL_VERSION_NUMBER */ #if OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(OPENSSL_NO_CHACHA) case ENCR_CHACHA20_POLY1305: switch (key_size) @@ -299,6 +345,13 @@ aead_t *openssl_aead_create(encryption_algorithm_t algo, return NULL; } + if (salt_size && salt_size != this->salt_size) + { + /* currently not supported */ + free(this); + return NULL; + } + if (!this->cipher) { free(this); diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 851d029dd..edc5ddab1 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -615,6 +615,18 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 16), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 24), PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 32), +#if OPENSSL_VERSION_NUMBER >= 0x1010000fL + /* CCM is available before 1.1.0 but not via generic controls */ + 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 /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_NO_AES */ #if OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(OPENSSL_NO_CHACHA) PLUGIN_PROVIDE(AEAD, ENCR_CHACHA20_POLY1305, 32), -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor