2
2
* QEMU Xbox EEPROM Generation (MCPX Version 1.0)
3
3
*
4
4
* Copyright (c) 2020 Mike Davis
5
+ * Copyright (c) 2024 Ryan Wendland
5
6
*
6
7
* This library is free software; you can redistribute it and/or
7
8
* modify it under the terms of the GNU Lesser General Public
17
18
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
19
*/
19
20
21
+ #include <stdint.h>
22
+ #include <stdio.h>
23
+ #include <string.h>
20
24
#include "eeprom_generation.h"
25
+ #include "util/sha1_rc4.h"
21
26
22
27
static uint32_t xbox_eeprom_crc (uint8_t * data , size_t len ) {
23
28
uint32_t high = 0 ;
@@ -32,44 +37,6 @@ static uint32_t xbox_eeprom_crc(uint8_t *data, size_t len) {
32
37
return ~(high + low );
33
38
}
34
39
35
- static void xbox_rc4_swap (RC4Context * ctx , int first , int second ) {
36
- uint8_t temp = ctx -> s [first ];
37
- ctx -> s [first ] = ctx -> s [second ];
38
- ctx -> s [second ] = temp ;
39
- }
40
-
41
- static void xbox_rc4_init (RC4Context * ctx , uint8_t * data , size_t len ) {
42
- for (int i = 0 ; i < 256 ; i ++ ) {
43
- ctx -> s [i ] = i ;
44
- }
45
- for (int i = 0 , j = 0 ; i < 256 ; i ++ ) {
46
- j = (j + ctx -> s [i ] + data [i % len ]) % 256 ;
47
- xbox_rc4_swap (ctx , i , j );
48
- }
49
- }
50
-
51
- static void xbox_rc4_crypt (RC4Context * ctx , uint8_t * data , size_t len ) {
52
- for (int i = 0 , j = 0 , k = 0 ; k < len ; k ++ ) {
53
- i = (i + 1 ) % 256 ;
54
- j = (j + ctx -> s [i ]) % 256 ;
55
- xbox_rc4_swap (ctx , i , j );
56
- data [k ] ^= ctx -> s [(ctx -> s [i ] + ctx -> s [j ]) % 256 ];
57
- }
58
- }
59
-
60
- static uint32_t xbox_sha1_rotate (uint32_t bits , uint32_t val ) {
61
- return (val << bits ) | (val >> (32 - bits ));
62
- }
63
-
64
- static void xbox_sha1_fill (SHA1Context * ctx ,
65
- uint32_t a , uint32_t b , uint32_t c , uint32_t d , uint32_t e ) {
66
- ctx -> intermediate [0 ] = a ;
67
- ctx -> intermediate [1 ] = b ;
68
- ctx -> intermediate [2 ] = c ;
69
- ctx -> intermediate [3 ] = d ;
70
- ctx -> intermediate [4 ] = e ;
71
- }
72
-
73
40
static void xbox_sha1_reset (SHA1Context * ctx , XboxEEPROMVersion ver , bool first ) {
74
41
ctx -> msg_blk_index = 0 ;
75
42
ctx -> computed = false;
@@ -79,127 +46,50 @@ static void xbox_sha1_reset(SHA1Context *ctx, XboxEEPROMVersion ver, bool first)
79
46
switch (ver ) {
80
47
case XBOX_EEPROM_VERSION_D :
81
48
if (first ) {
82
- xbox_sha1_fill (ctx , 0x85F9E51A , 0xE04613D2 ,
49
+ sha1_fill (ctx , 0x85F9E51A , 0xE04613D2 ,
83
50
0x6D86A50C , 0x77C32E3C , 0x4BD717A4 );
84
51
} else {
85
- xbox_sha1_fill (ctx , 0x5D7A9C6B , 0xE1922BEB ,
52
+ sha1_fill (ctx , 0x5D7A9C6B , 0xE1922BEB ,
86
53
0xB82CCDBC , 0x3137AB34 , 0x486B52B3 );
87
54
}
88
55
break ;
89
56
case XBOX_EEPROM_VERSION_R2 :
90
57
if (first ) {
91
- xbox_sha1_fill (ctx , 0x39B06E79 , 0xC9BD25E8 ,
58
+ sha1_fill (ctx , 0x39B06E79 , 0xC9BD25E8 ,
92
59
0xDBC6B498 , 0x40B4389D , 0x86BBD7ED );
93
60
} else {
94
- xbox_sha1_fill (ctx , 0x9B49BED3 , 0x84B430FC ,
61
+ sha1_fill (ctx , 0x9B49BED3 , 0x84B430FC ,
95
62
0x6B8749CD , 0xEBFE5FE5 , 0xD96E7393 );
96
63
}
97
64
break ;
98
65
case XBOX_EEPROM_VERSION_R3 :
99
66
if (first ) {
100
- xbox_sha1_fill (ctx , 0x8058763A , 0xF97D4E0E ,
67
+ sha1_fill (ctx , 0x8058763A , 0xF97D4E0E ,
101
68
0x865A9762 , 0x8A3D920D , 0x08995B2C );
102
69
} else {
103
- xbox_sha1_fill (ctx , 0x01075307 , 0xA2f1E037 ,
70
+ sha1_fill (ctx , 0x01075307 , 0xA2f1E037 ,
104
71
0x1186EEEA , 0x88DA9992 , 0x168A5609 );
105
72
}
106
73
break ;
107
74
default : // default to 1.0 version
108
75
if (first ) {
109
- xbox_sha1_fill (ctx , 0x72127625 , 0x336472B9 ,
76
+ sha1_fill (ctx , 0x72127625 , 0x336472B9 ,
110
77
0xBE609BEA , 0xF55E226B , 0x99958DAC );
111
78
} else {
112
- xbox_sha1_fill (ctx , 0x76441D41 , 0x4DE82659 ,
79
+ sha1_fill (ctx , 0x76441D41 , 0x4DE82659 ,
113
80
0x2E8EF85E , 0xB256FACA , 0xC4FE2DE8 );
114
81
}
115
82
}
116
83
}
117
84
118
- static void xbox_sha1_process (SHA1Context * ctx ) {
119
- const uint32_t k [] = { 0x5A827999 , 0x6ED9EBA1 , 0x8F1BBCDC , 0xCA62C1D6 };
120
- uint32_t w [80 ];
121
- uint32_t a = ctx -> intermediate [0 ];
122
- uint32_t b = ctx -> intermediate [1 ];
123
- uint32_t c = ctx -> intermediate [2 ];
124
- uint32_t d = ctx -> intermediate [3 ];
125
- uint32_t e = ctx -> intermediate [4 ];
126
-
127
- for (int i = 0 ; i < 16 ; i ++ ) {
128
- * (uint32_t * )& w [i ] = cpu_to_be32 (((uint32_t * )ctx -> msg_blk )[i ]);
129
- }
130
-
131
- for (int i = 16 ; i < 80 ; i ++ ) {
132
- w [i ] = xbox_sha1_rotate (1 , w [i - 3 ] ^ w [i - 8 ] ^ w [i - 14 ] ^ w [i - 16 ]);
133
- }
134
-
135
- for (int i = 0 ; i < 80 ; i ++ ) {
136
- uint32_t temp = xbox_sha1_rotate (5 , a ) + w [i ] + e ;
137
- switch (i / 20 ) {
138
- case 0 : temp += k [0 ] + ((b & c ) | ((~b ) & d )); break ;
139
- case 1 : temp += k [1 ] + (b ^ c ^ d ); break ;
140
- case 2 : temp += k [2 ] + ((b & c ) | (b & d ) | (c & d )); break ;
141
- case 3 : temp += k [3 ] + (b ^ c ^ d ); break ;
142
- }
143
- e = d ;
144
- d = c ;
145
- c = xbox_sha1_rotate (30 , b );
146
- b = a ;
147
- a = temp ;
148
- }
149
-
150
- ctx -> intermediate [0 ] += a ;
151
- ctx -> intermediate [1 ] += b ;
152
- ctx -> intermediate [2 ] += c ;
153
- ctx -> intermediate [3 ] += d ;
154
- ctx -> intermediate [4 ] += e ;
155
- ctx -> msg_blk_index = 0 ;
156
- }
157
-
158
- static void xbox_sha1_input (SHA1Context * ctx , uint8_t * data , size_t len ) {
159
- ctx -> length += len << 3 ;
160
- for (int i = 0 ; i < len ; i ++ ) {
161
- ctx -> msg_blk [ctx -> msg_blk_index ++ ] = data [i ];
162
- if (ctx -> msg_blk_index == 64 ) {
163
- xbox_sha1_process (ctx );
164
- }
165
- }
166
- }
167
-
168
- static void xbox_sha1_pad (SHA1Context * ctx ) {
169
- ctx -> msg_blk [ctx -> msg_blk_index ++ ] = 0x80 ;
170
- if (ctx -> msg_blk_index > 56 ) {
171
- while (ctx -> msg_blk_index < 64 ) {
172
- ctx -> msg_blk [ctx -> msg_blk_index ++ ] = 0 ;
173
- }
174
- xbox_sha1_process (ctx );
175
- }
176
- while (ctx -> msg_blk_index < 56 ) {
177
- ctx -> msg_blk [ctx -> msg_blk_index ++ ] = 0 ;
178
- }
179
- * (uint32_t * )& ctx -> msg_blk [56 ] = 0 ;
180
- * (uint32_t * )& ctx -> msg_blk [60 ] = cpu_to_be32 (ctx -> length );
181
- xbox_sha1_process (ctx );
182
- }
183
-
184
- static void xbox_sha1_result (SHA1Context * ctx , uint8_t * data ) {
185
- if (!ctx -> computed ) {
186
- xbox_sha1_pad (ctx );
187
- ctx -> length = 0 ;
188
- ctx -> computed = true;
189
- }
190
- for (int i = 0 ; i < 20 ; ++ i ) {
191
- data [i ] = ctx -> intermediate [i >> 2 ] >> 8 * (3 - (i & 3 ));
192
- }
193
- }
194
-
195
85
static void xbox_sha1_compute (SHA1Context * ctx , XboxEEPROMVersion ver ,
196
86
uint8_t * data , size_t len , uint8_t * hash ) {
197
87
xbox_sha1_reset (ctx , ver , true);
198
- xbox_sha1_input (ctx , data , len );
199
- xbox_sha1_result (ctx , ctx -> msg_blk );
88
+ sha1_input (ctx , data , len );
89
+ sha1_result (ctx , ctx -> msg_blk );
200
90
xbox_sha1_reset (ctx , ver , false);
201
- xbox_sha1_input (ctx , ctx -> msg_blk , 20 );
202
- xbox_sha1_result (ctx , hash );
91
+ sha1_input (ctx , ctx -> msg_blk , 20 );
92
+ sha1_result (ctx , hash );
203
93
}
204
94
205
95
bool xbox_eeprom_generate (const char * file , XboxEEPROMVersion ver ) {
@@ -237,8 +127,8 @@ bool xbox_eeprom_generate(const char *file, XboxEEPROMVersion ver) {
237
127
uint8_t seed [20 ];
238
128
xbox_sha1_compute (& sctx , ver , e .confounder , 0x1C , e .hash );
239
129
xbox_sha1_compute (& sctx , ver , e .hash , sizeof (e .hash ), seed );
240
- xbox_rc4_init (& rctx , seed , sizeof (seed ));
241
- xbox_rc4_crypt (& rctx , e .confounder , 0x1C );
130
+ rc4_init (& rctx , seed , sizeof (seed ));
131
+ rc4_crypt (& rctx , e .confounder , 0x1C );
242
132
243
133
// save to file
244
134
FILE * fd = qemu_fopen (file , "wb" );
0 commit comments