Commit e7608cf6cc for openssl.org

commit e7608cf6cc188fbee3e26ad9648564e39fb51c84
Author: 609bob <1850029304@qq.com>
Date:   Wed Oct 28 20:04:35 2026 +0800

    providers/implementations/kdfs/argon2.c: fix memory leak in argon2_derive()

    This also requires a more carefule thread handling
    in fill_mem_blocks_mt(), that avoids returning on error before joining
    all the outstanding threads.

    Fixes: 6dfa998f7ea1 "providers: add Argon2 KDF"
    Reviewed-by: Jakub Zelenka <jakub.zelenka@openssl.foundation>
    Reviewed-by: Norbert Pocs <norbertp@openssl.org>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Merge-date: Wed Nov 11 09:24:25 2026
    Merged-from: https://github.com/openssl/openssl/pull/33434

diff --git a/providers/implementations/kdfs/argon2.c b/providers/implementations/kdfs/argon2.c
index b988aa212f..61fdde9f52 100644
--- a/providers/implementations/kdfs/argon2.c
+++ b/providers/implementations/kdfs/argon2.c
@@ -574,11 +574,12 @@ static int fill_mem_blocks_mt(KDF_ARGON2 *ctx)
             for (l = 0; l < ctx->lanes; ++l) {
                 ARGON2_POS p;
                 if (l >= ctx->threads) {
-                    if (ossl_crypto_thread_join(t[l - ctx->threads], NULL) == 0)
+                    void *thr = t[l - ctx->threads];
+                    if (ossl_crypto_thread_join(thr, NULL) == 0)
                         goto fail;
-                    if (ossl_crypto_thread_clean(t[l - ctx->threads]) == 0)
+                    t[l - ctx->threads] = NULL;
+                    if (ossl_crypto_thread_clean(thr) == 0)
                         goto fail;
-                    t[l] = NULL;
                 }

                 p.pass = r;
@@ -591,22 +592,16 @@ static int fill_mem_blocks_mt(KDF_ARGON2 *ctx)
                 t[l] = ossl_crypto_thread_start(ctx->libctx, &fill_segment_thr,
                     (void *)&t_data[l]);
                 if (t[l] == NULL) {
-                    for (ll = 0; ll < l; ++ll) {
-                        if (ossl_crypto_thread_join(t[ll], NULL) == 0)
-                            goto fail;
-                        if (ossl_crypto_thread_clean(t[ll]) == 0)
-                            goto fail;
-                        t[ll] = NULL;
-                    }
                     goto fail;
                 }
             }
             for (l = ctx->lanes - ctx->threads; l < ctx->lanes; ++l) {
-                if (ossl_crypto_thread_join(t[l], NULL) == 0)
-                    goto fail;
-                if (ossl_crypto_thread_clean(t[l]) == 0)
+                void *thr = t[l];
+                if (ossl_crypto_thread_join(thr, NULL) == 0)
                     goto fail;
                 t[l] = NULL;
+                if (ossl_crypto_thread_clean(thr) == 0)
+                    goto fail;
             }
         }
     }
@@ -617,10 +612,18 @@ static int fill_mem_blocks_mt(KDF_ARGON2 *ctx)
     return 1;

 fail:
-    if (t_data != NULL)
-        OPENSSL_free(t_data);
-    if (t != NULL)
-        OPENSSL_free(t);
+    if (t != NULL) {
+        for (ll = 0; ll < ctx->lanes; ++ll) {
+            if (t[ll] == NULL)
+                continue;
+            if (ossl_crypto_thread_join(t[ll], NULL) != 0)
+                (void)ossl_crypto_thread_clean(t[ll]);
+            t[ll] = NULL;
+        }
+    }
+
+    OPENSSL_free(t_data);
+    OPENSSL_free(t);
     return 0;
 }

@@ -1110,8 +1113,15 @@ static int kdf_argon2_derive(void *vctx, unsigned char *out, size_t outlen,
     if (initialize(ctx) != 1)
         return 0;

-    if (fill_memory_blocks(ctx) != 1)
+    if (fill_memory_blocks(ctx) != 1) {
+        if (ctx->type != ARGON2_D)
+            OPENSSL_secure_clear_free(ctx->memory,
+                ctx->memory_blocks * sizeof(BLOCK));
+        else
+            OPENSSL_clear_free(ctx->memory,
+                ctx->memory_blocks * sizeof(BLOCK));
         return 0;
+    }

     finalize(ctx, out);