From 8e3d93e1e0f7e21a32e68b424897e28677f55f29 Mon Sep 17 00:00:00 2001 From: grecow Date: Thu, 25 Jun 2026 15:54:02 +0200 Subject: [PATCH] fix: cleanse only secret scalars in ~ecdsa_preprocessing_data OPENSSL_cleanse(k.data, sizeof(ecdsa_preprocessing_data)) passes the size of the WHOLE struct. Because k is the first member, k.data aliases the object base, so the cleanse spans the non-trivial members mta_request (std::vector), G_proofs and public_data (std::map). A user-declared destructor body runs before the implicit member destructors, so this zeroes the live container control blocks; the subsequent ~vector/~map then operate on zeroed internals (undefined behaviour + heap leak of their allocations). Cleanse each secret scalar individually instead, leaving the containers to their own destructors. Mirrors the correct pattern already used by eddsa_signature_data in eddsa_online_signing_service.h (sizeof(k.data)). Co-Authored-By: Claude Opus 4.8 --- include/cosigner/cmp_ecdsa_signing_service.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/include/cosigner/cmp_ecdsa_signing_service.h b/include/cosigner/cmp_ecdsa_signing_service.h index 3f7b978..cd00873 100644 --- a/include/cosigner/cmp_ecdsa_signing_service.h +++ b/include/cosigner/cmp_ecdsa_signing_service.h @@ -82,7 +82,21 @@ struct ecdsa_preprocessing_data byte_vector_t mta_request; std::map G_proofs; std::map public_data; - ~ecdsa_preprocessing_data() {OPENSSL_cleanse(k.data, sizeof(ecdsa_preprocessing_data));} + ~ecdsa_preprocessing_data() + { + // Wipe each secret scalar individually. Passing sizeof(ecdsa_preprocessing_data) + // to OPENSSL_cleanse() spans the non-trivial members below (mta_request, G_proofs, + // public_data); since this destructor body runs before the implicit member + // destructors, it would zero the live std::vector/std::map control blocks and the + // subsequent ~vector/~map would then run on zeroed internals (UB + leak). + // Mirrors the correct pattern in eddsa_signature_data (eddsa_online_signing_service.h). + OPENSSL_cleanse(k.data, sizeof(k.data)); + OPENSSL_cleanse(gamma.data, sizeof(gamma.data)); + OPENSSL_cleanse(a.data, sizeof(a.data)); + OPENSSL_cleanse(b.data, sizeof(b.data)); + OPENSSL_cleanse(delta.data, sizeof(delta.data)); + OPENSSL_cleanse(chi.data, sizeof(chi.data)); + } }; // this class holds the common functionality for cmp_ecdsa_online_signing_service and cmp_ecdsa_offline_signing_service