Пример #1
0
        private void DecryptKeyblobs(IProgressReport logger = null)
        {
            var cmac         = new byte[0x10];
            var expectedCmac = new byte[0x10];
            var counter      = new byte[0x10];

            for (int i = 0; i < UsedKeyblobCount; i++)
            {
                if (KeyblobKeys[i].IsEmpty() || KeyblobMacKeys[i].IsEmpty() || EncryptedKeyblobs[i].IsEmpty())
                {
                    continue;
                }

                Array.Copy(EncryptedKeyblobs[i], expectedCmac, 0x10);
                Crypto.CalculateAesCmac(KeyblobMacKeys[i], EncryptedKeyblobs[i], 0x10, cmac, 0, 0xa0);

                if (!Util.ArraysEqual(cmac, expectedCmac))
                {
                    logger?.LogMessage($"Warning: Keyblob MAC {i:x2} is invalid. Are SBK/TSEC key correct?");
                }

                Array.Copy(EncryptedKeyblobs[i], 0x10, counter, 0, 0x10);

                using (var keyblobDec = new Aes128CtrStorage(
                           new MemoryStorage(EncryptedKeyblobs[i], 0x20, Keyblobs[i].Length), KeyblobKeys[i], counter, false))
                {
                    keyblobDec.Read(Keyblobs[i], 0);
                }
            }
        }
Пример #2
0
        private IStorage OpenAesCtrExStorage(IStorage baseStorage, int index)
        {
            NcaFsHeader    fsHeader = Header.GetFsHeader(index);
            NcaFsPatchInfo info     = fsHeader.GetPatchInfo();

            long sectionOffset = Header.GetSectionStartOffset(index);
            long sectionSize   = Header.GetSectionSize(index);

            long bktrOffset = info.RelocationTreeOffset;
            long bktrSize   = sectionSize - bktrOffset;
            long dataSize   = info.RelocationTreeOffset;

            byte[] key       = GetContentKey(NcaKeyType.AesCtr);
            byte[] counter   = Aes128CtrStorage.CreateCounter(fsHeader.Counter, bktrOffset + sectionOffset);
            byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset);

            IStorage bucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true);

            IStorage encryptionBucketTreeData = bucketTreeData.Slice(info.EncryptionTreeOffset - bktrOffset);
            IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), encryptionBucketTreeData, key, counterEx, true);

            decStorage = new CachedStorage(decStorage, 0x4000, 4, true);

            return(new ConcatenationStorage(new[] { decStorage, bucketTreeData }, true));
        }
Пример #3
0
        public static RSAParameters DecryptRsaKey(byte[] encryptedKey, byte[] kek)
        {
            var counter = new byte[0x10];

            Array.Copy(encryptedKey, counter, 0x10);
            var body = new byte[0x230];

            Array.Copy(encryptedKey, 0x10, body, 0, 0x230);
            var dec = new byte[0x230];

            using (var storageDec = new Aes128CtrStorage(new MemoryStorage(body), kek, counter, false))
            {
                storageDec.Read(dec, 0);
            }

            var d = new byte[0x100];
            var n = new byte[0x100];
            var e = new byte[4];

            Array.Copy(dec, 0, d, 0, 0x100);
            Array.Copy(dec, 0x100, n, 0, 0x100);
            Array.Copy(dec, 0x200, e, 0, 4);

            BigInteger dInt = GetBigInteger(d);
            BigInteger nInt = GetBigInteger(n);
            BigInteger eInt = GetBigInteger(e);

            RSAParameters rsaParams = RecoverRsaParameters(nInt, eInt, dInt);

            TestRsaKey(rsaParams);
            return(rsaParams);
        }
Пример #4
0
        public static void Process(Context ctx)
        {
            switch (ctx.Options.BenchType?.ToLower())
            {
            case "aesctr":
            {
                IStorage decStorage = new MemoryStorage(new byte[Size]);
                IStorage encStorage = new Aes128CtrStorage(new MemoryStorage(new byte[Size]), new byte[0x10], new byte[0x10], true);

                CopyBenchmark(decStorage, encStorage, Iterations, "MemoryStorage Encrypt: ", ctx.Logger);
                CopyBenchmark(encStorage, decStorage, Iterations, "MemoryStorage Decrypt: ", ctx.Logger);

                decStorage = new NullStorage(Size);
                encStorage = new Aes128CtrStorage(new NullStorage(Size), new byte[0x10], new byte[0x10], true);

                CopyBenchmark(decStorage, encStorage, Iterations, "NullStorage Encrypt: ", ctx.Logger);
                CopyBenchmark(encStorage, decStorage, Iterations, "NullStorage Decrypt: ", ctx.Logger);

                decStorage = new MemoryStorage(new byte[Size]);
                encStorage = new CachedStorage(new Aes128CtrStorage(new MemoryStorage(new byte[Size]), new byte[0x10], new byte[0x10], true), 0x4000, 4, true);

                CopyBenchmark(decStorage, encStorage, Iterations, "CachedStorage Encrypt: ", ctx.Logger);
                CopyBenchmark(encStorage, decStorage, Iterations, "CachedStorage Decrypt: ", ctx.Logger);

                break;
            }

            case "aesxts":
            {
                IStorage decStorage = new MemoryStorage(new byte[Size]);
                IStorage encStorage = new Aes128XtsStorage(new MemoryStorage(new byte[Size]), new byte[0x20], 81920, true);

                CopyBenchmark(decStorage, encStorage, Iterations, "MemoryStorage Encrypt: ", ctx.Logger);
                CopyBenchmark(encStorage, decStorage, Iterations, "MemoryStorage Decrypt: ", ctx.Logger);

                decStorage = new NullStorage(Size);
                encStorage = new Aes128XtsStorage(new NullStorage(Size), new byte[0x20], 81920, true);

                CopyBenchmark(decStorage, encStorage, Iterations, "NullStorage Encrypt: ", ctx.Logger);
                CopyBenchmark(encStorage, decStorage, Iterations, "NullStorage Decrypt: ", ctx.Logger);

                decStorage = new MemoryStorage(new byte[Size]);
                encStorage = new CachedStorage(new Aes128XtsStorage(new MemoryStorage(new byte[Size]), new byte[0x20], 0x4000, true), 4, true);

                CopyBenchmark(decStorage, encStorage, Iterations, "CachedStorage Encrypt: ", ctx.Logger);
                CopyBenchmark(encStorage, decStorage, Iterations, "CachedStorage Decrypt: ", ctx.Logger);
                break;
            }

            default:
                ctx.Logger.LogMessage("Unknown benchmark type.");
                return;
            }
        }
Пример #5
0
        // ReSharper restore UnusedParameter.Local

        private IStorage OpenAesCtrStorage(IStorage baseStorage, int index)
        {
            NcaFsHeader fsHeader = Header.GetFsHeader(index);

            byte[] key     = GetContentKey(NcaKeyType.AesCtr);
            byte[] counter = Aes128CtrStorage.CreateCounter(fsHeader.Counter, Header.GetSectionStartOffset(index));

            var aesStorage = new Aes128CtrStorage(baseStorage, key, Header.GetSectionStartOffset(index), counter, true);

            return(new CachedStorage(aesStorage, 0x4000, 4, true));
        }
Пример #6
0
        private IStorage OpenAesCtrExStorage(IStorage baseStorage, int index, bool decrypting)
        {
            NcaFsHeader    fsHeader = GetFsHeader(index);
            NcaFsPatchInfo info     = fsHeader.GetPatchInfo();

            long sectionOffset = Header.GetSectionStartOffset(index);
            long sectionSize   = Header.GetSectionSize(index);

            long bktrOffset = info.RelocationTreeOffset;
            long bktrSize   = sectionSize - bktrOffset;
            long dataSize   = info.RelocationTreeOffset;

            byte[] key       = GetContentKey(NcaKeyType.AesCtr);
            byte[] counter   = Aes128CtrStorage.CreateCounter(fsHeader.Counter, bktrOffset + sectionOffset);
            byte[] counterEx = Aes128CtrStorage.CreateCounter(fsHeader.Counter, sectionOffset);

            IStorage bucketTreeData;
            IStorage outputBucketTreeData;

            if (decrypting)
            {
                bucketTreeData       = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true);
                outputBucketTreeData = bucketTreeData;
            }
            else
            {
                bucketTreeData       = baseStorage.Slice(bktrOffset, bktrSize);
                outputBucketTreeData = new CachedStorage(new Aes128CtrStorage(baseStorage.Slice(bktrOffset, bktrSize), key, counter, true), 4, true);
            }

            var encryptionBucketTreeData = new SubStorage(bucketTreeData,
                                                          info.EncryptionTreeOffset - bktrOffset, sectionSize - info.EncryptionTreeOffset);

            var cachedBucketTreeData = new CachedStorage(encryptionBucketTreeData, IndirectStorage.NodeSize, 6, true);

            var treeHeader = new BucketTree.Header();

            info.EncryptionTreeHeader.CopyTo(SpanHelpers.AsByteSpan(ref treeHeader));
            long nodeStorageSize  = IndirectStorage.QueryNodeStorageSize(treeHeader.EntryCount);
            long entryStorageSize = IndirectStorage.QueryEntryStorageSize(treeHeader.EntryCount);

            var tableNodeStorage  = new SubStorage(cachedBucketTreeData, 0, nodeStorageSize);
            var tableEntryStorage = new SubStorage(cachedBucketTreeData, nodeStorageSize, entryStorageSize);

            IStorage decStorage = new Aes128CtrExStorage(baseStorage.Slice(0, dataSize), tableNodeStorage,
                                                         tableEntryStorage, treeHeader.EntryCount, key, counterEx, true);

            return(new ConcatenationStorage(new[] { decStorage, outputBucketTreeData }, true));
        }
Пример #7
0
        private Result SetPk11Storage()
        {
            // Read the PK11 header from the body storage
            int pk11Offset = IsModern ? ModernStage1Size : LegacyStage1Size;

            Result rc = BodyStorage.Read(pk11Offset, SpanHelpers.AsByteSpan(ref _pk11Header));

            if (rc.IsFailure())
            {
                return(rc);
            }

            // Check if PK11 is already decrypted, creating the PK11 storage if it is
            IsDecrypted = _pk11Header.Magic == Package1Pk11Header.ExpectedMagic;

            if (IsDecrypted)
            {
                Pk11Storage = new SubStorage(BodyStorage, pk11Offset, Pk11Size);
                return(Result.Success);
            }

            var encPk11Storage = new SubStorage(BodyStorage, pk11Offset, Pk11Size);

            // See if we have an Erista package1 key that can decrypt this PK11
            if (!IsMariko && TryFindEristaKeyRevision())
            {
                IsDecrypted = true;
                IStorage decPk11Storage;

                if (IsModern)
                {
                    decPk11Storage = new AesCbcStorage(encPk11Storage, KeySet.Package1Keys[KeyRevision],
                                                       _stage1Footer.Iv, true);
                }
                else
                {
                    decPk11Storage = new Aes128CtrStorage(encPk11Storage,
                                                          KeySet.Package1Keys[KeyRevision].DataRo.ToArray(), _stage1Footer.Iv.ToArray(), true);
                }

                Pk11Storage = new CachedStorage(decPk11Storage, 0x4000, 1, true);

                return(Result.Success);
            }

            // We can't decrypt the PK11. Set Pk11Storage to the encrypted PK11 storage
            Pk11Storage = encPk11Storage;
            return(Result.Success);
        }
Пример #8
0
        private int FindKeyGeneration(Keyset keyset, IStorage storage)
        {
            var counter   = new byte[0x10];
            var decBuffer = new byte[0x10];

            storage.Read(0x100, counter).ThrowIfFailure();

            for (int i = 0; i < 0x20; i++)
            {
                var dec = new Aes128CtrStorage(storage.Slice(0x100), keyset.Package2Keys[i], counter, false);
                dec.Read(0x50, decBuffer).ThrowIfFailure();

                if (BitConverter.ToUInt32(decBuffer, 0) == Pk21Magic)
                {
                    return(i);
                }
            }

            throw new InvalidDataException("Failed to decrypt package2! Is the correct key present?");
        }
Пример #9
0
        public Package1(KeySet keySet, IStorage storage)
        {
            Storage = storage;
            var reader = new BinaryReader(storage.AsStream());

            BuildHash = reader.ReadBytes(0x10);
            BuildDate = reader.ReadAscii(0xE);
            Field1E   = reader.ReadUInt16();

            reader.BaseStream.Position = 0x3FE0;
            Pk11Size = reader.ReadInt32();

            reader.BaseStream.Position += 0xC;
            Counter = reader.ReadBytes(0x10);

            // Try decrypting the PK11 blob with all known package1 keys
            IStorage encStorage = Storage.Slice(0x4000, Pk11Size);

            byte[] decBuffer = new byte[0x10];

            for (int i = 0; i < 0x20; i++)
            {
                var dec = new Aes128CtrStorage(encStorage, keySet.Package1Keys[i].DataRo.ToArray(), Counter, true);
                dec.Read(0, decBuffer).ThrowIfFailure();

                if (BitConverter.ToUInt32(decBuffer, 0) == Pk11Magic)
                {
                    KeyRevision = i;

                    Pk11 = new Pk11(new CachedStorage(dec, 4, true));

                    return;
                }
            }

            throw new InvalidDataException("Failed to decrypt PK11! Is the correct key present?");
        }