]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
ChaCha20-Poly1305 no longer supports truncated IV's.
authorslontis <shane.lontis@oracle.com>
Fri, 27 Jan 2023 03:18:17 +0000 (13:18 +1000)
committerTomas Mraz <tomas@openssl.org>
Mon, 30 Jan 2023 08:48:50 +0000 (09:48 +0100)
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 https://github.com/openssl/openssl/pull/20151)

doc/man3/EVP_EncryptInit.pod
doc/man7/migration_guide.pod
providers/implementations/ciphers/cipher_chacha20_poly1305.c
providers/implementations/ciphers/cipher_chacha20_poly1305.h
providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
test/recipes/30-test_evp_data/evpciph_chacha.txt

index 514d72c54b25c3d89190933be41a5f6672a12d0c..039f3ce12e414656bf9d10e92593ed72bd65b05a 100644 (file)
@@ -1469,11 +1469,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)
 
index e82471370f0173e772acdd341056cca407e563c7..ddfa81e13e4203033bca6e99a6fd26af86315c65 100644 (file)
@@ -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
index 0ba7483780f47124ca1af2af27ca23fd530512e4..8cbaa50d9545acbb282da0c4e0b0fd93219ed0c4 100644 (file)
@@ -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
@@ -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);
     }
@@ -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;
         }
@@ -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);
index 1f6f0066dc758d7a89c8225d49abc978a8088277..9a5ce34e7bc3a4b8a099c5d5c1cb811cd696bcf0 100644 (file)
@@ -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;
index 1533a3869b89377a7c652c42dc23ff5afd340086..421380e86ebb74aa5917fc3221cebd23692f7b60 100644 (file)
@@ -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)
 {
@@ -78,6 +77,7 @@ 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;
@@ -85,22 +85,20 @@ static int chacha20_poly1305_initiv(PROV_CIPHER_CTX *bctx)
     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;
 }
 
index 3315a66f33757d97b45515dcb2bdcbd525d3e015..f283b240f3a0942f1ee9448a03c82101410ba164 100644 (file)
@@ -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