recover_pk.py: replace secp192r1 by prime192v1
[RRG-proxmark3.git] / armsrc / optimized_elite.c
blob4fdda62f0e15a9bacc62f191a16b8d93bee23a5d
1 //-----------------------------------------------------------------------------
2 // Borrowed initially from https://github.com/holiman/loclass
3 // Copyright (C) 2014 Martin Holst Swende
4 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // See LICENSE.txt for the text of the license.
17 //-----------------------------------------------------------------------------
18 // WARNING
20 // THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
22 // USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
23 // PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
24 // AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
26 // THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
27 //-----------------------------------------------------------------------------
28 // It is a reconstruction of the cipher engine used in iClass, and RFID techology.
30 // The implementation is based on the work performed by
31 // Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
32 // Milosch Meriac in the paper "Dismantling IClass".
33 //-----------------------------------------------------------------------------
34 #include "optimized_elite.h"
36 #include <stdint.h>
37 #include <stdbool.h>
38 #include <string.h>
39 #include "mbedtls/des.h"
40 #include "optimized_ikeys.h"
42 /**
43 * @brief Permutes a key from standard NIST format to Iclass specific format
44 * from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220
46 * If you permute [6c 8d 44 f9 2a 2d 01 bf] you get [8a 0d b9 88 bb a7 90 ea] as shown below.
48 * 1 0 1 1 1 1 1 1 bf
49 * 0 0 0 0 0 0 0 1 01
50 * 0 0 1 0 1 1 0 1 2d
51 * 0 0 1 0 1 0 1 0 2a
52 * 1 1 1 1 1 0 0 1 f9
53 * 0 1 0 0 0 1 0 0 44
54 * 1 0 0 0 1 1 0 1 8d
55 * 0 1 1 0 1 1 0 0 6c
57 * 8 0 b 8 b a 9 e
58 * a d 9 8 b 7 0 a
60 * @param key
61 * @param dest
63 void permutekey(const uint8_t key[8], uint8_t dest[8]) {
64 int i;
65 for (i = 0 ; i < 8 ; i++) {
66 dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) |
67 (((key[6] & (0x80 >> i)) >> (7 - i)) << 6) |
68 (((key[5] & (0x80 >> i)) >> (7 - i)) << 5) |
69 (((key[4] & (0x80 >> i)) >> (7 - i)) << 4) |
70 (((key[3] & (0x80 >> i)) >> (7 - i)) << 3) |
71 (((key[2] & (0x80 >> i)) >> (7 - i)) << 2) |
72 (((key[1] & (0x80 >> i)) >> (7 - i)) << 1) |
73 (((key[0] & (0x80 >> i)) >> (7 - i)) << 0);
76 /**
77 * Permutes a key from iclass specific format to NIST format
78 * @brief permutekey_rev
79 * @param key
80 * @param dest
82 void permutekey_rev(const uint8_t key[8], uint8_t dest[8]) {
83 int i;
84 for (i = 0 ; i < 8 ; i++) {
85 dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) |
86 (((key[1] & (0x80 >> i)) >> (7 - i)) << 6) |
87 (((key[2] & (0x80 >> i)) >> (7 - i)) << 5) |
88 (((key[3] & (0x80 >> i)) >> (7 - i)) << 4) |
89 (((key[4] & (0x80 >> i)) >> (7 - i)) << 3) |
90 (((key[5] & (0x80 >> i)) >> (7 - i)) << 2) |
91 (((key[6] & (0x80 >> i)) >> (7 - i)) << 1) |
92 (((key[7] & (0x80 >> i)) >> (7 - i)) << 0);
96 /**
97 * Helper function for hash1
98 * @brief rr
99 * @param val
100 * @return
102 static uint8_t rr(uint8_t val) {
103 return val >> 1 | ((val & 1) << 7);
107 * Helper function for hash1
108 * @brief rl
109 * @param val
110 * @return
112 static uint8_t rl(uint8_t val) {
113 return val << 1 | ((val & 0x80) >> 7);
117 * Helper function for hash1
118 * @brief swap
119 * @param val
120 * @return
122 static uint8_t swap(uint8_t val) {
123 return ((val >> 4) & 0xFF) | ((val & 0xFF) << 4);
127 * Hash1 takes CSN as input, and determines what bytes in the keytable will be used
128 * when constructing the K_sel.
129 * @param csn the CSN used
130 * @param k output
132 void hash1(const uint8_t csn[], uint8_t k[]) {
133 k[0] = csn[0] ^ csn[1] ^ csn[2] ^ csn[3] ^ csn[4] ^ csn[5] ^ csn[6] ^ csn[7];
134 k[1] = csn[0] + csn[1] + csn[2] + csn[3] + csn[4] + csn[5] + csn[6] + csn[7];
135 k[2] = rr(swap(csn[2] + k[1]));
136 k[3] = rl(swap(csn[3] + k[0]));
137 k[4] = ~rr(csn[4] + k[2]) + 1;
138 k[5] = ~rl(csn[5] + k[3]) + 1;
139 k[6] = rr(csn[6] + (k[4] ^ 0x3c));
140 k[7] = rl(csn[7] + (k[5] ^ 0xc3));
142 k[7] &= 0x7F;
143 k[6] &= 0x7F;
144 k[5] &= 0x7F;
145 k[4] &= 0x7F;
146 k[3] &= 0x7F;
147 k[2] &= 0x7F;
148 k[1] &= 0x7F;
149 k[0] &= 0x7F;
152 Definition 14. Define the rotate key function rk : (F 82 ) 8 × N → (F 82 ) 8 as
153 rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
154 rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
156 static void rk(const uint8_t *key, uint8_t n, uint8_t *outp_key) {
157 memcpy(outp_key, key, 8);
158 uint8_t j;
159 while (n-- > 0) {
160 for (j = 0; j < 8 ; j++)
161 outp_key[j] = rl(outp_key[j]);
163 return;
166 static mbedtls_des_context ctx_enc;
167 static mbedtls_des_context ctx_dec;
169 static void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
170 uint8_t key_std_format[8] = {0};
171 permutekey_rev(iclass_key, key_std_format);
172 mbedtls_des_setkey_dec(&ctx_dec, key_std_format);
173 mbedtls_des_crypt_ecb(&ctx_dec, input, output);
176 static void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
177 uint8_t key_std_format[8] = {0};
178 permutekey_rev(iclass_key, key_std_format);
179 mbedtls_des_setkey_enc(&ctx_enc, key_std_format);
180 mbedtls_des_crypt_ecb(&ctx_enc, input, output);
184 * @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select.
185 * @param key unpermuted custom key
186 * @param hash1 hash1
187 * @param key_sel output key_sel=h[hash1[i]]
189 void hash2(uint8_t *key64, uint8_t *outp_keytable) {
191 *Expected:
192 * High Security Key Table
194 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
195 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
196 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
197 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
198 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
199 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
200 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
201 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
203 **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/
204 uint8_t key64_negated[8] = {0};
205 uint8_t z[8][8] = {{0}, {0}};
206 uint8_t temp_output[8] = {0};
208 //calculate complement of key
209 int i;
210 for (i = 0; i < 8; i++)
211 key64_negated[i] = ~key64[i];
213 // Once again, key is on iclass-format
214 desencrypt_iclass(key64, key64_negated, z[0]);
216 uint8_t y[8][8] = {{0}, {0}};
218 // y[0]=DES_dec(z[0],~key)
219 // Once again, key is on iclass-format
220 desdecrypt_iclass(z[0], key64_negated, y[0]);
222 for (i = 1; i < 8; i++) {
223 rk(key64, i, temp_output);
224 desdecrypt_iclass(temp_output, z[i - 1], z[i]);
225 desencrypt_iclass(temp_output, y[i - 1], y[i]);
228 if (outp_keytable != NULL) {
229 for (i = 0 ; i < 8 ; i++) {
230 memcpy(outp_keytable + i * 16, y[i], 8);
231 memcpy(outp_keytable + 8 + i * 16, z[i], 8);