diff --git a/providers/implementations/digests/sha3_prov.c b/providers/implementations/digests/sha3_prov.c index dea94a2a98..29c23c2f09 100644 --- a/providers/implementations/digests/sha3_prov.c +++ b/providers/implementations/digests/sha3_prov.c @@ -245,6 +245,7 @@ static int s390x_shake_final(void *vctx, unsigned char *out, size_t outlen) static int s390x_shake_squeeze(void *vctx, unsigned char *out, size_t outlen) { KECCAK1600_CTX *ctx = vctx; + unsigned int fc; size_t len; if (!ossl_prov_is_running()) @@ -255,8 +256,10 @@ static int s390x_shake_squeeze(void *vctx, unsigned char *out, size_t outlen) * On the first squeeze call, finish the absorb process (incl. padding). */ if (ctx->xof_state != XOF_STATE_SQUEEZE) { + fc = ctx->pad; + fc |= ctx->xof_state == XOF_STATE_INIT ? S390X_KLMD_NIP : 0; ctx->xof_state = XOF_STATE_SQUEEZE; - s390x_klmd(ctx->buf, ctx->bufsz, out, outlen, ctx->pad, ctx->A); + s390x_klmd(ctx->buf, ctx->bufsz, out, outlen, fc, ctx->A); ctx->bufsz = outlen % ctx->block_size; /* reuse ctx->bufsz to count bytes squeezed from current sponge */ return 1; diff --git a/test/evp_xof_test.c b/test/evp_xof_test.c index fd4313cbf5..42d358b638 100644 --- a/test/evp_xof_test.c +++ b/test/evp_xof_test.c @@ -500,6 +500,34 @@ err: return ret; } +/* Test that a squeeze without a preceding absorb works */ +static int shake_squeeze_no_absorb_test(void) +{ + int ret = 0; + EVP_MD_CTX *ctx = NULL; + unsigned char out[1000]; + unsigned char out2[1000]; + const char *alg = "SHAKE128"; + + if (!TEST_ptr(ctx = shake_setup(alg)) + || !TEST_true(EVP_DigestFinalXOF(ctx, out, sizeof(out)))) + goto err; + + if (!TEST_true(EVP_DigestInit_ex2(ctx, NULL, NULL)) + || !TEST_true(EVP_DigestSqueeze(ctx, out2, sizeof(out2) / 2)) + || !TEST_true(EVP_DigestSqueeze(ctx, out2 + sizeof(out2) / 2, + sizeof(out2) / 2))) + goto err; + + if (!TEST_mem_eq(out2, sizeof(out2), out, sizeof(out))) + goto err; + ret = 1; + +err: + EVP_MD_CTX_free(ctx); + return ret; +} + static int xof_fail_test(void) { int ret; @@ -521,5 +549,6 @@ int setup_tests(void) ADD_ALL_TESTS(shake_squeeze_large_test, OSSL_NELEM(stride_tests)); ADD_ALL_TESTS(shake_squeeze_dup_test, OSSL_NELEM(dupoffset_tests)); ADD_TEST(xof_fail_test); + ADD_TEST(shake_squeeze_no_absorb_test); return 1; }