1+ #ifndef CRYPTO1_H
2+ #define CRYPTO1_H
3+
4+ #include <inttypes.h>
5+ #include "mfkey.h"
6+ #include <nfc/protocols/mf_classic/mf_classic.h>
7+
8+ #define LF_POLY_ODD (0x29CE5C)
9+ #define LF_POLY_EVEN (0x870804)
10+ #define BIT (x , n ) ((x) >> (n) & 1)
11+ #define BEBIT (x , n ) BIT(x, (n) ^ 24)
12+ #define SWAPENDIAN (x ) \
13+ ((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16)
14+
15+ static inline uint32_t prng_successor (uint32_t x , uint32_t n );
16+ static inline int filter (uint32_t const x );
17+ static inline uint8_t evenparity32 (uint32_t x );
18+ static inline void update_contribution (unsigned int data [], int item , int mask1 , int mask2 );
19+ void crypto1_get_lfsr (struct Crypto1State * state , MfClassicKey * lfsr );
20+ static inline uint32_t crypt_word (struct Crypto1State * s );
21+ static inline void crypt_word_noret (struct Crypto1State * s , uint32_t in , int x );
22+ static inline uint32_t crypt_word_ret (struct Crypto1State * s , uint32_t in , int x );
23+ static inline void rollback_word_noret (struct Crypto1State * s , uint32_t in , int x );
24+
25+ static const uint8_t lookup1 [256 ] = {
26+ 0 , 0 , 16 , 16 , 0 , 16 , 0 , 0 , 0 , 16 , 0 , 0 , 16 , 16 , 16 , 16 , 0 , 0 , 16 , 16 , 0 , 16 , 0 , 0 ,
27+ 0 , 16 , 0 , 0 , 16 , 16 , 16 , 16 , 0 , 0 , 16 , 16 , 0 , 16 , 0 , 0 , 0 , 16 , 0 , 0 , 16 , 16 , 16 , 16 ,
28+ 8 , 8 , 24 , 24 , 8 , 24 , 8 , 8 , 8 , 24 , 8 , 8 , 24 , 24 , 24 , 24 , 8 , 8 , 24 , 24 , 8 , 24 , 8 , 8 ,
29+ 8 , 24 , 8 , 8 , 24 , 24 , 24 , 24 , 8 , 8 , 24 , 24 , 8 , 24 , 8 , 8 , 8 , 24 , 8 , 8 , 24 , 24 , 24 , 24 ,
30+ 0 , 0 , 16 , 16 , 0 , 16 , 0 , 0 , 0 , 16 , 0 , 0 , 16 , 16 , 16 , 16 , 0 , 0 , 16 , 16 , 0 , 16 , 0 , 0 ,
31+ 0 , 16 , 0 , 0 , 16 , 16 , 16 , 16 , 8 , 8 , 24 , 24 , 8 , 24 , 8 , 8 , 8 , 24 , 8 , 8 , 24 , 24 , 24 , 24 ,
32+ 0 , 0 , 16 , 16 , 0 , 16 , 0 , 0 , 0 , 16 , 0 , 0 , 16 , 16 , 16 , 16 , 0 , 0 , 16 , 16 , 0 , 16 , 0 , 0 ,
33+ 0 , 16 , 0 , 0 , 16 , 16 , 16 , 16 , 8 , 8 , 24 , 24 , 8 , 24 , 8 , 8 , 8 , 24 , 8 , 8 , 24 , 24 , 24 , 24 ,
34+ 8 , 8 , 24 , 24 , 8 , 24 , 8 , 8 , 8 , 24 , 8 , 8 , 24 , 24 , 24 , 24 , 0 , 0 , 16 , 16 , 0 , 16 , 0 , 0 ,
35+ 0 , 16 , 0 , 0 , 16 , 16 , 16 , 16 , 8 , 8 , 24 , 24 , 8 , 24 , 8 , 8 , 8 , 24 , 8 , 8 , 24 , 24 , 24 , 24 ,
36+ 8 , 8 , 24 , 24 , 8 , 24 , 8 , 8 , 8 , 24 , 8 , 8 , 24 , 24 , 24 , 24 };
37+ static const uint8_t lookup2 [256 ] = {
38+ 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 ,
39+ 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 ,
40+ 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 ,
41+ 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 ,
42+ 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 ,
43+ 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 ,
44+ 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 ,
45+ 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 ,
46+ 2 , 6 , 2 , 2 , 6 , 6 , 6 , 6 , 2 , 2 , 6 , 6 , 2 , 6 , 2 , 2 , 2 , 6 , 2 , 2 , 6 , 6 , 6 , 6 };
47+
48+ static inline int filter (uint32_t const x ) {
49+ uint32_t f ;
50+ f = lookup1 [x & 0xff ] | lookup2 [(x >> 8 ) & 0xff ];
51+ f |= 0x0d938 >> (x >> 16 & 0xf ) & 1 ;
52+ return BIT (0xEC57E80A , f );
53+ }
54+
55+ #ifndef __ARM_ARCH_7EM__
56+ static inline uint8_t evenparity32 (uint32_t x ) {
57+ return __builtin_parity (x );
58+ }
59+ #endif
60+
61+ #ifdef __ARM_ARCH_7EM__
62+ static inline uint8_t evenparity32 (uint32_t x ) {
63+ uint32_t result ;
64+ __asm__ volatile ("eor r1, %[x], %[x], lsr #16 \n\t" // r1 = x ^ (x >> 16)
65+ "eor r1, r1, r1, lsr #8 \n\t" // r1 = r1 ^ (r1 >> 8)
66+ "eor r1, r1, r1, lsr #4 \n\t" // r1 = r1 ^ (r1 >> 4)
67+ "eor r1, r1, r1, lsr #2 \n\t" // r1 = r1 ^ (r1 >> 2)
68+ "eor r1, r1, r1, lsr #1 \n\t" // r1 = r1 ^ (r1 >> 1)
69+ "and %[result], r1, #1 \n\t" // result = r1 & 1
70+ : [result ] "=r" (result )
71+ : [x ] "r" (x )
72+ : "r1" );
73+ return result ;
74+ }
75+ #endif
76+
77+ static inline void update_contribution (unsigned int data [], int item , int mask1 , int mask2 ) {
78+ int p = data [item ] >> 25 ;
79+ p = p << 1 | evenparity32 (data [item ] & mask1 );
80+ p = p << 1 | evenparity32 (data [item ] & mask2 );
81+ data [item ] = p << 24 | (data [item ] & 0xffffff );
82+ }
83+
84+ static inline uint32_t crypt_word (struct Crypto1State * s ) {
85+ // "in" and "x" are always 0 (last iteration)
86+ uint32_t res_ret = 0 ;
87+ uint32_t feedin , t ;
88+ for (int i = 0 ; i <= 31 ; i ++ ) {
89+ res_ret |= (filter (s -> odd ) << (24 ^ i )); //-V629
90+ feedin = LF_POLY_EVEN & s -> even ;
91+ feedin ^= LF_POLY_ODD & s -> odd ;
92+ s -> even = s -> even << 1 | (evenparity32 (feedin ));
93+ t = s -> odd , s -> odd = s -> even , s -> even = t ;
94+ }
95+ return res_ret ;
96+ }
97+
98+ static inline void crypt_word_noret (struct Crypto1State * s , uint32_t in , int x ) {
99+ uint8_t ret ;
100+ uint32_t feedin , t , next_in ;
101+ for (int i = 0 ; i <= 31 ; i ++ ) {
102+ next_in = BEBIT (in , i );
103+ ret = filter (s -> odd );
104+ feedin = ret & (!!x );
105+ feedin ^= LF_POLY_EVEN & s -> even ;
106+ feedin ^= LF_POLY_ODD & s -> odd ;
107+ feedin ^= !!next_in ;
108+ s -> even = s -> even << 1 | (evenparity32 (feedin ));
109+ t = s -> odd , s -> odd = s -> even , s -> even = t ;
110+ }
111+ return ;
112+ }
113+
114+ static inline uint32_t crypt_word_ret (struct Crypto1State * s , uint32_t in , int x ) {
115+ uint32_t ret = 0 ;
116+ uint32_t feedin , t , next_in ;
117+ uint8_t next_ret ;
118+ for (int i = 0 ; i <= 31 ; i ++ ) {
119+ next_in = BEBIT (in , i );
120+ next_ret = filter (s -> odd );
121+ feedin = next_ret & (!!x );
122+ feedin ^= LF_POLY_EVEN & s -> even ;
123+ feedin ^= LF_POLY_ODD & s -> odd ;
124+ feedin ^= !!next_in ;
125+ s -> even = s -> even << 1 | (evenparity32 (feedin ));
126+ t = s -> odd , s -> odd = s -> even , s -> even = t ;
127+ ret |= next_ret << (24 ^ i );
128+ }
129+ return ret ;
130+ }
131+
132+ static inline void rollback_word_noret (struct Crypto1State * s , uint32_t in , int x ) {
133+ uint8_t ret ;
134+ uint32_t feedin , t , next_in ;
135+ for (int i = 31 ; i >= 0 ; i -- ) {
136+ next_in = BEBIT (in , i );
137+ s -> odd &= 0xffffff ;
138+ t = s -> odd , s -> odd = s -> even , s -> even = t ;
139+ ret = filter (s -> odd );
140+ feedin = ret & (!!x );
141+ feedin ^= s -> even & 1 ;
142+ feedin ^= LF_POLY_EVEN & (s -> even >>= 1 );
143+ feedin ^= LF_POLY_ODD & s -> odd ;
144+ feedin ^= !!next_in ;
145+ s -> even |= (evenparity32 (feedin )) << 23 ;
146+ }
147+ return ;
148+ }
149+
150+ static inline uint32_t prng_successor (uint32_t x , uint32_t n ) {
151+ SWAPENDIAN (x );
152+ while (n -- ) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21 ) << 31 ;
153+ return SWAPENDIAN (x );
154+ }
155+
156+ #endif // CRYPTO1_H
0 commit comments