From: Simo Sorce Date: Fri, 11 Apr 2025 21:24:09 +0000 (-0400) Subject: Add ml_dsa msg_update functions to provider code X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=341f1b7f70567aab668452c824d978768ea765b4;p=thirdparty%2Fopenssl.git Add ml_dsa msg_update functions to provider code Signed-off-by: Simo Sorce Reviewed-by: Viktor Dukhovni Reviewed-by: Tomas Mraz (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 7dfc91bb03d..3bbe7556e4d 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 e8054c61027..3508993542a 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 b799fda2cc0..63c5b7fecb4 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 }, \