Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/lib/SoftHSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6478,7 +6478,7 @@ CK_RV SoftHSM::WrapMechRsaAesKw
ByteString wrapped_1; // buffer for the wrapped AES key;
ByteString wrapped_2; // buffer for the wrapped target key;
CK_RSA_AES_KEY_WRAP_PARAMS_PTR params = (CK_RSA_AES_KEY_WRAP_PARAMS_PTR)pMechanism->pParameter;
CK_ULONG emphKeyLen = params->aes_key_bits / 8;
CK_ULONG emphKeyLen = params->ulAESKeyBits / 8;
CK_OBJECT_HANDLE hEmphKey = CK_INVALID_HANDLE;
CK_OBJECT_CLASS emphKeyClass = CKO_SECRET_KEY;
CK_KEY_TYPE emphKeyType = CKK_AES;
Expand Down Expand Up @@ -6540,7 +6540,7 @@ CK_RV SoftHSM::WrapMechRsaAesKw
emphKey->destroyObject();
hEmphKey = CK_INVALID_HANDLE;

CK_MECHANISM oaepMech = {CKM_RSA_PKCS_OAEP, params->oaep_params, sizeof(CK_RSA_PKCS_OAEP_PARAMS)};
CK_MECHANISM oaepMech = {CKM_RSA_PKCS_OAEP, params->pOAEPParams, sizeof(CK_RSA_PKCS_OAEP_PARAMS)};
// Wraps the AES emph key with the wrapping RSA key using CKM_RSA_PKCS_OAEP with parameters of OAEPParams.
rv = SoftHSM::WrapKeyAsym(&oaepMech, token, wrapKey, emphkeydata, wrapped_1);

Comment on lines +6543 to 6546
Copy link

@coderabbitai coderabbitai bot Sep 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

OAEP params are passed, but not actually used by WrapKeyAsym/UnwrapKeyAsym.

WrapKeyAsym/UnwrapKeyAsym ignore CK_MECHANISM::pParameter and always perform OAEP with SHA-1 (see the hard-coded size check and lack of param pluming). With the new API you accept non-SHA1 MGF values, which can mislead callers and cause interop failures when they expect OAEP(SHA-256, …). Either (a) restrict OAEPParams to SHA-1/MGF1-SHA1 here, or (b) plumb OAEP params down to the crypto backend and enforce consistency checks.

Apply this minimal guard now (option a):

--- a/src/lib/SoftHSM.cpp
+++ b/src/lib/SoftHSM.cpp
@@ -13162,6 +13192,24 @@ CK_RV SoftHSM::MechParamCheckRSAAESKEYWRAP(CK_MECHANISM_PTR pMechanism)
-    if (params->pOAEPParams->mgf < 1UL || params->pOAEPParams->mgf > 5UL)
-    {
-        ERROR_MSG("mgf not supported");
-        return CKR_ARGUMENTS_BAD;
-    }
+    /* SoftHSM currently supports OAEP with SHA-1 only. Keep checks consistent
+     * with MechParamCheckRSAPKCSOAEP until OAEP params are fully plumbed. */
+    if (params->pOAEPParams->hashAlg != CKM_SHA_1)
+    {
+        ERROR_MSG("hashAlg must be CKM_SHA_1");
+        return CKR_ARGUMENTS_BAD;
+    }
+    if (params->pOAEPParams->mgf != CKG_MGF1_SHA1)
+    {
+        ERROR_MSG("mgf must be CKG_MGF1_SHA1");
+        return CKR_ARGUMENTS_BAD;
+    }

Option (b) is preferable long-term: extend WrapKeyAsym/UnwrapKeyAsym and the RSA backend to accept OAEP params and validate hashAlg/mgf consistency.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
CK_MECHANISM oaepMech = {CKM_RSA_PKCS_OAEP, params->pOAEPParams, sizeof(CK_RSA_PKCS_OAEP_PARAMS)};
// Wraps the AES emph key with the wrapping RSA key using CKM_RSA_PKCS_OAEP with parameters of OAEPParams.
rv = SoftHSM::WrapKeyAsym(&oaepMech, token, wrapKey, emphkeydata, wrapped_1);
CK_RV SoftHSM::MechParamCheckRSAAESKEYWRAP(CK_MECHANISM_PTR pMechanism)
{
CK_RSA_AES_KEY_WRAP_PARAMS_PTR params = static_cast<CK_RSA_AES_KEY_WRAP_PARAMS_PTR>(pMechanism->pParameter);
/* SoftHSM currently supports OAEP with SHA-1 only. Keep checks consistent
* with MechParamCheckRSAPKCSOAEP until OAEP params are fully plumbed. */
if (params->pOAEPParams->hashAlg != CKM_SHA_1)
{
ERROR_MSG("hashAlg must be CKM_SHA_1");
return CKR_ARGUMENTS_BAD;
}
if (params->pOAEPParams->mgf != CKG_MGF1_SHA1)
{
ERROR_MSG("mgf must be CKG_MGF1_SHA1");
return CKR_ARGUMENTS_BAD;
}
// ...remaining checks ...
}
🤖 Prompt for AI Agents
In src/lib/SoftHSM.cpp around lines 6543-6546, the code passes OAEP params to
WrapKeyAsym but that function ignores pParameter and always uses SHA-1; to apply
the minimal guard, validate params->pOAEPParams before calling WrapKeyAsym: if
pOAEPParams is non-null, cast to CK_RSA_PKCS_OAEP_PARAMS and verify hashAlg ==
CKM_SHA_1 and mgf == CKG_MGF1_SHA1 (and pSource == CKZ_DATA or other allowed
source if applicable); if the check fails, return CKR_MECHANISM_PARAM_INVALID
(or an appropriate CKR) and avoid calling WrapKeyAsym; apply the same validation
for UnwrapKeyAsym call sites to ensure callers cannot request non-SHA1 OAEP
until full plumbing is implemented.

💡 Verification agent

🧩 Analysis chain

Confirm backend support before relaxing OAEP constraints.

If you plan to support OAEP with SHA-2, verify the RSA backend (OSSLCryptoFactory/BotanCryptoFactory) and AsymmetricAlgorithm::wrapKey/unwrapKey accept OAEP params and set the hash/MGF accordingly.

Run:

Also applies to: 7060-7063


🏁 Script executed:

#!/bin/bash
# Inspect whether OAEP params are used anywhere in RSA wrap/unwrap paths.
rg -nP -C3 'wrapKey\s*\(\s*publicKey\s*,\s*\w+\s*,\s*\w+\s*,\s*AsymMech::RSA_PKCS_OAEP' src
rg -nP -C3 'unwrapKey\s*\(\s*unwrappingkey\s*,\s*\w+\s*,\s*\w+\s*,\s*AsymMech::RSA_PKCS_OAEP' src
rg -nP -C3 'CK_RSA_PKCS_OAEP_PARAMS|hashAlg|mgf' src

Length of output: 41122


Do not relax OAEP constraints until backend OAEP (SHA‑2/MGF1) support is confirmed

SoftHSM currently forces CKM_SHA_1 / CKG_MGF1_SHA1 in OAEP paths (src/lib/SoftHSM.cpp:3207–3216 and 13117–13127) while Wrap/Unwrap pass params->pOAEPParams (src/lib/SoftHSM.cpp:6543, 7059). Verify that AsymmetricAlgorithm::wrapKey/unwrapKey and the RSA backends map CK_RSA_PKCS_OAEP_PARAMS → backend hash/MGF options (check src/lib/crypto/AsymmetricAlgorithm.{h,cpp}, src/lib/crypto/OSSLRSA.cpp, src/lib/crypto/BotanRSA.cpp). If backends do not accept OAEP params or SHA‑2 MGF1, either implement that mapping in the backends or keep the OAEP restriction to SHA‑1 and return CKR_ARGUMENTS_BAD.

🤖 Prompt for AI Agents
In src/lib/SoftHSM.cpp around lines 6543–6546, the code passes
params->pOAEPParams to WrapKeyAsym but SoftHSM currently forces OAEP to
SHA‑1/MGF1 elsewhere; do not relax this constraint until the RSA backends
actually support OAEP params and SHA‑2/MGF1. Verify
AsymmetricAlgorithm::wrapKey/unwrapKey and the RSA backend mappings in
src/lib/crypto/AsymmetricAlgorithm.{h,cpp}, src/lib/crypto/OSSLRSA.cpp, and
src/lib/crypto/BotanRSA.cpp: if those backends already map
CK_RSA_PKCS_OAEP_PARAMS to the correct hash/MGF options, ensure Wrap/Unwrap use
that mapping; if they do not, either implement the mapping in the backends to
accept pOAEPParams (supporting SHA‑2 and MGF1 variants) or enforce the existing
restriction by rejecting non‑SHA1 OAEP parameters and returning
CKR_ARGUMENTS_BAD.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR just changes the parameter name so this seems a bit out of scope but possibly a good suggestion for the future.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bukka Agreed—let’s keep this PR focused on the header update/param rename. I’ll defer the OAEP behavior checks.

Would you like me to open a follow‑up issue to track: “Plumb CK_RSA_PKCS_OAEP params (hash/MGF) through RSA wrap/unwrap or restrict to SHA‑1 until supported”? Draft:

  • Problem: WrapKeyAsym/UnwrapKeyAsym ignore CK_RSA_PKCS_OAEP_PARAMS; RSAAES check now allows non‑SHA1 MGF, which can mislead callers.
  • Short‑term options: (a) reject non‑SHA1 OAEP in RSAAES guard; (b) wire OAEP params to the RSA backend and add tests.
  • Deliverables: decide approach, implement, and add interop tests for OAEP(SHA‑1/256/384/512) if (b).

If you confirm, I’ll open it and link back to this PR/comment.


✏️ Learnings added
Learnt from: bukka
PR: softhsm/SoftHSMv2#815
File: src/lib/SoftHSM.cpp:6543-6546
Timestamp: 2025-09-11T16:54:00.347Z
Learning: SoftHSM PR #815 (pkcs11.h 3.1.0 update, CK_RSA_AES_KEY_WRAP_PARAMS fix): Maintainer bukka prefers to keep scope minimal (header sync and param rename only); broader OAEP parameter enforcement or backend plumbing is out of scope for this PR and should be handled in a follow-up issue.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: antoinelochet
PR: softhsm/SoftHSMv2#809
File: src/lib/SoftHSM.cpp:10044-10055
Timestamp: 2025-08-18T19:46:46.659Z
Learning: In SoftHSM::generateMLDSA (src/lib/SoftHSM.cpp), the project prefers using CKP_ML_DSA_* constants for parameter set checks and logs "Unsupported parameter set: %lu". The code currently returns CKR_PARAMETER_SET_NOT_SUPPORTED for unsupported sets.

Expand Down Expand Up @@ -7056,7 +7056,7 @@ CK_RV SoftHSM::UnwrapMechRsaAesKw
CK_ULONG wrappedLen2 = ulWrappedKeyLen - wrappedLen1;

ByteString wrapped_1(&wrapped[0], wrappedLen1); // the wrapped AES key
CK_MECHANISM oaepMech = {CKM_RSA_PKCS_OAEP, params->oaep_params, sizeof(CK_RSA_PKCS_OAEP_PARAMS)};
CK_MECHANISM oaepMech = {CKM_RSA_PKCS_OAEP, params->pOAEPParams, sizeof(CK_RSA_PKCS_OAEP_PARAMS)};

// Un-wraps the temporary AES key from the first part with the private RSA key using CKM_RSA_PKCS_OAEP.
rv = UnwrapKeyAsym(&oaepMech, wrapped_1, token, unwrapKey, emphkeydata);
Expand Down Expand Up @@ -13159,32 +13159,32 @@ CK_RV SoftHSM::MechParamCheckRSAAESKEYWRAP(CK_MECHANISM_PTR pMechanism)
}

CK_RSA_AES_KEY_WRAP_PARAMS_PTR params = (CK_RSA_AES_KEY_WRAP_PARAMS_PTR)pMechanism->pParameter;
if (params->aes_key_bits != 128 && params->aes_key_bits != 192 && params->aes_key_bits != 256)
if (params->ulAESKeyBits != 128 && params->ulAESKeyBits != 192 && params->ulAESKeyBits != 256)
{
ERROR_MSG("length of the temporary AES key in bits can be only 128, 192 or 256");
return CKR_ARGUMENTS_BAD;
}
if (params->oaep_params == NULL_PTR)
if (params->pOAEPParams == NULL_PTR)
{
ERROR_MSG("oaep_params must be of type CK_RSA_PKCS_OAEP_PARAMS");
return CKR_ARGUMENTS_BAD;
}
if (params->oaep_params->mgf < 1UL || params->oaep_params->mgf > 5UL)
if (params->pOAEPParams->mgf < 1UL || params->pOAEPParams->mgf > 5UL)
{
ERROR_MSG("mgf not supported");
return CKR_ARGUMENTS_BAD;
}
if (params->oaep_params->source != CKZ_DATA_SPECIFIED)
if (params->pOAEPParams->source != CKZ_DATA_SPECIFIED)
{
ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
return CKR_ARGUMENTS_BAD;
}
if (params->oaep_params->pSourceData != NULL)
if (params->pOAEPParams->pSourceData != NULL)
{
ERROR_MSG("pSourceData must be NULL");
return CKR_ARGUMENTS_BAD;
}
if (params->oaep_params->ulSourceDataLen != 0)
if (params->pOAEPParams->ulSourceDataLen != 0)
{
ERROR_MSG("ulSourceDataLen must be 0");
return CKR_ARGUMENTS_BAD;
Expand Down
Loading
Loading