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 * Copyright (C) secunet Security Networks AG
* *
@ -20,6 +20,12 @@
typedef struct private_openssl_crypter_t private_openssl_crypter_t; 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 * Private data of openssl_crypter_t
*/ */
@ -31,12 +37,17 @@ struct private_openssl_crypter_t {
openssl_crypter_t public; openssl_crypter_t public;
/* /*
* the key * The key
*/ */
chunk_t key; chunk_t key;
/**
* Nonce value (CTR mode)
*/
chunk_t nonce;
/* /*
* the cipher to use * The cipher to use
*/ */
const EVP_CIPHER *cipher; 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; EVP_CIPHER_CTX *ctx;
int len; int len;
u_char *out; u_char iv_buf[EVP_CIPHER_iv_length(this->cipher)], *iv_ptr = iv_buf, *out;
bool success = FALSE; 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; out = data.ptr;
if (dst) 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) && if (EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) &&
EVP_CIPHER_CTX_set_padding(ctx, 0) /* disable padding */ && EVP_CIPHER_CTX_set_padding(ctx, 0) /* disable padding */ &&
EVP_CIPHER_CTX_set_key_length(ctx, this->key.len) && 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) && EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) &&
/* since padding is disabled this does nothing */ /* since padding is disabled this does nothing */
EVP_CipherFinal_ex(ctx, out + len, &len)) 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, METHOD(crypter_t, get_iv_size, size_t,
private_openssl_crypter_t *this) private_openssl_crypter_t *this)
{ {
if (this->nonce.len)
{
return CTR_IV_LEN;
}
return EVP_CIPHER_iv_length(this->cipher); return EVP_CIPHER_iv_length(this->cipher);
} }
METHOD(crypter_t, get_key_size, size_t, METHOD(crypter_t, get_key_size, size_t,
private_openssl_crypter_t *this) private_openssl_crypter_t *this)
{ {
return this->key.len; return this->key.len + this->nonce.len;
} }
METHOD(crypter_t, set_key, bool, METHOD(crypter_t, set_key, bool,
private_openssl_crypter_t *this, chunk_t key) 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; return TRUE;
} }
@ -161,6 +196,7 @@ METHOD(crypter_t, destroy, void,
private_openssl_crypter_t *this) private_openssl_crypter_t *this)
{ {
chunk_clear(&this->key); chunk_clear(&this->key);
chunk_clear(&this->nonce);
free(this); free(this);
} }
@ -171,6 +207,7 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
size_t key_size) size_t key_size)
{ {
private_openssl_crypter_t *this; private_openssl_crypter_t *this;
size_t nonce_size = 0;
INIT(this, INIT(this,
.public = { .public = {
@ -212,6 +249,27 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
return NULL; return NULL;
} }
break; 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: case ENCR_AES_ECB:
switch (key_size) switch (key_size)
{ {
@ -272,6 +330,27 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
return NULL; return NULL;
} }
break; 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 #ifndef OPENSSL_NO_DES
case ENCR_DES_ECB: case ENCR_DES_ECB:
key_size = 8; key_size = 8;
@ -302,6 +381,7 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
} }
this->key = chunk_alloc(key_size); this->key = chunk_alloc(key_size);
this->nonce = chunk_alloc(nonce_size);
return &this->public; 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, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24), PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 32), 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, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 24), PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 32), 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, 16),
PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CBC, 24), PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CBC, 24),
PLUGIN_PROVIDE(CRYPTER, ENCR_CAMELLIA_CBC, 32), 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 #endif
#ifndef OPENSSL_NO_RC5 #ifndef OPENSSL_NO_RC5
PLUGIN_PROVIDE(CRYPTER, ENCR_RC5, 0), PLUGIN_PROVIDE(CRYPTER, ENCR_RC5, 0),