Commit acbec2d289 for strongswan.org

commit acbec2d2892798140bd84d2b00988d77c73fe5d7
Author: Duc Anh Luu <luuducanh05051995@gmail.com>
Date:   Tue Oct 20 15:08:52 2026 +0700

    pkcs11: Pass CKA_VALUE_LEN when deriving MODP shared secrets

    Some tokens, such as SoftHSM, reject the derivation of a generic secret
    with CKR_TEMPLATE_INCOMPLETE if the template has no CKA_VALUE_LEN. For MODP
    the shared secret has the length of the prime, so pass that. For ECDH the
    length is left to the token.

diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c b/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c
index bb91459658..95cb7a2e96 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c
@@ -80,6 +80,11 @@ struct private_pkcs11_dh_t {
 	 */
 	CK_MECHANISM_TYPE mech_derive;

+	/**
+	 * Length of the shared secret to derive, 0 to let the token decide
+	 */
+	CK_ULONG secret_len;
+
 };

 /**
@@ -97,6 +102,7 @@ static bool derive_secret(private_pkcs11_dh_t *this, chunk_t other)
 		{ CKA_KEY_TYPE, &type, sizeof(type) },
 		{ CKA_SENSITIVE, &ck_false, sizeof(ck_false) },
 		{ CKA_EXTRACTABLE, &ck_true, sizeof(ck_true) },
+		{ CKA_VALUE_LEN, &this->secret_len, sizeof(this->secret_len) },
 	};
 	CK_MECHANISM mech = {
 		this->mech_derive,
@@ -110,9 +116,15 @@ static bool derive_secret(private_pkcs11_dh_t *this, chunk_t other)
 		other.len,
 		other.ptr,
 	};
+	CK_ULONG attr_count = countof(attr);
 	CK_OBJECT_HANDLE secret;
 	CK_RV rv;

+	if (!this->secret_len)
+	{	/* CKA_VALUE_LEN is the last attribute, only pass it if we know it */
+		attr_count--;
+	}
+
 	switch (this->group)
 	{
 		case ECP_192_BIT:
@@ -130,7 +142,7 @@ static bool derive_secret(private_pkcs11_dh_t *this, chunk_t other)
 	}

 	rv = this->lib->f->C_DeriveKey(this->session, &mech, this->pri_key,
-								   attr, countof(attr), &secret);
+								   attr, attr_count, &secret);
 	if (rv != CKR_OK)
 	{
 		DBG1(DBG_CFG, "C_DeriveKey() error: %N", ck_rv_names, rv);
@@ -401,6 +413,9 @@ static pkcs11_dh_t *create_modp(key_exchange_method_t group, size_t exp_len,

 	if (this)
 	{
+		/* some tokens, like SoftHSM, require CKA_VALUE_LEN to derive a generic
+		 * secret, which for MODP is the length of the prime */
+		this->secret_len = p.len;
 		if (generate_key_pair_modp(this, exp_len, g, p))
 		{
 			return &this->public;