Hash PIN w/ SE2 secrets
This commit is contained in:
parent
bf86c9e61b
commit
e4ad63097c
@ -111,6 +111,8 @@ $(OBJS): Makefile
|
||||
|
||||
$(TARGETS): $(TARGET_ELF) Makefile
|
||||
|
||||
version.o: version.h
|
||||
|
||||
# makes the .py from a shared header file
|
||||
sigheader.py: mk-sigheader.py sigheader.h
|
||||
python3 mk-sigheader.py
|
||||
|
||||
@ -31,9 +31,6 @@ firewall_setup(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
enabled firewall, even debg
|
||||
|
||||
#if RELEASE
|
||||
// REMINDERS:
|
||||
// - cannot debug anything in boot loader w/ firewall enabled (no readback, no bkpt)
|
||||
@ -47,7 +44,6 @@ enabled firewall, even debg
|
||||
#else
|
||||
// for debug builds, never enable firewall
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern int firewall_starts; // see startup.S ... aligned@256 (0x08000300)
|
||||
|
||||
@ -27,12 +27,6 @@
|
||||
// - solution: adjust both the target and counter (upwards)
|
||||
#define MAX_TARGET_ATTEMPTS 13
|
||||
|
||||
// Pretty sure it doesn't matter, but adding some salt into our PIN->bytes[32] code
|
||||
// based on the purpose of the PIN code.
|
||||
//
|
||||
#define PIN_PURPOSE_NORMAL 0x334d1858
|
||||
#define PIN_PURPOSE_WORDS 0x2e6d6773
|
||||
|
||||
// Hash up a PIN for indicated purpose.
|
||||
static void pin_hash(const char *pin, int pin_len, uint8_t result[32], uint32_t purpose);
|
||||
|
||||
@ -120,13 +114,16 @@ pin_hash(const char *pin, int pin_len, uint8_t result[32], uint32_t purpose)
|
||||
SHA256_CTX ctx;
|
||||
sha256_init(&ctx);
|
||||
|
||||
sha256_update(&ctx, rom_secrets->pairing_secret, 32);
|
||||
sha256_update(&ctx, rom_secrets->hash_cache_secret, 32);
|
||||
sha256_update(&ctx, (uint8_t *)&purpose, 4);
|
||||
sha256_update(&ctx, (uint8_t *)pin, pin_len);
|
||||
sha256_update(&ctx, rom_secrets->pairing_secret, 32);
|
||||
|
||||
sha256_final(&ctx, result);
|
||||
|
||||
// and run that thru SE2 as well
|
||||
se2_pin_hash(result, purpose);
|
||||
|
||||
// and a second-sha256 on that, just in case.
|
||||
sha256_single(result, 32, result);
|
||||
}
|
||||
|
||||
@ -91,6 +91,12 @@ enum {
|
||||
EPIN_SE2_FAIL = -115, // (mk4) some issue w/ SE2
|
||||
};
|
||||
|
||||
// Pretty sure it doesn't matter, but adding some salt into our PIN->bytes[32] code
|
||||
// based on the purpose of the PIN code.
|
||||
//
|
||||
#define PIN_PURPOSE_NORMAL 0x334d1858
|
||||
#define PIN_PURPOSE_WORDS 0x2e6d6773
|
||||
|
||||
// early setup
|
||||
void pin_setup0(void);
|
||||
|
||||
|
||||
@ -462,6 +462,31 @@ se2_clear_volatile(void)
|
||||
CHECK_RIGHT(se2_read1() == RC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
// se2_set_counter()
|
||||
//
|
||||
// Can only be done once. Trusted env.
|
||||
//
|
||||
static void
|
||||
se2_set_counter(uint32_t val)
|
||||
{
|
||||
uint8_t tmp[32];
|
||||
|
||||
se2_read_page(PGN_DEC_COUNTER, tmp, false);
|
||||
|
||||
// datasheet says will read as "random data" if not yet set, but
|
||||
// observed 0xff, 0xff, 0xff, 0...0 (which is an illegal value, since only 17 bits)
|
||||
if(tmp[2] == 0xff) {
|
||||
tmp[0] = val & 0x0ff;
|
||||
tmp[1] = (val >> 8) & 0x0ff;
|
||||
tmp[2] = (val >> 16) & 0x01;
|
||||
|
||||
se2_write_page(PGN_DEC_COUNTER, tmp);
|
||||
} else {
|
||||
puts("ctr set?"); // not expected, but keep going
|
||||
}
|
||||
}
|
||||
|
||||
// se2_setup_config()
|
||||
//
|
||||
// One-time config and lockdown of the SE2 chip.
|
||||
@ -507,7 +532,7 @@ se2_setup_config(void)
|
||||
|
||||
memcpy(_tbd.romid, tmp+24, 8);
|
||||
|
||||
// forget a secret - B (will not be used)
|
||||
// forget a secret - B (will not be saved)
|
||||
rng_buffer(tmp, 32);
|
||||
se2_write_page(PGN_SECRET_B, tmp);
|
||||
|
||||
@ -560,6 +585,9 @@ se2_setup_config(void)
|
||||
|
||||
se2_set_protection(PGN_ROM_OPTIONS, PROT_APH); // not planning to change
|
||||
|
||||
// Need known value in counter, write once.
|
||||
se2_set_counter(128);
|
||||
|
||||
// NOTE: PGN_SE2_HARD_KEY and PUBKEY_C not yet known
|
||||
}
|
||||
|
||||
@ -1214,4 +1242,52 @@ se2_decrypt_secret(uint8_t secret[], int secret_len, int offset,
|
||||
aes_done(&ctx, secret, secret_len, aes_key, nonce);
|
||||
}
|
||||
|
||||
// se2_pin_hash()
|
||||
//
|
||||
// Hash up a PIN code for login attempt: to tie it into SE2's contents.
|
||||
//
|
||||
void
|
||||
se2_pin_hash(uint8_t digest_io[32], uint32_t purpose)
|
||||
{
|
||||
se2_setup();
|
||||
|
||||
if((setjmp(error_env))) {
|
||||
oled_show(screen_se2_issue);
|
||||
|
||||
LOCKUP_FOREVER();
|
||||
}
|
||||
|
||||
uint8_t tmp[32];
|
||||
HMAC_CTX ctx;
|
||||
|
||||
// HMAC(key=tpin_key, msg=given hash so far)
|
||||
hmac_sha256_init(&ctx);
|
||||
hmac_sha256_update(&ctx, digest_io, 32);
|
||||
hmac_sha256_update(&ctx, (uint8_t *)&purpose, 4);
|
||||
hmac_sha256_final(&ctx, SE2_SECRETS->tpin_key, tmp);
|
||||
|
||||
// NOTE: exposed as cleartext here
|
||||
se2_write_buffer(tmp, 32);
|
||||
|
||||
// HMAC(key=secret-B (we dont know it, but set random), msg=pubkeyA+buffer+junk)
|
||||
// - result put in secret-S (ram)
|
||||
CALL_CHECK(se2_write2(0x3c, (2<<6) | (1<<4) | PGN_SECRET_B, 0));
|
||||
CHECK_RIGHT(se2_read1() == RC_SUCCESS);
|
||||
|
||||
// .. HMAC(key=S, msg=counter), so we have something to read out
|
||||
se2_write_buffer(tmp, 32);
|
||||
CALL_CHECK(se2_write1(0xa5, (2<<5) | PGN_DEC_COUNTER));
|
||||
|
||||
uint8_t rx[34];
|
||||
CHECK_RIGHT(se2_read_n(sizeof(rx), rx) == RC_SUCCESS);
|
||||
|
||||
CHECK_RIGHT(rx[1] == RC_SUCCESS);
|
||||
|
||||
memcpy(digest_io, rx+2, 32);
|
||||
|
||||
// 12-12 => 606ad30d10c4683b7478aa6ffd09c644e7de6091d2cdcfb58bb698c7cfa90934
|
||||
//puts2("md: ");
|
||||
//hex_dump(digest_io, 32);
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
||||
@ -61,6 +61,9 @@ void se2_save_auth_pubkey(const uint8_t pubkey[64]);
|
||||
// call if a completely unknown PIN is provided
|
||||
void se2_handle_bad_pin(int num_fails);
|
||||
|
||||
// hash up a PIN code for login attempt: to tie it into SE2's contents
|
||||
void se2_pin_hash(uint8_t digest_io[32], uint32_t purpose);
|
||||
|
||||
#if 0
|
||||
// secp256r1 curve functions.
|
||||
bool p256_verify(const uint8_t pubkey[64], const uint8_t digest[32], const uint8_t signature[64]);
|
||||
|
||||
@ -769,6 +769,9 @@ fast_brick(void)
|
||||
// brick SE1 for future
|
||||
ae_brick_myself();
|
||||
|
||||
// NOTE: could brick SE1 (somewhat) by dec'ing the counter, which will
|
||||
// invalidate all PIN hashes
|
||||
|
||||
// no going back from that -- but for privacy, wipe more stuff
|
||||
oled_show(screen_brick);
|
||||
puts2("fast brick... ");
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
// Public version number for humans. Lots more version data added by Makefile.
|
||||
#define RELEASE_VERSION "3.0.4"
|
||||
#define RELEASE_VERSION "3.1.0"
|
||||
|
||||
extern const char version_string[];
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user