diff --git a/stm32/mk4-bootloader/ae.c b/stm32/mk4-bootloader/ae.c index 2b326b16..a55e34cc 100644 --- a/stm32/mk4-bootloader/ae.c +++ b/stm32/mk4-bootloader/ae.c @@ -696,7 +696,7 @@ ae_random(uint8_t randout[32]) // Generate a random number, using nonces generated by chip and by us. // Verify the result was not modified by MitM. // - int + void ae_secure_random(uint8_t randout[32]) { // Generate a digest of pairing secret slot, which will include diff --git a/stm32/mk4-bootloader/ae.h b/stm32/mk4-bootloader/ae.h index 10d30e22..7b7a6d92 100644 --- a/stm32/mk4-bootloader/ae.h +++ b/stm32/mk4-bootloader/ae.h @@ -89,7 +89,7 @@ void ae_keep_alive(void); // Pick a fresh random number. //int ae_random(uint8_t randout[32]); -int ae_secure_random(uint8_t randout[32]); +void ae_secure_random(uint8_t randout[32]); // Pick a EC keypair and return public part; private saved. int ae_gen_ecc_key(uint8_t keynum, uint8_t pubkey_out[64]); diff --git a/stm32/mk4-bootloader/ae_config.h b/stm32/mk4-bootloader/ae_config.h index 30b42f0f..88cb9d2a 100644 --- a/stm32/mk4-bootloader/ae_config.h +++ b/stm32/mk4-bootloader/ae_config.h @@ -17,7 +17,7 @@ // bytes [90..128) of chip config area #define AE_CHIP_CONFIG_2 { \ 0x02, 0x15, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x5c, 0x00, \ - 0xbc, 0x01, 0xfc, 0x01, 0xbc, 0x01, 0x9c, 0x01, 0x9c, 0x01, \ + 0xbc, 0x01, 0xfc, 0x01, 0xbc, 0x01, 0xdc, 0x01, 0xdc, 0x01, \ 0xd1, 0x03, 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x03, \ 0xdc, 0x03, 0xdc, 0x03, 0xdc, 0x01, 0x3c, 0x00 \ } @@ -70,10 +70,10 @@ KeyConfig[3] = 0xfc01 = KeyConfig(Private=0, PubInfo=0, KeyType=7, Lockable=1, R KeyConfig[4] = 0xbc01 = KeyConfig(Private=0, PubInfo=0, KeyType=7, Lockable=1, ReqRandom=0, ReqAuth=1, AuthKey=1, PersistentDisable=0, RFU=0, X509id=0)=0x01bc Slot[5] = 0x0043 = SlotConfig(ReadKey=0, NoMac=0, LimitedUse=0, EncryptRead=0, IsSecret=0, WriteKey=3, WriteConfig=4)=0x4300 -KeyConfig[5] = 0x9c01 = KeyConfig(Private=0, PubInfo=0, KeyType=7, Lockable=0, ReqRandom=0, ReqAuth=1, AuthKey=1, PersistentDisable=0, RFU=0, X509id=0)=0x019c +KeyConfig[5] = 0xdc01 = KeyConfig(Private=0, PubInfo=0, KeyType=7, Lockable=0, ReqRandom=1, ReqAuth=1, AuthKey=1, PersistentDisable=0, RFU=0, X509id=0)=0x01dc Slot[6] = 0x0043 = SlotConfig(ReadKey=0, NoMac=0, LimitedUse=0, EncryptRead=0, IsSecret=0, WriteKey=3, WriteConfig=4)=0x4300 -KeyConfig[6] = 0x9c01 = KeyConfig(Private=0, PubInfo=0, KeyType=7, Lockable=0, ReqRandom=0, ReqAuth=1, AuthKey=1, PersistentDisable=0, RFU=0, X509id=0)=0x019c +KeyConfig[6] = 0xdc01 = KeyConfig(Private=0, PubInfo=0, KeyType=7, Lockable=0, ReqRandom=1, ReqAuth=1, AuthKey=1, PersistentDisable=0, RFU=0, X509id=0)=0x01dc Slot[7] = 0x8320 = SlotConfig(ReadKey=3, NoMac=0, LimitedUse=0, EncryptRead=0, IsSecret=1, WriteKey=0, WriteConfig=2)=0x2083 KeyConfig[7] = 0xd103 = KeyConfig(Private=1, PubInfo=0, KeyType=4, Lockable=0, ReqRandom=1, ReqAuth=1, AuthKey=3, PersistentDisable=0, RFU=0, X509id=0)=0x03d1 diff --git a/stm32/mk4-bootloader/dispatch.c b/stm32/mk4-bootloader/dispatch.c index 21cb183e..f3eb3f96 100644 --- a/stm32/mk4-bootloader/dispatch.c +++ b/stm32/mk4-bootloader/dispatch.c @@ -568,10 +568,9 @@ firewall_dispatch(int method_num, uint8_t *buf_io, int len_in, switch(arg2) { case 1: // for SE1 - // LIMITATION: this has no MitM protection, subject to tampering + // secure, any MitM will be detected ae_setup(); - int rv = ae_secure_random(&buf_io[1]); - if(rv) fatal_mitm(); + ae_secure_random(&buf_io[1]); buf_io[0] = 32; break; diff --git a/stm32/mk4-bootloader/keylayout.py b/stm32/mk4-bootloader/keylayout.py index 3e32d122..df90ae16 100755 --- a/stm32/mk4-bootloader/keylayout.py +++ b/stm32/mk4-bootloader/keylayout.py @@ -202,9 +202,11 @@ def doit(partno, mk_num, ae, KEYNUM, fp): cc[KEYNUM.pin_stretch].hash_key().require_auth(KEYNUM.pairing).deterministic() # chip-enforced pin attempts: link keynum and enable "match count" feature - cc[KEYNUM.match_count].writeable_storage(main_pin).require_auth(KEYNUM.pairing) + cc[KEYNUM.match_count].writeable_storage(main_pin).require_auth(KEYNUM.pairing).require_rng() ae.counter_match(KEYNUM.match_count) + cc[KEYNUM.lastgood].require_rng() + # ECC keypair; we hold privkey, pubkey enables things in SE2 cc[KEYNUM.joiner_key].ec_key(limited_sign=False).no_pubkey().require_auth(main_pin) diff --git a/stm32/mk4-bootloader/secel_config.py b/stm32/mk4-bootloader/secel_config.py index d40d3292..2a06b7d4 100644 --- a/stm32/mk4-bootloader/secel_config.py +++ b/stm32/mk4-bootloader/secel_config.py @@ -393,6 +393,11 @@ class ComboConfig(object): self.kc.ReqRandom = 0 return self + def require_rng(self): + # prevents replay attacks + self.kc.ReqRandom = 1 + return self + def require_auth(self, kn): # knowledge of another key will be required assert 0 <= kn <= 15