Exemplo n.º 1
0
    async def verify_credentials(self):
        """Verify credentials with device."""
        _, public_key = self.srp.initialize()

        msg = messages.crypto_pairing({
            TlvValue.SeqNo: b"\x01",
            TlvValue.PublicKey: public_key
        })
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        resp = _get_pairing_data(resp)
        session_pub_key = resp[TlvValue.PublicKey]
        encrypted = resp[TlvValue.EncryptedData]
        log_binary(_LOGGER,
                   "Device",
                   Public=self.credentials.ltpk,
                   Encrypted=encrypted)

        encrypted_data = self.srp.verify1(self.credentials, session_pub_key,
                                          encrypted)
        msg = messages.crypto_pairing({
            TlvValue.SeqNo: b"\x03",
            TlvValue.EncryptedData: encrypted_data
        })
        await self.protocol.send_and_receive(msg, generate_identifier=False)

        # TODO: check status code

        self._output_key, self._input_key = self.srp.verify2()
Exemplo n.º 2
0
    async def finish_pairing(self, pin):
        """Finish pairing process."""
        self.srp.step1(pin)

        pub_key, proof = self.srp.step2(self._atv_pub_key, self._atv_salt)

        msg = messages.crypto_pairing({
            TlvValue.SeqNo: b"\x03",
            TlvValue.PublicKey: pub_key,
            TlvValue.Proof: proof,
        })
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        pairing_data = _get_pairing_data(resp)
        atv_proof = pairing_data[TlvValue.Proof]
        log_binary(_LOGGER, "Device", Proof=atv_proof)

        encrypted_data = self.srp.step3()
        msg = messages.crypto_pairing({
            TlvValue.SeqNo: b"\x05",
            TlvValue.EncryptedData: encrypted_data
        })
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        pairing_data = _get_pairing_data(resp)
        encrypted_data = pairing_data[TlvValue.EncryptedData]

        return self.srp.step4(encrypted_data)
Exemplo n.º 3
0
    async def verify_credentials(self):
        """Verify credentials with device."""
        _, public_key = self.srp.initialize()

        msg = messages.crypto_pairing({
            tlv8.TLV_SEQ_NO: b'\x01',
            tlv8.TLV_PUBLIC_KEY: public_key
        })
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        resp = _get_pairing_data(resp)
        session_pub_key = resp[tlv8.TLV_PUBLIC_KEY]
        encrypted = resp[tlv8.TLV_ENCRYPTED_DATA]
        log_binary(_LOGGER,
                   'Device',
                   Public=self.credentials.ltpk,
                   Encrypted=encrypted)

        encrypted_data = self.srp.verify1(self.credentials, session_pub_key,
                                          encrypted)
        msg = messages.crypto_pairing({
            tlv8.TLV_SEQ_NO: b'\x03',
            tlv8.TLV_ENCRYPTED_DATA: encrypted_data
        })
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        # TODO: check status code

        self._output_key, self._input_key = self.srp.verify2()
Exemplo n.º 4
0
    async def finish_pairing(self, pin):
        """Finish pairing process."""
        self.srp.step1(pin)

        pub_key, proof = self.srp.step2(self._atv_pub_key, self._atv_salt)

        msg = messages.crypto_pairing({
            tlv8.TLV_SEQ_NO: b'\x03',
            tlv8.TLV_PUBLIC_KEY: pub_key,
            tlv8.TLV_PROOF: proof
        })
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        pairing_data = _get_pairing_data(resp)
        atv_proof = pairing_data[tlv8.TLV_PROOF]
        log_binary(_LOGGER, 'Device', Proof=atv_proof)

        encrypted_data = self.srp.step3()
        msg = messages.crypto_pairing({
            tlv8.TLV_SEQ_NO: b'\x05',
            tlv8.TLV_ENCRYPTED_DATA: encrypted_data
        })
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        pairing_data = _get_pairing_data(resp)
        encrypted_data = pairing_data[tlv8.TLV_ENCRYPTED_DATA]

        return self.srp.step4(encrypted_data)
Exemplo n.º 5
0
    def _seqno_1(self, pairing_data):
        if self.has_paired:
            server_pub_key = self._verify_public.serialize()
            client_pub_key = pairing_data[tlv8.TLV_PUBLIC_KEY]

            self._shared = self._verify_private.get_shared_key(
                curve25519.Public(client_pub_key), hashfunc=lambda x: x)

            session_key = hkdf_expand('Pair-Verify-Encrypt-Salt',
                                      'Pair-Verify-Encrypt-Info', self._shared)

            info = server_pub_key + self.atv_device_id + client_pub_key
            signature = SigningKey(self._signing_key.to_seed()).sign(info)

            tlv = tlv8.write_tlv({
                tlv8.TLV_IDENTIFIER: self.atv_device_id,
                tlv8.TLV_SIGNATURE: signature
            })

            chacha = chacha20.Chacha20Cipher(session_key, session_key)
            encrypted = chacha.encrypt(tlv, nounce='PV-Msg02'.encode())

            msg = messages.crypto_pairing({
                tlv8.TLV_SEQ_NO: b'\x02',
                tlv8.TLV_PUBLIC_KEY: server_pub_key,
                tlv8.TLV_ENCRYPTED_DATA: encrypted
            })

            self.output_key = hkdf_expand('MediaRemote-Salt',
                                          'MediaRemote-Write-Encryption-Key',
                                          self._shared)

            self.input_key = hkdf_expand('MediaRemote-Salt',
                                         'MediaRemote-Read-Encryption-Key',
                                         self._shared)

            log_binary(_LOGGER,
                       'Keys',
                       Output=self.output_key,
                       Input=self.input_key)

        else:
            msg = messages.crypto_pairing({
                tlv8.TLV_SALT:
                binascii.unhexlify(self.salt),
                tlv8.TLV_PUBLIC_KEY:
                binascii.unhexlify(self._session.public),
                tlv8.TLV_SEQ_NO:
                b'\x02'
            })

        self._send(msg)
Exemplo n.º 6
0
    async def start_pairing(self):
        """Start pairing procedure."""
        self.srp.initialize()

        await self.protocol.start(skip_initial_messages=True)

        msg = messages.crypto_pairing(
            {
                tlv8.TLV_METHOD: b'\x00',
                tlv8.TLV_SEQ_NO: b'\x01'
            },
            is_pairing=True)
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        pairing_data = _get_pairing_data(resp)

        if tlv8.TLV_BACK_OFF in pairing_data:
            time = int.from_bytes(pairing_data[tlv8.TLV_BACK_OFF],
                                  byteorder='little')
            raise exceptions.BackOffError(
                'please wait {0}s before trying again'.format(time))

        self._atv_salt = pairing_data[tlv8.TLV_SALT]
        self._atv_pub_key = pairing_data[tlv8.TLV_PUBLIC_KEY]
Exemplo n.º 7
0
    def _seqno5_pairing(self, _):
        session_key = hkdf_expand('Pair-Setup-Encrypt-Salt',
                                  'Pair-Setup-Encrypt-Info',
                                  binascii.unhexlify(self.session.key))

        acc_device_x = hkdf_expand('Pair-Setup-Accessory-Sign-Salt',
                                   'Pair-Setup-Accessory-Sign-Info',
                                   binascii.unhexlify(self.session.key))

        device_info = acc_device_x + self.unique_id + self.keys.auth_pub
        signature = self.keys.sign.sign(device_info)

        tlv = tlv8.write_tlv({
            tlv8.TLV_IDENTIFIER: self.unique_id,
            tlv8.TLV_PUBLIC_KEY: self.keys.auth_pub,
            tlv8.TLV_SIGNATURE: signature
        })

        chacha = chacha20.Chacha20Cipher(session_key, session_key)
        encrypted = chacha.encrypt(tlv, nounce='PS-Msg06'.encode())

        msg = messages.crypto_pairing({
            tlv8.TLV_SEQ_NO: b'\x06',
            tlv8.TLV_ENCRYPTED_DATA: encrypted,
        })
        self.has_paired = True

        self.delegate.send(msg)
Exemplo n.º 8
0
    def _seqno5_pairing(self, _):
        session_key = hkdf_expand(
            "Pair-Setup-Encrypt-Salt",
            "Pair-Setup-Encrypt-Info",
            binascii.unhexlify(self.session.key),
        )

        acc_device_x = hkdf_expand(
            "Pair-Setup-Accessory-Sign-Salt",
            "Pair-Setup-Accessory-Sign-Info",
            binascii.unhexlify(self.session.key),
        )

        device_info = acc_device_x + self.unique_id + self.keys.auth_pub
        signature = self.keys.sign.sign(device_info)

        tlv = write_tlv({
            TlvValue.Identifier: self.unique_id,
            TlvValue.PublicKey: self.keys.auth_pub,
            TlvValue.Signature: signature,
        })

        chacha = chacha20.Chacha20Cipher(session_key, session_key)
        encrypted = chacha.encrypt(tlv, nounce="PS-Msg06".encode())

        msg = messages.crypto_pairing({
            TlvValue.SeqNo: b"\x06",
            TlvValue.EncryptedData: encrypted
        })
        self.has_paired = True

        self.delegate.send(msg)
Exemplo n.º 9
0
    def _seqno_3(self, pairing_data):
        if self.has_paired:
            self._send(messages.crypto_pairing({tlv8.TLV_SEQ_NO: b'\x04'}))
            self.chacha = chacha20.Chacha20Cipher(self.input_key,
                                                  self.output_key)
        else:
            pubkey = binascii.hexlify(
                pairing_data[tlv8.TLV_PUBLIC_KEY]).decode()
            self._session.process(pubkey, self.salt)

            proof = binascii.unhexlify(self._session.key_proof_hash)
            assert self._session.verify_proof(
                binascii.hexlify(pairing_data[tlv8.TLV_PROOF]))

            msg = messages.crypto_pairing({
                tlv8.TLV_PROOF: proof,
                tlv8.TLV_SEQ_NO: b'\x04'
            })
            self._send(msg)
Exemplo n.º 10
0
    def _seqno1_pairing(self, pairing_data):
        msg = messages.crypto_pairing({
            TlvValue.Salt:
            binascii.unhexlify(self.salt),
            TlvValue.PublicKey:
            binascii.unhexlify(self.session.public),
            TlvValue.SeqNo:
            b"\x02",
        })

        self.delegate.send(msg)
Exemplo n.º 11
0
    def _seqno1_pairing(self, pairing_data):
        msg = messages.crypto_pairing({
            tlv8.TLV_SALT:
            binascii.unhexlify(self.salt),
            tlv8.TLV_PUBLIC_KEY:
            binascii.unhexlify(self.session.public),
            tlv8.TLV_SEQ_NO:
            b'\x02'
        })

        self.delegate.send(msg)
Exemplo n.º 12
0
    def _seqno3_pairing(self, pairing_data):
        pubkey = binascii.hexlify(pairing_data[tlv8.TLV_PUBLIC_KEY]).decode()
        self.session.process(pubkey, self.salt)

        proof = binascii.unhexlify(self.session.key_proof_hash)
        if self.session.verify_proof(
                binascii.hexlify(pairing_data[tlv8.TLV_PROOF])):

            msg = messages.crypto_pairing({
                tlv8.TLV_PROOF: proof,
                tlv8.TLV_SEQ_NO: b'\x04'
            })
        else:
            msg = messages.crypto_pairing({
                tlv8.TLV_ERROR:
                tlv8.ERROR_AUTHENTICATION.encode(),
                tlv8.TLV_SEQ_NO:
                b'\x04'
            })

        self.delegate.send(msg)
Exemplo n.º 13
0
    def _seqno3_pairing(self, pairing_data):
        pubkey = binascii.hexlify(pairing_data[TlvValue.PublicKey]).decode()
        self.session.process(pubkey, self.salt)

        proof = binascii.unhexlify(self.session.key_proof_hash)
        if self.session.verify_proof(
                binascii.hexlify(pairing_data[TlvValue.Proof])):

            msg = messages.crypto_pairing({
                TlvValue.Proof: proof,
                TlvValue.SeqNo: b"\x04"
            })
        else:
            msg = messages.crypto_pairing({
                TlvValue.Error:
                bytes([ErrorCode.Authentication]),
                TlvValue.SeqNo:
                b"\x04",
            })

        self.delegate.send(msg)
Exemplo n.º 14
0
    async def start_pairing(self):
        """Start pairing procedure."""
        self.srp.initialize()

        await self.protocol.start(skip_initial_messages=True)

        msg = messages.crypto_pairing(
            {
                TlvValue.Method: b"\x00",
                TlvValue.SeqNo: b"\x01"
            },
            is_pairing=True,
        )
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        pairing_data = _get_pairing_data(resp)
        self._atv_salt = pairing_data[TlvValue.Salt]
        self._atv_pub_key = pairing_data[TlvValue.PublicKey]
Exemplo n.º 15
0
    def _seqno1_paired(self, pairing_data):
        server_pub_key = self.keys.verify_pub.public_bytes(
            encoding=serialization.Encoding.Raw,
            format=serialization.PublicFormat.Raw)
        client_pub_key = pairing_data[tlv8.TLV_PUBLIC_KEY]

        shared_key = self.keys.verify.exchange(
            X25519PublicKey.from_public_bytes(client_pub_key))

        session_key = hkdf_expand("Pair-Verify-Encrypt-Salt",
                                  "Pair-Verify-Encrypt-Info", shared_key)

        info = server_pub_key + self.unique_id + client_pub_key
        signature = self.keys.sign.sign(info)

        tlv = tlv8.write_tlv({
            tlv8.TLV_IDENTIFIER: self.unique_id,
            tlv8.TLV_SIGNATURE: signature
        })

        chacha = chacha20.Chacha20Cipher(session_key, session_key)
        encrypted = chacha.encrypt(tlv, nounce="PV-Msg02".encode())

        msg = messages.crypto_pairing({
            tlv8.TLV_SEQ_NO: b"\x02",
            tlv8.TLV_PUBLIC_KEY: server_pub_key,
            tlv8.TLV_ENCRYPTED_DATA: encrypted,
        })

        self.output_key = hkdf_expand("MediaRemote-Salt",
                                      "MediaRemote-Write-Encryption-Key",
                                      shared_key)

        self.input_key = hkdf_expand("MediaRemote-Salt",
                                     "MediaRemote-Read-Encryption-Key",
                                     shared_key)

        log_binary(_LOGGER,
                   "Keys",
                   Output=self.output_key,
                   Input=self.input_key)
        self.delegate.send(msg)
Exemplo n.º 16
0
    def _seqno1_paired(self, pairing_data):
        server_pub_key = self.keys.verify_pub.public_bytes(
            encoding=serialization.Encoding.Raw,
            format=serialization.PublicFormat.Raw)
        client_pub_key = pairing_data[TlvValue.PublicKey]

        shared_key = self.keys.verify.exchange(
            X25519PublicKey.from_public_bytes(client_pub_key))

        session_key = hkdf_expand("Pair-Verify-Encrypt-Salt",
                                  "Pair-Verify-Encrypt-Info", shared_key)

        info = server_pub_key + self.unique_id + client_pub_key
        signature = self.keys.sign.sign(info)

        tlv = write_tlv({
            TlvValue.Identifier: self.unique_id,
            TlvValue.Signature: signature
        })

        chacha = chacha20.Chacha20Cipher(session_key, session_key)
        encrypted = chacha.encrypt(tlv, nounce="PV-Msg02".encode())

        msg = messages.crypto_pairing({
            TlvValue.SeqNo: b"\x02",
            TlvValue.PublicKey: server_pub_key,
            TlvValue.EncryptedData: encrypted,
        })

        self.output_key = hkdf_expand("MediaRemote-Salt",
                                      "MediaRemote-Write-Encryption-Key",
                                      shared_key)

        self.input_key = hkdf_expand("MediaRemote-Salt",
                                     "MediaRemote-Read-Encryption-Key",
                                     shared_key)

        log_binary(_LOGGER,
                   "Keys",
                   Output=self.output_key,
                   Input=self.input_key)
        self.delegate.send(msg)
Exemplo n.º 17
0
    async def start_pairing(self):
        """Start pairing procedure."""
        self.srp.initialize()

        msg = messages.crypto_pairing({
            tlv8.TLV_METHOD: b'\x00',
            tlv8.TLV_SEQ_NO: b'\x01'
        })
        resp = await self.protocol.send_and_receive(msg,
                                                    generate_identifier=False)

        pairing_data = _get_pairing_data(resp)

        if tlv8.TLV_BACK_OFF in pairing_data:
            time = int.from_bytes(pairing_data[tlv8.TLV_BACK_OFF],
                                  byteorder='big')
            raise Exception('back off {0}s'.format(time))

        self._atv_salt = pairing_data[tlv8.TLV_SALT]
        self._atv_pub_key = pairing_data[tlv8.TLV_PUBLIC_KEY]
Exemplo n.º 18
0
    def _seqno1_paired(self, pairing_data):
        server_pub_key = self.keys.verify_pub.serialize()
        client_pub_key = pairing_data[tlv8.TLV_PUBLIC_KEY]

        shared_key = self.keys.verify.get_shared_key(
            curve25519.Public(client_pub_key), hashfunc=lambda x: x)

        session_key = hkdf_expand('Pair-Verify-Encrypt-Salt',
                                  'Pair-Verify-Encrypt-Info', shared_key)

        info = server_pub_key + self.unique_id + client_pub_key
        signature = self.keys.sign.sign(info)

        tlv = tlv8.write_tlv({
            tlv8.TLV_IDENTIFIER: self.unique_id,
            tlv8.TLV_SIGNATURE: signature
        })

        chacha = chacha20.Chacha20Cipher(session_key, session_key)
        encrypted = chacha.encrypt(tlv, nounce='PV-Msg02'.encode())

        msg = messages.crypto_pairing({
            tlv8.TLV_SEQ_NO: b'\x02',
            tlv8.TLV_PUBLIC_KEY: server_pub_key,
            tlv8.TLV_ENCRYPTED_DATA: encrypted
        })

        self.output_key = hkdf_expand('MediaRemote-Salt',
                                      'MediaRemote-Write-Encryption-Key',
                                      shared_key)

        self.input_key = hkdf_expand('MediaRemote-Salt',
                                     'MediaRemote-Read-Encryption-Key',
                                     shared_key)

        log_binary(_LOGGER,
                   'Keys',
                   Output=self.output_key,
                   Input=self.input_key)
        self.delegate.send(msg)
Exemplo n.º 19
0
 def _seqno3_paired(self, pairing_data):
     self.delegate.send(messages.crypto_pairing({tlv8.TLV_SEQ_NO: b'\x04'}))
     self.delegate.enable_encryption(self.input_key, self.output_key)
Exemplo n.º 20
0
 def _seqno3_paired(self, pairing_data):
     self.delegate.send(messages.crypto_pairing({TlvValue.SeqNo: b"\x04"}))
     self.delegate.enable_encryption(self.input_key, self.output_key)