Skip to content

SC HSM PKA registration - #3833

Open
lrascao wants to merge 2 commits into
OpenSC:masterfrom
lrascao:sc-hsm-pka-registration
Open

lrascao wants to merge 2 commits into
OpenSC:masterfrom
lrascao:sc-hsm-pka-registration

Conversation

@lrascao

@lrascao lrascao commented Sep 17, 2026

Copy link
Copy Markdown

Two independent bugs on the SmartCard-HSM M-of-N public key registration path,
found while implementing the PKA challenge-response over PC/SC.

card-sc-hsm: fixed status word check when probing for a registered public key

verify_certificate() asks the card whether a CHR is already known and treats
6A88 ("referenced data not found") as "not yet — import it below". The guard
used && where || was meant:

if (apdu.sw1 != 0x6A && apdu.sw2 != 0x88) {

so any status whose SW1 was 0x6A or whose SW2 was 0x88 satisfied it.
6A82, for instance, fell through and the import was attempted against a card
that had reported something else entirely.

sc-hsm-tool: log in before registering a public key

The card requires an authenticated session before accepting a public key —
PUK_AUTH 'Add' checks the security status and fails otherwise.
register_public_key() never established one, so -g could not succeed
regardless of the file passed to it. This calls ensure_login() as the other
write operations in the tool already do, which also gives -g the same
--pin handling and interactive prompt as --unwrap-key and
--import-dkek-share. The man page entry gains the same --pin note those
options carry.

Testing

opensc-tool -n reports SmartCard-HSM version 6.6 and 6.4, but these are
Pico HSM (polhenarejos/pico-hsm), a compatible reimplementation rather
than genuine SmartCard-HSM hardware — flagging that explicitly, since the
driver name doesn't distinguish them.

Neither fix is reproducible end to end on this hardware, and I'd rather say so
than imply otherwise. Registration fails earlier for an unrelated reason: the
device CVC chain on these devices is self-signed, so verify_certificate()
cannot import it (the CHR is unknown, and selecting the issuer of a
self-signed CA selects itself). The && branch is therefore never reached
here, and the missing login is masked by that earlier failure.

Both are visible by inspection against the card's documented behaviour, and
the second is confirmed at the firmware level: pico-hsm's cmd_puk_auth
rejects Add unless has_session_pin || has_session_sopin.

Checklist
  • Documentation is added or updated
  • New files have a LGPL 2.1 license statement
  • PKCS#11 module is tested
  • Windows minidriver is tested
  • macOS token is tested

@lrascao lrascao changed the title S hsm pka registration SC HSM PKA registration Sep 17, 2026
@lrascao
lrascao force-pushed the sc-hsm-pka-registration branch from 0bb1231 to 9978169 Compare September 17, 2026 09:11
Comment thread src/libopensc/card-sc-hsm.c Outdated
Comment on lines +1491 to +1494
/* Only 6A88 ("referenced data not found") means the key is simply not
* known yet and may be imported below; any other status is an error.
* With && this rejected nothing whose SW1 was 0x6A or whose SW2 was
* 0x88, so e.g. 6A82 fell through and the import was attempted anyway. */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this comment should be in the commit message only. It does not add any useful context to the code, only to the change itself.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Agreed, moved to the commit message, and the remaining comment describes what
the check does rather than what it used to do.

Comment thread src/libopensc/card-sc-hsm.c Outdated
…blic key

verify_certificate() asks the card whether a CHR is already known and treats
"referenced data not found" as "not yet -- import it below". The guard compared
the raw status bytes with && where || was meant, so anything whose SW1 was 0x6A
or whose SW2 was 0x88 satisfied it: 6A82, for instance, fell through and the
import was attempted against a card that had reported something else entirely.

sc_check_sw() already maps 6A88 to SC_ERROR_DATA_OBJECT_NOT_FOUND, so test that
instead of the status bytes, and propagate the actual error rather than
SC_ERROR_UNKNOWN.
The card requires an authenticated session before it will accept a public key
for n-of-m authentication: PUK_AUTH 'Add' checks the security status and
fails otherwise. register_public_key() never established one, so -g could not
succeed regardless of the file passed to it.

Call ensure_login() as the other write operations in this tool already do,
which also gives -g the same --pin handling and interactive prompt as
--unwrap-key and --import-dkek-share.

Found while implementing the PKA challenge-response over PC/SC. Not
reproducible end to end on the hardware available to me, where registration
fails earlier because the device CVC chain is self-signed and cannot be
verified.
@lrascao
lrascao force-pushed the sc-hsm-pka-registration branch from 9978169 to e069133 Compare September 18, 2026 14:00
@lrascao

lrascao commented Sep 18, 2026

Copy link
Copy Markdown
Author

sorry for the force push but wanted to keep clean history

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.

3 participants