10#ifndef M5_UNIT_UNIFIED_NFC_NFC_A_MIFARE_CLASSIC_CRYPTO1_HPP
11#define M5_UNIT_UNIFIED_NFC_NFC_A_MIFARE_CLASSIC_CRYPTO1_HPP
13#include <M5Utility.hpp>
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>;
47 void init(
const uint64_t key48)
noexcept
49 _state = state_type_t{};
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;
68 inline uint32_t
inject(uint32_t uid, uint32_t Nt,
const bool encrypted =
false) noexcept
70 return step32(uid ^ Nt, encrypted);
79 bool step_with(
const bool in,
const bool enc =
false) noexcept
85 const bool ext = in ^ (enc ? z : 0);
86 _state[0] = _state[0] ^ ext;
96 uint8_t
step8(
const uint8_t in,
const bool enc =
false) noexcept
99 for (uint_fast8_t i = 0; i < 8; ++i) {
111 uint32_t
step32(
const uint32_t in,
const bool enc =
false) noexcept
114 for (uint32_t i = 0; i < 32; ++i) {
115 bool t =
step_with((in >> (i ^ 24)) & 1u, enc);
128 uint8_t
encrypt(uint8_t buf[8],
const uint32_t Nr,
const uint32_t Ar)
noexcept
131 for (uint_fast8_t i = 0; i < 4; ++i) {
132 const uint8_t
v = ((Nr >> ((i ^ 0x03) << 3)) & 0xFF);
134 const uint8_t z =
filter();
135 parity |=
static_cast<uint8_t
>((z ^ m5::utility::oddParityBit(
v)) & 0x01) << i;
138 for (uint_fast8_t pos = 4; pos < 8; ++pos) {
139 const uint8_t i = pos - 4;
141 const uint8_t
v = (Ar >> (i << 3)) & 0xFF;
142 const uint8_t ks =
step8(0x00);
144 const uint8_t z =
filter();
145 parity |=
static_cast<uint8_t
>((z ^ m5::utility::oddParityBit(
v)) & 0x01) << pos;
157 uint32_t
encrypt(uint8_t* out,
const uint8_t* in,
const uint8_t in_len )
160 for (uint_fast8_t i = 0; i < in_len; ++i) {
161 uint8_t ks =
step8(0);
163 parity |= ((
filter() ^ m5::utility::oddParityBit(in[i])) & 1) << i;
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);
191 inline static bool fa(
bool a,
bool b,
bool c,
bool d)
noexcept
193 return ((
a ||
b) ^ (
a && d)) ^ (c && ((
a ^
b) || d));
204 inline static bool fb(
bool a,
bool b,
bool c,
bool d)
noexcept
206 return ((
a &&
b) || c) ^ ((
a ^
b) && (c || d));
218 inline static bool fc(
bool a,
bool b,
bool c,
bool d,
bool e)
noexcept
220 return (
a || ((
b || e) && (d ^ e))) ^ ((
a ^ (
b && d)) && ((c ^ d) || (
b && e)));
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
Top level namespace of M5Stack.