Пример #1
0
        public void Open()
        {
            DiskInfo disk    = SelectedDisk;
            var      storage = new CachedStorage(new DeviceStream(disk.PhysicalName, disk.Length).AsStorage(), disk.SectorSize * 100, 4, true);

            storage.SetReadOnly();
            Stream stream = storage.AsStream();

            Keyset keyset = OpenKeyset();
            var    nand   = new Nand(stream, keyset);

            Stream prodinfo    = nand.OpenProdInfo();
            var    calibration = new Calibration(prodinfo);

            keyset.EticketExtKeyRsa = Crypto.DecryptRsaKey(calibration.EticketExtKeyRsa, keyset.EticketRsaKek);
            Ticket[] tickets = GetTickets(keyset, nand);

            using (var outStream = new StreamWriter("titlekeys.txt"))
            {
                foreach (Ticket ticket in tickets)
                {
                    byte[] key = ticket.GetTitleKey(keyset);
                    outStream.WriteLine($"{ticket.RightsId.ToHexString()},{key.ToHexString()}");
                }
            }
        }
Пример #2
0
        public async Task <(RootedKeyPath KeyPath, Key PrivateKey)> CreatePrivateKey()
        {
            var settings = await this.GetSettings();

            Keyset wallet;

            if (settings.DefaultKeyset is HDFingerprint fp)
            {
                wallet = await OpenKeyset(fp);
            }
            else
            {
                var extkey = new ExtKey();
                wallet = new Keyset()
                {
                    HDKey = extkey.GetWif(this.Network), NextKeyPath = new KeyPath(0)
                };
                fp = extkey.Neuter().PubKey.GetHDFingerPrint();
                settings.DefaultKeyset = fp;
                await this.SaveSettings(settings);
            }
            var key = wallet.GetNextKey();

            await this.SaveKeyset(fp, wallet);

            return(new RootedKeyPath(fp, key.KeyPath), key.Key);
        }
Пример #3
0
        private bool DecryptTOC()
        {
            if (VolumeHeader is null)
            {
                throw new InvalidOperationException("Header was not yet loaded");
            }

            if (IsPatchVolume)
            {
                string path = PDIPFSPathResolver.GetPathFromSeed(VolumeHeader.TOCEntryIndex);

                string localPath = Path.Combine(this.PatchVolumeFolder, path);
                Program.Log($"[!] Volume Patch Path Table of contents located at: {localPath}", true);
                if (!File.Exists(localPath))
                {
                    Program.Log($"[X] Error: Unable to locate PDIPFS main TOC file on local filesystem. ({path})", true);
                    return(false);
                }

                using var fs = new FileStream(localPath, FileMode.Open);
                byte[] data = new byte[VolumeHeader.CompressedTOCSize];
                fs.Read(data);

                // Accessing a new file, we need to decrypt the header again
                Program.Log($"[-] TOC Entry is {VolumeHeader.TOCEntryIndex} which is at {path} - decrypting it", true);
                Keyset.CryptData(data, VolumeHeader.TOCEntryIndex);

                Program.Log($"[-] Decompressing TOC file..", true);
                if (!MiscUtils.TryInflateInMemory(data, VolumeHeader.TOCSize, out byte[] deflatedData))
Пример #4
0
        private static void DecryptFile(CryptVerbs options, Keyset keys, string file)
        {
            byte[] input = File.ReadAllBytes(file);
            if (!string.IsNullOrEmpty(options.Salsa20KeyEncrypt))
            {
                byte[] keyBytes = MiscUtils.StringToByteArray(options.Salsa20KeyEncrypt);
                using SymmetricAlgorithm salsa20 = new Salsa20SymmetricAlgorithm();
                byte[] dataKey = new byte[8];

                Console.WriteLine($"[:] Salsa Encrypting '{file}'..");
                using var decrypt = salsa20.CreateDecryptor(keyBytes, dataKey);
                decrypt.TransformBlock(input, 0, input.Length, input, 0);
            }
            else if (!string.IsNullOrEmpty(options.Salsa20KeyDecrypt))
            {
                byte[] keyBytes = MiscUtils.StringToByteArray(options.Salsa20KeyDecrypt);
                using SymmetricAlgorithm salsa20 = new Salsa20SymmetricAlgorithm();
                byte[] dataKey = new byte[8];

                Console.WriteLine($"[:] Salsa Decrypting '{file}'..");
                using var encrypt = salsa20.CreateEncryptor(keyBytes, dataKey);
                encrypt.TransformBlock(input, 0, input.Length, input, 0);
            }
            else
            {
                Console.WriteLine($"[:] Crypting '{file}'..");
                keys.CryptData(input, 0);
            }

            Console.WriteLine($"[:] Saving file as {file}.dec..");
            File.WriteAllBytes(file, input);
        }
Пример #5
0
        public static void generateJson(string firmware, string pathkey, string firmver, string fwint, string output)
        {
            Keyset        keyset = ExternalKeyReader.ReadKeyFile(pathkey);
            StringBuilder sb     = new StringBuilder();
            StringWriter  sw     = new StringWriter(sb);
            int           files  = Directory.GetFiles(firmware).Length;

            using (JsonWriter writer = new JsonTextWriter(sw))
            {
                writer.Formatting = Formatting.Indented;

                writer.WriteStartObject();
                writer.WritePropertyName("fw_info");
                writer.WriteStartObject();
                writer.WritePropertyName("version");
                writer.WriteValue(firmver);
                writer.WritePropertyName("IsExfat");
                writer.WriteValue(true);
                writer.WritePropertyName("files");
                writer.WriteValue(files);
                writer.WriteEnd();
                writer.WritePropertyName("titleids");
                writer.WriteStartArray();
                // escribir todos los titleid
                ListTitleid(firmware, keyset, writer);
                writer.WriteEndArray();
                writer.WritePropertyName("programid");
                writer.WriteStartObject();
                Listnca(firmware, fwint, keyset, writer);
                writer.WriteEndObject();
                writer.WriteEnd();
            }
            File.WriteAllText(Path.Combine(output, fwint), sb.ToString());
        }
Пример #6
0
        /// <summary>
        /// Decrypts a segmented file within a stream and saves it to the provided path.
        /// </summary>
        /// <param name="keyset"></param>
        /// <param name="fs"></param>
        /// <param name="seed"></param>
        /// <param name="outPath"></param>
        public unsafe static void DecryptToFile(Keyset keyset, FileStream fs, uint seed, uint outSize, string outPath, bool closeStream = true)
        {
            // Our new file
            using (var newFileStream = new FileStream(outPath, FileMode.Create))
            {
                var decryptStream = new CryptoStream(fs, new VolumeCryptoTransform(keyset, seed), CryptoStreamMode.Read);

                int       bytes = (int)outSize;
                int       read;
                const int bufSize = 81_920;
                byte[]    buffer  = ArrayPool <byte> .Shared.Rent(bufSize);

                while (outSize > 0 && (read = decryptStream.Read(buffer, 0, Math.Min(buffer.Length, (int)bytes))) > 0)
                {
                    newFileStream.Write(buffer, 0, read);
                    bytes -= read;
                }

                ArrayPool <byte> .Shared.Return(buffer);
            }

            if (closeStream)
            {
                fs.Dispose();
            }
        }
Пример #7
0
        public Nca(Keyset keyset, IStorage storage, bool leaveOpen, bool isDecryptedNca = false)
        {
            LeaveOpen      = leaveOpen;
            BaseStorage    = storage;
            Keyset         = keyset;
            IsDecryptedNca = isDecryptedNca;

            if (IsDecryptedNca)
            {
                var DecryptedHeader = new byte[0xC00];
                storage.AsStream().Read(DecryptedHeader, 0, 0xC00);
                Header = new NcaHeader(new BinaryReader(new MemoryStream(DecryptedHeader)), keyset);
            }
            else
            {
                Header = DecryptHeader();
            }

            CryptoType = Math.Max(Header.CryptoType, Header.CryptoType2);
            if (CryptoType > 0)
            {
                CryptoType--;
            }

            HasRightsId = !Header.RightsId.IsEmpty();

            if (!HasRightsId)
            {
                DecryptKeyArea(keyset);
            }
            else if (keyset.TitleKeys.TryGetValue(Header.RightsId, out byte[] titleKey))
Пример #8
0
        /// <summary>
        /// Load XCI file from disk
        /// </summary>
        /// <param name="path">Path to XCI file</param>
        /// <param name="verify">Verify hashes and signatures</param>
        /// <returns></returns>
        public static XCI Load(string path, Keyset keyset, bool verify = true)
        {
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (BinaryReader br = new BinaryReader(fs))
                {
                    XCI xci = new XCI(path);
                    xci.Keyset = keyset;

                    // Gamecard Header
                    byte[] bytes = br.ReadBytes(0x200); // sizeof XCIHeader
                    xci.GamecardHeader = bytes.ToStruct <XCIHeader>();

                    if (xci.GamecardHeader.MagicString != "HEAD")
                    {
                        throw new Exception("Invalid GamecardHeader magic! Maybe this isn't an XCI file?");
                    }

                    // TODO: Gamecard Info
                    // TODO: Gamecard Certificate
                    // TODO: Initial Data

                    // HFS0, see comments in HFS0Root and HFS0Partition
                    fs.Position    = 0xF000; // start of HFS0Header
                    xci.FileSystem = HFS0Root.Load(path, fs);

                    return(xci);
                }
        }
Пример #9
0
        public static void Extract(Stream inFileStream, string outDir, bool verify, Keyset keyset, Output Out, bool isDecryptedNca = false)
        {
            using (var file = new StreamStorage(inFileStream, false))
            {
                var nca = new Nca(keyset, file, false, isDecryptedNca);
                Out.Log(nca.Print());
                if (verify)
                {
                    Out.Log($"ValidateMasterHashes...\r\n");
                    nca.ValidateMasterHashes();
                }

                for (var i = 0; i < 3; ++i)
                {
                    if (nca.Sections[i] != null)
                    {
                        if (verify)
                        {
                            nca.VerifySection(i, Out);
                        }
                        nca.ExtractSection(i, Path.Combine(outDir, i.ToString()), IntegrityCheckLevel.None, Out);
                    }
                }
            }
        }
Пример #10
0
        public void UntrimAndEncrypt(Keyset keyset)
        {
            FolderTools.ExtractTitlekeys(decryptedDir, keyset, Out);

            var decryptedFs = new LocalFileSystem(decryptedDir);
            var encryptedFs = new LocalFileSystem(encryptedDir);

            EncryptNCA.Encrypt(decryptedFs, encryptedFs, VerifyHashes, keyset, Out);

            var dirDecrypted = new DirectoryInfo(decryptedDir);

            foreach (var file in decryptedFs.EnumerateEntries()
                     .Where(item => item.Type == DirectoryEntryType.File && !item.Name.EndsWith(".tca")))
            {
                if (!file.Name.EndsWith(".nca"))
                {
                    using (var srcFile = decryptedFs.OpenFile(file.FullPath, OpenMode.Read))
                        using (var destFile = FolderTools.CreateAndOpen(file, encryptedFs, file.Name, file.Size))
                        {
                            srcFile.CopyTo(destFile);
                        }
                }

                decryptedFs.DeleteFile(file.FullPath);
            }

            UntrimDeltaNCA.Process(decryptedDir, encryptedFs, keyset, Out);
            EncryptNCA.Encrypt(decryptedFs, encryptedFs, VerifyHashes, keyset, Out);
        }
Пример #11
0
    public static Keyset GetKeyset(KeysetName kn)
    {
        Keyset ks = new Keyset();

        if (kn.Equals(KeysetName.Arrows))
        {
            ks.LEFT   = KeyCode.LeftArrow;
            ks.RIGHT  = KeyCode.RightArrow;
            ks.UP     = KeyCode.UpArrow;
            ks.DOWN   = KeyCode.DownArrow;
            ks.JUMP   = KeyCode.Space;
            ks.ATTACK = KeyCode.M;
        }

        else if (kn.Equals(KeysetName.WASD))
        {
            ks.LEFT   = KeyCode.A;
            ks.RIGHT  = KeyCode.D;
            ks.UP     = KeyCode.W;
            ks.DOWN   = KeyCode.S;
            ks.JUMP   = KeyCode.R;
            ks.ATTACK = KeyCode.E;
        }
        return(ks);
    }
Пример #12
0
        public NcaWrapper(Keyset keyset, string ncaPath, string updateNcaPath = null)
        {
            // Open the FileStream
            fileStream = File.OpenRead(ncaPath);

            // Create the Nca instance
            baseNca = new Nca(keyset, fileStream.AsStorage(), true);

            // Open the update NCA if it exists
            if (updateNcaPath != null)
            {
                // Open the FileStream
                updateFileStream = File.OpenRead(updateNcaPath);

                // Create the update Nca instance
                updateNca = new Nca(keyset, updateFileStream.AsStorage(), true);

                // Set the baseNca
                updateNca.SetBaseNca(baseNca);
            }

            // Open the exefs
            Exefs = new PartitionFileSystem(nca.OpenSection(ProgramPartitionType.Code, false, IntegrityCheckLevel.ErrorOnInvalid, false));

            // Open the romfs
            Romfs = new RomFsFileSystem(nca.OpenSection(ProgramPartitionType.Data, false, IntegrityCheckLevel.ErrorOnInvalid, false));
        }
Пример #13
0
    // Start is called before the first frame update
    void Start()
    {
        inMiddleOfAttack = false;
        inMiddleOfJump   = false;
        rb = GetComponent <Rigidbody>();
        ks = Controls.GetKeyset(controls);
        if (rotationAxis.Equals(axis.x))
        {
            rotationVector = Vector3.right;
        }
        else if (rotationAxis.Equals(axis.y))
        {
            rotationVector = Vector3.up;
        }
        else if (rotationAxis.Equals(axis.z))
        {
            rotationVector = Vector3.forward;
        }
        rb.mass = mass;
        //deltaRotation = Quaternion.Euler(rotationVector * angularVelocity * Time.deltaTime);

        /* No amount of angular velocity could generate enough force to keep the blade stable while spinning.
         * So used this to keep the blade stable.
         */
        rb.freezeRotation     = true;
        Physics.gravity       = Vector3.down * jumpGravity;
        initRotation          = transform.rotation;
        dashAbility           = new DashAbility();
        dashAbility.dashState = DashState.Ready;
        tilt = new Tilt(initRotation.eulerAngles.x, maxTilt);
        //Rotating the blade every frame to keep it spinning.
        bladeSpin = Quaternion.Euler(Vector3.forward * angularVelocity * Time.deltaTime);
    }
Пример #14
0
        private static SwitchFs OpenSdCard(string path, IProgressReport logger = null)
        {
            SwitchFs switchFs;
            Keyset   keyset = OpenKeyset();

            var baseFs = new LocalFileSystem(path);

            if (Directory.Exists(Path.Combine(path, "Nintendo", "Contents", "registered")))
            {
                logger?.LogMessage("Treating path as SD card storage");
                switchFs = SwitchFs.OpenSdCard(keyset, baseFs);
            }
            else if (Directory.Exists(Path.Combine(path, "Contents", "registered")))
            {
                logger?.LogMessage("Treating path as NAND storage");
                switchFs = SwitchFs.OpenNandPartition(keyset, baseFs);
            }
            else
            {
                logger?.LogMessage("Treating path as a directory of loose NCAs");
                switchFs = SwitchFs.OpenNcaDirectory(keyset, baseFs);
            }

            return(switchFs);
        }
Пример #15
0
        public static InstallerUnpacker Load(Keyset keyset, string file, bool saveHeaderToc = false)
        {
            if (keyset.Key.Data is null || keyset.Key.Data.Length < 4)
            {
                return(null);
            }

            Span <byte> header = stackalloc byte[0x10];

            using (var fs = new FileStream(file, FileMode.Open))
                fs.Read(header);

            keyset.CryptData(header, DefaultSeed);

            SpanReader sr = new SpanReader(header, Endian.Big);

            if (sr.ReadStringRaw(4) != Magic)
            {
                return(null);
            }

            Program.Log($"[:] Successfully decrypted installer header with keyset: {keyset.GameCode} - {keyset.Magic}");

            uint  tocSize   = sr.ReadUInt32();
            ulong fileCount = sr.ReadUInt64();

            Program.Log($"[:] TOC Size: {tocSize}");
            Program.Log($"[:] File Count: {fileCount}..");

            InstallerUnpacker unpacker = new InstallerUnpacker(keyset, file);

            unpacker.LoadToC(tocSize, (uint)fileCount);

            return(unpacker);
        }
Пример #16
0
        public Savefile(Keyset keyset, Stream file, IntegrityCheckLevel integrityCheckLevel)
        {
            SavefileSource = new SharedStreamSource(file);

            Header = new Header(keyset, SavefileSource);
            FsLayout layout = Header.Layout;

            DataRemapStorage = new RemapStorage(SavefileSource.CreateStream(layout.FileMapDataOffset, layout.FileMapDataSize),
                                                Header.FileRemap, Header.FileMapEntries);

            DuplexData = InitDuplexStream(DataRemapStorage, Header);

            MetaRemapStorage = new RemapStorage(DuplexData, Header.MetaRemap, Header.MetaMapEntries);

            Stream journalTable = MetaRemapStorage.OpenStream(layout.JournalTableOffset, layout.JournalTableSize);

            MappingEntry[] journalMap = JournalStream.ReadMappingEntries(journalTable, Header.Journal.MainDataBlockCount);

            Stream journalData = DataRemapStorage.OpenStream(layout.JournalDataOffset,
                                                             layout.JournalDataSizeB + layout.SizeReservedArea);
            var journalStream = new JournalStream(journalData, journalMap, (int)Header.Journal.BlockSize);

            JournalStreamSource = new SharedStreamSource(journalStream);

            IvfcStream = InitIvfcStream(integrityCheckLevel);

            SaveFs = new SaveFs(IvfcStream, MetaRemapStorage.OpenStream(layout.FatOffset, layout.FatSize), Header.Save);

            IvfcStreamSource = new SharedStreamSource(IvfcStream);
        }
Пример #17
0
        public void LoadXCI()
        {
            Keyset keyset = Keyset.Load("keys.txt");
            XCI    xci    = XCI.Load(XCI_PATH, keyset);

            Assert.IsNotNull(xci);
        }
Пример #18
0
        public static List <Ticket> DumpTickets(Keyset keyset, IStorage savefile, string consoleName)
        {
            var           tickets      = new List <Ticket>();
            var           save         = new SaveDataFileSystem(keyset, savefile, IntegrityCheckLevel.ErrorOnInvalid, false);
            var           ticketList   = new BinaryReader(save.OpenFile("/ticket_list.bin", OpenMode.Read).AsStream());
            var           ticketFile   = new BinaryReader(save.OpenFile("/ticket.bin", OpenMode.Read).AsStream());
            DirectoryInfo ticketFolder = HACGUIKeyset.GetTicketsDirectory(consoleName);

            ticketFolder.Create();

            var titleId = ticketList.ReadUInt64();

            while (titleId != ulong.MaxValue)
            {
                ticketList.BaseStream.Position += 0x18;
                var    start            = ticketFile.BaseStream.Position;
                Ticket ticket           = new Ticket(ticketFile);
                Stream ticketFileStream = ticketFolder.GetFile(BitConverter.ToString(ticket.RightsId).Replace("-", "").ToLower() + ".tik").Create();
                byte[] data             = ticket.GetBytes();
                ticketFileStream.Write(data, 0, data.Length);
                ticketFileStream.Close();
                tickets.Add(ticket);
                ticketFile.BaseStream.Position = start + 0x400;
                titleId = ticketList.ReadUInt64();
            }

            return(tickets);
        }
Пример #19
0
        /// <summary>
        /// Decrypts and decompress a file in a segmented stream and saves it to the provided path.
        /// </summary>
        /// <param name="keyset"></param>
        /// <param name="fs"></param>
        /// <param name="seed"></param>
        /// <param name="outPath"></param>
        public unsafe static void DecryptAndInflateToFile(Keyset keyset, FileStream fs, uint seed, uint uncompressedSize, string outPath, bool closeStream = true)
        {
            // Our new file
            using (var newFileStream = new FileStream(outPath, FileMode.Create))
            {
                var decryptStream = new CryptoStream(fs, new VolumeCryptoTransform(keyset, seed), CryptoStreamMode.Read);
                decryptStream.Read(_tmpBuff, 0, 8); // Compress Ignore header

                var ds = new DeflateStream(decryptStream, CompressionMode.Decompress);

                int       bytesLeft = (int)uncompressedSize;
                int       read;
                const int bufSize = 81_920;
                byte[]    buffer  = ArrayPool <byte> .Shared.Rent(bufSize);

                int currentPos = 0;
                while (bytesLeft > 0 && (read = ds.Read(buffer, 0, Math.Min(buffer.Length, bytesLeft))) > 0)
                {
                    newFileStream.Write(buffer, 0, read);

                    bytesLeft -= read;
                }

                ArrayPool <byte> .Shared.Return(buffer);
            }

            if (closeStream)
            {
                fs.Dispose();
            }
        }
Пример #20
0
        public static void File2Tickets(string inFile, string outDirPath, Keyset keyset, Output Out)
        {
            var inFileExtension = Path.GetExtension(inFile).ToLower();

            using (var inputFile = new FileStream(inFile, FileMode.Open, FileAccess.Read))
            {
                switch (inFileExtension)
                {
                case ".nsp":
                    var pfs = new PartitionFileSystem(inputFile.AsStorage());
                    ProcessNsp.ExtractTickets(pfs, outDirPath, keyset, Out);
                    break;

                case ".xci":
                    var xci = new Xci(keyset, inputFile.AsStorage());
                    ProcessXci.ExtractTickets(xci, outDirPath, keyset, Out);
                    break;

                case ".nspz":
                case ".xciz":
                    var pfsz = new PartitionFileSystem(inputFile.AsStorage());
                    DecompressFs.ExtractTickets(pfsz, outDirPath, keyset, Out);
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
        }
Пример #21
0
        Script GetExecutedScript(string scriptTemplate, Script prevScript, Dictionary <string, Keyset> sets)
        {
            StringBuilder executedScript = new StringBuilder();
            int           lastToCopy     = 0;

            foreach (Match match in Regex.Matches(scriptTemplate, "<([^\\.]*?)\\.([^.]*?)>"))
            {
                var    name = match.Groups[1].Value;
                Keyset keyset;
                if (!sets.TryGetValue(name.ToLowerInvariant(), out keyset))
                {
                    keyset = new Keyset(name);
                    sets.Add(name.ToLowerInvariant(), keyset);
                }
                var element     = match.Groups[2].Value;
                var replacement = keyset.GetValue(element, prevScript);
                if (replacement == null)
                {
                    throw new Exception("Element " + element + " unrecognized, possible values are pubkey, pubkeyhash ,key, signature");
                }
                var before = scriptTemplate.Substring(lastToCopy, match.Index - lastToCopy);
                executedScript.Append(before);
                executedScript.Append(replacement);
                lastToCopy = match.Index + match.Length;
            }
            executedScript.Append(scriptTemplate.Substring(lastToCopy, scriptTemplate.Length - lastToCopy));
            return(new Script(executedScript.ToString()));
        }
Пример #22
0
        public Result Commit(Keyset keyset)
        {
            CoreDataIvfcStorage.Flush();
            FatIvfcStorage?.Flush();

            Stream headerStream = BaseStorage.AsStream();

            var hashData = new byte[0x3d00];

            headerStream.Position = 0x300;
            headerStream.Read(hashData, 0, hashData.Length);

            byte[] hash = Crypto.ComputeSha256(hashData, 0, hashData.Length);
            headerStream.Position = 0x108;
            headerStream.Write(hash, 0, hash.Length);

            if (keyset == null || keyset.SaveMacKey.IsEmpty())
            {
                return(ResultFs.PreconditionViolation);
            }

            var cmacData = new byte[0x200];
            var cmac     = new byte[0x10];

            headerStream.Position = 0x100;
            headerStream.Read(cmacData, 0, 0x200);

            Crypto.CalculateAesCmac(keyset.SaveMacKey, cmacData, 0, cmac, 0, 0x200);

            headerStream.Position = 0;
            headerStream.Write(cmac, 0, 0x10);
            headerStream.Flush();

            return(Result.Success);
        }
Пример #23
0
        public bool CommitHeader(Keyset keyset)
        {
            // todo
            Stream headerStream = BaseStorage.AsStream();

            var hashData = new byte[0x3d00];

            headerStream.Position = 0x300;
            headerStream.Read(hashData, 0, hashData.Length);

            byte[] hash = Crypto.ComputeSha256(hashData, 0, hashData.Length);
            headerStream.Position = 0x108;
            headerStream.Write(hash, 0, hash.Length);

            if (keyset.SaveMacKey.IsEmpty())
            {
                return(false);
            }

            var cmacData = new byte[0x200];
            var cmac     = new byte[0x10];

            headerStream.Position = 0x100;
            headerStream.Read(cmacData, 0, 0x200);

            Crypto.CalculateAesCmac(keyset.SaveMacKey, cmacData, 0, cmac, 0, 0x200);

            headerStream.Position = 0;
            headerStream.Write(cmac, 0, 0x10);
            headerStream.Flush();

            return(true);
        }
Пример #24
0
        public static void Listnca(string sdfs, string fwint, Keyset keyset, JsonWriter writer)
        {
            SwitchFs        switchFs;
            LocalFileSystem baseFs = new LocalFileSystem(sdfs);

            switchFs = SwitchFs.OpenNcaDirectory(keyset, baseFs);
            string lasttitleid = "";
            string lastncaid   = "";
            string type;

            foreach (SwitchFsNca nca in switchFs.Ncas.Values.OrderBy(x => x.Nca.Header.TitleId))
            {
                if (nca.Nca.Header.TitleId.ToString("X16") != lasttitleid)
                {
                    writer.WritePropertyName(nca.Nca.Header.TitleId.ToString("X16"));
                    writer.WriteStartObject();
                    writer.WritePropertyName(nca.Nca.Header.ContentType.ToString());
                    writer.WriteValue(nca.NcaId);
                    // solo contiene META
                    if (int.Parse(fwint) >= 738197944)
                    {
                        if ("0100000000000825" == nca.Nca.Header.TitleId.ToString("X16") || "0100000000000029" == nca.Nca.Header.TitleId.ToString("X16") || "0100000000000816" == nca.Nca.Header.TitleId.ToString("X16"))
                        {
                            writer.WriteEnd();
                        }
                    }
                    else if ("010000000000001B" == nca.Nca.Header.TitleId.ToString("X16") || "0100000000000029" == nca.Nca.Header.TitleId.ToString("X16") || "0100000000000816" == nca.Nca.Header.TitleId.ToString("X16"))
                    {
                        writer.WriteEnd();
                    }

                    lastncaid   = nca.NcaId;
                    lasttitleid = nca.Nca.Header.TitleId.ToString("X16");
                }
                if (lastncaid != nca.NcaId && lasttitleid == nca.Nca.Header.TitleId.ToString())
                {
                    if (nca.Nca.Header.ContentType.ToString() == "Data" || nca.Nca.Header.ContentType.ToString() == "PublicData")
                    {
                        type = "Program";
                    }
                    else
                    {
                        type = nca.Nca.Header.ContentType.ToString();
                    }
                    writer.WritePropertyName(type);
                    writer.WriteValue(nca.NcaId);
                    writer.WriteEnd();
                    lastncaid   = nca.NcaId;
                    lasttitleid = nca.Nca.Header.TitleId.ToString("X16");
                }
                else if (lastncaid != nca.NcaId && lasttitleid != nca.Nca.Header.TitleId.ToString())
                {
                    writer.WritePropertyName(nca.Nca.Header.ContentType.ToString());
                    writer.WriteValue(nca.NcaId);
                    writer.WriteEnd();
                    lastncaid   = nca.NcaId;
                    lasttitleid = nca.Nca.Header.TitleId.ToString("X16");
                }
            }
        }
Пример #25
0
        public static void Initialize()
        {
            // Get the KeysetConfig
            KeysetConfig keysetConfig = Configuration.LoadedConfiguration.KeysetConfig;

            Keyset = ExternalKeys.ReadKeyFile(keysetConfig.ProductionKeys, keysetConfig.TitleKeys);
        }
Пример #26
0
        private Validity ValidateSignature(Keyset keyset)
        {
            Span <byte> calculatedCmac = stackalloc byte[0x10];

            Aes.CalculateCmac(calculatedCmac, Data.AsSpan(0x100, 0x200), keyset.SaveMacKey);

            return(CryptoUtil.IsSameBytes(calculatedCmac, Cmac, Aes.BlockSize) ? Validity.Valid : Validity.Invalid);
        }
Пример #27
0
        private Validity ValidateSignature(Keyset keyset)
        {
            var calculatedCmac = new byte[0x10];

            Crypto.CalculateAesCmac(keyset.SaveMacKey, Data, 0x100, calculatedCmac, 0, 0x200);

            return(Util.ArraysEqual(calculatedCmac, Cmac) ? Validity.Valid : Validity.Invalid);
        }
Пример #28
0
        public NcaHeader(Keyset keyset, IStorage headerStorage)
        {
            (byte[] header, bool isEncrypted) = DecryptHeader(keyset, headerStorage);

            _header       = header;
            IsEncrypted   = isEncrypted;
            FormatVersion = DetectNcaVersion(_header.Span);
        }
Пример #29
0
        public Header(Keyset keyset, BinaryReader reader)
        {
            reader.BaseStream.Position = 0;
            Data = reader.ReadBytes(0x4000);
            reader.BaseStream.Position = 0;

            Cmac = reader.ReadBytes(0x10);

            reader.BaseStream.Position = 0x100;
            Layout = new FsLayout(reader);

            reader.BaseStream.Position = 0x300;
            Duplex = new DuplexHeader(reader);

            reader.BaseStream.Position = 0x344;
            Ivfc = new IvfcHeader(reader);

            reader.BaseStream.Position = 0x408;
            Journal = new JournalHeader(reader);

            reader.BaseStream.Position = 0x608;
            Save = new SaveHeader(reader);

            reader.BaseStream.Position = 0x650;
            FileRemap = new RemapHeader(reader);
            reader.BaseStream.Position = 0x690;
            MetaRemap = new RemapHeader(reader);

            reader.BaseStream.Position = 0x6D8;
            ExtraData = new ExtraData(reader);

            reader.BaseStream.Position = Layout.IvfcMasterHashOffsetA;
            MasterHashA = reader.ReadBytes((int)Layout.IvfcMasterHashSize);
            reader.BaseStream.Position = Layout.IvfcMasterHashOffsetB;
            MasterHashB = reader.ReadBytes((int)Layout.IvfcMasterHashSize);

            reader.BaseStream.Position = Layout.DuplexMasterOffsetA;
            DuplexMasterA = reader.ReadBytes((int)Layout.DuplexMasterSize);
            reader.BaseStream.Position = Layout.DuplexMasterOffsetB;
            DuplexMasterB = reader.ReadBytes((int)Layout.DuplexMasterSize);

            reader.BaseStream.Position = Layout.FileMapEntryOffset;
            FileMapEntries             = new MapEntry[FileRemap.MapEntryCount];
            for (int i = 0; i < FileRemap.MapEntryCount; i++)
            {
                FileMapEntries[i] = new MapEntry(reader);
            }

            reader.BaseStream.Position = Layout.MetaMapEntryOffset;
            MetaMapEntries             = new MapEntry[MetaRemap.MapEntryCount];
            for (int i = 0; i < MetaRemap.MapEntryCount; i++)
            {
                MetaMapEntries[i] = new MapEntry(reader);
            }

            HeaderHashValidity = Crypto.CheckMemoryHashTable(Data, Layout.Hash, 0x300, 0x3d00);
            SignatureValidity  = ValidateSignature(keyset);
        }
Пример #30
0
        public Header(IStorage storage, Keyset keyset)
        {
            MainStorage         = storage;
            MainHeader          = MainStorage.Slice(0x100, 0x200);
            DuplexHeader        = MainStorage.Slice(0x300, 0x44);
            DataIvfcHeader      = MainStorage.Slice(0x344, 0xC0);
            JournalHeader       = MainStorage.Slice(0x408, 0x200);
            SaveHeader          = MainStorage.Slice(0x608, 0x48);
            MainRemapHeader     = MainStorage.Slice(0x650, 0x40);
            MetaDataRemapHeader = MainStorage.Slice(0x690, 0x40);
            ExtraDataStorage    = MainStorage.Slice(0x6D8, 0x400);
            FatIvfcHeader       = MainStorage.Slice(0xAD8, 0xC0);

            Layout = new FsLayout(MainHeader);

            DuplexMasterBitmapA = MainStorage.Slice(Layout.DuplexMasterOffsetA, Layout.DuplexMasterSize);
            DuplexMasterBitmapB = MainStorage.Slice(Layout.DuplexMasterOffsetB, Layout.DuplexMasterSize);
            DataIvfcMaster      = MainStorage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize);
            FatIvfcMaster       = MainStorage.Slice(Layout.FatIvfcMasterHashA, Layout.IvfcMasterHashSize);

            var reader = new BinaryReader(storage.AsStream());

            reader.BaseStream.Position = 0;
            Data = reader.ReadBytes(0x4000);
            reader.BaseStream.Position = 0;

            Cmac = reader.ReadBytes(0x10);

            reader.BaseStream.Position = 0x100;

            reader.BaseStream.Position = 0x300;
            Duplex = new DuplexHeader(reader);

            reader.BaseStream.Position = 0x6D8;
            ExtraData = new ExtraData(reader);

            Ivfc = new IvfcHeader(DataIvfcHeader)
            {
                NumLevels = 5
            };

            if (Layout.Version >= 0x50000)
            {
                FatIvfc = new IvfcHeader(FatIvfcHeader)
                {
                    NumLevels = 4
                };
            }

            MasterHash = storage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize);

            Span <byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize];

            Sha256.GenerateSha256Hash(Data.AsSpan(0x300, 0x3d00), actualHeaderHash);

            HeaderHashValidity = Utilities.SpansEqual(Layout.Hash, actualHeaderHash) ? Validity.Valid : Validity.Invalid;
            SignatureValidity  = ValidateSignature(keyset);
        }