Esempio n. 1
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);
 }
Esempio n. 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);
        }
Esempio n. 3
0
        private byte[] writeValidNPD(string filename, byte[] devKLic, NPD[] npdPtr, FileStream fin, byte[] contentID, byte[] flags, byte[] version, byte[] type)
        {
            int num;

            byte[] dest = new byte[0x80];
            dest[0]  = 0x4e;
            dest[1]  = 80;
            dest[2]  = 0x44;
            dest[3]  = 0;
            dest[4]  = 0;
            dest[5]  = 0;
            dest[6]  = 0;
            dest[7]  = version[0];
            dest[8]  = 0;
            dest[9]  = 0;
            dest[10] = 0;
            dest[11] = 3;
            dest[12] = 0;
            dest[13] = 0;
            dest[14] = 0;
            dest[15] = type[0];
            for (num = 0; num < 0x30; num++)
            {
                dest[0x10 + num] = contentID[num];
            }
            ConversionUtils.arraycopy(ConversionUtils.charsToByte("FixedLicenseEDAT".ToCharArray()), 0, dest, 0x40L, 0x10);
            ConversionUtils.arraycopy(this.createNPDHash1(filename, dest), 0, dest, 80L, 0x10);
            ConversionUtils.arraycopy(this.createNPDHash2(devKLic, dest), 0, dest, 0x60L, 0x10);
            for (num = 0; num < 0x10; num++)
            {
                dest[0x70 + num] = 0;
            }
            npdPtr[0] = NPD.createNPD(dest);
            return(dest);
        }
Esempio n. 4
0
 private byte[] calculateBlockKey(int blk, NPD npd)
 {
     byte[] src  = (npd.getVersion() <= 1L) ? new byte[0x10] : npd.getDevHash();
     byte[] dest = new byte[0x10];
     ConversionUtils.arraycopy(src, 0, dest, 0L, 12);
     dest[12] = (byte)((blk >> 0x18) & 0xff);
     dest[13] = (byte)((blk >> 0x10) & 0xff);
     dest[14] = (byte)((blk >> 8) & 0xff);
     dest[15] = (byte)(blk & 0xff);
     return(dest);
 }
Esempio n. 5
0
 private byte[] calculateBlockKey(int blk, NPD npd)
 {
     byte[] baseKey = (npd.getVersion() <= 1) ? (new byte[0x10]) : npd.getDevHash();
     byte[] result  = new byte[0x10];
     ConversionUtils.arraycopy(baseKey, 0, result, 0, 0xC);
     result[0xC] = (byte)(blk >> 24 & 0xFF);
     result[0xD] = (byte)(blk >> 16 & 0xFF);
     result[0xE] = (byte)(blk >> 8 & 0xFF);
     result[0xF] = (byte)(blk & 0xFF);
     return(result);
 }
Esempio n. 6
0
        /* KDSBEST END */

        public int decryptFile(String inFile, String outFile, byte[] devKLic, byte[] keyFromRif)
        {
            FileStream fin = File.Open(inFile, FileMode.Open);

            string[] fn = fin.Name.Split('\\');
            //string[] fn = fin.Name.Split('/');
            Console.WriteLine(fn[fn.Length - 1]);

            NPD[] ptr    = new NPD[1];                                        //Ptr to Ptr
            int   result = validateNPD(fn[fn.Length - 1], devKLic, ptr, fin); //Validate NPD hashes

            if (result < 0)
            {
                fin.Close();
                return(result);
            }
            NPD      npd  = ptr[0];
            EDATData data = getEDATData(fin);                       //Get flags, blocksize and file len

            byte[] rifkey = getKey(npd, data, devKLic, keyFromRif); //Obtain the key for decryption (result of sc471 or sdatkey)
            if (rifkey == null)
            {
                Console.WriteLine("ERROR: Key for decryption is missing");
                fin.Close();
                return(STATUS_ERROR_MISSINGKEY);
            }
            else
            {
                Console.WriteLine("DECRYPTION KEY: " + ConversionUtils.getHexString(rifkey));
            }
            result = checkHeader(rifkey, data, npd, fin);
            if (result < 0)
            {
                fin.Close();
                return(result);
            }
            FileStream o = File.Open(outFile, FileMode.Create);

            result = decryptData(fin, o, npd, data, rifkey);
            if (result < 0)
            {
                fin.Close();
                return(result);
            }
            fin.Close();
            o.Close();
            Console.WriteLine("COMPLETE: File Written to disk");
            return(STATUS_OK);
        }
Esempio n. 7
0
        private int encryptData(FileStream ii, FileStream o, NPD npd, EDATData data, byte[] rifkey)
        {
            int num = (int)(((data.getFileLen() + data.getBlockSize()) - 1) / data.getBlockSize());

            byte[] dest    = new byte[num * 0x10];
            byte[] buffer2 = new byte[ii.Length + 15L];
            for (int i = 0; i < num; i++)
            {
                long offset = i * data.getBlockSize();
                ii.Seek(offset, SeekOrigin.Begin);
                int length = (int)data.getBlockSize();
                if (i == (num - 1))
                {
                    length = (int)(data.getFileLen() % new BigInteger(data.getBlockSize()));
                }
                int num5 = length;
                length = (length + 15) & -16;
                byte[] buffer3 = new byte[length];
                byte[] buffer4 = new byte[length];
                for (int j = num5; j > 0; j -= ii.Read(buffer4, num5 - j, j))
                {
                }
                for (int k = num5; k < length; k++)
                {
                    buffer4[k] = 0;
                }
                byte[] buffer5 = new byte[0x10];
                byte[] buffer6 = new byte[0x10];
                byte[] buffer7 = this.calculateBlockKey(i, npd);
                ToolsImpl.aesecbEncrypt(rifkey, buffer7, 0, buffer5, 0, buffer7.Length);
                ConversionUtils.arraycopy(buffer5, 0, buffer6, 0L, buffer5.Length);
                int cryptoFlag                 = 2;
                int hashFlag                   = 2;
                AppLoaderReverse reverse       = new AppLoaderReverse();
                byte[]           iv            = npd.getDigest();
                byte[]           generatedHash = new byte[0x10];
                reverse.doAll(hashFlag, cryptoFlag, buffer4, 0, buffer3, 0, buffer4.Length, buffer5, iv, buffer6, generatedHash, 0);
                ConversionUtils.arraycopy(buffer3, 0, buffer2, offset, length);
                ConversionUtils.arraycopy(generatedHash, 0, dest, (long)(i * 0x10), 0x10);
            }
            byte[] buffer = ConversionUtils.getByteArray("4D6164652062792052325220546F6F6C");
            o.Write(dest, 0, dest.Length);
            o.Write(buffer2, 0, buffer2.Length - 15);
            o.Write(buffer, 0, buffer.Length);
            return(STATUS_OK);
        }
Esempio n. 8
0
        public int decryptFile(string inFile, string outFile, byte[] devKLic, byte[] keyFromRif)
        {
            FileStream i = File.Open(inFile, FileMode.Open);

            string[] strArray = i.Name.Split(new char[] { '\\' });
            Console.WriteLine(strArray[strArray.Length - 1]);
            NPD[] npdPtr = new NPD[1];
            int   num    = this.validateNPD(strArray[strArray.Length - 1], devKLic, npdPtr, i);

            if (num < 0)
            {
                i.Close();
                return(num);
            }
            NPD      npd  = npdPtr[0];
            EDATData data = this.getEDATData(i);

            byte[] raw = this.getKey(npd, data, devKLic, keyFromRif);
            if (raw == null)
            {
                Console.WriteLine("ERROR: Key for decryption is missing");
                i.Close();
                return(STATUS_ERROR_MISSINGKEY);
            }
            Console.WriteLine("DECRYPTION KEY: " + ConversionUtils.getHexString(raw));
            num = this.checkHeader(raw, data, npd, i);
            if (num < 0)
            {
                i.Close();
                return(num);
            }
            FileStream o = File.Open(outFile, FileMode.Create);

            num = this.decryptData(i, o, npd, data, raw);
            if (num < 0)
            {
                i.Close();
                return(num);
            }
            i.Close();
            o.Close();
            Console.WriteLine("COMPLETE: File Written to disk");
            return(STATUS_OK);
        }
Esempio n. 9
0
 private byte[] getKey(NPD npd, EDATData data, byte[] devKLic, byte[] keyFromRif)
 {
     byte[] output = null;
     if ((data.getFlags() & FLAG_SDAT) != 0L)
     {
         output = new byte[0x10];
         ToolsImpl.XOR(output, npd.getDevHash(), EDATKeys.SDATKEY);
         return(output);
     }
     if (npd.getLicense() == 3L)
     {
         return(devKLic);
     }
     if (npd.getLicense() == 2L)
     {
         output = keyFromRif;
     }
     return(output);
 }
Esempio n. 10
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;
 }
Esempio n. 11
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);
        }
Esempio n. 12
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);
        }
Esempio n. 13
0
 public int decryptFile(string inFile, string outFile, byte[] devKLic, byte[] keyFromRif)
 {
     FileStream i = File.Open(inFile, FileMode.Open);
     string[] strArray = i.Name.Split(new char[] { '\\' });
     Console.WriteLine(strArray[strArray.Length - 1]);
     NPD[] npdPtr = new NPD[1];
     int num = this.validateNPD(strArray[strArray.Length - 1], devKLic, npdPtr, i);
     if (num < 0)
     {
         i.Close();
         return num;
     }
     NPD npd = npdPtr[0];
     EDATData data = this.getEDATData(i);
     byte[] raw = this.getKey(npd, data, devKLic, keyFromRif);
     if (raw == null)
     {
         Console.WriteLine("ERROR: Key for decryption is missing");
         i.Close();
         return STATUS_ERROR_MISSINGKEY;
     }
     Console.WriteLine("DECRYPTION KEY: " + ConversionUtils.getHexString(raw));
     num = this.checkHeader(raw, data, npd, i);
     if (num < 0)
     {
         i.Close();
         return num;
     }
     FileStream o = File.Open(outFile, FileMode.Create);
     num = this.decryptData(i, o, npd, data, raw);
     if (num < 0)
     {
         i.Close();
         return num;
     }
     i.Close();
     o.Close();
     Console.WriteLine("COMPLETE: File Written to disk");
     return STATUS_OK;
 }
Esempio n. 14
0
 private byte[] getKey(NPD npd, EDATData data, byte[] devKLic, byte[] keyFromRif)
 {
     byte[] result = null;
     if ((data.getFlags() & FLAG_SDAT) != 0)
     {
         //Case SDAT
         result = new byte[0x10];
         ToolsImpl.XOR(result, npd.getDevHash(), EDATKeys.SDATKEY);
     }
     else
     {
         //Case EDAT
         if (npd.getLicense() == 0x03)
         {
             result = devKLic;
         }
         else if (npd.getLicense() == 0x02)
         {
             result = keyFromRif;
         }
     }
     return(result);
 }
Esempio n. 15
0
        private int encryptData(FileStream ii, FileStream o, NPD npd, EDATData data, byte[] rifkey)
        {
            int numBlocks = (int)((data.getFileLen() + data.getBlockSize() - 1) / data.getBlockSize());

            byte[] expectedHashForFile  = new byte[numBlocks * 0x10];
            byte[] encryptedDataForFile = new byte[ii.Length + 0xF];

            // File Format:
            // ALL HASHES
            // Encrypted Data
            for (int i = 0; i < numBlocks; i++)
            {
                long offset;
                int  len;

                offset = i * data.getBlockSize();
                ii.Seek(offset, SeekOrigin.Begin);
                len = (int)(data.getBlockSize());
                if (i == numBlocks - 1)
                {
                    len = (int)(data.getFileLen() % (new BigInteger(data.getBlockSize())));
                }


                int realLen = len;
                len = (int)((uint)(len + 0x0F) & 0xFFFFFFF0);

                byte[] encryptedData = new byte[len];
                byte[] decryptedData = new byte[len];

                int toRead = realLen;
                while (toRead > 0)
                {
                    toRead -= ii.Read(decryptedData, realLen - toRead, toRead);
                }
                for (int ai = realLen; ai < len; ai++)
                {
                    decryptedData[ai] = 0x00;
                }

                byte[] key      = new byte[0x10];
                byte[] hash     = new byte[0x10];
                byte[] blockKey = calculateBlockKey(i, npd);

                ToolsImpl.aesecbEncrypt(rifkey, blockKey, 0, key, 0, blockKey.Length);
                ConversionUtils.arraycopy(key, 0, hash, 0, key.Length);
                int cryptoFlag = 0x2;
                int hashFlag   = 0x02;

                AppLoaderReverse a             = new AppLoaderReverse();
                byte[]           iv            = npd.getDigest();
                byte[]           generatedHash = new byte[0x10];
                a.doAll(hashFlag, cryptoFlag, decryptedData, 0, encryptedData, 0, decryptedData.Length, key, iv, hash, generatedHash, 0);
                ConversionUtils.arraycopy(encryptedData, 0, encryptedDataForFile, offset, len);
                ConversionUtils.arraycopy(generatedHash, 0, expectedHashForFile, i * 0x10, 0x10);
            }
            byte[] EDATAVersion = ConversionUtils.getByteArray("4D6164652062792052325220546F6F6C");
            o.Write(expectedHashForFile, 0, expectedHashForFile.Length);
            o.Write(encryptedDataForFile, 0, encryptedDataForFile.Length - 0xf);
            o.Write(EDATAVersion, 0, EDATAVersion.Length);
            return(STATUS_OK);
        }
Esempio n. 16
0
        /* KDSBEST START */
        public int encryptFile(String inFile, String outFile, byte[] devKLic, byte[] keyFromRif, byte[] contentID, byte[] flags, byte[] type, byte[] version)
        {
            FileStream fin = File.Open(inFile, FileMode.Open);

            //  MemoryMappedFile fin1 = MemoryMappedFile.CreateFromFile(inFile, FileMode.Open);
            NPD[]      ptr = new NPD[1]; //Ptr to Ptr
            FileStream o   = File.Open(outFile, FileMode.Create);

            string[] fn  = o.Name.Split('\\');
            byte[]   npd = writeValidNPD(fn[fn.Length - 1], devKLic, ptr, fin, contentID, flags, version, type);
            o.Write(npd, 0, npd.Length);
            byte[] buffer = new byte[4];
            // FLAGS
            buffer[0] = 0x00;
            buffer[1] = 0x00;
            buffer[2] = 0x00;
            buffer[3] = 0x00;
            o.Write(buffer, 0, 4);

            // blocksize 0x00004000
            buffer[2] = 0x40;
            o.Write(buffer, 0, 4);
            long len = fin.Length;

            byte[] lenBuf  = BitConverter.GetBytes(len);
            byte[] rLenBuf = new byte[8];
            for (int i = 0; i < 8; i++)
            {
                rLenBuf[i] = 0x00;
            }
            for (int i = 0; i < lenBuf.Length; i++)
            {
                rLenBuf[7 - i] = lenBuf[i];
            }
            o.Write(rLenBuf, 0, 8);

            // Fill the rest 0x10 bytes with dummy we generate the metasection hash later!
            // the bytes till 0x100 are unknown
            buffer[0] = 0x00;
            while (o.Length < 0x100)
            {
                o.Write(buffer, 0, 1);
            }

            EDATData data = new EDATData();

            data.flags     = 0x00000000;
            data.blockSize = 0x00004000;
            data.fileLen   = new BigInteger(len);
            byte[] rifkey   = getKey(ptr[0], data, devKLic, keyFromRif); //Obtain the key for decryption (result of sc471 or sdatkey)
            int    hashFlag = 0x00000002;


            encryptData(fin, o, ptr[0], data, rifkey);

            o.Seek(0x90, SeekOrigin.Begin);
            AppLoader aa = new AppLoader();

            aa.doInit(hashFlag, 0x00000001, new byte[0x10], new byte[0x10], rifkey);

            int sectionSize = ((data.getFlags() & FLAG_COMPRESSED) != 0) ? 0x20 : 0x010; //BUG??? What about FLAG0x20??
            //Determine the metadatasection total len
            int numBlocks = (int)((data.getFileLen() + data.getBlockSize() - 11) / data.getBlockSize());

            int readed     = 0;
            int baseOffset = 0x100;
            //baseOffset +=  modifier; //There is an unknown offset to add to the metadatasection... value seen 0
            long remaining = sectionSize * numBlocks;

            while (remaining > 0)
            {
                int lenToRead = (HEADER_MAX_BLOCKSIZE > remaining) ? (int)remaining : HEADER_MAX_BLOCKSIZE;
                o.Seek(baseOffset + readed, SeekOrigin.Begin);
                byte[] content = new byte[lenToRead];
                byte[] ooo     = new byte[lenToRead];
                o.Read(content, 0, content.Length);
                aa.doUpdate(content, 0, ooo, 0, lenToRead);
                readed    += lenToRead;
                remaining -= lenToRead;
            }
            byte[] headerHash = new byte[0x10];
            aa.doFinalButGetHash(headerHash);
            o.Seek(0x90, SeekOrigin.Begin);
            o.Write(headerHash, 0, headerHash.Length);

            // Header Complete

            // Generate Header Hash
            o.Seek(0, SeekOrigin.Begin);
            byte[] header       = new byte[0xA0];
            byte[] headerODummy = new byte[0xA0];
            o.Read(header, 0, header.Length);
            AppLoaderReverse a = new AppLoaderReverse();

            byte[] generatedHash = new byte[0x10];
            bool   result        = a.doAll(hashFlag, 0x00000001, header, 0, headerODummy, 0, header.Length, new byte[0x10], new byte[0x10], rifkey, generatedHash, 0);

            o.Seek(0xA0, SeekOrigin.Begin);
            o.Write(generatedHash, 0, generatedHash.Length);


            //KDSBest We don't know the DATA 0xB0 to 0x100!!!

            while (o.Length < 0x100)
            {
                o.Write(buffer, 0, 1);
            }


            o.Close();
            fin.Close();
            return(STATUS_OK);
        }
Esempio n. 17
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);
        }
Esempio n. 18
0
        public int encryptFile(string inFile, string outFile, byte[] devKLic, byte[] keyFromRif, byte[] contentID, byte[] flags, byte[] type, byte[] version)
        {
            int        num2;
            int        num9;
            FileStream fin = File.Open(inFile, FileMode.Open);

            NPD[]      npdPtr = new NPD[1];
            FileStream o      = File.Open(outFile, FileMode.Create);

            string[] strArray = o.Name.Split(new char[] { '\\' });
            byte[]   buffer   = this.writeValidNPD(strArray[strArray.Length - 1], devKLic, npdPtr, fin, contentID, flags, version, type);
            o.Write(buffer, 0, buffer.Length);
            byte[] buffer2 = new byte[] { 0, 0, 0, 0 };
            o.Write(buffer2, 0, 4);
            buffer2[2] = 0x40;
            o.Write(buffer2, 0, 4);
            long length = fin.Length;

            byte[] bytes   = BitConverter.GetBytes(length);
            byte[] buffer4 = new byte[8];
            for (num2 = 0; num2 < 8; num2++)
            {
                buffer4[num2] = 0;
            }
            for (num2 = 0; num2 < bytes.Length; num2++)
            {
                buffer4[7 - num2] = bytes[num2];
            }
            o.Write(buffer4, 0, 8);
            buffer2[0] = 0;
            while (o.Length < 0x100L)
            {
                o.Write(buffer2, 0, 1);
            }
            EDATData data = new EDATData {
                flags     = 0L,
                blockSize = 0x4000L,
                fileLen   = new BigInteger(length)
            };

            byte[] rifkey   = this.getKey(npdPtr[0], data, devKLic, keyFromRif);
            int    hashFlag = 2;

            this.encryptData(fin, o, npdPtr[0], data, rifkey);
            o.Seek(0x90L, SeekOrigin.Begin);
            AppLoader loader = new AppLoader();

            loader.doInit(hashFlag, 1, new byte[0x10], new byte[0x10], rifkey);
            int num4 = ((data.getFlags() & FLAG_COMPRESSED) != 0L) ? 0x20 : 0x10;
            int num5 = (int)(((data.getFileLen() + data.getBlockSize()) - 11) / data.getBlockSize());
            int num6 = 0;
            int num7 = 0x100;

            for (long i = num4 * num5; i > 0L; i -= num9)
            {
                num9 = (HEADER_MAX_BLOCKSIZE > i) ? ((int)i) : HEADER_MAX_BLOCKSIZE;
                o.Seek((long)(num7 + num6), SeekOrigin.Begin);
                byte[] buffer6 = new byte[num9];
                byte[] buffer7 = new byte[num9];
                o.Read(buffer6, 0, buffer6.Length);
                loader.doUpdate(buffer6, 0, buffer7, 0, num9);
                num6 += num9;
            }
            byte[] generatedHash = new byte[0x10];
            loader.doFinalButGetHash(generatedHash);
            o.Seek(0x90L, SeekOrigin.Begin);
            o.Write(generatedHash, 0, generatedHash.Length);
            o.Seek(0L, SeekOrigin.Begin);
            byte[] buffer9  = new byte[160];
            byte[] buffer10 = new byte[160];
            o.Read(buffer9, 0, buffer9.Length);
            AppLoaderReverse reverse = new AppLoaderReverse();

            byte[] buffer11 = new byte[0x10];
            bool   flag     = reverse.doAll(hashFlag, 1, buffer9, 0, buffer10, 0, buffer9.Length, new byte[0x10], new byte[0x10], rifkey, buffer11, 0);

            o.Seek(160L, SeekOrigin.Begin);
            o.Write(buffer11, 0, buffer11.Length);
            while (o.Length < 0x100L)
            {
                o.Write(buffer2, 0, 1);
            }
            o.Close();
            fin.Close();
            return(STATUS_OK);
        }
Esempio n. 19
0
        private int checkHeader(byte[] rifKey, EDATData data, NPD npd, FileStream i)
        {
            i.Seek(0, SeekOrigin.Begin);
            byte[] header       = new byte[0xA0];
            byte[] o            = new byte[0xA0];
            byte[] expectedHash = new byte[0x10];
            //Version check
            Console.WriteLine("Checking NPD Version:" + npd.getVersion());
            if ((npd.getVersion() == 0) || (npd.getVersion() == 1))
            {
                if ((data.getFlags() & 0x7FFFFFFE) != 0)
                {
                    Console.WriteLine("ERROR: Incorrect Header Flags"); return(STATUS_ERROR_INCORRECT_FLAGS);
                }
            }
            else if (npd.getVersion() == 2)
            {
                if ((data.getFlags() & 0x7EFFFFE0) != 0)
                {
                    Console.WriteLine("ERROR: Incorrect Header Flags"); return(STATUS_ERROR_INCORRECT_FLAGS);
                }
            }
            else if (npd.getVersion() == 3 || (npd.getVersion() == 4))
            {
                if ((data.getFlags() & 0x7EFFFFC0) != 0)
                {
                    Console.WriteLine("ERROR: Incorrect Header Flags"); return(STATUS_ERROR_INCORRECT_FLAGS);
                }
            }
            else
            {
                Console.WriteLine("ERROR: Unsupported EDAT version (need keys)"); return(STATUS_ERROR_INCORRECT_VERSION);
            }

            {
                int keyIndex = 0;
                if (npd.getVersion() == 4)
                {
                    keyIndex = 1;
                }


                i.Read(header, 0, header.Length);
                i.Read(expectedHash, 0, expectedHash.Length);
                Console.WriteLine("Checking header hash:");
                AppLoader a        = new AppLoader();
                int       hashFlag = ((data.getFlags() & FLAG_KEYENCRYPTED) == 0) ? 0x00000002 : 0x10000002;
                if ((data.getFlags() & FLAG_DEBUG) != 0)
                {
                    hashFlag |= 0x01000000;
                }



                //Veryfing header
                bool result = a.doAll(hashFlag, 0x00000001, header, 0, o, 0, header.Length, new byte[0x10], new byte[0x10], rifKey, expectedHash, 0);
                if (!result)
                {
                    Console.WriteLine("Error verifying header. Is rifKey valid?.");
                    return(STATUS_ERROR_HEADERCHECK);
                }
                Console.WriteLine("Checking metadata hash:");
                a = new AppLoader();
                a.doInit(hashFlag, 0x00000001, new byte[0x10], new byte[0x10], rifKey);

                int sectionSize = ((data.getFlags() & FLAG_COMPRESSED) != 0) ? 0x20 : 0x010; //BUG??? What about FLAG0x20??
                //Determine the metadatasection total len
                int numBlocks = (int)((data.getFileLen() + data.getBlockSize() - 11) / data.getBlockSize());

                int readed     = 0;
                int baseOffset = 0x100;
                //baseOffset +=  modifier; //There is an unknown offset to add to the metadatasection... value seen 0
                long remaining = sectionSize * numBlocks;
                while (remaining > 0)
                {
                    int lenToRead = (HEADER_MAX_BLOCKSIZE > remaining) ? (int)remaining : HEADER_MAX_BLOCKSIZE;
                    i.Seek(baseOffset + readed, SeekOrigin.Begin);
                    byte[] content = new byte[lenToRead];
                    o = new byte[lenToRead];
                    i.Read(content, 0, content.Length);
                    a.doUpdate(content, 0, o, 0, lenToRead);
                    readed    += lenToRead;
                    remaining -= lenToRead;
                }
                result = a.doFinal(header, 0x90);


                if (!result)
                {
                    Console.WriteLine("Error verifying metadatasection. Data tampered");
                    return(STATUS_ERROR_HEADERCHECK);
                }
                return(STATUS_OK);
            }
        }
Esempio n. 20
0
 private int checkHeader(byte[] rifKey, EDATData data, NPD npd, FileStream i)
 {
     int num8;
     i.Seek(0L, SeekOrigin.Begin);
     byte[] buffer = new byte[160];
     byte[] o = new byte[160];
     byte[] buffer3 = new byte[0x10];
     Console.WriteLine("Checking NPD Version:" + npd.getVersion());
     if ((npd.getVersion() == 0L) || (npd.getVersion() == 1L))
     {
         if ((data.getFlags() & 0x7ffffffeL) != 0L)
         {
             Console.WriteLine("ERROR: Incorrect Header Flags");
             return STATUS_ERROR_INCORRECT_FLAGS;
         }
     }
     else if (npd.getVersion() == 2L)
     {
         if ((data.getFlags() & 0x7effffe0L) != 0L)
         {
             Console.WriteLine("ERROR: Incorrect Header Flags");
             return STATUS_ERROR_INCORRECT_FLAGS;
         }
     }
     else if ((npd.getVersion() == 3L) || (npd.getVersion() == 4L))
     {
         if ((data.getFlags() & 0x7effffc0L) != 0L)
         {
             Console.WriteLine("ERROR: Incorrect Header Flags");
             return STATUS_ERROR_INCORRECT_FLAGS;
         }
     }
     else
     {
         Console.WriteLine("ERROR: Unsupported EDAT version (need keys)");
         return STATUS_ERROR_INCORRECT_VERSION;
     }
     if (npd.getVersion() == 4L)
     {
     }
     i.Read(buffer, 0, buffer.Length);
     i.Read(buffer3, 0, buffer3.Length);
     Console.WriteLine("Checking header hash:");
     AppLoader loader = new AppLoader();
     int hashFlag = ((data.getFlags() & FLAG_KEYENCRYPTED) == 0L) ? 2 : 0x10000002;
     if ((data.getFlags() & FLAG_DEBUG) != 0L)
     {
         hashFlag |= 0x1000000;
     }
     if (!loader.doAll(hashFlag, 1, buffer, 0, o, 0, buffer.Length, new byte[0x10], new byte[0x10], rifKey, buffer3, 0))
     {
         Console.WriteLine("Error verifying header. Is rifKey valid?.");
         return STATUS_ERROR_HEADERCHECK;
     }
     Console.WriteLine("Checking metadata hash:");
     loader = new AppLoader();
     loader.doInit(hashFlag, 1, new byte[0x10], new byte[0x10], rifKey);
     int num3 = ((data.getFlags() & FLAG_COMPRESSED) != 0L) ? 0x20 : 0x10;
     int num4 = (int) (((data.getFileLen() + data.getBlockSize()) - 11) / data.getBlockSize());
     int num5 = 0;
     int num6 = 0x100;
     for (long j = num3 * num4; j > 0L; j -= num8)
     {
         num8 = (HEADER_MAX_BLOCKSIZE > j) ? ((int) j) : HEADER_MAX_BLOCKSIZE;
         i.Seek((long) (num6 + num5), SeekOrigin.Begin);
         byte[] buffer4 = new byte[num8];
         o = new byte[num8];
         i.Read(buffer4, 0, buffer4.Length);
         loader.doUpdate(buffer4, 0, o, 0, num8);
         num5 += num8;
     }
     if (!loader.doFinal(buffer, 0x90))
     {
         Console.WriteLine("Error verifying metadatasection. Data tampered");
         return STATUS_ERROR_HEADERCHECK;
     }
     return STATUS_OK;
 }
Esempio n. 21
0
 private int encryptData(FileStream ii, FileStream o, NPD npd, EDATData data, byte[] rifkey)
 {
     int num = (int) (((data.getFileLen() + data.getBlockSize()) - 1) / data.getBlockSize());
     byte[] dest = new byte[num * 0x10];
     byte[] buffer2 = new byte[ii.Length + 15L];
     for (int i = 0; i < num; i++)
     {
         long offset = i * data.getBlockSize();
         ii.Seek(offset, SeekOrigin.Begin);
         int length = (int) data.getBlockSize();
         if (i == (num - 1))
         {
             length = (int) (data.getFileLen() % new BigInteger(data.getBlockSize()));
         }
         int num5 = length;
         length = (length + 15) & -16;
         byte[] buffer3 = new byte[length];
         byte[] buffer4 = new byte[length];
         for (int j = num5; j > 0; j -= ii.Read(buffer4, num5 - j, j))
         {
         }
         for (int k = num5; k < length; k++)
         {
             buffer4[k] = 0;
         }
         byte[] buffer5 = new byte[0x10];
         byte[] buffer6 = new byte[0x10];
         byte[] buffer7 = this.calculateBlockKey(i, npd);
         ToolsImpl.aesecbEncrypt(rifkey, buffer7, 0, buffer5, 0, buffer7.Length);
         ConversionUtils.arraycopy(buffer5, 0, buffer6, 0L, buffer5.Length);
         int cryptoFlag = 2;
         int hashFlag = 2;
         AppLoaderReverse reverse = new AppLoaderReverse();
         byte[] iv = npd.getDigest();
         byte[] generatedHash = new byte[0x10];
         reverse.doAll(hashFlag, cryptoFlag, buffer4, 0, buffer3, 0, buffer4.Length, buffer5, iv, buffer6, generatedHash, 0);
         ConversionUtils.arraycopy(buffer3, 0, buffer2, offset, length);
         ConversionUtils.arraycopy(generatedHash, 0, dest, (long) (i * 0x10), 0x10);
     }
     byte[] buffer = ConversionUtils.getByteArray("4D6164652062792052325220546F6F6C");
     o.Write(dest, 0, dest.Length);
     o.Write(buffer2, 0, buffer2.Length - 15);
     o.Write(buffer, 0, buffer.Length);
     return STATUS_OK;
 }
Esempio n. 22
0
 private byte[] writeValidNPD(string filename, byte[] devKLic, NPD[] npdPtr, FileStream fin, byte[] contentID, byte[] flags, byte[] version, byte[] type)
 {
     int num;
     byte[] dest = new byte[0x80];
     dest[0] = 0x4e;
     dest[1] = 80;
     dest[2] = 0x44;
     dest[3] = 0;
     dest[4] = 0;
     dest[5] = 0;
     dest[6] = 0;
     dest[7] = version[0];
     dest[8] = 0;
     dest[9] = 0;
     dest[10] = 0;
     dest[11] = 3;
     dest[12] = 0;
     dest[13] = 0;
     dest[14] = 0;
     dest[15] = type[0];
     for (num = 0; num < 0x30; num++)
     {
         dest[0x10 + num] = contentID[num];
     }
     ConversionUtils.arraycopy(ConversionUtils.charsToByte("FixedLicenseEDAT".ToCharArray()), 0, dest, 0x40L, 0x10);
     ConversionUtils.arraycopy(this.createNPDHash1(filename, dest), 0, dest, 80L, 0x10);
     ConversionUtils.arraycopy(this.createNPDHash2(devKLic, dest), 0, dest, 0x60L, 0x10);
     for (num = 0; num < 0x10; num++)
     {
         dest[0x70 + num] = 0;
     }
     npdPtr[0] = NPD.createNPD(dest);
     return dest;
 }
Esempio n. 23
0
 public int encryptFile(string inFile, string outFile, byte[] devKLic, byte[] keyFromRif, byte[] contentID, byte[] flags, byte[] type, byte[] version)
 {
     int num2;
     int num9;
     FileStream fin = File.Open(inFile, FileMode.Open);
     NPD[] npdPtr = new NPD[1];
     FileStream o = File.Open(outFile, FileMode.Create);
     string[] strArray = o.Name.Split(new char[] { '\\' });
     byte[] buffer = this.writeValidNPD(strArray[strArray.Length - 1], devKLic, npdPtr, fin, contentID, flags, version, type);
     o.Write(buffer, 0, buffer.Length);
     byte[] buffer2 = new byte[] { 0, 0, 0, 0 };
     o.Write(buffer2, 0, 4);
     buffer2[2] = 0x40;
     o.Write(buffer2, 0, 4);
     long length = fin.Length;
     byte[] bytes = BitConverter.GetBytes(length);
     byte[] buffer4 = new byte[8];
     for (num2 = 0; num2 < 8; num2++)
     {
         buffer4[num2] = 0;
     }
     for (num2 = 0; num2 < bytes.Length; num2++)
     {
         buffer4[7 - num2] = bytes[num2];
     }
     o.Write(buffer4, 0, 8);
     buffer2[0] = 0;
     while (o.Length < 0x100L)
     {
         o.Write(buffer2, 0, 1);
     }
     EDATData data = new EDATData {
         flags = 0L,
         blockSize = 0x4000L,
         fileLen = new BigInteger(length)
     };
     byte[] rifkey = this.getKey(npdPtr[0], data, devKLic, keyFromRif);
     int hashFlag = 2;
     this.encryptData(fin, o, npdPtr[0], data, rifkey);
     o.Seek(0x90L, SeekOrigin.Begin);
     AppLoader loader = new AppLoader();
     loader.doInit(hashFlag, 1, new byte[0x10], new byte[0x10], rifkey);
     int num4 = ((data.getFlags() & FLAG_COMPRESSED) != 0L) ? 0x20 : 0x10;
     int num5 = (int) (((data.getFileLen() + data.getBlockSize()) - 11) / data.getBlockSize());
     int num6 = 0;
     int num7 = 0x100;
     for (long i = num4 * num5; i > 0L; i -= num9)
     {
         num9 = (HEADER_MAX_BLOCKSIZE > i) ? ((int) i) : HEADER_MAX_BLOCKSIZE;
         o.Seek((long) (num7 + num6), SeekOrigin.Begin);
         byte[] buffer6 = new byte[num9];
         byte[] buffer7 = new byte[num9];
         o.Read(buffer6, 0, buffer6.Length);
         loader.doUpdate(buffer6, 0, buffer7, 0, num9);
         num6 += num9;
     }
     byte[] generatedHash = new byte[0x10];
     loader.doFinalButGetHash(generatedHash);
     o.Seek(0x90L, SeekOrigin.Begin);
     o.Write(generatedHash, 0, generatedHash.Length);
     o.Seek(0L, SeekOrigin.Begin);
     byte[] buffer9 = new byte[160];
     byte[] buffer10 = new byte[160];
     o.Read(buffer9, 0, buffer9.Length);
     AppLoaderReverse reverse = new AppLoaderReverse();
     byte[] buffer11 = new byte[0x10];
     bool flag = reverse.doAll(hashFlag, 1, buffer9, 0, buffer10, 0, buffer9.Length, new byte[0x10], new byte[0x10], rifkey, buffer11, 0);
     o.Seek(160L, SeekOrigin.Begin);
     o.Write(buffer11, 0, buffer11.Length);
     while (o.Length < 0x100L)
     {
         o.Write(buffer2, 0, 1);
     }
     o.Close();
     fin.Close();
     return STATUS_OK;
 }
Esempio n. 24
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;
 }
Esempio n. 25
0
 private byte[] getKey(NPD npd, EDATData data, byte[] devKLic, byte[] keyFromRif)
 {
     byte[] output = null;
     if ((data.getFlags() & FLAG_SDAT) != 0L)
     {
         output = new byte[0x10];
         ToolsImpl.XOR(output, npd.getDevHash(), EDATKeys.SDATKEY);
         return output;
     }
     if (npd.getLicense() == 3L)
     {
         return devKLic;
     }
     if (npd.getLicense() == 2L)
     {
         output = keyFromRif;
     }
     return output;
 }
Esempio n. 26
0
        private int checkHeader(byte[] rifKey, EDATData data, NPD npd, FileStream i)
        {
            int num8;

            i.Seek(0L, SeekOrigin.Begin);
            byte[] buffer  = new byte[160];
            byte[] o       = new byte[160];
            byte[] buffer3 = new byte[0x10];
            Console.WriteLine("Checking NPD Version:" + npd.getVersion());
            if ((npd.getVersion() == 0L) || (npd.getVersion() == 1L))
            {
                if ((data.getFlags() & 0x7ffffffeL) != 0L)
                {
                    Console.WriteLine("ERROR: Incorrect Header Flags");
                    return(STATUS_ERROR_INCORRECT_FLAGS);
                }
            }
            else if (npd.getVersion() == 2L)
            {
                if ((data.getFlags() & 0x7effffe0L) != 0L)
                {
                    Console.WriteLine("ERROR: Incorrect Header Flags");
                    return(STATUS_ERROR_INCORRECT_FLAGS);
                }
            }
            else if ((npd.getVersion() == 3L) || (npd.getVersion() == 4L))
            {
                if ((data.getFlags() & 0x7effffc0L) != 0L)
                {
                    Console.WriteLine("ERROR: Incorrect Header Flags");
                    return(STATUS_ERROR_INCORRECT_FLAGS);
                }
            }
            else
            {
                Console.WriteLine("ERROR: Unsupported EDAT version (need keys)");
                return(STATUS_ERROR_INCORRECT_VERSION);
            }
            if (npd.getVersion() == 4L)
            {
            }
            i.Read(buffer, 0, buffer.Length);
            i.Read(buffer3, 0, buffer3.Length);
            Console.WriteLine("Checking header hash:");
            AppLoader loader   = new AppLoader();
            int       hashFlag = ((data.getFlags() & FLAG_KEYENCRYPTED) == 0L) ? 2 : 0x10000002;

            if ((data.getFlags() & FLAG_DEBUG) != 0L)
            {
                hashFlag |= 0x1000000;
            }
            if (!loader.doAll(hashFlag, 1, buffer, 0, o, 0, buffer.Length, new byte[0x10], new byte[0x10], rifKey, buffer3, 0))
            {
                Console.WriteLine("Error verifying header. Is rifKey valid?.");
                return(STATUS_ERROR_HEADERCHECK);
            }
            Console.WriteLine("Checking metadata hash:");
            loader = new AppLoader();
            loader.doInit(hashFlag, 1, new byte[0x10], new byte[0x10], rifKey);
            int num3 = ((data.getFlags() & FLAG_COMPRESSED) != 0L) ? 0x20 : 0x10;
            int num4 = (int)(((data.getFileLen() + data.getBlockSize()) - 11) / data.getBlockSize());
            int num5 = 0;
            int num6 = 0x100;

            for (long j = num3 * num4; j > 0L; j -= num8)
            {
                num8 = (HEADER_MAX_BLOCKSIZE > j) ? ((int)j) : HEADER_MAX_BLOCKSIZE;
                i.Seek((long)(num6 + num5), SeekOrigin.Begin);
                byte[] buffer4 = new byte[num8];
                o = new byte[num8];
                i.Read(buffer4, 0, buffer4.Length);
                loader.doUpdate(buffer4, 0, o, 0, num8);
                num5 += num8;
            }
            if (!loader.doFinal(buffer, 0x90))
            {
                Console.WriteLine("Error verifying metadatasection. Data tampered");
                return(STATUS_ERROR_HEADERCHECK);
            }
            return(STATUS_OK);
        }
Esempio n. 27
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);
        }
Esempio n. 28
0
        private byte[] writeValidNPD(String filename, byte[] devKLic, NPD[] npdPtr, FileStream fin, byte[] contentID, byte[] flags, byte[] version, byte[] type)
        {
            byte[] npd = new byte[0x80];
            //NPD Magic
            //ConversionUtils.arraycopy(npd, 0, result.magic, 0, 4);
            npd[0] = 0x4E;
            npd[1] = 0x50;
            npd[2] = 0x44;
            npd[3] = 0x00;
            //Version 3
            //result.version = ConversionUtils.be32(npd, 4);
            npd[4] = 0x00;
            npd[5] = 0x00;
            npd[6] = 0x00;
            npd[7] = version[0];
            //License 2 ref 3 klic /* 1 network, 2 local, 3 free */
            //result.license = ConversionUtils.be32(npd, 8);
            npd[8]  = 0x00;
            npd[9]  = 0x00;
            npd[10] = 0x00;
            npd[11] = 0x03;


            //Type /* 1 exec, 21 update */
            //result.type = ConversionUtils.be32(npd, 0xC);
            npd[12] = 0x00;
            npd[13] = 0x00;
            npd[14] = 0x00;
            npd[15] = type[0];

            //No Idea where I get the content_id
            //ConversionUtils.arraycopy(npd, 0x10, result.content_id, 0, 0x30
            for (int i = 0; i < 0x30; i++)
            {
                npd[0x10 + i] = contentID[i];
            }



            //Used to create IV
            //ConversionUtils.arraycopy(npd, 0x40, result.digest, 0, 0x10);
            byte[] iv = ConversionUtils.charsToByte(("FixedLicenseEDAT").ToCharArray());
            ConversionUtils.arraycopy(iv, 0, npd, 0x40, 0x10);

            //I guess it's a full file hash
            //ConversionUtils.arraycopy(npd, 0x50, result.titleHash, 0, 0x10);
            byte[] hash = createNPDHash1(filename, npd);
            ConversionUtils.arraycopy(hash, 0x00, npd, 0x50, 0x10);


            //Used to create Blockkey
            //ConversionUtils.arraycopy(npd, 0x60, result.devHash, 0, 0x10);
            byte[] devHash = createNPDHash2(devKLic, npd);
            ConversionUtils.arraycopy(devHash, 0, npd, 0x60, 0x10);

            //NPD EOF?!?!?!
            //result.unknown3 = ConversionUtils.be64(npd, 0x70);
            //result.unknown4 = ConversionUtils.be64(npd, 0x78);
            for (int i = 0; i < 16; i++)
            {
                npd[0x70 + i] = 0x00;
            }

            npdPtr[0] = NPD.createNPD(npd);
            return(npd);
        }
Esempio n. 29
0
 private byte[] calculateBlockKey(int blk, NPD npd)
 {
     byte[] src = (npd.getVersion() <= 1L) ? new byte[0x10] : npd.getDevHash();
     byte[] dest = new byte[0x10];
     ConversionUtils.arraycopy(src, 0, dest, 0L, 12);
     dest[12] = (byte) ((blk >> 0x18) & 0xff);
     dest[13] = (byte) ((blk >> 0x10) & 0xff);
     dest[14] = (byte) ((blk >> 8) & 0xff);
     dest[15] = (byte) (blk & 0xff);
     return dest;
 }
Esempio n. 30
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;
 }