Beispiel #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);
                CryptoOld.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);

                Aes.DecryptCtr128(EncryptedKeyblobs[i].AsSpan(0x20), Keyblobs[i], KeyblobKeys[i], counter);
            }
        }
Beispiel #2
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);
                CryptoOld.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(0, Keyblobs[i]).ThrowIfFailure();
                }
            }
        }
Beispiel #3
0
        public byte[] GetTitleKey(KeySet keySet)
        {
            if (TitleKeyType == TitleKeyType.Common)
            {
                var commonKey = new byte[0x10];
                Array.Copy(TitleKeyBlock, commonKey, commonKey.Length);
                return(commonKey);
            }

            return(CryptoOld.DecryptRsaOaep(TitleKeyBlock, keySet.ETicketExtKeyRsa));
        }
Beispiel #4
0
        public Package2Header(IStorage storage, Keyset keyset, int keyGeneration)
        {
            var reader = new BinaryReader(storage.AsStream());

            byte[] key = keyset.Package2Keys[keyGeneration];

            Signature = reader.ReadBytes(0x100);
            byte[] sigData = reader.ReadBytes(0x100);
            SignatureValidity = CryptoOld.Rsa2048PssVerify(sigData, Signature, keyset.Package2FixedKeyModulus);

            reader.BaseStream.Position -= 0x100;
            Counter = reader.ReadBytes(0x10);

            Stream headerStream = new CachedStorage(new Aes128CtrStorage(storage.Slice(0x100), key, Counter, true), 0x4000, 4, true).AsStream();

            headerStream.Position = 0x10;
            reader = new BinaryReader(headerStream);

            for (int i = 0; i < 4; i++)
            {
                SectionCounters[i] = reader.ReadBytes(0x10);
            }

            Magic      = reader.ReadAscii(4);
            BaseOffset = reader.ReadInt32();

            reader.BaseStream.Position += 4;
            VersionMax = reader.ReadByte();
            VersionMin = reader.ReadByte();

            reader.BaseStream.Position += 2;

            for (int i = 0; i < 4; i++)
            {
                SectionSizes[i] = reader.ReadInt32();
            }

            for (int i = 0; i < 4; i++)
            {
                SectionOffsets[i] = reader.ReadInt32();
            }

            for (int i = 0; i < 4; i++)
            {
                SectionHashes[i] = reader.ReadBytes(0x20);
            }
        }
Beispiel #5
0
        public XciHeader(KeySet keySet, Stream stream)
        {
            using (var reader = new BinaryReader(stream, Encoding.Default, true))
            {
                Signature = reader.ReadBytes(SignatureSize);
                Magic     = reader.ReadAscii(4);
                if (Magic != HeaderMagic)
                {
                    throw new InvalidDataException("Invalid XCI file: Header magic invalid.");
                }

                reader.BaseStream.Position = SignatureSize;
                byte[] sigData = reader.ReadBytes(SignatureSize);
                reader.BaseStream.Position = SignatureSize + 4;

                SignatureValidity = CryptoOld.Rsa2048Pkcs1Verify(sigData, Signature, _xciHeaderPubk);

                RomAreaStartPage    = reader.ReadInt32();
                BackupAreaStartPage = reader.ReadInt32();
                byte keyIndex = reader.ReadByte();
                KekIndex          = (byte)(keyIndex >> 4);
                TitleKeyDecIndex  = (byte)(keyIndex & 7);
                GameCardSize      = (GameCardSizeInternal)reader.ReadByte();
                CardHeaderVersion = reader.ReadByte();
                Flags             = (GameCardAttribute)reader.ReadByte();
                PackageId         = reader.ReadUInt64();
                ValidDataEndPage  = reader.ReadInt64();
                AesCbcIv          = reader.ReadBytes(Aes.KeySize128);
                Array.Reverse(AesCbcIv);
                RootPartitionOffset     = reader.ReadInt64();
                RootPartitionHeaderSize = reader.ReadInt64();
                RootPartitionHeaderHash = reader.ReadBytes(Sha256.DigestSize);
                InitialDataHash         = reader.ReadBytes(Sha256.DigestSize);
                SelSec      = reader.ReadInt32();
                SelT1Key    = reader.ReadInt32();
                SelKey      = reader.ReadInt32();
                LimAreaPage = reader.ReadInt32();

                if (keySet != null && !keySet.XciHeaderKey.IsZeros())
                {
                    byte[] encHeader = reader.ReadBytes(EncryptedHeaderSize);
                    byte[] decHeader = new byte[EncryptedHeaderSize];
                    Aes.DecryptCbc128(encHeader, decHeader, keySet.XciHeaderKey, AesCbcIv);

                    using (var decReader = new BinaryReader(new MemoryStream(decHeader)))
                    {
                        FwVersion      = decReader.ReadUInt64();
                        AccCtrl1       = (CardClockRate)decReader.ReadInt32();
                        Wait1TimeRead  = decReader.ReadInt32();
                        Wait2TimeRead  = decReader.ReadInt32();
                        Wait1TimeWrite = decReader.ReadInt32();
                        Wait2TimeWrite = decReader.ReadInt32();
                        FwMode         = decReader.ReadInt32();
                        UppVersion     = decReader.ReadInt32();
                        decReader.BaseStream.Position += 4;
                        UppHash = decReader.ReadBytes(8);
                        UppId   = decReader.ReadUInt64();
                    }
                }

                ImageHash = new byte[Sha256.DigestSize];
                Sha256.GenerateSha256Hash(sigData, ImageHash);

                reader.BaseStream.Position = RootPartitionOffset;
                byte[] headerBytes = reader.ReadBytes((int)RootPartitionHeaderSize);

                Span <byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize];
                Sha256.GenerateSha256Hash(headerBytes, actualHeaderHash);

                PartitionFsHeaderValidity = Utilities.SpansEqual(RootPartitionHeaderHash, actualHeaderHash) ? Validity.Valid : Validity.Invalid;
            }
        }