Skip to content

feat: tedge cert create-key-hsm command#3709

Merged
Bravo555 merged 1 commit intothin-edge:mainfrom
Bravo555:feat/pkcs11-create-key
Nov 5, 2025
Merged

feat: tedge cert create-key-hsm command#3709
Bravo555 merged 1 commit intothin-edge:mainfrom
Bravo555:feat/pkcs11-create-key

Conversation

@Bravo555
Copy link
Copy Markdown
Member

@Bravo555 Bravo555 commented Jun 26, 2025

TODO

  • handle all supported keys (EC 256/384, RSA 2048/3072/4096)
  • allow selecting token, key label, key type and size using command line arguments
  • write a test to maintain compatibility with 1.5.1
  • figure out why p11tool sometimes doesn't print curve ids of EC keys added to module documentation
  • see if we can remove added dependencies
  • generate URI for the new key so the user can replace the entire URI instead of tweaking parts
  • don't generate CSR in create-key, do it in tedge cert download
  • cleanup
  • rename to create-key-pkcs11
  • allow user-provided ID and warn if object with such ID already exists
  • add --pin flag
  • add --outfile-pubkey flag

Follow-up

  • show more information after key is created
  • test failure modes

Proposed changes

Implements a tedge cert create-key command that can be used to create a private key on a PKCS11 token without additional tools.

tedge cert create-key generates the new keypair on the PKCS11 token and prints the URI of the newly created keypair. The user then needs to put this URI as their device.key_uri setting to use the key:

New keypair was successfully created.
Key URI: pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=a30ed1ca6244fc5f;token=test-token;id=%51%05%87%75%6F%B7%28%EC%5E%5D%1F%B8%EB%CF%FD%96%B7%E4%28%B6;object=my-key
Public key:
-----BEGIN PUBLIC KEY-----
BEsjmiXDdko90IDdjlAb/bWyTf6kd6S+/KPlj2Yd3zjHZe54evLyHJ1e8dSDhpy7
2Tcml9ZcHWBHA+MM0NFAbaw=
-----END PUBLIC KEY-----


Value of `device.key_uri` was updated to point to the new key

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Improvement (general improvements like code refactoring that doesn't explicitly fix a bug or add any new functionality)
  • Documentation Update (if none of the other choices apply)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Paste Link to the issue

#3665

Checklist

  • I have read the CONTRIBUTING doc
  • I have signed the CLA (in all commits with git commit -s. You can activate automatic signing by running just prepare-dev once)
  • I ran just format as mentioned in CODING_GUIDELINES
  • I used just check as mentioned in CODING_GUIDELINES
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Further comments

@Bravo555 Bravo555 had a problem deploying to Test Pull Request June 26, 2025 08:58 — with GitHub Actions Failure
@Bravo555 Bravo555 self-assigned this Jun 26, 2025
@codecov
Copy link
Copy Markdown

codecov bot commented Jun 26, 2025

Codecov Report

❌ Patch coverage is 32.48588% with 239 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ates/extensions/tedge-p11-server/src/pkcs11/mod.rs 0.00% 91 Missing ⚠️
...rates/core/tedge/src/cli/certificate/create_key.rs 62.84% 62 Missing and 6 partials ⚠️
crates/core/tedge/src/cli/certificate/cli.rs 0.00% 31 Missing ⚠️
...es/extensions/tedge-p11-server/src/proxy/client.rs 0.00% 25 Missing ⚠️
...es/extensions/tedge-p11-server/src/proxy/server.rs 0.00% 23 Missing ⚠️
crates/common/certificate/src/lib.rs 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from 7d44718 to c2e2aa1 Compare June 27, 2025 07:55
@Bravo555 Bravo555 had a problem deploying to Test Pull Request June 27, 2025 07:56 — with GitHub Actions Failure
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from c2e2aa1 to 993fd82 Compare June 27, 2025 17:57
@Bravo555 Bravo555 had a problem deploying to Test Pull Request June 27, 2025 17:57 — with GitHub Actions Failure
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from 993fd82 to 64f3a6b Compare June 30, 2025 17:06
@Bravo555 Bravo555 had a problem deploying to Test Pull Request June 30, 2025 17:06 — with GitHub Actions Failure
@reubenmiller reubenmiller added the theme:hsm Hardware Security Module related topics label Jul 3, 2025
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from 64f3a6b to 525651b Compare July 4, 2025 13:10
@Bravo555 Bravo555 had a problem deploying to Test Pull Request July 4, 2025 13:10 — with GitHub Actions Failure
@Bravo555 Bravo555 temporarily deployed to Test Pull Request July 9, 2025 16:23 — with GitHub Actions Inactive
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from 3025528 to c638b40 Compare July 10, 2025 07:52
@Bravo555 Bravo555 temporarily deployed to Test Pull Request July 10, 2025 07:52 — with GitHub Actions Inactive
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jul 10, 2025

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
736 0 3 736 100 2h17m50.339294s

@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from c638b40 to c3959cd Compare July 11, 2025 08:49
@Bravo555 Bravo555 temporarily deployed to Test Pull Request July 11, 2025 08:49 — with GitHub Actions Inactive
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from c3959cd to e099533 Compare July 14, 2025 14:31
@Bravo555 Bravo555 temporarily deployed to Test Pull Request July 14, 2025 14:31 — with GitHub Actions Inactive
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from e099533 to fef773e Compare July 14, 2025 14:36
@Bravo555 Bravo555 temporarily deployed to Test Pull Request July 14, 2025 14:36 — with GitHub Actions Inactive
@Bravo555 Bravo555 had a problem deploying to Test Pull Request July 14, 2025 15:13 — with GitHub Actions Failure
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from 25fe73f to 629ccbe Compare July 14, 2025 15:16
@Bravo555 Bravo555 temporarily deployed to Test Pull Request July 14, 2025 15:16 — with GitHub Actions Inactive
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from 048f3f3 to 799e0c1 Compare September 15, 2025 20:58
@Bravo555 Bravo555 force-pushed the feat/pkcs11-create-key branch from 799e0c1 to 1e2357f Compare September 15, 2025 21:24
@Bravo555 Bravo555 temporarily deployed to Test Pull Request September 15, 2025 21:24 — with GitHub Actions Inactive
@Bravo555 Bravo555 marked this pull request as ready for review September 15, 2025 21:24
identify a key, but doesn't contain attributes that identify a token, still the first token will be
selected, even if another token contains the intended key.

## Key generation
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A general question, can this command be used without a HSM? It doesn't seem so as the help is more centered around the HSM and the TOKEN positional argument is mandatory (which doesn't make sense for a file based key).

# tedge cert create-key 
error: the following required arguments were not provided:
--label <LABEL>
--type <TYPE>

Usage: tedge cert create-key --label <LABEL> --type <TYPE> [TOKEN]

For more information, try '--help'.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Indeed this command only operates on the HSM, so we can change the naming to something like create-key-pkcs11 to make it clear.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Though having a command to create a file based private key would be beneficial as it would allow users to integrate more easily into existing PKI services.

Ideally it would be nice to have one single command but given that there are a few pkcs11 only argments, and don't want users to accidentally create a file based key when they were expecting to create a HSM based key...so with that, I'm ok with calling it the following (though I'm not super thrilled about the name, but I don't have a better suggestion).

tedge cert create-key-pkcs11

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

About the name: create-key-pkcs11:

  • Why pkcs11, while elsewhere we use the term cryptoki?
  • Wouldn't create-pkcs11-key be better?
  • Personally, I would suggest create-hsm-key, but this introduces yet another acronym.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don’t mind HSM as it is more user friendly (even with the additional acronym)

Copy link
Copy Markdown
Member Author

@Bravo555 Bravo555 Oct 28, 2025

Choose a reason for hiding this comment

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

renamed to create-key-hsm in 458dc11

Why pkcs11, while elsewhere we use the term cryptoki

I've seen both terms used somewhat interchangably and haven't made an effort to only use one of them for consistency and also used both :/
Looking back, PKCS #11 is the name of the standard, and Cryptoki is the name of the interface defined by the standard.

Wouldn't create-pkcs11-key be better?

I view it as create-key-hsm being an HSM-specific variant of create-key, and if we add a generic create-key command in the future, the suffixed version fits better.
So decided to go with create-key-hsm.

key object.

```sh
tedge cert create-key --type ecdsa --curve 256 --label my-key
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is way too easy to accidentally create too many keys. This will create two private key objects where both have the token=tedge attribute set

tedge cert create-key --type ecdsa --label tedge "pkcs11:token=tedge"
tedge cert create-key --type ecdsa --label tedge "pkcs11:token=tedge"

But if the user tries to prevent duplications by providing an id attribute, the id attribute is ignored.

tedge cert create-key --type ecdsa --label tedge 'pkcs11:token=tedge;id=other'

Is there a way we can prevent the user from accidentally doing this? e.g. can we check if the key_uri already exists or something before creating another key (similar to how the tedge cert create would fail again if you run it twice)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A random id is generated such that when running the command twice, with the same parameters, the returned URI will be different.

The TOKEN positional argument is a URI identifying the token, while id attribute is related to objects on the token, so it's not relevant and thus ignored.

We could allow user to provide their id attribute for the key via --id flag, but it's not going to prevent them from making duplicates, but will allow them to make duplicates.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Though we're talking about creating a key for tedge to use, so it should check first if the device.key_uri in the tedge.toml exists, and only create a new key if nothing is found (and ideally use the value defined in the tedge.toml)

Comment on lines +277 to +278
--label <LABEL>
Human readable description (CKA_LABEL attribute) for the key
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would it also make sense to also allow the user to control the private key's id attribute (in addition to the label)? Would this make it easier for user to identify the unique object?

tedge cert create-key --label tedge --id '3'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We could allow the user to set it, but it would allow the user to generate objects that are not unique and have the same id. Handling these object after could get tricky, particularly p11tool gets confused when operating on objects that have the same URI.

What we do now is generate a random id which we include in the URI, so the object is always unique.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So PKCS11 doesn't reject an object which is created with the same ID? I would of expected that the API would fail somewhere. Plus I would assume that the id would not be globally unique, but only unique within the label (or token).

I still think it is worthwhile allow power-users to set the id value, and then use an autogenerated id by default (though something a bit shorter than the current generation would be nice).

Copy link
Copy Markdown
Contributor

@didier-wenzek didier-wenzek left a comment

Choose a reason for hiding this comment

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

From my point of view this PR is ready to be merged with one important exception: a new version must be added to the tedge-p11-server protocol to handle the requests added here. What is not clear to me is what is the more appropriate option: to add version support to this PR or in a separate fix for #3832?

Comment on lines +237 to +239
let Frame1::CreateKeyResponse(pubkey) = response else {
bail!("protocol error: bad response, expected create_key, received: {response:?}");
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One needs to properly handle the case where the server has not been updated and is not able to create a key. Nothing more can be done than failing the command, but the error message must be explicit and not user-puzzling as currently.

// practice, this only occurs with a client calls TedgeP11Client::with_ready_check.
Frame1::Ping => Frame1::Pong,

Frame1::CreateKeyRequest(request) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This must explicitly be a new version.

Suggested change
Frame1::CreateKeyRequest(request) => {
Frame2::CreateKeyRequest(request) => {

Comment on lines +100 to +103
CreateKeyRequest(CreateKeyRequest),
CreateKeyResponse(CreateKeyResponse),
GetTokensUrisRequest,
GetTokensUrisResponse(Vec<String>),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This must added into a new Frame::Version1(Frame1) case.

@didier-wenzek
Copy link
Copy Markdown
Contributor

From my point of view this PR is ready to be merged with one important exception: a new version must be added to the tedge-p11-server protocol to handle the requests added here. What is not clear to me is what is the more appropriate option: to add version support to this PR or in a separate fix for #3832?

After an offline discussion with @reubenmiller, we agreed to address the version issue in a follow-up PR.

Copy link
Copy Markdown
Contributor

@didier-wenzek didier-wenzek left a comment

Choose a reason for hiding this comment

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

Approved. Thank you for your sustained efforts in implementing the last missing piece of thin-edged HSM support.

Copy link
Copy Markdown
Contributor

@reubenmiller reubenmiller left a comment

Choose a reason for hiding this comment

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

Approved

Signed-off-by: Marcel Guzik <marcel.guzik@cumulocity.com>
@Bravo555
Copy link
Copy Markdown
Member Author

Bravo555 commented Nov 4, 2025

Integration tests consistently get stuck at Tests.Tedge Flows.Tedge Flows, so PR can't be merged.
This should be fixed by #3846, so I'll try merging again after that PR is merged.

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

Labels

theme:hsm Hardware Security Module related topics

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tedge cert create should support creating a key via the tedge-p11-server

3 participants