summaryrefslogtreecommitdiffstats
path: root/providers
diff options
context:
space:
mode:
authorslontis <shane.lontis@oracle.com>2023-07-21 15:05:38 +1000
committerTomas Mraz <tomas@openssl.org>2023-11-10 13:27:00 +0100
commit536649082212e7c643ab8d7bab89f620fbcd37f0 (patch)
treed5f28d382eb86111b2d2672db4f7ab0a836bc9c5 /providers
parent9257a89b6f25dfa5aeee7114baec8ea992fcf5e5 (diff)
Add EVP_DigestSqueeze() API.
Fixes #7894 This allows SHAKE to squeeze multiple times with different output sizes. The existing EVP_DigestFinalXOF() API has been left as a one shot operation. A similar interface is used by another toolkit. The low level SHA3_Squeeze() function needed to change slightly so that it can handle multiple squeezes. This involves changing the assembler code so that it passes a boolean to indicate whether the Keccak function should be called on entry. At the provider level, the squeeze is buffered, so that it only requests a multiple of the blocksize when SHA3_Squeeze() is called. On the first call the value is zero, on subsequent calls the value passed is 1. This PR is derived from the excellent work done by @nmathewson in https://github.com/openssl/openssl/pull/7921 Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/21511)
Diffstat (limited to 'providers')
-rw-r--r--providers/implementations/digests/sha3_prov.c114
1 files changed, 92 insertions, 22 deletions
diff --git a/providers/implementations/digests/sha3_prov.c b/providers/implementations/digests/sha3_prov.c
index 423bed7983..19576c7190 100644
--- a/providers/implementations/digests/sha3_prov.c
+++ b/providers/implementations/digests/sha3_prov.c
@@ -33,10 +33,12 @@ static OSSL_FUNC_digest_update_fn keccak_update;
static OSSL_FUNC_digest_final_fn keccak_final;
static OSSL_FUNC_digest_freectx_fn keccak_freectx;
static OSSL_FUNC_digest_dupctx_fn keccak_dupctx;
+static OSSL_FUNC_digest_squeeze_fn shake_squeeze;
static OSSL_FUNC_digest_set_ctx_params_fn shake_set_ctx_params;
static OSSL_FUNC_digest_settable_ctx_params_fn shake_settable_ctx_params;
static sha3_absorb_fn generic_sha3_absorb;
static sha3_final_fn generic_sha3_final;
+static sha3_squeeze_fn generic_sha3_squeeze;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) && defined(KECCAK1600_ASM)
/*
@@ -103,20 +105,37 @@ static int keccak_update(void *vctx, const unsigned char *inp, size_t len)
}
static int keccak_final(void *vctx, unsigned char *out, size_t *outl,
- size_t outsz)
+ size_t outlen)
{
int ret = 1;
KECCAK1600_CTX *ctx = vctx;
if (!ossl_prov_is_running())
return 0;
- if (outsz > 0)
- ret = ctx->meth.final(out, ctx);
+ if (outlen > 0)
+ ret = ctx->meth.final(ctx, out, ctx->md_size);
*outl = ctx->md_size;
return ret;
}
+static int shake_squeeze(void *vctx, unsigned char *out, size_t *outl,
+ size_t outlen)
+{
+ int ret = 1;
+ KECCAK1600_CTX *ctx = vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+ if (ctx->meth.squeeze == NULL)
+ return 0;
+ if (outlen > 0)
+ ret = ctx->meth.squeeze(ctx, out, outlen);
+
+ *outl = outlen;
+ return ret;
+}
+
/*-
* Generic software version of the absorb() and final().
*/
@@ -127,15 +146,28 @@ static size_t generic_sha3_absorb(void *vctx, const void *inp, size_t len)
return SHA3_absorb(ctx->A, inp, len, ctx->block_size);
}
-static int generic_sha3_final(unsigned char *md, void *vctx)
+static int generic_sha3_final(void *vctx, unsigned char *out, size_t outlen)
{
- return ossl_sha3_final(md, (KECCAK1600_CTX *)vctx);
+ return ossl_sha3_final((KECCAK1600_CTX *)vctx, out, outlen);
+}
+
+static int generic_sha3_squeeze(void *vctx, unsigned char *out, size_t outlen)
+{
+ return ossl_sha3_squeeze((KECCAK1600_CTX *)vctx, out, outlen);
}
static PROV_SHA3_METHOD sha3_generic_md =
{
generic_sha3_absorb,
- generic_sha3_final
+ generic_sha3_final,
+ NULL
+};
+
+static PROV_SHA3_METHOD shake_generic_md =
+{
+ generic_sha3_absorb,
+ generic_sha3_final,
+ generic_sha3_squeeze
};
#if defined(S390_SHA3)
@@ -156,59 +188,60 @@ static size_t s390x_sha3_absorb(void *vctx, const void *inp, size_t len)
return rem;
}
-static int s390x_sha3_final(unsigned char *md, void *vctx)
+static int s390x_sha3_final(void *vctx, unsigned char *out, size_t outlen)
{
KECCAK1600_CTX *ctx = vctx;
if (!ossl_prov_is_running())
return 0;
s390x_klmd(ctx->buf, ctx->bufsz, NULL, 0, ctx->pad, ctx->A);
- memcpy(md, ctx->A, ctx->md_size);
+ memcpy(out, ctx->A, outlen);
return 1;
}
-static int s390x_shake_final(unsigned char *md, void *vctx)
+static int s390x_shake_final(void *vctx, unsigned char *out, size_t outlen)
{
KECCAK1600_CTX *ctx = vctx;
if (!ossl_prov_is_running())
return 0;
- s390x_klmd(ctx->buf, ctx->bufsz, md, ctx->md_size, ctx->pad, ctx->A);
+ s390x_klmd(ctx->buf, ctx->bufsz, out, outlen, ctx->pad, ctx->A);
return 1;
}
-static int s390x_keccakc_final(unsigned char *md, void *vctx, int padding)
+static int s390x_keccakc_final(void *vctx, unsigned char *out, size_t outlen,
+ int padding)
{
KECCAK1600_CTX *ctx = vctx;
size_t bsz = ctx->block_size;
size_t num = ctx->bufsz;
- size_t needed = ctx->md_size;
+ size_t needed = outlen;
if (!ossl_prov_is_running())
return 0;
- if (ctx->md_size == 0)
+ if (outlen == 0)
return 1;
memset(ctx->buf + num, 0, bsz - num);
ctx->buf[num] = padding;
ctx->buf[bsz - 1] |= 0x80;
s390x_kimd(ctx->buf, bsz, ctx->pad, ctx->A);
num = needed > bsz ? bsz : needed;
- memcpy(md, ctx->A, num);
+ memcpy(out, ctx->A, num);
needed -= num;
if (needed > 0)
- s390x_klmd(NULL, 0, md + bsz, needed, ctx->pad | S390X_KLMD_PS, ctx->A);
+ s390x_klmd(NULL, 0, out + bsz, needed, ctx->pad | S390X_KLMD_PS, ctx->A);
return 1;
}
-static int s390x_keccak_final(unsigned char *md, void *vctx)
+static int s390x_keccak_final(void *vctx, unsigned char *out, size_t outlen)
{
- return s390x_keccakc_final(md, vctx, 0x01);
+ return s390x_keccakc_final(vctx, out, outlen, 0x01);
}
-static int s390x_kmac_final(unsigned char *md, void *vctx)
+static int s390x_kmac_final(void *vctx, unsigned char *out, size_t outlen)
{
- return s390x_keccakc_final(md, vctx, 0x04);
+ return s390x_keccakc_final(vctx, out, outlen, 0x04);
}
static PROV_SHA3_METHOD sha3_s390x_md =
@@ -220,7 +253,7 @@ static PROV_SHA3_METHOD sha3_s390x_md =
static PROV_SHA3_METHOD keccak_s390x_md =
{
s390x_sha3_absorb,
- s390x_keccak_final
+ s390x_keccak_final,
};
static PROV_SHA3_METHOD shake_s390x_md =
@@ -235,6 +268,14 @@ static PROV_SHA3_METHOD kmac_s390x_md =
s390x_kmac_final
};
+# define SHAKE_SET_MD(uname, typ) \
+ if (S390_SHA3_CAPABLE(uname)) { \
+ ctx->pad = S390X_##uname; \
+ ctx->meth = typ##_s390x_md; \
+ } else { \
+ ctx->meth = shake_generic_md; \
+ }
+
# define SHA3_SET_MD(uname, typ) \
if (S390_SHA3_CAPABLE(uname)) { \
ctx->pad = S390X_##uname; \
@@ -255,7 +296,7 @@ static PROV_SHA3_METHOD kmac_s390x_md =
static sha3_absorb_fn armsha3_sha3_absorb;
size_t SHA3_absorb_cext(uint64_t A[5][5], const unsigned char *inp, size_t len,
- size_t r);
+ size_t r);
/*-
* Hardware-assisted ARMv8.2 SHA3 extension version of the absorb()
*/
@@ -271,6 +312,19 @@ static PROV_SHA3_METHOD sha3_ARMSHA3_md =
armsha3_sha3_absorb,
generic_sha3_final
};
+static PROV_SHA3_METHOD shake_ARMSHA3_md =
+{
+ armsha3_sha3_absorb,
+ generic_sha3_final,
+ generic_sha3_squeeze
+};
+# define SHAKE_SET_MD(uname, typ) \
+ if (OPENSSL_armcap_P & ARMV8_HAVE_SHA3_AND_WORTH_USING) { \
+ ctx->meth = shake_ARMSHA3_md; \
+ } else { \
+ ctx->meth = shake_generic_md; \
+ }
+
# define SHA3_SET_MD(uname, typ) \
if (OPENSSL_armcap_P & ARMV8_HAVE_SHA3_AND_WORTH_USING) { \
ctx->meth = sha3_ARMSHA3_md; \
@@ -286,6 +340,7 @@ static PROV_SHA3_METHOD sha3_ARMSHA3_md =
#else
# define SHA3_SET_MD(uname, typ) ctx->meth = sha3_generic_md;
# define KMAC_SET_MD(bitlen) ctx->meth = sha3_generic_md;
+# define SHAKE_SET_MD(uname, typ) ctx->meth = shake_generic_md;
#endif /* S390_SHA3 */
#define SHA3_newctx(typ, uname, name, bitlen, pad) \
@@ -302,6 +357,20 @@ static void *name##_newctx(void *provctx) \
return ctx; \
}
+#define SHAKE_newctx(typ, uname, name, bitlen, pad) \
+static OSSL_FUNC_digest_newctx_fn name##_newctx; \
+static void *name##_newctx(void *provctx) \
+{ \
+ KECCAK1600_CTX *ctx = ossl_prov_is_running() ? OPENSSL_zalloc(sizeof(*ctx))\
+ : NULL; \
+ \
+ if (ctx == NULL) \
+ return NULL; \
+ ossl_sha3_init(ctx, pad, bitlen); \
+ SHAKE_SET_MD(uname, typ) \
+ return ctx; \
+}
+
#define KMAC_newctx(uname, bitlen, pad) \
static OSSL_FUNC_digest_newctx_fn uname##_newctx; \
static void *uname##_newctx(void *provctx) \
@@ -333,6 +402,7 @@ const OSSL_DISPATCH ossl_##name##_functions[] = { \
#define PROV_FUNC_SHAKE_DIGEST(name, bitlen, blksize, dgstsize, flags) \
PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags), \
+ { OSSL_FUNC_DIGEST_SQUEEZE, (void (*)(void))shake_squeeze }, \
{ OSSL_FUNC_DIGEST_INIT, (void (*)(void))keccak_init_params }, \
{ OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))shake_set_ctx_params }, \
{ OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, \
@@ -398,7 +468,7 @@ static int shake_set_ctx_params(void *vctx, const OSSL_PARAM params[])
SHA3_FLAGS)
#define IMPLEMENT_SHAKE_functions(bitlen) \
- SHA3_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, '\x1f') \
+ SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, '\x1f') \
PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen, \
SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
SHAKE_FLAGS)