def _m5_setup(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.send_to_client(msg)
def _m3_setup(self, pairing_data): pubkey = binascii.hexlify(pairing_data[TlvValue.PublicKey]) self.session.process(pubkey, self.salt) if self.session.verify_proof(binascii.hexlify(pairing_data[TlvValue.Proof])): proof = binascii.unhexlify(self.session.key_proof_hash) tlv = {TlvValue.SeqNo: b"\x04", TlvValue.Proof: proof} else: tlv = { TlvValue.SeqNo: b"\x04", TlvValue.Error: bytes([ErrorCode.Authentication]), } write_shared_key = hkdf_expand( "Control-Salt", "Control-Write-Encryption-Key", binascii.unhexlify(self.session.key), ) read_shared_key = hkdf_expand( "Control-Salt", "Control-Read-Encryption-Key", binascii.unhexlify(self.session.key), ) self.enable_encryption(write_shared_key, read_shared_key) self.has_paired() return write_tlv(tlv)
def encryption_keys(self, salt: str, output_info: str, input_info: str) -> Tuple[str, str]: """Return derived encryption keys.""" shared = binascii.unhexlify(self.srp.shared_key) output_key = hkdf_expand(salt, output_info, shared) input_key = hkdf_expand(salt, input_info, shared) log_binary(_LOGGER, "Keys", Output=output_key, Input=input_key) return output_key, input_key
def _m5_setup(self, pairing_data): 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), ) chacha = chacha20.Chacha20Cipher(session_key, session_key) decrypted_tlv_bytes = chacha.decrypt( pairing_data[TlvValue.EncryptedData], nounce="PS-Msg05".encode()) _LOGGER.debug("MSG5 EncryptedData=%s", read_tlv(decrypted_tlv_bytes)) other = { "altIRK": b"-\x54\xe0\x7a\x88*en\x11\xab\x82v-'%\xc5", "accountID": "DC6A7CB6-CA1A-4BF4-880D-A61B717814DB", "model": "AppleTV6,2", "wifiMAC": b"@\xff\xa1\x8f\xa1\xb9", "name": "Living Room", "mac": b"@\xc4\xff\x8f\xb1\x99", } device_info = acc_device_x + self.unique_id + self.keys.auth_pub signature = self.keys.sign.sign(device_info) tlv = { TlvValue.Identifier: self.unique_id, TlvValue.PublicKey: self.keys.auth_pub, TlvValue.Signature: signature, 17: opack.pack(other), } tlv = write_tlv(tlv) chacha = chacha20.Chacha20Cipher(session_key, session_key) encrypted = chacha.encrypt(tlv, nounce="PS-Msg06".encode()) tlv = write_tlv({ TlvValue.SeqNo: b"\x06", TlvValue.EncryptedData: encrypted }) self.send_to_client(FrameType.PS_Next, {"_pd": tlv}) self.has_paired()
def _m1_verify(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.send_to_client(msg)