CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Tools/SaveTool/decrypt.c
Views: 1401
/*1* PSP Software Development Kit - http://www.pspdev.org2* -----------------------------------------------------------------------3* Licensed under the BSD license, see LICENSE in PSPSDK root for details.4*5* decrypt.c - Decryption routines using sceChnnlsv6*7* Copyright (c) 2005 Jim Paris <[email protected]>8* Coypright (c) 2005 psp1239*10* $Id: decrypt.c 1562 2005-12-10 20:52:45Z jim $11*/1213#include "decrypt.h"14#include <stdio.h>15#include <stdlib.h>16#include <string.h>17#include <malloc.h>18#include <pspchnnlsv.h>19#include "kernelcall/kernelcall.h"2021unsigned int align16(unsigned int v)22{23return ((v + 0xF) >> 4) << 4;24}2526/* Read, decrypt, and write a savedata file. See main.c for example usage. */27int decrypt_file(const char *decrypted_filename,28const char *encrypted_filename,29const unsigned char *gamekey,30const int mainSdkVersion)31{32FILE *in, *out;33int len, aligned_len;34unsigned char *data, *cryptkey;35int retval;3637/* Open file and get size */3839if ((in = fopen(encrypted_filename, "r")) == NULL) {40retval = -1;41goto out;42}4344fseek(in, 0, SEEK_END);45len = ftell(in);46fseek(in, 0, SEEK_SET);4748if (len <= 0) {49retval = -2;50goto out1;51}5253/* Allocate buffers */5455aligned_len = align16(len);5657if ((data = (unsigned char *) memalign(0x10, aligned_len)) == NULL) {58retval = -3;59goto out1;60}6162if ((cryptkey = (unsigned char *) memalign(0x10, 0x10)) == NULL) {63retval = -4;64goto out2;65}6667/* Fill buffers */6869if (gamekey != NULL)70memcpy(cryptkey, gamekey, 0x10);7172memset(data + len, 0, aligned_len - len);73if (fread(data, 1, len, in) != len) {74retval = -5;75goto out3;76}7778/* Do the decryption */7980if ((retval = decrypt_data( gamekey ? (mainSdkVersion >= 4 ? 5 : 3) : 1, // 5 for sdk >= 4, else 381data, &len, &aligned_len,82gamekey ? cryptkey : NULL)) < 0) {83retval -= 100;84goto out3;85}8687/* Write the data out. decrypt_data has set len correctly. */8889if ((out = fopen(decrypted_filename, "w")) == NULL) {90retval = -6;91goto out3;92}9394if (fwrite(data, 1, len, out) != len) {95retval = -7;96goto out4;97}9899/* All done. Return file length. */100retval = len;101out4:102fclose(out);103out3:104free(cryptkey);105out2:106free(data);107out1:108fclose(in);109out:110return retval;111}112113/* Do the actual hardware decryption.114mode is 3 for saves with a cryptkey, or 1 otherwise115data, dataLen, and cryptkey must be multiples of 0x10.116cryptkey is NULL if mode == 1.117*/118int decrypt_data(unsigned int mode,119unsigned char *data,120int *dataLen,121int *alignedLen,122unsigned char *cryptkey)123{124pspChnnlsvContext1 ctx1;125pspChnnlsvContext2 ctx2;126127/* Need a 16-byte IV plus some data */128if (*alignedLen <= 0x10)129return -1;130*dataLen -= 0x10;131*alignedLen -= 0x10;132133/* Set up buffers */134memset(&ctx1, 0, sizeof(pspChnnlsvContext1));135memset(&ctx2, 0, sizeof(pspChnnlsvContext2));136137/* Perform the magic */138if (sceChnnlsv_E7833020_(&ctx1, mode) < 0)139return -2;140if (sceChnnlsv_ABFDFC8B_(&ctx2, mode, 2, data, cryptkey) < 0)141return -3;142if (sceChnnlsv_F21A1FCA_(&ctx1, data, 0x10) < 0)143return -4;144if (sceChnnlsv_F21A1FCA_(&ctx1, data + 0x10, *alignedLen) < 0)145return -5;146if (sceChnnlsv_850A7FA1_(&ctx2, data + 0x10, *alignedLen) < 0)147return -6;148149/* Verify that it decrypted correctly */150if (sceChnnlsv_21BE78B4_(&ctx2) < 0)151return -7;152153/* If desired, a new file hash from this PSP can be computed now:154if (sceChnnlsv_C4C494F8(ctx1, newhash, cryptkey) < 0)155return -8;156*/157158/* The decrypted data starts at data + 0x10, so shift it back. */159memmove(data, data + 0x10, *dataLen);160161/* All done */162return 0;163}164165166