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 return !__builtin_parity(x);
138 uint8_t
encrypt(uint8_t buf[8],
const uint32_t Nr,
const uint32_t Ar)
noexcept
141 for (uint_fast8_t i = 0; i < 4; ++i) {
142 const uint8_t
v = ((Nr >> ((i ^ 0x03) << 3)) & 0xFF);
144 const uint8_t z =
filter();
145 parity |=
static_cast<uint8_t
>((z ^
oddparity8(
v)) & 0x01) << i;
148 for (uint_fast8_t pos = 4; pos < 8; ++pos) {
149 const uint8_t i = pos - 4;
151 const uint8_t
v = (Ar >> (i << 3)) & 0xFF;
152 const uint8_t ks =
step8(0x00);
154 const uint8_t z =
filter();
155 parity |=
static_cast<uint8_t
>((z ^
oddparity8(
v)) & 0x01) << pos;
167 uint32_t
encrypt(uint8_t* out,
const uint8_t* in,
const uint8_t in_len )
170 for (uint_fast8_t i = 0; i < in_len; ++i) {
171 uint8_t ks =
step8(0);
184 const state_type_t& s = state();
185 const bool b5 =
fb(s[6], s[4], s[2], s[0]);
186 const bool a4 =
fa(s[14], s[12], s[10], s[8]);
187 const bool b3 =
fb(s[22], s[20], s[18], s[16]);
188 const bool b2 =
fb(s[30], s[28], s[26], s[24]);
189 const bool a1 =
fa(s[38], s[36], s[34], s[32]);
190 return fc(a1, b2, b3, a4, b5);
201 inline static bool fa(
bool a,
bool b,
bool c,
bool d)
noexcept
203 return ((
a ||
b) ^ (
a && d)) ^ (c && ((
a ^
b) || d));
214 inline static bool fb(
bool a,
bool b,
bool c,
bool d)
noexcept
216 return ((
a &&
b) || c) ^ ((
a ^
b) && (c || d));
228 inline static bool fc(
bool a,
bool b,
bool c,
bool d,
bool e)
noexcept
230 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:167
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:228
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:214
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:182
static bool fa(bool a, bool b, bool c, bool d) noexcept
Crypto1 filter helper A.
Definition mifare_classic_crypto1.hpp:201
static uint8_t oddparity8(uint8_t x) noexcept
Calculate odd parity for one byte.
Definition mifare_classic_crypto1.hpp:126
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:138
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.