#include <stdio.h>
#include <openssl/opensslconf.h>
+#include <openssl/byteorder.h>
/*-
* IMPLEMENTATION NOTES.
*
#endif
void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num);
-int SHA512_Final(unsigned char *md, SHA512_CTX *c)
+#define OUTPUT_RESULT(md, len) \
+ for (n = 0; n < (len / 8); n++) \
+ md = OPENSSL_store_u64_be(md, (uint64_t)c->h[n])
+
+int SHA512_Final(unsigned char *out, SHA512_CTX *c)
{
unsigned char *p = (unsigned char *)c->u.p;
size_t n = c->num;
c->u.d[SHA_LBLOCK - 2] = c->Nh;
c->u.d[SHA_LBLOCK - 1] = c->Nl;
#else
- p[sizeof(c->u) - 1] = (unsigned char)(c->Nl);
- p[sizeof(c->u) - 2] = (unsigned char)(c->Nl >> 8);
- p[sizeof(c->u) - 3] = (unsigned char)(c->Nl >> 16);
- p[sizeof(c->u) - 4] = (unsigned char)(c->Nl >> 24);
- p[sizeof(c->u) - 5] = (unsigned char)(c->Nl >> 32);
- p[sizeof(c->u) - 6] = (unsigned char)(c->Nl >> 40);
- p[sizeof(c->u) - 7] = (unsigned char)(c->Nl >> 48);
- p[sizeof(c->u) - 8] = (unsigned char)(c->Nl >> 56);
- p[sizeof(c->u) - 9] = (unsigned char)(c->Nh);
- p[sizeof(c->u) - 10] = (unsigned char)(c->Nh >> 8);
- p[sizeof(c->u) - 11] = (unsigned char)(c->Nh >> 16);
- p[sizeof(c->u) - 12] = (unsigned char)(c->Nh >> 24);
- p[sizeof(c->u) - 13] = (unsigned char)(c->Nh >> 32);
- p[sizeof(c->u) - 14] = (unsigned char)(c->Nh >> 40);
- p[sizeof(c->u) - 15] = (unsigned char)(c->Nh >> 48);
- p[sizeof(c->u) - 16] = (unsigned char)(c->Nh >> 56);
+ uint8_t *cu = p + sizeof(c->u) - 16;
+
+ cu = OPENSSL_store_u64_be(cu, (uint64_t)c->Nh);
+ cu = OPENSSL_store_u64_be(cu, (uint64_t)c->Nl);
#endif
sha512_block_data_order(c, p, 1);
- if (md == 0)
+ if (out == NULL)
return 0;
+ /* Let compiler decide if it's appropriate to unroll... */
switch (c->md_len) {
case SHA256_192_DIGEST_LENGTH:
- for (n = 0; n < SHA256_192_DIGEST_LENGTH / 8; n++) {
- SHA_LONG64 t = c->h[n];
-
- *(md++) = (unsigned char)(t >> 56);
- *(md++) = (unsigned char)(t >> 48);
- *(md++) = (unsigned char)(t >> 40);
- *(md++) = (unsigned char)(t >> 32);
- *(md++) = (unsigned char)(t >> 24);
- *(md++) = (unsigned char)(t >> 16);
- *(md++) = (unsigned char)(t >> 8);
- *(md++) = (unsigned char)(t);
- }
+ OUTPUT_RESULT(out, SHA256_192_DIGEST_LENGTH);
break;
- /* Let compiler decide if it's appropriate to unroll... */
- case SHA224_DIGEST_LENGTH:
- for (n = 0; n < SHA224_DIGEST_LENGTH / 8; n++) {
- SHA_LONG64 t = c->h[n];
-
- *(md++) = (unsigned char)(t >> 56);
- *(md++) = (unsigned char)(t >> 48);
- *(md++) = (unsigned char)(t >> 40);
- *(md++) = (unsigned char)(t >> 32);
- *(md++) = (unsigned char)(t >> 24);
- *(md++) = (unsigned char)(t >> 16);
- *(md++) = (unsigned char)(t >> 8);
- *(md++) = (unsigned char)(t);
- }
+ case SHA256_DIGEST_LENGTH:
+ OUTPUT_RESULT(out, SHA256_DIGEST_LENGTH);
+ break;
+ case SHA384_DIGEST_LENGTH:
+ OUTPUT_RESULT(out, SHA384_DIGEST_LENGTH);
+ break;
+ case SHA512_DIGEST_LENGTH:
+ OUTPUT_RESULT(out, SHA512_DIGEST_LENGTH);
+ break;
+ case SHA224_DIGEST_LENGTH: {
+ OUTPUT_RESULT(out, SHA224_DIGEST_LENGTH);
/*
* For 224 bits, there are four bytes left over that have to be
* processed separately.
{
SHA_LONG64 t = c->h[SHA224_DIGEST_LENGTH / 8];
- *(md++) = (unsigned char)(t >> 56);
- *(md++) = (unsigned char)(t >> 48);
- *(md++) = (unsigned char)(t >> 40);
- *(md++) = (unsigned char)(t >> 32);
- }
- break;
- case SHA256_DIGEST_LENGTH:
- for (n = 0; n < SHA256_DIGEST_LENGTH / 8; n++) {
- SHA_LONG64 t = c->h[n];
-
- *(md++) = (unsigned char)(t >> 56);
- *(md++) = (unsigned char)(t >> 48);
- *(md++) = (unsigned char)(t >> 40);
- *(md++) = (unsigned char)(t >> 32);
- *(md++) = (unsigned char)(t >> 24);
- *(md++) = (unsigned char)(t >> 16);
- *(md++) = (unsigned char)(t >> 8);
- *(md++) = (unsigned char)(t);
- }
- break;
- case SHA384_DIGEST_LENGTH:
- for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) {
- SHA_LONG64 t = c->h[n];
-
- *(md++) = (unsigned char)(t >> 56);
- *(md++) = (unsigned char)(t >> 48);
- *(md++) = (unsigned char)(t >> 40);
- *(md++) = (unsigned char)(t >> 32);
- *(md++) = (unsigned char)(t >> 24);
- *(md++) = (unsigned char)(t >> 16);
- *(md++) = (unsigned char)(t >> 8);
- *(md++) = (unsigned char)(t);
- }
- break;
- case SHA512_DIGEST_LENGTH:
- for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) {
- SHA_LONG64 t = c->h[n];
-
- *(md++) = (unsigned char)(t >> 56);
- *(md++) = (unsigned char)(t >> 48);
- *(md++) = (unsigned char)(t >> 40);
- *(md++) = (unsigned char)(t >> 32);
- *(md++) = (unsigned char)(t >> 24);
- *(md++) = (unsigned char)(t >> 16);
- *(md++) = (unsigned char)(t >> 8);
- *(md++) = (unsigned char)(t);
+ *(out++) = (unsigned char)(t >> 56);
+ *(out++) = (unsigned char)(t >> 48);
+ *(out++) = (unsigned char)(t >> 40);
+ *(out++) = (unsigned char)(t >> 32);
}
break;
+ }
/* ... as well as make sure md_len is not abused. */
default:
return 0;
#include "slh_dsa_local.h"
#include "slh_dsa_key.h"
+#include "openssl/sha.h"
+#include "internal/sha3.h"
+#include "crypto/evp.h"
+#include "crypto/sha.h"
+
#define MAX_DIGEST_SIZE 64 /* SHA-512 is used for security category 3 & 5 */
+#define NIBBLE_MASK 15
-static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_sha2;
-static OSSL_SLH_HASHFUNC_PRF slh_prf_sha2;
-static OSSL_SLH_HASHFUNC_PRF_MSG slh_prf_msg_sha2;
-static OSSL_SLH_HASHFUNC_F slh_f_sha2;
-static OSSL_SLH_HASHFUNC_H slh_h_sha2;
-static OSSL_SLH_HASHFUNC_T slh_t_sha2;
+/* Most hash functions in SLH-DSA truncate the output */
+#define sha256_final(ctx, out, outlen) \
+ (ctx)->md_len = (unsigned int)outlen; \
+ SHA256_Final(out, ctx)
-static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_shake;
+#define sha512_final(ctx, out, outlen) \
+ (ctx)->md_len = (unsigned int)outlen; \
+ SHA512_Final(out, ctx)
+
+static OSSL_SLH_HASHFUNC_PRF slh_prf_sha256;
static OSSL_SLH_HASHFUNC_PRF slh_prf_shake;
-static OSSL_SLH_HASHFUNC_PRF_MSG slh_prf_msg_shake;
+
+static OSSL_SLH_HASHFUNC_F slh_f_sha256;
static OSSL_SLH_HASHFUNC_F slh_f_shake;
-static OSSL_SLH_HASHFUNC_H slh_h_shake;
-static OSSL_SLH_HASHFUNC_T slh_t_shake;
-static ossl_inline int xof_digest_3(EVP_MD_CTX *ctx,
- const uint8_t *in1, size_t in1_len,
- const uint8_t *in2, size_t in2_len,
- const uint8_t *in3, size_t in3_len,
- uint8_t *out, size_t out_len)
-{
- return (EVP_DigestInit_ex2(ctx, NULL, NULL) == 1
- && EVP_DigestUpdate(ctx, in1, in1_len) == 1
- && EVP_DigestUpdate(ctx, in2, in2_len) == 1
- && EVP_DigestUpdate(ctx, in3, in3_len) == 1
- && EVP_DigestFinalXOF(ctx, out, out_len) == 1);
-}
+static OSSL_SLH_HASHFUNC_PRF_MSG slh_prf_msg_sha2;
+static OSSL_SLH_HASHFUNC_PRF_MSG slh_prf_msg_shake;
-static ossl_inline int xof_digest_4(EVP_MD_CTX *ctx,
- const uint8_t *in1, size_t in1_len,
- const uint8_t *in2, size_t in2_len,
- const uint8_t *in3, size_t in3_len,
- const uint8_t *in4, size_t in4_len,
- uint8_t *out, size_t out_len)
-{
- return (EVP_DigestInit_ex2(ctx, NULL, NULL) == 1
- && EVP_DigestUpdate(ctx, in1, in1_len) == 1
- && EVP_DigestUpdate(ctx, in2, in2_len) == 1
- && EVP_DigestUpdate(ctx, in3, in3_len) == 1
- && EVP_DigestUpdate(ctx, in4, in4_len) == 1
- && EVP_DigestFinalXOF(ctx, out, out_len) == 1);
-}
+static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_sha256;
+static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_sha512;
+static OSSL_SLH_HASHFUNC_H_MSG slh_hmsg_shake;
+
+static OSSL_SLH_HASHFUNC_H slh_h_sha256;
+static OSSL_SLH_HASHFUNC_H slh_h_sha512;
+static OSSL_SLH_HASHFUNC_H slh_h_shake;
+static OSSL_SLH_HASHFUNC_T slh_t_sha256;
+static OSSL_SLH_HASHFUNC_T slh_t_sha512;
+static OSSL_SLH_HASHFUNC_wots_pk_gen slh_wots_pk_gen_sha2;
+static OSSL_SLH_HASHFUNC_wots_pk_gen slh_wots_pk_gen_shake;
+
+static const uint8_t zeros[128] = { 0 };
/* See FIPS 205 Section 11.1 */
static int
-slh_hmsg_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *r,
+slh_hmsg_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *r,
const uint8_t *pk_seed, const uint8_t *pk_root,
const uint8_t *msg, size_t msg_len,
uint8_t *out, size_t out_len)
{
- const SLH_DSA_PARAMS *params = ctx->key->params;
+ KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->shactx);
+ const SLH_DSA_PARAMS *params = hctx->key->params;
size_t m = params->m;
size_t n = params->n;
- return xof_digest_4(ctx->md_ctx, r, n, pk_seed, n, pk_root, n,
- msg, msg_len, out, m);
+ ossl_sha3_reset(sctx);
+ ossl_sha3_absorb(sctx, r, n);
+ ossl_sha3_absorb(sctx, pk_seed, n);
+ ossl_sha3_absorb(sctx, pk_root, n);
+ ossl_sha3_absorb(sctx, msg, msg_len);
+ ossl_sha3_final(sctx, out, m);
+ return 1;
}
static int
-slh_prf_shake(SLH_DSA_HASH_CTX *ctx,
- const uint8_t *pk_seed, const uint8_t *sk_seed,
- const uint8_t *adrs, uint8_t *out, size_t out_len)
+slh_prf_msg_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *sk_prf,
+ const uint8_t *opt_rand, const uint8_t *msg, size_t msg_len,
+ WPACKET *pkt)
{
- const SLH_DSA_PARAMS *params = ctx->key->params;
+ unsigned char out[SLH_MAX_N];
+ const SLH_DSA_PARAMS *params = hctx->key->params;
size_t n = params->n;
-
- return xof_digest_3(ctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE,
- sk_seed, n, out, n);
+ KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->shactx);
+
+ ossl_sha3_reset(sctx);
+ ossl_sha3_absorb(sctx, sk_prf, n);
+ ossl_sha3_absorb(sctx, opt_rand, n);
+ ossl_sha3_absorb(sctx, msg, msg_len);
+ ossl_sha3_final(sctx, out, n);
+ return WPACKET_memcpy(pkt, out, n);
}
static int
-slh_prf_msg_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *sk_prf,
- const uint8_t *opt_rand, const uint8_t *msg, size_t msg_len,
- WPACKET *pkt)
+slh_f_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
+ const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
{
- unsigned char out[SLH_MAX_N];
- const SLH_DSA_PARAMS *params = ctx->key->params;
+ const SLH_DSA_PARAMS *params = hctx->key->params;
size_t n = params->n;
+ KECCAK1600_CTX sctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed));
- return xof_digest_3(ctx->md_ctx, sk_prf, n, opt_rand, n, msg, msg_len, out, n)
- && WPACKET_memcpy(pkt, out, n);
+ ossl_sha3_absorb(&sctx, adrs, SLH_ADRS_SIZE);
+ ossl_sha3_absorb(&sctx, m1, m1_len);
+ ossl_sha3_final(&sctx, out, n);
+ return 1;
}
static int
-slh_f_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *pk_seed, const uint8_t *adrs,
- const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
+slh_prf_shake(SLH_DSA_HASH_CTX *hctx,
+ const uint8_t *pk_seed, const uint8_t *sk_seed,
+ const uint8_t *adrs, uint8_t *out, size_t out_len)
{
- const SLH_DSA_PARAMS *params = ctx->key->params;
+ const SLH_DSA_PARAMS *params = hctx->key->params;
size_t n = params->n;
+ KECCAK1600_CTX sctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed));
- return xof_digest_3(ctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, m1, m1_len, out, n);
+ ossl_sha3_absorb(&sctx, adrs, SLH_ADRS_SIZE);
+ ossl_sha3_absorb(&sctx, sk_seed, n);
+ ossl_sha3_final(&sctx, out, n);
+ return 1;
}
static int
-slh_h_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *pk_seed, const uint8_t *adrs,
+slh_h_shake(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
{
- const SLH_DSA_PARAMS *params = ctx->key->params;
+ KECCAK1600_CTX ctx = *((KECCAK1600_CTX *)(hctx->shactx_pkseed)), *sctx = &ctx;
+ const SLH_DSA_PARAMS *params = hctx->key->params;
size_t n = params->n;
- return xof_digest_4(ctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, m1, n, m2, n, out, n);
+ ossl_sha3_absorb(sctx, adrs, SLH_ADRS_SIZE);
+ ossl_sha3_absorb(sctx, m1, n);
+ ossl_sha3_absorb(sctx, m2, n);
+ ossl_sha3_final(sctx, out, n);
+ return 1;
}
+/* FIPS 205 Section 11.2.1 and 11.2.2 */
+
static int
-slh_t_shake(SLH_DSA_HASH_CTX *ctx, const uint8_t *pk_seed, const uint8_t *adrs,
- const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
+slh_hmsg_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
+ const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
+ uint8_t *out, size_t out_len)
{
- const SLH_DSA_PARAMS *params = ctx->key->params;
+ SHA256_CTX ctx, *sctx = &ctx;
+ const SLH_DSA_PARAMS *params = hctx->key->params;
+ size_t m = params->m;
size_t n = params->n;
+ uint8_t seed[2 * SLH_MAX_N + SHA256_DIGEST_LENGTH];
+ long seed_len = SHA256_DIGEST_LENGTH + (long)(2 * n);
- return xof_digest_3(ctx->md_ctx, pk_seed, n, adrs, SLH_ADRS_SIZE, ml, ml_len, out, n);
-}
+ memcpy(seed, r, n);
+ memcpy(seed + n, pk_seed, n);
-static ossl_inline int
-digest_4(EVP_MD_CTX *ctx,
- const uint8_t *in1, size_t in1_len, const uint8_t *in2, size_t in2_len,
- const uint8_t *in3, size_t in3_len, const uint8_t *in4, size_t in4_len,
- uint8_t *out)
-{
- return (EVP_DigestInit_ex2(ctx, NULL, NULL) == 1
- && EVP_DigestUpdate(ctx, in1, in1_len) == 1
- && EVP_DigestUpdate(ctx, in2, in2_len) == 1
- && EVP_DigestUpdate(ctx, in3, in3_len) == 1
- && EVP_DigestUpdate(ctx, in4, in4_len) == 1
- && EVP_DigestFinal_ex(ctx, out, NULL) == 1);
+ SHA256_Init(sctx);
+ SHA256_Update(sctx, r, n);
+ SHA256_Update(sctx, pk_seed, n);
+ SHA256_Update(sctx, pk_root, n);
+ SHA256_Update(sctx, msg, msg_len);
+ return SHA256_Final(seed + 2 * n, sctx)
+ && (PKCS1_MGF1(out, (long)m, seed, seed_len, hctx->key->md) == 0);
}
-/* FIPS 205 Section 11.2.1 and 11.2.2 */
-
static int
-slh_hmsg_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
+slh_hmsg_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *r, const uint8_t *pk_seed,
const uint8_t *pk_root, const uint8_t *msg, size_t msg_len,
uint8_t *out, size_t out_len)
{
+ SHA512_CTX ctx, *sctx = &ctx;
const SLH_DSA_PARAMS *params = hctx->key->params;
size_t m = params->m;
size_t n = params->n;
- uint8_t seed[2 * SLH_MAX_N + MAX_DIGEST_SIZE];
- int sz = EVP_MD_get_size(hctx->key->md_big);
- size_t seed_len = (size_t)sz + 2 * n;
-
- if (sz <= 0)
- return 0;
+ uint8_t seed[2 * SLH_MAX_N + SHA512_DIGEST_LENGTH];
+ long seed_len = SHA512_DIGEST_LENGTH + (long)(2 * n);
memcpy(seed, r, n);
memcpy(seed + n, pk_seed, n);
- return digest_4(hctx->md_big_ctx, r, n, pk_seed, n, pk_root, n, msg, msg_len,
- seed + 2 * n)
- && (PKCS1_MGF1(out, (long)m, seed, (long)seed_len, hctx->key->md_big) == 0);
+
+ SHA512_Init(sctx);
+ SHA512_Update(sctx, r, n);
+ SHA512_Update(sctx, pk_seed, n);
+ SHA512_Update(sctx, pk_root, n);
+ SHA512_Update(sctx, msg, msg_len);
+ return SHA512_Final(seed + 2 * n, sctx)
+ && (PKCS1_MGF1(out, (long)m, seed, seed_len, hctx->key->md_sha512) == 0);
}
static int
* So we do a lazy update here on the first call.
*/
if (hctx->hmac_digest_used == 0) {
+ const char *nm = EVP_MD_get0_name(key->md_sha512 == NULL ? key->md : key->md_sha512);
+
p = params;
/* The underlying digest to be used */
- *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
- (char *)EVP_MD_get0_name(key->md_big), 0);
+ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)nm, 0);
if (key->propq != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
(char *)key->propq, 0);
return ret;
}
-static ossl_inline int
-do_hash(EVP_MD_CTX *ctx, size_t n, const uint8_t *pk_seed, const uint8_t *adrs,
- const uint8_t *m, size_t m_len, size_t b, uint8_t *out, size_t out_len)
+static int
+slh_prf_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed,
+ const uint8_t *sk_seed, const uint8_t *adrs,
+ uint8_t *out, size_t out_len)
{
- int ret;
- uint8_t zeros[128] = { 0 };
- uint8_t digest[MAX_DIGEST_SIZE];
+ SHA256_CTX ctx = *((SHA256_CTX *)hctx->shactx_pkseed), *sctx = &ctx;
+ size_t n = hctx->key->params->n;
- ret = digest_4(ctx, pk_seed, n, zeros, b - n, adrs, SLH_ADRSC_SIZE,
- m, m_len, digest);
- /* Truncated returned value is n = 16 bytes */
- memcpy(out, digest, n);
- return ret;
+ SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
+ SHA256_Update(sctx, sk_seed, n);
+ sha256_final(sctx, out, n);
+ return 1;
}
static int
-slh_prf_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed,
- const uint8_t *sk_seed, const uint8_t *adrs,
- uint8_t *out, size_t out_len)
+slh_wots_pk_gen_sha2(SLH_DSA_HASH_CTX *hctx,
+ const uint8_t *sk_seed, const uint8_t *pk_seed,
+ uint8_t *adrs, uint8_t *pk_out, size_t pk_out_len)
{
+ int ret = 0;
size_t n = hctx->key->params->n;
+ size_t i, j = 0, len = SLH_WOTS_LEN(n);
+ uint8_t sk[SLH_MAX_N];
+ SHA256_CTX *sctx = (SHA256_CTX *)(hctx->shactx_pkseed);
+ SHA256_CTX ctx;
+ const SLH_ADRS_FUNC *adrsf = hctx->key->adrs_func;
+ SLH_ADRS_DECLARE(sk_adrs);
+ SLH_ADRS_FN_DECLARE(adrsf, set_chain_address);
+ SLH_ADRS_FN_DECLARE(adrsf, set_hash_address);
+
+ adrsf->copy(sk_adrs, adrs);
+ adrsf->set_type_and_clear(sk_adrs, SLH_ADRS_TYPE_WOTS_PRF);
+ adrsf->copy_keypair_address(sk_adrs, adrs);
+
+ for (i = 0; i < len; ++i) { /* len = 2n + 3 */
+ set_chain_address(sk_adrs, (uint32_t)i);
+
+ /* PRF */
+ ctx = *sctx;
+ SHA256_Update(&ctx, sk_adrs, SLH_ADRSC_SIZE);
+ SHA256_Update(&ctx, sk_seed, n);
+ sha256_final(&ctx, sk, n);
+
+ set_chain_address(adrs, (uint32_t)i);
+ for (j = 0; j < NIBBLE_MASK; ++j) {
+ set_hash_address(adrs, (uint32_t)j);
+ /* F */
+ ctx = *sctx;
+ SHA256_Update(&ctx, adrs, SLH_ADRSC_SIZE);
+ SHA256_Update(&ctx, sk, n);
+ sha256_final(&ctx, sk, n);
+ }
+ memcpy(pk_out, sk, n);
+ pk_out += n;
+ }
+ ret = 1;
+ return ret;
+}
- return do_hash(hctx->md_ctx, n, pk_seed, adrs, sk_seed, n,
- OSSL_SLH_DSA_SHA2_NUM_ZEROS_H_AND_T_BOUND1, out, out_len);
+int slh_wots_pk_gen_shake(SLH_DSA_HASH_CTX *hctx,
+ const uint8_t *sk_seed, const uint8_t *pk_seed,
+ uint8_t *adrs, uint8_t *pk_out, size_t pk_out_len)
+{
+ int ret = 0;
+ size_t n = hctx->key->params->n;
+ size_t i, j = 0, len = SLH_WOTS_LEN(n);
+ uint8_t sk[SLH_MAX_N];
+ const SLH_ADRS_FUNC *adrsf = hctx->key->adrs_func;
+ SLH_ADRS_DECLARE(sk_adrs);
+ SLH_ADRS_FN_DECLARE(adrsf, set_chain_address);
+ SLH_ADRS_FN_DECLARE(adrsf, set_hash_address);
+ KECCAK1600_CTX *sctx = (KECCAK1600_CTX *)(hctx->shactx_pkseed);
+ KECCAK1600_CTX ctx;
+
+ adrsf->copy(sk_adrs, adrs);
+ adrsf->set_type_and_clear(sk_adrs, SLH_ADRS_TYPE_WOTS_PRF);
+ adrsf->copy_keypair_address(sk_adrs, adrs);
+
+ for (i = 0; i < len; ++i) { /* len = 2n + 3 */
+ set_chain_address(sk_adrs, (uint32_t)i);
+
+ /* PRF */
+ ctx = *sctx;
+ ossl_sha3_absorb(&ctx, sk_adrs, SLH_ADRS_SIZE);
+ ossl_sha3_absorb(&ctx, sk_seed, n);
+ ossl_sha3_final(&ctx, sk, n);
+
+ set_chain_address(adrs, (uint32_t)i);
+ for (j = 0; j < NIBBLE_MASK; ++j) {
+ set_hash_address(adrs, (uint32_t)j);
+ /* F */
+ ctx = *sctx;
+ ossl_sha3_absorb(&ctx, adrs, SLH_ADRS_SIZE);
+ ossl_sha3_absorb(&ctx, sk, n);
+ ossl_sha3_final(&ctx, sk, n);
+ }
+ memcpy(pk_out, sk, n);
+ pk_out += n;
+ }
+ ret = 1;
+ return ret;
}
static int
-slh_f_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
+slh_f_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
const uint8_t *m1, size_t m1_len, uint8_t *out, size_t out_len)
{
- return do_hash(hctx->md_ctx, hctx->key->params->n, pk_seed, adrs, m1, m1_len,
- OSSL_SLH_DSA_SHA2_NUM_ZEROS_H_AND_T_BOUND1, out, out_len);
+ SHA256_CTX ctx = *((SHA256_CTX *)hctx->shactx_pkseed), *sctx = &ctx;
+
+ SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
+ SHA256_Update(sctx, m1, m1_len);
+ sha256_final(sctx, out, hctx->key->params->n);
+ return 1;
}
static int
-slh_h_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
+slh_h_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
{
- uint8_t m[SLH_MAX_N * 2];
+ SHA256_CTX ctx = *((SHA256_CTX *)hctx->shactx_pkseed), *sctx = &ctx;
const SLH_DSA_PARAMS *prms = hctx->key->params;
size_t n = prms->n;
- memcpy(m, m1, n);
- memcpy(m + n, m2, n);
- return do_hash(hctx->md_big_ctx, n, pk_seed, adrs, m, 2 * n,
- prms->sha2_h_and_t_bound, out, out_len);
+ SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
+ SHA256_Update(sctx, m1, n);
+ SHA256_Update(sctx, m2, n);
+ sha256_final(sctx, out, n);
+ return 1;
+}
+
+static int
+slh_h_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
+ const uint8_t *m1, const uint8_t *m2, uint8_t *out, size_t out_len)
+{
+ SHA512_CTX ctx, *sctx = &ctx;
+ const SLH_DSA_PARAMS *prms = hctx->key->params;
+ size_t n = prms->n;
+
+ SHA512_Init(sctx);
+ SHA512_Update(sctx, pk_seed, n);
+ SHA512_Update(sctx, zeros, 128 - n);
+ SHA512_Update(sctx, adrs, SLH_ADRSC_SIZE);
+ SHA512_Update(sctx, m1, n);
+ SHA512_Update(sctx, m2, n);
+ sha512_final(sctx, out, n);
+ return 1;
+}
+
+static int
+slh_t_sha256(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
+ const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
+{
+ SHA256_CTX ctx = *((SHA256_CTX *)hctx->shactx_pkseed), *sctx = &ctx;
+
+ SHA256_Update(sctx, adrs, SLH_ADRSC_SIZE);
+ SHA256_Update(sctx, ml, ml_len);
+ sha256_final(sctx, out, hctx->key->params->n);
+ return 1;
}
static int
-slh_t_sha2(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
+slh_t_sha512(SLH_DSA_HASH_CTX *hctx, const uint8_t *pk_seed, const uint8_t *adrs,
const uint8_t *ml, size_t ml_len, uint8_t *out, size_t out_len)
{
+ SHA512_CTX ctx, *sctx = &ctx;
const SLH_DSA_PARAMS *prms = hctx->key->params;
+ size_t n = prms->n;
+
+ SHA512_Init(sctx);
+ SHA512_Update(sctx, pk_seed, n);
+ SHA512_Update(sctx, zeros, 128 - n);
+ SHA512_Update(sctx, adrs, SLH_ADRSC_SIZE);
+ SHA512_Update(sctx, ml, ml_len);
+ sha512_final(sctx, out, hctx->key->params->n);
+ return 1;
+}
+
+static int slh_hash_shake_precache(SLH_DSA_HASH_CTX *hctx, const uint8_t *pkseed, size_t n)
+{
+ KECCAK1600_CTX *ctx = NULL, *seedctx = NULL;
- return do_hash(hctx->md_big_ctx, prms->n, pk_seed, adrs, ml, ml_len,
- prms->sha2_h_and_t_bound, out, out_len);
+ ctx = ossl_shake256_new();
+ if (ctx == NULL)
+ return 0;
+ seedctx = OPENSSL_memdup(ctx, sizeof(*ctx));
+ if (seedctx == NULL) {
+ OPENSSL_free(ctx);
+ return 0;
+ }
+ ossl_sha3_absorb(seedctx, pkseed, n);
+ hctx->shactx = (void *)ctx;
+ hctx->shactx_pkseed = (void *)seedctx;
+ return 1;
}
-const SLH_HASH_FUNC *ossl_slh_get_hash_fn(int is_shake)
+static int slh_hash_shake_dup(SLH_DSA_HASH_CTX *dst, const SLH_DSA_HASH_CTX *src)
+{
+ if (src->shactx != NULL) {
+ dst->shactx = OPENSSL_memdup(src->shactx, sizeof(KECCAK1600_CTX));
+ if (dst->shactx == NULL)
+ return 0;
+ }
+ if (src->shactx_pkseed != NULL) {
+ dst->shactx_pkseed = OPENSSL_memdup(src->shactx_pkseed, sizeof(KECCAK1600_CTX));
+ if (dst->shactx_pkseed == NULL) {
+ OPENSSL_free(dst->shactx);
+ dst->shactx = NULL;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int slh_hash_sha256_precache(SLH_DSA_HASH_CTX *hctx, const uint8_t *pkseed, size_t n)
+{
+ SHA256_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx == NULL)
+ return 0;
+ SHA256_Init(ctx);
+ SHA256_Update(ctx, pkseed, n);
+ SHA256_Update(ctx, zeros, 64 - n);
+ hctx->shactx_pkseed = (void *)ctx;
+ return 1;
+}
+
+static int slh_hash_sha256_dup(SLH_DSA_HASH_CTX *dst, const SLH_DSA_HASH_CTX *src)
+{
+ if (src->shactx_pkseed != NULL) {
+ dst->shactx_pkseed = OPENSSL_memdup(src->shactx_pkseed, sizeof(SHA256_CTX));
+ if (dst->shactx_pkseed == NULL)
+ return 0;
+ }
+ return 1;
+}
+
+const SLH_HASH_FUNC *ossl_slh_get_hash_fn(int is_shake, int security_category)
{
static const SLH_HASH_FUNC methods[] = {
- { slh_hmsg_shake,
+ { slh_hash_shake_precache,
+ slh_hash_shake_dup,
+ slh_hmsg_shake,
slh_prf_shake,
slh_prf_msg_shake,
slh_f_shake,
slh_h_shake,
- slh_t_shake },
- { slh_hmsg_sha2,
- slh_prf_sha2,
+ slh_f_shake,
+ slh_wots_pk_gen_shake },
+ { slh_hash_sha256_precache,
+ slh_hash_sha256_dup,
+ slh_hmsg_sha256,
+ slh_prf_sha256,
+ slh_prf_msg_sha2,
+ slh_f_sha256,
+ slh_h_sha256,
+ slh_t_sha256,
+ slh_wots_pk_gen_sha2 },
+ { slh_hash_sha256_precache,
+ slh_hash_sha256_dup,
+ slh_hmsg_sha512,
+ slh_prf_sha256,
slh_prf_msg_sha2,
- slh_f_sha2,
- slh_h_sha2,
- slh_t_sha2 }
+ slh_f_sha256,
+ slh_h_sha512,
+ slh_t_sha512,
+ slh_wots_pk_gen_sha2 }
};
- return &methods[is_shake ? 0 : 1];
+ return &methods[is_shake ? 0 : (security_category == 1 ? 1 : 2)];
}