@@ -151,7 +151,6 @@ static const char *xerox_c_type[] = { "drum", "yellow", "magenta", "cyan", "blac
151151static const uint8_t FACTORY_SOLD [] = { 0xDB , 0x3A , 0xDB , 0x3A };
152152static const uint8_t FACTORY_METERED [] = { 0xD8 , 0x3A , 0xD8 , 0x3A };
153153
154-
155154static int CmdHelp (const char * Cmd );
156155void RC2_set_key (RC2_KEY * key , int len , const unsigned char * data , int bits );
157156void 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+
380408static 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