+
+int mfnested(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) {
+
+ // flush queue
+ clearCommandBuffer();
+
+ UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}};
+ memcpy(c.d.asBytes, key, 6);
+ SendCommand(&c);
+
+ UsbCommand resp;
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
+ return -1;
+ }
+
+ if ((int)resp.arg[0]) {
+ return (int)resp.arg[0]; // error during nested
+ }
+
+ uint32_t uid;
+ memcpy(&uid, resp.d.asBytes, 4);
+ PrintAndLog("uid:%08x trgbl=%d trgkey=%x", uid, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8);
+
+ StateList_t statelists[2];
+ for (int i = 0; i < 2; i++) {
+ statelists[i].blockNo = resp.arg[2] & 0xff;
+ statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;
+ statelists[i].uid = uid;
+ memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4);
+ memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4);
+ }
+
+ uint32_t authentication_timeout;
+ memcpy(&authentication_timeout, resp.d.asBytes + 20, 4);
+ PrintAndLog("Setting authentication timeout to %" PRIu32 "us", authentication_timeout * 1000 / 106);
+
+ uint8_t num_unique_nonces;
+ uint32_t fixed_nt = 0;
+ if (statelists[0].nt == statelists[1].nt && statelists[0].ks1 == statelists[1].ks1) {
+ num_unique_nonces = 1;
+ memcpy(&fixed_nt, resp.d.asBytes + 24, 4);
+ PrintAndLog("Fixed nt detected: %08" PRIx32 " on first authentication, %08" PRIx32 " on nested authentication", fixed_nt, statelists[0].nt);
+ } else {
+ num_unique_nonces = 2;
+ }
+
+ // create and run worker threads to calculate possible crypto states
+ pthread_t thread_id[2];
+ for (int i = 0; i < num_unique_nonces; i++) {
+ pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]);
+ }
+ // wait for threads to terminate:
+ for (int i = 0; i < num_unique_nonces; i++) {
+ pthread_join(thread_id[i], (void*)&statelists[i].head.slhead);
+ }
+
+ if (num_unique_nonces == 2) {
+ return nested_standard(statelists, authentication_timeout, resultKey);
+ } else {
+ return nested_fixed_nonce(statelists[0], fixed_nt, authentication_timeout, resultKey);
+ }
+}
+
+