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:
parent
6736bd2cb6
commit
a248ec771e
15 changed files with 3051 additions and 61 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
307
crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc
Normal file
307
crypto/ml_dsa/ml_dsa_sample_hw_x86_64.inc
Normal 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
|
||||
};
|
||||
|
|
@ -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)) */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
2344
crypto/sha/asm/keccak1600x4-avx512vl.pl
Executable file
2344
crypto/sha/asm/keccak1600x4-avx512vl.pl
Executable file
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
|
|||
213
crypto/sha/sha3_x4_avx512vl.c
Normal file
213
crypto/sha/sha3_x4_avx512vl.c
Normal 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 */
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
7e5428946b50e077e099dd7bd3891b854b37c623ede0cc8ace51c09b94871db7 providers/fips-sources.checksums
|
||||
864d3535e188440ca60b8268ce8137e0cffb870be990531fd9f68a23f0ffa898 providers/fips-sources.checksums
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue