Path: blob/main/crypto/openssl/providers/implementations/signature/slh_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 <openssl/core_names.h>10#include <openssl/err.h>11#include <openssl/rand.h>12#include <openssl/proverr.h>13#include "prov/implementations.h"14#include "prov/providercommon.h"15#include "prov/provider_ctx.h"16#include "prov/der_slh_dsa.h"17#include "crypto/slh_dsa.h"18#include "internal/sizes.h"1920#define SLH_DSA_MAX_ADD_RANDOM_LEN 322122#define SLH_DSA_MESSAGE_ENCODE_RAW 023#define SLH_DSA_MESSAGE_ENCODE_PURE 12425static OSSL_FUNC_signature_sign_message_init_fn slh_dsa_sign_msg_init;26static OSSL_FUNC_signature_sign_fn slh_dsa_sign;27static OSSL_FUNC_signature_verify_message_init_fn slh_dsa_verify_msg_init;28static OSSL_FUNC_signature_verify_fn slh_dsa_verify;29static OSSL_FUNC_signature_digest_sign_init_fn slh_dsa_digest_signverify_init;30static OSSL_FUNC_signature_digest_sign_fn slh_dsa_digest_sign;31static OSSL_FUNC_signature_digest_verify_fn slh_dsa_digest_verify;32static OSSL_FUNC_signature_freectx_fn slh_dsa_freectx;33static OSSL_FUNC_signature_dupctx_fn slh_dsa_dupctx;34static OSSL_FUNC_signature_set_ctx_params_fn slh_dsa_set_ctx_params;35static OSSL_FUNC_signature_settable_ctx_params_fn slh_dsa_settable_ctx_params;3637/*38* NOTE: Any changes to this structure may require updating slh_dsa_dupctx().39*/40typedef struct {41SLH_DSA_KEY *key; /* Note that the key is not owned by this object */42SLH_DSA_HASH_CTX *hash_ctx;43uint8_t context_string[SLH_DSA_MAX_CONTEXT_STRING_LEN];44size_t context_string_len;45uint8_t add_random[SLH_DSA_MAX_ADD_RANDOM_LEN];46size_t add_random_len;47int msg_encode;48int deterministic;49OSSL_LIB_CTX *libctx;50char *propq;51const char *alg;52/* The Algorithm Identifier of the signature algorithm */53uint8_t aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];54size_t aid_len;55} PROV_SLH_DSA_CTX;5657static void slh_dsa_freectx(void *vctx)58{59PROV_SLH_DSA_CTX *ctx = (PROV_SLH_DSA_CTX *)vctx;6061ossl_slh_dsa_hash_ctx_free(ctx->hash_ctx);62OPENSSL_free(ctx->propq);63OPENSSL_cleanse(ctx->add_random, ctx->add_random_len);64OPENSSL_free(ctx);65}6667static void *slh_dsa_newctx(void *provctx, const char *alg, const char *propq)68{69PROV_SLH_DSA_CTX *ctx;7071if (!ossl_prov_is_running())72return NULL;7374ctx = OPENSSL_zalloc(sizeof(PROV_SLH_DSA_CTX));75if (ctx == NULL)76return NULL;7778ctx->libctx = PROV_LIBCTX_OF(provctx);79if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)80goto err;81ctx->alg = alg;82ctx->msg_encode = SLH_DSA_MESSAGE_ENCODE_PURE;83return ctx;84err:85slh_dsa_freectx(ctx);86return NULL;87}8889static void *slh_dsa_dupctx(void *vctx)90{91PROV_SLH_DSA_CTX *src = (PROV_SLH_DSA_CTX *)vctx;92PROV_SLH_DSA_CTX *ret;9394if (!ossl_prov_is_running())95return NULL;9697/*98* Note that the SLH_DSA_KEY is ref counted via EVP_PKEY so we can just copy99* the key here.100*/101ret = OPENSSL_memdup(src, sizeof(*src));102if (ret == NULL)103return NULL;104ret->propq = NULL;105ret->hash_ctx = NULL;106if (src->propq != NULL && (ret->propq = OPENSSL_strdup(src->propq)) == NULL)107goto err;108ret->hash_ctx = ossl_slh_dsa_hash_ctx_dup(src->hash_ctx);109if (ret->hash_ctx == NULL)110goto err;111112return ret;113err:114slh_dsa_freectx(ret);115return NULL;116}117118static int slh_dsa_set_alg_id_buffer(PROV_SLH_DSA_CTX *ctx)119{120int ret;121WPACKET pkt;122uint8_t *aid = NULL;123124/*125* We do not care about DER writing errors.126* All it really means is that for some reason, there's no127* AlgorithmIdentifier to be had, but the operation itself is128* still valid, just as long as it's not used to construct129* anything that needs an AlgorithmIdentifier.130*/131ctx->aid_len = 0;132ret = WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf));133ret = ret && ossl_DER_w_algorithmIdentifier_SLH_DSA(&pkt, -1, ctx->key);134if (ret && WPACKET_finish(&pkt)) {135WPACKET_get_total_written(&pkt, &ctx->aid_len);136aid = WPACKET_get_curr(&pkt);137}138WPACKET_cleanup(&pkt);139if (aid != NULL && ctx->aid_len != 0)140memmove(ctx->aid_buf, aid, ctx->aid_len);141return 1;142}143144static int slh_dsa_signverify_msg_init(void *vctx, void *vkey,145const OSSL_PARAM params[], int operation,146const char *desc)147{148PROV_SLH_DSA_CTX *ctx = (PROV_SLH_DSA_CTX *)vctx;149SLH_DSA_KEY *key = vkey;150151if (!ossl_prov_is_running()152|| ctx == NULL)153return 0;154155if (vkey == NULL && ctx->key == NULL) {156ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);157return 0;158}159160if (key != NULL) {161if (!ossl_slh_dsa_key_type_matches(key, ctx->alg))162return 0;163ctx->hash_ctx = ossl_slh_dsa_hash_ctx_new(key);164if (ctx->hash_ctx == NULL)165return 0;166ctx->key = vkey;167}168169slh_dsa_set_alg_id_buffer(ctx);170if (!slh_dsa_set_ctx_params(ctx, params))171return 0;172return 1;173}174175static int slh_dsa_sign_msg_init(void *vctx, void *vkey, const OSSL_PARAM params[])176{177return slh_dsa_signverify_msg_init(vctx, vkey, params,178EVP_PKEY_OP_SIGN, "SLH_DSA Sign Init");179}180181static int slh_dsa_digest_signverify_init(void *vctx, const char *mdname,182void *vkey, const OSSL_PARAM params[])183{184PROV_SLH_DSA_CTX *ctx = (PROV_SLH_DSA_CTX *)vctx;185186if (mdname != NULL && mdname[0] != '\0') {187ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,188"Explicit digest not supported for SLH-DSA operations");189return 0;190}191192if (vkey == NULL && ctx->key != NULL)193return slh_dsa_set_ctx_params(ctx, params);194195return slh_dsa_signverify_msg_init(vctx, vkey, params,196EVP_PKEY_OP_SIGN, "SLH_DSA Sign Init");197}198199static int slh_dsa_sign(void *vctx, unsigned char *sig, size_t *siglen,200size_t sigsize, const unsigned char *msg, size_t msg_len)201{202int ret = 0;203PROV_SLH_DSA_CTX *ctx = (PROV_SLH_DSA_CTX *)vctx;204uint8_t add_rand[SLH_DSA_MAX_ADD_RANDOM_LEN], *opt_rand = NULL;205size_t n = 0;206207if (!ossl_prov_is_running())208return 0;209210if (sig != NULL) {211if (ctx->add_random_len != 0) {212opt_rand = ctx->add_random;213} else if (ctx->deterministic == 0) {214n = ossl_slh_dsa_key_get_n(ctx->key);215if (RAND_priv_bytes_ex(ctx->libctx, add_rand, n, 0) <= 0)216return 0;217opt_rand = add_rand;218}219}220ret = ossl_slh_dsa_sign(ctx->hash_ctx, msg, msg_len,221ctx->context_string, ctx->context_string_len,222opt_rand, ctx->msg_encode,223sig, siglen, sigsize);224if (opt_rand != add_rand)225OPENSSL_cleanse(opt_rand, n);226return ret;227}228229static int slh_dsa_digest_sign(void *vctx, uint8_t *sig, size_t *siglen, size_t sigsize,230const uint8_t *tbs, size_t tbslen)231{232return slh_dsa_sign(vctx, sig, siglen, sigsize, tbs, tbslen);233}234235static int slh_dsa_verify_msg_init(void *vctx, void *vkey, const OSSL_PARAM params[])236{237return slh_dsa_signverify_msg_init(vctx, vkey, params, EVP_PKEY_OP_VERIFY,238"SLH_DSA Verify Init");239}240241static int slh_dsa_verify(void *vctx, const uint8_t *sig, size_t siglen,242const uint8_t *msg, size_t msg_len)243{244PROV_SLH_DSA_CTX *ctx = (PROV_SLH_DSA_CTX *)vctx;245246if (!ossl_prov_is_running())247return 0;248return ossl_slh_dsa_verify(ctx->hash_ctx, msg, msg_len,249ctx->context_string, ctx->context_string_len,250ctx->msg_encode, sig, siglen);251}252static int slh_dsa_digest_verify(void *vctx, const uint8_t *sig, size_t siglen,253const uint8_t *tbs, size_t tbslen)254{255return slh_dsa_verify(vctx, sig, siglen, tbs, tbslen);256}257258static int slh_dsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])259{260PROV_SLH_DSA_CTX *pctx = (PROV_SLH_DSA_CTX *)vctx;261const OSSL_PARAM *p;262263if (pctx == NULL)264return 0;265if (ossl_param_is_empty(params))266return 1;267268p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_CONTEXT_STRING);269if (p != NULL) {270void *vp = pctx->context_string;271272if (!OSSL_PARAM_get_octet_string(p, &vp, sizeof(pctx->context_string),273&(pctx->context_string_len))) {274pctx->context_string_len = 0;275return 0;276}277}278p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_TEST_ENTROPY);279if (p != NULL) {280void *vp = pctx->add_random;281size_t n = ossl_slh_dsa_key_get_n(pctx->key);282283if (!OSSL_PARAM_get_octet_string(p, &vp, n, &(pctx->add_random_len))284|| pctx->add_random_len != n) {285pctx->add_random_len = 0;286return 0;287}288}289p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DETERMINISTIC);290if (p != NULL && !OSSL_PARAM_get_int(p, &pctx->deterministic))291return 0;292293p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING);294if (p != NULL && !OSSL_PARAM_get_int(p, &pctx->msg_encode))295return 0;296return 1;297}298299static const OSSL_PARAM *slh_dsa_settable_ctx_params(void *vctx,300ossl_unused void *provctx)301{302static const OSSL_PARAM settable_ctx_params[] = {303OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),304OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_TEST_ENTROPY, NULL, 0),305OSSL_PARAM_int(OSSL_SIGNATURE_PARAM_DETERMINISTIC, 0),306OSSL_PARAM_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, 0),307OSSL_PARAM_END308};309310return settable_ctx_params;311}312313static const OSSL_PARAM known_gettable_ctx_params[] = {314OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),315OSSL_PARAM_END316};317318static const OSSL_PARAM *slh_dsa_gettable_ctx_params(ossl_unused void *vctx,319ossl_unused void *provctx)320{321return known_gettable_ctx_params;322}323324static int slh_dsa_get_ctx_params(void *vctx, OSSL_PARAM *params)325{326PROV_SLH_DSA_CTX *ctx = (PROV_SLH_DSA_CTX *)vctx;327OSSL_PARAM *p;328329if (ctx == NULL)330return 0;331332p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);333if (p != NULL334&& !OSSL_PARAM_set_octet_string(p,335ctx->aid_len == 0 ? NULL : ctx->aid_buf,336ctx->aid_len))337return 0;338339return 1;340}341342#define MAKE_SIGNATURE_FUNCTIONS(alg, fn) \343static OSSL_FUNC_signature_newctx_fn slh_dsa_##fn##_newctx; \344static void *slh_dsa_##fn##_newctx(void *provctx, const char *propq) \345{ \346return slh_dsa_newctx(provctx, alg, propq); \347} \348const OSSL_DISPATCH ossl_slh_dsa_##fn##_signature_functions[] = { \349{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))slh_dsa_##fn##_newctx }, \350{ OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, \351(void (*)(void))slh_dsa_sign_msg_init }, \352{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))slh_dsa_sign }, \353{ OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, \354(void (*)(void))slh_dsa_verify_msg_init }, \355{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))slh_dsa_verify }, \356{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \357(void (*)(void))slh_dsa_digest_signverify_init }, \358{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN, \359(void (*)(void))slh_dsa_digest_sign }, \360{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, \361(void (*)(void))slh_dsa_digest_signverify_init }, \362{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, \363(void (*)(void))slh_dsa_digest_verify }, \364{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))slh_dsa_freectx }, \365{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))slh_dsa_dupctx }, \366{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))slh_dsa_set_ctx_params },\367{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \368(void (*)(void))slh_dsa_settable_ctx_params }, \369{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \370(void (*)(void))slh_dsa_get_ctx_params }, \371{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \372(void (*)(void))slh_dsa_gettable_ctx_params }, \373OSSL_DISPATCH_END \374}375376MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHA2-128s", sha2_128s);377MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHA2-128f", sha2_128f);378MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHA2-192s", sha2_192s);379MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHA2-192f", sha2_192f);380MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHA2-256s", sha2_256s);381MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHA2-256f", sha2_256f);382MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHAKE-128s", shake_128s);383MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHAKE-128f", shake_128f);384MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHAKE-192s", shake_192s);385MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHAKE-192f", shake_192f);386MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHAKE-256s", shake_256s);387MAKE_SIGNATURE_FUNCTIONS("SLH-DSA-SHAKE-256f", shake_256f);388389390