Path: blob/main/crypto/openssl/providers/implementations/signature/eddsa_sig.c
108817 views
/*1* Copyright 2020-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/crypto.h>10#include <openssl/core_dispatch.h>11#include <openssl/core_names.h>12#include <openssl/err.h>13#include <openssl/params.h>14#include <openssl/evp.h>15#include <openssl/proverr.h>16#include "internal/nelem.h"17#include "internal/sizes.h"18#include "prov/providercommon.h"19#include "prov/implementations.h"20#include "prov/securitycheck.h"21#include "prov/provider_ctx.h"22#include "prov/der_ecx.h"23#include "crypto/ecx.h"2425#ifdef S390X_EC_ASM26#include "s390x_arch.h"2728#define S390X_CAN_SIGN(edtype) \29((OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_##edtype)) \30&& (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_##edtype)) \31&& (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_##edtype)))3233static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,34const unsigned char *tbs, size_t tbslen);35static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,36const unsigned char *tbs, size_t tbslen);37static int s390x_ed25519_digestverify(const ECX_KEY *edkey,38const unsigned char *sig,39const unsigned char *tbs, size_t tbslen);40static int s390x_ed448_digestverify(const ECX_KEY *edkey,41const unsigned char *sig,42const unsigned char *tbs, size_t tbslen);4344#endif /* S390X_EC_ASM */4546enum ID_EdDSA_INSTANCE {47ID_NOT_SET = 0,48ID_Ed25519,49ID_Ed25519ctx,50ID_Ed25519ph,51ID_Ed448,52ID_Ed448ph53};5455#define SN_Ed25519 "Ed25519"56#define SN_Ed25519ph "Ed25519ph"57#define SN_Ed25519ctx "Ed25519ctx"58#define SN_Ed448 "Ed448"59#define SN_Ed448ph "Ed448ph"6061#define EDDSA_MAX_CONTEXT_STRING_LEN 25562#define EDDSA_PREHASH_OUTPUT_LEN 646364static OSSL_FUNC_signature_newctx_fn eddsa_newctx;65static OSSL_FUNC_signature_sign_message_init_fn ed25519_signverify_message_init;66static OSSL_FUNC_signature_sign_message_init_fn ed25519ph_signverify_message_init;67static OSSL_FUNC_signature_sign_message_init_fn ed25519ctx_signverify_message_init;68static OSSL_FUNC_signature_sign_message_init_fn ed448_signverify_message_init;69static OSSL_FUNC_signature_sign_message_init_fn ed448ph_signverify_message_init;70static OSSL_FUNC_signature_sign_fn ed25519_sign;71static OSSL_FUNC_signature_sign_fn ed448_sign;72static OSSL_FUNC_signature_verify_fn ed25519_verify;73static OSSL_FUNC_signature_verify_fn ed448_verify;74static OSSL_FUNC_signature_digest_sign_init_fn ed25519_digest_signverify_init;75static OSSL_FUNC_signature_digest_sign_init_fn ed448_digest_signverify_init;76static OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign;77static OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign;78static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify;79static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify;80static OSSL_FUNC_signature_freectx_fn eddsa_freectx;81static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx;82static OSSL_FUNC_signature_query_key_types_fn ed25519_sigalg_query_key_types;83static OSSL_FUNC_signature_query_key_types_fn ed448_sigalg_query_key_types;84static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params;85static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params;86static OSSL_FUNC_signature_set_ctx_params_fn eddsa_set_ctx_params;87static OSSL_FUNC_signature_settable_ctx_params_fn eddsa_settable_ctx_params;88static OSSL_FUNC_signature_settable_ctx_params_fn eddsa_settable_variant_ctx_params;8990/* there are five EdDSA instances:9192Ed2551993Ed25519ph94Ed25519ctx95Ed44896Ed448ph9798Quoting from RFC 8032, Section 5.1:99100For Ed25519, dom2(f,c) is the empty string. The phflag value is101irrelevant. The context (if present at all) MUST be empty. This102causes the scheme to be one and the same with the Ed25519 scheme103published earlier.104105For Ed25519ctx, phflag=0. The context input SHOULD NOT be empty.106107For Ed25519ph, phflag=1 and PH is SHA512 instead. That is, the input108is hashed using SHA-512 before signing with Ed25519.109110Quoting from RFC 8032, Section 5.2:111112Ed448ph is the same but with PH being SHAKE256(x, 64) and phflag113being 1, i.e., the input is hashed before signing with Ed448 with a114hash constant modified.115116Value of context is set by signer and verifier (maximum of 255117octets; the default is empty string) and has to match octet by octet118for verification to be successful.119120Quoting from RFC 8032, Section 2:121122dom2(x, y) The blank octet string when signing or verifying123Ed25519. Otherwise, the octet string: "SigEd25519 no124Ed25519 collisions" || octet(x) || octet(OLEN(y)) ||125y, where x is in range 0-255 and y is an octet string126of at most 255 octets. "SigEd25519 no Ed25519127collisions" is in ASCII (32 octets).128129dom4(x, y) The octet string "SigEd448" || octet(x) ||130octet(OLEN(y)) || y, where x is in range 0-255 and y131is an octet string of at most 255 octets. "SigEd448"132is in ASCII (8 octets).133134Note above that x is the pre-hash flag, and y is the context string.135*/136137typedef struct {138OSSL_LIB_CTX *libctx;139ECX_KEY *key;140141/* The Algorithm Identifier of the signature algorithm */142unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];143size_t aid_len;144145/* id indicating the EdDSA instance */146int instance_id;147/* indicates that instance_id and associated flags are preset / hardcoded */148unsigned int instance_id_preset_flag : 1;149/* for ph instances, this indicates whether the caller is expected to prehash */150unsigned int prehash_by_caller_flag : 1;151152unsigned int dom2_flag : 1;153unsigned int prehash_flag : 1;154155/* indicates that a non-empty context string is required, as in Ed25519ctx */156unsigned int context_string_flag : 1;157158unsigned char context_string[EDDSA_MAX_CONTEXT_STRING_LEN];159size_t context_string_len;160161} PROV_EDDSA_CTX;162163static void *eddsa_newctx(void *provctx, const char *propq_unused)164{165PROV_EDDSA_CTX *peddsactx;166167if (!ossl_prov_is_running())168return NULL;169170peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));171if (peddsactx == NULL)172return NULL;173174peddsactx->libctx = PROV_LIBCTX_OF(provctx);175176return peddsactx;177}178179static int eddsa_setup_instance(void *vpeddsactx, int instance_id,180unsigned int instance_id_preset,181unsigned int prehash_by_caller)182{183PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;184185switch (instance_id) {186case ID_Ed25519:187if (peddsactx->key->type != ECX_KEY_TYPE_ED25519)188return 0;189peddsactx->dom2_flag = 0;190peddsactx->prehash_flag = 0;191peddsactx->context_string_flag = 0;192break;193#ifndef FIPS_MODULE194case ID_Ed25519ctx:195if (peddsactx->key->type != ECX_KEY_TYPE_ED25519)196return 0;197peddsactx->dom2_flag = 1;198peddsactx->prehash_flag = 0;199peddsactx->context_string_flag = 1;200break;201#endif202case ID_Ed25519ph:203if (peddsactx->key->type != ECX_KEY_TYPE_ED25519)204return 0;205peddsactx->dom2_flag = 1;206peddsactx->prehash_flag = 1;207peddsactx->context_string_flag = 0;208break;209case ID_Ed448:210if (peddsactx->key->type != ECX_KEY_TYPE_ED448)211return 0;212peddsactx->prehash_flag = 0;213peddsactx->context_string_flag = 0;214break;215case ID_Ed448ph:216if (peddsactx->key->type != ECX_KEY_TYPE_ED448)217return 0;218peddsactx->prehash_flag = 1;219peddsactx->context_string_flag = 0;220break;221default:222/* we did not recognize the instance */223return 0;224}225peddsactx->instance_id = instance_id;226peddsactx->instance_id_preset_flag = instance_id_preset;227peddsactx->prehash_by_caller_flag = prehash_by_caller;228return 1;229}230231static int eddsa_signverify_init(void *vpeddsactx, void *vedkey)232{233PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;234ECX_KEY *edkey = (ECX_KEY *)vedkey;235WPACKET pkt;236int ret;237unsigned char *aid = NULL;238239if (!ossl_prov_is_running())240return 0;241242if (edkey == NULL) {243ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);244return 0;245}246247if (!ossl_ecx_key_up_ref(edkey)) {248ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);249return 0;250}251252peddsactx->instance_id_preset_flag = 0;253peddsactx->dom2_flag = 0;254peddsactx->prehash_flag = 0;255peddsactx->context_string_flag = 0;256peddsactx->context_string_len = 0;257258peddsactx->key = edkey;259260/*261* We do not care about DER writing errors.262* All it really means is that for some reason, there's no263* AlgorithmIdentifier to be had, but the operation itself is264* still valid, just as long as it's not used to construct265* anything that needs an AlgorithmIdentifier.266*/267peddsactx->aid_len = 0;268ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));269switch (edkey->type) {270case ECX_KEY_TYPE_ED25519:271ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);272break;273case ECX_KEY_TYPE_ED448:274ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);275break;276default:277/* Should never happen */278ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);279ossl_ecx_key_free(edkey);280peddsactx->key = NULL;281WPACKET_cleanup(&pkt);282return 0;283}284if (ret && WPACKET_finish(&pkt)) {285WPACKET_get_total_written(&pkt, &peddsactx->aid_len);286aid = WPACKET_get_curr(&pkt);287}288WPACKET_cleanup(&pkt);289if (aid != NULL && peddsactx->aid_len != 0)290memmove(peddsactx->aid_buf, aid, peddsactx->aid_len);291292return 1;293}294295static int ed25519_signverify_message_init(void *vpeddsactx, void *vedkey,296const OSSL_PARAM params[])297{298return eddsa_signverify_init(vpeddsactx, vedkey)299&& eddsa_setup_instance(vpeddsactx, ID_Ed25519, 1, 0)300&& eddsa_set_ctx_params(vpeddsactx, params);301}302303static int ed25519ph_signverify_message_init(void *vpeddsactx, void *vedkey,304const OSSL_PARAM params[])305{306return eddsa_signverify_init(vpeddsactx, vedkey)307&& eddsa_setup_instance(vpeddsactx, ID_Ed25519ph, 1, 0)308&& eddsa_set_ctx_params(vpeddsactx, params);309}310311static int ed25519ph_signverify_init(void *vpeddsactx, void *vedkey,312const OSSL_PARAM params[])313{314return eddsa_signverify_init(vpeddsactx, vedkey)315&& eddsa_setup_instance(vpeddsactx, ID_Ed25519ph, 1, 1)316&& eddsa_set_ctx_params(vpeddsactx, params);317}318319/*320* This supports using ED25519 with EVP_PKEY_{sign,verify}_init_ex() and321* EVP_PKEY_{sign,verify}_init_ex2(), under the condition that the caller322* explicitly sets the Ed25519ph instance (this is verified by ed25519_sign()323* and ed25519_verify())324*/325static int ed25519_signverify_init(void *vpeddsactx, void *vedkey,326const OSSL_PARAM params[])327{328return eddsa_signverify_init(vpeddsactx, vedkey)329&& eddsa_setup_instance(vpeddsactx, ID_Ed25519, 0, 1)330&& eddsa_set_ctx_params(vpeddsactx, params);331}332333static int ed25519ctx_signverify_message_init(void *vpeddsactx, void *vedkey,334const OSSL_PARAM params[])335{336return eddsa_signverify_init(vpeddsactx, vedkey)337&& eddsa_setup_instance(vpeddsactx, ID_Ed25519ctx, 1, 0)338&& eddsa_set_ctx_params(vpeddsactx, params);339}340341static int ed448_signverify_message_init(void *vpeddsactx, void *vedkey,342const OSSL_PARAM params[])343{344return eddsa_signverify_init(vpeddsactx, vedkey)345&& eddsa_setup_instance(vpeddsactx, ID_Ed448, 1, 0)346&& eddsa_set_ctx_params(vpeddsactx, params);347}348349static int ed448ph_signverify_message_init(void *vpeddsactx, void *vedkey,350const OSSL_PARAM params[])351{352return eddsa_signverify_init(vpeddsactx, vedkey)353&& eddsa_setup_instance(vpeddsactx, ID_Ed448ph, 1, 0)354&& eddsa_set_ctx_params(vpeddsactx, params);355}356357static int ed448ph_signverify_init(void *vpeddsactx, void *vedkey,358const OSSL_PARAM params[])359{360return eddsa_signverify_init(vpeddsactx, vedkey)361&& eddsa_setup_instance(vpeddsactx, ID_Ed448ph, 1, 1)362&& eddsa_set_ctx_params(vpeddsactx, params);363}364365/*366* This supports using ED448 with EVP_PKEY_{sign,verify}_init_ex() and367* EVP_PKEY_{sign,verify}_init_ex2(), under the condition that the caller368* explicitly sets the Ed448ph instance (this is verified by ed448_sign()369* and ed448_verify())370*/371static int ed448_signverify_init(void *vpeddsactx, void *vedkey,372const OSSL_PARAM params[])373{374return eddsa_signverify_init(vpeddsactx, vedkey)375&& eddsa_setup_instance(vpeddsactx, ID_Ed448, 0, 1)376&& eddsa_set_ctx_params(vpeddsactx, params);377}378379/*380* This is used directly for OSSL_FUNC_SIGNATURE_SIGN and indirectly381* for OSSL_FUNC_SIGNATURE_DIGEST_SIGN382*/383static int ed25519_sign(void *vpeddsactx,384unsigned char *sigret, size_t *siglen, size_t sigsize,385const unsigned char *tbs, size_t tbslen)386{387PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;388const ECX_KEY *edkey = peddsactx->key;389uint8_t md[EVP_MAX_MD_SIZE];390size_t mdlen;391392if (!ossl_prov_is_running())393return 0;394395if (sigret == NULL) {396*siglen = ED25519_SIGSIZE;397return 1;398}399if (sigsize < ED25519_SIGSIZE) {400ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);401return 0;402}403if (edkey->privkey == NULL) {404ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);405return 0;406}407#ifdef S390X_EC_ASM408/*409* s390x_ed25519_digestsign() does not yet support dom2 or context-strings.410* fall back to non-accelerated sign if those options are set, or pre-hasing411* is provided.412*/413if (S390X_CAN_SIGN(ED25519)414&& !peddsactx->dom2_flag415&& !peddsactx->context_string_flag416&& peddsactx->context_string_len == 0417&& !peddsactx->prehash_flag418&& !peddsactx->prehash_by_caller_flag) {419if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {420ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);421return 0;422}423*siglen = ED25519_SIGSIZE;424return 1;425}426#endif /* S390X_EC_ASM */427428if (peddsactx->prehash_flag) {429if (!peddsactx->prehash_by_caller_flag) {430if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL,431tbs, tbslen, md, &mdlen)432|| mdlen != EDDSA_PREHASH_OUTPUT_LEN) {433ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PREHASHED_DIGEST_LENGTH);434return 0;435}436tbs = md;437tbslen = mdlen;438} else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {439ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);440return 0;441}442} else if (peddsactx->prehash_by_caller_flag) {443/* The caller is supposed to set up a ph instance! */444ERR_raise(ERR_LIB_PROV,445PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);446return 0;447}448449if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,450peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,451peddsactx->context_string, peddsactx->context_string_len,452peddsactx->libctx, NULL)453== 0) {454ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);455return 0;456}457*siglen = ED25519_SIGSIZE;458return 1;459}460461/* EVP_Q_digest() does not allow variable output length for XOFs,462so we use this function */463static int ed448_shake256(OSSL_LIB_CTX *libctx,464const char *propq,465const uint8_t *in, size_t inlen,466uint8_t *out, size_t outlen)467{468int ret = 0;469EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new();470EVP_MD *shake256 = EVP_MD_fetch(libctx, SN_shake256, propq);471472if (hash_ctx == NULL || shake256 == NULL)473goto err;474475if (!EVP_DigestInit_ex(hash_ctx, shake256, NULL)476|| !EVP_DigestUpdate(hash_ctx, in, inlen)477|| !EVP_DigestFinalXOF(hash_ctx, out, outlen))478goto err;479480ret = 1;481482err:483EVP_MD_CTX_free(hash_ctx);484EVP_MD_free(shake256);485return ret;486}487488/*489* This is used directly for OSSL_FUNC_SIGNATURE_SIGN and indirectly490* for OSSL_FUNC_SIGNATURE_DIGEST_SIGN491*/492static int ed448_sign(void *vpeddsactx,493unsigned char *sigret, size_t *siglen, size_t sigsize,494const unsigned char *tbs, size_t tbslen)495{496PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;497const ECX_KEY *edkey = peddsactx->key;498uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];499size_t mdlen = sizeof(md);500501if (!ossl_prov_is_running())502return 0;503504if (sigret == NULL) {505*siglen = ED448_SIGSIZE;506return 1;507}508if (sigsize < ED448_SIGSIZE) {509ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);510return 0;511}512if (edkey->privkey == NULL) {513ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);514return 0;515}516#ifdef S390X_EC_ASM517/*518* s390x_ed448_digestsign() does not yet support context-strings or519* pre-hashing. Fall back to non-accelerated sign if a context-string or520* pre-hasing is provided.521*/522if (S390X_CAN_SIGN(ED448)523&& peddsactx->context_string_len == 0524&& !peddsactx->prehash_flag525&& !peddsactx->prehash_by_caller_flag) {526if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {527ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);528return 0;529}530*siglen = ED448_SIGSIZE;531return 1;532}533#endif /* S390X_EC_ASM */534535if (peddsactx->prehash_flag) {536if (!peddsactx->prehash_by_caller_flag) {537if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))538return 0;539tbs = md;540tbslen = mdlen;541} else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {542ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);543return 0;544}545} else if (peddsactx->prehash_by_caller_flag) {546/* The caller is supposed to set up a ph instance! */547ERR_raise(ERR_LIB_PROV,548PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);549return 0;550}551552if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen,553edkey->pubkey, edkey->privkey,554peddsactx->context_string, peddsactx->context_string_len,555peddsactx->prehash_flag, edkey->propq)556== 0) {557ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);558return 0;559}560*siglen = ED448_SIGSIZE;561return 1;562}563564/*565* This is used directly for OSSL_FUNC_SIGNATURE_VERIFY and indirectly566* for OSSL_FUNC_SIGNATURE_DIGEST_VERIFY567*/568static int ed25519_verify(void *vpeddsactx,569const unsigned char *sig, size_t siglen,570const unsigned char *tbs, size_t tbslen)571{572PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;573const ECX_KEY *edkey = peddsactx->key;574uint8_t md[EVP_MAX_MD_SIZE];575size_t mdlen;576577if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)578return 0;579580#ifdef S390X_EC_ASM581/*582* s390x_ed25519_digestverify() does not yet support dom2 or context-strings.583* fall back to non-accelerated verify if those options are set, or584* pre-hasing is provided.585*/586if (S390X_CAN_SIGN(ED25519)587&& !peddsactx->dom2_flag588&& !peddsactx->context_string_flag589&& peddsactx->context_string_len == 0590&& !peddsactx->prehash_flag591&& !peddsactx->prehash_by_caller_flag)592return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);593#endif /* S390X_EC_ASM */594595if (peddsactx->prehash_flag) {596if (!peddsactx->prehash_by_caller_flag) {597if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL,598tbs, tbslen, md, &mdlen)599|| mdlen != EDDSA_PREHASH_OUTPUT_LEN) {600ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PREHASHED_DIGEST_LENGTH);601return 0;602}603tbs = md;604tbslen = mdlen;605} else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {606ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);607return 0;608}609} else if (peddsactx->prehash_by_caller_flag) {610/* The caller is supposed to set up a ph instance! */611ERR_raise(ERR_LIB_PROV,612PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);613return 0;614}615616return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,617peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,618peddsactx->context_string, peddsactx->context_string_len,619peddsactx->libctx, edkey->propq);620}621622/*623* This is used directly for OSSL_FUNC_SIGNATURE_VERIFY and indirectly624* for OSSL_FUNC_SIGNATURE_DIGEST_VERIFY625*/626static int ed448_verify(void *vpeddsactx,627const unsigned char *sig, size_t siglen,628const unsigned char *tbs, size_t tbslen)629{630PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;631const ECX_KEY *edkey = peddsactx->key;632uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];633size_t mdlen = sizeof(md);634635if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)636return 0;637638#ifdef S390X_EC_ASM639/*640* s390x_ed448_digestverify() does not yet support context-strings or641* pre-hashing. Fall back to non-accelerated verify if a context-string or642* pre-hasing is provided.643*/644if (S390X_CAN_SIGN(ED448)645&& peddsactx->context_string_len == 0646&& !peddsactx->prehash_flag647&& !peddsactx->prehash_by_caller_flag)648return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);649#endif /* S390X_EC_ASM */650651if (peddsactx->prehash_flag) {652if (!peddsactx->prehash_by_caller_flag) {653if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))654return 0;655tbs = md;656tbslen = mdlen;657} else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {658ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);659return 0;660}661} else if (peddsactx->prehash_by_caller_flag) {662/* The caller is supposed to set up a ph instance! */663ERR_raise(ERR_LIB_PROV,664PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);665return 0;666}667668return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,669peddsactx->context_string, peddsactx->context_string_len,670peddsactx->prehash_flag, edkey->propq);671}672673/* All digest_{sign,verify} are simple wrappers around the functions above */674675static int ed25519_digest_signverify_init(void *vpeddsactx, const char *mdname,676void *vedkey,677const OSSL_PARAM params[])678{679PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;680681if (mdname != NULL && mdname[0] != '\0') {682ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,683"Explicit digest not allowed with EdDSA operations");684return 0;685}686687if (vedkey == NULL && peddsactx->key != NULL)688return eddsa_set_ctx_params(peddsactx, params);689690return eddsa_signverify_init(vpeddsactx, vedkey)691&& eddsa_setup_instance(vpeddsactx, ID_Ed25519, 0, 0)692&& eddsa_set_ctx_params(vpeddsactx, params);693}694695static int ed25519_digest_sign(void *vpeddsactx,696unsigned char *sigret, size_t *siglen, size_t sigsize,697const unsigned char *tbs, size_t tbslen)698{699return ed25519_sign(vpeddsactx, sigret, siglen, sigsize, tbs, tbslen);700}701702static int ed25519_digest_verify(void *vpeddsactx,703const unsigned char *sigret, size_t siglen,704const unsigned char *tbs, size_t tbslen)705{706return ed25519_verify(vpeddsactx, sigret, siglen, tbs, tbslen);707}708709static int ed448_digest_signverify_init(void *vpeddsactx, const char *mdname,710void *vedkey,711const OSSL_PARAM params[])712{713PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;714715if (mdname != NULL && mdname[0] != '\0') {716ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,717"Explicit digest not allowed with EdDSA operations");718return 0;719}720721if (vedkey == NULL && peddsactx->key != NULL)722return eddsa_set_ctx_params(peddsactx, params);723724return eddsa_signverify_init(vpeddsactx, vedkey)725&& eddsa_setup_instance(vpeddsactx, ID_Ed448, 0, 0)726&& eddsa_set_ctx_params(vpeddsactx, params);727}728729static int ed448_digest_sign(void *vpeddsactx,730unsigned char *sigret, size_t *siglen, size_t sigsize,731const unsigned char *tbs, size_t tbslen)732{733return ed448_sign(vpeddsactx, sigret, siglen, sigsize, tbs, tbslen);734}735736static int ed448_digest_verify(void *vpeddsactx,737const unsigned char *sigret, size_t siglen,738const unsigned char *tbs, size_t tbslen)739{740return ed448_verify(vpeddsactx, sigret, siglen, tbs, tbslen);741}742743static void eddsa_freectx(void *vpeddsactx)744{745PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;746747ossl_ecx_key_free(peddsactx->key);748749OPENSSL_free(peddsactx);750}751752static void *eddsa_dupctx(void *vpeddsactx)753{754PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;755PROV_EDDSA_CTX *dstctx;756757if (!ossl_prov_is_running())758return NULL;759760dstctx = OPENSSL_zalloc(sizeof(*srcctx));761if (dstctx == NULL)762return NULL;763764*dstctx = *srcctx;765dstctx->key = NULL;766767if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {768ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);769goto err;770}771dstctx->key = srcctx->key;772773return dstctx;774err:775eddsa_freectx(dstctx);776return NULL;777}778779static const char **ed25519_sigalg_query_key_types(void)780{781static const char *keytypes[] = { "ED25519", NULL };782783return keytypes;784}785786static const char **ed448_sigalg_query_key_types(void)787{788static const char *keytypes[] = { "ED448", NULL };789790return keytypes;791}792793static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)794{795PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;796OSSL_PARAM *p;797798if (peddsactx == NULL)799return 0;800801p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);802if (p != NULL803&& !OSSL_PARAM_set_octet_string(p,804peddsactx->aid_len == 0 ? NULL : peddsactx->aid_buf,805peddsactx->aid_len))806return 0;807808return 1;809}810811static const OSSL_PARAM known_gettable_ctx_params[] = {812OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),813OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),814OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),815OSSL_PARAM_END816};817818static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,819ossl_unused void *provctx)820{821return known_gettable_ctx_params;822}823824static int eddsa_set_ctx_params(void *vpeddsactx, const OSSL_PARAM params[])825{826PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;827const OSSL_PARAM *p;828829if (peddsactx == NULL)830return 0;831if (ossl_param_is_empty(params))832return 1;833834p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_INSTANCE);835if (p != NULL) {836char instance_name[OSSL_MAX_NAME_SIZE] = "";837char *pinstance_name = instance_name;838839if (peddsactx->instance_id_preset_flag) {840/* When the instance is preset, the caller must no try to set it */841ERR_raise_data(ERR_LIB_PROV, PROV_R_NO_INSTANCE_ALLOWED,842"the EdDSA instance is preset, you may not try to specify it",843NULL);844return 0;845}846847if (!OSSL_PARAM_get_utf8_string(p, &pinstance_name, sizeof(instance_name)))848return 0;849850/*851* When setting the new instance, we're careful not to change the852* prehash_by_caller flag, as that's always preset by the init853* functions. The sign functions will determine if the instance854* matches this flag.855*/856if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519) == 0) {857eddsa_setup_instance(peddsactx, ID_Ed25519, 0,858peddsactx->prehash_by_caller_flag);859#ifndef FIPS_MODULE860} else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ctx) == 0) {861eddsa_setup_instance(peddsactx, ID_Ed25519ctx, 0,862peddsactx->prehash_by_caller_flag);863#endif864} else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ph) == 0) {865eddsa_setup_instance(peddsactx, ID_Ed25519ph, 0,866peddsactx->prehash_by_caller_flag);867} else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448) == 0) {868eddsa_setup_instance(peddsactx, ID_Ed448, 0,869peddsactx->prehash_by_caller_flag);870} else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448ph) == 0) {871eddsa_setup_instance(peddsactx, ID_Ed448ph, 0,872peddsactx->prehash_by_caller_flag);873} else {874/* we did not recognize the instance */875ERR_raise_data(ERR_LIB_PROV,876PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION,877"unknown INSTANCE name: %s",878pinstance_name != NULL ? pinstance_name : "<null>");879return 0;880}881}882883p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_CONTEXT_STRING);884if (p != NULL) {885void *vp_context_string = peddsactx->context_string;886887if (!OSSL_PARAM_get_octet_string(p, &vp_context_string, sizeof(peddsactx->context_string), &(peddsactx->context_string_len))) {888peddsactx->context_string_len = 0;889return 0;890}891}892893return 1;894}895896static const OSSL_PARAM settable_ctx_params[] = {897OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),898OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),899OSSL_PARAM_END900};901902static const OSSL_PARAM *eddsa_settable_ctx_params(ossl_unused void *vpeddsactx,903ossl_unused void *provctx)904{905return settable_ctx_params;906}907908static const OSSL_PARAM settable_variant_ctx_params[] = {909OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),910OSSL_PARAM_END911};912913static const OSSL_PARAM *914eddsa_settable_variant_ctx_params(ossl_unused void *vpeddsactx,915ossl_unused void *provctx)916{917return settable_variant_ctx_params;918}919920/*921* Ed25519 can be used with:922* - EVP_PKEY_sign_init_ex2() [ instance and prehash assumed done by caller ]923* - EVP_PKEY_verify_init_ex2() [ instance and prehash assumed done by caller ]924* - EVP_PKEY_sign_message_init()925* - EVP_PKEY_verify_message_init()926* - EVP_DigestSignInit_ex()927* - EVP_DigestVerifyInit_ex()928* Ed25519ph can be used with:929* - EVP_PKEY_sign_init_ex2() [ prehash assumed done by caller ]930* - EVP_PKEY_verify_init_ex2() [ prehash assumed done by caller ]931* - EVP_PKEY_sign_message_init()932* - EVP_PKEY_verify_message_init()933* Ed25519ctx can be used with:934* - EVP_PKEY_sign_message_init()935* - EVP_PKEY_verify_message_init()936* Ed448 can be used with:937* - EVP_PKEY_sign_init_ex2() [ instance and prehash assumed done by caller ]938* - EVP_PKEY_verify_init_ex2() [ instance and prehash assumed done by caller ]939* - EVP_PKEY_sign_message_init()940* - EVP_PKEY_verify_message_init()941* - EVP_DigestSignInit_ex()942* - EVP_DigestVerifyInit_ex()943* Ed448ph can be used with:944* - EVP_PKEY_sign_init_ex2() [ prehash assumed done by caller ]945* - EVP_PKEY_verify_init_ex2() [ prehash assumed done by caller ]946* - EVP_PKEY_sign_message_init()947* - EVP_PKEY_verify_message_init()948*/949950#define ed25519_DISPATCH_END \951{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \952(void (*)(void))ed25519_signverify_init }, \953{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \954(void (*)(void))ed25519_signverify_init }, \955{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \956(void (*)(void))ed25519_digest_signverify_init }, \957{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN, \958(void (*)(void))ed25519_digest_sign }, \959{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, \960(void (*)(void))ed25519_digest_signverify_init }, \961{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, \962(void (*)(void))ed25519_digest_verify }, \963{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \964(void (*)(void))eddsa_get_ctx_params }, \965{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \966(void (*)(void))eddsa_gettable_ctx_params }, \967{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \968(void (*)(void))eddsa_set_ctx_params }, \969{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \970(void (*)(void))eddsa_settable_ctx_params }, \971OSSL_DISPATCH_END972973#define eddsa_variant_DISPATCH_END(v) \974{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \975(void (*)(void))v##_signverify_message_init }, \976{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \977(void (*)(void))v##_signverify_message_init }, \978{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \979(void (*)(void))eddsa_get_ctx_params }, \980{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \981(void (*)(void))eddsa_gettable_ctx_params }, \982{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \983(void (*)(void))eddsa_set_ctx_params }, \984{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \985(void (*)(void))eddsa_settable_variant_ctx_params }, \986OSSL_DISPATCH_END987988#define ed25519ph_DISPATCH_END \989{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \990(void (*)(void))ed25519ph_signverify_init }, \991{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \992(void (*)(void))ed25519ph_signverify_init }, \993eddsa_variant_DISPATCH_END(ed25519ph)994995#define ed25519ctx_DISPATCH_END eddsa_variant_DISPATCH_END(ed25519ctx)996997#define ed448_DISPATCH_END \998{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \999(void (*)(void))ed448_signverify_init }, \1000{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \1001(void (*)(void))ed448_signverify_init }, \1002{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \1003(void (*)(void))ed448_digest_signverify_init }, \1004{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN, \1005(void (*)(void))ed448_digest_sign }, \1006{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, \1007(void (*)(void))ed448_digest_signverify_init }, \1008{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, \1009(void (*)(void))ed448_digest_verify }, \1010{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \1011(void (*)(void))eddsa_get_ctx_params }, \1012{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \1013(void (*)(void))eddsa_gettable_ctx_params }, \1014{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \1015(void (*)(void))eddsa_set_ctx_params }, \1016{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \1017(void (*)(void))eddsa_settable_ctx_params }, \1018OSSL_DISPATCH_END10191020#define ed448ph_DISPATCH_END \1021{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \1022(void (*)(void))ed448ph_signverify_init }, \1023{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \1024(void (*)(void))ed448ph_signverify_init }, \1025eddsa_variant_DISPATCH_END(ed448ph)10261027/* vn = variant name, bn = base name */1028#define IMPL_EDDSA_DISPATCH(vn, bn) \1029const OSSL_DISPATCH ossl_##vn##_signature_functions[] = { \1030{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx }, \1031{ OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, \1032(void (*)(void))vn##_signverify_message_init }, \1033{ OSSL_FUNC_SIGNATURE_SIGN, \1034(void (*)(void))bn##_sign }, \1035{ OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, \1036(void (*)(void))vn##_signverify_message_init }, \1037{ OSSL_FUNC_SIGNATURE_VERIFY, \1038(void (*)(void))bn##_verify }, \1039{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, \1040{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx }, \1041{ OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES, \1042(void (*)(void))bn##_sigalg_query_key_types }, \1043vn##_DISPATCH_END \1044}10451046IMPL_EDDSA_DISPATCH(ed25519, ed25519);1047IMPL_EDDSA_DISPATCH(ed25519ph, ed25519);1048IMPL_EDDSA_DISPATCH(ed25519ctx, ed25519);1049IMPL_EDDSA_DISPATCH(ed448, ed448);1050IMPL_EDDSA_DISPATCH(ed448ph, ed448);10511052#ifdef S390X_EC_ASM10531054static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,1055const unsigned char *tbs, size_t tbslen)1056{1057int rc;1058union {1059struct {1060unsigned char sig[64];1061unsigned char priv[32];1062} ed25519;1063unsigned long long buff[512];1064} param;10651066memset(¶m, 0, sizeof(param));1067memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));10681069rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen);1070OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));1071if (rc != 0)1072return 0;10731074s390x_flip_endian32(sig, param.ed25519.sig);1075s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);1076return 1;1077}10781079static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,1080const unsigned char *tbs, size_t tbslen)1081{1082int rc;1083union {1084struct {1085unsigned char sig[128];1086unsigned char priv[64];1087} ed448;1088unsigned long long buff[512];1089} param;10901091memset(¶m, 0, sizeof(param));1092memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);10931094rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen);1095OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));1096if (rc != 0)1097return 0;10981099s390x_flip_endian64(param.ed448.sig, param.ed448.sig);1100s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);1101memcpy(sig, param.ed448.sig, 57);1102memcpy(sig + 57, param.ed448.sig + 64, 57);1103return 1;1104}11051106static int s390x_ed25519_digestverify(const ECX_KEY *edkey,1107const unsigned char *sig,1108const unsigned char *tbs, size_t tbslen)1109{1110union {1111struct {1112unsigned char sig[64];1113unsigned char pub[32];1114} ed25519;1115unsigned long long buff[512];1116} param;11171118memset(¶m, 0, sizeof(param));1119s390x_flip_endian32(param.ed25519.sig, sig);1120s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);1121s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);11221123return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,1124¶m.ed25519, tbs, tbslen)1125== 01126? 11127: 0;1128}11291130static int s390x_ed448_digestverify(const ECX_KEY *edkey,1131const unsigned char *sig,1132const unsigned char *tbs,1133size_t tbslen)1134{1135union {1136struct {1137unsigned char sig[128];1138unsigned char pub[64];1139} ed448;1140unsigned long long buff[512];1141} param;11421143memset(¶m, 0, sizeof(param));1144memcpy(param.ed448.sig, sig, 57);1145s390x_flip_endian64(param.ed448.sig, param.ed448.sig);1146memcpy(param.ed448.sig + 64, sig + 57, 57);1147s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);1148memcpy(param.ed448.pub, edkey->pubkey, 57);1149s390x_flip_endian64(param.ed448.pub, param.ed448.pub);11501151return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,1152¶m.ed448, tbs, tbslen)1153== 01154? 11155: 0;1156}11571158#endif /* S390X_EC_ASM */115911601161