The branch master has been updated via d62be1580bf402f7088cdec5f21a87f27f40f18e (commit) via 3965480c824c9823db7803cc1a403be863cecc00 (commit) via eea1e780a1c2c6952af7b9e00129f5aaefb7207e (commit) via af6d8dd30ff48046f5af7d84095f30356c33264a (commit) from db4b3d8392fc1c3a1033045efdda222fd76c26b2 (commit)
- Log ----------------------------------------------------------------- commit d62be1580bf402f7088cdec5f21a87f27f40f18e Author: Matt Caswell <m...@openssl.org> Date: Thu Mar 5 17:16:04 2020 +0000 Document the new DigestSign provider functions As well as the newly added "one shot" functions, we also document a number of the other other digestsign functions which were missing documentation in provider-signature.pod. Reviewed-by: Shane Lontis <shane.lon...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11261) commit 3965480c824c9823db7803cc1a403be863cecc00 Author: Matt Caswell <m...@openssl.org> Date: Thu Mar 5 15:42:13 2020 +0000 Implement provider support for Ed25519 annd Ed448 At the moment we only provider support for these algorithms in the default provider. These algorithms only support "one shot" EVP_DigestSign() and EVP_DigestVerify() as per the existing libcrypto versions. Reviewed-by: Shane Lontis <shane.lon...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11261) commit eea1e780a1c2c6952af7b9e00129f5aaefb7207e Author: Matt Caswell <m...@openssl.org> Date: Thu Mar 5 15:40:48 2020 +0000 Add provider awareness of EVP_DigestSign() and EVP_DigestVerify() These "one-shot" functions are the only ones supported by Ed25519 and Ed448, so we need to ensure that libcrypto can handle provider based implementations of these functions. Reviewed-by: Shane Lontis <shane.lon...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11261) commit af6d8dd30ff48046f5af7d84095f30356c33264a Author: Matt Caswell <m...@openssl.org> Date: Mon Feb 17 16:37:24 2020 +0000 Add Key Management support for EdDSA keys Support added for Ed25519 and Ed448 Reviewed-by: Shane Lontis <shane.lon...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11261) ----------------------------------------------------------------------- Summary of changes: crypto/ec/curve448/curve448_local.h | 9 - crypto/ec/curve448/eddsa.c | 1 + crypto/ec/ec_local.h | 4 - crypto/ec/ecx_meth.c | 4 + crypto/err/openssl.txt | 1 + crypto/evp/evp_local.h | 2 + crypto/evp/m_sigver.c | 62 +++++- crypto/evp/signature.c | 32 +++- doc/man7/provider-signature.pod | 166 +++++++++++++++- include/crypto/ecx.h | 41 ++-- include/openssl/core_numbers.h | 34 ++-- providers/common/include/prov/providercommonerr.h | 1 + providers/common/provider_err.c | 1 + providers/defltprov.c | 6 + .../implementations/include/prov/implementations.h | 4 + providers/implementations/keymgmt/ecx_kmgmt.c | 67 ++++--- providers/implementations/signature/build.info | 5 + providers/implementations/signature/eddsa.c | 211 +++++++++++++++++++++ 18 files changed, 571 insertions(+), 80 deletions(-) create mode 100644 providers/implementations/signature/eddsa.c diff --git a/crypto/ec/curve448/curve448_local.h b/crypto/ec/curve448/curve448_local.h index 36f960ec0e..b70a1b5406 100644 --- a/crypto/ec/curve448/curve448_local.h +++ b/crypto/ec/curve448/curve448_local.h @@ -10,15 +10,6 @@ # define OSSL_CRYPTO_EC_CURVE448_LOCAL_H # include "curve448utils.h" -int ED448_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t *message, - size_t message_len, const uint8_t public_key[57], - const uint8_t private_key[57], const uint8_t *context, - size_t context_len); - -int ED448_verify(OPENSSL_CTX *ctx, const uint8_t *message, size_t message_len, - const uint8_t signature[114], const uint8_t public_key[57], - const uint8_t *context, size_t context_len); - int ED448ph_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64], const uint8_t public_key[57], const uint8_t private_key[57], const uint8_t *context, size_t context_len); diff --git a/crypto/ec/curve448/eddsa.c b/crypto/ec/curve448/eddsa.c index b5762cb584..1cd76844d9 100644 --- a/crypto/ec/curve448/eddsa.c +++ b/crypto/ec/curve448/eddsa.c @@ -12,6 +12,7 @@ #include <string.h> #include <openssl/crypto.h> #include <openssl/evp.h> +#include "crypto/ecx.h" #include "curve448_local.h" #include "word.h" #include "ed448.h" diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h index dacb2ca0af..b5963a7e5f 100644 --- a/crypto/ec/ec_local.h +++ b/crypto/ec/ec_local.h @@ -679,10 +679,6 @@ ECDSA_SIG *ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, int ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); -int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, - const uint8_t public_key[32], const uint8_t private_key[32]); -int ED25519_verify(const uint8_t *message, size_t message_len, - const uint8_t signature[64], const uint8_t public_key[32]); void ED25519_public_from_private(uint8_t out_public_key[32], const uint8_t private_key[32]); diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c index 32817562bf..f107df3aa4 100644 --- a/crypto/ec/ecx_meth.c +++ b/crypto/ec/ecx_meth.c @@ -648,6 +648,8 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { ecx_set_pub_key, ecx_get_priv_key, ecx_get_pub_key, + ecx_pkey_dirty_cnt, + ecx_pkey_export_to }; const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = { @@ -690,6 +692,8 @@ const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = { ecx_set_pub_key, ecx_get_priv_key, ecx_get_pub_key, + ecx_pkey_dirty_cnt, + ecx_pkey_export_to }; static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index f14acc65b6..8689e34925 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2773,6 +2773,7 @@ PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter +PROV_R_FAILED_TO_SIGN:175:failed to sign PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\ illegal or unsupported padding mode PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 774db4da8f..858f1c49d6 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -129,9 +129,11 @@ struct evp_signature_st { OSSL_OP_signature_digest_sign_init_fn *digest_sign_init; OSSL_OP_signature_digest_sign_update_fn *digest_sign_update; OSSL_OP_signature_digest_sign_final_fn *digest_sign_final; + OSSL_OP_signature_digest_sign_fn *digest_sign; OSSL_OP_signature_digest_verify_init_fn *digest_verify_init; OSSL_OP_signature_digest_verify_update_fn *digest_verify_update; OSSL_OP_signature_digest_verify_final_fn *digest_verify_final; + OSSL_OP_signature_digest_verify_fn *digest_verify; OSSL_OP_signature_freectx_fn *freectx; OSSL_OP_signature_dupctx_fn *dupctx; OSSL_OP_signature_get_ctx_params_fn *get_ctx_params; diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index b6c66722ec..225017b509 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -24,6 +24,18 @@ static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen) return 0; } +/* + * If we get the "NULL" md then the name comes back as "UNDEF". We want to use + * NULL for this. + */ +static const char *canon_mdname(const char *mdname) +{ + if (mdname != NULL && strcmp(mdname, "UNDEF") == 0) + return NULL; + + return mdname; +} + static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, const char *mdname, const char *props, ENGINE *e, EVP_PKEY *pkey, @@ -134,12 +146,12 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, if (type != NULL) { ctx->reqdigest = type; if (mdname == NULL) - mdname = EVP_MD_name(type); + mdname = canon_mdname(EVP_MD_name(type)); } else { if (mdname == NULL && EVP_PKEY_get_default_digest_name(locpctx->pkey, locmdname, sizeof(locmdname))) - mdname = locmdname; + mdname = canon_mdname(locmdname); if (mdname != NULL) { /* @@ -280,6 +292,11 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) || pctx->op.sig.signature == NULL) goto legacy; + if (pctx->op.sig.signature->digest_sign_update == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return pctx->op.sig.signature->digest_sign_update(pctx->op.sig.sigprovctx, data, dsize); @@ -297,6 +314,11 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) || pctx->op.sig.signature == NULL) goto legacy; + if (pctx->op.sig.signature->digest_verify_update == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + return pctx->op.sig.signature->digest_verify_update(pctx->op.sig.sigprovctx, data, dsize); @@ -391,8 +413,22 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, const unsigned char *tbs, size_t tbslen) { - if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL) - return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); + EVP_PKEY_CTX *pctx = ctx->pctx; + + if (pctx != NULL + && pctx->operation == EVP_PKEY_OP_SIGNCTX + && pctx->op.sig.sigprovctx != NULL + && pctx->op.sig.signature != NULL) { + if (pctx->op.sig.signature->digest_sign != NULL) + return pctx->op.sig.signature->digest_sign(pctx->op.sig.sigprovctx, + sigret, siglen, SIZE_MAX, + tbs, tbslen); + } else { + /* legacy */ + if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL) + return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); + } + if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0) return 0; return EVP_DigestSignFinal(ctx, sigret, siglen); @@ -454,8 +490,22 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen, const unsigned char *tbs, size_t tbslen) { - if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL) - return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); + EVP_PKEY_CTX *pctx = ctx->pctx; + + if (pctx != NULL + && pctx->operation == EVP_PKEY_OP_VERIFYCTX + && pctx->op.sig.sigprovctx != NULL + && pctx->op.sig.signature != NULL) { + if (pctx->op.sig.signature->digest_verify != NULL) + return pctx->op.sig.signature->digest_verify(pctx->op.sig.sigprovctx, + sigret, siglen, + tbs, tbslen); + } else { + /* legacy */ + if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL) + return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); + } + if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) return -1; return EVP_DigestVerifyFinal(ctx, sigret, siglen); diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index 3dfd4041e7..c01f076609 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -105,7 +105,6 @@ static void *evp_signature_from_dispatch(int name_id, break; signature->digest_sign_init = OSSL_get_OP_signature_digest_sign_init(fns); - digsignfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE: if (signature->digest_sign_update != NULL) @@ -121,12 +120,17 @@ static void *evp_signature_from_dispatch(int name_id, = OSSL_get_OP_signature_digest_sign_final(fns); digsignfncnt++; break; + case OSSL_FUNC_SIGNATURE_DIGEST_SIGN: + if (signature->digest_sign != NULL) + break; + signature->digest_sign + = OSSL_get_OP_signature_digest_sign(fns); + break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT: if (signature->digest_verify_init != NULL) break; signature->digest_verify_init = OSSL_get_OP_signature_digest_verify_init(fns); - digverifyfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE: if (signature->digest_verify_update != NULL) @@ -142,6 +146,12 @@ static void *evp_signature_from_dispatch(int name_id, = OSSL_get_OP_signature_digest_verify_final(fns); digverifyfncnt++; break; + case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY: + if (signature->digest_verify != NULL) + break; + signature->digest_verify + = OSSL_get_OP_signature_digest_verify(fns); + break; case OSSL_FUNC_SIGNATURE_FREECTX: if (signature->freectx != NULL) break; @@ -216,12 +226,20 @@ static void *evp_signature_from_dispatch(int name_id, && verifyfncnt == 0 && verifyrecfncnt == 0 && digsignfncnt == 0 - && digverifyfncnt == 0) + && digverifyfncnt == 0 + && signature->digest_sign == NULL + && signature->digest_verify == NULL) || (signfncnt != 0 && signfncnt != 2) || (verifyfncnt != 0 && verifyfncnt != 2) || (verifyrecfncnt != 0 && verifyrecfncnt != 2) - || (digsignfncnt != 0 && digsignfncnt != 3) - || (digverifyfncnt != 0 && digverifyfncnt != 3) + || (digsignfncnt != 0 && digsignfncnt != 2) + || (digsignfncnt == 2 && signature->digest_sign_init == NULL) + || (digverifyfncnt != 0 && digverifyfncnt != 2) + || (digverifyfncnt == 2 && signature->digest_verify_init == NULL) + || (signature->digest_sign != NULL + && signature->digest_sign_init == NULL) + || (signature->digest_verify != NULL + && signature->digest_verify_init == NULL) || (gparamfncnt != 0 && gparamfncnt != 2) || (sparamfncnt != 0 && sparamfncnt != 2) || (gmdparamfncnt != 0 && gmdparamfncnt != 2) @@ -234,7 +252,9 @@ static void *evp_signature_from_dispatch(int name_id, * (verify_init verify) or * (verify_recover_init, verify_recover) or * (digest_sign_init, digest_sign_update, digest_sign_final) or - * (digest_verify_init, digest_verify_update, digest_verify_final). + * (digest_verify_init, digest_verify_update, digest_verify_final) or + * (digest_sign_init, digest_sign) or + * (digest_verify_init, digest_verify). * * set_ctx_params and settable_ctx_params are optional, but if one of * them is present then the other one must also be present. The same diff --git a/doc/man7/provider-signature.pod b/doc/man7/provider-signature.pod index d5f0c396c1..771c55f6f5 100644 --- a/doc/man7/provider-signature.pod +++ b/doc/man7/provider-signature.pod @@ -38,12 +38,40 @@ provider-signature - The signature library E<lt>-E<gt> provider functions size_t *routlen, size_t routsize, const unsigned char *sig, size_t siglen); + /* Digest Sign */ + int OP_signature_digest_sign_init(void *ctx, const char *mdname, + const char *props, void *provkey); + int OP_signature_digest_sign_update(void *ctx, const unsigned char *data, + size_t datalen); + int OP_signature_digest_sign_final(void *ctx, unsigned char *sig, + size_t *siglen, size_t sigsize); + int OP_signature_digest_sign(void *ctx, unsigned char *sigret, size_t *siglen, + size_t sigsize, const unsigned char *tbs, + size_t tbslen); + + /* Digest Verify */ + int OP_signature_digest_verify_init(void *ctx, const char *mdname, + const char *props, void *provkey); + int OP_signature_digest_verify_update(void *ctx, const unsigned char *data, + size_t datalen); + int OP_signature_digest_verify_final(void *ctx, const unsigned char *sig, + size_t siglen); + int OP_signature_digest_verify(void *ctx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen); + /* Signature parameters */ int OP_signature_get_ctx_params(void *ctx, OSSL_PARAM params[]); const OSSL_PARAM *OP_signature_gettable_ctx_params(void); int OP_signature_set_ctx_params(void *ctx, const OSSL_PARAM params[]); const OSSL_PARAM *OP_signature_settable_ctx_params(void); + /* MD parameters */ + int OP_signature_get_ctx_md_params(void *ctx, OSSL_PARAM params[]); + const OSSL_PARAM * OP_signature_gettable_ctx_md_params(void *ctx); + int OP_signature_set_ctx_md_params(void *ctx, const OSSL_PARAM params[]); + const OSSL_PARAM * OP_signature_settable_ctx_md_params(void *ctx); + =head1 DESCRIPTION This documentation is primarily aimed at provider authors. See L<provider(7)> @@ -88,18 +116,53 @@ macros in L<openssl-core_numbers.h(7)>, as follows: OP_signature_verify_recover_init OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT OP_signature_verify_recover OSSL_FUNC_SIGNATURE_VERIFY_RECOVER + OP_signature_digest_sign_init OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT + OP_signature_digest_sign_update OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE + OP_signature_digest_sign_final OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL + OP_signature_digest_sign OSSL_FUNC_SIGNATURE_DIGEST_SIGN + + OP_signature_digest_verify_init OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT + OP_signature_digest_verify_update OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE + OP_signature_digest_verify_final OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL + OP_signature_digest_verify OSSL_FUNC_SIGNATURE_DIGEST_VERIFY + OP_signature_get_ctx_params OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS OP_signature_gettable_ctx_params OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS OP_signature_set_ctx_params OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS OP_signature_settable_ctx_params OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS + OP_signature_get_ctx_md_params OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS + OP_signature_gettable_ctx_md_params OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS + OP_signature_set_ctx_md_params OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS + OP_signature_settable_ctx_md_params OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS + A signature algorithm implementation may not implement all of these functions. -In order to be a consistent set of functions a provider must implement -OP_signature_newctx and OP_signature_freectx. -It must also implement both of OP_signature_sign_init and OP_signature_sign, -or both of OP_signature_verify_init and OP_signature_verify, or both of -OP_signature_verify_recover_init and OP_signature_verify_recover. -All other functions are optional. +In order to be a consistent set of functions we must have at least a set of +context functions (OP_signature_newctx and OP_signature_freectx) as well as a +set of "signature" functions, i.e. at least one of: + +=over 4 + +=item OP_signature_sign_init and OP_signature_sign + +=item OP_signature_verify_init and OP_signature_verify + +=item OP_signature_verify_recover_init and OP_signature_verify_init + +=item OP_signature_digest_sign_init, OP_signature_digest_sign_update and OP_signature_digest_sign_final + +=item OP_signature_digest_verify_init, OP_signature_digest_verify_update and OP_signature_digest_verify_final + +=item OP_signature_digest_sign_init and OP_signature_digest_sign + +=item OP_signature_digest_verify_init and OP_signature_digest_verify + +=back + +OP_signature_set_ctx_params and OP_signature_settable_ctx_params are optional, +but if one of them is present then the other one must also be present. The same +applies to OP_signature_get_ctx_params and OP_signature_gettable_ctx_params, as +well as the "md_params" functions. The OP_signature_dupctx function is optional. A signature algorithm must also implement some mechanism for generating, loading or importing keys via the key management (OSSL_OP_KEYMGMT) operation. @@ -176,6 +239,70 @@ The length of the recovered data should be written to I<*routlen>. If I<rout> is NULL then the maximum size of the output buffer is written to the I<routlen> parameter. +=head2 Digest Sign Functions + +OP_signature_digeset_sign_init() initialises a context for signing given a +provider side signature context in the I<ctx> parameter, and a pointer to a +provider key object in the I<provkey> parameter. The key object should have been +previously generated, loaded or imported into the provider using the +key management (OSSL_OP_KEYMGMT) operation (see provider-keymgmt(7)>. +The name of the digest to be used will be in the I<mdname> parameter. There may +also be properties to be used in fetching the digest in the I<props> parameter, +although this may be ignored by providers. + +OP_signature_digest_sign_update() provides data to be signed in the I<data> +parameter which should be of length I<datalen>. A previously initialised +signature context is passed in the I<ctx> parameter. This function may be called +multiple times to cummulatively add data to be signed. + +OP_signature_digest_sign_final() finalises a signature operation previously +started through OP_signature_digest_sign_init() and +OP_signature_digest_sign_update() calls. Once finalised no more data will be +added through OP_signature_digest_sign_update(). A previously initialised +signature context is passed in the I<ctx> parameter. Unless I<sig> is NULL, the +signature should be written to the location pointed to by the I<sig> parameter +and it should not exceed I<sigsize> bytes in length. The length of the signature +should be written to I<*siglen>. If I<sig> is NULL then the maximum length of +the signature should be written to I<*siglen>. + +OP_signature_digest_sign() implements a "one shot" digest sign operation +previously started through OP_signature_digeset_sign_init(). A previously +initialised signature context is passed in the I<ctx> parameter. The data to be +signed is in I<tbs> which should be I<tbslen> bytes long. Unless I<sig> is NULL, +the signature should be written to the location pointed to by the I<sig> +parameter and it should not exceed I<sigsize> bytes in length. The length of the +signature should be written to I<*siglen>. If I<sig> is NULL then the maximum +length of the signature should be written to I<*siglen>. + +=head2 Digest Verify Functions + +OP_signature_digeset_verify_init() initialises a context for verifying given a +provider side verification context in the I<ctx> parameter, and a pointer to a +provider key object in the I<provkey> parameter. The key object should have been +previously generated, loaded or imported into the provider using the +key management (OSSL_OP_KEYMGMT) operation (see provider-keymgmt(7)>. +The name of the digest to be used will be in the I<mdname> parameter. There may +also be properties to be used in fetching the digest in the I<props> parameter, +although this may be ignored by providers. + +OP_signature_digest_verify_update() provides data to be verified in the I<data> +parameter which should be of length I<datalen>. A previously initialised +verification context is passed in the I<ctx> parameter. This function may be +called multiple times to cummulatively add data to be verified. + +OP_signature_digest_verify_final() finalises a verification operation previously +started through OP_signature_digest_verify_init() and +OP_signature_digest_verify_update() calls. Once finalised no more data will be +added through OP_signature_digest_verify_update(). A previously initialised +verification context is passed in the I<ctx> parameter. The signature to be +verified is in I<sig> which is I<siglen> bytes long. + +OP_signature_digest_verify() implements a "one shot" digest verify operation +previously started through OP_signature_digeset_verify_init(). A previously +initialised verification context is passed in the I<ctx> parameter. The data to be +verified is in I<tbs> which should be I<tbslen> bytes long. The signature to be +verified is in I<sig> which is I<siglen> bytes long. + =head2 Signature Parameters See L<OSSL_PARAM(3)> for further details on the parameters structure used by @@ -214,11 +341,38 @@ i.e. parameters that can be used with OP_signature_get_ctx_params() and OP_signature_set_ctx_params() respectively. See L<OSSL_PARAM(3)> for the use of B<OSSL_PARAM> as parameter descriptor. +=head2 MD Parameters + +See L<OSSL_PARAM(3)> for further details on the parameters structure used by +the OP_signature_get_md_ctx_params() and OP_signature_set_md_ctx_params() +functions. + +OP_signature_get_md_ctx_params() gets digest parameters associated with the +given provider side digest signature context I<ctx> and stores them in I<params>. +OP_signature_set_ms_ctx_params() sets the digest parameters associated with the +given provider side digest signature context I<ctx> to I<params>. +Any parameter settings are additional to any that were previously set. + +Parameters currently recognised by built-in signature algorithms are the same +as those for built-in digest algorithms. See +L<provider-digest(7)/Digest Parameters> for further information. + +OP_signature_gettable_md_ctx_params() and OP_signature_settable_md_ctx_params() +get a constant B<OSSL_PARAM> array that describes the gettable and settable +digest parameters, i.e. parameters that can be used with +OP_signature_get_md_ctx_params() and OP_signature_set_md_ctx_params() +respectively. See L<OSSL_PARAM(3)> for the use of B<OSSL_PARAM> as parameter +descriptor. + =head1 RETURN VALUES OP_signature_newctx() and OP_signature_dupctx() should return the newly created provider side signature, or NULL on failure. +OP_signature_gettable_ctx_params(), OP_signature_settable_ctx_params(), +OP_signature_gettable_md_ctx_params() and OP_signature_settable_md_ctx_params(), +return the gettable or settable parameters in a constant B<OSSL_PARAM> array. + All other functions should return 1 for success or 0 on error. =head1 SEE ALSO diff --git a/include/crypto/ecx.h b/include/crypto/ecx.h index e179db1b53..3e494bf092 100644 --- a/include/crypto/ecx.h +++ b/include/crypto/ecx.h @@ -19,23 +19,28 @@ # include <openssl/crypto.h> # include "internal/refcount.h" -# define X25519_KEYLEN 32 -# define X448_KEYLEN 56 -# define ED25519_KEYLEN 32 -# define ED448_KEYLEN 57 +# define X25519_KEYLEN 32 +# define X448_KEYLEN 56 +# define ED25519_KEYLEN 32 +# define ED448_KEYLEN 57 # define MAX_KEYLEN ED448_KEYLEN -# define X25519_BITS 253 -# define X25519_SECURITY_BITS 128 +# define X25519_BITS 253 +# define X25519_SECURITY_BITS 128 -# define ED25519_SIGSIZE 64 +# define X448_BITS 448 +# define X448_SECURITY_BITS 224 -# define X448_BITS 448 -# define ED448_BITS 456 -# define X448_SECURITY_BITS 224 +# define ED25519_BITS 256 +/* RFC8032 Section 8.5 */ +# define ED25519_SECURITY_BITS 128 +# define ED25519_SIGSIZE 64 -# define ED448_SIGSIZE 114 +# define ED448_BITS 456 +/* RFC8032 Section 8.5 */ +# define ED448_SECURITY_BITS 224 +# define ED448_SIGSIZE 114 struct ecx_key_st { unsigned int haspubkey:1; @@ -58,6 +63,20 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], void X25519_public_from_private(uint8_t out_public_value[32], const uint8_t private_key[32]); +int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, + const uint8_t public_key[32], const uint8_t private_key[32]); +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[64], const uint8_t public_key[32]); + +int ED448_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t *message, + size_t message_len, const uint8_t public_key[57], + const uint8_t private_key[57], const uint8_t *context, + size_t context_len); + +int ED448_verify(OPENSSL_CTX *ctx, const uint8_t *message, size_t message_len, + const uint8_t signature[114], const uint8_t public_key[57], + const uint8_t *context, size_t context_len); + int X448(uint8_t out_shared_key[56], const uint8_t private_key[56], const uint8_t peer_public_value[56]); void X448_public_from_private(uint8_t out_public_value[56], diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h index 3314a0f665..c65041894a 100644 --- a/include/openssl/core_numbers.h +++ b/include/openssl/core_numbers.h @@ -480,19 +480,21 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, OP_keyexch_gettable_ctx_params, # define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT 8 # define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE 9 # define OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL 10 -# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT 11 -# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE 12 -# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL 13 -# define OSSL_FUNC_SIGNATURE_FREECTX 14 -# define OSSL_FUNC_SIGNATURE_DUPCTX 15 -# define OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS 16 -# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS 17 -# define OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS 18 -# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS 19 -# define OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS 20 -# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS 21 -# define OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS 22 -# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS 23 +# define OSSL_FUNC_SIGNATURE_DIGEST_SIGN 11 +# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT 12 +# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE 13 +# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL 14 +# define OSSL_FUNC_SIGNATURE_DIGEST_VERIFY 15 +# define OSSL_FUNC_SIGNATURE_FREECTX 16 +# define OSSL_FUNC_SIGNATURE_DUPCTX 17 +# define OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS 18 +# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS 19 +# define OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS 20 +# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS 21 +# define OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS 22 +# define OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS 23 +# define OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS 24 +# define OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS 25 OSSL_CORE_MAKE_FUNC(void *, OP_signature_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(int, OP_signature_sign_init, (void *ctx, void *provkey)) @@ -522,6 +524,9 @@ OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_sign_update, OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_sign_final, (void *ctx, unsigned char *sig, size_t *siglen, size_t sigsize)) +OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_sign, + (void *ctx, unsigned char *sigret, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen)) OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_verify_init, (void *ctx, const char *mdname, const char *props, void *provkey)) @@ -529,6 +534,9 @@ OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_verify_update, (void *ctx, const unsigned char *data, size_t datalen)) OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_verify_final, (void *ctx, const unsigned char *sig, size_t siglen)) +OSSL_CORE_MAKE_FUNC(int, OP_signature_digest_verify, + (void *ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen)) OSSL_CORE_MAKE_FUNC(void, OP_signature_freectx, (void *ctx)) OSSL_CORE_MAKE_FUNC(void *, OP_signature_dupctx, (void *ctx)) OSSL_CORE_MAKE_FUNC(int, OP_signature_get_ctx_params, diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h index 19ecab1f0f..f834a71347 100644 --- a/providers/common/include/prov/providercommonerr.h +++ b/providers/common/include/prov/providercommonerr.h @@ -64,6 +64,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_FAILED_TO_GENERATE_KEY 121 # define PROV_R_FAILED_TO_GET_PARAMETER 103 # define PROV_R_FAILED_TO_SET_PARAMETER 104 +# define PROV_R_FAILED_TO_SIGN 175 # define PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 165 # define PROV_R_INAVLID_UKM_LENGTH 146 # define PROV_R_INVALID_AAD 108 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index f73f82351f..1a65e2cc87 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -39,6 +39,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "failed to get parameter"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER), "failed to set parameter"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SIGN), "failed to sign"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), "illegal or unsupported padding mode"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INAVLID_UKM_LENGTH), diff --git a/providers/defltprov.c b/providers/defltprov.c index 0f66aa2b71..7bb23e300e 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -385,6 +385,10 @@ static const OSSL_ALGORITHM deflt_signature[] = { { "DSA:dsaEncryption", "provider=default", dsa_signature_functions }, #endif { "RSA:rsaEncryption", "provider=default", rsa_signature_functions }, +#ifndef OPENSSL_NO_EC + { "ED25519:Ed25519", "provider=default", ed25519_signature_functions }, + { "ED448:Ed448", "provider=default", ed448_signature_functions }, +#endif { NULL, NULL, NULL } }; @@ -405,6 +409,8 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = { { "EC:id-ecPublicKey", "provider=default", ec_keymgmt_functions }, { "X25519", "provider=default", x25519_keymgmt_functions }, { "X448", "provider=default", x448_keymgmt_functions }, + { "ED25519", "provider=default", ed25519_keymgmt_functions }, + { "ED448", "provider=default", ed448_keymgmt_functions }, #endif { NULL, NULL, NULL } }; diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index ea33bedfd8..94265adfc2 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -259,6 +259,8 @@ extern const OSSL_DISPATCH dsa_keymgmt_functions[]; extern const OSSL_DISPATCH rsa_keymgmt_functions[]; extern const OSSL_DISPATCH x25519_keymgmt_functions[]; extern const OSSL_DISPATCH x448_keymgmt_functions[]; +extern const OSSL_DISPATCH ed25519_keymgmt_functions[]; +extern const OSSL_DISPATCH ed448_keymgmt_functions[]; extern const OSSL_DISPATCH ec_keymgmt_functions[]; /* Key Exchange */ @@ -270,6 +272,8 @@ extern const OSSL_DISPATCH ecdh_keyexch_functions[]; /* Signature */ extern const OSSL_DISPATCH dsa_signature_functions[]; extern const OSSL_DISPATCH rsa_signature_functions[]; +extern const OSSL_DISPATCH ed25519_signature_functions[]; +extern const OSSL_DISPATCH ed448_signature_functions[]; /* Asym Cipher */ extern const OSSL_DISPATCH rsa_asym_cipher_functions[]; diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index d3aa9ba1f9..b078c6de58 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -18,8 +18,12 @@ static OSSL_OP_keymgmt_new_fn x25519_new_key; static OSSL_OP_keymgmt_new_fn x448_new_key; +static OSSL_OP_keymgmt_new_fn ed25519_new_key; +static OSSL_OP_keymgmt_new_fn ed448_new_key; static OSSL_OP_keymgmt_get_params_fn x25519_get_params; static OSSL_OP_keymgmt_get_params_fn x448_get_params; +static OSSL_OP_keymgmt_get_params_fn ed25519_get_params; +static OSSL_OP_keymgmt_get_params_fn ed448_get_params; static OSSL_OP_keymgmt_gettable_params_fn ecx_gettable_params; static OSSL_OP_keymgmt_has_fn ecx_has; static OSSL_OP_keymgmt_import_fn ecx_import; @@ -39,6 +43,16 @@ static void *x448_new_key(void *provctx) return ecx_key_new(X448_KEYLEN, 0); } +static void *ed25519_new_key(void *provctx) +{ + return ecx_key_new(ED25519_KEYLEN, 0); +} + +static void *ed448_new_key(void *provctx) +{ + return ecx_key_new(ED448_KEYLEN, 0); +} + static int ecx_has(void *keydata, int selection) { ECX_KEY *key = keydata; @@ -186,6 +200,16 @@ static int x448_get_params(void *key, OSSL_PARAM params[]) return ecx_get_params(params, X448_BITS, X448_SECURITY_BITS, X448_KEYLEN); } +static int ed25519_get_params(void *key, OSSL_PARAM params[]) +{ + return ecx_get_params(params, ED25519_BITS, ED25519_SECURITY_BITS, ED25519_KEYLEN); +} + +static int ed448_get_params(void *key, OSSL_PARAM params[]) +{ + return ecx_get_params(params, ED448_BITS, ED448_SECURITY_BITS, ED448_KEYLEN); +} + static const OSSL_PARAM ecx_params[] = { OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), @@ -198,28 +222,21 @@ static const OSSL_PARAM *ecx_gettable_params(void) return ecx_params; } -const OSSL_DISPATCH x25519_keymgmt_functions[] = { - { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))x25519_new_key }, - { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, - { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))x25519_get_params }, - { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ecx_gettable_params }, - { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, - { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, - { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, - { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, - { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, - { 0, NULL } -}; - -const OSSL_DISPATCH x448_keymgmt_functions[] = { - { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))x448_new_key }, - { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, - { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))x448_get_params }, - { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ecx_gettable_params }, - { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, - { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, - { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, - { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, - { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, - { 0, NULL } -}; +#define MAKE_KEYMGMT_FUNCTIONS(alg) \ + const OSSL_DISPATCH alg##_keymgmt_functions[] = { \ + { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \ + { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \ + { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \ + { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ecx_gettable_params }, \ + { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \ + { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \ + { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \ + { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \ + { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \ + { 0, NULL } \ + }; + +MAKE_KEYMGMT_FUNCTIONS(x25519) +MAKE_KEYMGMT_FUNCTIONS(x448) +MAKE_KEYMGMT_FUNCTIONS(ed25519) +MAKE_KEYMGMT_FUNCTIONS(ed448) diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info index 22b55dcf54..c5d0645a8a 100644 --- a/providers/implementations/signature/build.info +++ b/providers/implementations/signature/build.info @@ -3,11 +3,16 @@ $DSA_GOAL=../../libimplementations.a $RSA_GOAL=../../libimplementations.a +$EC_GOAL=../../libimplementations.a IF[{- !$disabled{dsa} -}] SOURCE[$DSA_GOAL]=dsa.c ENDIF +IF[{- !$disabled{ec} -}] + SOURCE[$EC_GOAL]=eddsa.c +ENDIF + SOURCE[$RSA_GOAL]=rsa.c diff --git a/providers/implementations/signature/eddsa.c b/providers/implementations/signature/eddsa.c new file mode 100644 index 0000000000..d2444f9e36 --- /dev/null +++ b/providers/implementations/signature/eddsa.c @@ -0,0 +1,211 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/crypto.h> +#include <openssl/core_numbers.h> +#include <openssl/core_names.h> +#include <openssl/err.h> +#include <openssl/params.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include "internal/nelem.h" +#include "internal/sizes.h" +#include "prov/providercommonerr.h" +#include "prov/implementations.h" +#include "prov/providercommonerr.h" +#include "prov/provider_ctx.h" +#include "crypto/ecx.h" + +static OSSL_OP_signature_newctx_fn eddsa_newctx; +static OSSL_OP_signature_digest_sign_init_fn eddsa_digest_signverify_init; +static OSSL_OP_signature_digest_sign_fn ed25519_digest_sign; +static OSSL_OP_signature_digest_sign_fn ed448_digest_sign; +static OSSL_OP_signature_digest_verify_fn ed25519_digest_verify; +static OSSL_OP_signature_digest_verify_fn ed448_digest_verify; +static OSSL_OP_signature_freectx_fn eddsa_freectx; +static OSSL_OP_signature_dupctx_fn eddsa_dupctx; + +typedef struct { + OPENSSL_CTX *libctx; + ECX_KEY *key; +} PROV_EDDSA_CTX; + +static void *eddsa_newctx(void *provctx) +{ + PROV_EDDSA_CTX *peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX)); + + if (peddsactx == NULL) { + PROVerr(0, ERR_R_MALLOC_FAILURE); + return NULL; + } + + peddsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); + + return peddsactx; +} + +static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname, + const char *props, void *vedkey) +{ + PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; + ECX_KEY *edkey = (ECX_KEY *)vedkey; + + if (mdname != NULL) { + PROVerr(0, PROV_R_INVALID_DIGEST); + return 0; + } + + if (!ecx_key_up_ref(edkey)) { + PROVerr(0, ERR_R_INTERNAL_ERROR); + return 0; + } + + peddsactx->key = edkey; + + return 1; +} + +int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret, + size_t *siglen, size_t sigsize, + const unsigned char *tbs, size_t tbslen) +{ + PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; + const ECX_KEY *edkey = peddsactx->key; + + if (sigret == NULL) { + *siglen = ED25519_SIGSIZE; + return 1; + } + if (sigsize < ED25519_SIGSIZE) { + PROVerr(0, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (ED25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0) { + PROVerr(0, PROV_R_FAILED_TO_SIGN); + return 0; + } + *siglen = ED25519_SIGSIZE; + return 1; +} + +int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret, + size_t *siglen, size_t sigsize, + const unsigned char *tbs, size_t tbslen) +{ + PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; + const ECX_KEY *edkey = peddsactx->key; + + if (sigret == NULL) { + *siglen = ED448_SIGSIZE; + return 1; + } + if (sigsize < ED448_SIGSIZE) { + PROVerr(0, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (ED448_sign(peddsactx->libctx, sigret, tbs, tbslen, edkey->pubkey, + edkey->privkey, NULL, 0) == 0) { + PROVerr(0, PROV_R_FAILED_TO_SIGN); + return 0; + } + *siglen = ED448_SIGSIZE; + return 1; +} + +int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen) +{ + PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; + const ECX_KEY *edkey = peddsactx->key; + + if (siglen != ED25519_SIGSIZE) + return 0; + + return ED25519_verify(tbs, tbslen, sig, edkey->pubkey); +} + +int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig, + size_t siglen, const unsigned char *tbs, + size_t tbslen) +{ + PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; + const ECX_KEY *edkey = peddsactx->key; + + if (siglen != ED448_SIGSIZE) + return 0; + + return ED448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey, + NULL, 0); +} + +static void eddsa_freectx(void *vpeddsactx) +{ + PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; + + ecx_key_free(peddsactx->key); + + OPENSSL_free(peddsactx); +} + +static void *eddsa_dupctx(void *vpeddsactx) +{ + PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx; + PROV_EDDSA_CTX *dstctx; + + dstctx = OPENSSL_zalloc(sizeof(*srcctx)); + if (dstctx == NULL) + return NULL; + + *dstctx = *srcctx; + dstctx->key = NULL; + + if (srcctx->key != NULL && !ecx_key_up_ref(srcctx->key)) { + PROVerr(0, ERR_R_INTERNAL_ERROR); + goto err; + } + dstctx->key = srcctx->key; + + return dstctx; + err: + eddsa_freectx(dstctx); + return NULL; +} + +const OSSL_DISPATCH ed25519_signature_functions[] = { + { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, + (void (*)(void))eddsa_digest_signverify_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN, + (void (*)(void))ed25519_digest_sign }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, + (void (*)(void))eddsa_digest_signverify_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, + (void (*)(void))ed25519_digest_verify }, + { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, + { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx }, + { 0, NULL } +}; + +const OSSL_DISPATCH ed448_signature_functions[] = { + { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, + (void (*)(void))eddsa_digest_signverify_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN, + (void (*)(void))ed448_digest_sign }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, + (void (*)(void))eddsa_digest_signverify_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY, + (void (*)(void))ed448_digest_verify }, + { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, + { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx }, + { 0, NULL } +};