Commit a010fde5b6 for openssl.org

commit a010fde5b6566d283c83f6590d88fbf3b681fd0d
Author: Simo Sorce <simo@redhat.com>
Date:   Thu Nov 20 14:08:56 2025 -0500

    Add documentation for digest serialization

    Documents EVP_MD_CTX_[s|des]erialize functions.

    Signed-off-by: Simo Sorce <simo@redhat.com>

    Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
    Reviewed-by: Tomas Mraz <tomas@openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/28837)

diff --git a/CHANGES.md b/CHANGES.md
index 8a04fadc9c..31ec4adf52 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -88,6 +88,14 @@ OpenSSL 4.0

    *Barry Fussell and Helen Zhang*

+ * Added `EVP_MD_CTX_serialize()`/`EVP_MD_CTX_deserialize()` functions. These
+   functions allow to export the internal state of a Digest and re-import it
+   later to continue a computation from a specific checkpoint.  Only SHA-2 and
+   the SHA-3 family (Keccak, SHAKE, SHA-3) of functions currently support this
+   functionality
+
+   *Simo Sorce*
+
 OpenSSL 3.6
 -----------

diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod
index 804a76f73b..c7392018be 100644
--- a/doc/man3/EVP_DigestInit.pod
+++ b/doc/man3/EVP_DigestInit.pod
@@ -13,6 +13,7 @@ EVP_MD_CTX_set_flags, EVP_MD_CTX_clear_flags, EVP_MD_CTX_test_flags,
 EVP_Q_digest, EVP_Digest, EVP_DigestInit_ex2, EVP_DigestInit_ex, EVP_DigestInit,
 EVP_DigestUpdate, EVP_DigestFinal_ex, EVP_DigestFinalXOF, EVP_DigestFinal,
 EVP_DigestSqueeze,
+EVP_MD_CTX_serialize, EVP_MD_CTX_deserialize,
 EVP_MD_is_a, EVP_MD_get0_name, EVP_MD_get0_description,
 EVP_MD_names_do_all, EVP_MD_get0_provider, EVP_MD_get_type,
 EVP_MD_get_pkey_type, EVP_MD_get_size, EVP_MD_get_block_size, EVP_MD_get_flags,
@@ -65,6 +66,8 @@ EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data
  int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
  int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
  int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
+ int EVP_MD_CTX_serialize(EVP_MD_CTX *ctx, unsigned char *out, size_t *outlen);
+ int EVP_MD_CTX_deserialize(EVP_MD_CTX *ctx, const unsigned char *in, size_t inlen);

  EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in);
  int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in);
@@ -319,6 +322,24 @@ Similar to EVP_DigestFinalXOF() but allows multiple calls to be made to
 squeeze variable length output data.
 EVP_DigestFinalXOF() should not be called after this.

+=item EVP_MD_CTX_serialize() and EVP_MD_CTX_deserialize()
+
+EVP_MD_CTX_serialize() serializes the state of the digest context I<ctx>
+and stores it in I<out>, unless I<out> is NULL.
+Otherwise the maximum necessary size of the output buffer is written to
+the I<outlen> parameter. If I<out> is not NULL then before the call the
+I<outlen> parameter must contain the length of the I<out> buffer. If the
+call is successful the data is written to I<out> and the amount of data
+written to I<outlen>.
+
+EVP_MD_CTX_deserialize() deserializes the data from I<in> of size I<inlen>
+into the digest context I<ctx>.
+
+These functions do not guarantee importability of state exported by a
+different OpenSSL version and does not guarantee interoperability between
+different providers. Some providers may not allow export/import across
+process boundaries.
+
 =item EVP_MD_CTX_dup()

 Can be used to duplicate the message digest state from I<in>.  This is useful
@@ -632,7 +653,9 @@ EVP_DigestInit_ex(),
 EVP_DigestInit(),
 EVP_DigestUpdate(),
 EVP_DigestFinal_ex(),
-EVP_DigestFinalXOF(), and
+EVP_DigestFinalXOF(),
+EVP_MD_CTX_serialize(),
+EVP_MD_CTX_deserialize(), and
 EVP_DigestFinal()

 return 1 for
@@ -863,6 +886,9 @@ to be aliases for EVP_MD_CTX_get_size_ex(), previously they were aliases for
 EVP_MD_get_size which returned a constant value. This is required for XOF
 digests since they do not have a fixed size.

+The EVP_MD_CTX_serialize() and EVP_MD_CTX_deserialize() functions were added in
+OpenSSL 4.0.
+
 =head1 COPYRIGHT

 Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man7/provider-digest.pod b/doc/man7/provider-digest.pod
index c44de648dc..5620812e3f 100644
--- a/doc/man7/provider-digest.pod
+++ b/doc/man7/provider-digest.pod
@@ -30,6 +30,10 @@ provider-digest - The digest library E<lt>-E<gt> provider functions
  int OSSL_FUNC_digest_digest(void *provctx, const unsigned char *in, size_t inl,
                              unsigned char *out, size_t *outl, size_t outsz);

+ /* Digest state serialization */
+ int OSSL_FUNC_digest_serialize(void *dctx, unsigned char *out, size_t *outl);
+ int OSSL_FUNC_digest_deserialize(void *dctx, const unsigned char *in, size_t inl);
+
  /* Digest parameter descriptors */
  const OSSL_PARAM *OSSL_FUNC_digest_gettable_params(void *provctx);

@@ -84,6 +88,9 @@ macros in L<openssl-core_dispatch.h(7)>, as follows:
  OSSL_FUNC_digest_final                OSSL_FUNC_DIGEST_FINAL
  OSSL_FUNC_digest_digest               OSSL_FUNC_DIGEST_DIGEST

+ OSSL_FUNC_digest_serialize            OSSL_FUNC_DIGEST_SERIALIZE
+ OSSL_FUNC_digest_deserialize          OSSL_FUNC_DIGEST_DESERIALIZE
+
  OSSL_FUNC_digest_get_params           OSSL_FUNC_DIGEST_GET_PARAMS
  OSSL_FUNC_digest_get_ctx_params       OSSL_FUNC_DIGEST_GET_CTX_PARAMS
  OSSL_FUNC_digest_set_ctx_params       OSSL_FUNC_DIGEST_SET_CTX_PARAMS
@@ -152,6 +159,26 @@ I<inl> bytes at I<in> should be digested and the result should be stored at
 I<out>. The length of the digest should be stored in I<*outl> which should not
 exceed I<outsz> bytes.

+=head2 Digest State Serialization Functions
+
+OSSL_FUNC_digest_serialize() serializes the state of the digest context I<dctx>.
+If I<out> is NULL, then the maximum necessary size for the output buffer is
+written to I<*outl>.
+If I<out> is not NULL, then I<*outl> is assumed to contain the length of the
+I<out> buffer. If the call is successful, the serialized data is written
+to I<out> and the amount of data written is stored in I<*outl>.
+
+OSSL_FUNC_digest_deserialize() deserializes the data from I<in> of size I<inlen>
+into the digest context I<dctx>.
+The context I<dctx> should be initialized before calling this function.
+After a successful deserialization, the context is ready to be used for
+any subsequent digest operations.
+
+The content of the state and its validity (over time, process lifetime, etc) are
+completely in control of the provider. The documentation for each provider
+should state what guarantees it can offer in terms of recovering the state of a
+serialized blob.
+
 =head2 Digest Parameters

 See L<OSSL_PARAM(3)> for further details on the parameters structure used by
@@ -254,9 +281,11 @@ See L<OSSL_PARAM(3)> for further details on the parameters structure.
 OSSL_FUNC_digest_newctx() and OSSL_FUNC_digest_dupctx() should return the newly created
 provider side digest context, or NULL on failure.

-OSSL_FUNC_digest_init(), OSSL_FUNC_digest_update(), OSSL_FUNC_digest_final(), OSSL_FUNC_digest_digest(),
-OSSL_FUNC_digest_set_params() and OSSL_FUNC_digest_get_params() should return 1 for success or
-0 on error.
+OSSL_FUNC_digest_init(), OSSL_FUNC_digest_update(), OSSL_FUNC_digest_final(),
+OSSL_FUNC_digest_digest(), OSSL_FUNC_digest_get_params(),
+OSSL_FUNC_digest_set_ctx_params(), OSSL_FUNC_digest_get_ctx_params(),
+OSSL_FUNC_digest_serialize(), and OSSL_FUNC_digest_deserialize() should return 1 for
+success or 0 on error.

 OSSL_FUNC_digest_size() should return the digest size.