forked from flipperdevices/flipperzero-firmware
-
-
Notifications
You must be signed in to change notification settings - Fork 545
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
1,632 additions
and
3,006 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#ifndef COMMON_H | ||
#define COMMON_H | ||
|
||
#include <inttypes.h> | ||
|
||
inline uint64_t napi_nfc_util_bytes2num(const uint8_t* src, uint8_t len); | ||
|
||
inline uint64_t napi_nfc_util_bytes2num(const uint8_t* src, uint8_t len) { | ||
furi_assert(src); | ||
furi_assert(len <= 8); | ||
|
||
uint64_t res = 0; | ||
while(len--) { | ||
res = (res << 8) | (*src); | ||
src++; | ||
} | ||
return res; | ||
} | ||
|
||
#endif // COMMON_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#pragma GCC optimize("O3") | ||
#pragma GCC optimize("-funroll-all-loops") | ||
|
||
#include <inttypes.h> | ||
#include "crypto1.h" | ||
#include "mfkey.h" | ||
|
||
#define BIT(x, n) ((x) >> (n) & 1) | ||
|
||
void crypto1_get_lfsr(struct Crypto1State* state, MfClassicKey* lfsr) { | ||
int i; | ||
uint64_t lfsr_value = 0; | ||
for(i = 23; i >= 0; --i) { | ||
lfsr_value = lfsr_value << 1 | BIT(state->odd, i ^ 3); | ||
lfsr_value = lfsr_value << 1 | BIT(state->even, i ^ 3); | ||
} | ||
|
||
// Assign the key value to the MfClassicKey struct | ||
for(i = 0; i < 6; ++i) { | ||
lfsr->data[i] = (lfsr_value >> ((5 - i) * 8)) & 0xFF; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
#ifndef CRYPTO1_H | ||
#define CRYPTO1_H | ||
|
||
#include <inttypes.h> | ||
#include "mfkey.h" | ||
#include <nfc/protocols/mf_classic/mf_classic.h> | ||
|
||
#define LF_POLY_ODD (0x29CE5C) | ||
#define LF_POLY_EVEN (0x870804) | ||
#define BIT(x, n) ((x) >> (n) & 1) | ||
#define BEBIT(x, n) BIT(x, (n) ^ 24) | ||
#define SWAPENDIAN(x) \ | ||
((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16) | ||
|
||
static inline uint32_t prng_successor(uint32_t x, uint32_t n); | ||
static inline int filter(uint32_t const x); | ||
static inline uint8_t evenparity32(uint32_t x); | ||
static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2); | ||
void crypto1_get_lfsr(struct Crypto1State* state, MfClassicKey* lfsr); | ||
static inline uint32_t crypt_word(struct Crypto1State* s); | ||
static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x); | ||
static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x); | ||
static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x); | ||
|
||
static const uint8_t lookup1[256] = { | ||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, | ||
0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, | ||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, | ||
8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, | ||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, | ||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, | ||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, | ||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, | ||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 0, 0, 16, 16, 0, 16, 0, 0, | ||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, | ||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24}; | ||
static const uint8_t lookup2[256] = { | ||
0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, | ||
4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, | ||
2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, | ||
2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, | ||
0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, | ||
2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, | ||
4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, | ||
2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, | ||
2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6}; | ||
|
||
static inline int filter(uint32_t const x) { | ||
uint32_t f; | ||
f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff]; | ||
f |= 0x0d938 >> (x >> 16 & 0xf) & 1; | ||
return BIT(0xEC57E80A, f); | ||
} | ||
|
||
#ifndef __ARM_ARCH_7EM__ | ||
static inline uint8_t evenparity32(uint32_t x) { | ||
return __builtin_parity(x); | ||
} | ||
#endif | ||
|
||
#ifdef __ARM_ARCH_7EM__ | ||
static inline uint8_t evenparity32(uint32_t x) { | ||
uint32_t result; | ||
__asm__ volatile("eor r1, %[x], %[x], lsr #16 \n\t" // r1 = x ^ (x >> 16) | ||
"eor r1, r1, r1, lsr #8 \n\t" // r1 = r1 ^ (r1 >> 8) | ||
"eor r1, r1, r1, lsr #4 \n\t" // r1 = r1 ^ (r1 >> 4) | ||
"eor r1, r1, r1, lsr #2 \n\t" // r1 = r1 ^ (r1 >> 2) | ||
"eor r1, r1, r1, lsr #1 \n\t" // r1 = r1 ^ (r1 >> 1) | ||
"and %[result], r1, #1 \n\t" // result = r1 & 1 | ||
: [result] "=r"(result) | ||
: [x] "r"(x) | ||
: "r1"); | ||
return result; | ||
} | ||
#endif | ||
|
||
static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2) { | ||
int p = data[item] >> 25; | ||
p = p << 1 | evenparity32(data[item] & mask1); | ||
p = p << 1 | evenparity32(data[item] & mask2); | ||
data[item] = p << 24 | (data[item] & 0xffffff); | ||
} | ||
|
||
static inline uint32_t crypt_word(struct Crypto1State* s) { | ||
// "in" and "x" are always 0 (last iteration) | ||
uint32_t res_ret = 0; | ||
uint32_t feedin, t; | ||
for(int i = 0; i <= 31; i++) { | ||
res_ret |= (filter(s->odd) << (24 ^ i)); //-V629 | ||
feedin = LF_POLY_EVEN & s->even; | ||
feedin ^= LF_POLY_ODD & s->odd; | ||
s->even = s->even << 1 | (evenparity32(feedin)); | ||
t = s->odd, s->odd = s->even, s->even = t; | ||
} | ||
return res_ret; | ||
} | ||
|
||
static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x) { | ||
uint8_t ret; | ||
uint32_t feedin, t, next_in; | ||
for(int i = 0; i <= 31; i++) { | ||
next_in = BEBIT(in, i); | ||
ret = filter(s->odd); | ||
feedin = ret & (!!x); | ||
feedin ^= LF_POLY_EVEN & s->even; | ||
feedin ^= LF_POLY_ODD & s->odd; | ||
feedin ^= !!next_in; | ||
s->even = s->even << 1 | (evenparity32(feedin)); | ||
t = s->odd, s->odd = s->even, s->even = t; | ||
} | ||
return; | ||
} | ||
|
||
static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x) { | ||
uint32_t ret = 0; | ||
uint32_t feedin, t, next_in; | ||
uint8_t next_ret; | ||
for(int i = 0; i <= 31; i++) { | ||
next_in = BEBIT(in, i); | ||
next_ret = filter(s->odd); | ||
feedin = next_ret & (!!x); | ||
feedin ^= LF_POLY_EVEN & s->even; | ||
feedin ^= LF_POLY_ODD & s->odd; | ||
feedin ^= !!next_in; | ||
s->even = s->even << 1 | (evenparity32(feedin)); | ||
t = s->odd, s->odd = s->even, s->even = t; | ||
ret |= next_ret << (24 ^ i); | ||
} | ||
return ret; | ||
} | ||
|
||
static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x) { | ||
uint8_t ret; | ||
uint32_t feedin, t, next_in; | ||
for(int i = 31; i >= 0; i--) { | ||
next_in = BEBIT(in, i); | ||
s->odd &= 0xffffff; | ||
t = s->odd, s->odd = s->even, s->even = t; | ||
ret = filter(s->odd); | ||
feedin = ret & (!!x); | ||
feedin ^= s->even & 1; | ||
feedin ^= LF_POLY_EVEN & (s->even >>= 1); | ||
feedin ^= LF_POLY_ODD & s->odd; | ||
feedin ^= !!next_in; | ||
s->even |= (evenparity32(feedin)) << 23; | ||
} | ||
return; | ||
} | ||
|
||
static inline uint32_t prng_successor(uint32_t x, uint32_t n) { | ||
SWAPENDIAN(x); | ||
while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; | ||
return SWAPENDIAN(x); | ||
} | ||
|
||
#endif // CRYPTO1_H |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.