Пример #1
0
        public virtual sbyte[] GetKeyFromRif(sbyte[] rifBuf, sbyte[] actdatBuf, sbyte[] openPSID)
        {
            AES128 aes = new AES128("AES/ECB/NoPadding");

            sbyte[] rifIndex     = new sbyte[0x10];
            sbyte[] rifDatKey    = new sbyte[0x10];
            sbyte[] encRifIndex  = new sbyte[0x10];
            sbyte[] encRifDatKey = new sbyte[0x10];

            sbyte[] rifKey = new sbyte[KeyVault.drmRifKey.Length];
            for (int i = 0; i < KeyVault.drmRifKey.Length; i++)
            {
                rifKey[i] = unchecked ((sbyte)(KeyVault.drmRifKey[i] & 0xFF));
            }

            Array.Copy(rifBuf, 0x40, encRifIndex, 0x0, 0x10);
            Array.Copy(rifBuf, 0x50, encRifDatKey, 0x0, 0x10);

            rifIndex = aes.decrypt(encRifIndex, rifKey, iv);

            long index = rifIndex[0xF];

            if (index < 0x80)
            {
                sbyte[] actDat = DecryptActdat(actdatBuf, openPSID);
                sbyte[] datKey = new sbyte[0x10];
                Array.Copy(actDat, (int)index * 16, datKey, 0, 0x10);
                rifDatKey = aes.decrypt(encRifDatKey, datKey, iv);
            }

            return(rifDatKey);
        }
Пример #2
0
        // Encrypt with AESCBC128 using keys from table.
        private int executeKIRKCmd5(ByteBuffer @out, ByteBuffer @in, int size)
        {
            // Return an error if the crypto engine hasn't been initialized.
            if (!CryptoEngine.CryptoEngineStatus)
            {
                return(PSP_KIRK_NOT_INIT);
            }

            int outPosition = @out.position();

            // Read in the CMD4 format header.
            AES128_CBC_Header header = new AES128_CBC_Header(@in);

            if (header.mode != PSP_KIRK_CMD_MODE_ENCRYPT_CBC)
            {
                return(PSP_KIRK_INVALID_MODE);                // Only valid for mode ENCRYPT_CBC.
            }

            if (header.dataSize == 0)
            {
                return(PSP_KIRK_DATA_SIZE_IS_ZERO);
            }

            sbyte[] key = null;
            if (header.keySeed == 0x100)
            {
                key = priv_iv;
            }
            else
            {
                return(PSP_KIRK_INVALID_SIZE);                // Dummy.
            }

            sbyte[] encKey = new sbyte[16];
            for (int i = 0; i < encKey.Length; i++)
            {
                encKey[i] = (sbyte)key[i];
            }

            AES128 aes = new AES128("AES/CBC/NoPadding");

            sbyte[] inBuf = new sbyte[header.dataSize];
            @in.get(inBuf, 0, header.dataSize);
            sbyte[] outBuf = aes.encrypt(inBuf, encKey, priv_iv);

            @out.position(outPosition);
            // The header is kept in the output and the header.mode is even updated from
            // PSP_KIRK_CMD_MODE_ENCRYPT_CBC to PSP_KIRK_CMD_MODE_DECRYPT_CBC.
            @out.putInt(PSP_KIRK_CMD_MODE_DECRYPT_CBC);
            @out.putInt(header.unk1);
            @out.putInt(header.unk2);
            @out.putInt(header.keySeed);
            @out.putInt(header.dataSize);
            @out.put(outBuf);
            @in.clear();

            return(0);
        }
Пример #3
0
        public virtual sbyte[] DecryptActdat(sbyte[] actdatBuf, sbyte[] openPSID)
        {
            AES128 aes = new AES128("AES/ECB/NoPadding");

            sbyte[] actdat     = new sbyte[0x800];
            sbyte[] consoleKey = GetConsoleKey(openPSID);
            Array.Copy(actdatBuf, 0x10, actdat, 0x0, actdat.Length - 0x10);

            return(aes.decrypt(actdat, consoleKey, iv));
        }
Пример #4
0
        public virtual sbyte[] GetConsoleKey(sbyte[] openPSID)
        {
            AES128 aes = new AES128("AES/ECB/NoPadding");

            sbyte[] actdatKey = new sbyte[KeyVault.drmActdatKey.Length];
            for (int i = 0; i < KeyVault.drmActdatKey.Length; i++)
            {
                actdatKey[i] = unchecked ((sbyte)(KeyVault.drmActdatKey[i] & 0xFF));
            }

            return(aes.encrypt(openPSID, actdatKey, iv));
        }
Пример #5
0
        /*
         * sceNpDrm - npdrm.prx
         */
        public virtual sbyte[] hleNpDrmGetFixedKey(sbyte[] hash, sbyte[] data, int mode)
        {
            // Setup the crypto and keygen modes and initialize both context structs.
            AMCTRL.BBMac_Ctx bbctx = new AMCTRL.BBMac_Ctx();
            AES128           aes   = new AES128("AES/CBC/NoPadding");

            // Get the encryption key.
            sbyte[] encKey = new sbyte[0x10];
            if ((mode & 0x1) == 0x1)
            {
                for (int i = 0; i < 0x10; i++)
                {
                    encKey[i] = unchecked ((sbyte)(KeyVault.drmEncKey1[i] & 0xFF));
                }
            }
            else if ((mode & 0x2) == 0x2)
            {
                for (int i = 0; i < 0x10; i++)
                {
                    encKey[i] = unchecked ((sbyte)(KeyVault.drmEncKey2[i] & 0xFF));
                }
            }
            else if ((mode & 0x3) == 0x3)
            {
                for (int i = 0; i < 0x10; i++)
                {
                    encKey[i] = unchecked ((sbyte)(KeyVault.drmEncKey3[i] & 0xFF));
                }
            }
            else
            {
                return(null);
            }

            // Get the fixed key.
            sbyte[] fixedKey = new sbyte[0x10];
            for (int i = 0; i < 0x10; i++)
            {
                fixedKey[i] = unchecked ((sbyte)(KeyVault.drmFixedKey[i] & 0xFF));
            }

            // Call the BBMac functions.
            amctrl.hleDrmBBMacInit(bbctx, 1);
            amctrl.hleDrmBBMacUpdate(bbctx, data, data.Length);
            amctrl.hleDrmBBMacFinal(bbctx, hash, fixedKey);

            // Encrypt and return the hash.
            return(aes.encrypt(hash, encKey, iv));
        }
Пример #6
0
        // Decrypt with AESCBC128 using keys from table.
        private int executeKIRKCmd7(ByteBuffer @out, ByteBuffer @in, int size)
        {
            // Return an error if the crypto engine hasn't been initialized.
            if (!CryptoEngine.CryptoEngineStatus)
            {
                return(PSP_KIRK_NOT_INIT);
            }

            int outPosition = @out.position();

            // Read in the CMD7 format header.
            AES128_CBC_Header header = new AES128_CBC_Header(@in);

            if (header.mode != PSP_KIRK_CMD_MODE_DECRYPT_CBC)
            {
                return(PSP_KIRK_INVALID_MODE);                // Only valid for mode DECRYPT_CBC.
            }

            if (header.dataSize == 0)
            {
                return(PSP_KIRK_DATA_SIZE_IS_ZERO);
            }

            int[] key = getAESKeyFromSeed(header.keySeed);
            if (key == null)
            {
                return(PSP_KIRK_INVALID_SEED);
            }

            sbyte[] decKey = new sbyte[16];
            for (int i = 0; i < decKey.Length; i++)
            {
                decKey[i] = (sbyte)key[i];
            }

            AES128 aes = new AES128("AES/CBC/NoPadding");

            sbyte[] inBuf = new sbyte[header.dataSize];
            @in.get(inBuf, 0, header.dataSize);
            sbyte[] outBuf = aes.decrypt(inBuf, decKey, priv_iv);

            @out.position(outPosition);
            @out.put(outBuf);
            @in.clear();

            return(0);
        }
Пример #7
0
        // CMAC Sig check.
        private int executeKIRKCmd10(ByteBuffer @in, int size)
        {
            // Return an error if the crypto engine hasn't been initialized.
            if (!CryptoEngine.CryptoEngineStatus)
            {
                return(PSP_KIRK_NOT_INIT);
            }

            int headerOffset = @in.position();

            // Read in the CMD10 format header.
            AES128_CMAC_Header header = new AES128_CMAC_Header(@in);

            if ((header.mode != PSP_KIRK_CMD_MODE_CMD1) && (header.mode != PSP_KIRK_CMD_MODE_CMD2) && (header.mode != PSP_KIRK_CMD_MODE_CMD3))
            {
                return(PSP_KIRK_INVALID_MODE);                // Only valid for modes CMD1, CMD2 and CMD3.
            }

            if (header.dataSize == 0)
            {
                return(PSP_KIRK_DATA_SIZE_IS_ZERO);
            }

            AES128 aes = new AES128("AES/CBC/NoPadding");

            // Convert the AES CMD1 key into a real byte array.
            sbyte[] k = new sbyte[16];
            for (int i = 0; i < KeyVault.kirkAESKey0.Length; i++)
            {
                k[i] = (sbyte)KeyVault.kirkAESKey0[i];
            }

            // Decrypt and extract the new AES and CMAC keys from the top of the data.
            sbyte[] encryptedKeys = new sbyte[32];
            Array.Copy(header.AES128Key, 0, encryptedKeys, 0, 16);
            Array.Copy(header.CMACKey, 0, encryptedKeys, 16, 16);
            sbyte[] decryptedKeys = aes.decrypt(encryptedKeys, k, priv_iv);

            sbyte[] cmacHeaderHash = new sbyte[16];
            sbyte[] cmacDataHash   = new sbyte[16];

            sbyte[] cmacBuf = new sbyte[16];
            Array.Copy(decryptedKeys, 16, cmacBuf, 0, cmacBuf.Length);

            // Position the buffer at the CMAC keys offset.
            sbyte[] inBuf = new sbyte[@in.capacity() - 0x60 - headerOffset];
            Array.Copy(@in.array(), headerOffset + 0x60, inBuf, 0, inBuf.Length);

            // Calculate CMAC header hash.
            aes.doInitCMAC(cmacBuf);
            aes.doUpdateCMAC(inBuf, 0, 0x30);
            cmacHeaderHash = aes.doFinalCMAC();

            int blockSize = header.dataSize;

            if ((blockSize % 16) != 0)
            {
                blockSize += (16 - (blockSize % 16));
            }

            // Calculate CMAC data hash.
            aes.doInitCMAC(cmacBuf);
            aes.doUpdateCMAC(inBuf, 0, 0x30 + blockSize + header.dataOffset);
            cmacDataHash = aes.doFinalCMAC();

            for (int i = 0; i < cmacHeaderHash.Length; i++)
            {
                if (cmacHeaderHash[i] != header.CMACHeaderHash[i])
                {
                    return(PSP_KIRK_INVALID_HEADER_HASH);
                }
            }

            for (int i = 0; i < cmacDataHash.Length; i++)
            {
                if (cmacDataHash[i] != header.CMACDataHash[i])
                {
                    return(PSP_KIRK_INVALID_DATA_HASH);
                }
            }

            return(0);
        }
Пример #8
0
        /*
         * KIRK commands: main emulated crypto functions.
         */
        // Decrypt with AESCBC128-CMAC header and sig check.
        private int executeKIRKCmd1(ByteBuffer @out, ByteBuffer @in, int size)
        {
            // Return an error if the crypto engine hasn't been initialized.
            if (!CryptoEngine.CryptoEngineStatus)
            {
                return(PSP_KIRK_NOT_INIT);
            }

            int outPosition = @out.position();

            // Copy the input for sig check.
            ByteBuffer sigIn = @in.duplicate();

            sigIn.order(@in.order());             // duplicate() does not copy the order()

            int headerSize   = AES128_CMAC_Header.SIZEOF();
            int headerOffset = @in.position();

            // Read in the CMD1 format header.
            AES128_CMAC_Header header = new AES128_CMAC_Header(@in);

            if (header.mode != PSP_KIRK_CMD_MODE_CMD1)
            {
                return(PSP_KIRK_INVALID_MODE);                // Only valid for mode CMD1.
            }

            // Start AES128 processing.
            AES128 aes = new AES128("AES/CBC/NoPadding");

            // Convert the AES CMD1 key into a real byte array for SecretKeySpec.
            sbyte[] k = new sbyte[16];
            for (int i = 0; i < KeyVault.kirkAESKey0.Length; i++)
            {
                k[i] = (sbyte)KeyVault.kirkAESKey0[i];
            }

            // Decrypt and extract the new AES and CMAC keys from the top of the data.
            sbyte[] encryptedKeys = new sbyte[32];
            Array.Copy(header.AES128Key, 0, encryptedKeys, 0, 16);
            Array.Copy(header.CMACKey, 0, encryptedKeys, 16, 16);
            sbyte[] decryptedKeys = aes.decrypt(encryptedKeys, k, priv_iv);

            // Check for a valid signature.
            int sigCheck = executeKIRKCmd10(sigIn, size);

            if (decryptedKeys == null)
            {
                // Only return the sig check result if the keys are invalid
                // to allow skipping the CMAC comparision.
                // TODO: Trace why the CMAC hashes aren't matching.
                return(sigCheck);
            }

            // Get the newly decrypted AES key and proceed with the
            // full data decryption.
            sbyte[] aesBuf = new sbyte[16];
            Array.Copy(decryptedKeys, 0, aesBuf, 0, aesBuf.Length);

            // Extract the sealed override ELF params.
            int elfDataSize   = header.dataSize;
            int elfDataOffset = header.dataOffset;

            // Input buffer for decryption must have a Length aligned on 16 bytes
            int paddedElfDataSize = Utilities.alignUp(elfDataSize, 15);

            // Decrypt all the ELF data.
            sbyte[] inBuf = new sbyte[paddedElfDataSize];
            Array.Copy(@in.array(), elfDataOffset + headerOffset + headerSize, inBuf, 0, paddedElfDataSize);
            sbyte[] outBuf = aes.decrypt(inBuf, aesBuf, priv_iv);

            @out.position(outPosition);
            @out.put(outBuf);
            @out.limit(elfDataSize);
            @in.clear();

            return(0);
        }