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/hash.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
* hash.c - Hashing routines using sceChnnlsv
7
*
8
* Copyright (c) 2005 Jim Paris <[email protected]>
9
* Coypright (c) 2005 psp123
10
*
11
* $Id: hash.c 1560 2005-12-10 01:16:32Z jim $
12
*/
13
14
#include "hash.h"
15
#include "psf.h"
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <malloc.h>
20
#include <pspchnnlsv.h>
21
#include "kernelcall/kernelcall.h"
22
23
static inline int align16(unsigned int v)
24
{
25
return ((v + 0xF) >> 4) << 4;
26
}
27
28
/* Update the hashes in the param.sfo data, using
29
the given file hash, and by computing the param.sfo hashes.
30
filehash must be a multiple of 16 bytes, and is reused to
31
store other hashes. The filename is e.g. "DATA.BIN". */
32
int update_hashes(unsigned char *data,
33
int len,
34
const char *filename,
35
unsigned char *filehash,
36
int encryptmode)
37
{
38
int alignedLen = align16(len);
39
unsigned char *datafile, *savedata_params;
40
int listLen, paramsLen;
41
int ret;
42
43
/* Locate SAVEDATA_PARAM section in the param.sfo. */
44
if ((ret = find_psf_section("SAVEDATA_PARAMS", data, 0x1330,
45
&savedata_params, &paramsLen)) < 0) {
46
return ret - 100;
47
}
48
49
/* Locate the pointer for this DATA.BIN equivalent */
50
if ((ret = find_psf_section("SAVEDATA_FILE_LIST", data, 0x1330,
51
&datafile, &listLen)) < 0) {
52
return ret - 200;
53
}
54
55
if ((ret = find_psf_datafile(filename, datafile,
56
listLen, &datafile)) < 0) {
57
return ret - 300;
58
}
59
60
/* Check minimum sizes based on where we want to write */
61
if ((listLen < 0x20) || (paramsLen < 0x80)) {
62
return -1;
63
}
64
65
/* Clear params and insert file hash */
66
memset(savedata_params, 0, paramsLen);
67
memcpy(datafile + 0x0D, filehash, 0x10);
68
69
/* Compute 11D0 hash over entire file */
70
if ((ret = build_hash(filehash, data, len, alignedLen,
71
(encryptmode & 2) ? 4 : 2, NULL)) < 0) { // Not sure about "2"
72
return ret - 400;
73
}
74
75
/* Copy 11D0 hash to param.sfo and set flag indicating it's there */
76
memcpy(savedata_params + 0x20, filehash, 0x10);
77
*savedata_params |= 0x01;
78
79
/* If new encryption mode, compute and insert the 1220 hash. */
80
if (encryptmode & 2) {
81
82
/* Enable the hash bit first */
83
*savedata_params |= 0x20;
84
85
if ((ret = build_hash(filehash, data, len, alignedLen,
86
3, 0)) < 0) {
87
return ret - 500;
88
}
89
memcpy(savedata_params + 0x70, filehash, 0x10);
90
}
91
92
/* Compute and insert the 11C0 hash. */
93
if ((ret = build_hash(filehash, data, len, alignedLen, 1, 0)) < 0) {
94
return ret - 600;
95
}
96
memcpy(savedata_params + 0x10, filehash, 0x10);
97
98
/* All done. */
99
return 0;
100
}
101
102
/* Build a single hash using the given data and mode.
103
data and alignedLen must be multiples of 0x10.
104
cryptkey is NULL for savedata. */
105
int build_hash(unsigned char *output,
106
unsigned char *data,
107
unsigned int len,
108
unsigned int alignedLen,
109
int mode,
110
unsigned char *cryptkey)
111
{
112
pspChnnlsvContext1 ctx1;
113
114
/* Set up buffers */
115
memset(&ctx1, 0, sizeof(pspChnnlsvContext1));
116
memset(output, 0, 0x10);
117
memset(data + len, 0, alignedLen - len);
118
119
/* Perform the magic */
120
if (sceChnnlsv_E7833020_(&ctx1, mode & 0xFF) < 0)
121
return -1;
122
if (sceChnnlsv_F21A1FCA_(&ctx1, data, alignedLen) < 0)
123
return -2;
124
if (sceChnnlsv_C4C494F8_(&ctx1, output, cryptkey) < 0)
125
return -3;
126
127
/* All done. */
128
return 0;
129
}
130
131