Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

securechip: add initial Optiga implementation #1341

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

benma
Copy link
Collaborator

@benma benma commented Dec 12, 2024

This commit implements the securechip.h interface for the Optiga Trust M V3, with an interface and configuration roughly corresponding to how we use the ATECC608 secure chip:

  • A KDF key that is internally generated and cannot be read and written from the host MCU
  • A KDF key that is generated on the host
  • A monotonic counter attached to the first KDF key which limits the maxmium number of uses of the key over the lifetime of the device
  • Attestation key that is internally generated and used to sign attestation challenges

The factory setup configures the metadata of each object we use, setting the state to Operational. After this, metadata cannot be changed, and the access conditions apply as specified.

Shielded communication encrypts the communication with the chip and is active and enforced through the metadata access configs. It roughly corresponds to IO protection in the ATECC608.

In the ATECC608, we additionally authorize each command with the authorization_key, another pre-shared secret. The Optiga offers the same functionality, but we don't use it to authorize all commands, as it is redundant to using the shielded communication in terms of enabling the host MCU to execute commands.

@benma benma force-pushed the optiga branch 4 times, most recently from 5fb80cd to 8fcc0b9 Compare December 12, 2024 12:57
@benma benma requested a review from NickeZ December 12, 2024 13:32
@benma benma marked this pull request as ready for review December 12, 2024 13:32
@benma benma closed this Dec 12, 2024
@benma benma reopened this Dec 12, 2024
@benma benma mentioned this pull request Dec 12, 2024
@benma benma force-pushed the optiga branch 6 times, most recently from 18c858a to 100a9da Compare December 16, 2024 13:29
src/atecc/atecc.h Outdated Show resolved Hide resolved
src/optiga/pal/pal_os_lock.c Outdated Show resolved Hide resolved
@NickeZ
Copy link
Collaborator

NickeZ commented Dec 30, 2024

You have two spelling mistakes in the commit message: "An KDF" and "reundnant".

@benma benma force-pushed the optiga branch 2 times, most recently from ee352dc to 0017ef2 Compare December 30, 2024 09:23
@benma
Copy link
Collaborator Author

benma commented Dec 30, 2024

You have two spelling mistakes in the commit message: "An KDF" and "reundnant".

Thx, fixed.

Copy link
Collaborator

@NickeZ NickeZ left a comment

Choose a reason for hiding this comment

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

First round of review, I still need to go through the config and test the firmware.

// Factory setup will be performed in the normal firmware, which makes it easier to tinker with the
// chip setup and config.
// Must be 0 for the production firmware releases.
#define FACTORY_DURING_PROD 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be a cmake option, i.e. cd build; cmake .. -DFACTORY_DURING_PROD=1? So that you don't have to change a file and risk committing it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Doesn't that just shift the risk of committing it in the Makefile? The cmake option seems involved, as then I'd need to turn it into a compile definition too.

What about just removing the variable once the config is final?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I wouldn't have a shortcut in the Makefile. You would have to manually type the cmake command to set up such a project. Or you could have a new shortcut like make firmware-with-factory-setup.

You can just remove it. I can flash the factor-setup instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Okay - I'll keep a local patch to use it for my own development then, unless you think it's okay to keep this until the config is final and remove it then.

src/optiga/optiga.c Outdated Show resolved Hide resolved
src/optiga/optiga.c Outdated Show resolved Hide resolved
src/optiga/optiga.c Outdated Show resolved Hide resolved
src/optiga/optiga.c Outdated Show resolved Hide resolved
// not present.
static bool _read_lcso(const uint8_t* metadata, size_t metadata_len, uint8_t* lcso_out)
{
uint8_t tag_data[100] = {0};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this buffer 100 bytes long when LCSO is 1 byte?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

My initial reaction was because we can't guarantee the chip or the library will not return more, so it would be UB. Then I realized the same is true for 100, so I now actually pass the input data length and do a size check before writing to the buffer. See the diff.

src/optiga/optiga.c Show resolved Hide resolved
src/optiga/optiga.c Show resolved Hide resolved
bool optiga_gen_attestation_key(uint8_t* pubkey_out)
{
ABORT_IF_NULL(_crypt);
optiga_key_id_t slot = OPTIGA_KEY_ID_E0F1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

should this define be OID_ATTESTATION?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought it would be proper to use the enum optiga_key_id_t as defined:

https://github.com/BitBoxSwiss/optiga-trust-m/blob/5b924c8615f563334136d5a84431f1682cfce3ea/include/common/optiga_lib_common.h#L67

Then it's clear we are not passing in something invalid.

uint8_t sig_der[70] = {0};
uint16_t sig_der_size = sizeof(sig_der);
optiga_lib_status_t res = _optiga_crypt_ecdsa_sign_sync(
_crypt, challenge, 32, OPTIGA_KEY_ID_E0F1, sig_der, &sig_der_size);
Copy link
Collaborator

Choose a reason for hiding this comment

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

same here, should this be OID_ATTESTATION?

@benma benma force-pushed the optiga branch 3 times, most recently from e5bfb97 to 0d8a0e3 Compare January 7, 2025 11:38
benma and others added 2 commits January 7, 2025 12:40
This commit implements the securechip.h interface for the Optiga Trust
M V3, with an interface and configuration roughly corresponding to how
we use the ATECC608 secure chip:

- A KDF key that is internally generated and cannot be read and
written from the host MCU
- A KDF key that is generated on the host
- A monotonic counter attached to the first KDF key which limits the
  maxmium number of uses of the key over the lifetime of the device
- Attestation key that is internally generated and used to sign
  attestation challenges

The factory setup configures the metadata of each object we use,
setting the state to Operational. After this, metadata cannot be
changed, and the access conditions apply as specified.

Shielded communication encrypts the communication with the chip and is
active and enforced through the metadata access configs. It roughly
corresponds to IO protection in the ATECC608.

In the ATECC608, we additionally authorize each command with the
authorization_key, another pre-shared secret. The Optiga offers the
same functionality, but we don't use it to authorize all commands, as
it is redundant to using the shielded communication in terms of
enabling the host MCU to execute commands.

Co-Authored-By: Niklas <[email protected]>
To disable interrupts when processing Optiga commands.
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