예제 #1
0
파일: usb.py 프로젝트: jimmysong/firmware
    def handle_crypto_setup(self, version, his_pubkey):
        # pick a one-time key pair for myself, and return the pubkey for that
        # determine what the session key will be for this connection
        assert version == 0x1
        assert len(his_pubkey) == 64

        # pick a random key pair, just for this session
        my_key = tcc.secp256k1.generate_secret()
        my_pubkey = tcc.secp256k1.publickey(my_key, False)

        #print('my pubkey = ' + str(b2a_hex(my_pubkey)))
        #print('his pubkey = ' + str(b2a_hex(his_pubkey)))

        pt = tcc.secp256k1.multiply(my_key, b'\x04' + his_pubkey)
        assert pt[0] == 4
        self.session_key = tcc.sha256(pt[1:]).digest()

        #print("session = " + str(b2a_hex(self.session_key)))

        # Would be nice to have nonce in addition to the counter, but
        # library not ready for that, and also harder on the desktop side.
        self.encrypt = tcc.AES(tcc.AES.CTR | tcc.AES.Encrypt, self.session_key)
        self.decrypt = tcc.AES(tcc.AES.CTR | tcc.AES.Decrypt, self.session_key)

        from main import settings
        xfp = settings.get('xfp', 0)
        xpub = settings.get('xpub', '')

        assert my_pubkey[0] == 0x04
        return b'mypb' + my_pubkey[1:] + pack('<II', xfp, len(xpub)) + xpub
예제 #2
0
    def read_file(self, fd, password, max_size=2000, progress_fcn=None):
        # read a file we wrote; unlikely to work on anything else.
        # assuming single file contained inside
        fhdr = FileHeader.read(fd)
        assert fhdr.has_good_magic()

        for shdr, meta, body in SectionHeader.read_iter(fd):
            # read out salt data, fname, sizes
            fname, body_size, unpacked_size, expect_crc = self.parse_section_hdr(meta)

            assert len(body) == body_size
            assert unpacked_size <= max_size, 'too big'
            assert len(body) <= unpacked_size+16, 'too big, encoded'
            assert len(body) % 16 == 0, 'not blocked'

            # figure out key to be used
            key = self.calculate_key(password, progress_fcn)

            out = b''
            aes = tcc.AES(tcc.AES.CBC | tcc.AES.Decrypt, key, self.iv)

            for blk in range(0, len(body), 16):
                out += aes.update(body[blk:blk+16])

            # trim padding, check CRC
            out = out[0:unpacked_size]
            if masked_crc(out) != expect_crc:
                raise ValueError("Wrong password given, or damaged file.")

            # done. return contents
            return fname, out
예제 #3
0
    async def append(self, xfp, bip39pw):
        # encrypt and save; always appends.
        from ux import ux_dramatic_pause
        from main import dis
        from actions import needs_microsd

        while 1:
            dis.fullscreen('Saving...')

            try:
                with CardSlot() as card:
                    self._calc_key(card)

                    data = self._read(card) if self.key else []

                    data.append(dict(xfp=xfp, pw=bip39pw))

                    encrypt = tcc.AES(tcc.AES.CTR | tcc.AES.Encrypt, self.key)

                    msg = encrypt.update(ujson.dumps(data))

                    with open(self.filename(card), 'wb') as fd:
                        fd.write(msg)

                await ux_dramatic_pause("Saved.", 1)
                return

            except CardMissingError:
                ch = await needs_microsd()
                if ch == 'x':  # undocumented, but needs escape route
                    break
예제 #4
0
    def _read(self, card):
        # Return a list of saved passphrases, or empty list if fail.
        # Fail silently in all cases. Expect to see lots of noise here.
        decrypt = tcc.AES(tcc.AES.CTR | tcc.AES.Decrypt, self.key)

        try:
            msg = open(self.filename(card), 'rb').read()
            txt = decrypt.update(msg)
            return ujson.loads(txt)
        except:
            return []
예제 #5
0
    def add_data(self, raw):
        if not self.aes:
            # do this late, so easier to test w/ known values.
            #self.aes = AES.AESCipher(self.key, mode=AES.MODE_CBC, IV=self.iv)
            self.aes = tcc.AES(tcc.AES.CBC | tcc.AES.Encrypt, self.key, self.iv)

        here = len(raw)
        self.pt_crc = crc32(raw, self.pt_crc)

        padded_len = (here + 15) & ~15
        if padded_len != here:
            if self.padding != None:
                raise ValueError("can't do less than a block except at end")
            self.padding =  (padded_len - here)
            raw += '\x00' * self.padding
        self.unpacked_size += here

        assert len(raw) % 16 == 0, b2a_hex(raw)
        self.body += self.aes.update(raw)
예제 #6
0
 def get_aes(self, mode, pos):
     # Build AES key for en/decrypt of specific block.
     # Include the slot number as part of the initial counter (CTR)
     return tcc.AES(tcc.AES.CTR | mode, self.nvram_key,
                    ustruct.pack('<4I', 4, 3, 2, pos))