Commit 341f1b7f70 for openssl.org
commit 341f1b7f70567aab668452c824d978768ea765b4
Author: Simo Sorce <simo@redhat.com>
Date: Fri Apr 11 17:24:09 2025 -0400
Add ml_dsa msg_update functions to provider code
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/27342)
diff --git a/crypto/ml_dsa/ml_dsa_local.h b/crypto/ml_dsa/ml_dsa_local.h
index 7dfc91bb03..3bbe7556e4 100644
--- a/crypto/ml_dsa/ml_dsa_local.h
+++ b/crypto/ml_dsa/ml_dsa_local.h
@@ -29,7 +29,6 @@
# define ML_DSA_PRIV_SEED_BYTES 64 /* p' = Private random seed */
# define ML_DSA_K_BYTES 32 /* K = Private random seed for signing */
# define ML_DSA_TR_BYTES 64 /* Size of the Hash of the public key used for signing */
-# define ML_DSA_MU_BYTES 64 /* Size of the Hash for the message representative */
# define ML_DSA_RHO_PRIME_BYTES 64 /* private random seed size */
/*
diff --git a/include/crypto/ml_dsa.h b/include/crypto/ml_dsa.h
index e8054c6102..3508993542 100644
--- a/include/crypto/ml_dsa.h
+++ b/include/crypto/ml_dsa.h
@@ -22,6 +22,8 @@
# define ML_DSA_ENTROPY_LEN 32
+# define ML_DSA_MU_BYTES 64 /* Size of the Hash for the message representative */
+
/* See FIPS 204 Section 4 Table 1 & Table 2 */
# define ML_DSA_44_PRIV_LEN 2560
# define ML_DSA_44_PUB_LEN 1312
diff --git a/providers/implementations/signature/ml_dsa_sig.c b/providers/implementations/signature/ml_dsa_sig.c
index b799fda2cc..63c5b7fecb 100644
--- a/providers/implementations/signature/ml_dsa_sig.c
+++ b/providers/implementations/signature/ml_dsa_sig.c
@@ -27,8 +27,12 @@
#define ML_DSA_MESSAGE_ENCODE_PURE 1
static OSSL_FUNC_signature_sign_message_init_fn ml_dsa_sign_msg_init;
+static OSSL_FUNC_signature_sign_message_update_fn ml_dsa_signverify_msg_update;
+static OSSL_FUNC_signature_sign_message_final_fn ml_dsa_sign_msg_final;
static OSSL_FUNC_signature_sign_fn ml_dsa_sign;
static OSSL_FUNC_signature_verify_message_init_fn ml_dsa_verify_msg_init;
+static OSSL_FUNC_signature_verify_message_update_fn ml_dsa_signverify_msg_update;
+static OSSL_FUNC_signature_verify_message_final_fn ml_dsa_verify_msg_final;
static OSSL_FUNC_signature_verify_fn ml_dsa_verify;
static OSSL_FUNC_signature_digest_sign_init_fn ml_dsa_digest_signverify_init;
static OSSL_FUNC_signature_digest_sign_fn ml_dsa_digest_sign;
@@ -54,13 +58,20 @@ typedef struct {
uint8_t aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
size_t aid_len;
int mu; /* Flag indicating we should begin from \mu, not the message */
+
+ int operation;
+ EVP_MD_CTX *md_ctx; /* Ctx for msg_init/update/final interface */
+ unsigned char *sig; /* Signature, for verification */
+ size_t siglen;
} PROV_ML_DSA_CTX;
static void ml_dsa_freectx(void *vctx)
{
PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;
+ EVP_MD_CTX_free(ctx->md_ctx);
OPENSSL_cleanse(ctx->test_entropy, ctx->test_entropy_len);
+ OPENSSL_free(ctx->sig);
OPENSSL_free(ctx);
}
@@ -84,6 +95,7 @@ static void *ml_dsa_newctx(void *provctx, int evp_type, const char *propq)
static void *ml_dsa_dupctx(void *vctx)
{
PROV_ML_DSA_CTX *srcctx = (PROV_ML_DSA_CTX *)vctx;
+ PROV_ML_DSA_CTX *dstctx;
if (!ossl_prov_is_running())
return NULL;
@@ -92,7 +104,32 @@ static void *ml_dsa_dupctx(void *vctx)
* Note that the ML_DSA_KEY is ref counted via EVP_PKEY so we can just copy
* the key here.
*/
- return OPENSSL_memdup(srcctx, sizeof(*srcctx));
+ dstctx = OPENSSL_memdup(srcctx, sizeof(*srcctx));
+
+ if (dstctx == NULL)
+ return NULL;
+
+ if (srcctx->sig != NULL) {
+ dstctx->sig = OPENSSL_memdup(srcctx->sig, srcctx->siglen);
+ if (dstctx->sig == NULL) {
+ /*
+ * Can't call ml_dsa_freectx() here, as it would free
+ * md_ctx which has not been duplicated yet.
+ */
+ OPENSSL_free(dstctx);
+ return NULL;
+ }
+ }
+
+ if (srcctx->md_ctx != NULL) {
+ dstctx->md_ctx = EVP_MD_CTX_dup(srcctx->md_ctx);
+ if (dstctx->md_ctx == NULL) {
+ ml_dsa_freectx(dstctx);
+ return NULL;
+ }
+ }
+
+ return dstctx;
}
static int set_alg_id_buffer(PROV_ML_DSA_CTX *ctx)
@@ -144,6 +181,7 @@ static int ml_dsa_signverify_msg_init(void *vctx, void *vkey,
set_alg_id_buffer(ctx);
ctx->mu = 0;
+ ctx->operation = operation;
return ml_dsa_set_ctx_params(ctx, params);
}
@@ -174,6 +212,72 @@ static int ml_dsa_digest_signverify_init(void *vctx, const char *mdname,
EVP_PKEY_OP_SIGN, "ML_DSA Sign Init");
}
+static int ml_dsa_signverify_msg_update(void *vctx,
+ const unsigned char *data,
+ size_t datalen)
+{
+ PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;
+
+ if (ctx == NULL)
+ return 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (ctx->mu)
+ return 0;
+
+ if (ctx->md_ctx == NULL) {
+ ctx->md_ctx = ossl_ml_dsa_mu_init(ctx->key, ctx->msg_encode,
+ ctx->context_string,
+ ctx->context_string_len);
+ if (ctx->md_ctx == NULL)
+ return 0;
+ }
+
+ return ossl_ml_dsa_mu_update(ctx->md_ctx, data, datalen);
+}
+
+static int ml_dsa_sign_msg_final(void *vctx, unsigned char *sig,
+ size_t *siglen, size_t sigsize)
+{
+ PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;
+ uint8_t rand_tmp[ML_DSA_ENTROPY_LEN], *rnd = NULL;
+ uint8_t mu[ML_DSA_MU_BYTES];
+ int ret = 0;
+
+ if (ctx == NULL)
+ return 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (ctx->md_ctx == NULL)
+ return 0;
+
+ if (sig != NULL) {
+ if (ctx->test_entropy_len != 0) {
+ rnd = ctx->test_entropy;
+ } else {
+ rnd = rand_tmp;
+
+ if (ctx->deterministic == 1)
+ memset(rnd, 0, sizeof(rand_tmp));
+ else if (RAND_priv_bytes_ex(ctx->libctx, rnd, sizeof(rand_tmp), 0) <= 0)
+ return 0;
+ }
+
+ if (!ossl_ml_dsa_mu_finalize(ctx->md_ctx, mu, sizeof(mu)))
+ return 0;
+ }
+
+ ret = ossl_ml_dsa_sign(ctx->key, 1, mu, sizeof(mu), NULL, 0, rnd,
+ sizeof(rand_tmp), 0, sig, siglen, sigsize);
+ if (rnd != ctx->test_entropy)
+ OPENSSL_cleanse(rand_tmp, sizeof(rand_tmp));
+ return ret;
+}
+
static int ml_dsa_sign(void *vctx, uint8_t *sig, size_t *siglen, size_t sigsize,
const uint8_t *msg, size_t msg_len)
{
@@ -217,6 +321,24 @@ static int ml_dsa_verify_msg_init(void *vctx, void *vkey, const OSSL_PARAM param
"ML_DSA Verify Init");
}
+static int ml_dsa_verify_msg_final(void *vctx)
+{
+ PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;
+ uint8_t mu[ML_DSA_MU_BYTES];
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if (ctx->md_ctx == NULL)
+ return 0;
+
+ if (!ossl_ml_dsa_mu_finalize(ctx->md_ctx, mu, sizeof(mu)))
+ return 0;
+
+ return ossl_ml_dsa_verify(ctx->key, 1, mu, sizeof(mu), NULL, 0, 0,
+ ctx->sig, ctx->siglen);
+}
+
static int ml_dsa_verify(void *vctx, const uint8_t *sig, size_t siglen,
const uint8_t *msg, size_t msg_len)
{
@@ -281,6 +403,18 @@ static int ml_dsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])
if (p != NULL && !OSSL_PARAM_get_int(p, &pctx->mu))
return 0;
+ if (pctx->operation == EVP_PKEY_OP_VERIFYMSG) {
+ p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE);
+ if (p != NULL) {
+ OPENSSL_free(pctx->sig);
+ pctx->sig = NULL;
+ pctx->siglen = 0;
+ if (!OSSL_PARAM_get_octet_string(p, (void **)&pctx->sig,
+ 0, &pctx->siglen))
+ return 0;
+ }
+ }
+
return 1;
}
@@ -338,9 +472,17 @@ static int ml_dsa_get_ctx_params(void *vctx, OSSL_PARAM *params)
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ml_dsa_##alg##_newctx }, \
{ OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, \
(void (*)(void))ml_dsa_sign_msg_init }, \
+ { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE, \
+ (void (*)(void))ml_dsa_signverify_msg_update }, \
+ { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL, \
+ (void (*)(void))ml_dsa_sign_msg_final }, \
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ml_dsa_sign }, \
{ OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, \
(void (*)(void))ml_dsa_verify_msg_init }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE, \
+ (void (*)(void))ml_dsa_signverify_msg_update }, \
+ { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL, \
+ (void (*)(void))ml_dsa_verify_msg_final }, \
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))ml_dsa_verify }, \
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \
(void (*)(void))ml_dsa_digest_signverify_init }, \