Signing is always done with first key when label is supplied to pkcs11-tool

When I try to sign a SHA with
pkcs11-tool.exe --sign --input-file tempfile.sha -m ECDSA --output-file signature.bin -v --label {private_key_label}
The SHA is always signed with the first key stored on the HSM.

it works fine when using:
pkcs11-tool.exe --sign --input-file tempfile.sha -m ECDSA --output-file signature.bin -v --id {private_key_id}

As a workaround I first lookup the ID of the label and use the latter command line.

We want to use the espressif idf.py / espsecure.py tool to sign our code with the HSM but this is not possible as for this tooling you need to supply the label and not the ID

The following applies to PKCS#11 tokens in general, not just the Nitrokey HSM. Any well-behaved PKCS#11 token would show the behaviour that you describe.

The PKCS#11 standard does not require labels (CKA_LABEL) to be unique. It’s perfectly permissable to have multiple objects with the same label on a PKCS#11 token. In practice, you often have 3 objects with the same label: a public key, private key, and a certificate. (These objects have different classes, so they are still distinguishable.)

As far as PKCS#11 is concerned, it is the responsibility of you as the operator to make sure that you have a proper naming scheme for labeling your objects.

PKCS#11 gives you this flexibility/power, at the risk of giving you the ability to shoot yourself in the foot. Whether this is a good idea from a standards perspective is another question. But here we are.

If you got yourself into a state where two private key objects have the same label:

pkcs11-tool is a basic tool that doesn’t expose the full power of the PKCS#11 API (pkcs11.h). I can understand how the authors simplified their life to always select the first object. So you will need another way to select the “right” object. This can be the CKA_ID, like you mentioned. If all else fails (e.g., if CKA_ID is not set), you will have to write custom code that calls the PKCS#11 API and iterates over both/all objects and figures out which is the right one. Here the scope of pkcs11-tool ends.

As to how to get yourself out of this situation:

In theory, if an object was created with CKA_MODIFIABLE=true, you may be able to change the label to something else. But 1) chances are that your objects are CKA_MODIFIABLE=false and 2) pkcs11-tool does not implement the ability to modify attributes afaik, so you need to write custom code.
The easiest way is to delete your object(s) with pkcs11-tool and start again. This time, choose unique labels!

The labels are unique otherwise my workaround to lookup the ID for the label also wouldn’t work. Yes maybe the private key, public key and certificate have the same label but signing with a certificate or public key doesn’t make sense. It now always used the first private key on the HSM and seems completely ignoring the label name.

It now always used the first private key on the HSM and seems completely ignoring the label name.

Ah, I misunderstood your question. I thought (or mentally auto-completed) that you meant the first key on HSM from a set of keys having the same label.

Completely ignoring the label should indeed not happen.

The pkcs11-tool from OpenSC does not support selecting the signing key by label. You need to specify the key id (CKA_ID), as this is unique. The label can be assigned to multiple objects.

If no id is specified, the first key is used.

The PKCS#11 interface does support selecting objects by filter. You can include CKA_LABEL in the search template to locate the object.