Skip to content

HMAC cleanup fixes - #135

Closed
is-alnilam wants to merge 4 commits into
eclipse-keypont:masterfrom
is-alnilam:hmac_cleanup_fixes
Closed

HMAC cleanup fixes#135
is-alnilam wants to merge 4 commits into
eclipse-keypont:masterfrom
is-alnilam:hmac_cleanup_fixes

Conversation

@is-alnilam

Copy link
Copy Markdown

Proposed Changes

While reviewing HMAC error paths, I started looking into the way that errors are returned from Sum(). This can only panic, due to the Go APIs. I was looking into how best to recover from that when I spotted a leak of the session handle. As HMAC is a multi-step process, errors can occur at points where the existing cleanup function isn't called—this change closes those gaps.

This change does introduce the possibility that cleanup will be called twice, which would cause the session to be returned to the pool twice. This is guarded against by adding a test for hi.session == nil at the start of cleanup.

When testing, I also spotted that the tests didn't run on SoftHSM, as there's a comment that SoftHSM doesn't support HMAC. I'm not sure if this relates to an older version of SoftHSM? Current versions do support HMAC (I'm using it in production), so I removed this guard.

That then exposed a bug in symmetric.go where the fallback from a specific key type to a generic key wasn't being allowed as the particular return type didn't match the code's expectations—it turns out that I've been working around this at the application layer without realising what the issue was. I've checked the return values given by SoftHSM and the Utimaco HSM simulator and have updated the check to work with both of those, as well as the previous nShield and CloudHSM values. (My workaround was to copy the CipherHMACSHA384 definition into my code, but to remove the first entry in the GenParams list, leaving only the generic secret option.)

Types of Changes

Bugfix

Verification

New and updated test cases cover the majority of the functionality. For the 'mid process' error case, though, this is difficult to test and will probably have to be left as just reviewed.

Testing

I've updated the HMAC tests to cover cases where my changes may have changed behaviour (or could trigger problems). I've not been able to test the specific leak, as to do wo would need a way to inject faults into the HSM session and I'm not sure how/if that can be done.

I've also updated the general HMAC tests (as mentioned above) to allow testing from SoftHSM. As well as enabling the tests and fixing the bug on mechanism fallback, I've also moved the 'full' test flag from the truncated 'general' HMAC (which isn't supported on SoftHSM) onto the full SHA256 HMAC, which should be supported everywhere.

Tests have been run against SoftHSM and Utimaco HSM simulator—I may be able to test against CloudHSM in a few days.

Linked Issues

User-Facing Change

In very rare cases, the HSM session could leak during HMAC operations.

Exported HMAC key definitions (e.g. `CipherHMACSHA384`) will now work as expected on SoftHSM and Utimaco HSMs.

Further Comments

The precise trigger for the errors investigation was CloudHSM—an HSM in the cluster can be removed at any time, creating a need to retry any operations which were in progress at the time. Retrying signing was easy enough, but HMAC is more difficult due to the Go APIs and the lack of an error return (just the panic). This then led to digging further and spotting the potential for a leak.

The HMAC algorithm involves multiple calls to the PKCS#11 API. If it
fails half-way through, a session can be leaked.

This change ensures that the call to 'cleanup' is always made, and also
ensures that this call is safe to call twice by adding a guard to check
if the session ID has been cleared, signalling that the session has
already been returned once to the pool. Without this test, a session
might be returned twice (which could panic as the pool is oversize, or
would corrupt the pool by adding the same session handle twice).

The guard is needed rather than using Put(hi.session) as a nil would
create a new session and increase the size of the pool, leaking the old
session.
SoftHSM (now?) supports the HMAC mechanisms, so the unconditional skip
is unnecessary. The hash-independent subtests (Empty/MultiSum/Reset)
move to the plain SHA256 case so they run on SoftHSM; the _GENERAL cases
have no SoftHSM equivalent and skip themselves via
skipIfMechUnsupported.

MultiSum now exercises the post-Sum errHmacClosed guard against a real
token.
GenerateSecretKeyWithAttributes tries vendor-specific
CKM_NC_*_HMAC_KEY_GEN before the generic-secret fallback, but only
advanced to the next mechanism on CKR_TEMPLATE_INCONSISTENT or
CKR_ATTRIBUTE_VALUE_INVALID. SoftHSM rejects the unknown nShield
mechanism with CKR_MECHANISM_INVALID, so HMAC key generation failed
outright there rather than falling back. Add that code to the
fall-through set.

Also fix the operator precedence: `ok && A || B` parsed as `(ok && A) ||
B`, so a nil-or-wrong-type error could still match the second branch.
@Nicolas-Peiffer

Copy link
Copy Markdown
Contributor

Hi @is-alnilam 😃 , TY 🙏 for your interest and this PR.

In 2026 the big project for crypto11 is to add the support of PKCS#11 v3.2 and the support of the ML-KEM PQC algorithm:

The other big project for 2026 is giving + moving the crypto11 project under the Eclipse Foundation.

This is an opportunity for us to fix bugs like yours before releasing the new version !

On our current branch pkcs11-v3.2-ml-kem, we implemented a revision of you fix at 02c2ba8 with the help of LLM code assistant.

You are very welcome to try one of our crypto11@v2 release candidate like for example crypto11@v2.0.0-rc3. Tell us if this fixes your issue.

Your PR is mentioned in the commit 02c2ba8 and in

- Ported an upstream fix (ThalesGroup PR #135): HMAC sessions were leaked on mid-operation error

We are considering adding a file CONTRIBUTORS.md. If you are interested, we can add your name to a contributor "hall of fame" file.

@Nicolas-Peiffer Nicolas-Peiffer self-assigned this Aug 3, 2026
@Nicolas-Peiffer Nicolas-Peiffer added this to the v2.0.0 milestone Aug 3, 2026
@Nicolas-Peiffer Nicolas-Peiffer added the security Security related issue label Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement security Security related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants