CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Tools/SaveTool/decrypt.c
Views: 1401
1
/*
2
* PSP Software Development Kit - http://www.pspdev.org
3
* -----------------------------------------------------------------------
4
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
5
*
6
* decrypt.c - Decryption routines using sceChnnlsv
7
*
8
* Copyright (c) 2005 Jim Paris <[email protected]>
9
* Coypright (c) 2005 psp123
10
*
11
* $Id: decrypt.c 1562 2005-12-10 20:52:45Z jim $
12
*/
13
14
#include "decrypt.h"
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <string.h>
18
#include <malloc.h>
19
#include <pspchnnlsv.h>
20
#include "kernelcall/kernelcall.h"
21
22
unsigned int align16(unsigned int v)
23
{
24
return ((v + 0xF) >> 4) << 4;
25
}
26
27
/* Read, decrypt, and write a savedata file. See main.c for example usage. */
28
int decrypt_file(const char *decrypted_filename,
29
const char *encrypted_filename,
30
const unsigned char *gamekey,
31
const int mainSdkVersion)
32
{
33
FILE *in, *out;
34
int len, aligned_len;
35
unsigned char *data, *cryptkey;
36
int retval;
37
38
/* Open file and get size */
39
40
if ((in = fopen(encrypted_filename, "r")) == NULL) {
41
retval = -1;
42
goto out;
43
}
44
45
fseek(in, 0, SEEK_END);
46
len = ftell(in);
47
fseek(in, 0, SEEK_SET);
48
49
if (len <= 0) {
50
retval = -2;
51
goto out1;
52
}
53
54
/* Allocate buffers */
55
56
aligned_len = align16(len);
57
58
if ((data = (unsigned char *) memalign(0x10, aligned_len)) == NULL) {
59
retval = -3;
60
goto out1;
61
}
62
63
if ((cryptkey = (unsigned char *) memalign(0x10, 0x10)) == NULL) {
64
retval = -4;
65
goto out2;
66
}
67
68
/* Fill buffers */
69
70
if (gamekey != NULL)
71
memcpy(cryptkey, gamekey, 0x10);
72
73
memset(data + len, 0, aligned_len - len);
74
if (fread(data, 1, len, in) != len) {
75
retval = -5;
76
goto out3;
77
}
78
79
/* Do the decryption */
80
81
if ((retval = decrypt_data( gamekey ? (mainSdkVersion >= 4 ? 5 : 3) : 1, // 5 for sdk >= 4, else 3
82
data, &len, &aligned_len,
83
gamekey ? cryptkey : NULL)) < 0) {
84
retval -= 100;
85
goto out3;
86
}
87
88
/* Write the data out. decrypt_data has set len correctly. */
89
90
if ((out = fopen(decrypted_filename, "w")) == NULL) {
91
retval = -6;
92
goto out3;
93
}
94
95
if (fwrite(data, 1, len, out) != len) {
96
retval = -7;
97
goto out4;
98
}
99
100
/* All done. Return file length. */
101
retval = len;
102
out4:
103
fclose(out);
104
out3:
105
free(cryptkey);
106
out2:
107
free(data);
108
out1:
109
fclose(in);
110
out:
111
return retval;
112
}
113
114
/* Do the actual hardware decryption.
115
mode is 3 for saves with a cryptkey, or 1 otherwise
116
data, dataLen, and cryptkey must be multiples of 0x10.
117
cryptkey is NULL if mode == 1.
118
*/
119
int decrypt_data(unsigned int mode,
120
unsigned char *data,
121
int *dataLen,
122
int *alignedLen,
123
unsigned char *cryptkey)
124
{
125
pspChnnlsvContext1 ctx1;
126
pspChnnlsvContext2 ctx2;
127
128
/* Need a 16-byte IV plus some data */
129
if (*alignedLen <= 0x10)
130
return -1;
131
*dataLen -= 0x10;
132
*alignedLen -= 0x10;
133
134
/* Set up buffers */
135
memset(&ctx1, 0, sizeof(pspChnnlsvContext1));
136
memset(&ctx2, 0, sizeof(pspChnnlsvContext2));
137
138
/* Perform the magic */
139
if (sceChnnlsv_E7833020_(&ctx1, mode) < 0)
140
return -2;
141
if (sceChnnlsv_ABFDFC8B_(&ctx2, mode, 2, data, cryptkey) < 0)
142
return -3;
143
if (sceChnnlsv_F21A1FCA_(&ctx1, data, 0x10) < 0)
144
return -4;
145
if (sceChnnlsv_F21A1FCA_(&ctx1, data + 0x10, *alignedLen) < 0)
146
return -5;
147
if (sceChnnlsv_850A7FA1_(&ctx2, data + 0x10, *alignedLen) < 0)
148
return -6;
149
150
/* Verify that it decrypted correctly */
151
if (sceChnnlsv_21BE78B4_(&ctx2) < 0)
152
return -7;
153
154
/* If desired, a new file hash from this PSP can be computed now:
155
if (sceChnnlsv_C4C494F8(ctx1, newhash, cryptkey) < 0)
156
return -8;
157
*/
158
159
/* The decrypted data starts at data + 0x10, so shift it back. */
160
memmove(data, data + 0x10, *dataLen);
161
162
/* All done */
163
return 0;
164
}
165
166