#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;
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);
}
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;
* 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)
set_alg_id_buffer(ctx);
ctx->mu = 0;
+ ctx->operation = operation;
return ml_dsa_set_ctx_params(ctx, params);
}
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)
{
"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)
{
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;
}
{ 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 }, \