Commit ef039b373f for strongswan.org

commit ef039b373f1612d2b2a81191092d817f9c6017de
Author: Tobias Brunner <tobias@strongswan.org>
Date:   Wed May 13 10:27:10 2026 +0200

    signature-params: Only encode length in context string of PQC params

    While the length prefix is also used for PQC or hybrid algorithms other
    than ML-DSA, the first byte that was previously encoded is used to
    distinguish ML-DSA from HashML-DSA (Pre-Hash ML-DSA), where it would be
    set to 1.  NIST doesn't recommend that mode and we currently don't
    support it.  If we ever do, that flag could be made part of the params.

diff --git a/src/libstrongswan/credentials/keys/signature_params.c b/src/libstrongswan/credentials/keys/signature_params.c
index daa902f190..1b97853b91 100644
--- a/src/libstrongswan/credentials/keys/signature_params.c
+++ b/src/libstrongswan/credentials/keys/signature_params.c
@@ -423,9 +423,8 @@ bool pqc_params_create(pqc_params_t *p_in, pqc_params_t *p_out)

 	if (!p_in)
 	{
-		p_out->pre_ctx = chunk_alloc(2);
+		p_out->pre_ctx = chunk_alloc(1);
 		p_out->pre_ctx.ptr[0] = 0x00;
-		p_out->pre_ctx.ptr[1] = 0x00;
 	}
 	else
 	{
@@ -438,12 +437,11 @@ bool pqc_params_create(pqc_params_t *p_in, pqc_params_t *p_out)
 				 PQC_MAX_CTX_LEN);
 			return FALSE;
 		}
-		p_out->pre_ctx = chunk_alloc(2 + p_in->ctx.len);
-		p_out->pre_ctx.ptr[0] = 0x00;
-		p_out->pre_ctx.ptr[1] = (uint8_t)p_in->ctx.len;
-		memcpy(p_out->pre_ctx.ptr + 2, p_in->ctx.ptr, p_in->ctx.len);
+		p_out->pre_ctx = chunk_alloc(p_in->ctx.len + 1);
+		p_out->pre_ctx.ptr[0] = (uint8_t)p_in->ctx.len;
+		memcpy(p_out->pre_ctx.ptr + 1, p_in->ctx.ptr, p_in->ctx.len);
 	}
-	p_out->ctx = chunk_skip(p_out->pre_ctx, 2);
+	p_out->ctx = chunk_skip(p_out->pre_ctx, 1);

 	return TRUE;
 }
diff --git a/src/libstrongswan/plugins/ml/ml_dsa_private_key.c b/src/libstrongswan/plugins/ml/ml_dsa_private_key.c
index 79635de43b..c0c2d37c9f 100644
--- a/src/libstrongswan/plugins/ml/ml_dsa_private_key.c
+++ b/src/libstrongswan/plugins/ml/ml_dsa_private_key.c
@@ -265,6 +265,7 @@ METHOD(private_key_t, sign, bool,
 	private_private_key_t *this, signature_scheme_t scheme,
 	void *params, chunk_t data, chunk_t *signature)
 {
+	const u_char pre_hash = 0;
 	const u_int k = this->params->k;
 	const u_int l = this->params->l;
 	const u_int gamma2 = this->params->gamma2;
@@ -319,7 +320,8 @@ METHOD(private_key_t, sign, bool,
 	}

 	/* compute message representative mu */
-	seed = chunk_cat("ccc", tr, pqc_params.pre_ctx, data);
+	seed = chunk_cat("cccc", tr, chunk_from_thing(pre_hash), pqc_params.pre_ctx,
+					 data);
 	if (!H->set_seed(H, seed) ||
 		!H->get_bytes(H, ML_DSA_MU_LEN, mu.ptr))
 	{
diff --git a/src/libstrongswan/plugins/ml/ml_dsa_public_key.c b/src/libstrongswan/plugins/ml/ml_dsa_public_key.c
index 49ef68f30f..bd3131bc88 100644
--- a/src/libstrongswan/plugins/ml/ml_dsa_public_key.c
+++ b/src/libstrongswan/plugins/ml/ml_dsa_public_key.c
@@ -328,6 +328,7 @@ METHOD(public_key_t, verify, bool,
 	private_public_key_t *this, signature_scheme_t scheme,
 	void *params, chunk_t data, chunk_t signature)
 {
+	const u_char pre_hash = 0;
 	const u_int k = this->params->k;
 	const u_int l = this->params->l;
 	const int32_t bound = (1 << this->params->gamma1_exp) - this->params->beta;
@@ -376,7 +377,8 @@ METHOD(public_key_t, verify, bool,
 	}

 	/* compute message representative mu */
-	seed = chunk_cat("ccc", tr, pqc_params.pre_ctx, data);
+	seed = chunk_cat("cccc", tr, chunk_from_thing(pre_hash), pqc_params.pre_ctx,
+					 data);
 	if (!H->set_seed(H, seed) ||
 		!H->get_bytes(H, ML_DSA_MU_LEN, mu.ptr))
 	{