[Aaru.Decryption] Reformat and cleanup.

This commit is contained in:
2023-10-03 23:10:41 +01:00
parent ac1db3b2e9
commit 4ce6ff54c8
10 changed files with 1615 additions and 1597 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -33,8 +33,8 @@
<NoWarn>CS1591;CS1574</NoWarn> <NoWarn>CS1591;CS1574</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<InternalsVisibleTo Include="Aaru.Tests" /> <InternalsVisibleTo Include="Aaru.Tests"/>
<InternalsVisibleTo Include="Aaru.Tests.Devices" /> <InternalsVisibleTo Include="Aaru.Tests.Devices"/>
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>
<NrtRevisionFormat>$(Version)+{chash:8}</NrtRevisionFormat> <NrtRevisionFormat>$(Version)+{chash:8}</NrtRevisionFormat>
@@ -43,9 +43,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Aaru.Decoders\Aaru.Decoders.csproj" /> <ProjectReference Include="..\Aaru.Decoders\Aaru.Decoders.csproj"/>
<ProjectReference Include="..\Aaru.Devices\Aaru.Devices.csproj" /> <ProjectReference Include="..\Aaru.Devices\Aaru.Devices.csproj"/>
<ProjectReference Include="..\Aaru.Images\Aaru.Images.csproj" /> <ProjectReference Include="..\Aaru.Images\Aaru.Images.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,2 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xml:space="preserve">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=localization/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=localization/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -58,99 +58,17 @@ public class CSS
{ {
static readonly byte[,] _playerKeys = static readonly byte[,] _playerKeys =
{ {
{ { 0x01, 0xaf, 0xe3, 0x12, 0x80 }, { 0x12, 0x11, 0xca, 0x04, 0x3b }, { 0x14, 0x0c, 0x9e, 0xd0, 0x09 },
0x01, 0xaf, 0xe3, 0x12, 0x80 { 0x14, 0x71, 0x35, 0xba, 0xe2 }, { 0x1a, 0xa4, 0x33, 0x21, 0xa6 }, { 0x26, 0xec, 0xc4, 0xa7, 0x4e },
}, { 0x2c, 0xb2, 0xc1, 0x09, 0xee }, { 0x2f, 0x25, 0x9e, 0x96, 0xdd }, { 0x33, 0x2f, 0x49, 0x6c, 0xe0 },
{ { 0x35, 0x5b, 0xc1, 0x31, 0x0f }, { 0x36, 0x67, 0xb2, 0xe3, 0x85 }, { 0x39, 0x3d, 0xf1, 0xf1, 0xbd },
0x12, 0x11, 0xca, 0x04, 0x3b { 0x3b, 0x31, 0x34, 0x0d, 0x91 }, { 0x45, 0xed, 0x28, 0xeb, 0xd3 }, { 0x48, 0xb7, 0x6c, 0xce, 0x69 },
}, { 0x4b, 0x65, 0x0d, 0xc1, 0xee }, { 0x4c, 0xbb, 0xf5, 0x5b, 0x23 }, { 0x51, 0x67, 0x67, 0xc5, 0xe0 },
{ { 0x53, 0x94, 0xe1, 0x75, 0xbf }, { 0x57, 0x2c, 0x8b, 0x31, 0xae }, { 0x63, 0xdb, 0x4c, 0x5b, 0x4a },
0x14, 0x0c, 0x9e, 0xd0, 0x09 { 0x7b, 0x1e, 0x5e, 0x2b, 0x57 }, { 0x85, 0xf3, 0x85, 0xa0, 0xe0 }, { 0xab, 0x1e, 0xe7, 0x7b, 0x72 },
}, { 0xab, 0x36, 0xe3, 0xeb, 0x76 }, { 0xb1, 0xb8, 0xf9, 0x38, 0x03 }, { 0xb8, 0x5d, 0xd8, 0x53, 0xbd },
{ { 0xbf, 0x92, 0xc3, 0xb0, 0xe2 }, { 0xcf, 0x1a, 0xb2, 0xf8, 0x0a }, { 0xec, 0xa0, 0xcf, 0xb3, 0xff },
0x14, 0x71, 0x35, 0xba, 0xe2 { 0xfc, 0x95, 0xa9, 0x87, 0x35 }
},
{
0x1a, 0xa4, 0x33, 0x21, 0xa6
},
{
0x26, 0xec, 0xc4, 0xa7, 0x4e
},
{
0x2c, 0xb2, 0xc1, 0x09, 0xee
},
{
0x2f, 0x25, 0x9e, 0x96, 0xdd
},
{
0x33, 0x2f, 0x49, 0x6c, 0xe0
},
{
0x35, 0x5b, 0xc1, 0x31, 0x0f
},
{
0x36, 0x67, 0xb2, 0xe3, 0x85
},
{
0x39, 0x3d, 0xf1, 0xf1, 0xbd
},
{
0x3b, 0x31, 0x34, 0x0d, 0x91
},
{
0x45, 0xed, 0x28, 0xeb, 0xd3
},
{
0x48, 0xb7, 0x6c, 0xce, 0x69
},
{
0x4b, 0x65, 0x0d, 0xc1, 0xee
},
{
0x4c, 0xbb, 0xf5, 0x5b, 0x23
},
{
0x51, 0x67, 0x67, 0xc5, 0xe0
},
{
0x53, 0x94, 0xe1, 0x75, 0xbf
},
{
0x57, 0x2c, 0x8b, 0x31, 0xae
},
{
0x63, 0xdb, 0x4c, 0x5b, 0x4a
},
{
0x7b, 0x1e, 0x5e, 0x2b, 0x57
},
{
0x85, 0xf3, 0x85, 0xa0, 0xe0
},
{
0xab, 0x1e, 0xe7, 0x7b, 0x72
},
{
0xab, 0x36, 0xe3, 0xeb, 0x76
},
{
0xb1, 0xb8, 0xf9, 0x38, 0x03
},
{
0xb8, 0x5d, 0xd8, 0x53, 0xbd
},
{
0xbf, 0x92, 0xc3, 0xb0, 0xe2
},
{
0xcf, 0x1a, 0xb2, 0xf8, 0x0a
},
{
0xec, 0xa0, 0xcf, 0xb3, 0xff
},
{
0xfc, 0x95, 0xa9, 0x87, 0x35
}
}; };
static readonly byte[] _cssTable1 = static readonly byte[] _cssTable1 =
@@ -341,15 +259,7 @@ public class CSS
static readonly byte[,] _permutationChallenge = static readonly byte[,] _permutationChallenge =
{ {
{ { 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 }, { 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 }, { 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 }
1, 3, 0, 7, 5, 2, 9, 6, 4, 8
},
{
6, 1, 9, 3, 8, 5, 7, 4, 0, 2
},
{
4, 0, 3, 5, 7, 2, 8, 6, 1, 9
}
}; };
static readonly byte[,] _permutationVariant = static readonly byte[,] _permutationVariant =
@@ -370,10 +280,7 @@ public class CSS
0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B, 0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01 0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B, 0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01
}; };
static readonly byte[] _secret = static readonly byte[] _secret = { 0x55, 0xD6, 0xC4, 0xC5, 0x28 };
{
0x55, 0xD6, 0xC4, 0xC5, 0x28
};
/// <summary> /// <summary>
/// The disc key returned by the logical unit is encoded with the bus key to prevent man-in-the-middle attacks. /// The disc key returned by the logical unit is encoded with the bus key to prevent man-in-the-middle attacks.
@@ -391,7 +298,7 @@ public class CSS
byte[] key = response.Skip(4).Take(2048).ToArray(); byte[] key = response.Skip(4).Take(2048).ToArray();
for(uint i = 0; i < key.Length; i++) for(uint i = 0; i < key.Length; i++)
key[i] ^= busKey[4 - (i % busKey.Length)]; key[i] ^= busKey[4 - i % busKey.Length];
return new CSS_CPRM.DiscKey return new CSS_CPRM.DiscKey
{ {
@@ -418,7 +325,7 @@ public class CSS
byte[] key = response.Skip(5).Take(5).ToArray(); byte[] key = response.Skip(5).Take(5).ToArray();
for(uint i = 0; i < key.Length; i++) for(uint i = 0; i < key.Length; i++)
key[i] ^= busKey[4 - (i % busKey.Length)]; key[i] ^= busKey[4 - i % busKey.Length];
return new CSS_CPRM.TitleKey return new CSS_CPRM.TitleKey
{ {
@@ -440,49 +347,49 @@ public class CSS
/// <returns>The encrypted key.</returns> /// <returns>The encrypted key.</returns>
public static void EncryptKey(DvdCssKeyType keyType, uint variant, byte[] challenge, out byte[] key) public static void EncryptKey(DvdCssKeyType keyType, uint variant, byte[] challenge, out byte[] key)
{ {
byte[] bits = new byte[30]; var bits = new byte[30];
byte[] scratch = new byte[10]; var scratch = new byte[10];
byte index = sizeof(byte) * 30; byte index = sizeof(byte) * 30;
byte[] temp1 = new byte[5]; var temp1 = new byte[5];
byte[] temp2 = new byte[5]; var temp2 = new byte[5];
byte carry = 0; byte carry = 0;
key = new byte[5]; key = new byte[5];
for(int i = 9; i >= 0; --i) for(var i = 9; i >= 0; --i)
scratch[i] = challenge[_permutationChallenge[(uint)keyType, i]]; scratch[i] = challenge[_permutationChallenge[(uint)keyType, i]];
byte cssVariant = (byte)(keyType == 0 ? variant : _permutationVariant[(uint)keyType - 1, variant]); var cssVariant = (byte)(keyType == 0 ? variant : _permutationVariant[(uint)keyType - 1, variant]);
for(int i = 5; --i >= 0;) for(var i = 5; --i >= 0;)
temp1[i] = (byte)(scratch[5 + i] ^ _secret[i] ^ _encryptTable2[i]); temp1[i] = (byte)(scratch[5 + i] ^ _secret[i] ^ _encryptTable2[i]);
uint lfsr0 = (uint)((temp1[0] << 17) | (temp1[1] << 9) | ((temp1[2] & ~7) << 1) | 8 | (temp1[2] & 7)); var lfsr0 = (uint)(temp1[0] << 17 | temp1[1] << 9 | (temp1[2] & ~7) << 1 | 8 | temp1[2] & 7);
uint lfsr1 = (uint)((temp1[3] << 9) | 0x100 | temp1[4]); var lfsr1 = (uint)(temp1[3] << 9 | 0x100 | temp1[4]);
do do
{ {
byte val = 0; byte val = 0;
for(int bit = 0; bit < 8; ++bit) for(var bit = 0; bit < 8; ++bit)
{ {
byte oLfsr0 = (byte)(((lfsr0 >> 24) ^ (lfsr0 >> 21) ^ (lfsr0 >> 20) ^ (lfsr0 >> 12)) & 1); var oLfsr0 = (byte)((lfsr0 >> 24 ^ lfsr0 >> 21 ^ lfsr0 >> 20 ^ lfsr0 >> 12) & 1);
lfsr0 = (lfsr0 << 1) | oLfsr0; lfsr0 = lfsr0 << 1 | oLfsr0;
byte oLfsr1 = (byte)(((lfsr1 >> 16) ^ (lfsr1 >> 2)) & 1); var oLfsr1 = (byte)((lfsr1 >> 16 ^ lfsr1 >> 2) & 1);
lfsr1 = (lfsr1 << 1) | oLfsr1; lfsr1 = lfsr1 << 1 | oLfsr1;
byte combined = (byte)(Convert.ToByte(oLfsr1 == 0) + carry + Convert.ToByte(oLfsr0 == 0)); var combined = (byte)(Convert.ToByte(oLfsr1 == 0) + carry + Convert.ToByte(oLfsr0 == 0));
carry = (byte)((combined >> 1) & 1); carry = (byte)(combined >> 1 & 1);
val |= (byte)((combined & 1) << bit); val |= (byte)((combined & 1) << bit);
} }
bits[--index] = val; bits[--index] = val;
} while(index > 0); } while(index > 0);
byte cse = (byte)(_variants[cssVariant] ^ _encryptTable2[cssVariant]); var cse = (byte)(_variants[cssVariant] ^ _encryptTable2[cssVariant]);
int term = 0; var term = 0;
for(int i = 5; --i >= 0; term = scratch[i]) for(var i = 5; --i >= 0; term = scratch[i])
{ {
index = (byte)(bits[25 + i] ^ scratch[i]); index = (byte)(bits[25 + i] ^ scratch[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
@@ -493,7 +400,7 @@ public class CSS
temp1[4] ^= temp1[0]; temp1[4] ^= temp1[0];
term = 0; term = 0;
for(int i = 5; --i >= 0; term = temp1[i]) for(var i = 5; --i >= 0; term = temp1[i])
{ {
index = (byte)(bits[20 + i] ^ temp1[i]); index = (byte)(bits[20 + i] ^ temp1[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
@@ -504,7 +411,7 @@ public class CSS
temp2[4] ^= temp2[0]; temp2[4] ^= temp2[0];
term = 0; term = 0;
for(int i = 5; --i >= 0; term = temp2[i]) for(var i = 5; --i >= 0; term = temp2[i])
{ {
index = (byte)(bits[15 + i] ^ temp2[i]); index = (byte)(bits[15 + i] ^ temp2[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
@@ -516,7 +423,7 @@ public class CSS
temp1[4] ^= temp1[0]; temp1[4] ^= temp1[0];
term = 0; term = 0;
for(int i = 5; --i >= 0; term = temp1[i]) for(var i = 5; --i >= 0; term = temp1[i])
{ {
index = (byte)(bits[10 + i] ^ temp1[i]); index = (byte)(bits[10 + i] ^ temp1[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
@@ -528,7 +435,7 @@ public class CSS
temp2[4] ^= temp2[0]; temp2[4] ^= temp2[0];
term = 0; term = 0;
for(int i = 5; --i >= 0; term = temp2[i]) for(var i = 5; --i >= 0; term = temp2[i])
{ {
index = (byte)(bits[5 + i] ^ temp2[i]); index = (byte)(bits[5 + i] ^ temp2[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
@@ -539,7 +446,7 @@ public class CSS
temp1[4] ^= temp1[0]; temp1[4] ^= temp1[0];
term = 0; term = 0;
for(int i = 5; --i >= 0; term = temp1[i]) for(var i = 5; --i >= 0; term = temp1[i])
{ {
index = (byte)(bits[i] ^ temp1[i]); index = (byte)(bits[i] ^ temp1[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
@@ -556,27 +463,27 @@ public class CSS
static void DecryptKey(byte invert, byte[] cryptoKey, byte[] encryptedKey, out byte[] decryptedKey) static void DecryptKey(byte invert, byte[] cryptoKey, byte[] encryptedKey, out byte[] decryptedKey)
{ {
decryptedKey = new byte[5]; decryptedKey = new byte[5];
byte[] k = new byte[5]; var k = new byte[5];
uint lfsr1Lo = (uint)(cryptoKey[0] | 0x100); var lfsr1Lo = (uint)(cryptoKey[0] | 0x100);
uint lfsr1Hi = cryptoKey[1]; uint lfsr1Hi = cryptoKey[1];
uint lfsr0 = (uint)(((cryptoKey[4] << 17) | (cryptoKey[3] << 9) | (cryptoKey[2] << 1)) + 8 - var lfsr0 = (uint)((cryptoKey[4] << 17 | cryptoKey[3] << 9 | cryptoKey[2] << 1) + 8 -
(cryptoKey[2] & 7)); (cryptoKey[2] & 7));
lfsr0 = (uint)((_cssTable4[lfsr0 & 0xff] << 24) | (_cssTable4[(lfsr0 >> 8) & 0xff] << 16) | lfsr0 = (uint)(_cssTable4[lfsr0 & 0xff] << 24 | _cssTable4[lfsr0 >> 8 & 0xff] << 16 |
(_cssTable4[(lfsr0 >> 16) & 0xff] << 8) | _cssTable4[(lfsr0 >> 24) & 0xff]); _cssTable4[lfsr0 >> 16 & 0xff] << 8 | _cssTable4[lfsr0 >> 24 & 0xff]);
uint combined = 0; uint combined = 0;
for(uint i = 0; i < 5; i++) for(uint i = 0; i < 5; i++)
{ {
byte oLfsr1 = (byte)(_cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]); var oLfsr1 = (byte)(_cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]);
lfsr1Hi = lfsr1Lo >> 1; lfsr1Hi = lfsr1Lo >> 1;
lfsr1Lo = ((lfsr1Lo & 1) << 8) ^ oLfsr1; lfsr1Lo = (lfsr1Lo & 1) << 8 ^ oLfsr1;
oLfsr1 = _cssTable4[oLfsr1]; oLfsr1 = _cssTable4[oLfsr1];
byte oLfsr0 = (byte)(((((((lfsr0 >> 8) ^ lfsr0) >> 1) ^ lfsr0) >> 3) ^ lfsr0) >> 7); var oLfsr0 = (byte)((((lfsr0 >> 8 ^ lfsr0) >> 1 ^ lfsr0) >> 3 ^ lfsr0) >> 7);
lfsr0 = (lfsr0 >> 8) | ((uint)oLfsr0 << 24); lfsr0 = lfsr0 >> 8 | (uint)oLfsr0 << 24;
combined += (uint)((oLfsr0 ^ invert) + oLfsr1); combined += (uint)((oLfsr0 ^ invert) + oLfsr1);
k[i] = (byte)(combined & 0xff); k[i] = (byte)(combined & 0xff);
combined >>= 8; combined >>= 8;
@@ -636,14 +543,14 @@ public class CSS
/// <param name="blockSize">Size of one sector.</param> /// <param name="blockSize">Size of one sector.</param>
/// <returns>The decrypted sector.</returns> /// <returns>The decrypted sector.</returns>
public static byte[] DecryptSector(byte[] sectorData, byte[] keyData, byte[]? cmiData, uint blocks = 1, public static byte[] DecryptSector(byte[] sectorData, byte[] keyData, byte[]? cmiData, uint blocks = 1,
uint blockSize = 2048) uint blockSize = 2048)
{ {
// None of the sectors are encrypted // None of the sectors are encrypted
if((cmiData != null && cmiData.All(static cmi => (cmi & 0x80) >> 7 == 0)) || if(cmiData != null && cmiData.All(static cmi => (cmi & 0x80) >> 7 == 0) ||
keyData.All(static k => k == 0)) keyData.All(static k => k == 0))
return sectorData; return sectorData;
byte[] decryptedBuffer = new byte[sectorData.Length]; var decryptedBuffer = new byte[sectorData.Length];
for(uint i = 0; i < blocks; i++) for(uint i = 0; i < blocks; i++)
{ {
@@ -665,21 +572,21 @@ public class CSS
} }
/// <summary> /// <summary>
/// Unscrambles a DVD sector with a title key. /// Unscrambles a DVD sector with a title key.
/// </summary> /// </summary>
/// <param name="key">The title key.</param> /// <param name="key">The title key.</param>
/// <param name="sector">The scrambled sector.</param> /// <param name="sector">The scrambled sector.</param>
/// <returns>The unscrambled sector.</returns> /// <returns>The unscrambled sector.</returns>
static byte[] UnscrambleSector(IReadOnlyList<byte> key, byte[] sector) static byte[] UnscrambleSector(IReadOnlyList<byte> key, byte[] sector)
{ {
long lfsr1Lo = (key[0] ^ sector[0x54]) | 0x100; long lfsr1Lo = key[0] ^ sector[0x54] | 0x100;
long lfsr1Hi = key[1] ^ sector[0x55]; long lfsr1Hi = key[1] ^ sector[0x55];
long lfsr0 = (key[2] | (key[3] << 8) | (key[4] << 16)) ^ long lfsr0 = (key[2] | key[3] << 8 | key[4] << 16) ^
(sector[0x56] | (sector[0x57] << 8) | (sector[0x58] << 16)); (sector[0x56] | sector[0x57] << 8 | sector[0x58] << 16);
long oLfsr1 = lfsr0 & 7; long oLfsr1 = lfsr0 & 7;
lfsr0 = (lfsr0 * 2) + 8 - oLfsr1; lfsr0 = lfsr0 * 2 + 8 - oLfsr1;
long combined = 0; long combined = 0;
@@ -687,13 +594,13 @@ public class CSS
{ {
oLfsr1 = _cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]; oLfsr1 = _cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo];
lfsr1Hi = lfsr1Lo >> 1; lfsr1Hi = lfsr1Lo >> 1;
lfsr1Lo = ((lfsr1Lo & 1) << 8) ^ oLfsr1; lfsr1Lo = (lfsr1Lo & 1) << 8 ^ oLfsr1;
oLfsr1 = _cssTable5[oLfsr1]; oLfsr1 = _cssTable5[oLfsr1];
long oLfsr0 = (((((((lfsr0 >> 3) ^ lfsr0) >> 1) ^ lfsr0) >> 8) ^ lfsr0) >> 5) & 0xff; long oLfsr0 = (((lfsr0 >> 3 ^ lfsr0) >> 1 ^ lfsr0) >> 8 ^ lfsr0) >> 5 & 0xff;
lfsr0 = (lfsr0 << 8) | oLfsr0; lfsr0 = lfsr0 << 8 | oLfsr0;
oLfsr0 = _cssTable4[oLfsr0]; oLfsr0 = _cssTable4[oLfsr0];
combined += oLfsr0 + oLfsr1; combined += oLfsr0 + oLfsr1;
sector[i] = (byte)(_cssTable1[sector[i]] ^ (combined & 0xff)); sector[i] = (byte)(_cssTable1[sector[i]] ^ combined & 0xff);
combined >>= 8; combined >>= 8;
} }
@@ -705,14 +612,17 @@ public class CSS
} }
/// <summary> /// <summary>
/// Analyzes data to try to figure out if the sector is encrypted, including /// Analyzes data to try to figure out if the sector is encrypted, including
/// <list type="bullet"> /// <list type="bullet">
/// <item>If the packet is not an MPEG packet</item> /// <item>If the packet is not an MPEG packet</item>
/// <item>If the CMI tells us the sector isn't encrypted</item> /// <item>If the CMI tells us the sector isn't encrypted</item>
/// <item>If the key is all zeroes</item> /// <item>If the key is all zeroes</item>
/// <item>If the MPEG Packetized Elementary Stream scrambling control value tells us the packet is not scrambled</item> /// <item>If the MPEG Packetized Elementary Stream scrambling control value tells us the packet is not scrambled</item>
/// <item>If if the packet is system_header, padding_stream or private_stream2 (cannot be encrypted according to libdvdcss)</item> /// <item>
/// </list> /// If if the packet is system_header, padding_stream or private_stream2 (cannot be encrypted according to
/// libdvdcss)
/// </item>
/// </list>
/// </summary> /// </summary>
/// <param name="cmi">The Copyright Management Information.</param> /// <param name="cmi">The Copyright Management Information.</param>
/// <param name="key">The title key.</param> /// <param name="key">The title key.</param>
@@ -754,21 +664,21 @@ public class CSS
if(cmi.RegionInformation is 0xFF or 0x00) if(cmi.RegionInformation is 0xFF or 0x00)
return true; return true;
return ((rpc.RegionMask & 0x01) == (cmi.RegionInformation & 0x01) && (rpc.RegionMask & 0x01) != 0x01) || return (rpc.RegionMask & 0x01) == (cmi.RegionInformation & 0x01) && (rpc.RegionMask & 0x01) != 0x01 ||
((rpc.RegionMask & 0x02) == (cmi.RegionInformation & 0x02) && (rpc.RegionMask & 0x02) != 0x02) || (rpc.RegionMask & 0x02) == (cmi.RegionInformation & 0x02) && (rpc.RegionMask & 0x02) != 0x02 ||
((rpc.RegionMask & 0x04) == (cmi.RegionInformation & 0x04) && (rpc.RegionMask & 0x04) != 0x04) || (rpc.RegionMask & 0x04) == (cmi.RegionInformation & 0x04) && (rpc.RegionMask & 0x04) != 0x04 ||
((rpc.RegionMask & 0x08) == (cmi.RegionInformation & 0x08) && (rpc.RegionMask & 0x08) != 0x08) || (rpc.RegionMask & 0x08) == (cmi.RegionInformation & 0x08) && (rpc.RegionMask & 0x08) != 0x08 ||
((rpc.RegionMask & 0x10) == (cmi.RegionInformation & 0x10) && (rpc.RegionMask & 0x10) != 0x10) || (rpc.RegionMask & 0x10) == (cmi.RegionInformation & 0x10) && (rpc.RegionMask & 0x10) != 0x10 ||
((rpc.RegionMask & 0x20) == (cmi.RegionInformation & 0x20) && (rpc.RegionMask & 0x20) != 0x20) || (rpc.RegionMask & 0x20) == (cmi.RegionInformation & 0x20) && (rpc.RegionMask & 0x20) != 0x20 ||
((rpc.RegionMask & 0x40) == (cmi.RegionInformation & 0x40) && (rpc.RegionMask & 0x40) != 0x40) || (rpc.RegionMask & 0x40) == (cmi.RegionInformation & 0x40) && (rpc.RegionMask & 0x40) != 0x40 ||
((rpc.RegionMask & 0x80) == (cmi.RegionInformation & 0x80) && (rpc.RegionMask & 0x80) != 0x80); (rpc.RegionMask & 0x80) == (cmi.RegionInformation & 0x80) && (rpc.RegionMask & 0x80) != 0x80;
} }
/// <summary> /// <summary>
/// This tries to find a title key for a range of sectors by doing a brute force pattern search developed by /// This tries to find a title key for a range of sectors by doing a brute force pattern search developed by
/// Ethan Hawke of DeCSSPlus. CSS encrypted sectors have parts of them that are unencrypted (byte 0x0 - 0x80). /// Ethan Hawke of DeCSSPlus. CSS encrypted sectors have parts of them that are unencrypted (byte 0x0 - 0x80).
/// We try to find a long pattern of repeated bytes just before the encryption starts. If we assume this /// We try to find a long pattern of repeated bytes just before the encryption starts. If we assume this
/// pattern continues into the encrypted part, we can force keys until one of them satisfies this condition. /// pattern continues into the encrypted part, we can force keys until one of them satisfies this condition.
/// </summary> /// </summary>
/// <param name="sector">The sector to analyze.</param> /// <param name="sector">The sector to analyze.</param>
/// <param name="key">The key found.</param> /// <param name="key">The key found.</param>
@@ -782,7 +692,7 @@ public class CSS
for(uint i = 2; i < 0x30; i++) for(uint i = 2; i < 0x30; i++)
{ {
// Find the number of bytes that repeats in cycles. // Find the number of bytes that repeats in cycles.
for(uint j = i + 1; j < 0x80 && sector[0x7F - (j % i)] == sector[0x7F - j]; j++) for(uint j = i + 1; j < 0x80 && sector[0x7F - j % i] == sector[0x7F - j]; j++)
{ {
if(j <= bestPatternLength) if(j <= bestPatternLength)
continue; continue;
@@ -798,18 +708,18 @@ public class CSS
bestPatternLength / bestPattern < 2) bestPatternLength / bestPattern < 2)
return false; return false;
int offset = (int)(0x80 - ((bestPatternLength / bestPattern) * bestPattern)); var offset = (int)(0x80 - bestPatternLength / bestPattern * bestPattern);
int result = RecoverTitleKey(0, sector.Skip(0x80).Take(sector.Length - 0x80).ToArray(), int result = RecoverTitleKey(0, sector.Skip(0x80).Take(sector.Length - 0x80).ToArray(),
sector.Skip(offset).Take((int)(sector.Length - offset)).ToArray(), sector.Skip(offset).Take(sector.Length - offset).ToArray(),
sector.Skip(0x54).Take(5).ToArray(), out key); sector.Skip(0x54).Take(5).ToArray(), out key);
return result >= 0; return result >= 0;
} }
/// <summary> /// <summary>
/// Takes a guessed plain text and a encrypted bytes and tries to recover the title key /// Takes a guessed plain text and a encrypted bytes and tries to recover the title key
/// from those. Attack developed by Frank Stevenson. /// from those. Attack developed by Frank Stevenson.
/// </summary> /// </summary>
/// <param name="start">Start position.</param> /// <param name="start">Start position.</param>
/// <param name="encryptedBytes">Buffer with encrypted bytes.</param> /// <param name="encryptedBytes">Buffer with encrypted bytes.</param>
@@ -817,15 +727,15 @@ public class CSS
/// <param name="sectorSeed">This sector's seed values.</param> /// <param name="sectorSeed">This sector's seed values.</param>
/// <param name="key">The title key.</param> /// <param name="key">The title key.</param>
/// <returns>Positive values on success.</returns> /// <returns>Positive values on success.</returns>
static int RecoverTitleKey(uint start, byte[] encryptedBytes, byte[] decryptedBytes, byte[] sectorSeed, static int RecoverTitleKey(uint start, byte[] encryptedBytes, byte[] decryptedBytes, byte[] sectorSeed,
out byte[] key) out byte[] key)
{ {
byte[] buffer = new byte[10]; var buffer = new byte[10];
long oLfsr1; long oLfsr1;
long oLfsr0; long oLfsr0;
long iTry; long iTry;
uint i; uint i;
int exit = -1; int exit = -1;
key = new byte[5]; key = new byte[5];
for(i = 0; i < 10; i++) for(i = 0; i < 10; i++)
@@ -833,7 +743,7 @@ public class CSS
for(iTry = start; iTry < 0x10000; iTry++) for(iTry = start; iTry < 0x10000; iTry++)
{ {
long lfsr1Lo = (iTry >> 8) | 0x100; long lfsr1Lo = iTry >> 8 | 0x100;
long lfsr1Hi = iTry & 0xff; long lfsr1Hi = iTry & 0xff;
long lfsr0 = 0; long lfsr0 = 0;
long combined = 0; long combined = 0;
@@ -844,12 +754,12 @@ public class CSS
// Advance LFSR1 normally // Advance LFSR1 normally
oLfsr1 = _cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]; oLfsr1 = _cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo];
lfsr1Hi = lfsr1Lo >> 1; lfsr1Hi = lfsr1Lo >> 1;
lfsr1Lo = ((lfsr1Lo & 1) << 8) ^ oLfsr1; lfsr1Lo = (lfsr1Lo & 1) << 8 ^ oLfsr1;
oLfsr1 = _cssTable5[oLfsr1]; oLfsr1 = _cssTable5[oLfsr1];
oLfsr0 = buffer[i]; oLfsr0 = buffer[i];
if(combined > 0) if(combined > 0)
oLfsr0 = (oLfsr0 + 0xff) & 0x0ff; oLfsr0 = oLfsr0 + 0xff & 0x0ff;
if(oLfsr0 < oLfsr1) if(oLfsr0 < oLfsr1)
oLfsr0 += 0x100; oLfsr0 += 0x100;
@@ -857,7 +767,7 @@ public class CSS
oLfsr0 -= oLfsr1; oLfsr0 -= oLfsr1;
combined += oLfsr0 + oLfsr1; combined += oLfsr0 + oLfsr1;
oLfsr0 = _cssTable4[oLfsr0]; oLfsr0 = _cssTable4[oLfsr0];
lfsr0 = (lfsr0 << 8) | oLfsr0; lfsr0 = lfsr0 << 8 | oLfsr0;
combined >>= 8; combined >>= 8;
} }
@@ -868,10 +778,10 @@ public class CSS
{ {
oLfsr1 = _cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]; oLfsr1 = _cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo];
lfsr1Hi = lfsr1Lo >> 1; lfsr1Hi = lfsr1Lo >> 1;
lfsr1Lo = ((lfsr1Lo & 1) << 8) ^ oLfsr1; lfsr1Lo = (lfsr1Lo & 1) << 8 ^ oLfsr1;
oLfsr1 = _cssTable5[oLfsr1]; oLfsr1 = _cssTable5[oLfsr1];
oLfsr0 = (((((((lfsr0 >> 3) ^ lfsr0) >> 1) ^ lfsr0) >> 8) ^ lfsr0) >> 5) & 0xff; oLfsr0 = (((lfsr0 >> 3 ^ lfsr0) >> 1 ^ lfsr0) >> 8 ^ lfsr0) >> 5 & 0xff;
lfsr0 = (lfsr0 << 8) | oLfsr0; lfsr0 = lfsr0 << 8 | oLfsr0;
oLfsr0 = _cssTable4[oLfsr0]; oLfsr0 = _cssTable4[oLfsr0];
combined += oLfsr0 + oLfsr1; combined += oLfsr0 + oLfsr1;
@@ -889,12 +799,12 @@ public class CSS
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
{ {
lfsr1Lo = lfsr0 & 0xff; lfsr1Lo = lfsr0 & 0xff;
lfsr0 = (lfsr0 >> 8); lfsr0 = lfsr0 >> 8;
for(uint j = 0; j < 256; j++) for(uint j = 0; j < 256; j++)
{ {
lfsr0 = (lfsr0 & 0x1ffff) | (j << 17); lfsr0 = lfsr0 & 0x1ffff | j << 17;
oLfsr0 = (((((((lfsr0 >> 3) ^ lfsr0) >> 1) ^ lfsr0) >> 8) ^ lfsr0) >> 5) & 0xff; oLfsr0 = (((lfsr0 >> 3 ^ lfsr0) >> 1 ^ lfsr0) >> 8 ^ lfsr0) >> 5 & 0xff;
if(oLfsr0 == lfsr1Lo) if(oLfsr0 == lfsr1Lo)
break; break;
@@ -905,14 +815,14 @@ public class CSS
for(combined = 0; combined < 8; combined++) for(combined = 0; combined < 8; combined++)
{ {
if(((oLfsr1 + combined) * 2) + 8 - ((oLfsr1 + combined) & 7) != lfsr0) if((oLfsr1 + combined) * 2 + 8 - (oLfsr1 + combined & 7) != lfsr0)
continue; continue;
key[0] = (byte)(iTry >> 8); key[0] = (byte)(iTry >> 8);
key[1] = (byte)(iTry & 0xFF); key[1] = (byte)(iTry & 0xFF);
key[2] = (byte)(((oLfsr1 + combined) >> 0) & 0xFF); key[2] = (byte)(oLfsr1 + combined >> 0 & 0xFF);
key[3] = (byte)(((oLfsr1 + combined) >> 8) & 0xFF); key[3] = (byte)(oLfsr1 + combined >> 8 & 0xFF);
key[4] = (byte)(((oLfsr1 + combined) >> 16) & 0xFF); key[4] = (byte)(oLfsr1 + combined >> 16 & 0xFF);
exit = (int)(iTry + 1); exit = (int)(iTry + 1);
} }
} }
@@ -930,7 +840,7 @@ public class CSS
} }
/// <summary> /// <summary>
/// Tries to find a title key by attacking CSS vulnerabilities. /// Tries to find a title key by attacking CSS vulnerabilities.
/// </summary> /// </summary>
/// <param name="input"><c>IOpticalMediaImage</c> to find the title key in.</param> /// <param name="input"><c>IOpticalMediaImage</c> to find the title key in.</param>
/// <param name="startSector">Sector index to begin search.</param> /// <param name="startSector">Sector index to begin search.</param>
@@ -938,7 +848,7 @@ public class CSS
/// <returns>The title key.</returns> /// <returns>The title key.</returns>
static byte[] FindTitleKey(IOpticalMediaImage input, ulong startSector, ulong sectorsToSearch = 20000) static byte[] FindTitleKey(IOpticalMediaImage input, ulong startSector, ulong sectorsToSearch = 20000)
{ {
byte[] titleKey = new byte[5]; var titleKey = new byte[5];
for(ulong i = 0; i < sectorsToSearch; i++) for(ulong i = 0; i < sectorsToSearch; i++)
{ {
@@ -955,7 +865,7 @@ public class CSS
} }
/// <summary> /// <summary>
/// Generates title keys for all sectors in a track. /// Generates title keys for all sectors in a track.
/// </summary> /// </summary>
/// <param name="input"><c>IOpticalMediaImage</c> to generate keys for.</param> /// <param name="input"><c>IOpticalMediaImage</c> to generate keys for.</param>
/// <param name="partitions">List of <c>Partition</c> to analyze.</param> /// <param name="partitions">List of <c>Partition</c> to analyze.</param>
@@ -963,9 +873,9 @@ public class CSS
/// <param name="pluginType"></param> /// <param name="pluginType"></param>
/// <returns>A byte array with keys for every sector in the track. One key is 5 bytes.</returns> /// <returns>A byte array with keys for every sector in the track. One key is 5 bytes.</returns>
public static byte[] GenerateTitleKeys(IOpticalMediaImage input, List<Partition> partitions, ulong trackSectors, public static byte[] GenerateTitleKeys(IOpticalMediaImage input, List<Partition> partitions, ulong trackSectors,
Type pluginType) Type pluginType)
{ {
byte[] keys = new byte[trackSectors * 5]; var keys = new byte[trackSectors * 5];
foreach(Partition partition in partitions) foreach(Partition partition in partitions)
{ {
@@ -1004,7 +914,7 @@ public class CSS
} }
/// <summary> /// <summary>
/// DVD video discs always have a <c>VIDEO_TS</c> folder. If it doesn't have one, it's not a DVD video. /// DVD video discs always have a <c>VIDEO_TS</c> folder. If it doesn't have one, it's not a DVD video.
/// </summary> /// </summary>
/// <param name="input"><c>IOpticalMediaImage</c> to check for <c>VIDEO_TS</c> folder in.</param> /// <param name="input"><c>IOpticalMediaImage</c> to check for <c>VIDEO_TS</c> folder in.</param>
/// <param name="fs"><c>IReadOnlyFilesystem</c> to check in.</param> /// <param name="fs"><c>IReadOnlyFilesystem</c> to check in.</param>

View File

@@ -70,14 +70,14 @@ public sealed class Dump
out double duration) out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[8]; buffer = new byte[8];
cdb[0] = (byte)ScsiCommands.ReportKey; cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.Asf ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssReportKeyFormat.Asf ^ (Agid & 0x03) << 6);
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense);
@@ -98,14 +98,14 @@ public sealed class Dump
out double duration) out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[8]; buffer = new byte[8];
cdb[0] = (byte)ScsiCommands.ReportKey; cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.RpcState ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssReportKeyFormat.RpcState ^ (Agid & 0x03) << 6);
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense);
@@ -126,14 +126,14 @@ public sealed class Dump
out double duration) out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = Array.Empty<byte>(); buffer = Array.Empty<byte>();
cdb[0] = (byte)ScsiCommands.ReportKey; cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.InvalidateAgid ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssReportKeyFormat.InvalidateAgid ^ (Agid & 0x03) << 6);
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense);
@@ -154,14 +154,14 @@ public sealed class Dump
out double duration) out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[8]; buffer = new byte[8];
cdb[0] = (byte)ScsiCommands.ReportKey; cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.AgidForCssCppm ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssReportKeyFormat.AgidForCssCppm ^ (Agid & 0x03) << 6);
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense);
@@ -183,14 +183,14 @@ public sealed class Dump
out double duration) out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[12]; buffer = new byte[12];
cdb[0] = (byte)ScsiCommands.ReportKey; cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.Key1 ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssReportKeyFormat.Key1 ^ (Agid & 0x03) << 6);
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense);
@@ -211,14 +211,14 @@ public sealed class Dump
out double duration) out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[16]; buffer = new byte[16];
cdb[0] = (byte)ScsiCommands.ReportKey; cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.ChallengeKey ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssReportKeyFormat.ChallengeKey ^ (Agid & 0x03) << 6);
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense);
@@ -236,20 +236,20 @@ public sealed class Dump
/// <param name="timeout">Timeout in seconds.</param> /// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns> /// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool SendChallenge(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, byte[] challengeKey, public bool SendChallenge(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, byte[] challengeKey,
uint timeout, out double duration) uint timeout, out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[16]; buffer = new byte[16];
cdb[0] = (byte)ScsiCommands.SendKey; cdb[0] = (byte)ScsiCommands.SendKey;
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssSendKeyFormat.ChallengeKey ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssSendKeyFormat.ChallengeKey ^ (Agid & 0x03) << 6);
buffer[0] = (byte)(((buffer.Length - 2) & 0xFF00) >> 8); buffer[0] = (byte)((buffer.Length - 2 & 0xFF00) >> 8);
buffer[1] = (byte)((buffer.Length - 2) & 0xFF); buffer[1] = (byte)(buffer.Length - 2 & 0xFF);
buffer[4] = challengeKey[9]; buffer[4] = challengeKey[9];
buffer[5] = challengeKey[8]; buffer[5] = challengeKey[8];
buffer[6] = challengeKey[7]; buffer[6] = challengeKey[7];
@@ -283,16 +283,16 @@ public sealed class Dump
out double duration) out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[12]; buffer = new byte[12];
cdb[0] = (byte)ScsiCommands.SendKey; cdb[0] = (byte)ScsiCommands.SendKey;
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssSendKeyFormat.Key2 ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssSendKeyFormat.Key2 ^ (Agid & 0x03) << 6);
buffer[0] = (byte)(((buffer.Length - 2) & 0xFF00) >> 8); buffer[0] = (byte)((buffer.Length - 2 & 0xFF00) >> 8);
buffer[1] = (byte)((buffer.Length - 2) & 0xFF); buffer[1] = (byte)(buffer.Length - 2 & 0xFF);
buffer[4] = key2[4]; buffer[4] = key2[4];
buffer[5] = key2[3]; buffer[5] = key2[3];
buffer[6] = key2[2]; buffer[6] = key2[2];
@@ -318,7 +318,7 @@ public sealed class Dump
public bool ReadDiscKey(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration) public bool ReadDiscKey(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
{ {
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[2052]; buffer = new byte[2052];
cdb[0] = (byte)ScsiCommands.ReadDiscStructure; cdb[0] = (byte)ScsiCommands.ReadDiscStructure;
@@ -348,10 +348,10 @@ public sealed class Dump
buffer = Array.Empty<byte>(); buffer = Array.Empty<byte>();
senseBuffer = new byte[64]; senseBuffer = new byte[64];
bool sense = false; var sense = false;
byte[] challenge = new byte[CHALLENGE_SIZE]; var challenge = new byte[CHALLENGE_SIZE];
byte[] key1 = new byte[KEY_SIZE]; var key1 = new byte[KEY_SIZE];
byte variant = 0; byte variant = 0;
for(byte i = 0; i < 4; i++) for(byte i = 0; i < 4; i++)
{ {
@@ -368,7 +368,8 @@ public sealed class Dump
out duration); out duration);
break; break;
case CopyrightType.CPRM: throw new NotImplementedException(); case CopyrightType.CPRM:
throw new NotImplementedException();
} }
if(sense) if(sense)
@@ -450,8 +451,8 @@ public sealed class Dump
/// <param name="timeout">Timeout in seconds.</param> /// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param> /// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns> /// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool ReadTitleKey(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, ulong address, public bool ReadTitleKey(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, ulong address,
uint timeout, out double duration) uint timeout, out double duration)
{ {
// We need to be in a bus key state to read title keys. Only CSS has title keys. // We need to be in a bus key state to read title keys. Only CSS has title keys.
ReadBusKey(out buffer, out senseBuffer, CopyrightType.CSS, timeout, out duration); ReadBusKey(out buffer, out senseBuffer, CopyrightType.CSS, timeout, out duration);
@@ -459,7 +460,7 @@ public sealed class Dump
BusKey = buffer; BusKey = buffer;
senseBuffer = new byte[64]; senseBuffer = new byte[64];
byte[] cdb = new byte[12]; var cdb = new byte[12];
buffer = new byte[12]; buffer = new byte[12];
cdb[0] = (byte)ScsiCommands.ReportKey; cdb[0] = (byte)ScsiCommands.ReportKey;
@@ -470,7 +471,7 @@ public sealed class Dump
cdb[7] = (byte)keyClass; cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF); cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.TitleKey ^ ((Agid & 0x03) << 6)); cdb[10] = (byte)((byte)CssReportKeyFormat.TitleKey ^ (Agid & 0x03) << 6);
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense); _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out bool sense);

View File

@@ -44,44 +44,107 @@ namespace Aaru.Decryption.DVD;
public class MPEG public class MPEG
{ {
static byte[] _mpeg2PackHeaderStartCode = #region Mpeg2StreamId enum
{
0x0, 0x0, 0x1
};
public enum Mpeg2StreamId : byte public enum Mpeg2StreamId : byte
{ {
ProgramEnd = 0xB9, PackHeader = 0xBA, SystemHeader = 0xBB, ProgramEnd = 0xB9,
ProgramStreamMap = 0xBC, PrivateStream1 = 0xBD, PaddingStream = 0xBE, PackHeader = 0xBA,
PrivateStream2 = 0xBF, EcmStream = 0xF0, EmmStream = 0xF1, SystemHeader = 0xBB,
ItuTRecH222_0_or_IsoIec13818_1AnnexA_or_IsoIec13818_6DsmccStream = 0xF2, IsoIec13522Stream = 0xF3, ProgramStreamMap = 0xBC,
ItuTRecH222_1TypeA = 0xF4, ItuTRecH222_1TypeB = 0xF5, ItuTRecH222_1TypeC = 0xF6, PrivateStream1 = 0xBD,
ItuTRecH222_1TypeD = 0xF7, ItuTRecH222_1TypeE = 0xF8, AncillaryStream = 0xF9, PaddingStream = 0xBE,
Reserved1 = 0xFA, Reserved2 = 0xFB, Reserved3 = 0xFC, PrivateStream2 = 0xBF,
Reserved4 = 0xFD, Reserved5 = 0xFE, ProgramStreamDirectory = 0xFF, EcmStream = 0xF0,
EmmStream = 0xF1,
ItuTRecH222_0_or_IsoIec13818_1AnnexA_or_IsoIec13818_6DsmccStream = 0xF2,
IsoIec13522Stream = 0xF3,
ItuTRecH222_1TypeA = 0xF4,
ItuTRecH222_1TypeB = 0xF5,
ItuTRecH222_1TypeC = 0xF6,
ItuTRecH222_1TypeD = 0xF7,
ItuTRecH222_1TypeE = 0xF8,
AncillaryStream = 0xF9,
Reserved1 = 0xFA,
Reserved2 = 0xFB,
Reserved3 = 0xFC,
Reserved4 = 0xFD,
Reserved5 = 0xFE,
ProgramStreamDirectory = 0xFF,
// DVD Video can only hold 8 audio streams // DVD Video can only hold 8 audio streams
MpegAudioStream1 = 0xC0, MpegAudioStream2 = 0xC1, MpegAudioStream3 = 0xC2, MpegAudioStream1 = 0xC0,
MpegAudioStream4 = 0xC3, MpegAudioStream5 = 0xC4, MpegAudioStream6 = 0xC5, MpegAudioStream2 = 0xC1,
MpegAudioStream7 = 0xC6, MpegAudioStream8 = 0xC7, MpegAudioStream9 = 0xC8, MpegAudioStream3 = 0xC2,
MpegAudioStream10 = 0xC9, MpegAudioStream11 = 0xCA, MpegAudioStream12 = 0xCB, MpegAudioStream4 = 0xC3,
MpegAudioStream13 = 0xCC, MpegAudioStream14 = 0xCD, MpegAudioStream15 = 0xCE, MpegAudioStream5 = 0xC4,
MpegAudioStream16 = 0xCF, MpegAudioStream17 = 0xD0, MpegAudioStream18 = 0xD1, MpegAudioStream6 = 0xC5,
MpegAudioStream19 = 0xD2, MpegAudioStream20 = 0xD3, MpegAudioStream21 = 0xD4, MpegAudioStream7 = 0xC6,
MpegAudioStream22 = 0xD5, MpegAudioStream23 = 0xD6, MpegAudioStream24 = 0xD7, MpegAudioStream8 = 0xC7,
MpegAudioStream25 = 0xD8, MpegAudioStream26 = 0xD9, MpegAudioStream27 = 0xDA, MpegAudioStream9 = 0xC8,
MpegAudioStream28 = 0xDB, MpegAudioStream29 = 0xDC, MpegAudioStream30 = 0xDD, MpegAudioStream10 = 0xC9,
MpegAudioStream31 = 0xDE, MpegAudioStream32 = 0xDF, MpegAudioStream11 = 0xCA,
MpegAudioStream12 = 0xCB,
MpegAudioStream13 = 0xCC,
MpegAudioStream14 = 0xCD,
MpegAudioStream15 = 0xCE,
MpegAudioStream16 = 0xCF,
MpegAudioStream17 = 0xD0,
MpegAudioStream18 = 0xD1,
MpegAudioStream19 = 0xD2,
MpegAudioStream20 = 0xD3,
MpegAudioStream21 = 0xD4,
MpegAudioStream22 = 0xD5,
MpegAudioStream23 = 0xD6,
MpegAudioStream24 = 0xD7,
MpegAudioStream25 = 0xD8,
MpegAudioStream26 = 0xD9,
MpegAudioStream27 = 0xDA,
MpegAudioStream28 = 0xDB,
MpegAudioStream29 = 0xDC,
MpegAudioStream30 = 0xDD,
MpegAudioStream31 = 0xDE,
MpegAudioStream32 = 0xDF,
// DVD Video can only hold 1 video stream // DVD Video can only hold 1 video stream
MpegVideStream1 = 0xE0, MpegVideStream2 = 0xE1, MpegVideStream3 = 0xE2, MpegVideStream1 = 0xE0,
MpegVideStream4 = 0xE3, MpegVideStream5 = 0xE4, MpegVideStream6 = 0xE5, MpegVideStream2 = 0xE1,
MpegVideStream7 = 0xE6, MpegVideStream8 = 0xE7, MpegVideStream9 = 0xE8, MpegVideStream3 = 0xE2,
MpegVideStream10 = 0xE9, MpegVideStream11 = 0xEA, MpegVideStream12 = 0xEB, MpegVideStream4 = 0xE3,
MpegVideStream13 = 0xEC, MpegVideStream14 = 0xED, MpegVideStream15 = 0xEE, MpegVideStream5 = 0xE4,
MpegVideStream6 = 0xE5,
MpegVideStream7 = 0xE6,
MpegVideStream8 = 0xE7,
MpegVideStream9 = 0xE8,
MpegVideStream10 = 0xE9,
MpegVideStream11 = 0xEA,
MpegVideStream12 = 0xEB,
MpegVideStream13 = 0xEC,
MpegVideStream14 = 0xED,
MpegVideStream15 = 0xEE,
MpegVideStream16 = 0xEF MpegVideStream16 = 0xEF
} }
#endregion
static readonly byte[] _mpeg2PackHeaderStartCode = { 0x0, 0x0, 0x1 };
public static bool ContainsMpegPackets(byte[] sectorData, uint blocks = 1, uint blockSize = 2048)
{
for(uint i = 0; i < blocks; i++)
{
if(IsMpegPacket(sectorData.Skip((int)(i * blockSize))))
return true;
}
return false;
}
public static bool IsMpegPacket(IEnumerable<byte> sector) =>
sector.Take(3).ToArray().SequenceEqual(_mpeg2PackHeaderStartCode);
#region Nested type: MpegHeader
public struct MpegHeader public struct MpegHeader
{ {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
@@ -94,15 +157,5 @@ public class MPEG
byte packStuffingLengthBlock; byte packStuffingLengthBlock;
} }
public static bool ContainsMpegPackets(byte[] sectorData, uint blocks = 1, uint blockSize = 2048) #endregion
{
for(uint i = 0; i < blocks; i++)
if(IsMpegPacket(sectorData.Skip((int)(i * blockSize))))
return true;
return false;
}
public static bool IsMpegPacket(IEnumerable<byte> sector) =>
sector.Take(3).ToArray().SequenceEqual(_mpeg2PackHeaderStartCode);
} }

View File

@@ -2,10 +2,13 @@ namespace Aaru.Decryption;
public enum DvdCssKeyClass : byte public enum DvdCssKeyClass : byte
{ {
DvdCssCppmOrCprm = 0, RewritableSecurityServicesA = 1 DvdCssCppmOrCprm = 0,
RewritableSecurityServicesA = 1
} }
public enum DvdCssKeyType public enum DvdCssKeyType
{ {
Key1 = 0, Key2 = 1, BusKey = 2 Key1 = 0,
Key2 = 1,
BusKey = 2
} }

View File

@@ -11,32 +11,46 @@ namespace Aaru.Decryption {
using System; using System;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] /// <summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()] /// A strongly-typed resource class, for looking up localized strings, etc.
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()] /// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Localization { internal class Localization {
private static System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Localization() { internal Localization() {
} }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] /// <summary>
internal static System.Resources.ResourceManager ResourceManager { /// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.Equals(null, resourceMan)) { if (object.ReferenceEquals(resourceMan, null)) {
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Aaru.Decryption.Localization.Localization", typeof(Localization).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Aaru.Decryption.Localization.Localization", typeof(Localization).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] /// <summary>
internal static System.Globalization.CultureInfo Culture { /// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
@@ -45,52 +59,76 @@ namespace Aaru.Decryption {
} }
} }
internal static string REPORT_ASF_AGID_1_Sense_2_Last_Error_3_took_0_ms { /// <summary>
/// Looks up a localized string similar to GET TITLE KEY (AGID: {1}, LBA: {2}, Sense: {3}) took {0} ms..
/// </summary>
internal static string GET_TITLE_KEY_AGID_1_LBA_2_Sense_3_took_0_ms {
get { get {
return ResourceManager.GetString("REPORT_ASF_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture); return ResourceManager.GetString("GET_TITLE_KEY_AGID_1_LBA_2_Sense_3_took_0_ms", resourceCulture);
} }
} }
/// <summary>
/// Looks up a localized string similar to INVALIDATE AGID (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms..
/// </summary>
internal static string INVALIDATE_AGID_AGID_1_Sense_2_Last_Error_3_took_0_ms { internal static string INVALIDATE_AGID_AGID_1_Sense_2_Last_Error_3_took_0_ms {
get { get {
return ResourceManager.GetString("INVALIDATE_AGID_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture); return ResourceManager.GetString("INVALIDATE_AGID_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture);
} }
} }
/// <summary>
/// Looks up a localized string similar to REPORT AGID CSS/CPPM (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms..
/// </summary>
internal static string REPORT_AGID_CSS_CPPM_AGID_1_Sense_2_Last_Error_3_took_0_ms { internal static string REPORT_AGID_CSS_CPPM_AGID_1_Sense_2_Last_Error_3_took_0_ms {
get { get {
return ResourceManager.GetString("REPORT_AGID_CSS_CPPM_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture); return ResourceManager.GetString("REPORT_AGID_CSS_CPPM_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture);
} }
} }
internal static string REPORT_KEY1_AGID_1_Sense_2_Last_Error_3_took_0_ms { /// <summary>
/// Looks up a localized string similar to REPORT ASF (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms..
/// </summary>
internal static string REPORT_ASF_AGID_1_Sense_2_Last_Error_3_took_0_ms {
get { get {
return ResourceManager.GetString("REPORT_KEY1_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture); return ResourceManager.GetString("REPORT_ASF_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture);
} }
} }
/// <summary>
/// Looks up a localized string similar to REPORT CHALLENGE (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms..
/// </summary>
internal static string REPORT_CHALLENGE_AGID_1_Sense_2_Last_Error_3_took_0_ms { internal static string REPORT_CHALLENGE_AGID_1_Sense_2_Last_Error_3_took_0_ms {
get { get {
return ResourceManager.GetString("REPORT_CHALLENGE_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture); return ResourceManager.GetString("REPORT_CHALLENGE_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture);
} }
} }
/// <summary>
/// Looks up a localized string similar to REPORT KEY1 (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms..
/// </summary>
internal static string REPORT_KEY1_AGID_1_Sense_2_Last_Error_3_took_0_ms {
get {
return ResourceManager.GetString("REPORT_KEY1_AGID_1_Sense_2_Last_Error_3_took_0_ms", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to SEND CHALLENGE (AGID: {1}, Challenge {2}, Sense: {3}, Last Error: {4}) took {0} ms..
/// </summary>
internal static string SEND_CHALLENGE_AGID_1_Challenge_2_Sense_3_Last_Error_4_took_0_ms { internal static string SEND_CHALLENGE_AGID_1_Challenge_2_Sense_3_Last_Error_4_took_0_ms {
get { get {
return ResourceManager.GetString("SEND_CHALLENGE_AGID_1_Challenge_2_Sense_3_Last_Error_4_took_0_ms", resourceCulture); return ResourceManager.GetString("SEND_CHALLENGE_AGID_1_Challenge_2_Sense_3_Last_Error_4_took_0_ms", resourceCulture);
} }
} }
/// <summary>
/// Looks up a localized string similar to SEND CHALLENGE (AGID: {1}, KEY2 {2}, Sense: {3}, Last Error: {4}) took {0} ms..
/// </summary>
internal static string SEND_CHALLENGE_AGID_1_KEY2_2_Sense_3_Last_Error_4_took_0_ms { internal static string SEND_CHALLENGE_AGID_1_KEY2_2_Sense_3_Last_Error_4_took_0_ms {
get { get {
return ResourceManager.GetString("SEND_CHALLENGE_AGID_1_KEY2_2_Sense_3_Last_Error_4_took_0_ms", resourceCulture); return ResourceManager.GetString("SEND_CHALLENGE_AGID_1_KEY2_2_Sense_3_Last_Error_4_took_0_ms", resourceCulture);
} }
} }
internal static string GET_TITLE_KEY_AGID_1_LBA_2_Sense_3_took_0_ms {
get {
return ResourceManager.GetString("GET_TITLE_KEY_AGID_1_LBA_2_Sense_3_took_0_ms", resourceCulture);
}
}
} }
} }

View File

@@ -1,39 +1,43 @@
<root> <root>
<!-- ReSharper disable MarkupTextTypo --> <!-- ReSharper disable MarkupTextTypo -->
<resheader name="resmimetype"> <resheader name="resmimetype">
<value>text/microsoft-resx</value> <value>text/microsoft-resx</value>
</resheader> </resheader>
<resheader name="version"> <resheader name="version">
<value>1.3</value> <value>1.3</value>
</resheader> </resheader>
<resheader name="reader"> <resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
</resheader> PublicKeyToken=b77a5c561934e089
<resheader name="writer"> </value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> </resheader>
</resheader> <resheader name="writer">
<data name="GET_TITLE_KEY_AGID_1_LBA_2_Sense_3_took_0_ms" xml:space="preserve"> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089
</value>
</resheader>
<data name="GET_TITLE_KEY_AGID_1_LBA_2_Sense_3_took_0_ms" xml:space="preserve">
<value>GET TITLE KEY (AGID: {1}, LBA: {2}, Sense: {3}) tardó {0} ms.</value> <value>GET TITLE KEY (AGID: {1}, LBA: {2}, Sense: {3}) tardó {0} ms.</value>
</data> </data>
<data name="INVALIDATE_AGID_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="INVALIDATE_AGID_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>INVALIDATE AGID (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value> <value>INVALIDATE AGID (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value>
</data> </data>
<data name="REPORT_AGID_CSS_CPPM_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="REPORT_AGID_CSS_CPPM_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>REPORT AGID CSS/CPPM (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value> <value>REPORT AGID CSS/CPPM (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value>
</data> </data>
<data name="REPORT_ASF_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="REPORT_ASF_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>REPORT ASF (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value> <value>REPORT ASF (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value>
</data> </data>
<data name="REPORT_CHALLENGE_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="REPORT_CHALLENGE_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>REPORT CHALLENGE (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value> <value>REPORT CHALLENGE (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value>
</data> </data>
<data name="REPORT_KEY1_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="REPORT_KEY1_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>REPORT KEY1 (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value> <value>REPORT KEY1 (AGID: {1}, Sense: {2}, Error: {3}) tardó {0} ms.</value>
</data> </data>
<data name="SEND_CHALLENGE_AGID_1_Challenge_2_Sense_3_Last_Error_4_took_0_ms" xml:space="preserve"> <data name="SEND_CHALLENGE_AGID_1_Challenge_2_Sense_3_Last_Error_4_took_0_ms" xml:space="preserve">
<value>SEND CHALLENGE (AGID: {1}, Desafío {2}, Sense: {3}, Error: {4}) tardó {0} ms.</value> <value>SEND CHALLENGE (AGID: {1}, Desafío {2}, Sense: {3}, Error: {4}) tardó {0} ms.</value>
</data> </data>
<data name="SEND_CHALLENGE_AGID_1_KEY2_2_Sense_3_Last_Error_4_took_0_ms" xml:space="preserve"> <data name="SEND_CHALLENGE_AGID_1_KEY2_2_Sense_3_Last_Error_4_took_0_ms" xml:space="preserve">
<value>SEND CHALLENGE (AGID: {1}, KEY2 {2}, Sense: {3}, Error: {4}) tardó {0} ms.</value> <value>SEND CHALLENGE (AGID: {1}, KEY2 {2}, Sense: {3}, Error: {4}) tardó {0} ms.</value>
</data> </data>
</root> </root>

View File

@@ -1,48 +1,50 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<root> <root>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root" <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns=""> xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element> id="root"
</xsd:schema> xmlns="">
<resheader name="resmimetype"> <xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
<value>text/microsoft-resx</value> </xsd:schema>
</resheader> <resheader name="resmimetype">
<resheader name="version"> <value>text/microsoft-resx</value>
<value>1.3</value> </resheader>
</resheader> <resheader name="version">
<resheader name="reader"> <value>1.3</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, </resheader>
PublicKeyToken=b77a5c561934e089 <resheader name="reader">
</value> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
</resheader> PublicKeyToken=b77a5c561934e089
<resheader name="writer"> </value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, </resheader>
PublicKeyToken=b77a5c561934e089 <resheader name="writer">
</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
</resheader> PublicKeyToken=b77a5c561934e089
<data name="REPORT_ASF_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> </value>
</resheader>
<data name="REPORT_ASF_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>REPORT ASF (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value> <value>REPORT ASF (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value>
</data> </data>
<data name="INVALIDATE_AGID_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="INVALIDATE_AGID_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>INVALIDATE AGID (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value> <value>INVALIDATE AGID (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value>
</data> </data>
<data name="REPORT_AGID_CSS_CPPM_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="REPORT_AGID_CSS_CPPM_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>REPORT AGID CSS/CPPM (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value> <value>REPORT AGID CSS/CPPM (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value>
</data> </data>
<data name="REPORT_KEY1_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="REPORT_KEY1_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>REPORT KEY1 (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value> <value>REPORT KEY1 (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value>
</data> </data>
<data name="REPORT_CHALLENGE_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve"> <data name="REPORT_CHALLENGE_AGID_1_Sense_2_Last_Error_3_took_0_ms" xml:space="preserve">
<value>REPORT CHALLENGE (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value> <value>REPORT CHALLENGE (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.</value>
</data> </data>
<data name="SEND_CHALLENGE_AGID_1_Challenge_2_Sense_3_Last_Error_4_took_0_ms" xml:space="preserve"> <data name="SEND_CHALLENGE_AGID_1_Challenge_2_Sense_3_Last_Error_4_took_0_ms" xml:space="preserve">
<value>SEND CHALLENGE (AGID: {1}, Challenge {2}, Sense: {3}, Last Error: {4}) took {0} ms.</value> <value>SEND CHALLENGE (AGID: {1}, Challenge {2}, Sense: {3}, Last Error: {4}) took {0} ms.</value>
</data> </data>
<data name="SEND_CHALLENGE_AGID_1_KEY2_2_Sense_3_Last_Error_4_took_0_ms" xml:space="preserve"> <data name="SEND_CHALLENGE_AGID_1_KEY2_2_Sense_3_Last_Error_4_took_0_ms" xml:space="preserve">
<value>SEND CHALLENGE (AGID: {1}, KEY2 {2}, Sense: {3}, Last Error: {4}) took {0} ms.</value> <value>SEND CHALLENGE (AGID: {1}, KEY2 {2}, Sense: {3}, Last Error: {4}) took {0} ms.</value>
</data> </data>
<data name="GET_TITLE_KEY_AGID_1_LBA_2_Sense_3_took_0_ms" xml:space="preserve"> <data name="GET_TITLE_KEY_AGID_1_LBA_2_Sense_3_took_0_ms" xml:space="preserve">
<value>GET TITLE KEY (AGID: {1}, LBA: {2}, Sense: {3}) took {0} ms.</value> <value>GET TITLE KEY (AGID: {1}, LBA: {2}, Sense: {3}) took {0} ms.</value>
</data> </data>
</root> </root>