Decrypt CSS images on conversion

This commit is contained in:
Rebecca Wallander
2023-07-29 23:50:37 +02:00
parent 1eb45e5cac
commit e7ede15234
7 changed files with 5409 additions and 8248 deletions

View File

@@ -181,7 +181,7 @@ partial class Dump
outputFormat.WriteSectorTag(titleKey.Value.Key, i + j, SectorTagType.DvdTitleKey); outputFormat.WriteSectorTag(titleKey.Value.Key, i + j, SectorTagType.DvdTitleKey);
_resume.MissingTitleKeys.Remove(i + j); _resume.MissingTitleKeys.Remove(i + j);
CSS.DecryptTitleKey(0, discKey, titleKey.Value.Key, out tmpBuf); CSS.DecryptTitleKey(discKey, titleKey.Value.Key, out tmpBuf);
outputFormat.WriteSectorTag(tmpBuf, i + j, SectorTagType.DvdTitleKeyDecrypted); outputFormat.WriteSectorTag(tmpBuf, i + j, SectorTagType.DvdTitleKeyDecrypted);
} }
@@ -203,7 +203,7 @@ partial class Dump
ErrorMessage?. ErrorMessage?.
Invoke(string.Format(Localization.Core.Error_retrieving_title_key_for_sector_0, i)); Invoke(string.Format(Localization.Core.Error_retrieving_title_key_for_sector_0, i));
else else
buffer = CSS.DecryptSector(buffer, cmi, titleKey, blocksToRead, blockSize); buffer = CSS.DecryptSector(buffer, titleKey, cmi, blocksToRead, blockSize);
} }
} }
} }

View File

@@ -409,7 +409,7 @@ partial class Dump
if(discKey != null) if(discKey != null)
{ {
CSS.DecryptTitleKey(0, discKey, titleKey.Value.Key, out buffer); CSS.DecryptTitleKey(discKey, titleKey.Value.Key, out buffer);
outputFormat.WriteSectorTag(buffer, missingKey, SectorTagType.DvdTitleKeyDecrypted); outputFormat.WriteSectorTag(buffer, missingKey, SectorTagType.DvdTitleKeyDecrypted);
} }

View File

@@ -1759,9 +1759,6 @@ public sealed partial class AaruFormat
trk.EndSector == 0) trk.EndSector == 0)
return ErrorNumber.SectorNotFound; return ErrorNumber.SectorNotFound;
if(trk.Type == TrackType.Data)
return ErrorNumber.NotSupported;
switch(tag) switch(tag)
{ {
case SectorTagType.CdSectorEcc: case SectorTagType.CdSectorEcc:

File diff suppressed because it is too large Load Diff

View File

@@ -959,6 +959,9 @@ In you are unsure, please press N to not continue.</value>
<data name="Generates_subchannels_help" xml:space="preserve"> <data name="Generates_subchannels_help" xml:space="preserve">
<value>Generates missing subchannels.</value> <value>Generates missing subchannels.</value>
</data> </data>
<data name="Decrypt_sectors_help" xml:space="preserve">
<value>Try to decrypt encrypted sectors.</value>
</data>
<data name="Input_image_path" xml:space="preserve"> <data name="Input_image_path" xml:space="preserve">
<value>Input image path</value> <value>Input image path</value>
</data> </data>
@@ -3012,4 +3015,7 @@ Do you want to continue?</value>
<data name="Dump_graph_dimensions_argument_help" xml:space="preserve"> <data name="Dump_graph_dimensions_argument_help" xml:space="preserve">
<value>Dimensions in pixels of the square that will contain the graph of dumped media.</value> <value>Dimensions in pixels of the square that will contain the graph of dumped media.</value>
</data> </data>
<data name="Generating_decryption_keys" xml:space="preserve">
<value>Decryption keys not found. Trying to generate keys.</value>
</data>
</root> </root>

View File

@@ -47,6 +47,7 @@ using Aaru.CommonTypes.Metadata;
using Aaru.Console; using Aaru.Console;
using Aaru.Core; using Aaru.Core;
using Aaru.Core.Media; using Aaru.Core.Media;
using Aaru.Decryption.DVD;
using Aaru.Devices; using Aaru.Devices;
using Aaru.Localization; using Aaru.Localization;
using Schemas; using Schemas;
@@ -54,6 +55,7 @@ using Spectre.Console;
using File = System.IO.File; using File = System.IO.File;
using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo; using ImageInfo = Aaru.CommonTypes.Structs.ImageInfo;
using MediaType = Aaru.CommonTypes.MediaType; using MediaType = Aaru.CommonTypes.MediaType;
using Partition = Aaru.CommonTypes.Partition;
using TapeFile = Aaru.CommonTypes.Structs.TapeFile; using TapeFile = Aaru.CommonTypes.Structs.TapeFile;
using TapePartition = Aaru.CommonTypes.Structs.TapePartition; using TapePartition = Aaru.CommonTypes.Structs.TapePartition;
using Track = Aaru.CommonTypes.Structs.Track; using Track = Aaru.CommonTypes.Structs.Track;
@@ -144,6 +146,11 @@ sealed class ConvertImageCommand : Command
"--generate-subchannels" "--generate-subchannels"
}, () => false, UI.Generates_subchannels_help)); }, () => false, UI.Generates_subchannels_help));
Add(new Option<bool>(new[]
{
"--decrypt"
}, () => false, UI.Decrypt_sectors_help));
Add(new Option<string>(new[] Add(new Option<string>(new[]
{ {
"--aaru-metadata", "-m" "--aaru-metadata", "-m"
@@ -173,7 +180,7 @@ sealed class ConvertImageCommand : Command
int mediaSequence, string mediaSerialNumber, string mediaTitle, string outputPath, int mediaSequence, string mediaSerialNumber, string mediaTitle, string outputPath,
string options, string resumeFile, string format, string geometry, string options, string resumeFile, string format, string geometry,
bool fixSubchannelPosition, bool fixSubchannel, bool fixSubchannelCrc, bool fixSubchannelPosition, bool fixSubchannel, bool fixSubchannelCrc,
bool generateSubchannels, string aaruMetadata) bool generateSubchannels, bool decrypt, string aaruMetadata)
{ {
MainClass.PrintCopyright(); MainClass.PrintCopyright();
@@ -239,6 +246,7 @@ sealed class ConvertImageCommand : Command
AaruConsole.DebugWriteLine("Image convert command", "--fix-subchannel={0}", fixSubchannel); AaruConsole.DebugWriteLine("Image convert command", "--fix-subchannel={0}", fixSubchannel);
AaruConsole.DebugWriteLine("Image convert command", "--fix-subchannel-crc={0}", fixSubchannelCrc); AaruConsole.DebugWriteLine("Image convert command", "--fix-subchannel-crc={0}", fixSubchannelCrc);
AaruConsole.DebugWriteLine("Image convert command", "--generate-subchannels={0}", generateSubchannels); AaruConsole.DebugWriteLine("Image convert command", "--generate-subchannels={0}", generateSubchannels);
AaruConsole.DebugWriteLine("Image convert command", "--decrypt={0}", decrypt);
AaruConsole.DebugWriteLine("Image convert command", "--aaru-metadata={0}", aaruMetadata); AaruConsole.DebugWriteLine("Image convert command", "--aaru-metadata={0}", aaruMetadata);
Dictionary<string, string> parsedOptions = Core.Options.Parse(options); Dictionary<string, string> parsedOptions = Core.Options.Parse(options);
@@ -766,12 +774,16 @@ sealed class ConvertImageCommand : Command
ErrorNumber errno = ErrorNumber.NoError; ErrorNumber errno = ErrorNumber.NoError;
if(decrypt)
AaruConsole.WriteLine("Decrypting encrypted sectors.");
AnsiConsole.Progress().AutoClear(true).HideCompleted(true). AnsiConsole.Progress().AutoClear(true).HideCompleted(true).
Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn()). Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn()).
Start(ctx => Start(ctx =>
{ {
ProgressTask discTask = ctx.AddTask(UI.Converting_disc); ProgressTask discTask = ctx.AddTask(UI.Converting_disc);
discTask.MaxValue = inputOptical.Tracks.Count; discTask.MaxValue = inputOptical.Tracks.Count;
byte[] generatedTitleKeys = null;
foreach(Track track in inputOptical.Tracks) foreach(Track track in inputOptical.Tracks)
{ {
@@ -861,6 +873,104 @@ sealed class ConvertImageCommand : Command
: inputOptical.ReadSectors(doneSectors + track.StartSector, : inputOptical.ReadSectors(doneSectors + track.StartSector,
sectorsToDo, out sector); sectorsToDo, out sector);
// TODO: Move to generic place when anything but CSS DVDs can be decrypted
if(inputOptical.Info.MediaType is MediaType.DVDROM or MediaType.DVDR
or MediaType.DVDRDL or MediaType.DVDPR or MediaType.DVDPRDL && decrypt)
{
// Only sectors which are MPEG packets can be encrypted.
if(MPEG.ContainsMpegPackets(sector, sectorsToDo))
{
byte[] cmi, titleKey;
if(sectorsToDo == 1)
{
if(inputOptical.ReadSectorTag(doneSectors + track.StartSector,
SectorTagType.DvdCmi, out cmi) == ErrorNumber.NoError &&
inputOptical.ReadSectorTag(doneSectors + track.StartSector,
SectorTagType.DvdTitleKeyDecrypted, out titleKey) ==
ErrorNumber.NoError)
sector = CSS.DecryptSector(sector, titleKey, cmi);
else
{
if(generatedTitleKeys == null)
{
List<Partition> partitions =
Aaru.Core.Partitions.GetAll(inputOptical);
partitions = partitions.FindAll(p =>
{
Core.Filesystems.Identify(inputOptical,
out List<string> idPlugins, p);
return idPlugins.Contains("iso9660 filesystem");
});
if(plugins.ReadOnlyFilesystems.
TryGetValue("iso9660 filesystem",
out Type pluginType))
{
AaruConsole.DebugWriteLine("Convert-image command",
UI.Generating_decryption_keys);
generatedTitleKeys = CSS.GenerateTitleKeys(inputOptical,
partitions, trackSectors, pluginType);
}
}
if(generatedTitleKeys != null)
sector = CSS.DecryptSector(sector,
generatedTitleKeys.
Skip((int)(5 * (doneSectors + track.StartSector))).
Take(5).ToArray(), null);
}
}
else
{
if(inputOptical.ReadSectorsTag(doneSectors + track.StartSector,
sectorsToDo, SectorTagType.DvdCmi, out cmi) ==
ErrorNumber.NoError &&
inputOptical.ReadSectorsTag(doneSectors + track.StartSector,
sectorsToDo, SectorTagType.DvdTitleKeyDecrypted,
out titleKey) == ErrorNumber.NoError)
sector = CSS.DecryptSector(sector, titleKey, cmi, sectorsToDo);
else
{
if(generatedTitleKeys == null)
{
List<Partition> partitions =
Aaru.Core.Partitions.GetAll(inputOptical);
partitions = partitions.FindAll(p =>
{
Core.Filesystems.Identify(inputOptical,
out List<string> idPlugins, p);
return idPlugins.Contains("iso9660 filesystem");
});
if(plugins.ReadOnlyFilesystems.
TryGetValue("iso9660 filesystem",
out Type pluginType))
{
AaruConsole.DebugWriteLine("Convert-image command",
UI.Generating_decryption_keys);
generatedTitleKeys = CSS.GenerateTitleKeys(inputOptical,
partitions, trackSectors, pluginType);
}
}
if(generatedTitleKeys != null)
sector = CSS.DecryptSector(sector,
generatedTitleKeys.
Skip((int)(5 * (doneSectors + track.StartSector))).
Take((int)(5 * sectorsToDo)).ToArray(), null,
sectorsToDo);
}
}
}
}
if(errno == ErrorNumber.NoError) if(errno == ErrorNumber.NoError)
result = sectorsToDo == 1 result = sectorsToDo == 1
? outputOptical.WriteSector(sector, ? outputOptical.WriteSector(sector,