Path: blob/main/crypto/openssl/providers/implementations/signature/ml_dsa_sig.c
48383 views
/*1* Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include "internal/deprecated.h"1011#include <assert.h>12#include <string.h> /* memset */13#include <openssl/core_names.h>14#include <openssl/err.h>15#include <openssl/rand.h>16#include <openssl/proverr.h>17#include "prov/implementations.h"18#include "prov/providercommon.h"19#include "prov/provider_ctx.h"20#include "prov/der_ml_dsa.h"21#include "crypto/ml_dsa.h"22#include "internal/packet.h"23#include "internal/sizes.h"2425#define ML_DSA_MESSAGE_ENCODE_RAW 026#define ML_DSA_MESSAGE_ENCODE_PURE 12728static OSSL_FUNC_signature_sign_message_init_fn ml_dsa_sign_msg_init;29static OSSL_FUNC_signature_sign_fn ml_dsa_sign;30static OSSL_FUNC_signature_verify_message_init_fn ml_dsa_verify_msg_init;31static OSSL_FUNC_signature_verify_fn ml_dsa_verify;32static OSSL_FUNC_signature_digest_sign_init_fn ml_dsa_digest_signverify_init;33static OSSL_FUNC_signature_digest_sign_fn ml_dsa_digest_sign;34static OSSL_FUNC_signature_digest_verify_fn ml_dsa_digest_verify;35static OSSL_FUNC_signature_freectx_fn ml_dsa_freectx;36static OSSL_FUNC_signature_set_ctx_params_fn ml_dsa_set_ctx_params;37static OSSL_FUNC_signature_settable_ctx_params_fn ml_dsa_settable_ctx_params;38static OSSL_FUNC_signature_get_ctx_params_fn ml_dsa_get_ctx_params;39static OSSL_FUNC_signature_gettable_ctx_params_fn ml_dsa_gettable_ctx_params;40static OSSL_FUNC_signature_dupctx_fn ml_dsa_dupctx;4142typedef struct {43ML_DSA_KEY *key;44OSSL_LIB_CTX *libctx;45uint8_t context_string[ML_DSA_MAX_CONTEXT_STRING_LEN];46size_t context_string_len;47uint8_t test_entropy[ML_DSA_ENTROPY_LEN];48size_t test_entropy_len;49int msg_encode;50int deterministic;51int evp_type;52/* The Algorithm Identifier of the signature algorithm */53uint8_t aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];54size_t aid_len;55int mu; /* Flag indicating we should begin from \mu, not the message */56} PROV_ML_DSA_CTX;5758static void ml_dsa_freectx(void *vctx)59{60PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;6162OPENSSL_cleanse(ctx->test_entropy, ctx->test_entropy_len);63OPENSSL_free(ctx);64}6566static void *ml_dsa_newctx(void *provctx, int evp_type, const char *propq)67{68PROV_ML_DSA_CTX *ctx;6970if (!ossl_prov_is_running())71return NULL;7273ctx = OPENSSL_zalloc(sizeof(PROV_ML_DSA_CTX));74if (ctx == NULL)75return NULL;7677ctx->libctx = PROV_LIBCTX_OF(provctx);78ctx->msg_encode = ML_DSA_MESSAGE_ENCODE_PURE;79ctx->evp_type = evp_type;80return ctx;81}8283static void *ml_dsa_dupctx(void *vctx)84{85PROV_ML_DSA_CTX *srcctx = (PROV_ML_DSA_CTX *)vctx;8687if (!ossl_prov_is_running())88return NULL;8990/*91* Note that the ML_DSA_KEY is ref counted via EVP_PKEY so we can just copy92* the key here.93*/94return OPENSSL_memdup(srcctx, sizeof(*srcctx));95}9697static int set_alg_id_buffer(PROV_ML_DSA_CTX *ctx)98{99int ret;100WPACKET pkt;101uint8_t *aid = NULL;102103/*104* We do not care about DER writing errors.105* All it really means is that for some reason, there's no106* AlgorithmIdentifier to be had, but the operation itself is107* still valid, just as long as it's not used to construct108* anything that needs an AlgorithmIdentifier.109*/110ctx->aid_len = 0;111ret = WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf));112ret = ret && ossl_DER_w_algorithmIdentifier_ML_DSA(&pkt, -1, ctx->key);113if (ret && WPACKET_finish(&pkt)) {114WPACKET_get_total_written(&pkt, &ctx->aid_len);115aid = WPACKET_get_curr(&pkt);116}117WPACKET_cleanup(&pkt);118if (aid != NULL && ctx->aid_len != 0)119memmove(ctx->aid_buf, aid, ctx->aid_len);120return 1;121}122123static int ml_dsa_signverify_msg_init(void *vctx, void *vkey,124const OSSL_PARAM params[], int operation,125const char *desc)126{127PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;128ML_DSA_KEY *key = vkey;129130if (!ossl_prov_is_running()131|| ctx == NULL)132return 0;133134if (vkey == NULL && ctx->key == NULL) {135ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);136return 0;137}138139if (key != NULL)140ctx->key = vkey;141if (!ossl_ml_dsa_key_matches(ctx->key, ctx->evp_type))142return 0;143144set_alg_id_buffer(ctx);145ctx->mu = 0;146147return ml_dsa_set_ctx_params(ctx, params);148}149150static int ml_dsa_sign_msg_init(void *vctx, void *vkey, const OSSL_PARAM params[])151{152return ml_dsa_signverify_msg_init(vctx, vkey, params,153EVP_PKEY_OP_SIGN, "ML_DSA Sign Init");154}155156static int ml_dsa_digest_signverify_init(void *vctx, const char *mdname,157void *vkey, const OSSL_PARAM params[])158{159PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;160161if (mdname != NULL && mdname[0] != '\0') {162ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,163"Explicit digest not supported for ML-DSA operations");164return 0;165}166167ctx->mu = 0;168169if (vkey == NULL && ctx->key != NULL)170return ml_dsa_set_ctx_params(ctx, params);171172return ml_dsa_signverify_msg_init(vctx, vkey, params,173EVP_PKEY_OP_SIGN, "ML_DSA Sign Init");174}175176static int ml_dsa_sign(void *vctx, uint8_t *sig, size_t *siglen, size_t sigsize,177const uint8_t *msg, size_t msg_len)178{179int ret = 0;180PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;181uint8_t rand_tmp[ML_DSA_ENTROPY_LEN], *rnd = NULL;182183if (!ossl_prov_is_running())184return 0;185186if (sig != NULL) {187if (ctx->test_entropy_len != 0) {188rnd = ctx->test_entropy;189} else {190rnd = rand_tmp;191192if (ctx->deterministic == 1)193memset(rnd, 0, sizeof(rand_tmp));194else if (RAND_priv_bytes_ex(ctx->libctx, rnd, sizeof(rand_tmp), 0) <= 0)195return 0;196}197}198ret = ossl_ml_dsa_sign(ctx->key, ctx->mu, msg, msg_len,199ctx->context_string, ctx->context_string_len,200rnd, sizeof(rand_tmp), ctx->msg_encode,201sig, siglen, sigsize);202if (rnd != ctx->test_entropy)203OPENSSL_cleanse(rand_tmp, sizeof(rand_tmp));204return ret;205}206207static int ml_dsa_digest_sign(void *vctx, uint8_t *sig, size_t *siglen, size_t sigsize,208const uint8_t *tbs, size_t tbslen)209{210return ml_dsa_sign(vctx, sig, siglen, sigsize, tbs, tbslen);211}212213static int ml_dsa_verify_msg_init(void *vctx, void *vkey, const OSSL_PARAM params[])214{215return ml_dsa_signverify_msg_init(vctx, vkey, params, EVP_PKEY_OP_VERIFY,216"ML_DSA Verify Init");217}218219static int ml_dsa_verify(void *vctx, const uint8_t *sig, size_t siglen,220const uint8_t *msg, size_t msg_len)221{222PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;223224if (!ossl_prov_is_running())225return 0;226return ossl_ml_dsa_verify(ctx->key, ctx->mu, msg, msg_len,227ctx->context_string, ctx->context_string_len,228ctx->msg_encode, sig, siglen);229}230static int ml_dsa_digest_verify(void *vctx,231const uint8_t *sig, size_t siglen,232const uint8_t *tbs, size_t tbslen)233{234return ml_dsa_verify(vctx, sig, siglen, tbs, tbslen);235}236237static int ml_dsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])238{239PROV_ML_DSA_CTX *pctx = (PROV_ML_DSA_CTX *)vctx;240const OSSL_PARAM *p;241242if (pctx == NULL)243return 0;244if (ossl_param_is_empty(params))245return 1;246247p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_CONTEXT_STRING);248if (p != NULL) {249void *vp = pctx->context_string;250251if (!OSSL_PARAM_get_octet_string(p, &vp, sizeof(pctx->context_string),252&(pctx->context_string_len))) {253pctx->context_string_len = 0;254return 0;255}256}257p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_TEST_ENTROPY);258if (p != NULL) {259void *vp = pctx->test_entropy;260261pctx->test_entropy_len = 0;262if (!OSSL_PARAM_get_octet_string(p, &vp, sizeof(pctx->test_entropy),263&(pctx->test_entropy_len)))264return 0;265if (pctx->test_entropy_len != sizeof(pctx->test_entropy)) {266pctx->test_entropy_len = 0;267ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH);268return 0;269}270}271p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DETERMINISTIC);272if (p != NULL && !OSSL_PARAM_get_int(p, &pctx->deterministic))273return 0;274275p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING);276if (p != NULL && !OSSL_PARAM_get_int(p, &pctx->msg_encode))277return 0;278279p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MU);280if (p != NULL && !OSSL_PARAM_get_int(p, &pctx->mu))281return 0;282283return 1;284}285286static const OSSL_PARAM *ml_dsa_settable_ctx_params(void *vctx,287ossl_unused void *provctx)288{289static const OSSL_PARAM settable_ctx_params[] = {290OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),291OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_TEST_ENTROPY, NULL, 0),292OSSL_PARAM_int(OSSL_SIGNATURE_PARAM_DETERMINISTIC, 0),293OSSL_PARAM_int(OSSL_SIGNATURE_PARAM_MU, 0),294OSSL_PARAM_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, 0),295OSSL_PARAM_END296};297298return settable_ctx_params;299}300301static const OSSL_PARAM known_gettable_ctx_params[] = {302OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),303OSSL_PARAM_END304};305306static const OSSL_PARAM *ml_dsa_gettable_ctx_params(ossl_unused void *vctx,307ossl_unused void *provctx)308{309return known_gettable_ctx_params;310}311312static int ml_dsa_get_ctx_params(void *vctx, OSSL_PARAM *params)313{314PROV_ML_DSA_CTX *ctx = (PROV_ML_DSA_CTX *)vctx;315OSSL_PARAM *p;316317if (ctx == NULL)318return 0;319320p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);321if (p != NULL322&& !OSSL_PARAM_set_octet_string(p,323ctx->aid_len == 0 ? NULL : ctx->aid_buf,324ctx->aid_len))325return 0;326327return 1;328}329330#define MAKE_SIGNATURE_FUNCTIONS(alg) \331static OSSL_FUNC_signature_newctx_fn ml_dsa_##alg##_newctx; \332static void *ml_dsa_##alg##_newctx(void *provctx, const char *propq) \333{ \334return ml_dsa_newctx(provctx, EVP_PKEY_ML_DSA_##alg, propq); \335} \336const OSSL_DISPATCH ossl_ml_dsa_##alg##_signature_functions[] = { \337{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ml_dsa_##alg##_newctx }, \338{ OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, \339(void (*)(void))ml_dsa_sign_msg_init }, \340{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ml_dsa_sign }, \341{ OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, \342(void (*)(void))ml_dsa_verify_msg_init }, \343{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))ml_dsa_verify }, \344{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \345(void (*)(void))ml_dsa_digest_signverify_init }, \346{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN, \347(void (*)(void))ml_dsa_digest_sign }, \348{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, \349(void (*)(void))ml_dsa_digest_signverify_init }, \350{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, \351(void (*)(void))ml_dsa_digest_verify }, \352{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ml_dsa_freectx }, \353{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \354(void (*)(void))ml_dsa_set_ctx_params }, \355{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \356(void (*)(void))ml_dsa_settable_ctx_params }, \357{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \358(void (*)(void))ml_dsa_get_ctx_params }, \359{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \360(void (*)(void))ml_dsa_gettable_ctx_params }, \361{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ml_dsa_dupctx }, \362OSSL_DISPATCH_END \363}364365MAKE_SIGNATURE_FUNCTIONS(44);366MAKE_SIGNATURE_FUNCTIONS(65);367MAKE_SIGNATURE_FUNCTIONS(87);368369370