forked from silicontrip/SkyReader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
crypt.cpp
108 lines (88 loc) · 3.39 KB
/
crypt.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "crypt.h"
/*
data encryption
Every block from 0x08 onward (with the exception of the access control blocks) is encrypted using a key unique to that block.
The algorithm is 128-bit AES, ECB mode and zero-byte padding. As that's a symmetric key algorithm, the same key is used to
both encrypt and decrypt.
The key itself is the MD5 hash of the following 0x56 bytes:
<first 0x20 bytes of sector 0> <1-byte block index> <0x35-byte constant>
*/
int Crypt::IsAccessControlBlock(unsigned int blockIndex)
{
return (((blockIndex % 4) != 3) ? 0 : 1);
}
int Crypt::ShouldEncryptBlock(unsigned int blockIndex)
{
if ((blockIndex >= 8) && (IsAccessControlBlock(blockIndex) == 0))
{
return 1;
}
return 0;
}
void Crypt::ComputeMD5(unsigned char digest[16], void const* bytesIn, unsigned int inputLen)
{
MD5 md5;
MD5Open(&md5);
MD5Digest(&md5, bytesIn, inputLen);
MD5Close(&md5, digest);
}
/* Compute key used by AES
The key is the MD5 hash of the following 0x56 bytes:
<first 0x20 bytes of sector 0> <1-byte block index> <0x35-byte constant>
*/
void Crypt::ComputeEncryptionKey(unsigned char keyOut[16], unsigned char const* tagBlocks0and1, unsigned int blockIndex)
{
// <0x35-byte constant>
unsigned char hashConst[] = {
0x20, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, // Copyright (C) 2
0x30, 0x31, 0x30, 0x20, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x2E, 0x20, // 010 Activision.
0x41, 0x6C, 0x6C, 0x20, 0x52, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x52, 0x65, 0x73, 0x65, 0x72, // All Rights Reser
0x76, 0x65, 0x64, 0x2E, 0x20}; // ved.
const int hashLen = 0x56;
unsigned char hashBuf[hashLen];
unsigned char *numPtr = hashBuf;
memcpy(numPtr, tagBlocks0and1, 0x20);
numPtr += 0x20;
numPtr[0] = (unsigned char)blockIndex;
numPtr += 1;
memcpy(numPtr, hashConst, 0x35);
//fprinthex(stdout,hashBuf, 0x56);
ComputeMD5(keyOut, hashBuf, 0x56);
}
#define KEYBITS 128
void Crypt::EncryptAES128ECB(unsigned char * key, unsigned char const* plainTextIn, unsigned char* cipherTextOut)
{
unsigned long rk[RKLENGTH(KEYBITS)];
int nrounds;
nrounds = rijndaelSetupEncrypt(rk, key, KEYBITS);
rijndaelEncrypt(rk, nrounds, plainTextIn, cipherTextOut);
}
void Crypt::DecryptAES128ECB(unsigned char * key, unsigned char const* cipherTextIn, unsigned char* plainTextOut)
{
unsigned long rk[RKLENGTH(KEYBITS)];
int nrounds;
nrounds = rijndaelSetupDecrypt(rk, key, KEYBITS);
rijndaelDecrypt(rk, nrounds, cipherTextIn, plainTextOut);
}
void Crypt::EncryptTagBlock(unsigned char* blockData, unsigned int blockIndex, unsigned char const* tagBlocks0and1)
{
if (ShouldEncryptBlock(blockIndex) != 0)
{
unsigned char cipherText[16];
unsigned char aesKey[16];
ComputeEncryptionKey(aesKey, tagBlocks0and1, blockIndex);
EncryptAES128ECB(aesKey, blockData, cipherText);
memcpy(blockData, cipherText, 16);
}
}
void Crypt::DecryptTagBlock(unsigned char* blockData, unsigned int blockIndex, unsigned char const* tagBlocks0and1)
{
if (ShouldEncryptBlock(blockIndex) != 0)
{
unsigned char plainText[16];
unsigned char aesKey[16];
ComputeEncryptionKey(aesKey, tagBlocks0and1, blockIndex);
DecryptAES128ECB(aesKey, blockData, plainText);
memcpy(blockData, plainText, 16);
}
}