diff --git a/NDecrypt.Core/CIATool.cs b/NDecrypt.Core/CIATool.cs index a7ba60e..6cfcb36 100644 --- a/NDecrypt.Core/CIATool.cs +++ b/NDecrypt.Core/CIATool.cs @@ -295,7 +295,7 @@ namespace NDecrypt.Core // Create the ExeFS AES cipher for this partition int ctroffsetE = (int)(mediaUnitSize / 0x10); - byte[] exefsIVWithOffset = AddToByteArray(header.ExeFSIV(), ctroffsetE); + byte[] exefsIVWithOffset = Add(header.ExeFSIV(), ctroffsetE); var cipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset); // Setup and perform the decryption @@ -393,7 +393,7 @@ namespace NDecrypt.Core // Create the ExeFS AES ciphers for this partition uint ctroffset = (fileHeader.FileOffset + mediaUnitSize) / 0x10; - byte[] exefsIVWithOffsetForHeader = AddToByteArray(header.ExeFSIV(), (int)ctroffset); + byte[] exefsIVWithOffsetForHeader = Add(header.ExeFSIV(), (int)ctroffset); var firstCipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader); var secondCipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader); @@ -684,7 +684,7 @@ namespace NDecrypt.Core // Create the ExeFS AES cipher for this partition int ctroffsetE = (int)(mediaUnitSize / 0x10); - byte[] exefsIVWithOffset = AddToByteArray(header.ExeFSIV(), ctroffsetE); + byte[] exefsIVWithOffset = Add(header.ExeFSIV(), ctroffsetE); var cipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset); // Setup and perform the decryption @@ -782,7 +782,7 @@ namespace NDecrypt.Core // Create the ExeFS AES ciphers for this partition uint ctroffset = (fileHeader.FileOffset + mediaUnitSize) / 0x10; - byte[] exefsIVWithOffsetForHeader = AddToByteArray(header.ExeFSIV(), (int)ctroffset); + byte[] exefsIVWithOffsetForHeader = Add(header.ExeFSIV(), (int)ctroffset); var firstCipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader); var secondCipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader); diff --git a/NDecrypt.Core/CommonOperations.cs b/NDecrypt.Core/CommonOperations.cs index 2ed107d..7845565 100644 --- a/NDecrypt.Core/CommonOperations.cs +++ b/NDecrypt.Core/CommonOperations.cs @@ -9,7 +9,7 @@ using SabreTools.Models.N3DS; namespace NDecrypt.Core { - internal static class CommonOperations + public static class CommonOperations { #region AES @@ -167,7 +167,7 @@ namespace NDecrypt.Core /// Byte array to add to /// Amount to add /// Byte array representing the new value - public static byte[] AddToByteArray(byte[] input, int add) + public static byte[] Add(byte[] input, int add) { int len = input.Length; Array.Reverse(input); @@ -190,6 +190,35 @@ namespace NDecrypt.Core return arr; } + /// + /// Add two numbers represented by byte arrays + /// + /// Byte array to add to + /// Amount to add + /// Byte array representing the new value + public static byte[] Add(byte[] left, byte[] right) + { + int addBytes = Math.Min(left.Length, right.Length); + int outLength = Math.Max(left.Length, right.Length); + + byte[] output = new byte[outLength]; + + int carry = 0; + for (int i = 0; i < addBytes; i++) + { + int addValue = left[i] + right[i] + carry; + output[i] = (byte)addValue; + carry = addValue > byte.MaxValue ? byte.MaxValue - addValue : 0; + } + + if (outLength != addBytes && left.Length == outLength) + Array.Copy(left, addBytes, output, addBytes, outLength - addBytes); + else if (outLength != addBytes && right.Length == outLength) + Array.Copy(right, addBytes, output, addBytes, outLength - addBytes); + + return output; + } + /// /// Perform a rotate left on a BigInteger /// @@ -202,6 +231,69 @@ namespace NDecrypt.Core return (val << r_bits % max_bits) & (BigInteger.Pow(2, max_bits) - 1) | ((val & (BigInteger.Pow(2, max_bits) - 1)) >> (max_bits - (r_bits % max_bits))); } + /// + /// Perform a rotate left on a byte array + /// + /// Byte array value to rotate + /// Number of bits to rotate + /// Rotated byte array value + public static byte[] RotateLeft(byte[] val, int r_bits) + { + // Shift by bytes + while (r_bits >= 8) + { + byte temp = val[0]; + for (int i = 0; i < val.Length - 1; i++) + { + val[i] = val[i + 1]; + } + + val[val.Length - 1] = temp; + r_bits -= 8; + } + + // Shift by bits + while (r_bits-- > 0) + { + int carry = 0; + for (int i = 0; i < val.Length; i++) + { + byte nextByte = (byte)((val[i] << 1) + carry); + carry = (val[i] << 1) > byte.MaxValue ? byte.MaxValue - (val[i] << 1) : 0; + val[i] = nextByte; + } + + val[val.Length - 1] = (byte)(val[val.Length - 1] + carry); + } + + return val; + } + + /// + /// XOR two numbers represented by byte arrays + /// + /// Byte array to XOR to + /// Amount to XOR + /// Byte array representing the new value + public static byte[] Xor(byte[] left, byte[] right) + { + int xorBytes = Math.Min(left.Length, right.Length); + int outLength = Math.Max(left.Length, right.Length); + + byte[] output = new byte[outLength]; + for (int i = 0; i < xorBytes; i++) + { + output[i] = (byte)(left[i] ^ right[i]); + } + + if (outLength != xorBytes && left.Length == outLength) + Array.Copy(left, xorBytes, output, xorBytes, outLength - xorBytes); + else if (outLength != xorBytes && right.Length == outLength) + Array.Copy(right, xorBytes, output, xorBytes, outLength - xorBytes); + + return output; + } + #endregion #region Offsets diff --git a/NDecrypt.Core/ThreeDSTool.cs b/NDecrypt.Core/ThreeDSTool.cs index c1b975b..fc45c06 100644 --- a/NDecrypt.Core/ThreeDSTool.cs +++ b/NDecrypt.Core/ThreeDSTool.cs @@ -283,7 +283,7 @@ namespace NDecrypt.Core // Create the ExeFS AES cipher for this partition int ctroffsetE = (int)(cart.MediaUnitSize() / 0x10); - byte[] exefsIVWithOffset = AddToByteArray(cart.ExeFSIV(index), ctroffsetE); + byte[] exefsIVWithOffset = Add(cart.ExeFSIV(index), ctroffsetE); var cipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset); // Setup and perform the decryption @@ -369,7 +369,7 @@ namespace NDecrypt.Core // Create the ExeFS AES ciphers for this partition uint ctroffset = (fileHeader.FileOffset + cart.MediaUnitSize()) / 0x10; - byte[] exefsIVWithOffsetForHeader = AddToByteArray(cart.ExeFSIV(index), (int)ctroffset); + byte[] exefsIVWithOffsetForHeader = Add(cart.ExeFSIV(index), (int)ctroffset); var firstCipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader); var secondCipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader); @@ -643,7 +643,7 @@ namespace NDecrypt.Core // Create the ExeFS AES cipher for this partition int ctroffsetE = (int)(cart.MediaUnitSize() / 0x10); - byte[] exefsIVWithOffset = AddToByteArray(cart.ExeFSIV(index), ctroffsetE); + byte[] exefsIVWithOffset = Add(cart.ExeFSIV(index), ctroffsetE); var cipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset); // Setup and perform the encryption @@ -729,7 +729,7 @@ namespace NDecrypt.Core // Create the ExeFS AES ciphers for this partition uint ctroffset = (fileHeader.FileOffset + cart.MediaUnitSize()) / 0x10; - byte[] exefsIVWithOffsetForHeader = AddToByteArray(cart.ExeFSIV(index), (int)ctroffset); + byte[] exefsIVWithOffsetForHeader = Add(cart.ExeFSIV(index), (int)ctroffset); var firstCipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader); var secondCipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader); diff --git a/NDecrypt/Program.cs b/NDecrypt/Program.cs index cf10c7b..b08aea7 100644 --- a/NDecrypt/Program.cs +++ b/NDecrypt/Program.cs @@ -14,6 +14,18 @@ namespace NDecrypt public static void Main(string[] args) { + // TEMP SHIT CODE + + byte[] x = + [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + ]; + x = CommonOperations.Add(x, x); + string s = BitConverter.ToString(x); + + // END TEMP SHIT CODE + if (args.Length < 2) { DisplayHelp("Not enough arguments");