Skip to content

Commit

Permalink
ChaCha20-Poly1305 no longer supports truncated IV's.
Browse files Browse the repository at this point in the history
Fixes #20084

In the 3.0 provider implementation the generic code that handles IV's
only allows a 12 byte IV. Older code intentionally added the ability for
the IV to be truncated.
As this truncation is unsafe, the documentation has been updated to
state that this in no longer allowed. The code has been updated to
produce an error when the iv length is set to any value other than 12.

NOTE: It appears that this additional padding may have originated from the code
which uses a 12 byte IV, that is then passed to CHACHA which zero pads it to 16 bytes.

Note that legacy behaviour in e_chacha20_poly1305.c has not been
updated.

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from #20151)

(cherry picked from commit a011523)
  • Loading branch information
slontis authored and t8m committed Jan 30, 2023
1 parent 00e8275 commit b4120a1
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 28 deletions.
9 changes: 4 additions & 5 deletions doc/man3/EVP_EncryptInit.pod
Expand Up @@ -1433,11 +1433,10 @@ The following I<ctrl>s are supported for the ChaCha20-Poly1305 AEAD algorithm.

=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)

Sets the nonce length. This call can only be made before specifying the nonce.
If not called a default nonce length of 12 (i.e. 96 bits) is used. The maximum
nonce length is 12 bytes (i.e. 96-bits). If a nonce of less than 12 bytes is set
then the nonce is automatically padded with leading 0 bytes to make it 12 bytes
in length.
Sets the nonce length. This call is now redundant since the only valid value
is the default length of 12 (i.e. 96 bits).
Prior to OpenSSL 3.0 a nonce of less than 12 bytes could be used to automatically
pad the iv with leading 0 bytes to make it 12 bytes in length.

=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag)

Expand Down
8 changes: 8 additions & 0 deletions doc/man7/migration_guide.pod
Expand Up @@ -490,6 +490,14 @@ The function code part of the error code is now always set to 0. For that
reason the ERR_GET_FUNC() macro was removed. Applications must resolve
the error codes only using the library number and the reason code.

=head4 ChaCha20-Poly1305 cipher does not allow a truncated IV length to be used

In OpenSSL 3.0 setting the IV length to any value other than 12 will result in an
error.
Prior to OpenSSL 3.0 the ivlen could be smaller that the required 12 byte length,
using EVP_CIPHER_CTX_ctrl(ctx, EVP_CRTL_AEAD_SET_IVLEN, ivlen, NULL). This resulted
in an IV that had leading zero padding.

=head2 Installation and Compilation

Please refer to the INSTALL.md file in the top of the distribution for
Expand Down
7 changes: 2 additions & 5 deletions providers/implementations/ciphers/cipher_chacha20_poly1305.c
Expand Up @@ -14,7 +14,6 @@
#include "prov/implementations.h"
#include "prov/providercommon.h"


#define CHACHA20_POLY1305_KEYLEN CHACHA_KEY_SIZE
#define CHACHA20_POLY1305_BLKLEN 1
#define CHACHA20_POLY1305_MAX_IVLEN 12
Expand Down Expand Up @@ -53,7 +52,6 @@ static void *chacha20_poly1305_newctx(void *provctx)
ossl_prov_cipher_hw_chacha20_poly1305(
CHACHA20_POLY1305_KEYLEN * 8),
NULL);
ctx->nonce_len = CHACHA20_POLY1305_IVLEN;
ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
ossl_chacha20_initctx(&ctx->chacha);
}
Expand Down Expand Up @@ -85,7 +83,7 @@ static int chacha20_poly1305_get_ctx_params(void *vctx, OSSL_PARAM params[])

p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_set_size_t(p, ctx->nonce_len)) {
if (!OSSL_PARAM_set_size_t(p, CHACHA20_POLY1305_IVLEN)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
Expand Down Expand Up @@ -169,11 +167,10 @@ static int chacha20_poly1305_set_ctx_params(void *vctx,
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (len == 0 || len > CHACHA20_POLY1305_MAX_IVLEN) {
if (len != CHACHA20_POLY1305_MAX_IVLEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
ctx->nonce_len = len;
}

p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
Expand Down
Expand Up @@ -25,7 +25,7 @@ typedef struct {
struct { uint64_t aad, text; } len;
unsigned int aad : 1;
unsigned int mac_inited : 1;
size_t tag_len, nonce_len;
size_t tag_len;
size_t tls_payload_length;
size_t tls_aad_pad_sz;
} PROV_CHACHA20_POLY1305_CTX;
Expand Down
32 changes: 15 additions & 17 deletions providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
Expand Up @@ -55,7 +55,6 @@ static int chacha_poly1305_tls_iv_set_fixed(PROV_CIPHER_CTX *bctx,
return 1;
}


static int chacha20_poly1305_initkey(PROV_CIPHER_CTX *bctx,
const unsigned char *key, size_t keylen)
{
Expand All @@ -78,29 +77,28 @@ static int chacha20_poly1305_initiv(PROV_CIPHER_CTX *bctx)
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
unsigned char tempiv[CHACHA_CTR_SIZE] = { 0 };
int ret = 1;
size_t noncelen = CHACHA20_POLY1305_IVLEN;

ctx->len.aad = 0;
ctx->len.text = 0;
ctx->aad = 0;
ctx->mac_inited = 0;
ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;

/* pad on the left */
if (ctx->nonce_len <= CHACHA_CTR_SIZE) {
memcpy(tempiv + CHACHA_CTR_SIZE - ctx->nonce_len, bctx->oiv,
ctx->nonce_len);

if (bctx->enc)
ret = ossl_chacha20_einit(&ctx->chacha, NULL, 0,
tempiv, sizeof(tempiv), NULL);
else
ret = ossl_chacha20_dinit(&ctx->chacha, NULL, 0,
tempiv, sizeof(tempiv), NULL);
ctx->nonce[0] = ctx->chacha.counter[1];
ctx->nonce[1] = ctx->chacha.counter[2];
ctx->nonce[2] = ctx->chacha.counter[3];
bctx->iv_set = 1;
}
/* pad on the left */
memcpy(tempiv + CHACHA_CTR_SIZE - noncelen, bctx->oiv,
noncelen);

if (bctx->enc)
ret = ossl_chacha20_einit(&ctx->chacha, NULL, 0,
tempiv, sizeof(tempiv), NULL);
else
ret = ossl_chacha20_dinit(&ctx->chacha, NULL, 0,
tempiv, sizeof(tempiv), NULL);
ctx->nonce[0] = ctx->chacha.counter[1];
ctx->nonce[1] = ctx->chacha.counter[2];
ctx->nonce[2] = ctx->chacha.counter[3];
bctx->iv_set = 1;
return ret;
}

Expand Down
10 changes: 10 additions & 0 deletions test/recipes/30-test_evp_data/evpciph_chacha.txt
Expand Up @@ -153,6 +153,16 @@ Tag = eead9d67890cbb22392336fea1851f38
Plaintext = 496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d
Ciphertext = 64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b

# Test that a truncated IV is no longer allowed (since 3.0)
# This is the same test as above with the leading zeros stripped from the IV
Cipher = chacha20-poly1305
Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
IV = 0102030405060708
AAD = f33388860000000000004e91
Tag = eead9d67890cbb22392336fea1851f38
Plaintext = 496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d
Result = INVALID_IV_LENGTH

Cipher = chacha20-poly1305
Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
IV = 000000000102030405060708
Expand Down

0 comments on commit b4120a1

Please sign in to comment.