From 1909851ed4e78dbb46162a020b381c44d165872f Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 10 Mar 2026 13:18:58 -0400 Subject: [PATCH] Add XGD security sector models --- .../Models/Xbox/ChallengeResponseDataXGD23.cs | 31 +++ .../Xbox/DecryptedChallengeResponseXGD23.cs | 47 ++++ .../Models/Xbox/DriveEntryData.cs | 30 +++ .../Xbox/EncryptedChallengeResponseXGD1.cs | 15 ++ .../Xbox/EncryptedChallengeResponseXGD23.cs | 15 ++ .../Models/Xbox/SecuritySector.cs | 66 ++++++ .../Models/Xbox/SecuritySectorXGD1.cs | 190 +++++++++++++++ .../Models/Xbox/SecuritySectorXGD2.cs | 218 ++++++++++++++++++ .../Models/Xbox/SecuritySectorXGD3.cs | 217 +++++++++++++++++ 9 files changed, 829 insertions(+) create mode 100644 SabreTools.Serialization/Models/Xbox/ChallengeResponseDataXGD23.cs create mode 100644 SabreTools.Serialization/Models/Xbox/DecryptedChallengeResponseXGD23.cs create mode 100644 SabreTools.Serialization/Models/Xbox/DriveEntryData.cs create mode 100644 SabreTools.Serialization/Models/Xbox/EncryptedChallengeResponseXGD1.cs create mode 100644 SabreTools.Serialization/Models/Xbox/EncryptedChallengeResponseXGD23.cs create mode 100644 SabreTools.Serialization/Models/Xbox/SecuritySector.cs create mode 100644 SabreTools.Serialization/Models/Xbox/SecuritySectorXGD1.cs create mode 100644 SabreTools.Serialization/Models/Xbox/SecuritySectorXGD2.cs create mode 100644 SabreTools.Serialization/Models/Xbox/SecuritySectorXGD3.cs diff --git a/SabreTools.Serialization/Models/Xbox/ChallengeResponseDataXGD23.cs b/SabreTools.Serialization/Models/Xbox/ChallengeResponseDataXGD23.cs new file mode 100644 index 00000000..660857c3 --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/ChallengeResponseDataXGD23.cs @@ -0,0 +1,31 @@ +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD2/3 challenge response data + /// + public class ChallengeResponseDataXGD23 + { + /// + /// Challenge data + /// + /// 4 bytes + public byte[] ChallengeData { get; set; } = new byte[4]; // 0-3 + + /// + /// Angle + /// + /// Little-endian + public short Angle { get; set; } + + /// + /// Unknown response data + /// + public byte Unknown06 { get; set; } + + /// + /// Angle2 + /// + /// Little-endian + public short Angle2 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/Xbox/DecryptedChallengeResponseXGD23.cs b/SabreTools.Serialization/Models/Xbox/DecryptedChallengeResponseXGD23.cs new file mode 100644 index 00000000..f759c7f1 --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/DecryptedChallengeResponseXGD23.cs @@ -0,0 +1,47 @@ +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD2/3 decrypted challenge response table entry + /// + /// Decrypted form of + public class DecryptedChallengeResponseXGD23 + { + /// + /// Challenge Type + /// + public byte ChallengeType { get; set; } + + /// + /// Challenge ID + /// + public byte ChallengeID { get; set; } + + /// + /// Tolerance + /// + public byte Tolerance { get; set; } + + /// + /// Type + /// + /// TODO: Is there an enum for this? + public byte Type { get; set; } + + /// + /// Challenge data + /// + public byte[] ChallengeData { get; set; } = new byte[4]; + + /// + /// Unknown response data + /// + /// 2 bytes + public byte[] Unknown08 { get; set; } = new byte[2]; + + /// + /// Angle + /// + /// Little-endian + public short Angle { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/Xbox/DriveEntryData.cs b/SabreTools.Serialization/Models/Xbox/DriveEntryData.cs new file mode 100644 index 00000000..e7dec2b5 --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/DriveEntryData.cs @@ -0,0 +1,30 @@ +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD1/2/3 drive entry data + /// + public class DriveEntryData + { + /// + /// Response type + /// + /// TODO: Is there an enum for this? + public byte ResponseType { get; set; } + + /// + /// Challenge ID + /// + public byte ChallengeID { get; set; } + + /// + /// Mod + /// + public byte Mod { get; set; } + + /// + /// Drive response data + /// + /// 6 bytes; Includes SS ranges + public byte[] Data { get; set; } = new byte[6]; + } +} diff --git a/SabreTools.Serialization/Models/Xbox/EncryptedChallengeResponseXGD1.cs b/SabreTools.Serialization/Models/Xbox/EncryptedChallengeResponseXGD1.cs new file mode 100644 index 00000000..ada59d56 --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/EncryptedChallengeResponseXGD1.cs @@ -0,0 +1,15 @@ +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD1 encrypted challenge response + /// + /// Decrypted form is undocumented + public class EncryptedChallengeResponseXGD1 + { + /// + /// Encrypted response data + /// + /// 11 bytes + public byte[] EncryptedData { get; set; } = new byte[11]; + } +} diff --git a/SabreTools.Serialization/Models/Xbox/EncryptedChallengeResponseXGD23.cs b/SabreTools.Serialization/Models/Xbox/EncryptedChallengeResponseXGD23.cs new file mode 100644 index 00000000..c101199b --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/EncryptedChallengeResponseXGD23.cs @@ -0,0 +1,15 @@ +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD2/3 encrypted challenge response + /// + /// Encrypted form of + public class EncryptedChallengeResponseXGD23 + { + /// + /// Encrypted response data + /// + /// 12 bytes + public byte[] EncryptedData { get; set; } = new byte[12]; + } +} diff --git a/SabreTools.Serialization/Models/Xbox/SecuritySector.cs b/SabreTools.Serialization/Models/Xbox/SecuritySector.cs new file mode 100644 index 00000000..3cf04edd --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/SecuritySector.cs @@ -0,0 +1,66 @@ +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD1 security sector data + /// + /// + public abstract class SecuritySector + { + #region PFI Common Data + + /// + /// Version Number (bits 0-3) and Book Type (bits 4-7) + /// + /// Should be 0xD1 (XGD1) or 0xE1 (XGD2/3) + /// TODO: Split into separate properties + public byte VersionNumberAndBookType { get; set; } + + /// + /// Maximum Rate (bits 0-3) and Disc Size (bits 4-7) + /// + /// Should be 0x0F + /// TODO: Split into separate properties + public byte MaximumRateAndDiscSize { get; set; } + + /// + /// Layer Type (bits 0-3), Path (bit 4), Layer Count (bits 5-6), + /// and Reserved (bit 7) + /// + /// Should be 0xA1 + /// TODO: Split into separate properties + public byte LayerTypePathLayerCount { get; set; } + + /// + /// Track Density (bits 0-3) and Linear Density (bits 4-7) + /// + /// Should be 0x10 + /// TODO: Split into separate properties + public byte TrackDensityAndLinearDensity { get; set; } + + /// + /// Data start physical sector + /// + /// Big-endian(?) + public uint DataStartPhysicalSector { get; set; } + + /// + /// Data end physical sector + /// + /// Big-endian(?) + public uint DataEndPhysicalSector { get; set; } + + /// + /// Layer 0 end physical sector + /// + /// Big-endian(?) + public uint Layer0EndPhysicalSector { get; set; } + + /// + /// If 0x10000000, then BCA is present. + /// + /// Bits 0-6 are reserved + public byte BCAFlag { get; set; } + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD1.cs b/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD1.cs new file mode 100644 index 00000000..d9100030 --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD1.cs @@ -0,0 +1,190 @@ +using System; + +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD1 security sector data + /// + /// + public class SecuritySectorXGD1 : SecuritySector + { + // Common PFI data in base class + + /// + /// Reserved + /// + /// 703 bytes, all 0x00 + public byte[] Reserved0011 { get; set; } = new byte[703]; + + /// + /// CPR_MAI key + /// + /// Unknown endianness + public uint CprMaiKey { get; set; } + + /// + /// Reserved + /// + /// 44 bytes, all 0x00 + public byte[] Reserved02D4 { get; set; } = new byte[44]; + + /// + /// Encrypted challenge response table - version + /// + /// Should be 0x01 + public byte EncryptedChallengeResponseTableVersion { get; set; } + + /// + /// Encrypted challenge response table - entries + /// + /// Should be 0x17 + public byte EncryptedChallengeResponseTableEntryCount { get; set; } + + /// + /// Encrypted challenge responses + /// + /// 23 entries + public EncryptedChallengeResponseXGD1[] EncryptedChallengeResponses { get; set; } = new EncryptedChallengeResponseXGD1[23]; + + /// + /// Reserved + /// + /// 32 bytes, all 0x00 + public byte[] Reserved03FF { get; set; } = new byte[32]; + + /// + /// FILETIME - Creation Timestamp? + /// + public ulong CreationTimestamp { get; set; } + + /// + /// Unknown 16 bytes (Certificate GUID?) + /// + public Guid CertificateGuid { get; set; } + + /// + /// Reserved + /// + /// 4 bytes, all 0x00 + public byte[] Reserved0437 { get; set; } = new byte[4]; + + /// + /// Unknown 16 bytes (Authoring GUID?) + /// + public Guid AuthoringGuid { get; set; } + + /// + /// Reserved + /// + /// 84 bytes, all 0x00 + public byte[] Reserved044B { get; set; } = new byte[84]; + + /// + /// FILETIME - Authoring Timestamp + /// + public ulong AuthoringTimestamp { get; set; } + + /// + /// time_t - Certificate Timestamp + /// + /// Early discs are all 0x00, if so then 0x427 is also 0x00 + public uint CertificateTimestamp { get; set; } + + /// + /// Reserved + /// + /// 15 bytes, all 0x00 + public byte[] Reserved04AB { get; set; } = new byte[15]; + + /// + /// Version? + /// + /// Should be 0x01 + public byte Version { get; set; } + + /// + /// Unknown 16 bytes (ISO Mastering GUID?) + /// + public Guid ISOMasteringGuid { get; set; } + + /// + /// SHA-1 hash A + /// + /// 20 bytes + public byte[] SHA1HashA { get; set; } = new byte[20]; + + /// + /// Signature A + /// + /// 256 bytes + public byte[] SignatureA { get; set; } = new byte[256]; + + /// + /// FILETIME - Disc Mastering Timestamp + /// + public ulong DiscMasteringTimestamp { get; set; } + + /// + /// Reserved + /// + /// 4 bytes, all 0x00; meant to be a time_t? + public byte[] Reserved05E7 { get; set; } = new byte[4]; + + /// + /// Reserved + /// + /// 15 bytes, all 0x00 + public byte[] Reserved05EB { get; set; } = new byte[15]; + + /// + /// Unknown + /// + /// 0xFF (XGD1 discs from Mar-2007 onwards are 0x02 like XGD2) + public byte Unknown05FA { get; set; } + + /// + /// Unknown 16 bytes (Disc Mastering GUID? 26 known variations for XGD1) + /// + public Guid DiscMasteringGuid { get; set; } + + /// + /// SHA-1 hash B + /// + /// 20 bytes + public byte[] SHA1HashB { get; set; } = new byte[20]; + + /// + /// Signature B + /// + /// 256 bytes + public byte[] SignatureB { get; set; } = new byte[256]; + + /// + /// SS Version + /// + /// Should be 0x01 + public byte SSVersion { get; set; } + + /// + /// Number of security sector ranges + /// + /// Should be 0x17 + public byte NumberOfSecuritySectorRanges { get; set; } + + /// + /// 23 Challenge Response Data (9 bytes each, includes Security Sector Ranges) + /// + public DriveEntryData[] ChallengeResponses { get; set; } = new DriveEntryData[23]; + + /// + /// Duplicated 23 Challenge Response Data (9 bytes each) + /// + public DriveEntryData[] DuplicatedChallengeResponses { get; set; } = new DriveEntryData[23]; + + /// + /// Reserved + /// + /// Should be 0x00 + public byte Reserved07FF { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD2.cs b/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD2.cs new file mode 100644 index 00000000..8e70624e --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD2.cs @@ -0,0 +1,218 @@ +using System; + +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD2 security sector data + /// + /// + public class SecuritySectorXGD2 : SecuritySector + { + // Common PFI data in base class + + /// + /// Reserved + /// + /// 239 bytes, all 0x00 + public byte[] Reserved0011 { get; set; } = new byte[239]; + + /// + /// Unknown + /// + /// Should be 0x00, 0x00, 0x00, 0x30 + public byte[] Unknown0100 { get; set; } = new byte[4]; + + /// + /// Unknown + /// + /// Should be 0x00, 0x00, 0x06, 0xE0 + public byte[] Unknown0104 { get; set; } = new byte[4]; + + /// + /// Unknown + /// + /// SHA-1? Unique for each ISO + public byte[] Unknown0108 { get; set; } = new byte[20]; + + /// + /// Reserved + /// + /// 228 bytes, all 0x00 + public byte[] Reserved011C { get; set; } = new byte[228]; + + /// + /// 23 Challege Response data (9 bytes each) + /// + public ChallengeResponseDataXGD23[] ChallengeResponses { get; set; } = new ChallengeResponseDataXGD23[23]; + + /// + /// Reserved + /// + /// Should be 0x00 + public byte Reserved02CF { get; set; } + + /// + /// CPR_MAI key + /// + /// Unknown endianness + public uint CprMaiKey { get; set; } + + /// + /// Reserved + /// + /// 44 bytes, all 0x00 + public byte[] Reserved02D4 { get; set; } = new byte[44]; + + /// + /// Encrypted challenge response table - version + /// + /// Should be 0x01 + public byte EncryptedChallengeResponseTableVersion { get; set; } + + /// + /// Encrypted challenge response table - entries + /// + /// Should be 0x17 + public byte EncryptedChallengeResponseTableEntryCount { get; set; } + + /// + /// Reserved + /// + /// 2 bytes, all 0x00 + public byte[] Reserved0302 { get; set; } = new byte[2]; + + /// + /// Encrypted challenge responses + /// + /// 21 entries + public EncryptedChallengeResponseXGD23[] EncryptedChallengeResponses { get; set; } = new EncryptedChallengeResponseXGD23[21]; + + /// + /// Reserved + /// + /// 96 bytes, all 0x00 + public byte[] Reserved0400 { get; set; } = new byte[96]; + + /// + /// Media ID + /// + /// 16 bytes + public byte[] MediaID { get; set; } = new byte[16]; + + /// + /// Reserved + /// + /// 46 bytes, all 0x00 + public byte[] Reserved0470 { get; set; } = new byte[46]; + + /// + /// Unknown + /// + /// Should be 0x04 + public byte Unknown049E { get; set; } + + /// + /// FILETIME - Authoring Timestamp + /// + public ulong AuthoringTimestamp { get; set; } + + /// + /// Reserved + /// + /// 19 bytes, all 0x00 + public byte[] Reserved04A7 { get; set; } = new byte[19]; + + /// + /// Version? + /// + /// Should be 0x02 + public byte Version { get; set; } + + /// + /// Unknown 16 bytes (ISO Mastering GUID?) + /// + public Guid ISOMasteringGuid { get; set; } + + /// + /// SHA-1 hash A + /// + /// 20 bytes + public byte[] SHA1HashA { get; set; } = new byte[20]; + + /// + /// Signature A + /// + /// 256 bytes + public byte[] SignatureA { get; set; } = new byte[256]; + + /// + /// FILETIME - Disc Mastering Timestamp + /// + public ulong DiscMasteringTimestamp { get; set; } + + /// + /// Reserved + /// + /// 4 bytes, all 0x00; meant to be a time_t? + public byte[] Reserved05E7 { get; set; } = new byte[4]; + + /// + /// Reserved + /// + /// 15 bytes, all 0x00 + public byte[] Reserved05EB { get; set; } = new byte[15]; + + /// + /// Unknown + /// + /// Should be 0x02 + public byte Unknown05FA { get; set; } + + /// + /// Unknown 16 bytes (Disc Mastering GUID?) + /// + public Guid DiscMasteringGuid { get; set; } + + /// + /// SHA-1 hash B + /// + /// 20 bytes + public byte[] SHA1HashB { get; set; } = new byte[20]; + + /// + /// Signature B + /// + /// 256 bytes + public byte[] SignatureB { get; set; } = new byte[256]; + + /// + /// SS Version + /// + /// Should be 0x02 + public byte SSVersion { get; set; } + + /// + /// Number of security sector ranges + /// + /// Should be 0x15 + public byte NumberOfSecuritySectorRanges { get; set; } + + /// + /// 21 Security Sector Ranges (9 bytes each) + /// + /// Actually 23 entries + public DriveEntryData[] DriveEntries { get; set; } = new DriveEntryData[23]; + + /// + /// Duplicated 21 Security Sector Ranges (9 bytes each) + /// + /// Actually 23 entries + public DriveEntryData[] DuplicatedDriveEntries { get; set; } = new DriveEntryData[23]; + + /// + /// Reserved + /// + /// Should be 0x00 + public byte Reserved07FF { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD3.cs b/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD3.cs new file mode 100644 index 00000000..fe693a5c --- /dev/null +++ b/SabreTools.Serialization/Models/Xbox/SecuritySectorXGD3.cs @@ -0,0 +1,217 @@ +using System; + +namespace SabreTools.Data.Models.Xbox +{ + /// + /// XGD2 security sector data + /// + /// + public class SecuritySectorXGD3 : SecuritySector + { + // Common PFI data in base class + + /// + /// Reserved + /// + /// 10 bytes, all 0x00 + public byte[] Reserved0011 { get; set; } = new byte[10]; + + /// + /// Unknown + /// + /// Should be 0x06 + public byte Unknown001B { get; set; } + + /// + /// Reserved + /// + /// 4 bytes, all 0x00 + public byte[] Reserved001C { get; set; } = new byte[4]; + + /// + /// 23 Challege Response data (9 bytes each), usually only 8 + /// + public ChallengeResponseDataXGD23[] ChallengeResponses { get; set; } = new ChallengeResponseDataXGD23[23]; + + /// + /// Reserved + /// + /// Should be 0x00 + public byte Reserved00EF { get; set; } + + /// + /// CPR_MAI key + /// + /// Unknown endianness + public uint CprMaiKey { get; set; } + + /// + /// Unknown + /// + public byte[] Unknown0100 { get; set; } = new byte[4]; + + /// + /// Unknown + /// + /// Should be 0x00, 0x00, 0x06, 0xE0 + public byte[] Unknown0104 { get; set; } = new byte[4]; + + /// + /// Unknown + /// + /// 506 bytes + public byte[] Unknown0108 { get; set; } = new byte[506]; + + /// + /// Encrypted challenge response table - version + /// + /// Should be 0x02 + public byte EncryptedChallengeResponseTableVersion { get; set; } + + /// + /// Encrypted challenge response table - entries + /// + /// Should be 0x15 + public byte EncryptedChallengeResponseTableEntryCount { get; set; } + + /// + /// Reserved + /// + /// 2 bytes, all 0x00 + public byte[] Reserved0302 { get; set; } = new byte[2]; + + /// + /// Encrypted challenge responses + /// + /// 21 entries + public EncryptedChallengeResponseXGD23[] EncryptedChallengeResponses { get; set; } = new EncryptedChallengeResponseXGD23[21]; + + /// + /// Reserved + /// + /// 96 bytes, all 0x00 + public byte[] Reserved0400 { get; set; } = new byte[96]; + + /// + /// Media ID + /// + /// 16 bytes + public byte[] MediaID { get; set; } = new byte[16]; + + /// + /// Reserved + /// + /// 46 bytes, all 0x00 + public byte[] Reserved0470 { get; set; } = new byte[46]; + + /// + /// Unknown + /// + /// Should be 0x04 + public byte Unknown049E { get; set; } + + /// + /// FILETIME - Authoring Timestamp + /// + public ulong AuthoringTimestamp { get; set; } + + /// + /// Reserved + /// + /// 19 bytes, all 0x00 + public byte[] Reserved04A7 { get; set; } = new byte[19]; + + /// + /// Version? + /// + /// Should be 0x02 + public byte Version { get; set; } + + /// + /// Unknown 16 bytes (ISO Mastering GUID?) + /// + public Guid ISOMasteringGuid { get; set; } + + /// + /// SHA-1 hash A + /// + /// 20 bytes + public byte[] SHA1HashA { get; set; } = new byte[20]; + + /// + /// Signature A + /// + /// 256 bytes + public byte[] SignatureA { get; set; } = new byte[256]; + + /// + /// FILETIME - Disc Mastering Timestamp + /// + public ulong DiscMasteringTimestamp { get; set; } + + /// + /// Reserved + /// + /// 4 bytes, all 0x00; meant to be a time_t? + public byte[] Reserved05E7 { get; set; } = new byte[4]; + + /// + /// Reserved + /// + /// 15 bytes, all 0x00 + public byte[] Reserved05EB { get; set; } = new byte[15]; + + /// + /// Unknown + /// + /// Should be 0x02 + public byte Unknown05FA { get; set; } + + /// + /// Unknown 16 bytes (Disc Mastering GUID?) + /// + public Guid DiscMasteringGuid { get; set; } + + /// + /// SHA-1 hash B + /// + /// 20 bytes + public byte[] SHA1HashB { get; set; } = new byte[20]; + + /// + /// Signature B + /// + /// 256 bytes + public byte[] SignatureB { get; set; } = new byte[256]; + + /// + /// SS Version + /// + /// Should be 0x02 + public byte SSVersion { get; set; } + + /// + /// Number of security sector ranges + /// + /// Should be 0x15 + public byte NumberOfSecuritySectorRanges { get; set; } + + /// + /// 21 Security Sector Ranges (9 bytes each) + /// + /// Actually 23 entries + public DriveEntryData[] DriveEntries { get; set; } = new DriveEntryData[23]; + + /// + /// Duplicated 21 Security Sector Ranges (9 bytes each) + /// + /// Actually 23 entries + public DriveEntryData[] DuplicatedDriveEntries { get; set; } = new DriveEntryData[23]; + + /// + /// Reserved + /// + /// Should be 0x00 + public byte Reserved07FF { get; set; } + } +}