Esempio n. 1
0
		public virtual int hleSdSetMember(SD_Ctx2 ctx, sbyte[] data, int Length)
		{
			if (Length == 0)
			{
				return 0;
			}
			if ((Length & 0xF) != 0)
			{
				return -1;
			}

			// Parse the data in 0x800 blocks first.
			int index = 0;
			if (Length >= 0x800)
			{
				for (index = 0; Length >= 0x800; index += 0x800)
				{
					cryptMember(ctx, data, index, 0x800);
					Length -= 0x800;
				}
			}

			// Finally parse the rest of the data.
			if (Length >= 0x10)
			{
				cryptMember(ctx, data, index, Length);
			}

			return 0;
		}
Esempio n. 2
0
		public virtual int hleSdCleanList(SD_Ctx2 ctx)
		{
			ctx.mode = 0;
			ctx.unk = 0;
			for (int i = 0; i < 0x10; i++)
			{
				ctx.buf[i] = 0;
			}
			return 0;
		}
Esempio n. 3
0
		public virtual sbyte[] DecryptSavedata(sbyte[] buf, int size, sbyte[] key)
		{
			// Initialize the context structs.
			int sdDecMode;
			SD_Ctx1 ctx1 = new SD_Ctx1();
			SD_Ctx2 ctx2 = new SD_Ctx2();

			// Setup the buffers.
			int alignedSize = (((size + 0xF) >> 4) << 4) - 0x10;
			sbyte[] decbuf = new sbyte[size - 0x10];
			sbyte[] tmpbuf = new sbyte[alignedSize];

			// Set the decryption mode.
			if (isNullKey(key))
			{
				sdDecMode = 1;
			}
			else
			{
				// After firmware version 2.7.1 the decryption mode used is 5.
				// Note: Due to a mislabel, 3 games from firmware 2.8.1 (Sonic Rivals, 
				// Star Trek: Tactical Assault and Brothers in Arms: D-Day) 
				// still use the decryption mode 3.
				if (Emulator.Instance.FirmwareVersion > 271 && !((State.discId.Equals("ULUS10195") || State.discId.Equals("ULES00622")) || (State.discId.Equals("ULUS10193") || State.discId.Equals("ULES00608")) || (State.discId.Equals("ULUS10150") || State.discId.Equals("ULES00623"))))
				{
					sdDecMode = 5;
				}
				else
				{
					sdDecMode = 3;
				}
			}

			// Perform the decryption.
			hleSdSetIndex(ctx1, sdDecMode);
			hleSdCreateList(ctx2, sdDecMode, 2, buf, key);
			hleSdRemoveValue(ctx1, buf, 0x10);

			Array.Copy(buf, 0x10, tmpbuf, 0, size - 0x10);
			hleSdRemoveValue(ctx1, tmpbuf, alignedSize);

			hleSdSetMember(ctx2, tmpbuf, alignedSize);

			// Clear context 2.
			hleSdCleanList(ctx2);

			// Copy back the data.
			Array.Copy(tmpbuf, 0, decbuf, 0, size - 0x10);

			return decbuf;
		}
Esempio n. 4
0
		public virtual sbyte[] EncryptSavedata(sbyte[] buf, int size, sbyte[] key)
		{
			// Initialize the context structs.
			int sdEncMode;
			SD_Ctx1 ctx1 = new SD_Ctx1();
			SD_Ctx2 ctx2 = new SD_Ctx2();

			// Setup the buffers.
			int alignedSize = ((size + 0xF) >> 4) << 4;
			sbyte[] tmpbuf1 = new sbyte[alignedSize + 0x10];
			sbyte[] tmpbuf2 = new sbyte[alignedSize];
			sbyte[] hash = new sbyte[0x10];

			// Copy the plain data to tmpbuf.
			Array.Copy(buf, 0, tmpbuf1, 0x10, size);

			// Set the encryption mode.
			if (isNullKey(key))
			{
				sdEncMode = 1;
			}
			else
			{
				// After firmware version 2.7.1 the encryption mode used is 5.
				// Note: Due to a mislabel, 3 games from firmware 2.8.1 (Sonic Rivals, 
				// Star Trek: Tactical Assault and Brothers in Arms: D-Day) 
				// still use the encryption mode 3.
				if (Emulator.Instance.FirmwareVersion > 271 && !((State.discId.Equals("ULUS10195") || State.discId.Equals("ULES00622")) || (State.discId.Equals("ULUS10193") || State.discId.Equals("ULES00608")) || (State.discId.Equals("ULUS10150") || State.discId.Equals("ULES00623"))))
				{
					sdEncMode = 5;
				}
				else
				{
					sdEncMode = 3;
				}
			}

			// Generate the encryption IV (first 0x10 bytes).
			hleSdCreateList(ctx2, sdEncMode, 1, tmpbuf1, key);
			hleSdSetIndex(ctx1, sdEncMode);
			hleSdRemoveValue(ctx1, tmpbuf1, 0x10);

			Array.Copy(tmpbuf1, 0x10, tmpbuf2, 0, alignedSize);
			hleSdSetMember(ctx2, tmpbuf2, alignedSize);

			// Clear extra bytes.
			for (int i = 0; i < (alignedSize - size); i++)
			{
				tmpbuf2[size + i] = 0;
			}

			// Encrypt the data.
			hleSdRemoveValue(ctx1, tmpbuf2, alignedSize);

			// Copy back the encrypted data + IV.
			for (int i = 0; i < (tmpbuf1.Length - 0x10); i++)
			{
				tmpbuf1[0x10 + i] = 0;
			}
			Array.Copy(tmpbuf2, 0, tmpbuf1, 0x10, alignedSize);
			Array.Copy(tmpbuf1, 0, buf, 0, buf.Length);

			// Clear context 2.
			hleSdCleanList(ctx2);

			// Generate a file hash for this data.
			hleSdGetLastIndex(ctx1, hash, key);

			return hash;
		}
Esempio n. 5
0
		public virtual int hleSdCreateList(SD_Ctx2 ctx, int encMode, int genMode, sbyte[] data, sbyte[] key)
		{
			// If the key is not a 16-byte key, return an error.
			if (!isNullKey(key) && key.Length < 0x10)
			{
				return -1;
			}

			// Set the mode and the unknown parameters.
			ctx.mode = encMode;
			ctx.unk = 0x1;

			// Key generator mode 0x1 (encryption): use an encrypted pseudo random number before XORing the data with the given key.
			if (genMode == 0x1)
			{
				sbyte[] header = new sbyte[0x24];
				sbyte[] seed = new sbyte[0x14];

				// Generate SHA-1 to act as seed for encryption.
				ByteBuffer bSeed = ByteBuffer.wrap(seed);
				kirk.hleUtilsBufferCopyWithRange(bSeed, 0x14, null, 0, KIRK.PSP_KIRK_CMD_PRNG);

				// Propagate SHA-1 in kirk header.
				Array.Copy(bSeed.array(), 0, header, 0, 0x14);
				Array.Copy(bSeed.array(), 0, header, 0x14, 0x10);
				header[0x20] = 0;
				header[0x21] = 0;
				header[0x22] = 0;
				header[0x23] = 0;

				// Encryption mode 0x1: encrypt with KIRK CMD4 and XOR with the given key.
				if (ctx.mode == 0x1)
				{
					ScrambleSD(header, 0x10, 0x4, 0x4, KIRK.PSP_KIRK_CMD_ENCRYPT);
					Array.Copy(header, 0x14, ctx.buf, 0, 0x10);
					Array.Copy(header, 0x14, data, 0, 0x10);
					// If the key is not null, XOR the hash with it.
					if (!isNullKey(key))
					{
						ctx.buf = xorKey(ctx.buf, 0, key, 0, 0x10);
					}
					return 0;
				}
				else if (ctx.mode == 0x2)
				{ // Encryption mode 0x2: encrypt with KIRK CMD5 and XOR with the given key.
					ScrambleSD(header, 0x10, 0x100, 0x4, KIRK.PSP_KIRK_CMD_ENCRYPT_FUSE);
					Array.Copy(header, 0x14, ctx.buf, 0, 0x10);
					Array.Copy(header, 0x14, data, 0, 0x10);
					// If the key is not null, XOR the hash with it.
					if (!isNullKey(key))
					{
						ctx.buf = xorKey(ctx.buf, 0, key, 0, 0x10);
					}
					return 0;
				}
				else if (ctx.mode == 0x3)
				{ // Encryption mode 0x3: XOR with SD keys, encrypt with KIRK CMD4 and XOR with the given key.
					header = xorHash(header, 0x14, KeyVault.sdHashKey3, 0, 0x10);
					ScrambleSD(header, 0x10, 0xE, 0x4, KIRK.PSP_KIRK_CMD_ENCRYPT);
					header = xorHash(header, 0x14, KeyVault.sdHashKey4, 0, 0x10);
					Array.Copy(header, 0x14, ctx.buf, 0, 0x10);
					Array.Copy(header, 0x14, data, 0, 0x10);
					// If the key is not null, XOR the hash with it.
					if (!isNullKey(key))
					{
						ctx.buf = xorKey(ctx.buf, 0, key, 0, 0x10);
					}
					return 0;
				}
				else if (ctx.mode == 0x4)
				{ // Encryption mode 0x4: XOR with SD keys, encrypt with KIRK CMD5 and XOR with the given key.
					header = xorHash(header, 0x14, KeyVault.sdHashKey3, 0, 0x10);
					ScrambleSD(header, 0x10, 0x100, 0x4, KIRK.PSP_KIRK_CMD_ENCRYPT_FUSE);
					header = xorHash(header, 0x14, KeyVault.sdHashKey4, 0, 0x10);
					Array.Copy(header, 0x14, ctx.buf, 0, 0x10);
					Array.Copy(header, 0x14, data, 0, 0x10);
					// If the key is not null, XOR the hash with it.
					if (!isNullKey(key))
					{
						ctx.buf = xorKey(ctx.buf, 0, key, 0, 0x10);
					}
					return 0;
				}
				else if (ctx.mode == 0x6)
				{ // Encryption mode 0x6: XOR with new SD keys, encrypt with KIRK CMD5 and XOR with the given key.
					header = xorHash(header, 0x14, KeyVault.sdHashKey6, 0, 0x10);
					ScrambleSD(header, 0x10, 0x100, 0x4, KIRK.PSP_KIRK_CMD_ENCRYPT_FUSE);
					header = xorHash(header, 0x14, KeyVault.sdHashKey7, 0, 0x10);
					Array.Copy(header, 0x14, ctx.buf, 0, 0x10);
					Array.Copy(header, 0x14, data, 0, 0x10);
					// If the key is not null, XOR the hash with it.
					if (!isNullKey(key))
					{
						ctx.buf = xorKey(ctx.buf, 0, key, 0, 0x10);
					}
					return 0;
				}
				else
				{ // Encryption mode 0x5: XOR with new SD keys, encrypt with KIRK CMD4 and XOR with the given key.
					header = xorHash(header, 0x14, KeyVault.sdHashKey6, 0, 0x10);
					ScrambleSD(header, 0x10, 0x12, 0x4, KIRK.PSP_KIRK_CMD_ENCRYPT);
					header = xorHash(header, 0x14, KeyVault.sdHashKey7, 0, 0x10);
					Array.Copy(header, 0x14, ctx.buf, 0, 0x10);
					Array.Copy(header, 0x14, data, 0, 0x10);
					// If the key is not null, XOR the hash with it.
					if (!isNullKey(key))
					{
						ctx.buf = xorKey(ctx.buf, 0, key, 0, 0x10);
					}
					return 0;
				}
			}
			else if (genMode == 0x2)
			{ // Key generator mode 0x02 (decryption): directly XOR the data with the given key.
				// Grab the data hash (first 16-bytes).
				Array.Copy(data, 0, ctx.buf, 0, 0x10);
				// If the key is not null, XOR the hash with it.
				if (!isNullKey(key))
				{
					ctx.buf = xorKey(ctx.buf, 0, key, 0, 0x10);
				}
				return 0;
			}
			else
			{
				// Invalid mode.
				return -1;
			}
		}
Esempio n. 6
0
		private void cryptMember(SD_Ctx2 ctx, sbyte[] data, int data_offset, int Length)
		{
			int finalSeed;
			sbyte[] dataBuf = new sbyte[Length + 0x14];
			sbyte[] keyBuf1 = new sbyte[0x10];
			sbyte[] keyBuf2 = new sbyte[0x10];
			sbyte[] hashBuf = new sbyte[0x10];

			// Copy the hash stored by hleSdCreateList.
			Array.Copy(ctx.buf, 0, dataBuf, 0x14, 0x10);

			if (ctx.mode == 0x1)
			{
				// Decryption mode 0x01: decrypt the hash directly with KIRK CMD7.
				ScrambleSD(dataBuf, 0x10, 0x4, 5, KIRK.PSP_KIRK_CMD_DECRYPT);
				finalSeed = 0x53;
			}
			else if (ctx.mode == 0x2)
			{
				// Decryption mode 0x02: decrypt the hash directly with KIRK CMD8.
				ScrambleSD(dataBuf, 0x10, 0x100, 5, KIRK.PSP_KIRK_CMD_DECRYPT_FUSE);
				finalSeed = 0x53;
			}
			else if (ctx.mode == 0x3)
			{
				// Decryption mode 0x03: XOR the hash with SD keys and decrypt with KIRK CMD7.
				dataBuf = xorHash(dataBuf, 0x14, KeyVault.sdHashKey4, 0, 0x10);
				ScrambleSD(dataBuf, 0x10, 0xE, 5, KIRK.PSP_KIRK_CMD_DECRYPT);
				dataBuf = xorHash(dataBuf, 0, KeyVault.sdHashKey3, 0, 0x10);
				finalSeed = 0x57;
			}
			else if (ctx.mode == 0x4)
			{
				// Decryption mode 0x04: XOR the hash with SD keys and decrypt with KIRK CMD8.
				dataBuf = xorHash(dataBuf, 0x14, KeyVault.sdHashKey4, 0, 0x10);
				ScrambleSD(dataBuf, 0x10, 0x100, 5, KIRK.PSP_KIRK_CMD_DECRYPT_FUSE);
				dataBuf = xorHash(dataBuf, 0, KeyVault.sdHashKey3, 0, 0x10);
				finalSeed = 0x57;
			}
			else if (ctx.mode == 0x6)
			{
				// Decryption mode 0x06: XOR the hash with new SD keys and decrypt with KIRK CMD8.
				dataBuf = xorHash(dataBuf, 0x14, KeyVault.sdHashKey7, 0, 0x10);
				ScrambleSD(dataBuf, 0x10, 0x100, 5, KIRK.PSP_KIRK_CMD_DECRYPT_FUSE);
				dataBuf = xorHash(dataBuf, 0, KeyVault.sdHashKey6, 0, 0x10);
				finalSeed = 0x64;
			}
			else
			{
				// Decryption mode 0x05: XOR the hash with new SD keys and decrypt with KIRK CMD7.
				dataBuf = xorHash(dataBuf, 0x14, KeyVault.sdHashKey7, 0, 0x10);
				ScrambleSD(dataBuf, 0x10, 0x12, 5, KIRK.PSP_KIRK_CMD_DECRYPT);
				dataBuf = xorHash(dataBuf, 0, KeyVault.sdHashKey6, 0, 0x10);
				finalSeed = 0x64;
			}

			// Store the calculated key.
			Array.Copy(dataBuf, 0, keyBuf2, 0, 0x10);

			// Apply extra padding if ctx.unk is not 1.
			if (ctx.unk != 0x1)
			{
				Array.Copy(keyBuf2, 0, keyBuf1, 0, 0xC);
				keyBuf1[0xC] = unchecked((sbyte)((ctx.unk - 1) & 0xFF));
				keyBuf1[0xD] = unchecked((sbyte)(((ctx.unk - 1) >> 8) & 0xFF));
				keyBuf1[0xE] = unchecked((sbyte)(((ctx.unk - 1) >> 16) & 0xFF));
				keyBuf1[0xF] = unchecked((sbyte)(((ctx.unk - 1) >> 24) & 0xFF));
			}

			// Copy the first 0xC bytes of the obtained key and replicate them
			// across a new list buffer. As a terminator, add the ctx1.seed parameter's
			// 4 bytes (endian swapped) to achieve a full numbered list.
			for (int i = 0x14; i < (Length + 0x14); i += 0x10)
			{
				Array.Copy(keyBuf2, 0, dataBuf, i, 0xC);
				dataBuf[i + 0xC] = unchecked((sbyte)(ctx.unk & 0xFF));
				dataBuf[i + 0xD] = unchecked((sbyte)((ctx.unk >> 8) & 0xFF));
				dataBuf[i + 0xE] = unchecked((sbyte)((ctx.unk >> 16) & 0xFF));
				dataBuf[i + 0xF] = unchecked((sbyte)((ctx.unk >> 24) & 0xFF));
				ctx.unk++;
			}

			// Copy the generated hash to hashBuf.
			Array.Copy(dataBuf, Length + 0x04, hashBuf, 0, 0x10);

			// Decrypt the hash with KIRK CMD7.
			ScrambleSD(dataBuf, Length, finalSeed, 5, KIRK.PSP_KIRK_CMD_DECRYPT);

			// XOR the first 16-bytes of data with the saved key to generate a new hash.
			dataBuf = xorKey(dataBuf, 0, keyBuf1, 0, 0x10);

			// Copy back the last hash from the list to the first keyBuf.
			Array.Copy(hashBuf, 0, keyBuf1, 0, 0x10);

			// Finally, XOR the full list with the given data.
			xorKey(data, data_offset, dataBuf, 0, Length);
		}