Skip to content

Commit bc63399

Browse files
committed
Worked on Xerox generator secret blocks
1 parent 8a0545f commit bc63399

1 file changed

Lines changed: 109 additions & 34 deletions

File tree

client/src/cmdhfxerox.c

Lines changed: 109 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ static const char *xerox_c_type[] = { "drum", "yellow", "magenta", "cyan", "blac
151151
static const uint8_t FACTORY_SOLD[] = { 0xDB, 0x3A, 0xDB, 0x3A };
152152
static const uint8_t FACTORY_METERED[] = { 0xD8, 0x3A, 0xD8, 0x3A };
153153

154-
155154
static int CmdHelp(const char *Cmd);
156155
void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits);
157156
void RC2_encrypt(unsigned long *d, RC2_KEY *key);
@@ -377,6 +376,35 @@ void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
377376
tin[0] = tin[1] = 0;
378377
}
379378

379+
static void xerox_derive_key(const uint8_t *data, RC2_KEY *out_key) {
380+
uint8_t k1[8], iv[8], k2[8];
381+
382+
k1[0] = data[8];
383+
k1[1] = data[5];
384+
k1[2] = data[6];
385+
k1[3] = data[7];
386+
k1[4] = data[(0x18 * XEROX_BLOCK_SIZE) + 0];
387+
k1[5] = data[(0x18 * XEROX_BLOCK_SIZE) + 1];
388+
k1[6] = data[(0x22 * XEROX_BLOCK_SIZE) + 0];
389+
k1[7] = 0;
390+
391+
RC2_set_key(out_key, 8, k1, 64);
392+
393+
memset(iv, 0, sizeof(iv));
394+
iv[0] = k1[6];
395+
iv[1] = k1[7];
396+
iv[2] = 1;
397+
398+
RC2_cbc_encrypt(k1, k2, 8, out_key, iv, RC2_ENCRYPT);
399+
400+
memcpy(k1, k2, sizeof(k1));
401+
k1[2] = k2[3] ^ data[(0x22 * XEROX_BLOCK_SIZE) + 0];
402+
k1[3] = k2[4] ^ data[(0x22 * XEROX_BLOCK_SIZE) + 1];
403+
k1[5] = k2[1] ^ 0x01;
404+
405+
RC2_set_key(out_key, 8, k1, 64);
406+
}
407+
380408
static int switch_off_field(void) {
381409
SetISODEPState(ISODEP_INACTIVE);
382410
iso14b_raw_cmd_t packet = {
@@ -971,33 +999,9 @@ static int CmdHFXeroxDump(const char *Cmd) {
971999
PrintAndLogEx(INFO, "Decrypting secret blocks...");
9721000

9731001
RC2_KEY exp_key;
974-
uint8_t k1[8], iv[8], k2[8], decr[8];
975-
976-
k1[0] = data[8];
977-
k1[1] = data[5];
978-
k1[2] = data[6];
979-
k1[3] = data[7];
980-
k1[4] = data[(0x18 * XEROX_BLOCK_SIZE) + 0];
981-
k1[5] = data[(0x18 * XEROX_BLOCK_SIZE) + 1];
982-
k1[6] = data[(0x22 * XEROX_BLOCK_SIZE) + 0];
983-
k1[7] = 0;
984-
985-
RC2_set_key(&exp_key, 8, k1, 64);
986-
987-
memset(iv, 0, sizeof(iv));
988-
iv[0] = k1[6];
989-
iv[1] = k1[7];
990-
iv[2] = 1;
991-
992-
RC2_cbc_encrypt(k1, k2, 8, &exp_key, iv, RC2_ENCRYPT);
1002+
uint8_t iv[8], decr[8];
9931003

994-
memcpy(k1, k2, sizeof(k1));
995-
996-
k1[2] = k2[3] ^ data[(0x22 * XEROX_BLOCK_SIZE) + 0];
997-
k1[3] = k2[4] ^ data[(0x22 * XEROX_BLOCK_SIZE) + 1]; // first_key[7];
998-
k1[5] = k2[1] ^ 0x01; // 01 = crypto method? rfid[23][2]
999-
1000-
RC2_set_key(&exp_key, 8, k1, 64);
1004+
xerox_derive_key(data, &exp_key);
10011005

10021006
for (int n = 0; n < sizeof(var_list); n++) {
10031007

@@ -1457,6 +1461,62 @@ static int map_generator(const json_t *selected) {
14571461
PrintAndLogEx(INPLACE, "blk %3d", blockno);
14581462
}
14591463

1464+
RC2_KEY enc_key;
1465+
xerox_derive_key(data, &enc_key);
1466+
1467+
typedef struct {
1468+
uint8_t dadr;
1469+
uint8_t plain[8];
1470+
bool patch_lo;
1471+
bool patch_hi;
1472+
uint8_t cipher_lo[4];
1473+
uint8_t cipher_hi[4];
1474+
} xerox_secret_plain_t;
1475+
1476+
xerox_secret_plain_t secret_plains[] = {
1477+
{ 0x1D, {0x28,0x00,0xA5,0xF5, 0x00,0x00,0x00,0x00}, true, true, {0}, {0} }, // Block 29 - signature
1478+
// Block 30 - zeros
1479+
{ 0x1E, {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}, true, true, {0}, {0} }, // Block 30 - zeros
1480+
// Block 31 - FF FF pattern (low half only)
1481+
{ 0x1F, {0x00,0x00,0xFF,0xFF, 0x00,0x00,0x00,0x00}, true, false, {0}, {0} }, // Block 31 - FF FF pattern
1482+
// Block 33 - fixed value (high half only)
1483+
{ 0x21, {0x00,0x00,0x3F,0xFD, 0x00,0x00,0x00,0x00}, false, true, {0}, {0} }, // Block 33 - 3F FD
1484+
// Block 38 - 999 decimal (low half only)
1485+
{ 0x26, {0x00,0x00,0xE7,0x03, 0x00,0x00,0x00,0x00}, true, false, {0}, {0} }, // Block 38 - 999
1486+
// Block 40 - zeros
1487+
{ 0x28, {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}, true, true, {0}, {0} }, // Block 40 - zeros
1488+
// Block 42 - zeros
1489+
{ 0x2A, {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}, true, true, {0}, {0} }, // Block 42 - zeros
1490+
// Block 43 - FF FF pattern (low half only)
1491+
{ 0x2B, {0x00,0x00,0xFF,0xFF, 0x00,0x00,0x00,0x00}, true, false, {0}, {0} }, // Block 43 - FF FF pattern
1492+
// Block 44 - zeros
1493+
{ 0x2C, {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}, true, true, {0}, {0} }, // Block 44 - zeros
1494+
// Block 45 - FF FF pattern (low half only)
1495+
{ 0x2D, {0x00,0x00,0xFF,0xFF, 0x00,0x00,0x00,0x00}, true, false, {0}, {0} }, // Block 45 - FF FF pattern
1496+
// Block 46 - zeros
1497+
{ 0x2E, {0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}, true, true, {0}, {0} }, // Block 46 - zeros
1498+
// Block 47 - FF FF pattern (low half only)
1499+
{ 0x2F, {0x00,0x00,0xFF,0xFF, 0x00,0x00,0x00,0x00}, true, false, {0}, {0} }, // Block 47 - FF FF pattern
1500+
};
1501+
1502+
for (int s = 0; s < ARRAYLEN(secret_plains); s++) {
1503+
xerox_secret_plain_t *sp = &secret_plains[s];
1504+
1505+
if (!sp->patch_lo)
1506+
memcpy(sp->plain, data + (sp->dadr * XEROX_BLOCK_SIZE), 4);
1507+
if (!sp->patch_hi)
1508+
memcpy(sp->plain + 4, data + ((sp->dadr + 1) * XEROX_BLOCK_SIZE), 4);
1509+
1510+
uint8_t iv[8] = {0};
1511+
iv[0] = sp->dadr;
1512+
1513+
uint8_t cipher[8] = {0};
1514+
RC2_cbc_encrypt(sp->plain, cipher, 8, &enc_key, iv, RC2_ENCRYPT);
1515+
1516+
memcpy(sp->cipher_lo, cipher, 4);
1517+
memcpy(sp->cipher_hi, cipher + 4, 4);
1518+
}
1519+
14601520
// Partnumber (encode partnumber string → 6 bytes for blocks 0x15–0x16)
14611521
uint8_t pbytes[6] = {0};
14621522
xerox_encode_partno(part_number, pbytes);
@@ -1493,13 +1553,27 @@ static int map_generator(const json_t *selected) {
14931553
const char *desc;
14941554
} block_entry_t;
14951555

1496-
// Named blocks with specific target values
1556+
// Now named[] points directly into the struct — no switch, no separate buffers
14971557
block_entry_t named[] = {
1498-
{ 0x15, target_15, "Part# (1/2)" },
1499-
{ 0x16, target_16, "Part# (2/2)" },
1500-
{ 0x0C, target_12, "Type/Color" },
1501-
{ 0x22, target_22, "Type/Color" },
1502-
{ 0x83, target_83, "Factory pattern"},
1558+
{ 0x15, target_15, "Part# (1/2)" },
1559+
{ 0x16, target_16, "Part# (2/2)" },
1560+
{ 0x0C, target_12, "Type/Color" },
1561+
{ 0x22, target_22, "Type/Color" },
1562+
{ 0x83, target_83, "Factory pattern" },
1563+
1564+
// Secret blocks from secret_plains
1565+
{ 0x1D, secret_plains[0].cipher_lo, "Secret (enc)" }, // Block 29 - signature (low)
1566+
{ 0x1E, secret_plains[1].cipher_lo, "Secret (enc)" }, // Block 30 - zeros (low)
1567+
{ 0x1F, secret_plains[2].cipher_lo, "Secret (enc)" }, // Block 31 - FF FF (low)
1568+
{ 0x21, secret_plains[3].cipher_hi, "Secret (enc)" }, // Block 33 - 3F FD (high)
1569+
{ 0x26, secret_plains[4].cipher_lo, "Secret (enc)" }, // Block 38 - 999 (low)
1570+
{ 0x28, secret_plains[5].cipher_lo, "Secret (enc)" }, // Block 40 - zeros (low)
1571+
{ 0x2A, secret_plains[6].cipher_lo, "Secret (enc)" }, // Block 42 - zeros (low)
1572+
{ 0x2B, secret_plains[7].cipher_lo, "Secret (enc)" }, // Block 43 - FF FF (low)
1573+
{ 0x2C, secret_plains[8].cipher_lo, "Secret (enc)" }, // Block 44 - zeros (low)
1574+
{ 0x2D, secret_plains[9].cipher_lo, "Secret (enc)" }, // Block 45 - FF FF (low)
1575+
{ 0x2E, secret_plains[10].cipher_lo, "Secret (enc)" }, // Block 46 - zeros (low)
1576+
{ 0x2F, secret_plains[11].cipher_lo, "Secret (enc)" }, // Block 47 - FF FF (low)
15031577
};
15041578

15051579
// Blocks to zero out (counters, firmware, etc.)
@@ -1522,7 +1596,8 @@ static int map_generator(const json_t *selected) {
15221596
0xCF, 0xD1, 0xD3, 0xD5, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
15231597
0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE2, 0xE3, 0xE4, 0xE5,
15241598
0xE7, 0xE9, 0xEA, 0xEB, 0xEC, 0xEE, 0xEF, 0xF0, 0xF1,
1525-
0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xFA, 0xFC
1599+
0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xFA, 0xFC,
1600+
0xFE, 0xFF
15261601
};
15271602

15281603
int num_named = ARRAYLEN(named);

0 commit comments

Comments
 (0)