M5Unit-NFC 0.1.2 git rev:63c4caa
Loading...
Searching...
No Matches
mifare_classic_crypto1.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_UNIFIED_NFC_NFC_A_MIFARE_CLASSIC_CRYPTO1_HPP
11#define M5_UNIT_UNIFIED_NFC_NFC_A_MIFARE_CLASSIC_CRYPTO1_HPP
12
13#include <M5Utility.hpp>
14
15namespace m5 {
16namespace nfc {
17namespace a {
18namespace mifare {
19namespace classic {
20
22using MLFSR48 = m5::utility::FibonacciLFSR_Left<48, 5, 6, 7, 9, 13, 19, 21, 23, 24, 29, 31, 33, 34, 36, 38, 39, 43, 48>;
27class Crypto1 : public MLFSR48 {
28public:
30 Crypto1() noexcept : MLFSR48(0)
31 {
32 }
33
38 explicit Crypto1(const uint64_t key48) noexcept : MLFSR48(0)
39 {
40 init(key48);
41 }
42
47 void init(const uint64_t key48) noexcept
48 {
49 _state = state_type_t{};
50 // Change the bit order within the byte to LSB first
51 for (int i = 0; i < 48; ++i) {
52 int byte_index = i >> 3;
53 int bit_index = i & 0x07;
54 int reversed = (byte_index << 3) + (bit_index ^ 7);
55 bool bit = (key48 >> reversed) & 1ULL;
56 _state[i] = bit;
57 }
58 _count = 0;
59 }
60
68 inline uint32_t inject(uint32_t uid, uint32_t Nt, const bool encrypted = false) noexcept
69 {
70 return step32(uid ^ Nt, encrypted);
71 }
72
79 bool step_with(const bool in, const bool enc = false) noexcept
80 {
81 ++_count;
82
83 bool z = filter();
84 (void)step();
85 const bool ext = in ^ (enc ? z : 0);
86 _state[0] = _state[0] ^ ext;
87 return z;
88 }
89
96 uint8_t step8(const uint8_t in, const bool enc = false) noexcept
97 {
98 uint8_t v{};
99 for (uint_fast8_t i = 0; i < 8; ++i) {
100 v |= step_with((in >> i) & 1, enc) << i;
101 }
102 return v;
103 }
104
111 uint32_t step32(const uint32_t in, const bool enc = false) noexcept
112 {
113 uint32_t v{};
114 for (uint32_t i = 0; i < 32; ++i) {
115 bool t = step_with((in >> (i ^ 24)) & 1u, enc);
116 v |= t << (24 ^ i);
117 }
118 return v;
119 }
120
128 uint8_t encrypt(uint8_t buf[8], const uint32_t Nr, const uint32_t Ar) noexcept
129 {
130 uint8_t parity{};
131 for (uint_fast8_t i = 0; i < 4; ++i) {
132 const uint8_t v = ((Nr >> ((i ^ 0x03) << 3)) & 0xFF);
133 buf[i] = step8(v) ^ v;
134 const uint8_t z = filter();
135 parity |= static_cast<uint8_t>((z ^ m5::utility::oddParityBit(v)) & 0x01) << i;
136 }
137
138 for (uint_fast8_t pos = 4; pos < 8; ++pos) {
139 const uint8_t i = pos - 4;
140 // const uint8_t v = static_cast<uint8_t>(Ar >> (i << 3));
141 const uint8_t v = (Ar >> (i << 3)) & 0xFF;
142 const uint8_t ks = step8(0x00);
143 buf[pos] = ks ^ v;
144 const uint8_t z = filter();
145 parity |= static_cast<uint8_t>((z ^ m5::utility::oddParityBit(v)) & 0x01) << pos;
146 }
147 return parity;
148 }
149
157 uint32_t encrypt(uint8_t* out, const uint8_t* in, const uint8_t in_len /* max 32 */)
158 {
159 uint32_t parity{};
160 for (uint_fast8_t i = 0; i < in_len; ++i) {
161 uint8_t ks = step8(0);
162 out[i] = in[i] ^ ks;
163 parity |= ((filter() ^ m5::utility::oddParityBit(in[i])) & 1) << i;
164 }
165 return parity;
166 }
167
172 inline bool filter() const noexcept
173 {
174 const state_type_t& s = state();
175 const bool b5 = fb(s[6], s[4], s[2], s[0]);
176 const bool a4 = fa(s[14], s[12], s[10], s[8]);
177 const bool b3 = fb(s[22], s[20], s[18], s[16]);
178 const bool b2 = fb(s[30], s[28], s[26], s[24]);
179 const bool a1 = fa(s[38], s[36], s[34], s[32]);
180 return fc(a1, b2, b3, a4, b5);
181 }
182
191 inline static bool fa(bool a, bool b, bool c, bool d) noexcept
192 {
193 return ((a || b) ^ (a && d)) ^ (c && ((a ^ b) || d));
194 }
195
204 inline static bool fb(bool a, bool b, bool c, bool d) noexcept
205 {
206 return ((a && b) || c) ^ ((a ^ b) && (c || d));
207 }
208
218 inline static bool fc(bool a, bool b, bool c, bool d, bool e) noexcept
219 {
220 return (a || ((b || e) && (d ^ e))) ^ ((a ^ (b && d)) && ((c ^ d) || (b && e)));
221 }
222
223 uint32_t _count{}; // for debug
224};
225
226} // namespace classic
227} // namespace mifare
228} // namespace a
229} // namespace nfc
230} // namespace m5
231
232#endif
Crypto1 for MIFARE Classic.
Definition mifare_classic_crypto1.hpp:27
uint32_t encrypt(uint8_t *out, const uint8_t *in, const uint8_t in_len)
Encrypt a byte buffer.
Definition mifare_classic_crypto1.hpp:157
uint32_t inject(uint32_t uid, uint32_t Nt, const bool encrypted=false) noexcept
Inject UID and card nonce into the cipher state.
Definition mifare_classic_crypto1.hpp:68
static bool fc(bool a, bool b, bool c, bool d, bool e) noexcept
Crypto1 filter helper C.
Definition mifare_classic_crypto1.hpp:218
Crypto1() noexcept
Default ctor (zero-initialized state)
Definition mifare_classic_crypto1.hpp:30
bool step_with(const bool in, const bool enc=false) noexcept
Step the cipher with one input bit.
Definition mifare_classic_crypto1.hpp:79
uint32_t step32(const uint32_t in, const bool enc=false) noexcept
Step the cipher with 32 input bits.
Definition mifare_classic_crypto1.hpp:111
static bool fb(bool a, bool b, bool c, bool d) noexcept
Crypto1 filter helper B.
Definition mifare_classic_crypto1.hpp:204
Crypto1(const uint64_t key48) noexcept
Construct with 48-bit key.
Definition mifare_classic_crypto1.hpp:38
uint8_t step8(const uint8_t in, const bool enc=false) noexcept
Step the cipher with 8 input bits.
Definition mifare_classic_crypto1.hpp:96
bool filter() const noexcept
Crypto1 nonlinear filter.
Definition mifare_classic_crypto1.hpp:172
static bool fa(bool a, bool b, bool c, bool d) noexcept
Crypto1 filter helper A.
Definition mifare_classic_crypto1.hpp:191
void init(const uint64_t key48) noexcept
Initialize with 48-bit key.
Definition mifare_classic_crypto1.hpp:47
uint8_t encrypt(uint8_t buf[8], const uint32_t Nr, const uint32_t Ar) noexcept
Encrypt reader nonce and authenticator response.
Definition mifare_classic_crypto1.hpp:128
m5::utility::FibonacciLFSR_Left< 48, 5, 6, 7, 9, 13, 19, 21, 23, 24, 29, 31, 33, 34, 36, 38, 39, 43, 48 > MLFSR48
48-bit LFSR used by Crypto1
Definition mifare_classic_crypto1.hpp:22
NFC-A definitions.
NFC-B definitions.
For MIFARE classic.
Top level namespace of M5Stack.
For MIFARE.
NFC related definitions.
NFC-V definitions.