openssl: Add support for AES and Camellia in CTR mode

This commit is contained in:
Tobias Brunner 2022-05-31 16:03:43 +02:00
parent 3d966d6d0a
commit 112bb465fb
2 changed files with 93 additions and 7 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2008-2022 Tobias Brunner
*
* Copyright (C) secunet Security Networks AG
*
@ -20,6 +20,12 @@
typedef struct private_openssl_crypter_t private_openssl_crypter_t;
/**
* These are as defined by RFC 3686
*/
#define CTR_NONCE_LEN 4
#define CTR_IV_LEN 8
/**
* Private data of openssl_crypter_t
*/
@ -31,12 +37,17 @@ struct private_openssl_crypter_t {
openssl_crypter_t public;
/*
* the key
* The key
*/
chunk_t key;
/**
* Nonce value (CTR mode)
*/
chunk_t nonce;
/*
* the cipher to use
* The cipher to use
*/
const EVP_CIPHER *cipher;
};
@ -96,9 +107,24 @@ static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
{
EVP_CIPHER_CTX *ctx;
int len;
u_char *out;
u_char iv_buf[EVP_CIPHER_iv_length(this->cipher)], *iv_ptr = iv_buf, *out;
bool success = FALSE;
if (this->nonce.len && (this->nonce.len + iv.len) <= sizeof(iv_buf))
{
memset(iv_buf, 0, sizeof(iv_buf));
memcpy(iv_buf, this->nonce.ptr, this->nonce.len);
memcpy(iv_buf + this->nonce.len, iv.ptr, iv.len);
iv_buf[sizeof(iv_buf) - 1] = 1;
}
else if (iv.len == sizeof(iv_buf))
{
iv_ptr = iv.ptr;
}
else
{
return FALSE;
}
out = data.ptr;
if (dst)
{
@ -109,7 +135,7 @@ static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
if (EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) &&
EVP_CIPHER_CTX_set_padding(ctx, 0) /* disable padding */ &&
EVP_CIPHER_CTX_set_key_length(ctx, this->key.len) &&
EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, iv.ptr, enc) &&
EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, iv_ptr, enc) &&
EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) &&
/* since padding is disabled this does nothing */
EVP_CipherFinal_ex(ctx, out + len, &len))
@ -141,19 +167,28 @@ METHOD(crypter_t, get_block_size, size_t,
METHOD(crypter_t, get_iv_size, size_t,
private_openssl_crypter_t *this)
{
if (this->nonce.len)
{
return CTR_IV_LEN;
}
return EVP_CIPHER_iv_length(this->cipher);
}
METHOD(crypter_t, get_key_size, size_t,
private_openssl_crypter_t *this)
{
return this->key.len;
return this->key.len + this->nonce.len;
}
METHOD(crypter_t, set_key, bool,
private_openssl_crypter_t *this, chunk_t key)
{
memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
if (key.len != get_key_size(this))
{
return FALSE;
}
memcpy(this->nonce.ptr, key.ptr + key.len - this->nonce.len, this->nonce.len);
memcpy(this->key.ptr, key.ptr, this->key.len);
return TRUE;
}
@ -161,6 +196,7 @@ METHOD(crypter_t, destroy, void,
private_openssl_crypter_t *this)
{
chunk_clear(&this->key);
chunk_clear(&this->nonce);
free(this);
}
@ -171,6 +207,7 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
size_t key_size)
{
private_openssl_crypter_t *this;
size_t nonce_size = 0;
INIT(this,
.public = {
@ -212,6 +249,27 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
return NULL;
}
break;
case ENCR_AES_CTR:
switch (key_size)
{
case 0:
key_size = 16;
/* FALL */
case 16: /* AES 128 */
this->cipher = EVP_get_cipherbyname("aes-128-ctr");
break;
case 24: /* AES-192 */
this->cipher = EVP_get_cipherbyname("aes-192-ctr");
break;
case 32: /* AES-256 */
this->cipher = EVP_get_cipherbyname("aes-256-ctr");
break;
default:
free(this);
return NULL;
}
nonce_size = CTR_NONCE_LEN;
break;
case ENCR_AES_ECB:
switch (key_size)
{
@ -272,6 +330,27 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
return NULL;
}
break;
case ENCR_CAMELLIA_CTR:
switch (key_size)
{
case 0:
key_size = 16;
/* FALL */
case 16: /* CAMELLIA 128 */
this->cipher = EVP_get_cipherbyname("camellia-128-ctr");
break;
case 24: /* CAMELLIA 192 */
this->cipher = EVP_get_cipherbyname("camellia-192-ctr");
break;
case 32: /* CAMELLIA 256 */
this->cipher = EVP_get_cipherbyname("camellia-256-ctr");
break;
default:
free(this);
return NULL;
}
nonce_size = CTR_NONCE_LEN;
break;
#ifndef OPENSSL_NO_DES
case ENCR_DES_ECB:
key_size = 8;
@ -302,6 +381,7 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
}
this->key = chunk_alloc(key_size);
this->nonce = chunk_alloc(nonce_size);
return &this->public;
}

View File

@ -382,6 +382,9 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 32),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CTR, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CTR, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CTR, 32),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 32),
@ -393,6 +396,9 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CBC, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CBC, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CBC, 32),
PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CTR, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CTR, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CTR, 32),
#endif
#ifndef OPENSSL_NO_RC5
PLUGIN_PROVIDE(CRYPTER, ENCR_RC5, 0),