Skip to content

Commit 574c479

Browse files
committed
upd nfc magic
1 parent d8becee commit 574c479

31 files changed

+2874
-71
lines changed

base_pack/nfc_magic/application.fam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ App(
1010
],
1111
stack_size=4 * 1024,
1212
fap_description="Application for writing to NFC tags with modifiable sector 0",
13-
fap_version="1.5",
13+
fap_version="1.6",
1414
fap_icon="assets/Nfc_10px.png",
1515
fap_category="NFC",
1616
fap_private_libs=[

base_pack/nfc_magic/lib/magic/nfc_magic_scanner.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "nfc_magic_scanner.h"
22

33
#include "protocols/gen1a/gen1a_poller.h"
4+
#include "protocols/gen2/gen2_poller.h"
45
#include "protocols/gen4/gen4_poller.h"
56
#include <nfc/nfc_poller.h>
67

@@ -65,20 +66,33 @@ static int32_t nfc_magic_scanner_worker(void* context) {
6566
furi_assert(instance->session_state == NfcMagicScannerSessionStateActive);
6667

6768
while(instance->session_state == NfcMagicScannerSessionStateActive) {
68-
if(instance->current_protocol == NfcMagicProtocolGen1) {
69-
instance->magic_protocol_detected = gen1a_poller_detect(instance->nfc);
70-
} else if(instance->current_protocol == NfcMagicProtocolGen4) {
71-
Gen4PollerError error = gen4_poller_detect(instance->nfc, instance->gen4_password);
72-
if(error == Gen4PollerErrorProtocol) {
73-
NfcMagicScannerEvent event = {
74-
.type = NfcMagicScannerEventTypeDetectedNotMagic,
75-
};
76-
instance->callback(event, instance->context);
77-
break;
78-
} else {
69+
do {
70+
if(instance->current_protocol == NfcMagicProtocolGen1) {
71+
instance->magic_protocol_detected = gen1a_poller_detect(instance->nfc);
72+
if(instance->magic_protocol_detected) {
73+
break;
74+
}
75+
} else if(instance->current_protocol == NfcMagicProtocolGen4) {
76+
Gen4PollerError error = gen4_poller_detect(instance->nfc, instance->gen4_password);
7977
instance->magic_protocol_detected = (error == Gen4PollerErrorNone);
78+
if(instance->magic_protocol_detected) {
79+
break;
80+
}
81+
} else if(instance->current_protocol == NfcMagicProtocolGen2) {
82+
Gen2PollerError error = gen2_poller_detect(instance->nfc);
83+
instance->magic_protocol_detected = (error == Gen2PollerErrorNone);
84+
if(instance->magic_protocol_detected) {
85+
break;
86+
}
87+
} else if(instance->current_protocol == NfcMagicProtocolClassic) {
88+
NfcPoller* poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfClassic);
89+
instance->magic_protocol_detected = nfc_poller_detect(poller);
90+
nfc_poller_free(poller);
91+
if(instance->magic_protocol_detected) {
92+
break;
93+
}
8094
}
81-
}
95+
} while(false);
8296

8397
if(instance->magic_protocol_detected) {
8498
NfcMagicScannerEvent event = {
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
#include "crypto1.h"
2+
3+
#include <lib/nfc/helpers/nfc_util.h>
4+
#include <bit_lib.h>
5+
#include <furi.h>
6+
7+
// Algorithm from https://github.com/RfidResearchGroup/proxmark3.git
8+
9+
#define SWAPENDIAN(x) \
10+
((x) = ((x) >> 8 & 0xff00ff) | ((x)&0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16)
11+
#define LF_POLY_ODD (0x29CE5C)
12+
#define LF_POLY_EVEN (0x870804)
13+
14+
#define BEBIT(x, n) FURI_BIT(x, (n) ^ 24)
15+
16+
Crypto1* crypto1_alloc() {
17+
Crypto1* instance = malloc(sizeof(Crypto1));
18+
19+
return instance;
20+
}
21+
22+
void crypto1_free(Crypto1* instance) {
23+
furi_assert(instance);
24+
25+
free(instance);
26+
}
27+
28+
void crypto1_reset(Crypto1* crypto1) {
29+
furi_assert(crypto1);
30+
crypto1->even = 0;
31+
crypto1->odd = 0;
32+
}
33+
34+
void crypto1_init(Crypto1* crypto1, uint64_t key) {
35+
furi_assert(crypto1);
36+
crypto1->even = 0;
37+
crypto1->odd = 0;
38+
for(int8_t i = 47; i > 0; i -= 2) {
39+
crypto1->odd = crypto1->odd << 1 | FURI_BIT(key, (i - 1) ^ 7);
40+
crypto1->even = crypto1->even << 1 | FURI_BIT(key, i ^ 7);
41+
}
42+
}
43+
44+
static uint32_t crypto1_filter(uint32_t in) {
45+
uint32_t out = 0;
46+
out = 0xf22c0 >> (in & 0xf) & 16;
47+
out |= 0x6c9c0 >> (in >> 4 & 0xf) & 8;
48+
out |= 0x3c8b0 >> (in >> 8 & 0xf) & 4;
49+
out |= 0x1e458 >> (in >> 12 & 0xf) & 2;
50+
out |= 0x0d938 >> (in >> 16 & 0xf) & 1;
51+
return FURI_BIT(0xEC57E80A, out);
52+
}
53+
54+
uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) {
55+
furi_assert(crypto1);
56+
uint8_t out = crypto1_filter(crypto1->odd);
57+
uint32_t feed = out & (!!is_encrypted);
58+
feed ^= !!in;
59+
feed ^= LF_POLY_ODD & crypto1->odd;
60+
feed ^= LF_POLY_EVEN & crypto1->even;
61+
crypto1->even = crypto1->even << 1 | (nfc_util_even_parity32(feed));
62+
63+
FURI_SWAP(crypto1->odd, crypto1->even);
64+
return out;
65+
}
66+
67+
uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted) {
68+
furi_assert(crypto1);
69+
uint8_t out = 0;
70+
for(uint8_t i = 0; i < 8; i++) {
71+
out |= crypto1_bit(crypto1, FURI_BIT(in, i), is_encrypted) << i;
72+
}
73+
return out;
74+
}
75+
76+
uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted) {
77+
furi_assert(crypto1);
78+
uint32_t out = 0;
79+
for(uint8_t i = 0; i < 32; i++) {
80+
out |= (uint32_t)crypto1_bit(crypto1, BEBIT(in, i), is_encrypted) << (24 ^ i);
81+
}
82+
return out;
83+
}
84+
85+
uint32_t prng_successor(uint32_t x, uint32_t n) {
86+
SWAPENDIAN(x);
87+
while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
88+
89+
return SWAPENDIAN(x);
90+
}
91+
92+
void crypto1_decrypt(Crypto1* crypto, const BitBuffer* buff, BitBuffer* out) {
93+
furi_assert(crypto);
94+
furi_assert(buff);
95+
furi_assert(out);
96+
97+
size_t bits = bit_buffer_get_size(buff);
98+
bit_buffer_set_size(out, bits);
99+
const uint8_t* encrypted_data = bit_buffer_get_data(buff);
100+
if(bits < 8) {
101+
uint8_t decrypted_byte = 0;
102+
uint8_t encrypted_byte = encrypted_data[0];
103+
decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_byte, 0)) << 0;
104+
decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_byte, 1)) << 1;
105+
decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_byte, 2)) << 2;
106+
decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_byte, 3)) << 3;
107+
bit_buffer_set_byte(out, 0, decrypted_byte);
108+
} else {
109+
for(size_t i = 0; i < bits / 8; i++) {
110+
uint8_t decrypted_byte = crypto1_byte(crypto, 0, 0) ^ encrypted_data[i];
111+
bit_buffer_set_byte(out, i, decrypted_byte);
112+
}
113+
}
114+
}
115+
116+
void crypto1_encrypt(Crypto1* crypto, uint8_t* keystream, const BitBuffer* buff, BitBuffer* out) {
117+
furi_assert(crypto);
118+
furi_assert(buff);
119+
furi_assert(out);
120+
121+
size_t bits = bit_buffer_get_size(buff);
122+
bit_buffer_set_size(out, bits);
123+
const uint8_t* plain_data = bit_buffer_get_data(buff);
124+
if(bits < 8) {
125+
uint8_t encrypted_byte = 0;
126+
for(size_t i = 0; i < bits; i++) {
127+
encrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(plain_data[0], i)) << i;
128+
}
129+
bit_buffer_set_byte(out, 0, encrypted_byte);
130+
} else {
131+
for(size_t i = 0; i < bits / 8; i++) {
132+
uint8_t encrypted_byte = crypto1_byte(crypto, keystream ? keystream[i] : 0, 0) ^
133+
plain_data[i];
134+
bool parity_bit =
135+
((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(plain_data[i])) & 0x01);
136+
bit_buffer_set_byte_with_parity(out, i, encrypted_byte, parity_bit);
137+
}
138+
}
139+
}
140+
141+
void crypto1_encrypt_reader_nonce(
142+
Crypto1* crypto,
143+
uint64_t key,
144+
uint32_t cuid,
145+
uint8_t* nt,
146+
uint8_t* nr,
147+
BitBuffer* out,
148+
bool is_nested) {
149+
furi_assert(crypto);
150+
furi_assert(nt);
151+
furi_assert(nr);
152+
furi_assert(out);
153+
154+
bit_buffer_set_size_bytes(out, 8);
155+
uint32_t nt_num = bit_lib_bytes_to_num_be(nt, sizeof(uint32_t));
156+
157+
crypto1_init(crypto, key);
158+
if(is_nested) {
159+
nt_num = crypto1_word(crypto, nt_num ^ cuid, 1) ^ nt_num;
160+
} else {
161+
crypto1_word(crypto, nt_num ^ cuid, 0);
162+
}
163+
164+
for(size_t i = 0; i < 4; i++) {
165+
uint8_t byte = crypto1_byte(crypto, nr[i], 0) ^ nr[i];
166+
bool parity_bit = ((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(nr[i])) & 0x01);
167+
bit_buffer_set_byte_with_parity(out, i, byte, parity_bit);
168+
nr[i] = byte;
169+
}
170+
171+
nt_num = prng_successor(nt_num, 32);
172+
for(size_t i = 4; i < 8; i++) {
173+
nt_num = prng_successor(nt_num, 8);
174+
uint8_t byte = crypto1_byte(crypto, 0, 0) ^ (uint8_t)(nt_num);
175+
bool parity_bit = ((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(nt_num)) & 0x01);
176+
bit_buffer_set_byte_with_parity(out, i, byte, parity_bit);
177+
}
178+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#pragma once
2+
3+
#include <toolbox/bit_buffer.h>
4+
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
typedef struct {
10+
uint32_t odd;
11+
uint32_t even;
12+
} Crypto1;
13+
14+
Crypto1* crypto1_alloc();
15+
16+
void crypto1_free(Crypto1* instance);
17+
18+
void crypto1_reset(Crypto1* crypto1);
19+
20+
void crypto1_init(Crypto1* crypto1, uint64_t key);
21+
22+
uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted);
23+
24+
uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted);
25+
26+
uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted);
27+
28+
void crypto1_decrypt(Crypto1* crypto, const BitBuffer* buff, BitBuffer* out);
29+
30+
void crypto1_encrypt(Crypto1* crypto, uint8_t* keystream, const BitBuffer* buff, BitBuffer* out);
31+
32+
void crypto1_encrypt_reader_nonce(
33+
Crypto1* crypto,
34+
uint64_t key,
35+
uint32_t cuid,
36+
uint8_t* nt,
37+
uint8_t* nr,
38+
BitBuffer* out,
39+
bool is_nested);
40+
41+
uint32_t prng_successor(uint32_t x, uint32_t n);
42+
43+
#ifdef __cplusplus
44+
}
45+
#endif

0 commit comments

Comments
 (0)