Compares DSi BIOS files against unsupported files

DSi BIOS files can have various hashes, so rather than compare them against an expected hash, we now compare them against unsupported hashes and throw an error if it matches one.
This commit is contained in:
Riley Testut 2021-02-18 17:16:44 -06:00
parent 7c3b67fbfb
commit edb2af4dd5
2 changed files with 40 additions and 9 deletions

View File

@ -32,6 +32,7 @@ private extension MelonDSCoreSettingsViewController
{
case unknownSize(URL)
case incorrectHash(URL, hash: String, expectedHash: String)
case unsupportedHash(URL, hash: String)
@available(iOS 13, *)
case incorrectSize(URL, size: Int, validSizes: Set<ClosedRange<Measurement<UnitInformationStorage>>>)
@ -50,7 +51,10 @@ private extension MelonDSCoreSettingsViewController
return String(format: NSLocalizedString("%@s size could not be determined.", comment: ""), fileURL.lastPathComponent)
case .incorrectHash(let fileURL, let md5Hash, let expectedHash):
return String(format: NSLocalizedString("%@s hash does not match the expected hash.\n\nHash:\n%@\n\nExpected:\n%@.", comment: ""), fileURL.lastPathComponent, md5Hash, expectedHash)
return String(format: NSLocalizedString("%@s checksum does not match the expected checksum.\n\nChecksum:\n%@\n\nExpected:\n%@", comment: ""), fileURL.lastPathComponent, md5Hash, expectedHash)
case .unsupportedHash(let fileURL, let md5Hash):
return String(format: NSLocalizedString("%@ is not compatible with this version of Delta.\n\nChecksum:\n%@", comment: ""), fileURL.lastPathComponent, md5Hash)
case .incorrectSize(let fileURL, let size, let validSizes):
let actualSize = BIOSError.byteFormatter.string(fromByteCount: Int64(size))
@ -435,15 +439,21 @@ extension MelonDSCoreSettingsViewController: UIDocumentPickerDelegate
let measurement = Measurement<UnitInformationStorage>(value: Double(fileSize), unit: .bytes)
guard bios.validFileSizes.contains(where: { $0.contains(measurement) }) else { throw BIOSError.incorrectSize(fileURL, size: fileSize, validSizes: bios.validFileSizes) }
if let expectedMD5Hash = bios.expectedMD5Hash
if bios.expectedMD5Hash != nil || !bios.unsupportedMD5Hashes.isEmpty
{
// If there's an expected hash, make sure it matches.
// Only calculate hash if we need to.
let data = try Data(contentsOf: fileURL)
let md5Hash = Insecure.MD5.hash(data: data)
let hashString = md5Hash.compactMap { String(format: "%02x", $0) }.joined()
guard hashString == expectedMD5Hash else { throw BIOSError.incorrectHash(fileURL, hash: hashString, expectedHash: expectedMD5Hash) }
if let expectedMD5Hash = bios.expectedMD5Hash
{
guard hashString == expectedMD5Hash else { throw BIOSError.incorrectHash(fileURL, hash: hashString, expectedHash: expectedMD5Hash) }
}
guard !bios.unsupportedMD5Hashes.contains(hashString) else { throw BIOSError.unsupportedHash(fileURL, hash: hashString) }
}
}

View File

@ -16,6 +16,7 @@ protocol SystemBIOS
var filename: String { get }
var expectedMD5Hash: String? { get }
var unsupportedMD5Hashes: Set<String> { get }
// RangeSet would be preferable, but it's not in Swift stdlib yet.
@available(iOS 13, *)
@ -27,6 +28,14 @@ extension SystemBIOS
var filename: String {
return self.fileURL.lastPathComponent
}
var expectedMD5Hash: String? {
return nil
}
var unsupportedMD5Hashes: Set<String> {
return []
}
}
enum DSBIOS: SystemBIOS, CaseIterable
@ -88,13 +97,25 @@ enum DSiBIOS: SystemBIOS, CaseIterable
}
}
var expectedMD5Hash: String? {
var unsupportedMD5Hashes: Set<String> {
switch self
{
case .bios7: return "559dae4ea78eb9d67702c56c1d791e81"
case .bios9: return "87b665fce118f76251271c3732532777"
case .firmware: return nil
case .nand: return nil
case .bios7:
return [
"c8b9fe70f1ef5cab8e55540cd1c13dc8", // BIOSDSI7.ROM
"3fbb3f39bd9a96e5d743f138bd4b9907", // BIOSDSI9.ROM
"87b665fce118f76251271c3732532777", // bios9i.bin
]
case .bios9:
return [
"c8b9fe70f1ef5cab8e55540cd1c13dc8", // BIOSDSI7.ROM
"3fbb3f39bd9a96e5d743f138bd4b9907", // BIOSDSI9.ROM
"559dae4ea78eb9d67702c56c1d791e81", // bios7i.bin
]
case .firmware: return []
case .nand: return []
}
}