ML-DSA: Add AVX512VL SHAKE x4 multi-buffer integration

Changes:
- Adds new SHAKE x4 API to perform 4 SHAKE operations in parallel when AVX512VL is supported.
- Adds AVX512VL Keccak x4 assembly module (keccak1600x4-avx512vl).
- Adds internal SHA3 x4 APIs/context in sha3.h and wrappers in sha3_x4.c modules.
- Adds runtime dispatch for ML-DSA sample operations with an OSSL_ML_DSA_SAMPLE_OPS vtable.
  Callers obtain the correct implementation via ossl_ml_dsa_sample_ops(), which returns
  either the generic scalar ops functions, or the AVX512VL multi-buffer ops depending
  on the build and CPU capabilities.
- Adds x86-64 multi-buffer function implementation into ml_dsa_sample_hw_x86_64.inc,
  included in ml_dsa_sample.c when KECCAK1600_ASM and x86_64 are defined.

Co-authored-by: Tomasz Kantecki <tomasz.kantecki@intel.com>
Signed-off-by: Marcel Cornu <marcel.d.cornu@intel.com>

Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
MergeDate: Mon Jul 13 15:55:54 2026
(Merged from https://github.com/openssl/openssl/pull/31090)
This commit is contained in:
Marcel Cornu 2026-04-10 09:36:25 +00:00 committed by Tomas Mraz
parent 6736bd2cb6
commit a248ec771e
15 changed files with 3051 additions and 61 deletions

View file

@ -31,6 +31,10 @@ OpenSSL Releases
### Changes between 4.0 and 4.1 [xx XXX xxxx]
* Added AVX512 optimized SHAKE x4 operations for ML-DSA on x86_64.
*Marcel Cornu and Tomasz Kantecki*
* EC key point format simplification.
The point conversion form (compressed, uncompressed, or hybrid)

View file

@ -332,7 +332,7 @@ int ossl_ml_dsa_key_has(const ML_DSA_KEY *key, int selection)
* @returns 1 on success, or 0 on failure.
*/
static int public_from_private(const ML_DSA_KEY *key, EVP_MD_CTX *md_ctx,
VECTOR *t1, VECTOR *t0)
const OSSL_ML_DSA_SAMPLE_OPS *sample_ops, VECTOR *t1, VECTOR *t0)
{
int ret = 0;
const ML_DSA_PARAMS *params = key->params;
@ -351,7 +351,7 @@ static int public_from_private(const ML_DSA_KEY *key, EVP_MD_CTX *md_ctx,
matrix_init(&a_ntt, s1_ntt.poly + l, k, l);
/* Using rho generate A' = A in NTT form */
if (!matrix_expand_A(md_ctx, key->shake128_md, key->rho, &a_ntt))
if (!sample_ops->matrix_expand_A(md_ctx, key->shake128_md, key->rho, &a_ntt))
goto err;
/* t = NTT_inv(A' * NTT(s1)) + s2 */
@ -376,6 +376,7 @@ err:
int ossl_ml_dsa_key_public_from_private(ML_DSA_KEY *key)
{
int ret = 0;
const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops();
VECTOR t0;
EVP_MD_CTX *md_ctx = NULL;
@ -383,7 +384,7 @@ int ossl_ml_dsa_key_public_from_private(ML_DSA_KEY *key)
return 0;
ret = ((md_ctx = EVP_MD_CTX_new()) != NULL)
&& ossl_ml_dsa_key_pub_alloc(key) /* allocate space for t1 */
&& public_from_private(key, md_ctx, &key->t1, &t0)
&& public_from_private(key, md_ctx, sample_ops, &key->t1, &t0)
&& vector_equal(&t0, &key->t0) /* compare the generated t0 to the expected */
&& ossl_ml_dsa_pk_encode(key)
&& shake_xof(md_ctx, key->shake256_md,
@ -397,6 +398,7 @@ int ossl_ml_dsa_key_public_from_private(ML_DSA_KEY *key)
int ossl_ml_dsa_key_pairwise_check(const ML_DSA_KEY *key)
{
int ret = 0;
const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops();
VECTOR t1, t0;
POLY *polys = NULL;
uint32_t k = (uint32_t)key->params->k;
@ -414,7 +416,7 @@ int ossl_ml_dsa_key_pairwise_check(const ML_DSA_KEY *key)
vector_init(&t1, polys, k);
vector_init(&t0, polys + k, k);
if (!public_from_private(key, md_ctx, &t1, &t0))
if (!public_from_private(key, md_ctx, sample_ops, &t1, &t0))
goto err;
ret = vector_equal(&t1, &key->t1) && vector_equal(&t0, &key->t0);
@ -435,6 +437,7 @@ err:
static int keygen_internal(ML_DSA_KEY *out)
{
int ret = 0;
const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops();
uint8_t augmented_seed[ML_DSA_SEED_BYTES + 2];
uint8_t expanded_seed[ML_DSA_RHO_BYTES + ML_DSA_PRIV_SEED_BYTES + ML_DSA_K_BYTES];
const uint8_t *const rho = expanded_seed; /* p = Public Random Seed */
@ -461,8 +464,9 @@ static int keygen_internal(ML_DSA_KEY *out)
memcpy(out->rho, rho, sizeof(out->rho));
memcpy(out->K, K, sizeof(out->K));
ret = vector_expand_S(md_ctx, out->shake256_md, params->eta, priv_seed, &out->s1, &out->s2)
&& public_from_private(out, md_ctx, &out->t1, &out->t0)
ret = sample_ops->vector_expand_S(md_ctx, out->shake256_md, params->eta,
priv_seed, &out->s1, &out->s2)
&& public_from_private(out, md_ctx, sample_ops, &out->t1, &out->t0)
&& ossl_ml_dsa_pk_encode(out)
&& shake_xof(md_ctx, out->shake256_md, out->pub_encoding, out->params->pk_len,
out->tr, sizeof(out->tr))

View file

@ -59,10 +59,21 @@ typedef struct vector_st VECTOR;
typedef struct matrix_st MATRIX;
typedef struct ml_dsa_sig_st ML_DSA_SIG;
int ossl_ml_dsa_matrix_expand_A(EVP_MD_CTX *g_ctx, const EVP_MD *md,
typedef int(ML_DSA_MATRIX_EXPAND_A_FN)(EVP_MD_CTX *g_ctx, const EVP_MD *md,
const uint8_t *rho, MATRIX *out);
int ossl_ml_dsa_vector_expand_S(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta,
const uint8_t *seed, VECTOR *s1, VECTOR *s2);
typedef int(ML_DSA_VECTOR_EXPAND_S_FN)(EVP_MD_CTX *h_ctx, const EVP_MD *md,
int eta, const uint8_t *seed, VECTOR *s1, VECTOR *s2);
typedef void(ML_DSA_VECTOR_EXPAND_MASK_FN)(VECTOR *out,
const uint8_t rho_prime[ML_DSA_RHO_PRIME_BYTES], uint32_t kappa, uint32_t gamma1,
EVP_MD_CTX *h_ctx, const EVP_MD *md);
typedef struct ossl_ml_dsa_sample_ops_st {
ML_DSA_MATRIX_EXPAND_A_FN *matrix_expand_A;
ML_DSA_VECTOR_EXPAND_S_FN *vector_expand_S;
ML_DSA_VECTOR_EXPAND_MASK_FN *vector_expand_mask;
} OSSL_ML_DSA_SAMPLE_OPS;
const OSSL_ML_DSA_SAMPLE_OPS *ossl_ml_dsa_sample_ops(void);
void ossl_ml_dsa_matrix_mult_vector(const MATRIX *matrix_kl, const VECTOR *vl,
VECTOR *vk);
int ossl_ml_dsa_poly_expand_mask(POLY *out, const uint8_t *seed, size_t seed_len,

View file

@ -41,11 +41,4 @@ matrix_mult_vector(const MATRIX *a, const VECTOR *s, VECTOR *t)
ossl_ml_dsa_matrix_mult_vector(a, s, t);
}
static ossl_inline ossl_unused int
matrix_expand_A(EVP_MD_CTX *g_ctx, const EVP_MD *md, const uint8_t *rho,
MATRIX *out)
{
return ossl_ml_dsa_matrix_expand_A(g_ctx, md, rho, out);
}
#endif /* !defined(OSSL_LIBCRYPTO_ML_DSA_ML_DSA_MATRIX_H) */

View file

@ -8,6 +8,7 @@
*/
#include <openssl/byteorder.h>
#include <openssl/crypto.h>
#include "ml_dsa_local.h"
#include "ml_dsa_vector.h"
#include "ml_dsa_matrix.h"
@ -35,6 +36,10 @@ typedef int(COEFF_FROM_NIBBLE_FUNC)(uint32_t nibble, uint32_t *out);
static COEFF_FROM_NIBBLE_FUNC coeff_from_nibble_4;
static COEFF_FROM_NIBBLE_FUNC coeff_from_nibble_2;
static ML_DSA_MATRIX_EXPAND_A_FN matrix_expand_A_scalar;
static ML_DSA_VECTOR_EXPAND_S_FN vector_expand_S_scalar;
static ML_DSA_VECTOR_EXPAND_MASK_FN vector_expand_mask_scalar;
/**
* @brief Combine 3 bytes to form an coefficient.
* See FIPS 204, Algorithm 14, CoeffFromThreeBytes()
@ -160,13 +165,14 @@ static int rej_bounded_poly(EVP_MD_CTX *h_ctx, const EVP_MD *md,
COEFF_FROM_NIBBLE_FUNC *coef_from_nibble,
const uint8_t *seed, size_t seed_len, POLY *out)
{
int ret = 0;
int j = 0;
uint32_t z0, z1;
uint8_t blocks[SHAKE256_BLOCKSIZE], *b, *end = blocks + sizeof(blocks);
/* Instead of just squeezing 1 byte at a time, we grab a whole block */
if (!shake_xof(h_ctx, md, seed, seed_len, blocks, sizeof(blocks)))
return 0;
goto err;
while (1) {
for (b = blocks; b < end; b++) {
@ -174,15 +180,22 @@ static int rej_bounded_poly(EVP_MD_CTX *h_ctx, const EVP_MD *md,
z1 = *b >> 4; /* high nibble of byte */
if (coef_from_nibble(z0, &out->coeff[j])
&& ++j >= ML_DSA_NUM_POLY_COEFFICIENTS)
return 1;
&& ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) {
ret = 1;
goto err;
}
if (coef_from_nibble(z1, &out->coeff[j])
&& ++j >= ML_DSA_NUM_POLY_COEFFICIENTS)
return 1;
&& ++j >= ML_DSA_NUM_POLY_COEFFICIENTS) {
ret = 1;
goto err;
}
}
if (!EVP_DigestSqueeze(h_ctx, blocks, sizeof(blocks)))
return 0;
goto err;
}
err:
OPENSSL_cleanse(blocks, sizeof(blocks));
return ret;
}
/**
@ -198,7 +211,7 @@ static int rej_bounded_poly(EVP_MD_CTX *h_ctx, const EVP_MD *md,
* in the range of 0..q-1.
* @returns 1 if the matrix was generated, or 0 on error.
*/
int ossl_ml_dsa_matrix_expand_A(EVP_MD_CTX *g_ctx, const EVP_MD *md,
static int matrix_expand_A_scalar(EVP_MD_CTX *g_ctx, const EVP_MD *md,
const uint8_t *rho, MATRIX *out)
{
int ret = 0;
@ -208,7 +221,6 @@ int ossl_ml_dsa_matrix_expand_A(EVP_MD_CTX *g_ctx, const EVP_MD *md,
/* The seed used for each matrix element is rho + column_index + row_index */
memcpy(derived_seed, rho, ML_DSA_RHO_BYTES);
for (i = 0; i < out->k; i++) {
for (j = 0; j < out->l; j++) {
derived_seed[ML_DSA_RHO_BYTES + 1] = (uint8_t)i;
@ -241,7 +253,7 @@ err:
* the range (q-eta)..0..eta
* @returns 1 if s1 and s2 were successfully generated, or 0 otherwise.
*/
int ossl_ml_dsa_vector_expand_S(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta,
static int vector_expand_S_scalar(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta,
const uint8_t *seed, VECTOR *s1, VECTOR *s2)
{
int ret = 0;
@ -275,6 +287,7 @@ int ossl_ml_dsa_vector_expand_S(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta,
}
ret = 1;
err:
OPENSSL_cleanse(derived_seed, sizeof(derived_seed));
return ret;
}
@ -285,9 +298,11 @@ int ossl_ml_dsa_poly_expand_mask(POLY *out, const uint8_t *seed, size_t seed_len
{
uint8_t buf[32 * 20];
size_t buf_len = 32 * (gamma1 == ML_DSA_GAMMA1_TWO_POWER_19 ? 20 : 18);
return shake_xof(h_ctx, md, seed, seed_len, buf, buf_len)
int ret = shake_xof(h_ctx, md, seed, seed_len, buf, buf_len)
&& ossl_ml_dsa_poly_decode_expand_mask(out, buf, buf_len, gamma1);
OPENSSL_cleanse(buf, sizeof(buf));
return ret;
}
/*
@ -376,3 +391,46 @@ int ossl_ml_dsa_poly_sample_in_ball(POLY *out_c, const uint8_t *seed, int seed_l
}
return 1;
}
static void vector_expand_mask_scalar(VECTOR *out,
const uint8_t rho_prime[ML_DSA_RHO_PRIME_BYTES], uint32_t kappa, uint32_t gamma1,
EVP_MD_CTX *h_ctx, const EVP_MD *md)
{
size_t i;
uint8_t derived_seed[ML_DSA_RHO_PRIME_BYTES + 2];
memcpy(derived_seed, rho_prime, ML_DSA_RHO_PRIME_BYTES);
for (i = 0; i < out->num_poly; i++) {
size_t index = kappa + i;
derived_seed[ML_DSA_RHO_PRIME_BYTES] = index & 0xFF;
derived_seed[ML_DSA_RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF;
poly_expand_mask(out->poly + i, derived_seed, sizeof(derived_seed),
gamma1, h_ctx, md);
}
OPENSSL_cleanse(derived_seed, sizeof(derived_seed));
}
static const OSSL_ML_DSA_SAMPLE_OPS ml_dsa_sample_generic_meth = {
matrix_expand_A_scalar,
vector_expand_S_scalar,
vector_expand_mask_scalar
};
#if defined(KECCAK1600_ASM) \
&& (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \
&& !defined(OPENSSL_NO_ASM)
#include "ml_dsa_sample_hw_x86_64.inc"
const OSSL_ML_DSA_SAMPLE_OPS *ossl_ml_dsa_sample_ops(void)
{
if (SHA3_avx512vl_capable())
return &ml_dsa_sample_x86_64;
return &ml_dsa_sample_generic_meth;
}
#else
const OSSL_ML_DSA_SAMPLE_OPS *ossl_ml_dsa_sample_ops(void)
{
return &ml_dsa_sample_generic_meth;
}
#endif

View file

@ -0,0 +1,307 @@
/*
* Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2026 Intel Corporation. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#define ML_DSA_SHAKE_X4_BATCH_SIZE 4
#define ML_DSA_SHAKE_X4_DONE_MASK ((1 << ML_DSA_SHAKE_X4_BATCH_SIZE) - 1)
#define ML_DSA_EXPAND_MASK_BYTES_PER_COEFF 32
#define ML_DSA_EXPAND_MASK_COEFFS_GAMMA1_19 20
#define ML_DSA_EXPAND_MASK_COEFFS_GAMMA1_17 18
#define ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_19 \
(ML_DSA_EXPAND_MASK_BYTES_PER_COEFF * ML_DSA_EXPAND_MASK_COEFFS_GAMMA1_19)
#define ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_17 \
(ML_DSA_EXPAND_MASK_BYTES_PER_COEFF * ML_DSA_EXPAND_MASK_COEFFS_GAMMA1_17)
#define ML_DSA_EXPAND_MASK_BUF_SIZE(gamma1) \
((gamma1) == ML_DSA_GAMMA1_TWO_POWER_19 \
? ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_19 \
: ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_17)
static ossl_unused int rej_ntt_poly_mb(const uint8_t *seeds[ML_DSA_SHAKE_X4_BATCH_SIZE],
const size_t seed_len, POLY *outs[ML_DSA_SHAKE_X4_BATCH_SIZE], const size_t count)
{
KECCAK1600_X4_AVX512VL_CTX ctx;
uint8_t blocks[ML_DSA_SHAKE_X4_BATCH_SIZE][SHAKE128_BLOCKSIZE];
int coeff_idx[ML_DSA_SHAKE_X4_BATCH_SIZE] = { 0, 0, 0, 0 };
size_t done_mask = 0;
size_t lane;
for (lane = count; lane < ML_DSA_SHAKE_X4_BATCH_SIZE; lane++)
done_mask |= ((size_t)1 << lane);
ossl_sha3_shake128_x4_inc_init_avx512vl(&ctx);
ossl_sha3_shake128_x4_inc_absorb_avx512vl(&ctx, seeds[0], seeds[1],
seeds[2], seeds[3], seed_len);
while (done_mask != ML_DSA_SHAKE_X4_DONE_MASK) {
ossl_sha3_shake128_x4_inc_squeeze_avx512vl(blocks[0], blocks[1],
blocks[2], blocks[3], SHAKE128_BLOCKSIZE, &ctx);
for (lane = 0; lane < ML_DSA_SHAKE_X4_BATCH_SIZE; lane++) {
if (done_mask & ((size_t)1 << lane))
continue;
const uint8_t *b = blocks[lane];
const uint8_t *end = b + SHAKE128_BLOCKSIZE;
for (; b < end && coeff_idx[lane] < ML_DSA_NUM_POLY_COEFFICIENTS; b += 3) {
uint32_t *coeff_ptr = &(outs[lane]->coeff[coeff_idx[lane]]);
if (coeff_from_three_bytes(b, coeff_ptr))
coeff_idx[lane]++;
}
if (coeff_idx[lane] >= ML_DSA_NUM_POLY_COEFFICIENTS)
done_mask |= ((size_t)1 << lane);
}
}
return 1;
}
static void vector_expand_mask_mb(VECTOR *out,
const uint8_t rho_prime[ML_DSA_RHO_PRIME_BYTES], const uint32_t kappa, const uint32_t gamma1,
EVP_MD_CTX *h_ctx, const EVP_MD *md)
{
size_t i;
const size_t num_polys = out->num_poly;
uint8_t derived_seeds[ML_DSA_SHAKE_X4_BATCH_SIZE][ML_DSA_RHO_PRIME_BYTES + 2];
const size_t seed_len = sizeof(derived_seeds[0]);
const size_t buf_size = ML_DSA_EXPAND_MASK_BUF_SIZE(gamma1);
uint8_t buffers[ML_DSA_SHAKE_X4_BATCH_SIZE][ML_DSA_EXPAND_MASK_BUF_SIZE_GAMMA1_19];
(void)h_ctx;
(void)md;
for (i = 0; i < ML_DSA_SHAKE_X4_BATCH_SIZE; i++)
memcpy(derived_seeds[i], rho_prime, ML_DSA_RHO_PRIME_BYTES);
for (i = 0; i + (ML_DSA_SHAKE_X4_BATCH_SIZE - 1) < num_polys; i += ML_DSA_SHAKE_X4_BATCH_SIZE) {
size_t b;
for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) {
const size_t index = kappa + i + b;
derived_seeds[b][ML_DSA_RHO_PRIME_BYTES] = index & 0xFF;
derived_seeds[b][ML_DSA_RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF;
}
ossl_sha3_shake256_x4_avx512vl(buffers[0], buffers[1], buffers[2], buffers[3], buf_size,
derived_seeds[0], derived_seeds[1], derived_seeds[2], derived_seeds[3], seed_len);
ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 0], buffers[0], buf_size, gamma1);
ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 1], buffers[1], buf_size, gamma1);
ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 2], buffers[2], buf_size, gamma1);
ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 3], buffers[3], buf_size, gamma1);
}
/*
* num_polys is always 4 (ML-DSA-44), 5 (ML-DSA-65), or 7 (ML-DSA-87), so the
* above loops will always runs at least once, initializing derived_seeds.
* As a result, 'left' below will be 0, 1, or 3, meaning the 4 way shake will
* recalculate values that are not used.
*/
if (i < num_polys) {
const size_t left = num_polys - i;
size_t b;
for (b = 0; b < left; b++) {
const size_t index = kappa + i + b;
derived_seeds[b][ML_DSA_RHO_PRIME_BYTES] = (uint8_t)index;
derived_seeds[b][ML_DSA_RHO_PRIME_BYTES + 1] = (uint8_t)(index >> 8);
}
ossl_sha3_shake256_x4_avx512vl(buffers[0], buffers[1], buffers[2], buffers[3], buf_size,
derived_seeds[0], derived_seeds[1], derived_seeds[2], derived_seeds[3], seed_len);
ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 0], buffers[0], buf_size, gamma1);
if ((i + 1) < num_polys)
ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 1], buffers[1], buf_size, gamma1);
if ((i + 2) < num_polys)
ossl_ml_dsa_poly_decode_expand_mask(&out->poly[i + 2], buffers[2], buf_size, gamma1);
}
OPENSSL_cleanse(buffers, sizeof(buffers));
OPENSSL_cleanse(derived_seeds, sizeof(derived_seeds));
}
static ossl_unused int rej_bounded_poly_mb(COEFF_FROM_NIBBLE_FUNC *coef_from_nibble,
const uint8_t *seeds[ML_DSA_SHAKE_X4_BATCH_SIZE], const size_t seed_len,
POLY *outs[ML_DSA_SHAKE_X4_BATCH_SIZE], const size_t count)
{
KECCAK1600_X4_AVX512VL_CTX ctx;
uint8_t blocks[ML_DSA_SHAKE_X4_BATCH_SIZE][SHAKE256_BLOCKSIZE];
int coeff_idx[ML_DSA_SHAKE_X4_BATCH_SIZE] = { 0, 0, 0, 0 };
size_t done_mask = 0;
size_t lane;
for (lane = count; lane < ML_DSA_SHAKE_X4_BATCH_SIZE; lane++)
done_mask |= ((size_t)1 << lane);
ossl_sha3_shake256_x4_inc_init_avx512vl(&ctx);
ossl_sha3_shake256_x4_inc_absorb_avx512vl(&ctx, seeds[0], seeds[1],
seeds[2], seeds[3], seed_len);
while (done_mask != ML_DSA_SHAKE_X4_DONE_MASK) {
ossl_sha3_shake256_x4_inc_squeeze_avx512vl(blocks[0], blocks[1],
blocks[2], blocks[3], SHAKE256_BLOCKSIZE, &ctx);
for (lane = 0; lane < ML_DSA_SHAKE_X4_BATCH_SIZE; lane++) {
if (done_mask & ((size_t)1 << lane))
continue;
const uint8_t *b = blocks[lane];
const uint8_t *end = b + SHAKE256_BLOCKSIZE;
for (; b < end && coeff_idx[lane] < ML_DSA_NUM_POLY_COEFFICIENTS; b++) {
uint32_t z0 = *b & 0x0F;
uint32_t z1 = *b >> 4;
if (coef_from_nibble(z0, &outs[lane]->coeff[coeff_idx[lane]]))
coeff_idx[lane]++;
if (coeff_idx[lane] >= ML_DSA_NUM_POLY_COEFFICIENTS) {
done_mask |= ((size_t)1 << lane);
break;
}
if (coef_from_nibble(z1, &outs[lane]->coeff[coeff_idx[lane]]))
coeff_idx[lane]++;
if (coeff_idx[lane] >= ML_DSA_NUM_POLY_COEFFICIENTS) {
done_mask |= ((size_t)1 << lane);
break;
}
}
}
}
OPENSSL_cleanse(blocks, sizeof(blocks));
ossl_sha3_shake256_x4_inc_cleanup_avx512vl(&ctx);
return 1;
}
static int matrix_expand_A_mb(EVP_MD_CTX *g_ctx, const EVP_MD *md,
const uint8_t *rho, MATRIX *out)
{
size_t b, idx;
uint8_t derived_seeds[ML_DSA_SHAKE_X4_BATCH_SIZE][ML_DSA_RHO_BYTES + 2];
const size_t seed_len = sizeof(derived_seeds[0]);
const uint8_t *seeds[ML_DSA_SHAKE_X4_BATCH_SIZE];
POLY *polys[ML_DSA_SHAKE_X4_BATCH_SIZE];
POLY *poly = out->m_poly;
for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) {
memcpy(derived_seeds[b], rho, ML_DSA_RHO_BYTES);
seeds[b] = derived_seeds[b];
}
for (idx = 0; (idx + ML_DSA_SHAKE_X4_BATCH_SIZE - 1) < (out->k * out->l);
idx += ML_DSA_SHAKE_X4_BATCH_SIZE) {
for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) {
const size_t row = (idx + b) / out->l;
const size_t col = (idx + b) % out->l;
derived_seeds[b][ML_DSA_RHO_BYTES] = (uint8_t)col;
derived_seeds[b][ML_DSA_RHO_BYTES + 1] = (uint8_t)row;
polys[b] = &poly[idx + b];
}
if (!rej_ntt_poly_mb(seeds, seed_len, polys, 4))
return 0;
}
if (idx < (out->k * out->l)) {
const size_t left = (out->k * out->l) - idx;
for (b = 0; b < left; b++) {
const size_t row = (idx + b) / out->l;
const size_t col = (idx + b) % out->l;
derived_seeds[b][ML_DSA_RHO_BYTES] = (uint8_t)col;
derived_seeds[b][ML_DSA_RHO_BYTES + 1] = (uint8_t)row;
polys[b] = &poly[idx + b];
}
if (!rej_ntt_poly_mb(seeds, seed_len, polys, left))
return 0;
}
return 1;
}
static int vector_expand_S_mb(EVP_MD_CTX *h_ctx, const EVP_MD *md, const int eta,
const uint8_t *seed, VECTOR *s1, VECTOR *s2)
{
int ret = 0;
size_t b, idx;
const size_t l = s1->num_poly;
const size_t total = l + s2->num_poly;
uint8_t derived_seeds[ML_DSA_SHAKE_X4_BATCH_SIZE][ML_DSA_PRIV_SEED_BYTES + 2];
const uint8_t *seeds[ML_DSA_SHAKE_X4_BATCH_SIZE];
const size_t seed_len = sizeof(derived_seeds[0]);
POLY *polys[ML_DSA_SHAKE_X4_BATCH_SIZE];
COEFF_FROM_NIBBLE_FUNC *coef_from_nibble_fn = (eta == ML_DSA_ETA_4) ? coeff_from_nibble_4 : coeff_from_nibble_2;
for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) {
memcpy(derived_seeds[b], seed, ML_DSA_PRIV_SEED_BYTES);
seeds[b] = derived_seeds[b];
}
for (idx = 0; (idx + ML_DSA_SHAKE_X4_BATCH_SIZE - 1) < total; idx += ML_DSA_SHAKE_X4_BATCH_SIZE) {
for (b = 0; b < ML_DSA_SHAKE_X4_BATCH_SIZE; b++) {
const size_t poly_idx = idx + b;
derived_seeds[b][ML_DSA_PRIV_SEED_BYTES] = (uint8_t)(poly_idx);
derived_seeds[b][ML_DSA_PRIV_SEED_BYTES + 1] = (uint8_t)(poly_idx >> 8);
if (poly_idx < l)
polys[b] = &s1->poly[poly_idx];
else
polys[b] = &s2->poly[poly_idx - l];
}
if (!rej_bounded_poly_mb(coef_from_nibble_fn,
seeds, seed_len, polys, ML_DSA_SHAKE_X4_BATCH_SIZE))
goto err;
}
if (idx < total) {
const size_t batch_count = total - idx;
for (b = 0; b < batch_count; b++) {
const size_t poly_idx = idx + b;
derived_seeds[b][ML_DSA_PRIV_SEED_BYTES] = (uint8_t)(poly_idx);
derived_seeds[b][ML_DSA_PRIV_SEED_BYTES + 1] = (uint8_t)(poly_idx >> 8);
if (poly_idx < l)
polys[b] = &s1->poly[poly_idx];
else
polys[b] = &s2->poly[poly_idx - l];
}
if (!rej_bounded_poly_mb(coef_from_nibble_fn,
seeds, seed_len, polys, batch_count))
goto err;
}
ret = 1;
err:
OPENSSL_cleanse(derived_seeds, sizeof(derived_seeds));
return ret;
}
static const OSSL_ML_DSA_SAMPLE_OPS ml_dsa_sample_x86_64 = {
matrix_expand_A_mb,
vector_expand_S_mb,
vector_expand_mask_mb
};

View file

@ -164,6 +164,7 @@ static int ml_dsa_sign_internal(const ML_DSA_KEY *priv,
uint8_t *out_sig)
{
int ret = 0;
const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops();
const ML_DSA_PARAMS *params = priv->params;
EVP_MD_CTX *md_ctx = NULL;
uint32_t k = (uint32_t)params->k, l = (uint32_t)params->l;
@ -236,7 +237,7 @@ static int ml_dsa_sign_internal(const ML_DSA_KEY *priv,
CONSTTIME_SECRET_VECTOR(priv->s2);
CONSTTIME_SECRET_VECTOR(priv->t0);
if (!matrix_expand_A(md_ctx, priv->shake128_md, priv->rho, &a_ntt))
if (!sample_ops->matrix_expand_A(md_ctx, priv->shake128_md, priv->rho, &a_ntt))
goto err;
/*
@ -267,8 +268,8 @@ static int ml_dsa_sign_internal(const ML_DSA_KEY *priv,
VECTOR *ct0 = &w1;
uint32_t z_max, r0_max, ct0_max, h_ones;
vector_expand_mask(&y, rho_prime, sizeof(rho_prime), (uint32_t)kappa,
gamma1, md_ctx, priv->shake256_md);
sample_ops->vector_expand_mask(&y, rho_prime,
(uint32_t)kappa, gamma1, md_ctx, priv->shake256_md);
vector_copy(y_ntt, &y);
vector_ntt(y_ntt);
@ -391,6 +392,7 @@ static int ml_dsa_verify_internal(const ML_DSA_KEY *pub,
const uint8_t *sig_enc, size_t sig_enc_len)
{
int ret = 0;
const OSSL_ML_DSA_SAMPLE_OPS *sample_ops = ossl_ml_dsa_sample_ops();
uint8_t *alloc = NULL, *w1_encoded = NULL;
void *alloc_freeptr = NULL;
POLY *p, *c_ntt;
@ -448,7 +450,7 @@ static int ml_dsa_verify_internal(const ML_DSA_KEY *pub,
vector_init(&ct1_ntt, p + k, k);
if (!ossl_ml_dsa_sig_decode(&sig, sig_enc, sig_enc_len, pub->params)
|| !matrix_expand_A(md_ctx, pub->shake128_md, pub->rho, &a_ntt))
|| !sample_ops->matrix_expand_A(md_ctx, pub->shake128_md, pub->rho, &a_ntt))
goto err;
/* Compute verifiers challenge c_ntt = NTT(SampleInBall(c_tilde)) */

View file

@ -152,33 +152,6 @@ vector_mult_scalar(const VECTOR *lhs, const POLY *rhs, VECTOR *out)
ossl_ml_dsa_poly_ntt_mult(lhs->poly + i, rhs, out->poly + i);
}
static ossl_inline ossl_unused int
vector_expand_S(EVP_MD_CTX *h_ctx, const EVP_MD *md, int eta,
const uint8_t *seed, VECTOR *s1, VECTOR *s2)
{
return ossl_ml_dsa_vector_expand_S(h_ctx, md, eta, seed, s1, s2);
}
static ossl_inline ossl_unused void
vector_expand_mask(VECTOR *out, const uint8_t *rho_prime, size_t rho_prime_len,
uint32_t kappa, uint32_t gamma1,
EVP_MD_CTX *h_ctx, const EVP_MD *md)
{
size_t i;
uint8_t derived_seed[ML_DSA_RHO_PRIME_BYTES + 2];
memcpy(derived_seed, rho_prime, ML_DSA_RHO_PRIME_BYTES);
for (i = 0; i < out->num_poly; i++) {
size_t index = kappa + i;
derived_seed[ML_DSA_RHO_PRIME_BYTES] = index & 0xFF;
derived_seed[ML_DSA_RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF;
poly_expand_mask(out->poly + i, derived_seed, sizeof(derived_seed),
gamma1, h_ctx, md);
}
}
/* Scale back previously rounded value */
static ossl_inline ossl_unused void
vector_scale_power2_round_ntt(const VECTOR *in, VECTOR *out)

File diff suppressed because it is too large Load diff

View file

@ -65,7 +65,7 @@ ENDIF
$KECCAK1600ASM=keccak1600.c
IF[{- !$disabled{asm} -}]
$KECCAK1600ASM_x86=
$KECCAK1600ASM_x86_64=keccak1600-x86_64.s
$KECCAK1600ASM_x86_64=keccak1600-x86_64.s keccak1600x4-avx512vl.s sha3_x4_avx512vl.c
$KECCAK1600ASM_s390x=keccak1600-s390x.S
@ -198,4 +198,8 @@ GENERATE[keccak1600-avx512vl.S]=asm/keccak1600-avx512vl.pl
GENERATE[keccak1600-mmx.S]=asm/keccak1600-mmx.pl
GENERATE[keccak1600p8-ppc.S]=asm/keccak1600p8-ppc.pl
# keccak1600x4-avx512vl.s supports multi-squeeze
# Currently only used in ML-DSA on x86_64 with AVX-512VL support
GENERATE[keccak1600x4-avx512vl.s]=asm/keccak1600x4-avx512vl.pl
GENERATE[sha1-thumb.S]=asm/sha1-thumb.pl

View file

@ -0,0 +1,213 @@
/*
* Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2026 Intel Corporation. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* SHAKE x4 multi-buffer implementation for AVX-512VL
*
* This file provides incremental API wrappers around the AVX-512VL
* assembly implementations for processing 4 SHAKE instances in parallel.
*
* Callers should check SHA3_avx512vl_capable() before calling.
*/
#include "internal/sha3.h"
#include <openssl/crypto.h>
#include <string.h>
#if defined(KECCAK1600_ASM) \
&& (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \
&& !defined(OPENSSL_NO_ASM)
/* External assembly function declarations */
extern void SHA3_shake128_x4_inc_absorb_avx512vl(
uint64_t *state,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen);
extern void SHA3_shake256_x4_inc_absorb_avx512vl(
uint64_t *state,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen);
extern void SHA3_shake128_x4_inc_finalize_avx512vl(uint64_t *state);
extern void SHA3_shake256_x4_inc_finalize_avx512vl(uint64_t *state);
extern void SHA3_shake128_x4_inc_squeeze_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
uint64_t *state);
extern void SHA3_shake256_x4_inc_squeeze_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
uint64_t *state);
/* One-shot assembly function declarations */
extern void SHA3_shake128_x4_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen);
extern void SHA3_shake256_x4_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen);
/*
* SHAKE-128 x4 Implementation
*/
void ossl_sha3_shake128_x4_inc_init_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx)
{
memset(ctx->A, 0, sizeof(ctx->A));
ctx->rate = SHA3_BLOCKSIZE(128);
ctx->finalized = 0;
}
void ossl_sha3_shake128_x4_inc_absorb_avx512vl(
KECCAK1600_X4_AVX512VL_CTX *ctx,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen)
{
if (ctx->finalized) {
/* Error: cannot absorb after finalize */
return;
}
SHA3_shake128_x4_inc_absorb_avx512vl(
ctx->A, in0, in1, in2, in3, inlen);
}
void ossl_sha3_shake128_x4_inc_cleanup_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx)
{
OPENSSL_cleanse(ctx, sizeof(*ctx));
}
static void ossl_sha3_shake128_x4_inc_finalize_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx)
{
if (ctx->finalized) {
return; /* Already finalized */
}
SHA3_shake128_x4_inc_finalize_avx512vl(ctx->A);
ctx->finalized = 1;
}
void ossl_sha3_shake128_x4_inc_squeeze_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
KECCAK1600_X4_AVX512VL_CTX *ctx)
{
if (!ctx->finalized) {
/* Auto-finalize on first squeeze */
ossl_sha3_shake128_x4_inc_finalize_avx512vl(ctx);
}
SHA3_shake128_x4_inc_squeeze_avx512vl(
out0, out1, out2, out3, outlen, ctx->A);
}
/*
* SHAKE-256 x4 Implementation
*/
void ossl_sha3_shake256_x4_inc_init_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx)
{
memset(ctx->A, 0, sizeof(ctx->A));
ctx->rate = SHA3_BLOCKSIZE(256);
ctx->finalized = 0;
}
void ossl_sha3_shake256_x4_inc_absorb_avx512vl(
KECCAK1600_X4_AVX512VL_CTX *ctx,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen)
{
if (ctx->finalized) {
/* Error: cannot absorb after finalize */
return;
}
SHA3_shake256_x4_inc_absorb_avx512vl(
ctx->A, in0, in1, in2, in3, inlen);
}
void ossl_sha3_shake256_x4_inc_cleanup_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx)
{
OPENSSL_cleanse(ctx, sizeof(*ctx));
}
static void ossl_sha3_shake256_x4_inc_finalize_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx)
{
if (ctx->finalized) {
return; /* Already finalized */
}
SHA3_shake256_x4_inc_finalize_avx512vl(ctx->A);
ctx->finalized = 1;
}
void ossl_sha3_shake256_x4_inc_squeeze_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
KECCAK1600_X4_AVX512VL_CTX *ctx)
{
if (!ctx->finalized) {
/* Auto-finalize on first squeeze */
ossl_sha3_shake256_x4_inc_finalize_avx512vl(ctx);
}
SHA3_shake256_x4_inc_squeeze_avx512vl(
out0, out1, out2, out3, outlen, ctx->A);
}
/*
* Single-call wrapper APIs
*/
void ossl_sha3_shake128_x4_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen)
{
SHA3_shake128_x4_avx512vl(out0, out1, out2, out3, outlen,
in0, in1, in2, in3, inlen);
}
void ossl_sha3_shake256_x4_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen)
{
SHA3_shake256_x4_avx512vl(out0, out1, out2, out3, outlen,
in0, in1, in2, in3, inlen);
}
#endif /* KECCAK1600_ASM && x86_64 && !OPENSSL_NO_ASM */

View file

@ -65,4 +65,75 @@ int ossl_shake_squeeze_default(KECCAK1600_CTX *ctx, unsigned char *out, size_t o
size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
size_t r);
/* Multi-buffer (x4) Keccak-f[1600] context and API */
#if defined(KECCAK1600_ASM) \
&& (defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) \
&& !defined(OPENSSL_NO_ASM)
/* Runtime capability check for AVX512VL */
int SHA3_avx512vl_capable(void);
/* Context for 4-way parallel SHAKE operations */
typedef struct {
/* 4 interleaved Keccak states (800 bytes)
plus 8 bytes to store the number of
already absorbed or not yet squeezed bytes */
uint64_t A[(25 * 4) + 1];
size_t rate; /* Rate in bytes: 168 (SHAKE-128) or 136 (SHAKE-256) */
unsigned finalized; /* Has finalize been called? 0=no, 1=yes */
} KECCAK1600_X4_AVX512VL_CTX;
/* SHAKE-128 x4 incremental API */
void ossl_sha3_shake128_x4_inc_init_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx);
void ossl_sha3_shake128_x4_inc_absorb_avx512vl(
KECCAK1600_X4_AVX512VL_CTX *ctx,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen);
void ossl_sha3_shake128_x4_inc_cleanup_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx);
void ossl_sha3_shake128_x4_inc_squeeze_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
KECCAK1600_X4_AVX512VL_CTX *ctx);
/* SHAKE-256 x4 incremental API */
void ossl_sha3_shake256_x4_inc_init_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx);
void ossl_sha3_shake256_x4_inc_absorb_avx512vl(
KECCAK1600_X4_AVX512VL_CTX *ctx,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen);
void ossl_sha3_shake256_x4_inc_cleanup_avx512vl(KECCAK1600_X4_AVX512VL_CTX *ctx);
void ossl_sha3_shake256_x4_inc_squeeze_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
KECCAK1600_X4_AVX512VL_CTX *ctx);
/* Single-call SHAKE x4 APIs (wrapper functions) */
void ossl_sha3_shake128_x4_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen);
void ossl_sha3_shake256_x4_avx512vl(
void *out0, void *out1,
void *out2, void *out3,
size_t outlen,
const void *in0, const void *in1,
const void *in2, const void *in3,
size_t inlen);
#endif /* KECCAK1600_ASM && x86_64 && !OPENSSL_NO_ASM */
#endif /* OSSL_INTERNAL_SHA3_H */

View file

@ -270,6 +270,7 @@ ff65c82c56e341f47df03d0c74de7fb537de0e68a4fa23fa07a9fdb51c511f1c crypto/ml_dsa/
3e0980e67842c4d8637fa449ac41e9d650c614c1074c29f1021605d229a4f73d crypto/ml_dsa/ml_dsa_params.c
10e37ab3ee09a45d99007665e073efb2b062c819f30af8694c6b0f411eb33822 crypto/ml_dsa/ml_dsa_poly.h
26be5266a9f1a33999a5a68c96cffc7932ba64521d9554dabe7397591611c852 crypto/ml_dsa/ml_dsa_sample.c
9e57d844f2acedb490b6e8f32e125240078ddab380a7faa533baa9c447dee262 crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc
2127303173eff12cb2b71f92179d10370b555c26e7a305e87ce7066580d57689 crypto/ml_dsa/ml_dsa_sign.c
5217ef237e21872205703b95577290c34898423466a465c7bd609b2eb4627964 crypto/ml_dsa/ml_dsa_sign.h
e3ef4cf1598420c94eee4f53d13491ff0f9dc8cfb1fe1cacd3a1225e2073fa56 crypto/ml_dsa/ml_dsa_vector.h
@ -359,6 +360,7 @@ b7f1f4e69d41812dba39226aea0942fb2e3a638308c3130b0c83bb636a258ce6 crypto/sha/asm
82a84e6ae5ffe90e76530de560f6261c5004c23923fa9fd9aa2aae3852976426 crypto/sha/asm/keccak1600-s390x.pl
e485942ed7f7bf1f376059ed2e5e194907348f44a4308dfc4bbc2d8be05fed99 crypto/sha/asm/keccak1600-x86_64.pl
af173b53537e18453705a3843e0629334b37e8ca03483a2b164fd48252289da3 crypto/sha/asm/keccak1600p8-ppc.pl
d27078e0478f34536f596e037887ad673b05537d9cd4b79376e902774a4c8340 crypto/sha/asm/keccak1600x4-avx512vl.pl
3dd5e288f70b684d337f4054119935ab46af4042a40dffdca203868fe943bae0 crypto/sha/asm/sha1-586.pl
58378cb694b61022d70956ab344331d7577f9a26431acd00a60bed91229b29eb crypto/sha/asm/sha1-alpha.pl
8576b406e8596c8ac56a351a92175accfcf4121dd3dbffc59bae7d0ece0b0dab crypto/sha/asm/sha1-armv4-large.pl
@ -401,6 +403,7 @@ feb4283e1bb2a36f0a98d4cd7b43ac78c40b72efeab8d58b4f0aad8b65a1d2ba crypto/sha/asm
f6021e6e5f4694579ba5a014e2aba44b6d436b2fd25c18ecd474a7383042b027 crypto/sha/sha256.c
ed6049496d9786296d011a4582ffcfe0859a609b37f1f4ce57cee36136ee526c crypto/sha/sha3.c
db0f16a4cb9c86f971b4defbee9dccd77345766f64efc45e0f1bc8d448bfb3e3 crypto/sha/sha3_encode.c
8def0b2e5996f2a2e187abcb7443e5e98edd4be0f71ff918a1b8c717cb97eb27 crypto/sha/sha3_x4_avx512vl.c
833e0990a4b8590a40990bfe1cfe59542ece6923fde37d3dd6faddfe1b9418fc crypto/sha/sha512.c
7b99b3c9fa26c5e58a56cbbb62b6e2bfe62542a662799f910387e76e5688a13a crypto/sha/sha_local.h
dfd99e02830973ab349409ac6ba0ee901ba7736216030965bd7e5a54356abd7c crypto/slh_dsa/slh_adrs.c
@ -497,7 +500,7 @@ ee75ecd35b3ae90c51ace957ab7ce06de3c7d5064b97a878241ff65cc943a6db include/intern
3f476694478c1125574dfb2e75c4c0c0d04c7d3d763176686a4730028513fcd5 include/internal/rcu.h
b6e33da6011b2b74d27e39f27cf98e6f123fe47826562b6479d0dbd5c758c4c2 include/internal/refcount.h
f77c0844cc44bd92965647cd8cb6addb210f0300a8d1090da8c26e4382e87c2c include/internal/safe_math.h
ea565ff98b36d3ae2d8eb709a52cba75720b30e2527cdfda3b90aa426291ac38 include/internal/sha3.h
17f6585bc81ad324d00aaacd558e0176dbe22cc7cbdb353c8c9072fa40000a58 include/internal/sha3.h
8e672cc0620606b044f63b8446125f5233d64e3eea59df54c1fcca6bc90ba537 include/internal/sizes.h
188be736ff23a2202fe594e6d49a7ccf4c23a7baa86e2dac5d58360f21d9c986 include/internal/skey.h
abf03dc8635f2925bdc2299feabe115f8d5d6eaa450b421172ded222872386ba include/internal/ssl3_cbc.h

View file

@ -1 +1 @@
7e5428946b50e077e099dd7bd3891b854b37c623ede0cc8ace51c09b94871db7 providers/fips-sources.checksums
864d3535e188440ca60b8268ce8137e0cffb870be990531fd9f68a23f0ffa898 providers/fips-sources.checksums

View file

@ -270,6 +270,7 @@ crypto/ml_dsa/ml_dsa_ntt.c
crypto/ml_dsa/ml_dsa_params.c
crypto/ml_dsa/ml_dsa_poly.h
crypto/ml_dsa/ml_dsa_sample.c
crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc
crypto/ml_dsa/ml_dsa_sign.c
crypto/ml_dsa/ml_dsa_sign.h
crypto/ml_dsa/ml_dsa_vector.h
@ -359,6 +360,7 @@ crypto/sha/asm/keccak1600-ppc64.pl
crypto/sha/asm/keccak1600-s390x.pl
crypto/sha/asm/keccak1600-x86_64.pl
crypto/sha/asm/keccak1600p8-ppc.pl
crypto/sha/asm/keccak1600x4-avx512vl.pl
crypto/sha/asm/sha1-586.pl
crypto/sha/asm/sha1-alpha.pl
crypto/sha/asm/sha1-armv4-large.pl
@ -401,6 +403,7 @@ crypto/sha/sha1dgst.c
crypto/sha/sha256.c
crypto/sha/sha3.c
crypto/sha/sha3_encode.c
crypto/sha/sha3_x4_avx512vl.c
crypto/sha/sha512.c
crypto/sha/sha_local.h
crypto/slh_dsa/slh_adrs.c