@@ -17,6 +17,21 @@ const uint8_t bitlen[] = {7, 5, 5};
17
17
const int sublen [] = {32 , 48 , 48 };
18
18
uint8_t bit_dir = 0 ;
19
19
20
+ void bitbang_raw (bool value , MagSetting * setting )
21
+ {
22
+ switch (setting -> tx ) {
23
+ case MagTxStateRFID :
24
+ furi_hal_gpio_write (RFID_PIN_OUT , value );
25
+ break ;
26
+ case MagTxStateGPIOA6A7 :
27
+ furi_hal_gpio_write (GPIO_PIN_A , value );
28
+ furi_hal_gpio_write (GPIO_PIN_B , !value );
29
+ break ;
30
+ default :
31
+ break ;
32
+ }
33
+ }
34
+
20
35
void play_bit_rfid (uint8_t send_bit , MagSetting * setting ) {
21
36
// internal TX over RFID coil
22
37
bit_dir ^= 1 ;
@@ -214,6 +229,139 @@ void track_to_bits(uint8_t* bit_array, const char* track_data, uint8_t track_ind
214
229
//furi_string_free(tmp_str);
215
230
}
216
231
232
+ void mag_spoof_bitwise (Mag * mag ) {
233
+ MagSetting * setting = mag -> setting ;
234
+
235
+
236
+ FuriString * ft1 = mag -> mag_dev -> dev_data .track [0 ].str ;
237
+ FuriString * ft2 = mag -> mag_dev -> dev_data .track [1 ].str ;
238
+
239
+ char * data1 ; char * data2 ;
240
+ data1 = malloc (furi_string_size (ft1 )+ 1 );
241
+ data2 = malloc (furi_string_size (ft2 )+ 1 );
242
+ strncpy (data1 , furi_string_get_cstr (ft1 ), furi_string_size (ft1 ));
243
+ strncpy (data2 , furi_string_get_cstr (ft2 ), furi_string_size (ft2 ));
244
+
245
+ if (furi_log_get_level () >= FuriLogLevelDebug ) {
246
+ debug_msr_string (data1 , BITS_TRACK1 , OFFSET_TRACK1 );
247
+ debug_msr_string (data2 , BITS_TRACK2 , OFFSET_TRACK2 );
248
+ }
249
+
250
+
251
+ uint8_t bits_t1_raw [64 ] = {0x55 }; // 68 chars max track 1 + 1 char crc * 7 approx =~ 483 bits
252
+ uint8_t bits_t1_manchester [128 ] = {0x55 }; // twice the above
253
+ uint16_t bits_t1_count = msr_encode (data1 , (uint8_t * ) bits_t1_manchester , (uint8_t * ) bits_t1_raw , BITS_TRACK1 , OFFSET_TRACK1 );
254
+ uint8_t bits_t2_raw [64 ] = {0x55 }; // 68 chars max track 1 + 1 char crc * 7 approx =~ 483 bits
255
+ uint8_t bits_t2_manchester [128 ] = {0x55 }; // twice the above
256
+ uint16_t bits_t2_count = msr_encode (data2 , (uint8_t * ) bits_t2_manchester , (uint8_t * ) bits_t2_raw , BITS_TRACK2 , OFFSET_TRACK2 );
257
+
258
+ if (furi_log_get_level () >= FuriLogLevelDebug ) {
259
+ printf ("Manchester bitcount: T1: %d, T2: %d\r\n" , bits_t1_count , bits_t2_count );
260
+
261
+ printf ("T1 raw: " );
262
+ for (int i = 0 ; i < bits_t1_count / 16 ; i ++ ) printf ("%02x " , bits_t1_raw [i ]);
263
+ printf ("\r\n" );
264
+
265
+ printf ("T1 manchester: " );
266
+ for (int i = 0 ; i < bits_t1_count / 8 ; i ++ ) printf ("%02x " , bits_t1_manchester [i ]);
267
+ printf ("\r\n" );
268
+
269
+ printf ("T2 raw: " );
270
+ for (int i = 0 ; i < bits_t2_count / 16 ; i ++ ) printf ("%02x " , bits_t2_raw [i ]);
271
+ printf ("\r\n" );
272
+
273
+ printf ("T2 manchester: " );
274
+ for (int i = 0 ; i < bits_t2_count / 8 ; i ++ ) printf ("%02x " , bits_t2_manchester [i ]);
275
+ printf ("\r\n" );
276
+
277
+ printf ("Bitwise emulation done\r\n\r\n" );
278
+ }
279
+
280
+ if (!tx_init (setting )) return ;
281
+
282
+ FURI_CRITICAL_ENTER ();
283
+ bool bit = false;
284
+
285
+
286
+ if ((setting -> track == MagTrackStateAll ))
287
+ for (uint16_t i = 0 ; i < ZERO_PREFIX ; i ++ )
288
+ {
289
+ bit ^= 0xFF ;
290
+ bitbang_raw (bit , setting );
291
+ furi_delay_us (setting -> us_clock * 2 );
292
+ }
293
+
294
+ if ((setting -> track == MagTrackStateAll ) || (setting -> track == MagTrackStateOne ))
295
+ for (uint16_t i = 0 ; i < bits_t1_count ; i ++ )
296
+ {
297
+ uint8_t byte = i / 8 ;
298
+ uint8_t bitmask = 1 << (7 - (i % 8 ));
299
+ /* this comment is mostly for zw's convenience:
300
+ *
301
+ * bits are stored in their arrays like on a card (LSB first). This is not how usually bits are stored in a
302
+ * byte, with the MSB first. the var bitmask creates the pattern to iterate through each bit, LSB first, like so
303
+ * 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x80... masking bits one by one from the current byte
304
+ *
305
+ * i've chosen this LSB approach since bits and bytes are hard enough to visualize with the 5/8 and 7/8 encoding
306
+ * MSR uses. It's a biiit more complicated to process, but visualizing it with printf or a debugger is
307
+ * infinitely easier
308
+ *
309
+ * Encoding the following pairs of 5 bits as 5/8: A1234 B1234 C1234 D1234
310
+ * using this LSB format looks like: A1234B12 34C1234D 12340000
311
+ * using the MSB format, looks like: 21B4321A D4321C43 00004321
312
+ * this means reading each byte backwards when printing/debugging, and the jumping 16 bits ahead, reading 8 more
313
+ * bits backward, jumping 16 more bits ahead.
314
+ *
315
+ * I find this much more convenient for debugging, with the tiny incovenience of reading the bits in reverse
316
+ * order. THus, the reason for the bitmask above
317
+ */
318
+
319
+ bit = !!(bits_t1_manchester [byte ] & bitmask );
320
+
321
+ // TODO: reimplement timing delays. Replace fixed furi_hal_cortex_delay_us to wait instead to a specific value
322
+ // for DWT->CYCCNT. Note timer is aliased to 64us as per
323
+ // #define FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND (SystemCoreClock / 1000000) | furi_hal_cortex.c
324
+
325
+ bitbang_raw (bit , setting );
326
+ furi_delay_us (setting -> us_clock );
327
+ // if (i % 2 == 1) furi_delay_us(setting->us_interpacket);
328
+ }
329
+
330
+ if ((setting -> track == MagTrackStateAll ))
331
+ for (uint16_t i = 0 ; i < ZERO_BETWEEN ; i ++ )
332
+ {
333
+ bit ^= 0xFF ;
334
+ bitbang_raw (bit , setting );
335
+ furi_delay_us (setting -> us_clock * 2 );
336
+ }
337
+
338
+ if ((setting -> track == MagTrackStateAll ) || (setting -> track == MagTrackStateTwo ))
339
+ for (uint16_t i = 0 ; i < bits_t2_count ; i ++ )
340
+ {
341
+ uint16_t j = bits_t2_count - i - 1 ;
342
+ uint8_t byte = j / 8 ;
343
+ uint8_t bitmask = 1 << (7 - (j % 8 ));
344
+ bool bit = !!(bits_t2_manchester [byte ] & bitmask );
345
+ bitbang_raw (bit , setting );
346
+ furi_delay_us (setting -> us_clock );
347
+ // if (i % 2 == 1) furi_delay_us(setting->us_interpacket);
348
+ }
349
+
350
+ if ((setting -> track == MagTrackStateAll ))
351
+ for (uint16_t i = 0 ; i < ZERO_SUFFIX ; i ++ )
352
+ {
353
+ bit ^= 0xFF ;
354
+ bitbang_raw (bit , setting );
355
+ furi_delay_us (setting -> us_clock * 2 );
356
+ }
357
+
358
+ FURI_CRITICAL_EXIT ();
359
+ free (data1 );
360
+ free (data2 );
361
+ tx_reset (setting );
362
+
363
+ }
364
+
217
365
void mag_spoof (Mag * mag ) {
218
366
MagSetting * setting = mag -> setting ;
219
367
@@ -316,3 +464,132 @@ bool get_bit(uint8_t* b, uint32_t blen, uint32_t bitpos) {
316
464
}
317
465
return bitpos;
318
466
}*/
467
+
468
+
469
+
470
+
471
+ uint16_t add_bit (bool value , uint8_t * out , uint16_t count )
472
+ {
473
+ uint8_t bit = count % 8 ;
474
+ uint8_t byte = count / 8 ;
475
+ if (value )
476
+ {
477
+ out [byte ] |= 0x01 ;
478
+ }
479
+ if (bit < 7 ) out [byte ] <<= 1 ;
480
+ return count + 1 ;
481
+ }
482
+
483
+ uint16_t add_bit_manchester (bool value , uint8_t * out , uint16_t count )
484
+ {
485
+ static bool toggle = 0 ;
486
+ toggle ^= 0x01 ;
487
+ count = add_bit (toggle , out , count );
488
+ if (value ) toggle ^= 0x01 ;
489
+ count = add_bit (toggle , out , count );
490
+ return count ;
491
+ }
492
+
493
+
494
+ uint16_t msr_encode (char * data , uint8_t * out_manchester , uint8_t * out_raw , uint8_t track_bits , uint8_t track_ascii_offset )
495
+ {
496
+ /*
497
+ * track_bits - the number of raw (data) bits on the track. on ISO cards, that's 7 for track 5, or 4 for 2/3 - this is samy's bitlen
498
+ * - this count includes the parity bit
499
+ * track_ascii_offset - how much the ascii values are offset. track 1 makes space (ascii 32) become data 0x00,
500
+ * - tracks 2/3 make ascii "0" become data 0x00 - this is samy's sublen
501
+ *
502
+ */
503
+
504
+ uint16_t raw_bits_count = 0 ;
505
+ uint16_t output_count = 0 ;
506
+ int tmp , crc , lrc = 0 ;
507
+
508
+ for (int i = 0 ; i < PREFIX_NUM_ZEROES ; i ++ )
509
+ {
510
+ output_count = add_bit_manchester (0 , out_manchester , output_count );
511
+ raw_bits_count = add_bit (0 , out_raw , raw_bits_count );
512
+ }
513
+
514
+
515
+ for (int i = 0 ; * (data + i ) != 0 ; i ++ )
516
+ {
517
+ crc = 1 ;
518
+ tmp = * (data + i ) - track_ascii_offset ;
519
+
520
+ for (int j = 0 ; j < track_bits - 1 ; j ++ )
521
+ {
522
+ crc ^= tmp & 1 ;
523
+ lrc ^= (tmp & 1 ) << j ;
524
+ raw_bits_count = add_bit (tmp & 0x01 , out_raw , raw_bits_count );
525
+ output_count = add_bit_manchester (tmp & 0x01 , out_manchester , output_count );
526
+ tmp >>= 1 ;
527
+ }
528
+ raw_bits_count = add_bit (crc , out_raw , raw_bits_count );
529
+ output_count = add_bit_manchester (crc , out_manchester , output_count );
530
+ }
531
+
532
+
533
+ // LRC byte
534
+ tmp = lrc ;
535
+ crc = 1 ;
536
+ for (int j = 0 ; j < track_bits - 1 ; j ++ )
537
+ {
538
+ crc ^= tmp & 0x01 ;
539
+ raw_bits_count = add_bit (tmp & 0x01 , out_raw , raw_bits_count );
540
+ output_count = add_bit_manchester (tmp & 0x01 , out_manchester , output_count );
541
+ tmp >>= 1 ;
542
+ }
543
+ raw_bits_count = add_bit (crc , out_raw , raw_bits_count );
544
+ output_count = add_bit_manchester (crc , out_manchester , output_count );
545
+
546
+ return output_count ;
547
+ }
548
+
549
+ void debug_msr_string (char * data , uint8_t track_bits , uint8_t track_ascii_offset )
550
+ {
551
+ uint8_t bits_raw [64 ] = {0 }; // 68 chars max track 1 + 1 char crc * 7 approx =~ 483 bits
552
+ uint8_t bits_manchester [128 ] = {0 }; // twice the above
553
+ int numbits = 0 ;
554
+
555
+ printf ("Encoding [%s] with %d bits\r\n" , data , track_bits );
556
+ numbits = msr_encode (data , (uint8_t * )bits_manchester , (uint8_t * )bits_raw , track_bits , track_ascii_offset );
557
+ printf ("Got %d bits\r\n" , numbits );
558
+ printf ("Raw byte stream: " );
559
+ for (int i = 0 ; i < numbits / 8 / 2 ; i ++ )
560
+ {
561
+ printf ("%02x" , bits_raw [i ]);
562
+ if (i %4 == 3 ) printf (" " );
563
+ }
564
+
565
+ printf ("\r\n" );
566
+
567
+ printf ("Bits " );
568
+ int space_counter = 0 ;
569
+ for (int i = 0 ; i < numbits / 2 ; i ++ )
570
+ {
571
+ if (i < PREFIX_NUM_ZEROES )
572
+ {
573
+ printf ("X" );
574
+ continue ;
575
+ }
576
+ else if (i == PREFIX_NUM_ZEROES )
577
+ {
578
+ printf (" " );
579
+ space_counter = 0 ;
580
+ }
581
+ printf ("%01x" , (bits_raw [i /8 ] & (1 << (7 - (i %8 )))) != 0 );
582
+ if ((space_counter ) % track_bits == track_bits - 1 ) printf (" " );
583
+ space_counter ++ ;
584
+ }
585
+
586
+ printf ("\r\n" );
587
+
588
+ printf ("Manchester encoded, byte stream: " );
589
+ for (int i = 0 ; i < numbits / 8 ; i ++ )
590
+ {
591
+ printf ("%02x" , bits_manchester [i ]);
592
+ if (i %4 == 3 ) printf (" " );
593
+ }
594
+ printf ("\r\n\r\n" );
595
+ }
0 commit comments