Path: blob/main/crypto/openssl/providers/implementations/signature/eddsa_sig.c
48383 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;193case ID_Ed25519ctx:194if (peddsactx->key->type != ECX_KEY_TYPE_ED25519)195return 0;196peddsactx->dom2_flag = 1;197peddsactx->prehash_flag = 0;198peddsactx->context_string_flag = 1;199break;200case ID_Ed25519ph:201if (peddsactx->key->type != ECX_KEY_TYPE_ED25519)202return 0;203peddsactx->dom2_flag = 1;204peddsactx->prehash_flag = 1;205peddsactx->context_string_flag = 0;206break;207case ID_Ed448:208if (peddsactx->key->type != ECX_KEY_TYPE_ED448)209return 0;210peddsactx->prehash_flag = 0;211peddsactx->context_string_flag = 0;212break;213case ID_Ed448ph:214if (peddsactx->key->type != ECX_KEY_TYPE_ED448)215return 0;216peddsactx->prehash_flag = 1;217peddsactx->context_string_flag = 0;218break;219default:220/* we did not recognize the instance */221return 0;222}223peddsactx->instance_id = instance_id;224peddsactx->instance_id_preset_flag = instance_id_preset;225peddsactx->prehash_by_caller_flag = prehash_by_caller;226return 1;227}228229static int eddsa_signverify_init(void *vpeddsactx, void *vedkey)230{231PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;232ECX_KEY *edkey = (ECX_KEY *)vedkey;233WPACKET pkt;234int ret;235unsigned char *aid = NULL;236237if (!ossl_prov_is_running())238return 0;239240if (edkey == NULL) {241ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);242return 0;243}244245if (!ossl_ecx_key_up_ref(edkey)) {246ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);247return 0;248}249250peddsactx->instance_id_preset_flag = 0;251peddsactx->dom2_flag = 0;252peddsactx->prehash_flag = 0;253peddsactx->context_string_flag = 0;254peddsactx->context_string_len = 0;255256peddsactx->key = edkey;257258/*259* We do not care about DER writing errors.260* All it really means is that for some reason, there's no261* AlgorithmIdentifier to be had, but the operation itself is262* still valid, just as long as it's not used to construct263* anything that needs an AlgorithmIdentifier.264*/265peddsactx->aid_len = 0;266ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));267switch (edkey->type) {268case ECX_KEY_TYPE_ED25519:269ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);270break;271case ECX_KEY_TYPE_ED448:272ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);273break;274default:275/* Should never happen */276ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);277ossl_ecx_key_free(edkey);278peddsactx->key = NULL;279WPACKET_cleanup(&pkt);280return 0;281}282if (ret && WPACKET_finish(&pkt)) {283WPACKET_get_total_written(&pkt, &peddsactx->aid_len);284aid = WPACKET_get_curr(&pkt);285}286WPACKET_cleanup(&pkt);287if (aid != NULL && peddsactx->aid_len != 0)288memmove(peddsactx->aid_buf, aid, peddsactx->aid_len);289290return 1;291}292293static int ed25519_signverify_message_init(void *vpeddsactx, void *vedkey,294const OSSL_PARAM params[])295{296return eddsa_signverify_init(vpeddsactx, vedkey)297&& eddsa_setup_instance(vpeddsactx, ID_Ed25519, 1, 0)298&& eddsa_set_ctx_params(vpeddsactx, params);299}300301static int ed25519ph_signverify_message_init(void *vpeddsactx, void *vedkey,302const OSSL_PARAM params[])303{304return eddsa_signverify_init(vpeddsactx, vedkey)305&& eddsa_setup_instance(vpeddsactx, ID_Ed25519ph, 1, 0)306&& eddsa_set_ctx_params(vpeddsactx, params);307}308309static int ed25519ph_signverify_init(void *vpeddsactx, void *vedkey,310const OSSL_PARAM params[])311{312return eddsa_signverify_init(vpeddsactx, vedkey)313&& eddsa_setup_instance(vpeddsactx, ID_Ed25519ph, 1, 1)314&& eddsa_set_ctx_params(vpeddsactx, params);315}316317/*318* This supports using ED25519 with EVP_PKEY_{sign,verify}_init_ex() and319* EVP_PKEY_{sign,verify}_init_ex2(), under the condition that the caller320* explicitly sets the Ed25519ph instance (this is verified by ed25519_sign()321* and ed25519_verify())322*/323static int ed25519_signverify_init(void *vpeddsactx, void *vedkey,324const OSSL_PARAM params[])325{326return eddsa_signverify_init(vpeddsactx, vedkey)327&& eddsa_setup_instance(vpeddsactx, ID_Ed25519, 0, 1)328&& eddsa_set_ctx_params(vpeddsactx, params);329}330331static int ed25519ctx_signverify_message_init(void *vpeddsactx, void *vedkey,332const OSSL_PARAM params[])333{334return eddsa_signverify_init(vpeddsactx, vedkey)335&& eddsa_setup_instance(vpeddsactx, ID_Ed25519ctx, 1, 0)336&& eddsa_set_ctx_params(vpeddsactx, params);337}338339static int ed448_signverify_message_init(void *vpeddsactx, void *vedkey,340const OSSL_PARAM params[])341{342return eddsa_signverify_init(vpeddsactx, vedkey)343&& eddsa_setup_instance(vpeddsactx, ID_Ed448, 1, 0)344&& eddsa_set_ctx_params(vpeddsactx, params);345}346347static int ed448ph_signverify_message_init(void *vpeddsactx, void *vedkey,348const OSSL_PARAM params[])349{350return eddsa_signverify_init(vpeddsactx, vedkey)351&& eddsa_setup_instance(vpeddsactx, ID_Ed448ph, 1, 0)352&& eddsa_set_ctx_params(vpeddsactx, params);353}354355static int ed448ph_signverify_init(void *vpeddsactx, void *vedkey,356const OSSL_PARAM params[])357{358return eddsa_signverify_init(vpeddsactx, vedkey)359&& eddsa_setup_instance(vpeddsactx, ID_Ed448ph, 1, 1)360&& eddsa_set_ctx_params(vpeddsactx, params);361}362363/*364* This supports using ED448 with EVP_PKEY_{sign,verify}_init_ex() and365* EVP_PKEY_{sign,verify}_init_ex2(), under the condition that the caller366* explicitly sets the Ed448ph instance (this is verified by ed448_sign()367* and ed448_verify())368*/369static int ed448_signverify_init(void *vpeddsactx, void *vedkey,370const OSSL_PARAM params[])371{372return eddsa_signverify_init(vpeddsactx, vedkey)373&& eddsa_setup_instance(vpeddsactx, ID_Ed448, 0, 1)374&& eddsa_set_ctx_params(vpeddsactx, params);375}376377/*378* This is used directly for OSSL_FUNC_SIGNATURE_SIGN and indirectly379* for OSSL_FUNC_SIGNATURE_DIGEST_SIGN380*/381static int ed25519_sign(void *vpeddsactx,382unsigned char *sigret, size_t *siglen, size_t sigsize,383const unsigned char *tbs, size_t tbslen)384{385PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;386const ECX_KEY *edkey = peddsactx->key;387uint8_t md[EVP_MAX_MD_SIZE];388size_t mdlen;389390if (!ossl_prov_is_running())391return 0;392393if (sigret == NULL) {394*siglen = ED25519_SIGSIZE;395return 1;396}397if (sigsize < ED25519_SIGSIZE) {398ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);399return 0;400}401if (edkey->privkey == NULL) {402ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);403return 0;404}405#ifdef S390X_EC_ASM406/*407* s390x_ed25519_digestsign() does not yet support dom2 or context-strings.408* fall back to non-accelerated sign if those options are set, or pre-hasing409* is provided.410*/411if (S390X_CAN_SIGN(ED25519)412&& !peddsactx->dom2_flag413&& !peddsactx->context_string_flag414&& peddsactx->context_string_len == 0415&& !peddsactx->prehash_flag416&& !peddsactx->prehash_by_caller_flag) {417if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {418ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);419return 0;420}421*siglen = ED25519_SIGSIZE;422return 1;423}424#endif /* S390X_EC_ASM */425426if (peddsactx->prehash_flag) {427if (!peddsactx->prehash_by_caller_flag) {428if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL,429tbs, tbslen, md, &mdlen)430|| mdlen != EDDSA_PREHASH_OUTPUT_LEN) {431ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PREHASHED_DIGEST_LENGTH);432return 0;433}434tbs = md;435tbslen = mdlen;436} else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {437ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);438return 0;439}440} else if (peddsactx->prehash_by_caller_flag) {441/* The caller is supposed to set up a ph instance! */442ERR_raise(ERR_LIB_PROV,443PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);444return 0;445}446447if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,448peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,449peddsactx->context_string, peddsactx->context_string_len,450peddsactx->libctx, NULL) == 0) {451ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);452return 0;453}454*siglen = ED25519_SIGSIZE;455return 1;456}457458/* EVP_Q_digest() does not allow variable output length for XOFs,459so we use this function */460static int ed448_shake256(OSSL_LIB_CTX *libctx,461const char *propq,462const uint8_t *in, size_t inlen,463uint8_t *out, size_t outlen)464{465int ret = 0;466EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new();467EVP_MD *shake256 = EVP_MD_fetch(libctx, SN_shake256, propq);468469if (hash_ctx == NULL || shake256 == NULL)470goto err;471472if (!EVP_DigestInit_ex(hash_ctx, shake256, NULL)473|| !EVP_DigestUpdate(hash_ctx, in, inlen)474|| !EVP_DigestFinalXOF(hash_ctx, out, outlen))475goto err;476477ret = 1;478479err:480EVP_MD_CTX_free(hash_ctx);481EVP_MD_free(shake256);482return ret;483}484485/*486* This is used directly for OSSL_FUNC_SIGNATURE_SIGN and indirectly487* for OSSL_FUNC_SIGNATURE_DIGEST_SIGN488*/489static int ed448_sign(void *vpeddsactx,490unsigned char *sigret, size_t *siglen, size_t sigsize,491const unsigned char *tbs, size_t tbslen)492{493PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;494const ECX_KEY *edkey = peddsactx->key;495uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];496size_t mdlen = sizeof(md);497498if (!ossl_prov_is_running())499return 0;500501if (sigret == NULL) {502*siglen = ED448_SIGSIZE;503return 1;504}505if (sigsize < ED448_SIGSIZE) {506ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);507return 0;508}509if (edkey->privkey == NULL) {510ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);511return 0;512}513#ifdef S390X_EC_ASM514/*515* s390x_ed448_digestsign() does not yet support context-strings or516* pre-hashing. Fall back to non-accelerated sign if a context-string or517* pre-hasing is provided.518*/519if (S390X_CAN_SIGN(ED448)520&& peddsactx->context_string_len == 0521&& !peddsactx->prehash_flag522&& !peddsactx->prehash_by_caller_flag) {523if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {524ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);525return 0;526}527*siglen = ED448_SIGSIZE;528return 1;529}530#endif /* S390X_EC_ASM */531532if (peddsactx->prehash_flag) {533if (!peddsactx->prehash_by_caller_flag) {534if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))535return 0;536tbs = md;537tbslen = mdlen;538} else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {539ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);540return 0;541}542} else if (peddsactx->prehash_by_caller_flag) {543/* The caller is supposed to set up a ph instance! */544ERR_raise(ERR_LIB_PROV,545PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);546return 0;547}548549if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen,550edkey->pubkey, edkey->privkey,551peddsactx->context_string, peddsactx->context_string_len,552peddsactx->prehash_flag, edkey->propq) == 0) {553ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);554return 0;555}556*siglen = ED448_SIGSIZE;557return 1;558}559560/*561* This is used directly for OSSL_FUNC_SIGNATURE_VERIFY and indirectly562* for OSSL_FUNC_SIGNATURE_DIGEST_VERIFY563*/564static int ed25519_verify(void *vpeddsactx,565const unsigned char *sig, size_t siglen,566const unsigned char *tbs, size_t tbslen)567{568PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;569const ECX_KEY *edkey = peddsactx->key;570uint8_t md[EVP_MAX_MD_SIZE];571size_t mdlen;572573if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)574return 0;575576#ifdef S390X_EC_ASM577/*578* s390x_ed25519_digestverify() does not yet support dom2 or context-strings.579* fall back to non-accelerated verify if those options are set, or580* pre-hasing is provided.581*/582if (S390X_CAN_SIGN(ED25519)583&& !peddsactx->dom2_flag584&& !peddsactx->context_string_flag585&& peddsactx->context_string_len == 0586&& !peddsactx->prehash_flag587&& !peddsactx->prehash_by_caller_flag)588return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);589#endif /* S390X_EC_ASM */590591if (peddsactx->prehash_flag) {592if (!peddsactx->prehash_by_caller_flag) {593if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL,594tbs, tbslen, md, &mdlen)595|| mdlen != EDDSA_PREHASH_OUTPUT_LEN) {596ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PREHASHED_DIGEST_LENGTH);597return 0;598}599tbs = md;600tbslen = mdlen;601} else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {602ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);603return 0;604}605} else if (peddsactx->prehash_by_caller_flag) {606/* The caller is supposed to set up a ph instance! */607ERR_raise(ERR_LIB_PROV,608PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);609return 0;610}611612return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,613peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,614peddsactx->context_string, peddsactx->context_string_len,615peddsactx->libctx, edkey->propq);616}617618/*619* This is used directly for OSSL_FUNC_SIGNATURE_VERIFY and indirectly620* for OSSL_FUNC_SIGNATURE_DIGEST_VERIFY621*/622static int ed448_verify(void *vpeddsactx,623const unsigned char *sig, size_t siglen,624const unsigned char *tbs, size_t tbslen)625{626PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;627const ECX_KEY *edkey = peddsactx->key;628uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];629size_t mdlen = sizeof(md);630631if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)632return 0;633634#ifdef S390X_EC_ASM635/*636* s390x_ed448_digestverify() does not yet support context-strings or637* pre-hashing. Fall back to non-accelerated verify if a context-string or638* pre-hasing is provided.639*/640if (S390X_CAN_SIGN(ED448)641&& peddsactx->context_string_len == 0642&& !peddsactx->prehash_flag643&& !peddsactx->prehash_by_caller_flag)644return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);645#endif /* S390X_EC_ASM */646647if (peddsactx->prehash_flag) {648if (!peddsactx->prehash_by_caller_flag) {649if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))650return 0;651tbs = md;652tbslen = mdlen;653} else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {654ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);655return 0;656}657} else if (peddsactx->prehash_by_caller_flag) {658/* The caller is supposed to set up a ph instance! */659ERR_raise(ERR_LIB_PROV,660PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);661return 0;662}663664return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,665peddsactx->context_string, peddsactx->context_string_len,666peddsactx->prehash_flag, edkey->propq);667}668669/* All digest_{sign,verify} are simple wrappers around the functions above */670671static int ed25519_digest_signverify_init(void *vpeddsactx, const char *mdname,672void *vedkey,673const OSSL_PARAM params[])674{675PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;676677if (mdname != NULL && mdname[0] != '\0') {678ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,679"Explicit digest not allowed with EdDSA operations");680return 0;681}682683if (vedkey == NULL && peddsactx->key != NULL)684return eddsa_set_ctx_params(peddsactx, params);685686return eddsa_signverify_init(vpeddsactx, vedkey)687&& eddsa_setup_instance(vpeddsactx, ID_Ed25519, 0, 0)688&& eddsa_set_ctx_params(vpeddsactx, params);689}690691static int ed25519_digest_sign(void *vpeddsactx,692unsigned char *sigret, size_t *siglen, size_t sigsize,693const unsigned char *tbs, size_t tbslen)694{695return ed25519_sign(vpeddsactx, sigret, siglen, sigsize, tbs, tbslen);696}697698static int ed25519_digest_verify(void *vpeddsactx,699const unsigned char *sigret, size_t siglen,700const unsigned char *tbs, size_t tbslen)701{702return ed25519_verify(vpeddsactx, sigret, siglen, tbs, tbslen);703}704705static int ed448_digest_signverify_init(void *vpeddsactx, const char *mdname,706void *vedkey,707const OSSL_PARAM params[])708{709PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;710711if (mdname != NULL && mdname[0] != '\0') {712ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,713"Explicit digest not allowed with EdDSA operations");714return 0;715}716717if (vedkey == NULL && peddsactx->key != NULL)718return eddsa_set_ctx_params(peddsactx, params);719720return eddsa_signverify_init(vpeddsactx, vedkey)721&& eddsa_setup_instance(vpeddsactx, ID_Ed448, 0, 0)722&& eddsa_set_ctx_params(vpeddsactx, params);723}724725static int ed448_digest_sign(void *vpeddsactx,726unsigned char *sigret, size_t *siglen, size_t sigsize,727const unsigned char *tbs, size_t tbslen)728{729return ed448_sign(vpeddsactx, sigret, siglen, sigsize, tbs, tbslen);730}731732static int ed448_digest_verify(void *vpeddsactx,733const unsigned char *sigret, size_t siglen,734const unsigned char *tbs, size_t tbslen)735{736return ed448_verify(vpeddsactx, sigret, siglen, tbs, tbslen);737}738739static void eddsa_freectx(void *vpeddsactx)740{741PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;742743ossl_ecx_key_free(peddsactx->key);744745OPENSSL_free(peddsactx);746}747748static void *eddsa_dupctx(void *vpeddsactx)749{750PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;751PROV_EDDSA_CTX *dstctx;752753if (!ossl_prov_is_running())754return NULL;755756dstctx = OPENSSL_zalloc(sizeof(*srcctx));757if (dstctx == NULL)758return NULL;759760*dstctx = *srcctx;761dstctx->key = NULL;762763if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {764ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);765goto err;766}767dstctx->key = srcctx->key;768769return dstctx;770err:771eddsa_freectx(dstctx);772return NULL;773}774775static const char **ed25519_sigalg_query_key_types(void)776{777static const char *keytypes[] = { "ED25519", NULL };778779return keytypes;780}781782static const char **ed448_sigalg_query_key_types(void)783{784static const char *keytypes[] = { "ED448", NULL };785786return keytypes;787}788789790791static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)792{793PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;794OSSL_PARAM *p;795796if (peddsactx == NULL)797return 0;798799p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);800if (p != NULL801&& !OSSL_PARAM_set_octet_string(p,802peddsactx->aid_len == 0 ? NULL : peddsactx->aid_buf,803peddsactx->aid_len))804return 0;805806return 1;807}808809static const OSSL_PARAM known_gettable_ctx_params[] = {810OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),811OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),812OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),813OSSL_PARAM_END814};815816static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,817ossl_unused void *provctx)818{819return known_gettable_ctx_params;820}821822static int eddsa_set_ctx_params(void *vpeddsactx, const OSSL_PARAM params[])823{824PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;825const OSSL_PARAM *p;826827if (peddsactx == NULL)828return 0;829if (ossl_param_is_empty(params))830return 1;831832p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_INSTANCE);833if (p != NULL) {834char instance_name[OSSL_MAX_NAME_SIZE] = "";835char *pinstance_name = instance_name;836837if (peddsactx->instance_id_preset_flag) {838/* When the instance is preset, the caller must no try to set it */839ERR_raise_data(ERR_LIB_PROV, PROV_R_NO_INSTANCE_ALLOWED,840"the EdDSA instance is preset, you may not try to specify it",841NULL);842return 0;843}844845if (!OSSL_PARAM_get_utf8_string(p, &pinstance_name, sizeof(instance_name)))846return 0;847848/*849* When setting the new instance, we're careful not to change the850* prehash_by_caller flag, as that's always preset by the init851* functions. The sign functions will determine if the instance852* matches this flag.853*/854if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519) == 0) {855eddsa_setup_instance(peddsactx, ID_Ed25519, 0,856peddsactx->prehash_by_caller_flag);857} else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ctx) == 0) {858eddsa_setup_instance(peddsactx, ID_Ed25519ctx, 0,859peddsactx->prehash_by_caller_flag);860} else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ph) == 0) {861eddsa_setup_instance(peddsactx, ID_Ed25519ph, 0,862peddsactx->prehash_by_caller_flag);863} else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448) == 0) {864eddsa_setup_instance(peddsactx, ID_Ed448, 0,865peddsactx->prehash_by_caller_flag);866} else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448ph) == 0) {867eddsa_setup_instance(peddsactx, ID_Ed448ph, 0,868peddsactx->prehash_by_caller_flag);869} else {870/* we did not recognize the instance */871return 0;872}873874}875876p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_CONTEXT_STRING);877if (p != NULL) {878void *vp_context_string = peddsactx->context_string;879880if (!OSSL_PARAM_get_octet_string(p, &vp_context_string, sizeof(peddsactx->context_string), &(peddsactx->context_string_len))) {881peddsactx->context_string_len = 0;882return 0;883}884}885886return 1;887}888889static const OSSL_PARAM settable_ctx_params[] = {890OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),891OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),892OSSL_PARAM_END893};894895static const OSSL_PARAM *eddsa_settable_ctx_params(ossl_unused void *vpeddsactx,896ossl_unused void *provctx)897{898return settable_ctx_params;899}900901static const OSSL_PARAM settable_variant_ctx_params[] = {902OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),903OSSL_PARAM_END904};905906static const OSSL_PARAM *907eddsa_settable_variant_ctx_params(ossl_unused void *vpeddsactx,908ossl_unused void *provctx)909{910return settable_variant_ctx_params;911}912913/*914* Ed25519 can be used with:915* - EVP_PKEY_sign_init_ex2() [ instance and prehash assumed done by caller ]916* - EVP_PKEY_verify_init_ex2() [ instance and prehash assumed done by caller ]917* - EVP_PKEY_sign_message_init()918* - EVP_PKEY_verify_message_init()919* - EVP_DigestSignInit_ex()920* - EVP_DigestVerifyInit_ex()921* Ed25519ph can be used with:922* - EVP_PKEY_sign_init_ex2() [ prehash assumed done by caller ]923* - EVP_PKEY_verify_init_ex2() [ prehash assumed done by caller ]924* - EVP_PKEY_sign_message_init()925* - EVP_PKEY_verify_message_init()926* Ed25519ctx can be used with:927* - EVP_PKEY_sign_message_init()928* - EVP_PKEY_verify_message_init()929* Ed448 can be used with:930* - EVP_PKEY_sign_init_ex2() [ instance and prehash assumed done by caller ]931* - EVP_PKEY_verify_init_ex2() [ instance and prehash assumed done by caller ]932* - EVP_PKEY_sign_message_init()933* - EVP_PKEY_verify_message_init()934* - EVP_DigestSignInit_ex()935* - EVP_DigestVerifyInit_ex()936* Ed448ph can be used with:937* - EVP_PKEY_sign_init_ex2() [ prehash assumed done by caller ]938* - EVP_PKEY_verify_init_ex2() [ prehash assumed done by caller ]939* - EVP_PKEY_sign_message_init()940* - EVP_PKEY_verify_message_init()941*/942943#define ed25519_DISPATCH_END \944{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \945(void (*)(void))ed25519_signverify_init }, \946{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \947(void (*)(void))ed25519_signverify_init }, \948{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \949(void (*)(void))ed25519_digest_signverify_init }, \950{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN, \951(void (*)(void))ed25519_digest_sign }, \952{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, \953(void (*)(void))ed25519_digest_signverify_init }, \954{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, \955(void (*)(void))ed25519_digest_verify }, \956{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \957(void (*)(void))eddsa_get_ctx_params }, \958{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \959(void (*)(void))eddsa_gettable_ctx_params }, \960{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \961(void (*)(void))eddsa_set_ctx_params }, \962{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \963(void (*)(void))eddsa_settable_ctx_params }, \964OSSL_DISPATCH_END965966#define eddsa_variant_DISPATCH_END(v) \967{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \968(void (*)(void))v##_signverify_message_init }, \969{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \970(void (*)(void))v##_signverify_message_init }, \971{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \972(void (*)(void))eddsa_get_ctx_params }, \973{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \974(void (*)(void))eddsa_gettable_ctx_params }, \975{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \976(void (*)(void))eddsa_set_ctx_params }, \977{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \978(void (*)(void))eddsa_settable_variant_ctx_params }, \979OSSL_DISPATCH_END980981#define ed25519ph_DISPATCH_END \982{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \983(void (*)(void))ed25519ph_signverify_init }, \984{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \985(void (*)(void))ed25519ph_signverify_init }, \986eddsa_variant_DISPATCH_END(ed25519ph)987988#define ed25519ctx_DISPATCH_END eddsa_variant_DISPATCH_END(ed25519ctx)989990#define ed448_DISPATCH_END \991{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \992(void (*)(void))ed448_signverify_init }, \993{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \994(void (*)(void))ed448_signverify_init }, \995{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, \996(void (*)(void))ed448_digest_signverify_init }, \997{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN, \998(void (*)(void))ed448_digest_sign }, \999{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, \1000(void (*)(void))ed448_digest_signverify_init }, \1001{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, \1002(void (*)(void))ed448_digest_verify }, \1003{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, \1004(void (*)(void))eddsa_get_ctx_params }, \1005{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, \1006(void (*)(void))eddsa_gettable_ctx_params }, \1007{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, \1008(void (*)(void))eddsa_set_ctx_params }, \1009{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, \1010(void (*)(void))eddsa_settable_ctx_params }, \1011OSSL_DISPATCH_END10121013#define ed448ph_DISPATCH_END \1014{ OSSL_FUNC_SIGNATURE_SIGN_INIT, \1015(void (*)(void))ed448ph_signverify_init }, \1016{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, \1017(void (*)(void))ed448ph_signverify_init }, \1018eddsa_variant_DISPATCH_END(ed448ph)10191020/* vn = variant name, bn = base name */1021#define IMPL_EDDSA_DISPATCH(vn,bn) \1022const OSSL_DISPATCH ossl_##vn##_signature_functions[] = { \1023{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx }, \1024{ OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT, \1025(void (*)(void))vn##_signverify_message_init }, \1026{ OSSL_FUNC_SIGNATURE_SIGN, \1027(void (*)(void))bn##_sign }, \1028{ OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT, \1029(void (*)(void))vn##_signverify_message_init }, \1030{ OSSL_FUNC_SIGNATURE_VERIFY, \1031(void (*)(void))bn##_verify }, \1032{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, \1033{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx }, \1034{ OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES, \1035(void (*)(void))bn##_sigalg_query_key_types }, \1036vn##_DISPATCH_END \1037}10381039IMPL_EDDSA_DISPATCH(ed25519,ed25519);1040IMPL_EDDSA_DISPATCH(ed25519ph,ed25519);1041IMPL_EDDSA_DISPATCH(ed25519ctx,ed25519);1042IMPL_EDDSA_DISPATCH(ed448,ed448);1043IMPL_EDDSA_DISPATCH(ed448ph,ed448);10441045#ifdef S390X_EC_ASM10461047static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,1048const unsigned char *tbs, size_t tbslen)1049{1050int rc;1051union {1052struct {1053unsigned char sig[64];1054unsigned char priv[32];1055} ed25519;1056unsigned long long buff[512];1057} param;10581059memset(¶m, 0, sizeof(param));1060memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));10611062rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen);1063OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));1064if (rc != 0)1065return 0;10661067s390x_flip_endian32(sig, param.ed25519.sig);1068s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);1069return 1;1070}10711072static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,1073const unsigned char *tbs, size_t tbslen)1074{1075int rc;1076union {1077struct {1078unsigned char sig[128];1079unsigned char priv[64];1080} ed448;1081unsigned long long buff[512];1082} param;10831084memset(¶m, 0, sizeof(param));1085memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);10861087rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen);1088OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));1089if (rc != 0)1090return 0;10911092s390x_flip_endian64(param.ed448.sig, param.ed448.sig);1093s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);1094memcpy(sig, param.ed448.sig, 57);1095memcpy(sig + 57, param.ed448.sig + 64, 57);1096return 1;1097}10981099static int s390x_ed25519_digestverify(const ECX_KEY *edkey,1100const unsigned char *sig,1101const unsigned char *tbs, size_t tbslen)1102{1103union {1104struct {1105unsigned char sig[64];1106unsigned char pub[32];1107} ed25519;1108unsigned long long buff[512];1109} param;11101111memset(¶m, 0, sizeof(param));1112s390x_flip_endian32(param.ed25519.sig, sig);1113s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);1114s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);11151116return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,1117¶m.ed25519, tbs, tbslen) == 0 ? 1 : 0;1118}11191120static int s390x_ed448_digestverify(const ECX_KEY *edkey,1121const unsigned char *sig,1122const unsigned char *tbs,1123size_t tbslen)1124{1125union {1126struct {1127unsigned char sig[128];1128unsigned char pub[64];1129} ed448;1130unsigned long long buff[512];1131} param;11321133memset(¶m, 0, sizeof(param));1134memcpy(param.ed448.sig, sig, 57);1135s390x_flip_endian64(param.ed448.sig, param.ed448.sig);1136memcpy(param.ed448.sig + 64, sig + 57, 57);1137s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);1138memcpy(param.ed448.pub, edkey->pubkey, 57);1139s390x_flip_endian64(param.ed448.pub, param.ed448.pub);11401141return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,1142¶m.ed448, tbs, tbslen) == 0 ? 1 : 0;1143}11441145#endif /* S390X_EC_ASM */114611471148