mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-08-01 19:38:33 +00:00
feat(core): Implement derivation from master key in secret API.
[no changelog]
This commit is contained in:
parent
32c4d9f105
commit
d933598df4
@ -21,12 +21,14 @@
|
||||
|
||||
#define SECRET_NUM_KEY_SLOTS 3
|
||||
|
||||
#define SECRET_MASTER_KEY_SLOT_SIZE 0x20
|
||||
|
||||
// first page: static
|
||||
#define SECRET_HEADER_OFFSET 0x00
|
||||
#define SECRET_HEADER_LEN 0x10
|
||||
|
||||
#define SECRET_KEY_SLOT_0_OFFSET 0x10
|
||||
#define SECRET_KEY_SLOT_0_LEN 0x20
|
||||
#define SECRET_KEY_SLOT_0_LEN SECRET_MASTER_KEY_SLOT_SIZE
|
||||
|
||||
#define SECRET_MONOTONIC_COUNTER_0_OFFSET 0x30
|
||||
#define SECRET_MONOTONIC_COUNTER_0_LEN 0x400
|
||||
@ -35,7 +37,8 @@
|
||||
#define SECRET_MONOTONIC_COUNTER_1_LEN 0x400
|
||||
|
||||
#define SECRET_KEY_SLOT_1_OFFSET 0x830
|
||||
#define SECRET_KEY_SLOT_1_LEN 0x20
|
||||
#define SECRET_KEY_SLOT_1_LEN SECRET_MASTER_KEY_SLOT_SIZE
|
||||
#define SECRET_KEY_SLOT_1_PUBLIC 1
|
||||
|
||||
#define SECRET_KEY_SLOT_2_OFFSET 0x850
|
||||
#define SECRET_KEY_SLOT_2_LEN 0x20
|
||||
@ -46,6 +49,6 @@
|
||||
#define SECRET_BHK_LEN 0x20
|
||||
|
||||
// slot assignments
|
||||
#define SECRET_OPTIGA_SLOT 0
|
||||
#define SECRET_TROPIC_TREZOR_PRIVKEY_SLOT 1
|
||||
#define SECRET_PRIVILEGED_MASTER_KEY_SLOT 0
|
||||
#define SECRET_UNPRIVILEGED_MASTER_KEY_SLOT 1
|
||||
#define SECRET_TROPIC_TROPIC_PUBKEY_SLOT 2
|
||||
|
@ -23,20 +23,35 @@
|
||||
|
||||
#ifdef SECURE_MODE
|
||||
|
||||
#ifdef SECRET_MASTER_KEY_SLOT
|
||||
|
||||
#include <ed25519-donna/ed25519.h>
|
||||
|
||||
secbool secret_key_mcu_device_auth(curve25519_key dest);
|
||||
|
||||
#endif // SECRET_MASTER_KEY_SLOT
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
|
||||
#include <ecdsa.h>
|
||||
|
||||
#define OPTIGA_PAIRING_SECRET_SIZE 32
|
||||
secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]);
|
||||
secbool secret_key_optiga_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
|
||||
|
||||
#endif
|
||||
#endif // USE_OPTIGA
|
||||
|
||||
#ifdef USE_TROPIC
|
||||
|
||||
#include <ecdsa.h>
|
||||
#include <ed25519-donna/ed25519.h>
|
||||
|
||||
secbool secret_key_tropic_public(curve25519_key dest);
|
||||
|
||||
secbool secret_key_tropic_pairing(curve25519_key dest);
|
||||
#endif
|
||||
secbool secret_key_tropic_pairing_unprivileged(curve25519_key dest);
|
||||
secbool secret_key_tropic_pairing_privileged(curve25519_key dest);
|
||||
secbool secret_key_tropic_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]);
|
||||
|
||||
#endif
|
||||
#endif // USE_TROPIC
|
||||
|
||||
#endif // SECURE_MODE
|
||||
|
@ -26,22 +26,143 @@
|
||||
#include <sec/secret.h>
|
||||
#include <sec/secret_keys.h>
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
|
||||
return secret_key_get(SECRET_OPTIGA_SLOT, dest, OPTIGA_PAIRING_SECRET_SIZE);
|
||||
#ifdef SECRET_PRIVILEGED_MASTER_KEY_SLOT
|
||||
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "nist256p1.h"
|
||||
|
||||
// Key derivation indices
|
||||
#define KEY_INDEX_MCU_DEVICE_AUTH 0
|
||||
#define KEY_INDEX_OPTIGA_PAIRING 1
|
||||
#define KEY_INDEX_OPTIGA_MASKING 2
|
||||
#define KEY_INDEX_TROPIC_PAIRING_UNPRIVILEGED 3
|
||||
#define KEY_INDEX_TROPIC_PAIRING_PRIVILEGED 4
|
||||
#define KEY_INDEX_TROPIC_MASKING 5
|
||||
|
||||
static secbool secret_key_derive_sym(uint8_t slot, uint16_t index,
|
||||
uint16_t subindex,
|
||||
uint8_t dest[SHA256_DIGEST_LENGTH]) {
|
||||
secbool ret = sectrue;
|
||||
|
||||
// The diversifier consists of:
|
||||
// - the key derivation index (2 bytes big-endian), which identifies the
|
||||
// purpose of the key,
|
||||
// - the subindex (2 bytes big-endian), which is incremented until the derived
|
||||
// key meets required criteria, and
|
||||
// - the block index (1 byte), which can be used to produce outputs that are
|
||||
// longer than 32 bytes.
|
||||
uint8_t diversifier[] = {index >> 8, index & 0xff, subindex >> 8,
|
||||
subindex & 0xff, 0};
|
||||
|
||||
uint8_t master_key[32] = {0};
|
||||
ret = secret_key_get(slot, master_key, sizeof(master_key));
|
||||
if (ret != sectrue) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
hmac_sha256(master_key, sizeof(master_key), diversifier, sizeof(diversifier),
|
||||
dest);
|
||||
|
||||
cleanup:
|
||||
memzero(master_key, sizeof(master_key));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static secbool secret_key_derive_curve25519(uint8_t slot, uint16_t index,
|
||||
curve25519_key dest) {
|
||||
_Static_assert(sizeof(curve25519_key) == SHA256_DIGEST_LENGTH);
|
||||
|
||||
secbool ret = secret_key_derive_sym(slot, index, 0, dest);
|
||||
dest[0] &= 248;
|
||||
dest[31] &= 127;
|
||||
dest[31] |= 64;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(USE_OPTIGA) || defined(USE_TROPIC)
|
||||
static secbool secret_key_derive_nist256p1(
|
||||
uint8_t slot, uint16_t index, uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
|
||||
_Static_assert(ECDSA_PRIVATE_KEY_SIZE == SHA256_DIGEST_LENGTH);
|
||||
|
||||
secbool ret = sectrue;
|
||||
bignum256 s = {0};
|
||||
for (uint16_t i = 0; i < 10000; i++) {
|
||||
ret = secret_key_derive_sym(slot, index, i, dest);
|
||||
if (ret != sectrue) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
bn_read_be(dest, &s);
|
||||
if (!bn_is_zero(&s) && bn_is_less(&s, &nist256p1.order)) {
|
||||
// Valid private key, we are done.
|
||||
ret = sectrue;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Invalid private key, we generate the next key in line.
|
||||
}
|
||||
|
||||
// Loop exhausted all attempts without producing a valid private key.
|
||||
ret = secfalse;
|
||||
|
||||
cleanup:
|
||||
memzero(&s, sizeof(s));
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
secbool secret_key_mcu_device_auth(curve25519_key dest) {
|
||||
return secret_key_derive_curve25519(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
|
||||
KEY_INDEX_MCU_DEVICE_AUTH, dest);
|
||||
}
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
|
||||
_Static_assert(OPTIGA_PAIRING_SECRET_SIZE == SHA256_DIGEST_LENGTH);
|
||||
return secret_key_derive_sym(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
|
||||
KEY_INDEX_OPTIGA_PAIRING, 0, dest);
|
||||
}
|
||||
|
||||
secbool secret_key_optiga_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
|
||||
return secret_key_derive_nist256p1(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
|
||||
KEY_INDEX_OPTIGA_MASKING, dest);
|
||||
}
|
||||
#endif // USE_OPTIGA
|
||||
|
||||
#ifdef USE_TROPIC
|
||||
secbool secret_key_tropic_public(curve25519_key dest) {
|
||||
return secret_key_get(SECRET_TROPIC_TROPIC_PUBKEY_SLOT, dest,
|
||||
sizeof(curve25519_key));
|
||||
}
|
||||
|
||||
secbool secret_key_tropic_pairing(curve25519_key dest) {
|
||||
return secret_key_get(SECRET_TROPIC_TREZOR_PRIVKEY_SLOT, dest,
|
||||
sizeof(curve25519_key));
|
||||
secbool secret_key_tropic_pairing_unprivileged(curve25519_key dest) {
|
||||
return secret_key_derive_curve25519(SECRET_UNPRIVILEGED_MASTER_KEY_SLOT,
|
||||
KEY_INDEX_TROPIC_PAIRING_UNPRIVILEGED,
|
||||
dest);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
secbool secret_key_tropic_pairing_privileged(curve25519_key dest) {
|
||||
return secret_key_derive_curve25519(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
|
||||
KEY_INDEX_TROPIC_PAIRING_PRIVILEGED,
|
||||
dest);
|
||||
}
|
||||
|
||||
secbool secret_key_tropic_masking(uint8_t dest[ECDSA_PRIVATE_KEY_SIZE]) {
|
||||
return secret_key_derive_nist256p1(SECRET_PRIVILEGED_MASTER_KEY_SLOT,
|
||||
KEY_INDEX_TROPIC_MASKING, dest);
|
||||
}
|
||||
|
||||
#endif // USE_TROPIC
|
||||
|
||||
#else // SECRET_PRIVILEGED_MASTER_KEY_SLOT
|
||||
|
||||
#ifdef USE_OPTIGA
|
||||
secbool secret_key_optiga_pairing(uint8_t dest[OPTIGA_PAIRING_SECRET_SIZE]) {
|
||||
return secret_key_get(SECRET_OPTIGA_SLOT, dest, OPTIGA_PAIRING_SECRET_SIZE);
|
||||
}
|
||||
#endif // USE_OPTIGA
|
||||
|
||||
#endif // SECRET_PRIVILEGED_MASTER_KEY_SLOT
|
||||
|
||||
#endif // SECURE_MODE
|
||||
|
@ -49,7 +49,7 @@ secbool secret_key_tropic_public(curve25519_key dest) {
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool secret_key_tropic_pairing(curve25519_key dest) {
|
||||
secbool secret_key_tropic_pairing_privileged(curve25519_key dest) {
|
||||
memcpy(dest, SECRET_TROPIC_PAIRING_BYTES, sizeof(curve25519_key));
|
||||
return sectrue;
|
||||
}
|
||||
|
@ -61,7 +61,8 @@ bool tropic_init(void) {
|
||||
}
|
||||
|
||||
secbool pubkey_ok = secret_key_tropic_public(tropic_secret_tropic_pubkey);
|
||||
secbool privkey_ok = secret_key_tropic_pairing(tropic_secret_trezor_privkey);
|
||||
secbool privkey_ok =
|
||||
secret_key_tropic_pairing_privileged(tropic_secret_trezor_privkey);
|
||||
|
||||
if (pubkey_ok == sectrue && privkey_ok == sectrue) {
|
||||
uint8_t trezor_pubkey[32] = {0};
|
||||
|
@ -61,6 +61,8 @@ typedef struct {
|
||||
// (4 + 32 + 1 + 4 [checksum]) * 8 / log2(58) plus NUL.
|
||||
#define MAX_WIF_SIZE (57)
|
||||
|
||||
#define ECDSA_PRIVATE_KEY_SIZE 32
|
||||
|
||||
void point_copy(const curve_point *cp1, curve_point *cp2);
|
||||
void point_add(const ecdsa_curve *curve, const curve_point *cp1,
|
||||
curve_point *cp2);
|
||||
|
Loading…
Reference in New Issue
Block a user