forked from EstebanKubata/playfair
-
Notifications
You must be signed in to change notification settings - Fork 8
/
playfair.c
135 lines (113 loc) · 6.61 KB
/
playfair.c
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "playfair.h"
#define MODES 4
#define MODE_POSITON 14
#define TYPE_POSITION 5
#define SEQ_POSITION 6
#define SETUP_MESSAGE_TYPE 1
#define DECRYPT_MESSAGE_TYPE 2
#define SETUP1_MESSAGE_SEQ 1
#define SETUP2_MESSAGE_SEQ 3
#define SETUP1_RESPONSE_LENGTH 142
#define SETUP2_RESPONSE_LENGTH 32
#define SETUP2_RESPONSE_SUFFIX_LENGTH 20
// These are pre-computed. We use the same key material each time, so the first message we send depends only on the mode-byte in the initial message
char reply_message[MODES][SETUP1_RESPONSE_LENGTH] =
{
{0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x00,0x0f,0x9f,0x3f,0x9e,0x0a,0x25,0x21,0xdb,0xdf,0x31,0x2a,0xb2,0xbf,0xb2,0x9e,0x8d,0x23,0x2b,0x63,0x76,0xa8,0xc8,0x18,0x70,0x1d,0x22,0xae,0x93,0xd8,0x27,0x37,0xfe,0xaf,0x9d,0xb4,0xfd,0xf4,0x1c,0x2d,0xba,0x9d,0x1f,0x49,0xca,0xaa,0xbf,0x65,0x91,0xac,0x1f,0x7b,0xc6,0xf7,0xe0,0x66,0x3d,0x21,0xaf,0xe0,0x15,0x65,0x95,0x3e,0xab,0x81,0xf4,0x18,0xce,0xed,0x09,0x5a,0xdb,0x7c,0x3d,0x0e,0x25,0x49,0x09,0xa7,0x98,0x31,0xd4,0x9c,0x39,0x82,0x97,0x34,0x34,0xfa,0xcb,0x42,0xc6,0x3a,0x1c,0xd9,0x11,0xa6,0xfe,0x94,0x1a,0x8a,0x6d,0x4a,0x74,0x3b,0x46,0xc3,0xa7,0x64,0x9e,0x44,0xc7,0x89,0x55,0xe4,0x9d,0x81,0x55,0x00,0x95,0x49,0xc4,0xe2,0xf7,0xa3,0xf6,0xd5,0xba},
{0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x01,0xcf,0x32,0xa2,0x57,0x14,0xb2,0x52,0x4f,0x8a,0xa0,0xad,0x7a,0xf1,0x64,0xe3,0x7b,0xcf,0x44,0x24,0xe2,0x00,0x04,0x7e,0xfc,0x0a,0xd6,0x7a,0xfc,0xd9,0x5d,0xed,0x1c,0x27,0x30,0xbb,0x59,0x1b,0x96,0x2e,0xd6,0x3a,0x9c,0x4d,0xed,0x88,0xba,0x8f,0xc7,0x8d,0xe6,0x4d,0x91,0xcc,0xfd,0x5c,0x7b,0x56,0xda,0x88,0xe3,0x1f,0x5c,0xce,0xaf,0xc7,0x43,0x19,0x95,0xa0,0x16,0x65,0xa5,0x4e,0x19,0x39,0xd2,0x5b,0x94,0xdb,0x64,0xb9,0xe4,0x5d,0x8d,0x06,0x3e,0x1e,0x6a,0xf0,0x7e,0x96,0x56,0x16,0x2b,0x0e,0xfa,0x40,0x42,0x75,0xea,0x5a,0x44,0xd9,0x59,0x1c,0x72,0x56,0xb9,0xfb,0xe6,0x51,0x38,0x98,0xb8,0x02,0x27,0x72,0x19,0x88,0x57,0x16,0x50,0x94,0x2a,0xd9,0x46,0x68,0x8a},
{0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x02,0xc1,0x69,0xa3,0x52,0xee,0xed,0x35,0xb1,0x8c,0xdd,0x9c,0x58,0xd6,0x4f,0x16,0xc1,0x51,0x9a,0x89,0xeb,0x53,0x17,0xbd,0x0d,0x43,0x36,0xcd,0x68,0xf6,0x38,0xff,0x9d,0x01,0x6a,0x5b,0x52,0xb7,0xfa,0x92,0x16,0xb2,0xb6,0x54,0x82,0xc7,0x84,0x44,0x11,0x81,0x21,0xa2,0xc7,0xfe,0xd8,0x3d,0xb7,0x11,0x9e,0x91,0x82,0xaa,0xd7,0xd1,0x8c,0x70,0x63,0xe2,0xa4,0x57,0x55,0x59,0x10,0xaf,0x9e,0x0e,0xfc,0x76,0x34,0x7d,0x16,0x40,0x43,0x80,0x7f,0x58,0x1e,0xe4,0xfb,0xe4,0x2c,0xa9,0xde,0xdc,0x1b,0x5e,0xb2,0xa3,0xaa,0x3d,0x2e,0xcd,0x59,0xe7,0xee,0xe7,0x0b,0x36,0x29,0xf2,0x2a,0xfd,0x16,0x1d,0x87,0x73,0x53,0xdd,0xb9,0x9a,0xdc,0x8e,0x07,0x00,0x6e,0x56,0xf8,0x50,0xce},
{0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x03,0x90,0x01,0xe1,0x72,0x7e,0x0f,0x57,0xf9,0xf5,0x88,0x0d,0xb1,0x04,0xa6,0x25,0x7a,0x23,0xf5,0xcf,0xff,0x1a,0xbb,0xe1,0xe9,0x30,0x45,0x25,0x1a,0xfb,0x97,0xeb,0x9f,0xc0,0x01,0x1e,0xbe,0x0f,0x3a,0x81,0xdf,0x5b,0x69,0x1d,0x76,0xac,0xb2,0xf7,0xa5,0xc7,0x08,0xe3,0xd3,0x28,0xf5,0x6b,0xb3,0x9d,0xbd,0xe5,0xf2,0x9c,0x8a,0x17,0xf4,0x81,0x48,0x7e,0x3a,0xe8,0x63,0xc6,0x78,0x32,0x54,0x22,0xe6,0xf7,0x8e,0x16,0x6d,0x18,0xaa,0x7f,0xd6,0x36,0x25,0x8b,0xce,0x28,0x72,0x6f,0x66,0x1f,0x73,0x88,0x93,0xce,0x44,0x31,0x1e,0x4b,0xe6,0xc0,0x53,0x51,0x93,0xe5,0xef,0x72,0xe8,0x68,0x62,0x33,0x72,0x9c,0x22,0x7d,0x82,0x0c,0x99,0x94,0x45,0xd8,0x92,0x46,0xc8,0xc3,0x59}
};
char fp_header[] = {0x46, 0x50, 0x4c, 0x59, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14};
extern unsigned char default_sap[];
//dependencies from omg_hax
void generate_key_schedule(unsigned char* key_material, uint32_t key_schedule[11][4]);
void generate_session_key(unsigned char* oldSap, unsigned char* messageIn, unsigned char* sessionKey);
void cycle(unsigned char* block, uint32_t key_schedule[11][4]);
void z_xor(unsigned char* in, unsigned char* out, int blocks);
void x_xor(unsigned char* in, unsigned char* out, int blocks);
void print_block(char* msg, unsigned char* dword);
unsigned char* fairplay_setup(char* message, int length)
{
int type = message[TYPE_POSITION];
int seq = message[SEQ_POSITION];
if (type == SETUP_MESSAGE_TYPE)
{
unsigned char* response;
if (seq == SETUP1_MESSAGE_SEQ)
{
int mode = message[MODE_POSITON];
char *reply = reply_message[mode];
response = malloc(SETUP1_RESPONSE_LENGTH);
if (response != NULL)
{
memcpy(response, reply, SETUP1_RESPONSE_LENGTH);
}
}
else if (seq == SETUP2_MESSAGE_SEQ)
{
int header_size = sizeof(fp_header);
response = malloc(SETUP2_RESPONSE_LENGTH);
if (response != NULL)
{
memcpy(response, &fp_header, header_size);
memcpy(
&response[header_size],
&message[length - SETUP2_RESPONSE_SUFFIX_LENGTH],
SETUP2_RESPONSE_SUFFIX_LENGTH
);
}
}
return response;
}
else
{
return NULL;
}
}
unsigned char* fairplay_decrypt(char* message3, unsigned char* cipherText)
{
int messageType = message3[TYPE_POSITION];
int cipherType = cipherText[TYPE_POSITION];
int messageSeq = message3[SEQ_POSITION];
fprintf(stderr, "Decrypting: messageType=%i, messageSeq=%i, cipherType=%i\n", messageType, messageSeq, cipherType);
print_block("message3: ", &message3[0x00]);
print_block("message3: ", &message3[0x10]);
print_block("message3: ", &message3[0x20]);
print_block("message3: ", &message3[0x30]);
print_block("message3: ", &message3[0x40]);
print_block("message3: ", &message3[0x50]);
print_block("message3: ", &message3[0x60]);
print_block("message3: ", &message3[0x70]);
print_block("message3: ", &message3[0x80]);
print_block("message3: ", &message3[0x90]);
print_block("message3: ", &message3[0xA0]);
print_block("cipherText: ", &cipherText[0x00]);
print_block("cipherText: ", &cipherText[0x10]);
print_block("cipherText: ", &cipherText[0x20]);
print_block("cipherText: ", &cipherText[0x30]);
print_block("cipherText: ", &cipherText[0x40]);
if (messageType != SETUP_MESSAGE_TYPE || messageSeq != SETUP2_MESSAGE_SEQ ||
cipherType != DECRYPT_MESSAGE_TYPE)
{
return NULL;
}
unsigned char* chunk1 = &cipherText[16];
unsigned char* chunk2 = &cipherText[56];
int i;
unsigned char blockIn[16];
unsigned char* keyOut = malloc(16);
unsigned char sapKey[16];
uint32_t key_schedule[11][4];
generate_session_key(default_sap, (unsigned char*)message3, sapKey);
generate_key_schedule(sapKey, key_schedule);
z_xor(chunk2, blockIn, 1);
cycle(blockIn, key_schedule);
for (i = 0; i < 16; i++)
{
keyOut[i] = blockIn[i] ^ chunk1[i];
}
x_xor(keyOut, keyOut, 1);
z_xor(keyOut, keyOut, 1);
return keyOut;
}