1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
17 // tests for LRP here: Leakage Resilient Primitive (LRP) Specification, https://www.nxp.com/docs/en/application-note/AN12304.pdf
18 //-----------------------------------------------------------------------------
20 #include "desfiretest.h"
23 #include <string.h> // memcpy memset
24 #include "fileutils.h"
26 #include "crypto/libpcrypto.h"
27 #include "mifare/desfirecrypto.h"
28 #include "mifare/lrpcrypto.h"
30 static uint8_t CMACData
[] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
31 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
32 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
33 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51
37 static bool TestCRC16(void) {
38 uint8_t data
[] = {0x04, 0x44, 0x0F, 0x32, 0x76, 0x31, 0x80, 0x27, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
41 size_t len
= DesfireSearchCRCPos(data
, 16, 0x00, 2);
42 res
= res
&& (len
== 7);
44 len
= DesfireSearchCRCPos(data
, 7 + 2, 0x00, 2);
45 res
= res
&& (len
== 7);
47 len
= DesfireSearchCRCPos(data
, 7, 0x00, 2);
48 res
= res
&& (len
== 0);
50 len
= DesfireSearchCRCPos(data
, 3, 0x00, 2);
51 res
= res
&& (len
== 0);
53 len
= DesfireSearchCRCPos(data
, 1, 0x00, 2);
54 res
= res
&& (len
== 0);
56 PrintAndLogEx(INFO
, "CRC16............. ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
60 static bool TestCRC32(void) {
61 uint8_t data
[] = {0x04, 0x44, 0x0F, 0x32, 0x76, 0x31, 0x80, 0x99, 0xCE, 0x1A, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00};
64 size_t len
= DesfireSearchCRCPos(data
, 16, 0x00, 4);
65 res
= res
&& (len
== 7);
67 len
= DesfireSearchCRCPos(data
, 7 + 4, 0x00, 4);
68 res
= res
&& (len
== 7);
70 len
= DesfireSearchCRCPos(data
, 5, 0x00, 4);
71 res
= res
&& (len
== 0);
73 len
= DesfireSearchCRCPos(data
, 4, 0x00, 4);
74 res
= res
&& (len
== 0);
76 len
= DesfireSearchCRCPos(data
, 2, 0x00, 4);
77 res
= res
&& (len
== 0);
79 PrintAndLogEx(INFO
, "CRC32............. ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
83 // https://www.nxp.com/docs/en/application-note/AN10922.pdf
84 static bool TestCMACSubkeys(void) {
87 uint8_t key
[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
89 uint8_t sk1
[DESFIRE_MAX_CRYPTO_BLOCK_SIZE
] = {0};
90 uint8_t sk2
[DESFIRE_MAX_CRYPTO_BLOCK_SIZE
] = {0};
91 DesfireContext_t dctx
;
93 DesfireSetKey(&dctx
, 0, T_AES
, key
);
95 DesfireCMACGenerateSubkeys(&dctx
, DCOMainKey
, sk1
, sk2
);
97 uint8_t sk1test
[] = {0xFB, 0xC9, 0xF7, 0x5C, 0x94, 0x13, 0xC0, 0x41, 0xDF, 0xEE, 0x45, 0x2D, 0x3F, 0x07, 0x06, 0xD1};
98 uint8_t sk2test
[] = {0xF7, 0x93, 0xEE, 0xB9, 0x28, 0x27, 0x80, 0x83, 0xBF, 0xDC, 0x8A, 0x5A, 0x7E, 0x0E, 0x0D, 0x25};
100 res
= res
&& (memcmp(sk1
, sk1test
, sizeof(sk1test
)) == 0);
101 res
= res
&& (memcmp(sk2
, sk2test
, sizeof(sk2test
)) == 0);
104 DesfireSetKey(&dctx
, 0, T_3DES
, key
);
106 DesfireCMACGenerateSubkeys(&dctx
, DCOMainKey
, sk1
, sk2
);
108 uint8_t sk1_2tdea
[] = {0xF6, 0x12, 0xEB, 0x32, 0xE4, 0x60, 0x35, 0xF3};
109 uint8_t sk2_2tdea
[] = {0xEC, 0x25, 0xD6, 0x65, 0xC8, 0xC0, 0x6B, 0xFD};
111 res
= res
&& (memcmp(sk1
, sk1_2tdea
, sizeof(sk1_2tdea
)) == 0);
112 res
= res
&& (memcmp(sk2
, sk2_2tdea
, sizeof(sk2_2tdea
)) == 0);
115 uint8_t key3
[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
116 DesfireSetKey(&dctx
, 0, T_3K3DES
, key3
);
118 DesfireCMACGenerateSubkeys(&dctx
, DCOMainKey
, sk1
, sk2
);
120 uint8_t sk1_3tdea
[] = {0xA3, 0xED, 0x58, 0xF8, 0xE6, 0x94, 0x1B, 0xCA};
121 uint8_t sk2_3tdea
[] = {0x47, 0xDA, 0xB1, 0xF1, 0xCD, 0x28, 0x37, 0x8F};
123 res
= res
&& (memcmp(sk1
, sk1_3tdea
, sizeof(sk1_3tdea
)) == 0);
124 res
= res
&& (memcmp(sk2
, sk2_3tdea
, sizeof(sk2_3tdea
)) == 0);
126 PrintAndLogEx(INFO
, "CMAC subkeys...... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
130 // https://www.nxp.com/docs/en/application-note/AN10922.pdf
132 static bool TestAn10922KDFAES(void) {
135 uint8_t key
[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
137 DesfireContext_t dctx
;
138 DesfireSetKey(&dctx
, 0, T_AES
, key
);
140 uint8_t kdfInput
[] = {0x04, 0x78, 0x2E, 0x21, 0x80, 0x1D, 0x80, 0x30, 0x42, 0xF5, 0x4E, 0x58, 0x50, 0x20, 0x41, 0x62, 0x75};
141 MifareKdfAn10922(&dctx
, DCOMainKey
, kdfInput
, sizeof(kdfInput
));
143 uint8_t dkey
[] = {0xA8, 0xDD, 0x63, 0xA3, 0xB8, 0x9D, 0x54, 0xB3, 0x7C, 0xA8, 0x02, 0x47, 0x3F, 0xDA, 0x91, 0x75};
144 res
= res
&& (memcmp(dctx
.key
, dkey
, sizeof(dkey
)) == 0);
146 PrintAndLogEx(INFO
, "An10922 AES....... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
150 static bool TestAn10922KDF2TDEA(void) {
153 uint8_t key
[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
155 DesfireContext_t dctx
;
156 DesfireSetKey(&dctx
, 0, T_3DES
, key
);
158 uint8_t kdfInput
[] = {0x04, 0x78, 0x2E, 0x21, 0x80, 0x1D, 0x80, 0x30, 0x42, 0xF5, 0x4E, 0x58, 0x50, 0x20, 0x41};
159 MifareKdfAn10922(&dctx
, DCOMainKey
, kdfInput
, sizeof(kdfInput
));
161 uint8_t dkey
[] = {0x16, 0xF8, 0x59, 0x7C, 0x9E, 0x89, 0x10, 0xC8, 0x6B, 0x96, 0x48, 0xD0, 0x06, 0x10, 0x7D, 0xD7};
162 res
= res
&& (memcmp(dctx
.key
, dkey
, sizeof(dkey
)) == 0);
164 PrintAndLogEx(INFO
, "An10922 2TDEA..... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
168 static bool TestAn10922KDF3TDEA(void) {
171 uint8_t key
[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
173 DesfireContext_t dctx
;
174 DesfireSetKey(&dctx
, 0, T_3K3DES
, key
);
176 uint8_t kdfInput
[] = {0x04, 0x78, 0x2E, 0x21, 0x80, 0x1D, 0x80, 0x30, 0x42, 0xF5, 0x4E, 0x58, 0x50};
177 MifareKdfAn10922(&dctx
, DCOMainKey
, kdfInput
, sizeof(kdfInput
));
179 uint8_t dkey
[] = {0x2F, 0x0D, 0xD0, 0x36, 0x75, 0xD3, 0xFB, 0x9A, 0x57, 0x05, 0xAB, 0x0B, 0xDA, 0x91, 0xCA, 0x0B,
180 0x55, 0xB8, 0xE0, 0x7F, 0xCD, 0xBF, 0x10, 0xEC
182 res
= res
&& (memcmp(dctx
.key
, dkey
, sizeof(dkey
)) == 0);
184 PrintAndLogEx(INFO
, "An10922 3TDEA..... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
188 // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/TDES_CMAC.pdf
189 static bool TestCMAC3TDEA(void) {
192 uint8_t key
[DESFIRE_MAX_KEY_SIZE
] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
193 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
194 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
196 DesfireContext_t dctx
;
197 DesfireSetKey(&dctx
, 0, T_3K3DES
, key
);
198 memcpy(dctx
.sessionKeyMAC
, key
, DESFIRE_MAX_KEY_SIZE
);
199 uint8_t cmac
[DESFIRE_MAX_KEY_SIZE
] = {0};
201 uint8_t cmac1
[] = {0x7D, 0xB0, 0xD3, 0x7D, 0xF9, 0x36, 0xC5, 0x50};
202 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
203 DesfireCryptoCMAC(&dctx
, CMACData
, 0, cmac
);
204 res
= res
&& (memcmp(cmac
, cmac1
, sizeof(cmac1
)) == 0);
206 uint8_t cmac2
[] = {0x30, 0x23, 0x9C, 0xF1, 0xF5, 0x2E, 0x66, 0x09};
207 memset(cmac
, 0, sizeof(cmac
));
208 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
209 DesfireCryptoCMAC(&dctx
, CMACData
, 16, cmac
);
210 res
= res
&& (memcmp(cmac
, cmac2
, sizeof(cmac1
)) == 0);
212 uint8_t cmac3
[] = {0x6C, 0x9F, 0x3E, 0xE4, 0x92, 0x3F, 0x6B, 0xE2};
213 memset(cmac
, 0, sizeof(cmac
));
214 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
215 DesfireCryptoCMAC(&dctx
, CMACData
, 20, cmac
);
216 res
= res
&& (memcmp(cmac
, cmac3
, sizeof(cmac1
)) == 0);
218 uint8_t cmac4
[] = {0x99, 0x42, 0x9B, 0xD0, 0xBF, 0x79, 0x04, 0xE5};
219 memset(cmac
, 0, sizeof(cmac
));
220 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
221 DesfireCryptoCMAC(&dctx
, CMACData
, 32, cmac
);
222 res
= res
&& (memcmp(cmac
, cmac4
, sizeof(cmac1
)) == 0);
224 PrintAndLogEx(INFO
, "CMAC 3TDEA........ ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
228 // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/TDES_CMAC.pdf
229 static bool TestCMAC2TDEA(void) {
232 uint8_t key
[DESFIRE_MAX_KEY_SIZE
] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
233 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01
235 DesfireContext_t dctx
;
236 DesfireSetKey(&dctx
, 0, T_3DES
, key
);
237 memcpy(dctx
.sessionKeyMAC
, key
, DESFIRE_MAX_KEY_SIZE
);
238 uint8_t cmac
[DESFIRE_MAX_KEY_SIZE
] = {0};
240 uint8_t cmac1
[] = {0x79, 0xCE, 0x52, 0xA7, 0xF7, 0x86, 0xA9, 0x60};
241 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
242 DesfireCryptoCMAC(&dctx
, CMACData
, 0, cmac
);
243 // PrintAndLogEx(INFO, "cmac: %s", sprint_hex(cmac, 16));
244 res
= res
&& (memcmp(cmac
, cmac1
, sizeof(cmac1
)) == 0);
246 uint8_t cmac2
[] = {0xCC, 0x18, 0xA0, 0xB7, 0x9A, 0xF2, 0x41, 0x3B};
247 memset(cmac
, 0, sizeof(cmac
));
248 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
249 DesfireCryptoCMAC(&dctx
, CMACData
, 16, cmac
);
250 res
= res
&& (memcmp(cmac
, cmac2
, sizeof(cmac1
)) == 0);
252 uint8_t cmac3
[] = {0xC0, 0x6D, 0x37, 0x7E, 0xCD, 0x10, 0x19, 0x69};
253 memset(cmac
, 0, sizeof(cmac
));
254 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
255 DesfireCryptoCMAC(&dctx
, CMACData
, 20, cmac
);
256 res
= res
&& (memcmp(cmac
, cmac3
, sizeof(cmac1
)) == 0);
258 uint8_t cmac4
[] = {0x9C, 0xD3, 0x35, 0x80, 0xF9, 0xB6, 0x4D, 0xFB};
259 memset(cmac
, 0, sizeof(cmac
));
260 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
261 DesfireCryptoCMAC(&dctx
, CMACData
, 32, cmac
);
262 res
= res
&& (memcmp(cmac
, cmac4
, sizeof(cmac1
)) == 0);
264 PrintAndLogEx(INFO
, "CMAC 2TDEA........ ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
268 static bool TestCMACDES(void) {
271 uint8_t key
[DESFIRE_MAX_KEY_SIZE
] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
272 DesfireContext_t dctx
;
273 DesfireSetKey(&dctx
, 0, T_DES
, key
);
274 memcpy(dctx
.sessionKeyMAC
, key
, DESFIRE_MAX_KEY_SIZE
);
275 uint8_t cmac
[DESFIRE_MAX_KEY_SIZE
] = {0};
277 uint8_t cmac1
[] = {0x86, 0xF7, 0x9C, 0x13, 0xFD, 0x30, 0x6E, 0x67};
278 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
279 DesfireCryptoCMAC(&dctx
, CMACData
, 0, cmac
);
280 res
= res
&& (memcmp(cmac
, cmac1
, sizeof(cmac1
)) == 0);
282 uint8_t cmac2
[] = {0xBE, 0xA4, 0x21, 0x22, 0x92, 0x46, 0x2A, 0x85};
283 memset(cmac
, 0, sizeof(cmac
));
284 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
285 DesfireCryptoCMAC(&dctx
, CMACData
, 16, cmac
);
286 res
= res
&& (memcmp(cmac
, cmac2
, sizeof(cmac1
)) == 0);
288 uint8_t cmac3
[] = {0x3E, 0x2F, 0x83, 0x10, 0xC5, 0x69, 0x27, 0x5E};
289 memset(cmac
, 0, sizeof(cmac
));
290 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
291 DesfireCryptoCMAC(&dctx
, CMACData
, 20, cmac
);
292 res
= res
&& (memcmp(cmac
, cmac3
, sizeof(cmac1
)) == 0);
294 uint8_t cmac4
[] = {0x9D, 0x1F, 0xC4, 0xD4, 0xC0, 0x25, 0x91, 0x32};
295 memset(cmac
, 0, sizeof(cmac
));
296 memset(dctx
.IV
, 0, DESFIRE_MAX_KEY_SIZE
);
297 DesfireCryptoCMAC(&dctx
, CMACData
, 32, cmac
);
298 res
= res
&& (memcmp(cmac
, cmac4
, sizeof(cmac1
)) == 0);
300 PrintAndLogEx(INFO
, "CMAC DES.......... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
304 // https://www.nxp.com/docs/en/application-note/AN12343.pdf
306 static bool TestEV2SessionKeys(void) {
309 uint8_t key
[16] = {0};
310 uint8_t rnda
[] = {0xB0, 0x4D, 0x07, 0x87, 0xC9, 0x3E, 0xE0, 0xCC, 0x8C, 0xAC, 0xC8, 0xE8, 0x6F, 0x16, 0xC6, 0xFE};
311 uint8_t rndb
[] = {0xFA, 0x65, 0x9A, 0xD0, 0xDC, 0xA7, 0x38, 0xDD, 0x65, 0xDC, 0x7D, 0xC3, 0x86, 0x12, 0xAD, 0x81};
312 uint8_t sessionkeyauth
[] = {0x63, 0xDC, 0x07, 0x28, 0x62, 0x89, 0xA7, 0xA6, 0xC0, 0x33, 0x4C, 0xA3, 0x1C, 0x31, 0x4A, 0x04};
313 uint8_t sessionkeymac
[] = {0x77, 0x4F, 0x26, 0x74, 0x3E, 0xCE, 0x6A, 0xF5, 0x03, 0x3B, 0x6A, 0xE8, 0x52, 0x29, 0x46, 0xF6};
315 uint8_t sessionkey
[16] = {0};
316 DesfireGenSessionKeyEV2(key
, rnda
, rndb
, true, sessionkey
);
317 res
= res
&& (memcmp(sessionkey
, sessionkeyauth
, sizeof(sessionkeyauth
)) == 0);
319 memset(sessionkey
, 0, sizeof(sessionkey
));
320 DesfireGenSessionKeyEV2(key
, rnda
, rndb
, false, sessionkey
);
321 res
= res
&& (memcmp(sessionkey
, sessionkeymac
, sizeof(sessionkeymac
)) == 0);
323 PrintAndLogEx(INFO
, "EV2 session keys.. ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
327 static bool TestEV2IVEncode(void) {
330 uint8_t key
[] = {0x66, 0xA8, 0xCB, 0x93, 0x26, 0x9D, 0xC9, 0xBC, 0x28, 0x85, 0xB7, 0xA9, 0x1B, 0x9C, 0x69, 0x7B};
331 uint8_t ti
[] = {0xED, 0x56, 0xF6, 0xE6};
332 uint8_t ivres
[] = {0xDA, 0x0F, 0x64, 0x4A, 0x49, 0x86, 0x27, 0x59, 0x57, 0xCF, 0x1E, 0xC3, 0xAF, 0x4C, 0xCE, 0x53};
334 DesfireContext_t ctx
= {0};
336 memcpy(ctx
.sessionKeyEnc
, key
, 16);
337 memcpy(ctx
.TI
, ti
, 4);
340 uint8_t iv
[16] = {0};
341 DesfireEV2FillIV(&ctx
, true, iv
);
342 res
= res
&& (memcmp(iv
, ivres
, sizeof(ivres
)) == 0);
344 uint8_t key2
[] = {0x44, 0x5A, 0x86, 0x26, 0xB3, 0x33, 0x84, 0x59, 0x32, 0x12, 0x32, 0xfA, 0xDf, 0x6a, 0xDe, 0x2B};
345 uint8_t ti2
[] = {0x11, 0x22, 0x33, 0x44};
346 uint8_t ivres2
[] = {0x17, 0x74, 0x94, 0xFC, 0xC4, 0xF1, 0xDA, 0xB2, 0xAF, 0xBE, 0x8F, 0xAE, 0x20, 0x57, 0xA9, 0xD2};
347 memcpy(ctx
.sessionKeyEnc
, key2
, 16);
348 memcpy(ctx
.TI
, ti2
, 4);
352 DesfireEV2FillIV(&ctx
, true, iv
);
353 res
= res
&& (memcmp(iv
, ivres2
, sizeof(ivres2
)) == 0);
355 PrintAndLogEx(INFO
, "EV2 IV calc....... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
359 // https://www.nxp.com/docs/en/application-note/AN12343.pdf
361 static bool TestEV2MAC(void) {
364 uint8_t key
[] = {0x93, 0x66, 0xFA, 0x19, 0x5E, 0xB5, 0x66, 0xF5, 0xBD, 0x2B, 0xAD, 0x40, 0x20, 0xB8, 0x30, 0x02};
365 uint8_t ti
[] = {0xE2, 0xD3, 0xAF, 0x69};
367 uint8_t cmddata
[] = {0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
368 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
370 uint8_t macres
[] = {0x68, 0xF2, 0xC2, 0x8C, 0x57, 0x5A, 0x16, 0x28};
373 DesfireContext_t ctx
= {0};
375 memcpy(ctx
.sessionKeyMAC
, key
, 16);
376 memcpy(ctx
.TI
, ti
, 4);
380 uint8_t mac
[16] = {0};
381 DesfireEV2CalcCMAC(&ctx
, cmd
, cmddata
, sizeof(cmddata
), mac
);
382 res
= res
&& (memcmp(mac
, macres
, sizeof(macres
)) == 0);
385 memset(mac
, 0, sizeof(mac
));
386 uint8_t macres2
[] = {0x08, 0x20, 0xF6, 0x88, 0x98, 0xC2, 0xA7, 0xF1};
389 DesfireEV2CalcCMAC(&ctx
, rc
, NULL
, 0, mac
);
390 res
= res
&& (memcmp(mac
, macres2
, sizeof(macres2
)) == 0);
393 memset(mac
, 0, sizeof(mac
));
395 uint8_t cmddata3
[] = {0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00};
396 uint8_t macres3
[] = {0x0D, 0x9B, 0xE1, 0x91, 0xD5, 0x96, 0x08, 0x34};
397 DesfireEV2CalcCMAC(&ctx
, cmd
, cmddata3
, sizeof(cmddata3
), mac
);
398 res
= res
&& (memcmp(mac
, macres3
, sizeof(macres3
)) == 0);
403 uint8_t cmddata4
[] = {0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
404 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
407 uint8_t macres4
[] = {0xA4, 0x9A, 0x44, 0x22, 0x2D, 0x92, 0x66, 0x66};
408 DesfireEV2CalcCMAC(&ctx
, rc
, cmddata4
, sizeof(cmddata4
), mac
);
409 res
= res
&& (memcmp(mac
, macres4
, sizeof(macres4
)) == 0);
411 PrintAndLogEx(INFO
, "EV2 MAC calc...... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
415 static bool TestTransSessionKeys(void) {
417 uint8_t key
[] = {0x66, 0xA8, 0xCB, 0x93, 0x26, 0x9D, 0xC9, 0xBC, 0x28, 0x85, 0xB7, 0xA9, 0x1B, 0x9C, 0x69, 0x7B};
418 uint8_t uid
[] = {0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
421 uint8_t sessionkey
[16] = {0};
422 DesfireGenTransSessionKeyEV2(key
, trCntr
, uid
, true, sessionkey
);
423 uint8_t keymac
[] = {0x7C, 0x1A, 0xD2, 0xD9, 0xC5, 0xC0, 0x81, 0x54, 0xA0, 0xA4, 0x91, 0x4B, 0x40, 0x1A, 0x65, 0x98};
424 res
= res
&& (memcmp(sessionkey
, keymac
, sizeof(keymac
)) == 0);
426 DesfireGenTransSessionKeyEV2(key
, trCntr
, uid
, false, sessionkey
);
427 uint8_t keyenc
[] = {0x11, 0x9B, 0x90, 0x2A, 0x07, 0xB1, 0x8A, 0x86, 0x5B, 0x8E, 0x1B, 0x00, 0x60, 0x59, 0x47, 0x84};
428 res
= res
&& (memcmp(sessionkey
, keyenc
, sizeof(keyenc
)) == 0);
430 PrintAndLogEx(INFO
, "Trans session key. ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
434 // https://www.nxp.com/docs/en/application-note/AN12304.pdf
436 static bool TestLRPPlaintexts(void) {
439 uint8_t key
[] = {0x56, 0x78, 0x26, 0xB8, 0xDA, 0x8E, 0x76, 0x84, 0x32, 0xA9, 0x54, 0x8D, 0xBE, 0x4A, 0xA3, 0xA0};
440 LRPContext_t ctx
= {0};
441 LRPSetKey(&ctx
, key
, 0, false);
443 uint8_t pt0
[] = {0xAC, 0x20, 0xD3, 0x9F, 0x53, 0x41, 0xFE, 0x98, 0xDF, 0xCA, 0x21, 0xDA, 0x86, 0xBA, 0x79, 0x14};
444 res
= res
&& (memcmp(ctx
.plaintexts
[0], pt0
, sizeof(pt0
)) == 0);
446 uint8_t pt1
[] = {0x90, 0x7D, 0xA0, 0x3D, 0x67, 0x24, 0x49, 0x16, 0x69, 0x15, 0xE4, 0x56, 0x3E, 0x08, 0x9D, 0x6D};
447 res
= res
&& (memcmp(ctx
.plaintexts
[1], pt1
, sizeof(pt1
)) == 0);
449 uint8_t pt14
[] = {0x37, 0xD7, 0x34, 0xA5, 0x1C, 0x07, 0x6E, 0xB8, 0x03, 0xBD, 0x53, 0x0E, 0x17, 0xEB, 0x87, 0xDC};
450 res
= res
&& (memcmp(ctx
.plaintexts
[14], pt14
, sizeof(pt14
)) == 0);
452 uint8_t pt15
[] = {0x71, 0xB4, 0x44, 0xAF, 0x25, 0x7A, 0x93, 0x21, 0x53, 0x11, 0xD7, 0x58, 0xDD, 0x33, 0x32, 0x47};
453 res
= res
&& (memcmp(ctx
.plaintexts
[15], pt15
, sizeof(pt15
)) == 0);
455 PrintAndLogEx(INFO
, "LRP plaintexts.... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
459 // https://www.nxp.com/docs/en/application-note/AN12304.pdf
461 static bool TestLRPUpdatedKeys(void) {
464 uint8_t key
[] = {0x56, 0x78, 0x26, 0xB8, 0xDA, 0x8E, 0x76, 0x84, 0x32, 0xA9, 0x54, 0x8D, 0xBE, 0x4A, 0xA3, 0xA0};
465 LRPContext_t ctx
= {0};
466 LRPSetKey(&ctx
, key
, 0, false);
468 uint8_t key0
[] = {0x16, 0x3D, 0x14, 0xED, 0x24, 0xED, 0x93, 0x53, 0x73, 0x56, 0x8E, 0xC5, 0x21, 0xE9, 0x6C, 0xF4};
469 res
= res
&& (memcmp(ctx
.updatedKeys
[0], key0
, sizeof(key0
)) == 0);
471 uint8_t key1
[] = {0x1C, 0x51, 0x9C, 0x00, 0x02, 0x08, 0xB9, 0x5A, 0x39, 0xA6, 0x5D, 0xB0, 0x58, 0x32, 0x71, 0x88};
472 res
= res
&& (memcmp(ctx
.updatedKeys
[1], key1
, sizeof(key1
)) == 0);
474 uint8_t key2
[] = {0xFE, 0x30, 0xAB, 0x50, 0x46, 0x7E, 0x61, 0x78, 0x3B, 0xFE, 0x6B, 0x5E, 0x05, 0x60, 0x16, 0x0E};
475 res
= res
&& (memcmp(ctx
.updatedKeys
[2], key2
, sizeof(key2
)) == 0);
477 PrintAndLogEx(INFO
, "LRP updated keys.. ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
481 // https://www.nxp.com/docs/en/application-note/AN12304.pdf
482 // 3.2 LRP Eval, page 13
483 static bool TestLRPEval(void) {
486 LRPContext_t ctx
= {0};
488 uint8_t y
[CRYPTO_AES128_KEY_SIZE
] = {0};
489 uint8_t key
[] = {0x56, 0x78, 0x26, 0xB8, 0xDA, 0x8E, 0x76, 0x84, 0x32, 0xA9, 0x54, 0x8D, 0xBE, 0x4A, 0xA3, 0xA0};
490 uint8_t iv
[] = {0x13, 0x59};
491 LRPSetKey(&ctx
, key
, 2, false);
492 LRPEvalLRP(&ctx
, iv
, sizeof(iv
) * 2, true, y
);
494 uint8_t y1
[] = {0x1B, 0xA2, 0xC0, 0xC5, 0x78, 0x99, 0x6B, 0xC4, 0x97, 0xDD, 0x18, 0x1C, 0x68, 0x85, 0xA9, 0xDD};
495 res
= res
&& (memcmp(y
, y1
, sizeof(y1
)) == 0);
497 uint8_t key2
[] = {0xB6, 0x55, 0x57, 0xCE, 0x0E, 0x9B, 0x4C, 0x58, 0x86, 0xF2, 0x32, 0x20, 0x01, 0x13, 0x56, 0x2B};
498 uint8_t iv2
[] = {0xBB, 0x4F, 0xCF, 0x27, 0xC9, 0x40, 0x76, 0xF7, 0x56, 0xAB, 0x03, 0x0D};
499 LRPSetKey(&ctx
, key2
, 1, false);
500 LRPEvalLRP(&ctx
, iv2
, sizeof(iv2
) * 2, false, y
);
502 uint8_t y2
[] = {0x6F, 0xDF, 0xA8, 0xD2, 0xA6, 0xAA, 0x84, 0x76, 0xBF, 0x94, 0xE7, 0x1F, 0x25, 0x63, 0x7F, 0x96};
503 res
= res
&& (memcmp(y
, y2
, sizeof(y2
)) == 0);
505 uint8_t key3
[] = {0xC4, 0x8A, 0x8E, 0x8B, 0x16, 0x57, 0x16, 0x45, 0xA1, 0x55, 0x78, 0x25, 0xAA, 0x66, 0xAC, 0x91};
506 uint8_t iv3
[] = {0x1F, 0x0B, 0x7C, 0x0D, 0xB1, 0x28, 0x89, 0xCA, 0x43, 0x6C, 0xAB, 0xB7, 0x8B, 0xE4, 0x2F, 0x90};
507 LRPSetKey(&ctx
, key3
, 3, false);
508 LRPEvalLRP(&ctx
, iv3
, sizeof(iv3
) * 2 - 1, true, y
);
510 uint8_t y3
[] = {0x51, 0x29, 0x6B, 0x5E, 0x6D, 0x3B, 0x8D, 0xB8, 0xA1, 0xA7, 0x39, 0x97, 0x60, 0xA1, 0x91, 0x89};
511 res
= res
&& (memcmp(y
, y3
, sizeof(y3
)) == 0);
513 uint8_t key4
[] = {0x54, 0x9C, 0x67, 0xEC, 0xD6, 0x0E, 0x84, 0x8F, 0x77, 0x39, 0x90, 0x99, 0x0C, 0xAC, 0x68, 0x1E};
514 uint8_t iv4
[] = {0x47, 0x5B, 0xB4, 0x18, 0x78, 0xEB, 0x17, 0x46, 0x8F, 0x7A, 0x68, 0x84, 0x7D, 0xDD, 0x3B, 0xAC};
515 LRPSetKey(&ctx
, key4
, 3, false);
516 LRPEvalLRP(&ctx
, iv4
, sizeof(iv4
) * 2, true, y
);
518 uint8_t y4
[] = {0xC3, 0xB5, 0xEE, 0x74, 0xA7, 0x22, 0xE7, 0x84, 0x88, 0x7C, 0x4C, 0x9F, 0xDB, 0x49, 0x78, 0x55};
519 res
= res
&& (memcmp(y
, y4
, sizeof(y4
)) == 0);
521 uint8_t key5
[] = {0x80, 0x6A, 0x50, 0x53, 0x0D, 0x77, 0x35, 0xB4, 0x0A, 0xC4, 0xEF, 0x16, 0x38, 0xE8, 0xAD, 0x6A};
522 uint8_t iv5
[] = {0xD4, 0x13, 0x77, 0x64, 0x71, 0x6D, 0xBC, 0x8C, 0x57, 0x9B, 0xEA, 0xB7, 0xE7, 0x67, 0x54, 0xE0};
523 LRPSetKey(&ctx
, key5
, 3, false);
524 LRPEvalLRP(&ctx
, iv5
, sizeof(iv5
) * 2 - 1, false, y
);
526 uint8_t y5
[] = {0xCF, 0x99, 0x13, 0x92, 0xF0, 0x36, 0x93, 0x50, 0xA7, 0xE2, 0x1B, 0xE5, 0x2F, 0x74, 0x88, 0x21};
527 res
= res
&& (memcmp(y
, y5
, sizeof(y5
)) == 0);
529 PrintAndLogEx(INFO
, "LRP eval.......... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
533 static bool TestLRPIncCounter(void) {
536 uint8_t ctr1
[] = {0x00, 0x01};
537 LRPIncCounter(ctr1
, 4);
538 uint8_t ctrr1
[] = {0x00, 0x02};
539 res
= res
&& (memcmp(ctr1
, ctrr1
, sizeof(ctrr1
)) == 0);
541 uint8_t ctr2
[] = {0x00, 0xf0};
542 LRPIncCounter(ctr2
, 3);
543 uint8_t ctrr2
[] = {0x01, 0x00};
544 res
= res
&& (memcmp(ctr2
, ctrr2
, sizeof(ctrr2
)) == 0);
546 uint8_t ctr3
[] = {0xff, 0xf0};
547 LRPIncCounter(ctr3
, 3);
548 uint8_t ctrr3
[] = {0x00, 0x00};
549 res
= res
&& (memcmp(ctr3
, ctrr3
, sizeof(ctrr3
)) == 0);
551 uint8_t ctr4
[] = {0xf0};
552 LRPIncCounter(ctr4
, 1);
553 uint8_t ctrr4
[] = {0x00};
554 res
= res
&& (memcmp(ctr4
, ctrr4
, sizeof(ctrr4
)) == 0);
556 PrintAndLogEx(INFO
, "LRP inc counter... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
560 static bool TestLRPEncode(void) {
563 uint8_t resp
[100] = {0};
566 LRPContext_t ctx
= {0};
568 uint8_t key1
[] = {0xE0, 0xC4, 0x93, 0x5F, 0xF0, 0xC2, 0x54, 0xCD, 0x2C, 0xEF, 0x8F, 0xDD, 0xC3, 0x24, 0x60, 0xCF};
569 uint8_t iv1
[] = {0xC3, 0x31, 0x5D, 0xBF};
570 LRPSetKeyEx(&ctx
, key1
, iv1
, sizeof(iv1
) * 2, 0, true);
571 uint8_t data1
[] = {0x01, 0x2D, 0x7F, 0x16, 0x53, 0xCA, 0xF6, 0x50, 0x3C, 0x6A, 0xB0, 0xC1, 0x01, 0x0E, 0x8C, 0xB0};
572 LRPEncode(&ctx
, data1
, sizeof(data1
), resp
, &resplen
);
573 uint8_t res1
[] = {0xFC, 0xBB, 0xAC, 0xAA, 0x4F, 0x29, 0x18, 0x24, 0x64, 0xF9, 0x9D, 0xE4, 0x10, 0x85, 0x26, 0x6F,
574 0x48, 0x0E, 0x86, 0x3E, 0x48, 0x7B, 0xAA, 0xF6, 0x87, 0xB4, 0x3E, 0xD1, 0xEC, 0xE0, 0xD6, 0x23
576 res
= res
&& (resplen
== sizeof(res1
));
577 res
= res
&& (memcmp(resp
, res1
, sizeof(res1
)) == 0);
579 uint8_t key2
[] = {0xEF, 0xA5, 0xB7, 0x42, 0x9C, 0xD1, 0x53, 0xBF, 0x00, 0x86, 0xDE, 0xF9, 0x00, 0xC0, 0xF2, 0x35};
580 uint8_t iv2
[] = {0x90, 0x36, 0xFF, 0xFF};
581 LRPSetKeyEx(&ctx
, key2
, iv2
, sizeof(iv2
) * 2, 0, false);
582 uint8_t data2
[] = {0xE7, 0xF6, 0x1E, 0x01, 0x2F, 0x4F, 0x32, 0x55, 0x31, 0x2B, 0xA6, 0x8B, 0x1D, 0x2F, 0xDA, 0xBF};
583 LRPEncode(&ctx
, data2
, sizeof(data2
), resp
, &resplen
);
584 uint8_t res2
[] = {0xEA, 0x6E, 0x09, 0xAC, 0x2F, 0xB9, 0x7E, 0x10, 0x2D, 0x8C, 0xA6, 0x4C, 0x1C, 0xBC, 0x0C, 0x0C};
585 res
= res
&& (resplen
== sizeof(res2
));
586 res
= res
&& (memcmp(resp
, res2
, sizeof(res2
)) == 0);
588 uint8_t key3
[] = {0x9D, 0x81, 0x31, 0x34, 0xCF, 0xDE, 0xE9, 0xD5, 0x87, 0x55, 0xDE, 0xAC, 0xD4, 0xAF, 0x72, 0xA7};
589 uint8_t iv3
[] = {0xFF, 0xFF, 0xFF, 0xFF};
590 LRPSetKeyEx(&ctx
, key3
, iv3
, sizeof(iv3
) * 2, 0, true);
591 uint8_t data3
[] = {0x27};
592 LRPEncode(&ctx
, data3
, sizeof(data3
), resp
, &resplen
);
593 uint8_t res3
[] = {0xF5, 0x83, 0x3F, 0xC3, 0x97, 0x35, 0x6E, 0xA3, 0xD9, 0xEC, 0xAD, 0xBB, 0x9F, 0x6F, 0xE4, 0x40};
594 res
= res
&& (resplen
== sizeof(res3
));
595 res
= res
&& (memcmp(resp
, res3
, sizeof(res3
)) == 0);
597 uint8_t key4
[] = {0xF5, 0xC3, 0xE9, 0x9F, 0xB7, 0x5E, 0x31, 0x6B, 0x76, 0x68, 0x9F, 0xC5, 0x46, 0x42, 0x60, 0xCD};
598 uint8_t iv4
[] = {0x07, 0x97, 0xF6, 0xB7};
599 LRPSetKeyEx(&ctx
, key4
, iv4
, sizeof(iv4
) * 2, 0, true);
600 LRPEncode(&ctx
, NULL
, 0, resp
, &resplen
);
601 uint8_t res4
[] = {0x93, 0xDC, 0x3E, 0xE1, 0x4B, 0x61, 0x2B, 0xE6, 0xA3, 0xE9, 0xE2, 0xE8, 0x04, 0x0C, 0xDF, 0xCB};
602 res
= res
&& (resplen
== sizeof(res4
));
603 res
= res
&& (memcmp(resp
, res4
, sizeof(res4
)) == 0);
605 uint8_t key5
[] = {0x9B, 0x1E, 0x41, 0x8D, 0xF9, 0x75, 0x2F, 0x37, 0xEB, 0xBD, 0x8E, 0xE8, 0x33, 0xBD, 0xF2, 0xD7};
606 uint8_t iv5
[] = {0x24, 0xFF, 0xFF, 0xFF};
607 LRPSetKeyEx(&ctx
, key5
, iv5
, sizeof(iv5
) * 2, 0, true);
608 uint8_t data5
[] = {0x55, 0x53, 0x4E, 0x15, 0x9F, 0x14, 0xDD, 0x77, 0x31, 0x36, 0x89, 0x88, 0xEE, 0x6D, 0xD7, 0xC6,
609 0x11, 0x4E, 0x74, 0x7F, 0x9C, 0x17, 0xA9, 0x1B, 0xBC, 0x12, 0xD6, 0x8C, 0x26, 0x53, 0x1F, 0x2F,
612 LRPEncode(&ctx
, data5
, sizeof(data5
), resp
, &resplen
);
613 uint8_t res5
[] = {0x15, 0x8B, 0x3B, 0x9C, 0x61, 0x36, 0xFB, 0x71, 0x5C, 0xCF, 0x43, 0x5C, 0xA4, 0xCA, 0xDE, 0x80,
614 0x8D, 0x1F, 0x98, 0x43, 0x13, 0x27, 0x06, 0x1A, 0x9A, 0x64, 0xD5, 0x2A, 0x5F, 0xE7, 0xB2, 0x74,
615 0x6D, 0x7F, 0x5A, 0x63, 0x3F, 0xC0, 0xCF, 0xE7, 0x85, 0x56, 0x56, 0xAD, 0x3C, 0x6B, 0x94, 0xCF
617 res
= res
&& (resplen
== sizeof(res5
));
618 res
= res
&& (memcmp(resp
, res5
, sizeof(res5
)) == 0);
620 PrintAndLogEx(INFO
, "LRP encode........ ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
624 static bool TestLRPDecode(void) {
627 uint8_t resp
[100] = {0};
630 LRPContext_t ctx
= {0};
632 uint8_t key1
[] = {0xE0, 0xC4, 0x93, 0x5F, 0xF0, 0xC2, 0x54, 0xCD, 0x2C, 0xEF, 0x8F, 0xDD, 0xC3, 0x24, 0x60, 0xCF};
633 uint8_t iv1
[] = {0xC3, 0x31, 0x5D, 0xBF};
634 LRPSetKeyEx(&ctx
, key1
, iv1
, sizeof(iv1
) * 2, 0, true);
635 uint8_t data1
[] = {0xFC, 0xBB, 0xAC, 0xAA, 0x4F, 0x29, 0x18, 0x24, 0x64, 0xF9, 0x9D, 0xE4, 0x10, 0x85, 0x26, 0x6F,
636 0x48, 0x0E, 0x86, 0x3E, 0x48, 0x7B, 0xAA, 0xF6, 0x87, 0xB4, 0x3E, 0xD1, 0xEC, 0xE0, 0xD6, 0x23
638 LRPDecode(&ctx
, data1
, sizeof(data1
), resp
, &resplen
);
639 uint8_t res1
[] = {0x01, 0x2D, 0x7F, 0x16, 0x53, 0xCA, 0xF6, 0x50, 0x3C, 0x6A, 0xB0, 0xC1, 0x01, 0x0E, 0x8C, 0xB0};
640 res
= res
&& (resplen
== sizeof(res1
));
641 res
= res
&& (memcmp(resp
, res1
, sizeof(res1
)) == 0);
643 uint8_t key2
[] = {0xEF, 0xA5, 0xB7, 0x42, 0x9C, 0xD1, 0x53, 0xBF, 0x00, 0x86, 0xDE, 0xF9, 0x00, 0xC0, 0xF2, 0x35};
644 uint8_t iv2
[] = {0x90, 0x36, 0xFF, 0xFF};
645 LRPSetKeyEx(&ctx
, key2
, iv2
, sizeof(iv2
) * 2, 0, false);
646 uint8_t data2
[] = {0xEA, 0x6E, 0x09, 0xAC, 0x2F, 0xB9, 0x7E, 0x10, 0x2D, 0x8C, 0xA6, 0x4C, 0x1C, 0xBC, 0x0C, 0x0C};
647 LRPDecode(&ctx
, data2
, sizeof(data2
), resp
, &resplen
);
648 uint8_t res2
[] = {0xE7, 0xF6, 0x1E, 0x01, 0x2F, 0x4F, 0x32, 0x55, 0x31, 0x2B, 0xA6, 0x8B, 0x1D, 0x2F, 0xDA, 0xBF};
649 res
= res
&& (resplen
== sizeof(res2
));
650 res
= res
&& (memcmp(resp
, res2
, sizeof(res2
)) == 0);
652 uint8_t key3
[] = {0x9D, 0x81, 0x31, 0x34, 0xCF, 0xDE, 0xE9, 0xD5, 0x87, 0x55, 0xDE, 0xAC, 0xD4, 0xAF, 0x72, 0xA7};
653 uint8_t iv3
[] = {0xFF, 0xFF, 0xFF, 0xFF};
654 LRPSetKeyEx(&ctx
, key3
, iv3
, sizeof(iv3
) * 2, 0, true);
655 uint8_t data3
[] = {0xF5, 0x83, 0x3F, 0xC3, 0x97, 0x35, 0x6E, 0xA3, 0xD9, 0xEC, 0xAD, 0xBB, 0x9F, 0x6F, 0xE4, 0x40};
656 LRPDecode(&ctx
, data3
, sizeof(data3
), resp
, &resplen
);
657 uint8_t res3
[] = {0x27};
658 res
= res
&& (resplen
== sizeof(res3
));
659 res
= res
&& (memcmp(resp
, res3
, sizeof(res3
)) == 0);
661 uint8_t key4
[] = {0xF5, 0xC3, 0xE9, 0x9F, 0xB7, 0x5E, 0x31, 0x6B, 0x76, 0x68, 0x9F, 0xC5, 0x46, 0x42, 0x60, 0xCD};
662 uint8_t iv4
[] = {0x07, 0x97, 0xF6, 0xB7};
663 LRPSetKeyEx(&ctx
, key4
, iv4
, sizeof(iv4
) * 2, 0, true);
664 uint8_t data4
[] = {0x93, 0xDC, 0x3E, 0xE1, 0x4B, 0x61, 0x2B, 0xE6, 0xA3, 0xE9, 0xE2, 0xE8, 0x04, 0x0C, 0xDF, 0xCB};
665 LRPDecode(&ctx
, data4
, sizeof(data4
), resp
, &resplen
);
666 res
= res
&& (resplen
== 0);
668 uint8_t key5
[] = {0x9B, 0x1E, 0x41, 0x8D, 0xF9, 0x75, 0x2F, 0x37, 0xEB, 0xBD, 0x8E, 0xE8, 0x33, 0xBD, 0xF2, 0xD7};
669 uint8_t iv5
[] = {0x24, 0xFF, 0xFF, 0xFF};
670 LRPSetKeyEx(&ctx
, key5
, iv5
, sizeof(iv5
) * 2, 0, true);
671 uint8_t data5
[] = {0x15, 0x8B, 0x3B, 0x9C, 0x61, 0x36, 0xFB, 0x71, 0x5C, 0xCF, 0x43, 0x5C, 0xA4, 0xCA, 0xDE, 0x80,
672 0x8D, 0x1F, 0x98, 0x43, 0x13, 0x27, 0x06, 0x1A, 0x9A, 0x64, 0xD5, 0x2A, 0x5F, 0xE7, 0xB2, 0x74,
673 0x6D, 0x7F, 0x5A, 0x63, 0x3F, 0xC0, 0xCF, 0xE7, 0x85, 0x56, 0x56, 0xAD, 0x3C, 0x6B, 0x94, 0xCF
675 LRPDecode(&ctx
, data5
, sizeof(data5
), resp
, &resplen
);
676 uint8_t res5
[] = {0x55, 0x53, 0x4E, 0x15, 0x9F, 0x14, 0xDD, 0x77, 0x31, 0x36, 0x89, 0x88, 0xEE, 0x6D, 0xD7, 0xC6,
677 0x11, 0x4E, 0x74, 0x7F, 0x9C, 0x17, 0xA9, 0x1B, 0xBC, 0x12, 0xD6, 0x8C, 0x26, 0x53, 0x1F, 0x2F,
680 res
= res
&& (resplen
== sizeof(res5
));
681 res
= res
&& (memcmp(resp
, res5
, sizeof(res5
)) == 0);
683 PrintAndLogEx(INFO
, "LRP decode........ ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
687 // https://www.nxp.com/docs/en/application-note/AN12304.pdf
689 static bool TestLRPSubkeys(void) {
692 uint8_t sk1
[CRYPTO_AES128_KEY_SIZE
] = {0};
693 uint8_t sk2
[CRYPTO_AES128_KEY_SIZE
] = {0};
695 uint8_t key1
[] = {0x81, 0x95, 0x08, 0x8C, 0xE6, 0xC3, 0x93, 0x70, 0x8E, 0xBB, 0xE6, 0xC7, 0x91, 0x4E, 0xCB, 0x0B};
696 uint8_t sk1r1
[] = {0x16, 0x91, 0x2B, 0x8D, 0x19, 0xD9, 0x4B, 0x2D, 0x4D, 0xA4, 0xFF, 0xA1, 0xCA, 0xD2, 0x18, 0x23};
697 uint8_t sk2r1
[] = {0x2D, 0x22, 0x57, 0x1A, 0x33, 0xB2, 0x96, 0x5A, 0x9B, 0x49, 0xFF, 0x43, 0x95, 0xA4, 0x30, 0x46};
699 LRPGenSubkeys(key1
, sk1
, sk2
);
700 res
= res
&& (memcmp(sk1
, sk1r1
, sizeof(sk1r1
)) == 0);
701 res
= res
&& (memcmp(sk2
, sk2r1
, sizeof(sk2r1
)) == 0);
703 uint8_t key2
[] = {0x11, 0xED, 0x02, 0x02, 0x25, 0x70, 0xCB, 0x10, 0x50, 0x2B, 0xC1, 0xDA, 0xCF, 0x64, 0xB2, 0x1F};
704 uint8_t sk1r2
[] = {0x5B, 0x5D, 0x85, 0x36, 0x61, 0xE5, 0x1B, 0xC9, 0x13, 0x77, 0xED, 0xCE, 0xB6, 0x22, 0xBF, 0x6E};
705 uint8_t sk2r2
[] = {0xB6, 0xBB, 0x0A, 0x6C, 0xC3, 0xCA, 0x37, 0x92, 0x26, 0xEF, 0xDB, 0x9D, 0x6C, 0x45, 0x7E, 0xDC};
707 LRPGenSubkeys(key2
, sk1
, sk2
);
708 res
= res
&& (memcmp(sk1
, sk1r2
, sizeof(sk1r2
)) == 0);
709 res
= res
&& (memcmp(sk2
, sk2r2
, sizeof(sk2r2
)) == 0);
711 uint8_t key3
[] = {0x5A, 0xA9, 0xF6, 0xC6, 0xDE, 0x51, 0x38, 0x11, 0x3D, 0xF5, 0xD6, 0xB6, 0xC7, 0x7D, 0x5D, 0x52};
712 uint8_t sk1r3
[] = {0x2A, 0xE0, 0xEB, 0xD3, 0x76, 0xBC, 0xD4, 0xA2, 0x7B, 0x1C, 0xD4, 0x06, 0xD2, 0x43, 0x1C, 0xF9};
713 uint8_t sk2r3
[] = {0x55, 0xC1, 0xD7, 0xA6, 0xED, 0x79, 0xA9, 0x44, 0xF6, 0x39, 0xA8, 0x0D, 0xA4, 0x86, 0x39, 0xF2};
715 LRPGenSubkeys(key3
, sk1
, sk2
);
716 res
= res
&& (memcmp(sk1
, sk1r3
, sizeof(sk1r3
)) == 0);
717 res
= res
&& (memcmp(sk2
, sk2r3
, sizeof(sk2r3
)) == 0);
719 PrintAndLogEx(INFO
, "LRP subkeys....... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
723 // https://www.nxp.com/docs/en/application-note/AN12304.pdf
725 static bool TestLRPCMAC(void) {
728 LRPContext_t ctx
= {0};
729 uint8_t cmac
[CRYPTO_AES128_KEY_SIZE
] = {0};
731 uint8_t key1
[] = {0x81, 0x95, 0x08, 0x8C, 0xE6, 0xC3, 0x93, 0x70, 0x8E, 0xBB, 0xE6, 0xC7, 0x91, 0x4E, 0xCB, 0x0B};
732 LRPSetKey(&ctx
, key1
, 0, true);
733 uint8_t data1
[] = {0xBB, 0xD5, 0xB8, 0x57, 0x72, 0xC7};
734 LRPCMAC(&ctx
, data1
, sizeof(data1
), cmac
);
735 uint8_t cmacres1
[] = {0xAD, 0x85, 0x95, 0xE0, 0xB4, 0x9C, 0x5C, 0x0D, 0xB1, 0x8E, 0x77, 0x35, 0x5F, 0x5A, 0xAF, 0xF6};
736 res
= res
&& (memcmp(cmac
, cmacres1
, sizeof(cmacres1
)) == 0);
738 uint8_t key2
[] = {0x5A, 0xA9, 0xF6, 0xC6, 0xDE, 0x51, 0x38, 0x11, 0x3D, 0xF5, 0xD6, 0xB6, 0xC7, 0x7D, 0x5D, 0x52};
739 LRPSetKey(&ctx
, key2
, 0, true);
740 uint8_t data2
[] = {0xA4, 0x43, 0x4D, 0x74, 0x0C, 0x2C, 0xB6, 0x65, 0xFE, 0x53, 0x96, 0x95, 0x91, 0x89, 0x38, 0x3F};
741 LRPCMAC(&ctx
, data2
, sizeof(data2
), cmac
);
742 uint8_t cmacres2
[] = {0x8B, 0x43, 0xAD, 0xF7, 0x67, 0xE4, 0x6B, 0x69, 0x2E, 0x8F, 0x24, 0xE8, 0x37, 0xCB, 0x5E, 0xFC};
743 res
= res
&& (memcmp(cmac
, cmacres2
, sizeof(cmacres2
)) == 0);
745 uint8_t key3
[] = {0x0D, 0x46, 0x55, 0x75, 0x50, 0xCB, 0x31, 0x3F, 0x36, 0xAF, 0xBA, 0x87, 0x62, 0x5D, 0x96, 0x1A};
746 LRPSetKey(&ctx
, key3
, 0, true);
747 uint8_t data3
[] = {0x90};
748 LRPCMAC(&ctx
, data3
, sizeof(data3
), cmac
);
749 uint8_t cmacres3
[] = {0xF7, 0xC8, 0x55, 0x3D, 0xED, 0x57, 0x48, 0x29, 0xE6, 0xEE, 0x68, 0x11, 0x2C, 0xB3, 0x81, 0x7B};
750 res
= res
&& (memcmp(cmac
, cmacres3
, sizeof(cmacres3
)) == 0);
752 uint8_t key4
[] = {0x2A, 0x47, 0x3E, 0x38, 0xBB, 0xF4, 0x53, 0x7C, 0x53, 0x97, 0xF4, 0x5A, 0xE4, 0x98, 0xCD, 0x4D};
753 LRPSetKey(&ctx
, key4
, 0, true);
754 uint8_t data4
[] = {0xC2, 0xAC, 0x3D, 0x72, 0x50, 0xEE, 0xF0, 0x23, 0x18, 0xBC, 0x08, 0x4F, 0x29, 0x4B, 0x1A, 0xC7,
755 0x22, 0x91, 0xEE, 0x1D, 0xC0, 0x2A, 0xF4, 0x24, 0x94, 0x1C, 0xAA, 0xC6, 0x85, 0xFC, 0xA5, 0x9D,
756 0x90, 0x08, 0x67, 0x9B, 0x00, 0xC5, 0x6A, 0x05, 0x62, 0x58, 0x3B, 0xDA, 0xEC, 0x0B, 0xBA
758 LRPCMAC(&ctx
, data4
, sizeof(data4
), cmac
);
759 uint8_t cmacres4
[] = {0x66, 0xDC, 0x2B, 0xCE, 0x26, 0x9B, 0x79, 0x3B, 0x4A, 0xCA, 0x1A, 0x4D, 0x04, 0xDD, 0xD6, 0x68};
760 res
= res
&& (memcmp(cmac
, cmacres4
, sizeof(cmacres4
)) == 0);
762 uint8_t key5
[] = {0x63, 0xA0, 0x16, 0x9B, 0x4D, 0x9F, 0xE4, 0x2C, 0x72, 0xB2, 0x78, 0x4C, 0x80, 0x6E, 0xAC, 0x21};
763 LRPSetKey(&ctx
, key5
, 0, true);
764 LRPCMAC(&ctx
, NULL
, 0, cmac
);
765 uint8_t cmacres5
[] = {0x0E, 0x07, 0xC6, 0x01, 0x97, 0x08, 0x14, 0xA4, 0x17, 0x6F, 0xDA, 0x63, 0x3C, 0x6F, 0xC3, 0xDE};
766 res
= res
&& (memcmp(cmac
, cmacres5
, sizeof(cmacres5
)) == 0);
768 uint8_t key6
[] = {0x95, 0x2F, 0xDE, 0x83, 0x93, 0xC4, 0x5D, 0x23, 0x0A, 0x5B, 0xE9, 0xB3, 0x86, 0x36, 0xD1, 0x54};
769 LRPSetKey(&ctx
, key6
, 0, true);
770 uint8_t data6
[] = {0xD7, 0x80, 0x0E, 0x25, 0x70, 0x01, 0xA7, 0x74, 0xAE, 0x7B, 0xCF, 0xB2, 0xCE, 0x13, 0x07, 0xB5,
773 LRPCMAC(&ctx
, data6
, sizeof(data6
), cmac
);
774 uint8_t cmacres6
[] = {0x05, 0xF1, 0xCE, 0x30, 0x45, 0x1A, 0x03, 0xA6, 0xE4, 0x68, 0xB3, 0xA5, 0x90, 0x33, 0xA5, 0x54};
775 res
= res
&& (memcmp(cmac
, cmacres6
, sizeof(cmacres6
)) == 0);
777 PrintAndLogEx(INFO
, "LRP CMAC.......... ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
781 // https://www.nxp.com/docs/en/application-note/AN12343.pdf
783 static bool TestLRPSessionKeys(void) {
786 uint8_t key
[16] = {0};
787 uint8_t rnda
[] = {0x74, 0xD7, 0xDF, 0x6A, 0x2C, 0xEC, 0x0B, 0x72, 0xB4, 0x12, 0xDE, 0x0D, 0x2B, 0x11, 0x17, 0xE6};
788 uint8_t rndb
[] = {0x56, 0x10, 0x9A, 0x31, 0x97, 0x7C, 0x85, 0x53, 0x19, 0xCD, 0x46, 0x18, 0xC9, 0xD2, 0xAE, 0xD2};
789 uint8_t sessionkeyres
[] = {0x13, 0x2D, 0x7E, 0x6F, 0x35, 0xBA, 0x86, 0x1F, 0x39, 0xB3, 0x72, 0x21, 0x21, 0x4E, 0x25, 0xA5};
791 uint8_t sessionkey
[16] = {0};
792 DesfireGenSessionKeyLRP(key
, rnda
, rndb
, true, sessionkey
);
793 res
= res
&& (memcmp(sessionkey
, sessionkeyres
, sizeof(sessionkeyres
)) == 0);
795 PrintAndLogEx(INFO
, "LRP session keys.. ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
799 bool DesfireTest(bool verbose
) {
802 PrintAndLogEx(INFO
, "------ " _CYAN_("MIFARE DESFire tests") " ------");
804 res
= res
&& TestCRC16();
805 res
= res
&& TestCRC32();
806 res
= res
&& TestCMACSubkeys();
807 res
= res
&& TestAn10922KDFAES();
808 res
= res
&& TestAn10922KDF2TDEA();
809 res
= res
&& TestAn10922KDF3TDEA();
810 res
= res
&& TestCMAC3TDEA();
811 res
= res
&& TestCMAC2TDEA();
812 res
= res
&& TestCMACDES();
813 res
= res
&& TestEV2SessionKeys();
814 res
= res
&& TestEV2IVEncode();
815 res
= res
&& TestEV2MAC();
816 res
= res
&& TestTransSessionKeys();
817 res
= res
&& TestLRPPlaintexts();
818 res
= res
&& TestLRPUpdatedKeys();
819 res
= res
&& TestLRPEval();
820 res
= res
&& TestLRPIncCounter();
821 res
= res
&& TestLRPEncode();
822 res
= res
&& TestLRPDecode();
823 res
= res
&& TestLRPSubkeys();
824 res
= res
&& TestLRPCMAC();
825 res
= res
&& TestLRPSessionKeys();
827 PrintAndLogEx(INFO
, "---------------------------");
828 PrintAndLogEx(SUCCESS
, "Tests ( %s )", (res
) ? _GREEN_("ok") : _RED_("fail"));
829 PrintAndLogEx(NORMAL
, "");