Example #1
0
        public byte[] getrifKey(string rifIn, string actIn, string idps)
        {
            if ((rifIn == null) || (actIn == null))
            {
                return(null);
            }
            byte[]     o      = null;
            FileStream stream = File.Open(rifIn, FileMode.Open);

            byte[] buffer2 = new byte[0x10];
            byte[] buffer3 = new byte[0x10];
            byte[] buffer  = new byte[0x10];
            byte[] buffer5 = new byte[0x10];
            stream.Seek(0x40L, SeekOrigin.Begin);
            stream.Read(buffer, 0, buffer.Length);
            stream.Read(buffer5, 0, buffer5.Length);
            stream.Close();
            ToolsImpl.aesecbDecrypt(RIFKEY, buffer, 0, buffer2, 0, 0x10);
            long num = ConversionUtils.be32(buffer2, 12);

            if (num < 0x80L)
            {
                byte[] src  = decryptACTDAT(actIn, idps);
                byte[] dest = new byte[0x10];
                o = new byte[0x10];
                ConversionUtils.arraycopy(src, ((int)num) * 0x10, dest, 0L, 0x10);
                ToolsImpl.aesecbDecrypt(dest, buffer5, 0, o, 0, 0x10);
            }
            return(o);
        }
Example #2
0
        private int validateNPD(String filename, byte[] devKLic, NPD[] npdPtr, FileStream i)
        {
            i.Seek(0, SeekOrigin.Begin);
            byte[] npd = new byte[0x80];
            i.Read(npd, 0, npd.Length);
            byte[] extraData = new byte[0x04];
            i.Read(extraData, 0, extraData.Length);
            long flag = ConversionUtils.be32(extraData, 0);

            if ((flag & FLAG_SDAT) != 0)
            {
                Console.WriteLine("INFO: SDAT detected. NPD header is not validated");
            }
            else if (!checkNPDHash1(filename, npd))
            {
                Console.WriteLine("ERROR: Hashing Title ID Name");
                return(STATUS_ERROR_HASHTITLEIDNAME);
            }
            else if (devKLic == null)
            {
                Console.WriteLine("WARNING: Can not validate devklic header");
            }
            else if (!checkNPDHash2(devKLic, npd))
            {
                Console.WriteLine("ERROR: Hashing devklic");
                return(STATUS_ERROR_HASHDEVKLIC);
            }
            npdPtr[0] = NPD.createNPD(npd);
            return(STATUS_OK);
        }
Example #3
0
 private int validateNPD(string filename, byte[] devKLic, NPD[] npdPtr, FileStream i)
 {
     i.Seek(0L, SeekOrigin.Begin);
     byte[] buffer = new byte[0x80];
     i.Read(buffer, 0, buffer.Length);
     byte[] buffer2 = new byte[4];
     i.Read(buffer2, 0, buffer2.Length);
     if ((ConversionUtils.be32(buffer2, 0) & FLAG_SDAT) != 0L)
     {
         Console.WriteLine("INFO: SDAT detected. NPD header is not validated");
     }
     else
     {
         if (!this.checkNPDHash1(filename, buffer))
         {
             Console.WriteLine("ERROR: Hashing Title ID Name");
             return(STATUS_ERROR_HASHTITLEIDNAME);
         }
         if (devKLic == null)
         {
             Console.WriteLine("WARNING: Can not validate devklic header");
         }
         else if (!this.checkNPDHash2(devKLic, buffer))
         {
             Console.WriteLine("ERROR: Hashing devklic");
             return(STATUS_ERROR_HASHDEVKLIC);
         }
     }
     npdPtr[0] = NPD.createNPD(buffer);
     return(STATUS_OK);
 }
Example #4
0
        public byte[] getrifKey(String rifIn, String actIn, String idps)
        {
            if (rifIn == null || actIn == null)
            {
                return(null);
            }
            byte[]     result  = null;
            FileStream rifFile = File.Open(rifIn, FileMode.Open);

            byte[] rif0x40    = new byte[0x10];
            byte[] rif0x50    = new byte[0x10];
            byte[] encrif0x40 = new byte[0x10];
            byte[] encrif0x50 = new byte[0x10];
            rifFile.Seek(0x40, SeekOrigin.Begin);
            rifFile.Read(encrif0x40, 0, encrif0x40.Length);
            rifFile.Read(encrif0x50, 0, encrif0x50.Length);
            rifFile.Close();
            ToolsImpl.aesecbDecrypt(RIFKEY, encrif0x40, 0x00, rif0x40, 0, 0x10);
            long index = ConversionUtils.be32(rif0x40, 0xC); //

            if (index < 0x80)
            {
                byte[] actDat = decryptACTDAT(actIn, idps);
                byte[] datKey = new byte[0x10];
                result = new byte[0x10];
                ConversionUtils.arraycopy(actDat, (int)index * 16, datKey, 0, 0x10);
                ToolsImpl.aesecbDecrypt(datKey, encrif0x50, 0, result, 0, 0x10);
            }
            return(result);
        }
Example #5
0
        public static EDATData createEDATData(byte[] data)
        {
            EDATData result = new EDATData();

            result.flags     = ConversionUtils.be32(data, 0);
            result.blockSize = ConversionUtils.be32(data, 4);
            result.fileLen   = ConversionUtils.be64(data, 0x8);
            return(result);
        }
Example #6
0
        public static NPD createNPD(byte[] npd)
        {
            NPD result = new NPD();

            ConversionUtils.arraycopy(npd, 0, result.magic, 0, 4);
            result.version = ConversionUtils.be32(npd, 4);
            result.license = ConversionUtils.be32(npd, 8);
            result.type    = ConversionUtils.be32(npd, 0xC);
            ConversionUtils.arraycopy(npd, 0x10, result.content_id, 0, 0x30);
            ConversionUtils.arraycopy(npd, 0x40, result.digest, 0, 0x10);
            ConversionUtils.arraycopy(npd, 0x50, result.titleHash, 0, 0x10);
            ConversionUtils.arraycopy(npd, 0x60, result.devHash, 0, 0x10);
            result.unknown3 = ConversionUtils.be64(npd, 0x70);
            result.unknown4 = ConversionUtils.be64(npd, 0x78);
            if (!result.validate())
            {
                result = null;
            }
            return(result);
        }
Example #7
0
        public static NPD createNPD(byte[] npd)
        {
            NPD npd2 = new NPD();

            ConversionUtils.arraycopy(npd, 0, npd2.magic, 0L, 4);
            npd2.version = ConversionUtils.be32(npd, 4);
            npd2.license = ConversionUtils.be32(npd, 8);
            npd2.type    = ConversionUtils.be32(npd, 12);
            ConversionUtils.arraycopy(npd, 0x10, npd2.content_id, 0L, 0x30);
            ConversionUtils.arraycopy(npd, 0x40, npd2.digest, 0L, 0x10);
            ConversionUtils.arraycopy(npd, 80, npd2.titleHash, 0L, 0x10);
            ConversionUtils.arraycopy(npd, 0x60, npd2.devHash, 0L, 0x10);
            npd2.unknown3 = ConversionUtils.be64(npd, 0x70);
            npd2.unknown4 = ConversionUtils.be64(npd, 120);
            if (!npd2.validate())
            {
                npd2 = null;
            }
            return(npd2);
        }
Example #8
0
        private int decryptData(FileStream ii, FileStream o, NPD npd, EDATData data, byte[] rifkey)
        {
            int numBlocks           = (int)((data.getFileLen() + data.getBlockSize() - 1) / data.getBlockSize());
            int metadataSectionSize = ((data.getFlags() & FLAG_COMPRESSED) != 0 || (data.getFlags() & FLAG_0x20) != 0) ? 0x20 : 0x10;
            int baseOffset          = 0x100; //+ offset (unknown)

            for (int i = 0; i < numBlocks; i++)
            {
                ii.Seek(baseOffset + i * metadataSectionSize, SeekOrigin.Begin);
                byte[] expectedHash = new byte[0x10];
                long   offset;
                int    len;
                int    compressionEndBlock = 0;
                if ((data.getFlags() & FLAG_COMPRESSED) != 0)
                {
                    byte[] metadata = new byte[0x20];
                    ii.Read(metadata, 0, metadata.Length);
                    byte[] result = decryptMetadataSection(metadata);
                    offset = (int)(ConversionUtils.be64(result, 0)); // + offset (unknown)
                    len    = (int)(ConversionUtils.be32(result, 8));
                    compressionEndBlock = (int)(ConversionUtils.be32(result, 0xC));
                    ConversionUtils.arraycopy(metadata, 0, expectedHash, 0, 0x10);
                }
                else if ((data.getFlags() & FLAG_0x20) != 0)
                {
                    //NOT TESTED: CASE WHERE METADATASECTION IS 0x20 BYTES LONG
                    byte[] metadata = new byte[0x20];
                    ii.Read(metadata, 0, metadata.Length);
                    for (int j = 0; j < 0x10; j++)
                    {
                        expectedHash[j] = (byte)(metadata[j] ^ metadata[j + 0x10]);
                    }
                    offset = baseOffset + i * data.getBlockSize() + numBlocks * metadataSectionSize;
                    len    = (int)(data.getBlockSize());
                    if (i == numBlocks - 1)
                    {
                        len = (int)(data.getFileLen() % (new BigInteger(data.getBlockSize())));
                    }
                }
                else
                {
                    ii.Read(expectedHash, 0, expectedHash.Length);
                    offset = baseOffset + i * data.getBlockSize() + numBlocks * metadataSectionSize;
                    len    = (int)(data.getBlockSize());
                    if (i == numBlocks - 1)
                    {
                        len = (int)(data.getFileLen() % (new BigInteger(data.getBlockSize())));
                    }
                }
                int realLen = len;
                len = (int)((uint)(len + 0xF) & 0xFFFFFFF0);
                Debug.Print("Offset: %016X, len: %08X, realLen: %08X, endCompress: %d\r\n", offset, len, realLen, compressionEndBlock);
                ii.Seek(offset, SeekOrigin.Begin);
                byte[] encryptedData = new byte[len];
                byte[] decryptedData = new byte[len];
                ii.Read(encryptedData, 0, encryptedData.Length);
                byte[] key      = new byte[0x10];
                byte[] hash     = new byte[0x10];
                byte[] blockKey = calculateBlockKey(i, npd);

                ToolsImpl.aesecbEncrypt(rifkey, blockKey, 0, key, 0, blockKey.Length);
                if ((data.getFlags() & FLAG_0x10) != 0)
                {
                    ToolsImpl.aesecbEncrypt(rifkey, key, 0, hash, 0, key.Length);
                }
                else
                {
                    ConversionUtils.arraycopy(key, 0, hash, 0, key.Length);
                }
                int cryptoFlag = ((data.getFlags() & FLAG_0x02) == 0) ? 0x2 : 0x1;
                int hashFlag;
                if ((data.getFlags() & FLAG_0x10) == 0)
                {
                    hashFlag = 0x02;
                }
                else if ((data.getFlags() & FLAG_0x20) == 0)
                {
                    hashFlag = 0x04;
                }
                else
                {
                    hashFlag = 0x01;
                }
                if ((data.getFlags() & FLAG_KEYENCRYPTED) != 0)
                {
                    cryptoFlag |= 0x10000000;
                    hashFlag   |= 0x10000000;
                }
                if ((data.getFlags() & FLAG_DEBUG) != 0)
                {
                    cryptoFlag |= 0x01000000;
                    hashFlag   |= 0x01000000;
                }
                AppLoader a  = new AppLoader();
                byte[]    iv = (npd.getVersion() <= 1) ? (new byte[0x10]) : npd.getDigest();

                bool rresult = a.doAll(hashFlag, cryptoFlag, encryptedData, 0, decryptedData, 0, encryptedData.Length, key, npd.getDigest(), hash, expectedHash, 0);
                if (!rresult)
                {
                    Debug.WriteLine("Error decrypting block " + i);
                    // KDSBest find out why block 30 errors
                    //return STATUS_ERROR_DECRYPTING;
                }
                if ((data.getFlags() & FLAG_COMPRESSED) != 0)
                {
                    //byte[] decompress = new byte[Long.valueOf(data.getBlockSize()).intValue()];
                    //DECOMPRESS: MISSING ALGORITHM
                    //out.write(decompress, 0, data.getBlockSize());
                }
                else
                {
                    o.Write(decryptedData, 0, realLen);
                }
            }
            return(STATUS_OK);
        }
Example #9
0
 public static EDATData createEDATData(byte[] data)
 {
     return(new EDATData {
         flags = ConversionUtils.be32(data, 0), blockSize = ConversionUtils.be32(data, 4), fileLen = ConversionUtils.be64(data, 8)
     });
 }
Example #10
0
        private int decryptData(FileStream ii, FileStream o, NPD npd, EDATData data, byte[] rifkey)
        {
            int num  = (int)(((data.getFileLen() + data.getBlockSize()) - 1) / data.getBlockSize());
            int num2 = (((data.getFlags() & FLAG_COMPRESSED) != 0L) || ((data.getFlags() & FLAG_0x20) != 0L)) ? 0x20 : 0x10;
            int num3 = 0x100;

            for (int i = 0; i < num; i++)
            {
                long   num5;
                int    num6;
                byte[] buffer2;
                int    num11;
                ii.Seek((long)(num3 + (i * num2)), SeekOrigin.Begin);
                byte[] dest = new byte[0x10];
                int    num7 = 0;
                if ((data.getFlags() & FLAG_COMPRESSED) != 0L)
                {
                    buffer2 = new byte[0x20];
                    ii.Read(buffer2, 0, buffer2.Length);
                    byte[] buffer3 = this.decryptMetadataSection(buffer2);
                    num5 = (int)ConversionUtils.be64(buffer3, 0);
                    num6 = (int)ConversionUtils.be32(buffer3, 8);
                    num7 = (int)ConversionUtils.be32(buffer3, 12);
                    ConversionUtils.arraycopy(buffer2, 0, dest, 0L, 0x10);
                }
                else if ((data.getFlags() & FLAG_0x20) != 0L)
                {
                    buffer2 = new byte[0x20];
                    ii.Read(buffer2, 0, buffer2.Length);
                    for (int j = 0; j < 0x10; j++)
                    {
                        dest[j] = (byte)(buffer2[j] ^ buffer2[j + 0x10]);
                    }
                    num5 = (num3 + (i * data.getBlockSize())) + (num * num2);
                    num6 = (int)data.getBlockSize();
                    if (i == (num - 1))
                    {
                        num6 = (int)(data.getFileLen() % new BigInteger(data.getBlockSize()));
                    }
                }
                else
                {
                    ii.Read(dest, 0, dest.Length);
                    num5 = (num3 + (i * data.getBlockSize())) + (num * num2);
                    num6 = (int)data.getBlockSize();
                    if (i == (num - 1))
                    {
                        num6 = (int)(data.getFileLen() % new BigInteger(data.getBlockSize()));
                    }
                }
                int count = num6;
                num6 = (num6 + 15) & -16;
                Debug.Print("Offset: %016X, len: %08X, realLen: %08X, endCompress: %d\r\n", new object[] { num5, num6, count, num7 });
                ii.Seek(num5, SeekOrigin.Begin);
                byte[] buffer  = new byte[num6];
                byte[] buffer5 = new byte[num6];
                ii.Read(buffer, 0, buffer.Length);
                byte[] buffer6 = new byte[0x10];
                byte[] buffer7 = new byte[0x10];
                byte[] buffer8 = this.calculateBlockKey(i, npd);
                ToolsImpl.aesecbEncrypt(rifkey, buffer8, 0, buffer6, 0, buffer8.Length);
                if ((data.getFlags() & FLAG_0x10) != 0L)
                {
                    ToolsImpl.aesecbEncrypt(rifkey, buffer6, 0, buffer7, 0, buffer6.Length);
                }
                else
                {
                    ConversionUtils.arraycopy(buffer6, 0, buffer7, 0L, buffer6.Length);
                }
                int cryptoFlag = ((data.getFlags() & FLAG_0x02) == 0L) ? 2 : 1;
                if ((data.getFlags() & FLAG_0x10) == 0L)
                {
                    num11 = 2;
                }
                else if ((data.getFlags() & FLAG_0x20) == 0L)
                {
                    num11 = 4;
                }
                else
                {
                    num11 = 1;
                }
                if ((data.getFlags() & FLAG_KEYENCRYPTED) != 0L)
                {
                    cryptoFlag |= 0x10000000;
                    num11      |= 0x10000000;
                }
                if ((data.getFlags() & FLAG_DEBUG) != 0L)
                {
                    cryptoFlag |= 0x1000000;
                    num11      |= 0x1000000;
                }
                AppLoader loader  = new AppLoader();
                byte[]    buffer9 = (npd.getVersion() <= 1L) ? new byte[0x10] : npd.getDigest();
                if (!loader.doAll(num11, cryptoFlag, buffer, 0, buffer5, 0, buffer.Length, buffer6, npd.getDigest(), buffer7, dest, 0))
                {
                    Debug.WriteLine("Error decrypting block " + i);
                }
                if ((data.getFlags() & FLAG_COMPRESSED) == 0L)
                {
                    o.Write(buffer5, 0, count);
                }
            }
            return(STATUS_OK);
        }