def prefix_words(pin_prefix): # take a prefix of the PIN and turn it into a few # bip39 words for anti-phishing protection assert 1 <= len(pin_prefix) <= MAX_PIN_LEN, len(pin_prefix) global _word_cache if version.has_608: for k, v in _word_cache: if pin_prefix == k: return v buf = bytearray(pin_prefix + b'\0' * MAX_PIN_LEN) err = ckcc.gate(16, buf, len(pin_prefix)) if err: raise RuntimeError(err) # use just 22 bits of that bits = ustruct.unpack('I', buf[0:4])[0] w1 = (bits >> 11) & 0x7ff w2 = bits & 0x7ff rv = wordlist_en[w1], wordlist_en[w2] if version.has_608: # MRU: keep only a few if len(_word_cache) > 4: _word_cache.pop() _word_cache.insert(0, (pin_prefix, rv)) return rv
def get_bl_version(): # version string and related details # something like: ('1.0.0', [('time', '20180220.092345'), ('git', 'master@f8d1758')]) rv = bytearray(64) ln = ckcc.gate(0, rv, 0) ver, *args = str(rv[0:ln], 'utf8').split(' ') return ver, [tuple(i.split('=', 1)) for i in args]
def prefix_words(pin_prefix): # take a prefix of the PIN and turn it into a few # bip39 words for anti-phishing protection assert 1 <= len(pin_prefix) <= MAX_PIN_LEN, len(pin_prefix) buf = bytearray(pin_prefix + b'\0' * MAX_PIN_LEN) err = ckcc.gate(16, buf, len(pin_prefix)) if err: raise RuntimeError(err) # use just 22 bits of that bits = ustruct.unpack('I', buf[0:4])[0] w1 = (bits >> 11) & 0x7ff w2 = bits & 0x7ff return tcc.bip39.lookup_nth(w1), tcc.bip39.lookup_nth(w2)
def roundtrip(self, method_num, **kws): self.marshal(self.buf, **kws) #print("> tx: %s" % b2a_hex(buf)) err = ckcc.gate(18, self.buf, method_num) #print("[%d] rx: %s" % (err, b2a_hex(self.buf))) if err <= -100: #print("[%d] req: %s" % (err, b2a_hex(self.buf))) if err == EPIN_I_AM_BRICK: # don't try to continue! enter_dfu(3) raise BootloaderError(PA_ERROR_CODES[err], err) elif err: raise RuntimeError(err) return self.unmarshal(self.buf)
def set_bag_number(s): assert 3 <= len(s) < 32 arg = bytearray(32) # zero pad arg[0:len(s)] = s return ckcc.gate(19, arg, 1)
def get_is_bricked(): # see if we are a brick? return ckcc.gate(5, None, 0) != 0
def get_bl_rng(): # read 32 bytes of RNG (test) rv = bytearray(32) assert ckcc.gate(17, rv, 0) == 0 return rv
def get_dfu_button(): # read current state rv = bytearray(1) ckcc.gate(12, rv, 0) return (rv[0] == 1)
def set_genuine(): # does checksum over firmware, and might set green return ckcc.gate(4, None, 3)
def clear_genuine(): ckcc.gate(4, None, 1)
def has_608b(): config = bytearray(128) ckcc.gate(20, config, 0) return (config[7] >= 0x3)
def get_bl_checksum(salt=0): # salted checksum over code rv = bytearray(32) ckcc.gate(1, rv, salt) return rv
def has_608(): return ckcc.gate(6, None, 0) == 0
def set_highwater(ts): arg = bytearray(ts) return ckcc.gate(21, arg, 2)
def set_rdp_level(n): # complex hardware rules around these changes. assert n in {0, 1, 2} return ckcc.gate(19, None, 100 + n)
def get_highwater(): arg = bytearray(8) ckcc.gate(21, arg, 0) return arg
def get_genuine(): return ckcc.gate(4, None, 0)