From 9f71f906ea95331fd9b269502e92c42d1812dd9e Mon Sep 17 00:00:00 2001 From: Max Fillinger Date: Fri, 31 Oct 2025 11:08:04 +0100 Subject: [PATCH] Zeroize tls-crypt-v2 client keys Joshua Rogers sent in a bug report generated with ZeroPath that the tls-crypt-v2 client key is loaded before running the verify script. If the verify script fails, the key is not zeroized. While investigating this report, I found that free_tls_pre_decrypt_state never zeroizes tls_wrap_tmp.original_wrap_keydata. So also when the check is successful, key data will remain in memory when it is no longer needed. This commit moves the tls-crypt-v2-verify check before loading the key. If it fails, original_wrap_keydata is zeroized. Also, in free_tls_pre_decrypt_state, if a key has been loaded, original_wrap_keydata is zeroized. Reported-By: Joshua Rogers Found-by: ZeroPath (https://zeropath.com/) Change-Id: Icfcbf8ee20c1c0016eb98b570f24b9325b157c5c Signed-off-by: Max Fillinger Acked-by: Arne Schwabe Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1315 Message-Id: <20251031100819.24855-1-gert@greenie.muc.de> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg34103.html Signed-off-by: Gert Doering --- src/openvpn/ssl_pkt.c | 1 + src/openvpn/tls_crypt.c | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/openvpn/ssl_pkt.c b/src/openvpn/ssl_pkt.c index 825719cbf..d7f7ac3dd 100644 --- a/src/openvpn/ssl_pkt.c +++ b/src/openvpn/ssl_pkt.c @@ -280,6 +280,7 @@ free_tls_pre_decrypt_state(struct tls_pre_decrypt_state *state) if (state->tls_wrap_tmp.cleanup_key_ctx) { free_key_ctx_bi(&state->tls_wrap_tmp.opt.key_ctx_bi); + secure_memzero(&state->tls_wrap_tmp.original_wrap_keydata, sizeof(state->tls_wrap_tmp.original_wrap_keydata)); } } diff --git a/src/openvpn/tls_crypt.c b/src/openvpn/tls_crypt.c index 51b4eb3f4..a808de326 100644 --- a/src/openvpn/tls_crypt.c +++ b/src/openvpn/tls_crypt.c @@ -642,6 +642,12 @@ tls_crypt_v2_extract_client_key(struct buffer *buf, struct tls_wrap_ctx *ctx, return false; } + if (opt && opt->tls_crypt_v2_verify_script && !tls_crypt_v2_verify_metadata(ctx, opt)) + { + secure_memzero(&ctx->original_wrap_keydata, sizeof(ctx->original_wrap_keydata)); + return false; + } + /* Load the decrypted key */ ctx->mode = TLS_WRAP_CRYPT; ctx->cleanup_key_ctx = true; @@ -652,11 +658,6 @@ tls_crypt_v2_extract_client_key(struct buffer *buf, struct tls_wrap_ctx *ctx, /* Remove client key from buffer so tls-crypt code can unwrap message */ ASSERT(buf_inc_len(buf, -(BLEN(&wrapped_client_key)))); - if (opt && opt->tls_crypt_v2_verify_script) - { - return tls_crypt_v2_verify_metadata(ctx, opt); - } - return true; } -- 2.47.3