Skip to content

fix: check key type in C_SignInit/C_VerifyInit to prevent crash#854

Open
mingulov wants to merge 1 commit intosofthsm:mainfrom
mingulov:fix/sign-init-key-type-crash
Open

fix: check key type in C_SignInit/C_VerifyInit to prevent crash#854
mingulov wants to merge 1 commit intosofthsm:mainfrom
mingulov:fix/sign-init-key-type-crash

Conversation

@mingulov
Copy link
Copy Markdown

@mingulov mingulov commented Mar 23, 2026

Passing a wrong asymmetric key type (e.g. EC key) to a mismatched mechanism (for example RSA related) caused a crash (segfault or abort) because the code tried to read RSA attributes from an EC key object and passed invalid data to OpenSSL.

Add key type validation after the mechanism switch in both functions, returning CKR_KEY_TYPE_INCONSISTENT on mismatch. Also convert the GOST catch-all else branch to an explicit else-if(isGOST) check.

Regression tests use cross-matched asymmetric keys (EC key with RSA mechanisms, RSA key with ECDSA/EdDSA mechanisms) to verify the fix. Without the fix, C_SignInit accepts the wrong key type and the subsequent C_Sign crashes.

Summary by CodeRabbit

  • Bug Fixes

    • Strengthened key-type validation for sign/verify initialization, returning clear errors when a key and mechanism mismatch.
    • Clarified handling for GOST and ML-DSA mechanisms to ensure proper mechanism validation.
  • Tests

    • Added tests covering key-type mismatch scenarios for sign and verify initialization.

@mingulov mingulov requested a review from a team as a code owner March 23, 2026 09:32
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 23, 2026

📝 Walkthrough

Walkthrough

This PR updates asymmetric sign/verify initialization to fetch key type up-front, enforce per-mechanism key-type consistency (including explicit GOST handling), and adds tests asserting CKR_KEY_TYPE_INCONSISTENT is returned for mismatched mechanism/key-type pairs.

Changes

Cohort / File(s) Summary
Core Validation Logic
src/lib/SoftHSM.cpp
Refactored AsymSignInit and AsymVerifyInit to read CKA_KEY_TYPE early, introduce an isGOST flag, perform per-mechanism key-type checks before constructing algorithm objects, and return CKR_KEY_TYPE_INCONSISTENT on mismatch; adjusted final mechanism-invalid handling.
Test Coverage
src/lib/test/SignVerifyTests.cpp, src/lib/test/SignVerifyTests.h
Added testSignInitWrongKeyType and testVerifyInitWrongKeyType (and registered them) to verify C_SignInit/C_VerifyInit return CKR_KEY_TYPE_INCONSISTENT when mechanism and key type are mismatched; tests reset/init session, create mismatched keys, and assert expected error.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • jschlyter
  • bjosv

Poem

🐰 I sniffed the keys and checked their type,
Hopped through mechanisms, neat and ripe.
If RSA meets ECC by chance, I sigh—
I bounce it back with a friendly cry.
All matches purr; mismatches say goodbye.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main fix: adding key type validation in C_SignInit/C_VerifyInit to prevent crashes from mismatched key types.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/test/SignVerifyTests.cpp (1)

1290-1439: Optional: extract shared “wrong key type” assertion helper to reduce duplication.

Both new tests repeat the same mechanism-loop/assert logic; a small helper would keep future mechanism list updates in one place.

Refactor sketch
+static void assertInitWrongKeyType(
+	CK_SESSION_HANDLE hSession,
+	CK_OBJECT_HANDLE hKey,
+	const CK_MECHANISM_TYPE* mechs,
+	size_t mechCount,
+	CK_RV (*initFn)(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE))
+{
+	for (size_t i = 0; i < mechCount; i++)
+	{
+		CK_MECHANISM mechanism = { mechs[i], NULL_PTR, 0 };
+		CK_RV rv = initFn(hSession, &mechanism, hKey);
+		CPPUNIT_ASSERT(rv == CKR_KEY_TYPE_INCONSISTENT);
+	}
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/test/SignVerifyTests.cpp` around lines 1290 - 1439, Both tests
testSignInitWrongKeyType and testVerifyInitWrongKeyType duplicate the same
mechanism-loop/assert pattern; extract a small helper (e.g.,
assertInitReportsWrongKeyType) that takes a session handle, a mechanism type
array + count, a key handle and a pointer/enum to indicate whether to call
C_SignInit or C_VerifyInit, iterates the mechanisms, builds CK_MECHANISM, calls
the appropriate PKCS#11 init function (C_SignInit or C_VerifyInit) and asserts
CKR_KEY_TYPE_INCONSISTENT; move the mech arrays (rsaMechs, dsaMechs, ecdsaMechs)
to local/shared constants and replace the duplicated loops in
testSignInitWrongKeyType and testVerifyInitWrongKeyType with calls to this
helper, keeping calls to generateEC and generateRSA and existing key handles
(hEcPub/hEcPriv, hRsaPub/hRsaPriv) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/test/SignVerifyTests.cpp`:
- Around line 1290-1439: Both tests testSignInitWrongKeyType and
testVerifyInitWrongKeyType duplicate the same mechanism-loop/assert pattern;
extract a small helper (e.g., assertInitReportsWrongKeyType) that takes a
session handle, a mechanism type array + count, a key handle and a pointer/enum
to indicate whether to call C_SignInit or C_VerifyInit, iterates the mechanisms,
builds CK_MECHANISM, calls the appropriate PKCS#11 init function (C_SignInit or
C_VerifyInit) and asserts CKR_KEY_TYPE_INCONSISTENT; move the mech arrays
(rsaMechs, dsaMechs, ecdsaMechs) to local/shared constants and replace the
duplicated loops in testSignInitWrongKeyType and testVerifyInitWrongKeyType with
calls to this helper, keeping calls to generateEC and generateRSA and existing
key handles (hEcPub/hEcPriv, hRsaPub/hRsaPriv) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 47c75ed5-e53c-4a82-ad36-51d68e185e45

📥 Commits

Reviewing files that changed from the base of the PR and between 3e6e6c3 and ce64feb.

📒 Files selected for processing (3)
  • src/lib/SoftHSM.cpp
  • src/lib/test/SignVerifyTests.cpp
  • src/lib/test/SignVerifyTests.h

Copy link
Copy Markdown
Member

@bukka bukka left a comment

Choose a reason for hiding this comment

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

It looks good. I would just move it to the blocks below to save few comparisons...

Passing a wrong asymmetric key type (e.g. EC key) to a mismatched
mechanism (e.g. CKM_RSA_PKCS) caused a crash (segfault or abort)
because the code tried to read RSA attributes from an EC key object,
then passed invalid data to OpenSSL.

Add key type validation after the mechanism switch in both functions,
returning CKR_KEY_TYPE_INCONSISTENT on mismatch. Also convert the
GOST catch-all else branch to an explicit else-if(isGOST) check.
Move MLDSA check also - to be consistent with other checks.

Regression tests use cross-matched asymmetric keys (EC key with RSA
mechanisms, RSA key with ECDSA/EdDSA mechanisms) to verify the fix.
Without the fix, C_SignInit accepts the wrong key type and the
subsequent C_Sign crashes.
@mingulov mingulov force-pushed the fix/sign-init-key-type-crash branch from ce64feb to d7dd4f5 Compare March 28, 2026 17:17
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/SoftHSM.cpp (1)

4533-4676: Consider centralizing key-type validation mapping to reduce drift risk.

AsymSignInit and AsymVerifyInit now duplicate the same family checks (RSA/DSA/ECDSA/EDDSA/MLDSA/GOST). A small shared helper for expected key type per family would reduce maintenance risk in future mechanism additions.

Also applies to: 5631-5774

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/SoftHSM.cpp` around lines 4533 - 4676, Introduce a single helper that
maps an asymmetric family to its expected CK key type (e.g. CKK_RSA, CKK_DSA,
CKK_EC, CKK_EC_EDWARDS, CKK_ML_DSA, CKK_GOST) — e.g. CK_ULONG
expectedKeyTypeForAsymAlgo(AsymAlgo) — and call it from AsymSignInit and
AsymVerifyInit before creating the algorithm instance; replace each inline check
like "if (keyType != CKK_RSA)" / "if (keyType != CKK_DSA)" / "if (keyType !=
CKK_EC)" / "if (keyType != CKK_EC_EDWARDS)" / "if (keyType != CKK_ML_DSA)" / "if
(keyType != CKK_GOST)" with a single comparison against
expectedKeyTypeForAsymAlgo(...) (or return CKR_KEY_TYPE_INCONSISTENT when
mismatched), so the key-type validation logic is centralized and reused in both
AsymSignInit and AsymVerifyInit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/SoftHSM.cpp`:
- Around line 4533-4676: Introduce a single helper that maps an asymmetric
family to its expected CK key type (e.g. CKK_RSA, CKK_DSA, CKK_EC,
CKK_EC_EDWARDS, CKK_ML_DSA, CKK_GOST) — e.g. CK_ULONG
expectedKeyTypeForAsymAlgo(AsymAlgo) — and call it from AsymSignInit and
AsymVerifyInit before creating the algorithm instance; replace each inline check
like "if (keyType != CKK_RSA)" / "if (keyType != CKK_DSA)" / "if (keyType !=
CKK_EC)" / "if (keyType != CKK_EC_EDWARDS)" / "if (keyType != CKK_ML_DSA)" / "if
(keyType != CKK_GOST)" with a single comparison against
expectedKeyTypeForAsymAlgo(...) (or return CKR_KEY_TYPE_INCONSISTENT when
mismatched), so the key-type validation logic is centralized and reused in both
AsymSignInit and AsymVerifyInit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0d500499-19c2-48d1-83de-ad889c7b5ea3

📥 Commits

Reviewing files that changed from the base of the PR and between ce64feb and d7dd4f5.

📒 Files selected for processing (3)
  • src/lib/SoftHSM.cpp
  • src/lib/test/SignVerifyTests.cpp
  • src/lib/test/SignVerifyTests.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/test/SignVerifyTests.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants