static void init_offsets(uint64_t A, uint32_t a, uint32_t *offsets) { int bit; uint64_t multiplier_base = bytes_to_num(num_to_bytes(MAX(A / a, a))); uint64_t multiplier_byte; for (bit = 0; bit < 8; bit++) { multiplier_byte = num_to_bytes((multiplier_base + ind_to_mod[bit]) * a); while (multiplier_byte < num_to_bytes(A)) multiplier_byte += a; while (multiplier_byte - num_to_bytes(A) >= UINT16_MAX) multiplier_byte -= a; offsets[bit] = multiplier_byte - num_to_bytes(A); } }
static int l_nonce2key(lua_State *L) { size_t size; const char *p_uid = luaL_checklstring(L, 1, &size); if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size); const char *p_nt = luaL_checklstring(L, 2, &size); if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size); const char *p_nr = luaL_checklstring(L, 3, &size); if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size); const char *p_par_info = luaL_checklstring(L, 4, &size); if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size); const char *p_pks_info = luaL_checklstring(L, 5, &size); if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size); uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4); uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4); uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4); uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8); uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8); uint64_t key = 0; int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key); //Push the retval on the stack lua_pushinteger(L,retval); //Push the key onto the stack uint8_t dest_key[8]; num_to_bytes(key,sizeof(dest_key),dest_key); //printf("Pushing to lua stack: %012"llx"\n",key); lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key)); return 2; //Two return values }
/** * @brief l_foobar is a dummy function to test lua-integration with * @param L * @return */ static int l_foobar(lua_State *L) { //Check number of arguments int n = lua_gettop(L); printf("foobar called with %d arguments" , n); lua_settop(L, 0); printf("Arguments discarded, stack now contains %d elements", lua_gettop(L)); // todo: this is not used, where was it intended for? // UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}}; printf("Now returning a uint64_t as a string"); uint64_t x = 0xDEADBEEF; uint8_t destination[8]; num_to_bytes(x,sizeof(x),destination); lua_pushlstring(L,(const char *)&x,sizeof(x)); lua_pushlstring(L,(const char *)destination,sizeof(destination)); return 2; }
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKey, bool calibrate) { uint16_t i; uint32_t uid; UsbCommand resp; StateList_t statelists[2]; struct Crypto1State *p1, *p2, *p3, *p4; // flush queue WaitForResponseTimeout(CMD_ACK,NULL,100); UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}}; memcpy(c.d.asBytes, key, 6); SendCommand(&c); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { return -1; } if (resp.arg[0]) { return resp.arg[0]; // error during nested } 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); for (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); } // calc keys pthread_t thread_id[2]; // create and run worker threads for (i = 0; i < 2; i++) { pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]); } // wait for threads to terminate: for (i = 0; i < 2; i++) { pthread_join(thread_id[i], (void*)&statelists[i].head.slhead); } // the first 16 Bits of the cryptostate already contain part of our key. // Create the intersection of the two lists based on these 16 Bits and // roll back the cryptostate p1 = p3 = statelists[0].head.slhead; p2 = p4 = statelists[1].head.slhead; while (p1 <= statelists[0].tail.sltail && p2 <= statelists[1].tail.sltail) { if (Compare16Bits(p1, p2) == 0) { struct Crypto1State savestate, *savep = &savestate; savestate = *p1; while(Compare16Bits(p1, savep) == 0 && p1 <= statelists[0].tail.sltail) { *p3 = *p1; lfsr_rollback_word(p3, statelists[0].nt ^ statelists[0].uid, 0); p3++; p1++; } savestate = *p2; while(Compare16Bits(p2, savep) == 0 && p2 <= statelists[1].tail.sltail) { *p4 = *p2; lfsr_rollback_word(p4, statelists[1].nt ^ statelists[1].uid, 0); p4++; p2++; } } else { while (Compare16Bits(p1, p2) == -1) p1++; while (Compare16Bits(p1, p2) == 1) p2++; } } p3->even = 0; p3->odd = 0; p4->even = 0; p4->odd = 0; statelists[0].len = p3 - statelists[0].head.slhead; statelists[1].len = p4 - statelists[1].head.slhead; statelists[0].tail.sltail=--p3; statelists[1].tail.sltail=--p4; // the statelists now contain possible keys. The key we are searching for must be in the // intersection of both lists. Create the intersection: qsort(statelists[0].head.keyhead, statelists[0].len, sizeof(uint64_t), compar_int); qsort(statelists[1].head.keyhead, statelists[1].len, sizeof(uint64_t), compar_int); uint64_t *p5, *p6, *p7; p5 = p7 = statelists[0].head.keyhead; p6 = statelists[1].head.keyhead; while (p5 <= statelists[0].tail.keytail && p6 <= statelists[1].tail.keytail) { if (compar_int(p5, p6) == 0) { *p7++ = *p5++; p6++; } else { while (compar_int(p5, p6) == -1) p5++; while (compar_int(p5, p6) == 1) p6++; } } statelists[0].len = p7 - statelists[0].head.keyhead; statelists[0].tail.keytail=--p7; memset(resultKey, 0, 6); // The list may still contain several key candidates. Test each of them with mfCheckKeys for (i = 0; i < statelists[0].len; i++) { uint8_t keyBlock[6]; uint64_t key64; crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); num_to_bytes(key64, 6, keyBlock); key64 = 0; if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, 1, keyBlock, &key64)) { num_to_bytes(key64, 6, resultKey); break; } } free(statelists[0].head.slhead); free(statelists[1].head.slhead); return 0; }
int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { uint8_t data[64]; if (traceState == TRACE_ERROR) return 1; if (len > 64) { traceState = TRACE_ERROR; return 1; } memcpy(data, data_src, len); if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) { mf_crypto1_decrypt(traceCrypto1, data, len, 0); PrintAndLog("dec> %s", sprint_hex(data, len)); AddLogHex(logHexFileName, "dec> ", data, len); } switch (traceState) { case TRACE_IDLE: // check packet crc16! if ((len >= 4) && (!CheckCrc14443(CRC_14443_A, data, len))) { PrintAndLog("dec> CRC ERROR!!!"); AddLogLine(logHexFileName, "dec> ", "CRC ERROR!!!"); traceState = TRACE_ERROR; // do not decrypt the next commands return 1; } // AUTHENTICATION if ((len == 4) && ((data[0] == 0x60) || (data[0] == 0x61))) { traceState = TRACE_AUTH1; traceCurBlock = data[1]; traceCurKey = data[0] == 60 ? 1:0; return 0; } // READ if ((len ==4) && ((data[0] == 0x30))) { traceState = TRACE_READ_DATA; traceCurBlock = data[1]; return 0; } // WRITE if ((len ==4) && ((data[0] == 0xA0))) { traceState = TRACE_WRITE_OK; traceCurBlock = data[1]; return 0; } // HALT if ((len ==4) && ((data[0] == 0x50) && (data[1] == 0x00))) { traceState = TRACE_ERROR; // do not decrypt the next commands return 0; } return 0; break; case TRACE_READ_DATA: if (len == 18) { traceState = TRACE_IDLE; if (isBlockTrailer(traceCurBlock)) { memcpy(traceCard + traceCurBlock * 16 + 6, data + 6, 4); } else { memcpy(traceCard + traceCurBlock * 16, data, 16); } if (wantSaveToEmlFile) saveTraceCard(); return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_WRITE_OK: if ((len == 1) && (data[0] == 0x0a)) { traceState = TRACE_WRITE_DATA; return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_WRITE_DATA: if (len == 18) { traceState = TRACE_IDLE; memcpy(traceCard + traceCurBlock * 16, data, 16); if (wantSaveToEmlFile) saveTraceCard(); return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_AUTH1: if (len == 4) { traceState = TRACE_AUTH2; nt = bytes_to_num(data, 4); return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_AUTH2: if (len == 8) { traceState = TRACE_AUTH_OK; nr_enc = bytes_to_num(data, 4); ar_enc = bytes_to_num(data + 4, 4); return 0; } else { traceState = TRACE_ERROR; return 1; } break; case TRACE_AUTH_OK: if (len ==4) { traceState = TRACE_IDLE; at_enc = bytes_to_num(data, 4); // decode key here) ks2 = ar_enc ^ prng_successor(nt, 64); ks3 = at_enc ^ prng_successor(nt, 96); revstate = lfsr_recovery64(ks2, ks3); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, nr_enc, 1); lfsr_rollback_word(revstate, uid ^ nt, 0); crypto1_get_lfsr(revstate, &key); printf("Key: %012"llx"\n",key); AddLogUint64(logHexFileName, "key: ", key); int blockShift = ((traceCurBlock & 0xFC) + 3) * 16; if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4); if (traceCurKey) { num_to_bytes(key, 6, traceCard + blockShift + 10); } else { num_to_bytes(key, 6, traceCard + blockShift); } if (wantSaveToEmlFile) saveTraceCard(); if (traceCrypto1) { crypto1_destroy(traceCrypto1); } // set cryptosystem state traceCrypto1 = lfsr_recovery64(ks2, ks3); // nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt; /* traceCrypto1 = crypto1_create(key); // key in lfsr crypto1_word(traceCrypto1, nt ^ uid, 0); crypto1_word(traceCrypto1, ar, 1); crypto1_word(traceCrypto1, 0, 0); crypto1_word(traceCrypto1, 0, 0);*/ return 0; } else { traceState = TRACE_ERROR; return 1; } break; default: traceState = TRACE_ERROR; return 1; } return 0; }
int CmdFdxDemod(const char *Cmd){ //Differential Biphase / di-phase (inverted biphase) //get binary from ask wave if (!ASKbiphaseDemod("0 32 1 0", false)) { if (g_debugMode) PrintAndLog("DEBUG: Error - FDX-B ASKbiphaseDemod failed"); return 0; } size_t size = DemodBufferLen; int preambleIndex = FDXBdemodBI(DemodBuffer, &size); if (preambleIndex < 0){ if (g_debugMode){ if (preambleIndex == -1) PrintAndLog("DEBUG: Error - FDX-B too few bits found"); else if (preambleIndex == -2) PrintAndLog("DEBUG: Error - FDX-B preamble not found"); else if (preambleIndex == -3) PrintAndLog("DEBUG: Error - FDX-B Size not correct: %d", size); else PrintAndLog("DEBUG: Error - FDX-B ans: %d", preambleIndex); } return 0; } // set and leave DemodBuffer intact setDemodBuf(DemodBuffer, 128, preambleIndex); setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex*g_DemodClock)); uint8_t bits_no_spacer[117]; memcpy(bits_no_spacer, DemodBuffer + 11, 117); // remove marker bits (1's every 9th digit after preamble) (pType = 2) size = removeParity(bits_no_spacer, 0, 9, 2, 117); if ( size != 104 ) { if (g_debugMode) PrintAndLog("DEBUG: Error removeParity:: %d", size); return 0; } //got a good demod uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(bits_no_spacer+32,6)) << 32) | bytebits_to_byteLSBF(bits_no_spacer,32); uint32_t countryCode = bytebits_to_byteLSBF(bits_no_spacer+38,10); uint8_t dataBlockBit = bits_no_spacer[48]; uint32_t reservedCode = bytebits_to_byteLSBF(bits_no_spacer+49,14); uint8_t animalBit = bits_no_spacer[63]; uint32_t crc16 = bytebits_to_byteLSBF(bits_no_spacer+64,16); uint32_t extended = bytebits_to_byteLSBF(bits_no_spacer+80,24); uint64_t rawid = ((uint64_t)bytebits_to_byte(bits_no_spacer,32)<<32) | bytebits_to_byte(bits_no_spacer+32,32); uint8_t raw[8]; num_to_bytes(rawid, 8, raw); if (g_debugMode) { PrintAndLog("DEBUG: bits_no_spacer:\n%s",sprint_bin_break(bits_no_spacer,size,16)); PrintAndLog("DEBUG: Start marker %d; Size %d", preambleIndex, size); PrintAndLog("DEBUG: Raw ID Hex: %s", sprint_hex(raw,8)); } uint16_t calcCrc = crc16_ccitt_kermit(raw, 8); PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); PrintAndLog("Animal ID: %04u-%012" PRIu64, countryCode, NationalCode); PrintAndLog("National Code: %012" PRIu64, NationalCode); PrintAndLog("CountryCode: %04u", countryCode); PrintAndLog("Reserved Code: %u", reservedCode); PrintAndLog("Animal Tag: %s", animalBit ? "True" : "False"); PrintAndLog("Has Extended: %s [0x%X]", dataBlockBit ? "True" : "False", extended); PrintAndLog("CRC: 0x%04X - 0x%04X - [%s]\n", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed"); // set block 0 for later //g_DemodConfig = T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT; return 1; }