// // OpenHaystack – Tracking personal Bluetooth devices via Apple's Find My network // // Copyright © 2021 Secure Mobile Networking Lab (SEEMOO) // Copyright © 2021 The Open Wireless Link Project // // SPDX-License-Identifier: AGPL-3.0-only // import CryptoKit import Foundation /// Decode key files found in newer macOS versions. class FindMyKeyDecoder { /// Key files can be in different format. /// /// The old <= 10.15.3 have been using normal plists. Newer once use a binary format which needs different parsing. enum KeyFileFormat { /// Catalina > 10.15.4 key file format | Big Sur 11.0 Beta 1 uses a similar key file format that can be parsed identically. /// macOS 10.15.7 uses a new key file format that has not been reversed yet. /// (The key files are protected by sandboxing and only usable from a SIP disabled) case catalina_10_15_4 } var fileFormat: KeyFileFormat? func parse(keyFile: Data) throws -> [FindMyKey] { // Detect the format at first if fileFormat == nil { try self.checkFormat(for: keyFile) } guard let format = self.fileFormat else { throw ParsingError.unsupportedFormat } switch format { case .catalina_10_15_4: let keys = try self.parseBinaryKeyFiles(from: keyFile) return keys } } func checkFormat(for keyFile: Data) throws { // Key files need to start with KEY = 0x4B 45 59 let magicBytes = keyFile.subdata(in: 0..<3) guard magicBytes == Data([0x4b, 0x45, 0x59]) else { throw ParsingError.wrongMagicBytes } // Detect zeros let potentialZeros = keyFile[15..<31] guard potentialZeros == Data(repeating: 0x00, count: 16) else { throw ParsingError.wrongFormat } // Should be big sur self.fileFormat = .catalina_10_15_4 } fileprivate func parseBinaryKeyFiles(from keyFile: Data) throws -> [FindMyKey] { var keys = [FindMyKey]() // First key starts at 32 var i = 32 while i + 117 < keyFile.count { // We could not identify what those keys were _ = keyFile.subdata(in: i..