mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-31 19:08:28 +00:00
feat(core): Support pairing secret derivation from master key in prodtest.
[no changelog]
This commit is contained in:
parent
d933598df4
commit
0c5e71e973
@ -26,6 +26,7 @@
|
|||||||
#include <sec/optiga_commands.h>
|
#include <sec/optiga_commands.h>
|
||||||
#include <sec/optiga_transport.h>
|
#include <sec/optiga_transport.h>
|
||||||
#include <sec/secret.h>
|
#include <sec/secret.h>
|
||||||
|
#include <sec/secret_keys.h>
|
||||||
|
|
||||||
#include "aes/aes.h"
|
#include "aes/aes.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -57,8 +58,7 @@ typedef enum {
|
|||||||
OPTIGA_PAIRING_ERR_READ_FLASH,
|
OPTIGA_PAIRING_ERR_READ_FLASH,
|
||||||
OPTIGA_PAIRING_ERR_WRITE_FLASH,
|
OPTIGA_PAIRING_ERR_WRITE_FLASH,
|
||||||
OPTIGA_PAIRING_ERR_WRITE_OPTIGA,
|
OPTIGA_PAIRING_ERR_WRITE_OPTIGA,
|
||||||
OPTIGA_PAIRING_ERR_HANDSHAKE1,
|
OPTIGA_PAIRING_ERR_HANDSHAKE,
|
||||||
OPTIGA_PAIRING_ERR_HANDSHAKE2,
|
|
||||||
} optiga_pairing;
|
} optiga_pairing;
|
||||||
|
|
||||||
static optiga_pairing optiga_pairing_state = OPTIGA_PAIRING_UNPAIRED;
|
static optiga_pairing optiga_pairing_state = OPTIGA_PAIRING_UNPAIRED;
|
||||||
@ -89,11 +89,8 @@ static bool optiga_paired(cli_t* cli) {
|
|||||||
case OPTIGA_PAIRING_ERR_WRITE_OPTIGA:
|
case OPTIGA_PAIRING_ERR_WRITE_OPTIGA:
|
||||||
details = "failed to write pairing secret to Optiga";
|
details = "failed to write pairing secret to Optiga";
|
||||||
break;
|
break;
|
||||||
case OPTIGA_PAIRING_ERR_HANDSHAKE1:
|
case OPTIGA_PAIRING_ERR_HANDSHAKE:
|
||||||
details = "failed optiga_sec_chan_handshake 1";
|
details = "failed optiga_sec_chan_handshake";
|
||||||
break;
|
|
||||||
case OPTIGA_PAIRING_ERR_HANDSHAKE2:
|
|
||||||
details = "failed optiga_sec_chan_handshake 2";
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -148,23 +145,61 @@ static bool set_metadata(cli_t* cli, uint16_t oid,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static secbool initialize_secrets(void) {
|
||||||
|
#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
|
||||||
|
uint8_t secret[2 * SECRET_MASTER_KEY_SLOT_SIZE] = {0};
|
||||||
|
#else
|
||||||
|
uint8_t secret[OPTIGA_PAIRING_SECRET_SIZE] = {0};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Generate the pairing secret or master keys.
|
||||||
|
if (OPTIGA_SUCCESS != optiga_get_random(secret, sizeof(secret))) {
|
||||||
|
optiga_pairing_state = OPTIGA_PAIRING_ERR_RNG;
|
||||||
|
return secfalse;
|
||||||
|
}
|
||||||
|
random_xor(secret, sizeof(secret));
|
||||||
|
|
||||||
|
#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
|
||||||
|
// Store the master keys in the flash memory.
|
||||||
|
secbool ret = secret_key_set(SECRET_PRIVILEGED_MASTER_KEY_SLOT, secret,
|
||||||
|
SECRET_MASTER_KEY_SLOT_SIZE);
|
||||||
|
if (sectrue == ret) {
|
||||||
|
ret = secret_key_set(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
|
||||||
|
&secret[SECRET_MASTER_KEY_SLOT_SIZE],
|
||||||
|
SECRET_MASTER_KEY_SLOT_SIZE);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Store the pairing secret in the flash memory.
|
||||||
|
secbool ret =
|
||||||
|
secret_key_set(SECRET_OPTIGA_SLOT, secret, OPTIGA_PAIRING_SECRET_SIZE);
|
||||||
|
#endif
|
||||||
|
memzero(secret, sizeof(secret));
|
||||||
|
if (sectrue != ret) {
|
||||||
|
optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_FLASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void pair_optiga(cli_t* cli) {
|
void pair_optiga(cli_t* cli) {
|
||||||
uint8_t secret[32] = {0};
|
uint8_t pairing_secret[OPTIGA_PAIRING_SECRET_SIZE] = {0};
|
||||||
|
|
||||||
if (secret_key_get(SECRET_OPTIGA_SLOT, secret, sizeof(secret)) != sectrue) {
|
if (sectrue != secret_key_optiga_pairing(pairing_secret)) {
|
||||||
if (secret_key_writable(SECRET_OPTIGA_SLOT) != sectrue) {
|
if (sectrue != initialize_secrets()) {
|
||||||
// optiga pairing secret is unwritable, so fail
|
// optiga_pairing_state set by initialize_secrets().
|
||||||
optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_FLASH;
|
goto cleanup;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the pairing secret.
|
// Load the pairing secret from the flash memory.
|
||||||
if (OPTIGA_SUCCESS != optiga_get_random(secret, sizeof(secret))) {
|
if (sectrue != secret_key_optiga_pairing(pairing_secret)) {
|
||||||
optiga_pairing_state = OPTIGA_PAIRING_ERR_RNG;
|
optiga_pairing_state = OPTIGA_PAIRING_ERR_READ_FLASH;
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
random_xor(secret, sizeof(secret));
|
}
|
||||||
|
|
||||||
|
// Execute the handshake to verify that the secret is stored in Optiga.
|
||||||
|
if (OPTIGA_SUCCESS !=
|
||||||
|
optiga_sec_chan_handshake(pairing_secret, sizeof(pairing_secret))) {
|
||||||
// Enable writing the pairing secret to OPTIGA.
|
// Enable writing the pairing secret to OPTIGA.
|
||||||
optiga_metadata metadata = {0};
|
optiga_metadata metadata = {0};
|
||||||
metadata.change = OPTIGA_META_ACCESS_ALWAYS;
|
metadata.change = OPTIGA_META_ACCESS_ALWAYS;
|
||||||
@ -174,43 +209,25 @@ void pair_optiga(cli_t* cli) {
|
|||||||
false); // Ignore result.
|
false); // Ignore result.
|
||||||
|
|
||||||
// Store the pairing secret in OPTIGA.
|
// Store the pairing secret in OPTIGA.
|
||||||
if (OPTIGA_SUCCESS != optiga_set_data_object(OID_KEY_PAIRING, false, secret,
|
if (OPTIGA_SUCCESS != optiga_set_data_object(OID_KEY_PAIRING, false,
|
||||||
sizeof(secret))) {
|
pairing_secret,
|
||||||
|
sizeof(pairing_secret))) {
|
||||||
optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_OPTIGA;
|
optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_OPTIGA;
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the handshake to verify that the secret was stored correctly in
|
// Execute the handshake to verify that the secret is stored in Optiga.
|
||||||
// Optiga.
|
if (OPTIGA_SUCCESS !=
|
||||||
if (OPTIGA_SUCCESS != optiga_sec_chan_handshake(secret, sizeof(secret))) {
|
optiga_sec_chan_handshake(pairing_secret, sizeof(pairing_secret))) {
|
||||||
optiga_pairing_state = OPTIGA_PAIRING_ERR_HANDSHAKE1;
|
optiga_pairing_state = OPTIGA_PAIRING_ERR_HANDSHAKE;
|
||||||
return;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the pairing secret in the flash memory.
|
|
||||||
if (sectrue != secret_key_set(SECRET_OPTIGA_SLOT, secret, sizeof(secret))) {
|
|
||||||
optiga_pairing_state = OPTIGA_PAIRING_ERR_WRITE_FLASH;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload the pairing secret from the flash memory.
|
|
||||||
memzero(secret, sizeof(secret));
|
|
||||||
if (sectrue != secret_key_get(SECRET_OPTIGA_SLOT, secret, sizeof(secret))) {
|
|
||||||
optiga_pairing_state = OPTIGA_PAIRING_ERR_READ_FLASH;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the handshake to verify that the secret is stored correctly in both
|
|
||||||
// Optiga and MCU flash.
|
|
||||||
optiga_result ret = optiga_sec_chan_handshake(secret, sizeof(secret));
|
|
||||||
memzero(secret, sizeof(secret));
|
|
||||||
if (OPTIGA_SUCCESS != ret) {
|
|
||||||
optiga_pairing_state = OPTIGA_PAIRING_ERR_HANDSHAKE2;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optiga_pairing_state = OPTIGA_PAIRING_PAIRED;
|
optiga_pairing_state = OPTIGA_PAIRING_PAIRED;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
memzero(pairing_secret, sizeof(pairing_secret));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user