Merge pull request #1331 from Guilhem7/master
[RRG-proxmark3.git] / armsrc / optimized_elite.c
blobc84dd58be7b68c57f6650b5f66f2b0f8f01f8562
1 /*****************************************************************************
2 * WARNING
4 * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
6 * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
7 * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
8 * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
10 * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
12 *****************************************************************************
14 * This file is part of loclass. It is a reconstructon of the cipher engine
15 * used in iClass, and RFID techology.
17 * The implementation is based on the work performed by
18 * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
19 * Milosch Meriac in the paper "Dismantling IClass".
21 * Copyright (C) 2014 Martin Holst Swende
23 * This is free software: you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License version 2 as published
25 * by the Free Software Foundation, or, at your option, any later version.
27 * This file is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with loclass. If not, see <http://www.gnu.org/licenses/>.
37 ****************************************************************************/
38 #include "optimized_elite.h"
40 #include <stdint.h>
41 #include <stdbool.h>
42 #include <string.h>
43 #include "mbedtls/des.h"
44 #include "optimized_ikeys.h"
46 /**
47 * @brief Permutes a key from standard NIST format to Iclass specific format
48 * from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220
50 * If you permute [6c 8d 44 f9 2a 2d 01 bf] you get [8a 0d b9 88 bb a7 90 ea] as shown below.
52 * 1 0 1 1 1 1 1 1 bf
53 * 0 0 0 0 0 0 0 1 01
54 * 0 0 1 0 1 1 0 1 2d
55 * 0 0 1 0 1 0 1 0 2a
56 * 1 1 1 1 1 0 0 1 f9
57 * 0 1 0 0 0 1 0 0 44
58 * 1 0 0 0 1 1 0 1 8d
59 * 0 1 1 0 1 1 0 0 6c
61 * 8 0 b 8 b a 9 e
62 * a d 9 8 b 7 0 a
64 * @param key
65 * @param dest
67 void permutekey(uint8_t key[8], uint8_t dest[8]) {
68 int i;
69 for (i = 0 ; i < 8 ; i++) {
70 dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) |
71 (((key[6] & (0x80 >> i)) >> (7 - i)) << 6) |
72 (((key[5] & (0x80 >> i)) >> (7 - i)) << 5) |
73 (((key[4] & (0x80 >> i)) >> (7 - i)) << 4) |
74 (((key[3] & (0x80 >> i)) >> (7 - i)) << 3) |
75 (((key[2] & (0x80 >> i)) >> (7 - i)) << 2) |
76 (((key[1] & (0x80 >> i)) >> (7 - i)) << 1) |
77 (((key[0] & (0x80 >> i)) >> (7 - i)) << 0);
80 /**
81 * Permutes a key from iclass specific format to NIST format
82 * @brief permutekey_rev
83 * @param key
84 * @param dest
86 void permutekey_rev(uint8_t key[8], uint8_t dest[8]) {
87 int i;
88 for (i = 0 ; i < 8 ; i++) {
89 dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) |
90 (((key[1] & (0x80 >> i)) >> (7 - i)) << 6) |
91 (((key[2] & (0x80 >> i)) >> (7 - i)) << 5) |
92 (((key[3] & (0x80 >> i)) >> (7 - i)) << 4) |
93 (((key[4] & (0x80 >> i)) >> (7 - i)) << 3) |
94 (((key[5] & (0x80 >> i)) >> (7 - i)) << 2) |
95 (((key[6] & (0x80 >> i)) >> (7 - i)) << 1) |
96 (((key[7] & (0x80 >> i)) >> (7 - i)) << 0);
101 * Helper function for hash1
102 * @brief rr
103 * @param val
104 * @return
106 static uint8_t rr(uint8_t val) {
107 return val >> 1 | ((val & 1) << 7);
111 * Helper function for hash1
112 * @brief rl
113 * @param val
114 * @return
116 static uint8_t rl(uint8_t val) {
117 return val << 1 | ((val & 0x80) >> 7);
121 * Helper function for hash1
122 * @brief swap
123 * @param val
124 * @return
126 static uint8_t swap(uint8_t val) {
127 return ((val >> 4) & 0xFF) | ((val & 0xFF) << 4);
131 * Hash1 takes CSN as input, and determines what bytes in the keytable will be used
132 * when constructing the K_sel.
133 * @param csn the CSN used
134 * @param k output
136 void hash1(uint8_t csn[], uint8_t k[]) {
137 k[0] = csn[0] ^ csn[1] ^ csn[2] ^ csn[3] ^ csn[4] ^ csn[5] ^ csn[6] ^ csn[7];
138 k[1] = csn[0] + csn[1] + csn[2] + csn[3] + csn[4] + csn[5] + csn[6] + csn[7];
139 k[2] = rr(swap(csn[2] + k[1]));
140 k[3] = rl(swap(csn[3] + k[0]));
141 k[4] = ~rr(csn[4] + k[2]) + 1;
142 k[5] = ~rl(csn[5] + k[3]) + 1;
143 k[6] = rr(csn[6] + (k[4] ^ 0x3c));
144 k[7] = rl(csn[7] + (k[5] ^ 0xc3));
146 k[7] &= 0x7F;
147 k[6] &= 0x7F;
148 k[5] &= 0x7F;
149 k[4] &= 0x7F;
150 k[3] &= 0x7F;
151 k[2] &= 0x7F;
152 k[1] &= 0x7F;
153 k[0] &= 0x7F;
156 Definition 14. Define the rotate key function rk : (F 82 ) 8 × N → (F 82 ) 8 as
157 rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
158 rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
160 static void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) {
161 memcpy(outp_key, key, 8);
162 uint8_t j;
163 while (n-- > 0) {
164 for (j = 0; j < 8 ; j++)
165 outp_key[j] = rl(outp_key[j]);
167 return;
170 static mbedtls_des_context ctx_enc;
171 static mbedtls_des_context ctx_dec;
173 static void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
174 uint8_t key_std_format[8] = {0};
175 permutekey_rev(iclass_key, key_std_format);
176 mbedtls_des_setkey_dec(&ctx_dec, key_std_format);
177 mbedtls_des_crypt_ecb(&ctx_dec, input, output);
180 static void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
181 uint8_t key_std_format[8] = {0};
182 permutekey_rev(iclass_key, key_std_format);
183 mbedtls_des_setkey_enc(&ctx_enc, key_std_format);
184 mbedtls_des_crypt_ecb(&ctx_enc, input, output);
188 * @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select.
189 * @param key unpermuted custom key
190 * @param hash1 hash1
191 * @param key_sel output key_sel=h[hash1[i]]
193 void hash2(uint8_t *key64, uint8_t *outp_keytable) {
195 *Expected:
196 * High Security Key Table
198 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
199 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
200 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
201 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
202 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
203 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
204 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
205 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
207 **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/
208 uint8_t key64_negated[8] = {0};
209 uint8_t z[8][8] = {{0}, {0}};
210 uint8_t temp_output[8] = {0};
212 //calculate complement of key
213 int i;
214 for (i = 0; i < 8; i++)
215 key64_negated[i] = ~key64[i];
217 // Once again, key is on iclass-format
218 desencrypt_iclass(key64, key64_negated, z[0]);
220 uint8_t y[8][8] = {{0}, {0}};
222 // y[0]=DES_dec(z[0],~key)
223 // Once again, key is on iclass-format
224 desdecrypt_iclass(z[0], key64_negated, y[0]);
226 for (i = 1; i < 8; i++) {
227 rk(key64, i, temp_output);
228 desdecrypt_iclass(temp_output, z[i - 1], z[i]);
229 desencrypt_iclass(temp_output, y[i - 1], y[i]);
232 if (outp_keytable != NULL) {
233 for (i = 0 ; i < 8 ; i++) {
234 memcpy(outp_keytable + i * 16, y[i], 8);
235 memcpy(outp_keytable + 8 + i * 16, z[i], 8);