Skip to content

Commit

Permalink
securechip: replace sign interface function with native Rust impl
Browse files Browse the repository at this point in the history
The securechip unsafe sign key slot in the ATECC608 was only used as
an alternative to adding firmware code for signing using hte NIST
P-256 curve.

The Optiga Trust M does not support the same functionality - one can't
write a private key to this chip and extract the corresponding pubkey.

Since we want one interface for both chips, we remove the unsafe sign
functionality and replace it with the Rust p256 crate.

It is only used in U2F.

As an alternative, one could use the native MCU PUKCC/PUKCL feature to
derive a pubkey and sign using this curve (see pukcc.c), but I could
not get it to work. Using the Rust crate is much easier to implement /
use.

This adds 10592 bytes of binary space. If we need it back, we should
try again to use PUKCC instead and offload these operations to the
MCU.
  • Loading branch information
benma committed Dec 3, 2024
1 parent 5ce4a18 commit ffd218c
Show file tree
Hide file tree
Showing 372 changed files with 58,846 additions and 1,701 deletions.
69 changes: 0 additions & 69 deletions src/atecc/atecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ typedef enum {
ATECC_SLOT_ROLLKEY = 3,
ATECC_SLOT_KDF = 4,
ATECC_SLOT_ATTESTATION = 5,
ATECC_SLOT_ECC_UNSAFE_SIGN = 6,
ATECC_SLOT_DATA0 = 9,
// The other slots are currently not in use.
} atecc_slot_t;
Expand Down Expand Up @@ -631,74 +630,6 @@ bool atecc_random(uint8_t* rand_out)
return false;
}

// Length of priv_key must be 32 bytes
static bool _ecc_write_priv_key(const uint8_t* priv_key)
{
uint8_t atca_priv_key[36] = {0};
memcpy(atca_priv_key + 4, priv_key, 32);

uint8_t encryption_key[32] = {0};
UTIL_CLEANUP_32(encryption_key);
_interface_functions->get_encryption_key(encryption_key);

uint8_t nonce_contribution[32] = {0};
UTIL_CLEANUP_32(nonce_contribution);
_interface_functions->random_32_bytes(nonce_contribution);
#if NONCE_NUMIN_SIZE > 32
#error "size mismatch"
#endif

ATCA_STATUS result = _authorize_key();
if (result != ATCA_SUCCESS) {
return false;
}

return atcab_priv_write(
ATECC_SLOT_ECC_UNSAFE_SIGN,
atca_priv_key,
ATECC_SLOT_ENCRYPTION_KEY,
encryption_key,
nonce_contribution) == ATCA_SUCCESS;
}

bool atecc_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key)
{
if (!_ecc_write_priv_key(priv_key)) {
return false;
}

ATCA_STATUS result = _authorize_key();
if (result != ATCA_SUCCESS) {
return false;
}

result = atcab_get_pubkey(ATECC_SLOT_ECC_UNSAFE_SIGN, pub_key);
if (result != ATCA_SUCCESS) {
return false;
}

return true;
}

bool atecc_ecc_unsafe_sign(const uint8_t* priv_key, const uint8_t* msg, uint8_t* sig)
{
if (!_ecc_write_priv_key(priv_key)) {
return false;
}

ATCA_STATUS result = _authorize_key();
if (result != ATCA_SUCCESS) {
return false;
}

result = atcab_sign(ATECC_SLOT_ECC_UNSAFE_SIGN, msg, sig);
if (result != ATCA_SUCCESS) {
return false;
}

return true;
}

#if APP_U2F == 1 || FACTORYSETUP == 1
// Read a "standard" sized block from a data slot (must be 32 bytes)
static bool _read_data_slot_block(uint8_t* bytes, uint16_t slot, uint8_t block)
Expand Down
18 changes: 0 additions & 18 deletions src/atecc/atecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,24 +98,6 @@ USE_RESULT bool atecc_monotonic_increments_remaining(uint32_t* remaining_out);
*/
USE_RESULT bool atecc_random(uint8_t* rand_out);

/**
* Generates the matching public key to the provided private key. Will put private key in unsafe
* ECC slot.
* @param[in] priv_key Private key (32 bytes).
* @param[out] pub_key Public key. Format will be the X and Y coordinates in big-endian (64 bytes).
* @return True if success
*/
USE_RESULT bool atecc_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key);

/**
* Sign hash with private key. Will put private key in unsafe ECC slot.
* @param[in] priv_key Private key to use for signing (32 bytes)
* @param[in] msg Message to sign (32 bytes)
* @param[out] sig Signature (64 bytes)
* @return True if success
*/
USE_RESULT bool atecc_ecc_unsafe_sign(const uint8_t* priv_key, const uint8_t* msg, uint8_t* sig);

#if APP_U2F == 1 || FACTORYSETUP == 1
/**
* Set the u2f counter to `counter`. Should only be used for initialization.
Expand Down
138 changes: 136 additions & 2 deletions src/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/rust/bitbox02-rust-c/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bitbox02-rust = { path = "../bitbox02-rust", optional = true }
bitbox02 = { path = "../bitbox02", optional = true }
bitbox02-noise = { path = "../bitbox02-noise", optional = true }
util = { path = "../util" }
p256 = { version = "0.13.2", default-features = false, features = ["arithmetic", "ecdsa"] }
hex = { workspace = true }
sha2 = { workspace = true, optional = true }
sha3 = { workspace = true, optional = true }
Expand Down
3 changes: 3 additions & 0 deletions src/rust/bitbox02-rust-c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ mod sha2;
#[cfg(feature = "firmware")]
mod workflow;

#[cfg(feature = "firmware")]
mod p256;

// Whenever execution reaches somewhere it isn't supposed to rust code will "panic". Our panic
// handler will print the available information on the screen. If we compile with `panic=abort`
// this code will never get executed.
Expand Down
Loading

0 comments on commit ffd218c

Please sign in to comment.