+
+ if (write_stats) {
+ fprintf(fstats, "%d;", num_bitflips);
+ }
+}
+
+
+static void simulate_MFplus_RNG(uint32_t test_cuid, uint64_t test_key, uint32_t *nt_enc, uint8_t *par_enc)
+{
+ struct Crypto1State sim_cs;
+ sim_cs.odd = sim_cs.even = 0;
+
+ // init cryptostate with key:
+ for(int8_t i = 47; i > 0; i -= 2) {
+ sim_cs.odd = sim_cs.odd << 1 | BIT(test_key, (i - 1) ^ 7);
+ sim_cs.even = sim_cs.even << 1 | BIT(test_key, i ^ 7);
+ }
+
+ *par_enc = 0;
+ uint32_t nt = (rand() & 0xff) << 24 | (rand() & 0xff) << 16 | (rand() & 0xff) << 8 | (rand() & 0xff);
+ for (int8_t byte_pos = 3; byte_pos >= 0; byte_pos--) {
+ uint8_t nt_byte_dec = (nt >> (8*byte_pos)) & 0xff;
+ uint8_t nt_byte_enc = crypto1_byte(&sim_cs, nt_byte_dec ^ (test_cuid >> (8*byte_pos)), false) ^ nt_byte_dec; // encode the nonce byte
+ *nt_enc = (*nt_enc << 8) | nt_byte_enc;
+ uint8_t ks_par = filter(sim_cs.odd); // the keystream bit to encode/decode the parity bit
+ uint8_t nt_byte_par_enc = ks_par ^ oddparity8(nt_byte_dec); // determine the nt byte's parity and encode it
+ *par_enc = (*par_enc << 1) | nt_byte_par_enc;
+ }
+
+}
+
+
+static void simulate_acquire_nonces()
+{
+ clock_t time1 = clock();
+ bool filter_flip_checked = false;
+ uint32_t total_num_nonces = 0;
+ uint32_t next_fivehundred = 500;
+ uint32_t total_added_nonces = 0;
+
+ cuid = (rand() & 0xff) << 24 | (rand() & 0xff) << 16 | (rand() & 0xff) << 8 | (rand() & 0xff);
+ known_target_key = ((uint64_t)rand() & 0xfff) << 36 | ((uint64_t)rand() & 0xfff) << 24 | ((uint64_t)rand() & 0xfff) << 12 | ((uint64_t)rand() & 0xfff);
+
+ printf("Simulating nonce acquisition for target key %012"llx", cuid %08x ...\n", known_target_key, cuid);
+ fprintf(fstats, "%012"llx";%08x;", known_target_key, cuid);
+
+ do {
+ uint32_t nt_enc = 0;
+ uint8_t par_enc = 0;
+
+ simulate_MFplus_RNG(cuid, known_target_key, &nt_enc, &par_enc);
+ //printf("Simulated RNG: nt_enc1: %08x, nt_enc2: %08x, par_enc: %02x\n", nt_enc1, nt_enc2, par_enc);
+ total_added_nonces += add_nonce(nt_enc, par_enc);
+ total_num_nonces++;
+
+ if (first_byte_num == 256 ) {
+ // printf("first_byte_num = %d, first_byte_Sum = %d\n", first_byte_num, first_byte_Sum);
+ if (!filter_flip_checked) {
+ Check_for_FilterFlipProperties();
+ filter_flip_checked = true;
+ }
+ num_good_first_bytes = estimate_second_byte_sum();
+ if (total_num_nonces > next_fivehundred) {
+ next_fivehundred = (total_num_nonces/500+1) * 500;
+ printf("Acquired %5d nonces (%5d with distinct bytes 0 and 1). Number of bytes with probability for correctly guessed Sum(a8) > %1.1f%%: %d\n",
+ total_num_nonces,
+ total_added_nonces,
+ CONFIDENCE_THRESHOLD * 100.0,
+ num_good_first_bytes);
+ }
+ }
+
+ } while (num_good_first_bytes < GOOD_BYTES_REQUIRED);
+
+ time1 = clock() - time1;
+ if ( time1 > 0 ) {
+ PrintAndLog("Acquired a total of %d nonces in %1.1f seconds (%0.0f nonces/minute)",
+ total_num_nonces,
+ ((float)time1)/CLOCKS_PER_SEC,
+ total_num_nonces * 60.0 * CLOCKS_PER_SEC/(float)time1);
+ }
+ fprintf(fstats, "%d;%d;%d;%1.2f;", total_num_nonces, total_added_nonces, num_good_first_bytes, CONFIDENCE_THRESHOLD);
+