]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Intentionally break EVP_DigestFinal for SHAKE128 and SHAKE256
authorTomas Mraz <tomas@openssl.org>
Thu, 11 Apr 2024 08:29:23 +0000 (10:29 +0200)
committerTomas Mraz <tomas@openssl.org>
Wed, 15 May 2024 10:10:32 +0000 (12:10 +0200)
It will work only if OSSL_DIGEST_PARAM_XOFLEN is set.

Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/24105)

crypto/evp/digest.c
crypto/sha/sha3.c
include/internal/sha3.h
providers/implementations/digests/sha3_prov.c
test/evp_xof_test.c
test/recipes/20-test_dgst.t

index ab670a8f49cb688b70785afce709ed4df5bd5c3e..4c61ca4c4298c8b313333af6ac82ae0b7484f1ff 100644 (file)
@@ -454,6 +454,8 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
     if (ctx->digest->prov == NULL)
         goto legacy;
 
+    if (sz == 0) /* Assuming a xoflen must have been set. */
+        mdsize = SIZE_MAX;
     if (ctx->digest->gettable_ctx_params != NULL) {
         OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
 
index 2411b3f1f8e2feeb8d02538d878261a58f303a96..4d54712168d2dec3f97d51dbc6d2657571c0af63 100644 (file)
@@ -34,12 +34,12 @@ int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
     return 0;
 }
 
-int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
+int ossl_keccak_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen, size_t mdlen)
 {
     int ret = ossl_sha3_init(ctx, pad, bitlen);
 
     if (ret)
-        ctx->md_size *= 2;
+        ctx->md_size = mdlen / 8;
     return ret;
 }
 
index 332916aa54737e591fb7422487abbb1f8d0eed7e..77bd9dbd32da454b162b46518162b6da23cc5730 100644 (file)
@@ -51,8 +51,8 @@ struct keccak_st {
 
 void ossl_sha3_reset(KECCAK1600_CTX *ctx);
 int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen);
-int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad,
-                          size_t bitlen);
+int ossl_keccak_init(KECCAK1600_CTX *ctx, unsigned char pad,
+                     size_t typelen, size_t mdlen);
 int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
 int ossl_sha3_final(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen);
 int ossl_sha3_squeeze(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen);
index 2fd0f928e7b09235c60d193d9d2498af733cb4d3..dce2461a9d0fba7e4fe9cd86bb3705aa855b9a4a 100644 (file)
@@ -14,6 +14,7 @@
 #include <openssl/params.h>
 #include <openssl/err.h>
 #include <openssl/proverr.h>
+#include "internal/numbers.h"
 #include "internal/sha3.h"
 #include "prov/digestcommon.h"
 #include "prov/implementations.h"
@@ -112,6 +113,10 @@ static int keccak_final(void *vctx, unsigned char *out, size_t *outl,
 
     if (!ossl_prov_is_running())
         return 0;
+    if (ctx->md_size == SIZE_MAX) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
+        return 0;
+    }
     if (outlen > 0)
         ret = ctx->meth.final(ctx, out, ctx->md_size);
 
@@ -474,7 +479,7 @@ static void *name##_newctx(void *provctx)                                      \
     return ctx;                                                                \
 }
 
-#define SHAKE_newctx(typ, uname, name, bitlen, pad)                            \
+#define SHAKE_newctx(typ, uname, name, bitlen, mdlen, pad)                     \
 static OSSL_FUNC_digest_newctx_fn name##_newctx;                               \
 static void *name##_newctx(void *provctx)                                      \
 {                                                                              \
@@ -483,7 +488,9 @@ static void *name##_newctx(void *provctx)                                      \
                                                                                \
     if (ctx == NULL)                                                           \
         return NULL;                                                           \
-    ossl_sha3_init(ctx, pad, bitlen);                                          \
+    ossl_keccak_init(ctx, pad, bitlen, mdlen);                                 \
+    if (mdlen == 0)                                                            \
+        ctx->md_size = SIZE_MAX;                                               \
     SHAKE_SET_MD(uname, typ)                                                   \
     return ctx;                                                                \
 }
@@ -497,7 +504,7 @@ static void *uname##_newctx(void *provctx)                                     \
                                                                                \
     if (ctx == NULL)                                                           \
         return NULL;                                                           \
-    ossl_keccak_kmac_init(ctx, pad, bitlen);                                   \
+    ossl_keccak_init(ctx, pad, bitlen, 2 * bitlen);                            \
     KMAC_SET_MD(bitlen)                                                        \
     return ctx;                                                                \
 }
@@ -585,10 +592,12 @@ static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[])
                           SHA3_FLAGS)
 
 #define IMPLEMENT_SHAKE_functions(bitlen)                                      \
-    SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, '\x1f')        \
+    SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen,                \
+                 0 /* no default md length */, '\x1f')                         \
     PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen,                             \
-                          SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen),         \
+                          SHA3_BLOCKSIZE(bitlen), 0,                           \
                           SHAKE_FLAGS)
+
 #define IMPLEMENT_KMAC_functions(bitlen)                                       \
     KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04')                          \
     PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen,                       \
index eeff8667c4124912510ecebadfd565ea29bf521e..964005d0c1b95088b7201ac7d9d4fcaf79401bfb 100644 (file)
@@ -206,14 +206,29 @@ static int shake_kat_digestfinal_test(void)
     EVP_MD_CTX *ctx = NULL;
     unsigned char out[sizeof(shake256_output)];
 
+    /* Test that EVP_DigestFinal without setting XOFLEN fails */
     if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
         return 0;
     if (!TEST_true(EVP_DigestUpdate(ctx, shake256_input,
-                   sizeof(shake256_input)))
-        || !TEST_true(EVP_DigestFinal(ctx, out, &digest_length))
-        || !TEST_uint_eq(digest_length, 32)
-        || !TEST_mem_eq(out, digest_length,
-                        shake256_output, digest_length)
+                   sizeof(shake256_input))))
+        return 0;
+    ERR_set_mark();
+    if (!TEST_false(EVP_DigestFinal(ctx, out, &digest_length))) {
+        ERR_clear_last_mark();
+        return 0;
+    }
+    ERR_pop_to_mark();
+    EVP_MD_CTX_free(ctx);
+
+    /* However EVP_DigestFinalXOF must work */
+    if (!TEST_ptr(ctx = shake_setup("SHAKE256")))
+        return 0;
+    if (!TEST_true(EVP_DigestUpdate(ctx, shake256_input,
+                   sizeof(shake256_input))))
+        return 0;
+    if (!TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out)))
+        || !TEST_mem_eq(out, sizeof(out),
+                        shake256_output, sizeof(shake256_output))
         || !TEST_false(EVP_DigestFinalXOF(ctx, out, sizeof(out))))
         goto err;
     ret = 1;
index aed7bf3984cc1f88c4d121299f57eaff54de140a..5f07789bfddbc1dac01e00d4fb0b91d2110f5102 100644 (file)
@@ -223,13 +223,11 @@ subtest "Custom length XOF digest generation with `dgst` CLI" => sub {
 };
 
 subtest "SHAKE digest generation with no xoflen set `dgst` CLI" => sub {
-    plan tests => 1;
+    plan tests => 2;
 
     my $testdata = srctop_file('test', 'data.bin');
-    my @xofdata = run(app(['openssl', 'dgst', '-shake128', $testdata], stderr => "outerr.txt"), capture => 1);
-    chomp(@xofdata);
-    my $expected = qr/SHAKE-128\(\Q$testdata\E\)= bb565dac72640109e1c926ef441d3fa6/;
-    ok($xofdata[0] =~ $expected, "Check short digest is output");
+    ok(!run(app(['openssl', 'dgst', '-shake128', $testdata])), "SHAKE128 must fail without xoflen");
+    ok(!run(app(['openssl', 'dgst', '-shake256', $testdata])), "SHAKE256 must fail without xoflen");
 };
 
 SKIP: {