From: Simo Sorce Date: Thu, 20 Nov 2025 15:25:47 +0000 (-0500) Subject: Add EVP digest context serialization X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c1f66c1ec33763de0d5e94e66039238729ef9c4b;p=thirdparty%2Fopenssl.git Add EVP digest context serialization This commit introduces two new functions, EVP_MD_CTX_serialize and EVP_MD_CTX_deserialize, to the EVP digest API. These functions allow an application to save the state of a digest context (EVP_MD_CTX) and restore it later. This is useful for checkpointing long-running computations, enabling them to be paused and resumed without starting over. The implementation adds the OSSL_FUNC_DIGEST_SERIALIZE and OSSL_FUNC_DIGEST_DESERIALIZE dispatch functions for providers to supply this functionality. Signed-off-by: Simo Sorce Reviewed-by: Shane Lontis Reviewed-by: Tomas Mraz Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/28837) --- diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 70e06a6a38a..28f8b4fd619 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -700,6 +700,7 @@ EVP_R_CIPHER_NOT_GCM_MODE:184:cipher not gcm mode EVP_R_CIPHER_PARAMETER_ERROR:122:cipher parameter error EVP_R_COMMAND_NOT_SUPPORTED:147:command not supported EVP_R_CONFLICTING_ALGORITHM_NAME:201:conflicting algorithm name +EVP_R_CONTEXT_FINALIZED:239:context finalized EVP_R_COPY_ERROR:173:copy error EVP_R_CTRL_NOT_IMPLEMENTED:132:ctrl not implemented EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED:133:ctrl operation not implemented diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 7184f9a051e..61c9b49c509 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -494,6 +494,57 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *md, size_t size) return ctx->digest->dsqueeze(ctx->algctx, md, &size, size); } +int EVP_MD_CTX_serialize(EVP_MD_CTX *ctx, unsigned char *out, size_t *outlen) +{ + if (ctx->digest == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM); + return 0; + } + + if (ctx->digest->prov == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION); + return 0; + } + + if (ctx->digest->serialize == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED); + return 0; + } + + if (ossl_unlikely((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0)) { + ERR_raise(ERR_LIB_EVP, EVP_R_CONTEXT_FINALIZED); + return 0; + } + + return ctx->digest->serialize(ctx->algctx, out, outlen); +} + +int EVP_MD_CTX_deserialize(EVP_MD_CTX *ctx, const unsigned char *in, + size_t inlen) +{ + if (ctx->digest == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM); + return 0; + } + + if (ctx->digest->prov == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION); + return 0; + } + + if (ctx->digest->deserialize == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED); + return 0; + } + + if (ossl_unlikely((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0)) { + ERR_raise(ERR_LIB_EVP, EVP_R_CONTEXT_FINALIZED); + return 0; + } + + return ctx->digest->deserialize(ctx->algctx, in, inlen); +} + EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in) { EVP_MD_CTX *out = EVP_MD_CTX_new(); @@ -1035,6 +1086,14 @@ static void *evp_md_from_algorithm(int name_id, if (md->copyctx == NULL) md->copyctx = OSSL_FUNC_digest_copyctx(fns); break; + case OSSL_FUNC_DIGEST_SERIALIZE: + if (md->serialize == NULL) + md->serialize = OSSL_FUNC_digest_serialize(fns); + break; + case OSSL_FUNC_DIGEST_DESERIALIZE: + if (md->deserialize == NULL) + md->deserialize = OSSL_FUNC_digest_deserialize(fns); + break; } } if ((fncnt != 0 && fncnt != 5 && fncnt != 6) diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index 5672e7293f6..55b26c7cd7a 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -39,6 +39,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { "command not supported" }, { ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CONFLICTING_ALGORITHM_NAME), "conflicting algorithm name" }, + { ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CONTEXT_FINALIZED), "context finalized" }, { ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COPY_ERROR), "copy error" }, { ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CTRL_NOT_IMPLEMENTED), "ctrl not implemented" }, diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 43d4fdc5276..30de8b272f3 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -294,6 +294,8 @@ struct evp_md_st { OSSL_FUNC_digest_gettable_params_fn *gettable_params; OSSL_FUNC_digest_settable_ctx_params_fn *settable_ctx_params; OSSL_FUNC_digest_gettable_ctx_params_fn *gettable_ctx_params; + OSSL_FUNC_digest_serialize_fn *serialize; + OSSL_FUNC_digest_deserialize_fn *deserialize; } /* EVP_MD */; diff --git a/include/crypto/evperr.h b/include/crypto/evperr.h index 1a91b62fce5..afe136c816a 100644 --- a/include/crypto/evperr.h +++ b/include/crypto/evperr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 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 diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 8f6278070e1..acdf1543320 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -315,6 +315,8 @@ OSSL_CORE_MAKE_FUNC(int, SSL_QUIC_TLS_alert, #define OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS 13 #define OSSL_FUNC_DIGEST_SQUEEZE 14 #define OSSL_FUNC_DIGEST_COPYCTX 15 +#define OSSL_FUNC_DIGEST_SERIALIZE 16 +#define OSSL_FUNC_DIGEST_DESERIALIZE 17 OSSL_CORE_MAKE_FUNC(void *, digest_newctx, (void *provctx)) OSSL_CORE_MAKE_FUNC(int, digest_init, (void *dctx, const OSSL_PARAM params[])) @@ -345,6 +347,10 @@ OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, digest_settable_ctx_params, (void *dctx, void *provctx)) OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, digest_gettable_ctx_params, (void *dctx, void *provctx)) +OSSL_CORE_MAKE_FUNC(int, digest_serialize, + (void *dctx, unsigned char *out, size_t *outl)) +OSSL_CORE_MAKE_FUNC(int, digest_deserialize, + (void *dctx, const unsigned char *in, size_t inl)) /* Symmetric Ciphers */ diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 6c05d9a9136..1cf61076cc9 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -753,6 +753,10 @@ __owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); __owur int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); +__owur int EVP_MD_CTX_serialize(EVP_MD_CTX *ctx, unsigned char *out, + size_t *outlen); +__owur int EVP_MD_CTX_deserialize(EVP_MD_CTX *ctx, const unsigned char *in, + size_t inlen); __owur EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties); diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h index 23e4a9796a0..b3d2cb04efa 100644 --- a/include/openssl/evperr.h +++ b/include/openssl/evperr.h @@ -33,6 +33,7 @@ #define EVP_R_CIPHER_PARAMETER_ERROR 122 #define EVP_R_COMMAND_NOT_SUPPORTED 147 #define EVP_R_CONFLICTING_ALGORITHM_NAME 201 +#define EVP_R_CONTEXT_FINALIZED 239 #define EVP_R_COPY_ERROR 173 #define EVP_R_CTRL_NOT_IMPLEMENTED 132 #define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133 diff --git a/util/libcrypto.num b/util/libcrypto.num index 155ba0f93d1..324cc46a729 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5815,3 +5815,5 @@ OSSL_PARAM_clear_free ? 4_0_0 EXIST::FUNCTION: CMS_dataFinal_ex ? 4_0_0 EXIST::FUNCTION:CMS CMS_SignerInfo_verify_ex ? 4_0_0 EXIST::FUNCTION:CMS EVP_SIGNATURE_has_message_update ? 4_0_0 EXIST::FUNCTION: +EVP_MD_CTX_serialize ? 4_0_0 EXIST::FUNCTION: +EVP_MD_CTX_deserialize ? 4_0_0 EXIST::FUNCTION: