/* This file is part of jpcsp. Jpcsp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jpcsp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.crypto; public class DRM { private static AMCTRL amctrl; private byte[] iv = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; public DRM() { amctrl = new AMCTRL(); } /* * sceNpDrm - npdrm.prx */ public byte[] hleNpDrmGetFixedKey(byte[] hash, byte[] 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. byte[] encKey = new byte[0x10]; if ((mode & 0x1) == 0x1) { for (int i = 0; i < 0x10; i++) { encKey[i] = (byte) (KeyVault.drmEncKey1[i] & 0xFF); } } else if ((mode & 0x2) == 0x2) { for (int i = 0; i < 0x10; i++) { encKey[i] = (byte) (KeyVault.drmEncKey2[i] & 0xFF); } } else if ((mode & 0x3) == 0x3) { for (int i = 0; i < 0x10; i++) { encKey[i] = (byte) (KeyVault.drmEncKey3[i] & 0xFF); } } else { return null; } // Get the fixed key. byte[] fixedKey = new byte[0x10]; for (int i = 0; i < 0x10; i++) { fixedKey[i] = (byte) (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); } public byte[] GetKeyFromRif(byte[] rifBuf, byte[] actdatBuf, byte[] openPSID) { AES128 aes = new AES128("AES/ECB/NoPadding"); byte[] rifIndex = new byte[0x10]; byte[] rifDatKey = new byte[0x10]; byte[] encRifIndex = new byte[0x10]; byte[] encRifDatKey = new byte[0x10]; byte[] rifKey = new byte[KeyVault.drmRifKey.length]; for (int i = 0; i < KeyVault.drmRifKey.length; i++) { rifKey[i] = (byte) (KeyVault.drmRifKey[i] & 0xFF); } System.arraycopy(rifBuf, 0x40, encRifIndex, 0x0, 0x10); System.arraycopy(rifBuf, 0x50, encRifDatKey, 0x0, 0x10); rifIndex = aes.decrypt(encRifIndex, rifKey, iv); long index = rifIndex[0xF]; if (index < 0x80) { byte[] actDat = DecryptActdat(actdatBuf, openPSID); byte[] datKey = new byte[0x10]; System.arraycopy(actDat, (int) index * 16, datKey, 0, 0x10); rifDatKey = aes.decrypt(encRifDatKey, datKey, iv); } return rifDatKey; } public byte[] DecryptActdat(byte[] actdatBuf, byte[] openPSID) { AES128 aes = new AES128("AES/ECB/NoPadding"); byte[] actdat = new byte[0x800]; byte[] consoleKey = GetConsoleKey(openPSID); System.arraycopy(actdatBuf, 0x10, actdat, 0x0, actdat.length - 0x10); return aes.decrypt(actdat, consoleKey, iv); } public byte[] GetConsoleKey(byte[] openPSID) { AES128 aes = new AES128("AES/ECB/NoPadding"); byte[] actdatKey = new byte[KeyVault.drmActdatKey.length]; for (int i = 0; i < KeyVault.drmActdatKey.length; i++) { actdatKey[i] = (byte) (KeyVault.drmActdatKey[i] & 0xFF); } return aes.encrypt(openPSID, actdatKey, iv); } }