Skip to content

Commit b60927c

Browse files
committed
eeprom: Use sha1_rc4 util for hashing functions
1 parent b229979 commit b60927c

File tree

2 files changed

+19
-141
lines changed

2 files changed

+19
-141
lines changed

hw/xbox/eeprom_generation.c

+19-129
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* QEMU Xbox EEPROM Generation (MCPX Version 1.0)
33
*
44
* Copyright (c) 2020 Mike Davis
5+
* Copyright (c) 2024 Ryan Wendland
56
*
67
* This library is free software; you can redistribute it and/or
78
* modify it under the terms of the GNU Lesser General Public
@@ -17,7 +18,11 @@
1718
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
1819
*/
1920

21+
#include <stdint.h>
22+
#include <stdio.h>
23+
#include <string.h>
2024
#include "eeprom_generation.h"
25+
#include "util/sha1_rc4.h"
2126

2227
static uint32_t xbox_eeprom_crc(uint8_t *data, size_t len) {
2328
uint32_t high = 0;
@@ -32,44 +37,6 @@ static uint32_t xbox_eeprom_crc(uint8_t *data, size_t len) {
3237
return ~(high + low);
3338
}
3439

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-
7340
static void xbox_sha1_reset(SHA1Context *ctx, XboxEEPROMVersion ver, bool first) {
7441
ctx->msg_blk_index = 0;
7542
ctx->computed = false;
@@ -79,127 +46,50 @@ static void xbox_sha1_reset(SHA1Context *ctx, XboxEEPROMVersion ver, bool first)
7946
switch (ver) {
8047
case XBOX_EEPROM_VERSION_D:
8148
if (first) {
82-
xbox_sha1_fill(ctx, 0x85F9E51A, 0xE04613D2,
49+
sha1_fill(ctx, 0x85F9E51A, 0xE04613D2,
8350
0x6D86A50C, 0x77C32E3C, 0x4BD717A4);
8451
} else {
85-
xbox_sha1_fill(ctx, 0x5D7A9C6B, 0xE1922BEB,
52+
sha1_fill(ctx, 0x5D7A9C6B, 0xE1922BEB,
8653
0xB82CCDBC, 0x3137AB34, 0x486B52B3);
8754
}
8855
break;
8956
case XBOX_EEPROM_VERSION_R2:
9057
if (first) {
91-
xbox_sha1_fill(ctx, 0x39B06E79, 0xC9BD25E8,
58+
sha1_fill(ctx, 0x39B06E79, 0xC9BD25E8,
9259
0xDBC6B498, 0x40B4389D, 0x86BBD7ED);
9360
} else {
94-
xbox_sha1_fill(ctx, 0x9B49BED3, 0x84B430FC,
61+
sha1_fill(ctx, 0x9B49BED3, 0x84B430FC,
9562
0x6B8749CD, 0xEBFE5FE5, 0xD96E7393);
9663
}
9764
break;
9865
case XBOX_EEPROM_VERSION_R3:
9966
if (first) {
100-
xbox_sha1_fill(ctx, 0x8058763A, 0xF97D4E0E,
67+
sha1_fill(ctx, 0x8058763A, 0xF97D4E0E,
10168
0x865A9762, 0x8A3D920D, 0x08995B2C);
10269
} else {
103-
xbox_sha1_fill(ctx, 0x01075307, 0xA2f1E037,
70+
sha1_fill(ctx, 0x01075307, 0xA2f1E037,
10471
0x1186EEEA, 0x88DA9992, 0x168A5609);
10572
}
10673
break;
10774
default: // default to 1.0 version
10875
if (first) {
109-
xbox_sha1_fill(ctx, 0x72127625, 0x336472B9,
76+
sha1_fill(ctx, 0x72127625, 0x336472B9,
11077
0xBE609BEA, 0xF55E226B, 0x99958DAC);
11178
} else {
112-
xbox_sha1_fill(ctx, 0x76441D41, 0x4DE82659,
79+
sha1_fill(ctx, 0x76441D41, 0x4DE82659,
11380
0x2E8EF85E, 0xB256FACA, 0xC4FE2DE8);
11481
}
11582
}
11683
}
11784

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-
19585
static void xbox_sha1_compute(SHA1Context *ctx, XboxEEPROMVersion ver,
19686
uint8_t *data, size_t len, uint8_t *hash) {
19787
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);
20090
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);
20393
}
20494

20595
bool xbox_eeprom_generate(const char *file, XboxEEPROMVersion ver) {
@@ -237,8 +127,8 @@ bool xbox_eeprom_generate(const char *file, XboxEEPROMVersion ver) {
237127
uint8_t seed[20];
238128
xbox_sha1_compute(&sctx, ver, e.confounder, 0x1C, e.hash);
239129
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);
242132

243133
// save to file
244134
FILE *fd = qemu_fopen(file, "wb");

hw/xbox/eeprom_generation.h

-12
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,6 @@
2525
#include "crypto/random.h"
2626
#include "include/qemu/bswap.h"
2727

28-
typedef struct RC4Context {
29-
uint8_t s[256];
30-
} RC4Context;
31-
32-
typedef struct SHA1Context {
33-
uint32_t intermediate[5];
34-
uint8_t msg_blk[64];
35-
uint32_t msg_blk_index;
36-
uint32_t length;
37-
bool computed;
38-
} SHA1Context;
39-
4028
#pragma pack(push,1)
4129
typedef struct XboxEEPROM {
4230
uint8_t hash[20];

0 commit comments

Comments
 (0)