-/* $OpenBSD: digest.c,v 1.32 2021/12/12 21:30:13 tb Exp $ */
+/* $OpenBSD: digest.c,v 1.33 2022/01/09 15:15:25 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
EVP_MD_CTX_cleanup(out);
memcpy(out, in, sizeof *out);
+ /*
+ * Because of the EVP_PKEY_CTX_dup() below, EVP_MD_CTX_cleanup() needs
+ * to free out->pctx in all cases (even if this flag is set on in).
+ */
+ EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+
if (in->md_data && out->digest->ctx_size) {
if (tmp_buf) {
out->md_data = tmp_buf;
if (ctx->digest && ctx->digest->ctx_size && ctx->md_data &&
!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE))
freezero(ctx->md_data, ctx->digest->ctx_size);
- EVP_PKEY_CTX_free(ctx->pctx);
+ /*
+ * If EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set, EVP_MD_CTX_set_pkey() was
+ * called and its strange API contract implies we don't own ctx->pctx.
+ */
+ if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX))
+ EVP_PKEY_CTX_free(ctx->pctx);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(ctx->engine);
#endif
-/* $OpenBSD: evp.h,v 1.91 2022/01/07 21:58:17 tb Exp $ */
+/* $OpenBSD: evp.h,v 1.92 2022/01/09 15:15:25 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx);
+#if defined(LIBRESSL_CRYPTO_INTERANL) || defined(LIBRESSL_NEXT_API)
+EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx);
+void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx);
+#endif
#define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e))
#define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e))
#define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e))
-/* $OpenBSD: evp_lib.c,v 1.22 2022/01/07 11:13:54 tb Exp $ */
+/* $OpenBSD: evp_lib.c,v 1.23 2022/01/09 15:15:25 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
return ctx->md_data;
}
+EVP_PKEY_CTX *
+EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx)
+{
+ return ctx->pctx;
+}
+
+void
+EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
+{
+ if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) {
+ EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+ } else {
+ EVP_PKEY_CTX_free(ctx->pctx);
+ }
+
+ ctx->pctx = pctx;
+
+ if (pctx != NULL) {
+ /*
+ * For unclear reasons it was decided that the caller keeps
+ * ownership of pctx. So a flag was invented to make sure we
+ * don't free it in EVP_MD_CTX_cleanup(). We also need to
+ * unset it in EVP_MD_CTX_copy_ex(). Fortunately, the flag
+ * isn't public...
+ */
+ EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+ }
+}
+
void
EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags)
{
-/* $OpenBSD: evp_locl.h,v 1.17 2021/12/12 21:21:58 tb Exp $ */
+/* $OpenBSD: evp_locl.h,v 1.18 2022/01/09 15:15:25 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
__BEGIN_HIDDEN_DECLS
+/*
+ * Don't free md_ctx->pctx in EVP_MD_CTX_cleanup(). Needed for ownership
+ * handling in EVP_MD_CTX_set_pkey_ctx().
+ */
+#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX 0x0400
+
/* Macros to code block cipher wrappers */
/* Wrapper functions for each cipher mode */