Namespace loclass library (#1379)

* Namespace loclass library
* Lib: const for immutable variables and bss cleanup

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Eric Betts 2022-07-08 05:56:23 -07:00 committed by GitHub
parent 6b3625f46b
commit f46ae5a704
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 221 additions and 246 deletions

View File

@ -198,8 +198,8 @@ ReturnCode picopass_read_card(ApplicationArea* AA1) {
} }
memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0 memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
diversifyKey(selRes.CSN, picopass_iclass_key, div_key); loclass_diversifyKey(selRes.CSN, picopass_iclass_key, div_key);
opt_doReaderMAC(ccnr, div_key, mac); loclass_opt_doReaderMAC(ccnr, div_key, mac);
err = rfalPicoPassPollerCheck(mac, &chkRes); err = rfalPicoPassPollerCheck(mac, &chkRes);
if(err != ERR_NONE) { if(err != ERR_NONE) {

View File

@ -81,7 +81,7 @@
#include "optimized_ikeys.h" #include "optimized_ikeys.h"
#include "optimized_cipherutils.h" #include "optimized_cipherutils.h"
static const uint8_t opt_select_LUT[256] = { static const uint8_t loclass_opt_select_LUT[256] = {
00, 03, 02, 01, 02, 03, 00, 01, 04, 07, 07, 04, 06, 07, 05, 04, 00, 03, 02, 01, 02, 03, 00, 01, 04, 07, 07, 04, 06, 07, 05, 04,
01, 02, 03, 00, 02, 03, 00, 01, 05, 06, 06, 05, 06, 07, 05, 04, 01, 02, 03, 00, 02, 03, 00, 01, 05, 06, 06, 05, 06, 07, 05, 04,
06, 05, 04, 07, 04, 05, 06, 07, 06, 05, 05, 06, 04, 05, 07, 06, 06, 05, 04, 07, 04, 05, 06, 07, 06, 05, 05, 06, 04, 05, 07, 06,
@ -110,42 +110,18 @@ static void init_opt_select_LUT(void) {
uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3); uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3);
uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r; uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r;
uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r; uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r;
opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1); loclass_opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1);
} }
print_result("", opt_select_LUT, 256); print_result("", loclass_opt_select_LUT, 256);
} }
***********************************************************************************/ ***********************************************************************************/
#define opt__select(x,y,r) (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ( (r | r << 2) >> 3)))\ #define loclass_opt__select(x,y,r) (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ( (r | r << 2) >> 3)))\
|(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\ |(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\
|(1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x)) |(1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x))
/*
* Some background on the expression above can be found here...
uint8_t xopt__select(bool x, bool y, uint8_t r)
{
//r: r0 r1 r2 r3 r4 r5 r6 r7 static void loclass_opt_successor(const uint8_t *k, LoclassState_t *s, uint8_t y) {
//r_ls2: r2 r3 r4 r5 r6 r7 0 0
// z0
// z1
// uint8_t z0 = (r0 & r2) ^ (r1 & ~r3) ^ (r2 | r4); // <-- original
uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3);
// uint8_t z1 = (r0 | r2) ^ ( r5 | r7) ^ r1 ^ r6 ^ x ^ y; // <-- original
uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1);
// uint8_t z2 = (r3 & ~r5) ^ (r4 & r6 ) ^ r7 ^ x; // <-- original
uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r ^ x;
return (z0 & 4) | (z1 & 2) | (z2 & 1);
}
*/
static void opt_successor(const uint8_t *k, State_t *s, uint8_t y) {
// #define opt_T(s) (0x1 & ((s->t >> 15) ^ (s->t >> 14) ^ (s->t >> 10) ^ (s->t >> 8) ^ (s->t >> 5) ^ (s->t >> 4)^ (s->t >> 1) ^ s->t))
// uint8_t Tt = opt_T(s);
uint16_t Tt = s->t & 0xc533; uint16_t Tt = s->t & 0xc533;
Tt = Tt ^ (Tt >> 1); Tt = Tt ^ (Tt >> 1);
Tt = Tt ^ (Tt >> 4); Tt = Tt ^ (Tt >> 4);
@ -163,125 +139,125 @@ static void opt_successor(const uint8_t *k, State_t *s, uint8_t y) {
s->b = s->b >> 1; s->b = s->b >> 1;
s->b |= (opt_B ^ s->r) << 7; s->b |= (opt_B ^ s->r) << 7;
uint8_t opt_select = opt_select_LUT[s->r] & 0x04; uint8_t opt_select = loclass_opt_select_LUT[s->r] & 0x04;
opt_select |= (opt_select_LUT[s->r] ^ ((Tt ^ y) << 1)) & 0x02; opt_select |= (loclass_opt_select_LUT[s->r] ^ ((Tt ^ y) << 1)) & 0x02;
opt_select |= (opt_select_LUT[s->r] ^ Tt) & 0x01; opt_select |= (loclass_opt_select_LUT[s->r] ^ Tt) & 0x01;
uint8_t r = s->r; uint8_t r = s->r;
s->r = (k[opt_select] ^ s->b) + s->l ; s->r = (k[opt_select] ^ s->b) + s->l ;
s->l = s->r + r; s->l = s->r + r;
} }
static void opt_suc(const uint8_t *k, State_t *s, const uint8_t *in, uint8_t length, bool add32Zeroes) { static void loclass_opt_suc(const uint8_t *k, LoclassState_t *s, const uint8_t *in, uint8_t length, bool add32Zeroes) {
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
uint8_t head; uint8_t head;
head = in[i]; head = in[i];
opt_successor(k, s, head); loclass_opt_successor(k, s, head);
head >>= 1; head >>= 1;
opt_successor(k, s, head); loclass_opt_successor(k, s, head);
head >>= 1; head >>= 1;
opt_successor(k, s, head); loclass_opt_successor(k, s, head);
head >>= 1; head >>= 1;
opt_successor(k, s, head); loclass_opt_successor(k, s, head);
head >>= 1; head >>= 1;
opt_successor(k, s, head); loclass_opt_successor(k, s, head);
head >>= 1; head >>= 1;
opt_successor(k, s, head); loclass_opt_successor(k, s, head);
head >>= 1; head >>= 1;
opt_successor(k, s, head); loclass_opt_successor(k, s, head);
head >>= 1; head >>= 1;
opt_successor(k, s, head); loclass_opt_successor(k, s, head);
} }
//For tag MAC, an additional 32 zeroes //For tag MAC, an additional 32 zeroes
if (add32Zeroes) { if (add32Zeroes) {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
} }
} }
} }
static void opt_output(const uint8_t *k, State_t *s, uint8_t *buffer) { static void loclass_opt_output(const uint8_t *k, LoclassState_t *s, uint8_t *buffer) {
for (uint8_t times = 0; times < 4; times++) { for (uint8_t times = 0; times < 4; times++) {
uint8_t bout = 0; uint8_t bout = 0;
bout |= (s->r & 0x4) >> 2; bout |= (s->r & 0x4) >> 2;
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
bout |= (s->r & 0x4) >> 1; bout |= (s->r & 0x4) >> 1;
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
bout |= (s->r & 0x4); bout |= (s->r & 0x4);
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
bout |= (s->r & 0x4) << 1; bout |= (s->r & 0x4) << 1;
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
bout |= (s->r & 0x4) << 2; bout |= (s->r & 0x4) << 2;
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
bout |= (s->r & 0x4) << 3; bout |= (s->r & 0x4) << 3;
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
bout |= (s->r & 0x4) << 4; bout |= (s->r & 0x4) << 4;
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
bout |= (s->r & 0x4) << 5; bout |= (s->r & 0x4) << 5;
opt_successor(k, s, 0); loclass_opt_successor(k, s, 0);
buffer[times] = bout; buffer[times] = bout;
} }
} }
static void opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) { static void loclass_opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) {
State_t _init = { LoclassState_t _init = {
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(k, &_init, input, 12, false); loclass_opt_suc(k, &_init, input, 12, false);
opt_output(k, &_init, out); loclass_opt_output(k, &_init, out);
} }
static void opt_MAC_N(uint8_t *k, uint8_t *input, uint8_t in_size, uint8_t *out) { static void loclass_opt_MAC_N(uint8_t *k, uint8_t *input, uint8_t in_size, uint8_t *out) {
State_t _init = { LoclassState_t _init = {
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(k, &_init, input, in_size, false); loclass_opt_suc(k, &_init, input, in_size, false);
opt_output(k, &_init, out); loclass_opt_output(k, &_init, out);
} }
void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { void loclass_opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) {
uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
opt_MAC(div_key_p, cc_nr_p, dest); loclass_opt_MAC(div_key_p, cc_nr_p, dest);
memcpy(mac, dest, 4); memcpy(mac, dest, 4);
} }
void opt_doReaderMAC_2(State_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) { void loclass_opt_doReaderMAC_2(LoclassState_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) {
opt_suc(div_key_p, &_init, nr, 4, false); loclass_opt_suc(div_key_p, &_init, nr, 4, false);
opt_output(div_key_p, &_init, mac); loclass_opt_output(div_key_p, &_init, mac);
} }
void doMAC_N(uint8_t *in_p, uint8_t in_size, uint8_t *div_key_p, uint8_t mac[4]) { void loclass_doMAC_N(uint8_t *in_p, uint8_t in_size, uint8_t *div_key_p, uint8_t mac[4]) {
uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
opt_MAC_N(div_key_p, in_p, in_size, dest); loclass_opt_MAC_N(div_key_p, in_p, in_size, dest);
memcpy(mac, dest, 4); memcpy(mac, dest, 4);
} }
void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) { void loclass_opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
State_t _init = { LoclassState_t _init = {
((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(div_key_p, &_init, cc_p, 12, true); loclass_opt_suc(div_key_p, &_init, cc_p, 12, true);
opt_output(div_key_p, &_init, mac); loclass_opt_output(div_key_p, &_init, mac);
} }
/** /**
@ -292,14 +268,14 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
* @param div_key_p * @param div_key_p
* @return the cipher state * @return the cipher state
*/ */
State_t opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) { LoclassState_t loclass_opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
State_t _init = { LoclassState_t _init = {
((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(div_key_p, &_init, cc_p, 8, false); loclass_opt_suc(div_key_p, &_init, cc_p, 8, false);
return _init; return _init;
} }
@ -312,27 +288,26 @@ State_t opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
* @param mac - where to store the MAC * @param mac - where to store the MAC
* @param div_key_p - the key to use * @param div_key_p - the key to use
*/ */
void opt_doTagMAC_2(State_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) { void loclass_opt_doTagMAC_2(LoclassState_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) {
opt_suc(div_key_p, &_init, nr, 4, true); loclass_opt_suc(div_key_p, &_init, nr, 4, true);
opt_output(div_key_p, &_init, mac); loclass_opt_output(div_key_p, &_init, mac);
} }
void loclass_iclass_calc_div_key(uint8_t *csn, uint8_t *key, uint8_t *div_key, bool elite) {
void iclass_calc_div_key(uint8_t *csn, uint8_t *key, uint8_t *div_key, bool elite) {
if (elite) { if (elite) {
uint8_t keytable[128] = {0}; uint8_t keytable[128] = {0};
uint8_t key_index[8] = {0}; uint8_t key_index[8] = {0};
uint8_t key_sel[8] = { 0 }; uint8_t key_sel[8] = { 0 };
uint8_t key_sel_p[8] = { 0 }; uint8_t key_sel_p[8] = { 0 };
hash2(key, keytable); loclass_hash2(key, keytable);
hash1(csn, key_index); loclass_hash1(csn, key_index);
for (uint8_t i = 0; i < 8 ; i++) for (uint8_t i = 0; i < 8 ; i++)
key_sel[i] = keytable[key_index[i]]; key_sel[i] = keytable[key_index[i]];
//Permute from iclass format to standard format //Permute from iclass format to standard format
permutekey_rev(key_sel, key_sel_p); loclass_permutekey_rev(key_sel, key_sel_p);
diversifyKey(csn, key_sel_p, div_key); loclass_diversifyKey(csn, key_sel_p, div_key);
} else { } else {
diversifyKey(csn, key, div_key); loclass_diversifyKey(csn, key, div_key);
} }
} }

View File

@ -52,18 +52,18 @@ typedef struct {
uint8_t r; uint8_t r;
uint8_t b; uint8_t b;
uint16_t t; uint16_t t;
} State_t; } LoclassState_t;
/** The reader MAC is MAC(key, CC * NR ) /** The reader MAC is MAC(key, CC * NR )
**/ **/
void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]); void loclass_opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
void opt_doReaderMAC_2(State_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p); void loclass_opt_doReaderMAC_2(LoclassState_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p);
/** /**
* The tag MAC is MAC(key, CC * NR * 32x0)) * The tag MAC is MAC(key, CC * NR * 32x0))
*/ */
void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]); void loclass_opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]);
/** /**
* The tag MAC can be divided (both can, but no point in dividing the reader mac) into * The tag MAC can be divided (both can, but no point in dividing the reader mac) into
@ -73,7 +73,7 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]);
* @param div_key_p * @param div_key_p
* @return the cipher state * @return the cipher state
*/ */
State_t opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p); LoclassState_t loclass_opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p);
/** /**
* The second part of the tag MAC calculation, since the CC is already calculated into the state, * The second part of the tag MAC calculation, since the CC is already calculated into the state,
* this function is fed only the NR, and internally feeds the remaining 32 0-bits to generate the tag * this function is fed only the NR, and internally feeds the remaining 32 0-bits to generate the tag
@ -83,8 +83,8 @@ State_t opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p);
* @param mac - where to store the MAC * @param mac - where to store the MAC
* @param div_key_p - the key to use * @param div_key_p - the key to use
*/ */
void opt_doTagMAC_2(State_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p); void loclass_opt_doTagMAC_2(LoclassState_t _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p);
void doMAC_N(uint8_t *in_p, uint8_t in_size, uint8_t *div_key_p, uint8_t mac[4]); void loclass_doMAC_N(uint8_t *in_p, uint8_t in_size, uint8_t *div_key_p, uint8_t mac[4]);
void iclass_calc_div_key(uint8_t *csn, uint8_t *key, uint8_t *div_key, bool elite); void loclass_iclass_calc_div_key(uint8_t *csn, uint8_t *key, uint8_t *div_key, bool elite);
#endif // OPTIMIZED_CIPHER_H #endif // OPTIMIZED_CIPHER_H

View File

@ -40,7 +40,7 @@
* @param stream * @param stream
* @return * @return
*/ */
bool headBit(BitstreamIn_t *stream) { bool loclass_headBit(LoclassBitstreamIn_t *stream) {
int bytepos = stream->position >> 3; // divide by 8 int bytepos = stream->position >> 3; // divide by 8
int bitpos = (stream->position++) & 7; // mask out 00000111 int bitpos = (stream->position++) & 7; // mask out 00000111
return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1; return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1;
@ -50,7 +50,7 @@ bool headBit(BitstreamIn_t *stream) {
* @param stream * @param stream
* @return * @return
*/ */
bool tailBit(BitstreamIn_t *stream) { bool loclass_tailBit(LoclassBitstreamIn_t *stream) {
int bitpos = stream->numbits - 1 - (stream->position++); int bitpos = stream->numbits - 1 - (stream->position++);
int bytepos = bitpos >> 3; int bytepos = bitpos >> 3;
@ -62,7 +62,7 @@ bool tailBit(BitstreamIn_t *stream) {
* @param stream * @param stream
* @param bit * @param bit
*/ */
void pushBit(BitstreamOut_t *stream, bool bit) { void loclass_pushBit(LoclassBitstreamOut_t *stream, bool bit) {
int bytepos = stream->position >> 3; // divide by 8 int bytepos = stream->position >> 3; // divide by 8
int bitpos = stream->position & 7; int bitpos = stream->position & 7;
*(stream->buffer + bytepos) |= (bit) << (7 - bitpos); *(stream->buffer + bytepos) |= (bit) << (7 - bitpos);
@ -76,21 +76,21 @@ void pushBit(BitstreamOut_t *stream, bool bit) {
* @param stream * @param stream
* @param bits * @param bits
*/ */
void push6bits(BitstreamOut_t *stream, uint8_t bits) { void loclass_push6bits(LoclassBitstreamOut_t *stream, uint8_t bits) {
pushBit(stream, bits & 0x20); loclass_pushBit(stream, bits & 0x20);
pushBit(stream, bits & 0x10); loclass_pushBit(stream, bits & 0x10);
pushBit(stream, bits & 0x08); loclass_pushBit(stream, bits & 0x08);
pushBit(stream, bits & 0x04); loclass_pushBit(stream, bits & 0x04);
pushBit(stream, bits & 0x02); loclass_pushBit(stream, bits & 0x02);
pushBit(stream, bits & 0x01); loclass_pushBit(stream, bits & 0x01);
} }
/** /**
* @brief bitsLeft * @brief loclass_bitsLeft
* @param stream * @param stream
* @return number of bits left in stream * @return number of bits left in stream
*/ */
int bitsLeft(BitstreamIn_t *stream) { int loclass_bitsLeft(LoclassBitstreamIn_t *stream) {
return stream->numbits - stream->position; return stream->numbits - stream->position;
} }
/** /**
@ -98,14 +98,14 @@ int bitsLeft(BitstreamIn_t *stream) {
* @param stream * @param stream
* @return Number of bits stored in stream * @return Number of bits stored in stream
*/ */
void x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest) { void loclass_x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest) {
while (len--) { while (len--) {
dest[len] = (uint8_t) n; dest[len] = (uint8_t) n;
n >>= 8; n >>= 8;
} }
} }
uint64_t x_bytes_to_num(uint8_t *src, size_t len) { uint64_t loclass_x_bytes_to_num(uint8_t *src, size_t len) {
uint64_t num = 0; uint64_t num = 0;
while (len--) { while (len--) {
num = (num << 8) | (*src); num = (num << 8) | (*src);
@ -114,24 +114,24 @@ uint64_t x_bytes_to_num(uint8_t *src, size_t len) {
return num; return num;
} }
uint8_t reversebytes(uint8_t b) { uint8_t loclass_reversebytes(uint8_t b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1; b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b; return b;
} }
void reverse_arraybytes(uint8_t *arr, size_t len) { void loclass_reverse_arraybytes(uint8_t *arr, size_t len) {
uint8_t i; uint8_t i;
for (i = 0; i < len ; i++) { for (i = 0; i < len ; i++) {
arr[i] = reversebytes(arr[i]); arr[i] = loclass_reversebytes(arr[i]);
} }
} }
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) { void loclass_reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) {
uint8_t i; uint8_t i;
for (i = 0; i < len ; i++) { for (i = 0; i < len ; i++) {
dest[i] = reversebytes(arr[i]); dest[i] = loclass_reversebytes(arr[i]);
} }
} }

View File

@ -42,23 +42,23 @@ typedef struct {
uint8_t *buffer; uint8_t *buffer;
uint8_t numbits; uint8_t numbits;
uint8_t position; uint8_t position;
} BitstreamIn_t; } LoclassBitstreamIn_t;
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
uint8_t numbits; uint8_t numbits;
uint8_t position; uint8_t position;
} BitstreamOut_t; } LoclassBitstreamOut_t;
bool headBit(BitstreamIn_t *stream); bool loclass_headBit(LoclassBitstreamIn_t *stream);
bool tailBit(BitstreamIn_t *stream); bool loclass_tailBit(LoclassBitstreamIn_t *stream);
void pushBit(BitstreamOut_t *stream, bool bit); void loclass_pushBit(LoclassBitstreamOut_t *stream, bool bit);
int bitsLeft(BitstreamIn_t *stream); int loclass_bitsLeft(LoclassBitstreamIn_t *stream);
void push6bits(BitstreamOut_t *stream, uint8_t bits); void loclass_push6bits(LoclassBitstreamOut_t *stream, uint8_t bits);
void x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest); void loclass_x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest);
uint64_t x_bytes_to_num(uint8_t *src, size_t len); uint64_t loclass_x_bytes_to_num(uint8_t *src, size_t len);
uint8_t reversebytes(uint8_t b); uint8_t loclass_reversebytes(uint8_t b);
void reverse_arraybytes(uint8_t *arr, size_t len); void loclass_reverse_arraybytes(uint8_t *arr, size_t len);
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len); void loclass_reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len);
#endif // CIPHERUTILS_H #endif // CIPHERUTILS_H

View File

@ -43,7 +43,7 @@
* @brief Permutes a key from standard NIST format to Iclass specific format * @brief Permutes a key from standard NIST format to Iclass specific format
* from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220 * from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220
* *
* If you permute [6c 8d 44 f9 2a 2d 01 bf] you get [8a 0d b9 88 bb a7 90 ea] as shown below. * If you loclass_permute [6c 8d 44 f9 2a 2d 01 bf] you get [8a 0d b9 88 bb a7 90 ea] as shown below.
* *
* 1 0 1 1 1 1 1 1 bf * 1 0 1 1 1 1 1 1 bf
* 0 0 0 0 0 0 0 1 01 * 0 0 0 0 0 0 0 1 01
@ -60,7 +60,7 @@
* @param key * @param key
* @param dest * @param dest
*/ */
void permutekey(const uint8_t key[8], uint8_t dest[8]) { void loclass_permutekey(const uint8_t key[8], uint8_t dest[8]) {
int i; int i;
for (i = 0 ; i < 8 ; i++) { for (i = 0 ; i < 8 ; i++) {
dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) | dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) |
@ -75,11 +75,11 @@ void permutekey(const uint8_t key[8], uint8_t dest[8]) {
} }
/** /**
* Permutes a key from iclass specific format to NIST format * Permutes a key from iclass specific format to NIST format
* @brief permutekey_rev * @brief loclass_permutekey_rev
* @param key * @param key
* @param dest * @param dest
*/ */
void permutekey_rev(const uint8_t key[8], uint8_t dest[8]) { void loclass_permutekey_rev(const uint8_t key[8], uint8_t dest[8]) {
int i; int i;
for (i = 0 ; i < 8 ; i++) { for (i = 0 ; i < 8 ; i++) {
dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) | dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) |
@ -94,32 +94,32 @@ void permutekey_rev(const uint8_t key[8], uint8_t dest[8]) {
} }
/** /**
* Helper function for hash1 * Helper function for loclass_hash1
* @brief rr * @brief loclass_rr
* @param val * @param val
* @return * @return
*/ */
static uint8_t rr(uint8_t val) { static uint8_t loclass_rr(uint8_t val) {
return val >> 1 | ((val & 1) << 7); return val >> 1 | ((val & 1) << 7);
} }
/** /**
* Helper function for hash1 * Helper function for loclass_hash1
* @brief rl * @brief rl
* @param val * @param val
* @return * @return
*/ */
static uint8_t rl(uint8_t val) { static uint8_t loclass_rl(uint8_t val) {
return val << 1 | ((val & 0x80) >> 7); return val << 1 | ((val & 0x80) >> 7);
} }
/** /**
* Helper function for hash1 * Helper function for loclass_hash1
* @brief swap * @brief loclass_swap
* @param val * @param val
* @return * @return
*/ */
static uint8_t swap(uint8_t val) { static uint8_t loclass_swap(uint8_t val) {
return ((val >> 4) & 0xFF) | ((val & 0xFF) << 4); return ((val >> 4) & 0xFF) | ((val & 0xFF) << 4);
} }
@ -129,15 +129,15 @@ static uint8_t swap(uint8_t val) {
* @param csn the CSN used * @param csn the CSN used
* @param k output * @param k output
*/ */
void hash1(const uint8_t csn[], uint8_t k[]) { void loclass_hash1(const uint8_t csn[], uint8_t k[]) {
k[0] = csn[0] ^ csn[1] ^ csn[2] ^ csn[3] ^ csn[4] ^ csn[5] ^ csn[6] ^ csn[7]; k[0] = csn[0] ^ csn[1] ^ csn[2] ^ csn[3] ^ csn[4] ^ csn[5] ^ csn[6] ^ csn[7];
k[1] = csn[0] + csn[1] + csn[2] + csn[3] + csn[4] + csn[5] + csn[6] + csn[7]; k[1] = csn[0] + csn[1] + csn[2] + csn[3] + csn[4] + csn[5] + csn[6] + csn[7];
k[2] = rr(swap(csn[2] + k[1])); k[2] = loclass_rr(loclass_swap(csn[2] + k[1]));
k[3] = rl(swap(csn[3] + k[0])); k[3] = loclass_rl(loclass_swap(csn[3] + k[0]));
k[4] = ~rr(csn[4] + k[2]) + 1; k[4] = ~loclass_rr(csn[4] + k[2]) + 1;
k[5] = ~rl(csn[5] + k[3]) + 1; k[5] = ~loclass_rl(csn[5] + k[3]) + 1;
k[6] = rr(csn[6] + (k[4] ^ 0x3c)); k[6] = loclass_rr(csn[6] + (k[4] ^ 0x3c));
k[7] = rl(csn[7] + (k[5] ^ 0xc3)); k[7] = loclass_rl(csn[7] + (k[5] ^ 0xc3));
k[7] &= 0x7F; k[7] &= 0x7F;
k[6] &= 0x7F; k[6] &= 0x7F;
@ -149,42 +149,42 @@ void hash1(const uint8_t csn[], uint8_t k[]) {
k[0] &= 0x7F; k[0] &= 0x7F;
} }
/** /**
Definition 14. Define the rotate key function rk : (F 82 ) 8 × N (F 82 ) 8 as Definition 14. Define the rotate key function loclass_rk : (F 82 ) 8 × N (F 82 ) 8 as
rk(x [0] . . . x [7] , 0) = x [0] . . . x [7] loclass_rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n) loclass_rk(x [0] . . . x [7] , n + 1) = loclass_rk(loclass_rl(x [0] ) . . . loclass_rl(x [7] ), n)
**/ **/
static void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) { static void loclass_rk(uint8_t *key, uint8_t n, uint8_t *outp_key) {
memcpy(outp_key, key, 8); memcpy(outp_key, key, 8);
uint8_t j; uint8_t j;
while (n-- > 0) { while (n-- > 0) {
for (j = 0; j < 8 ; j++) for (j = 0; j < 8 ; j++)
outp_key[j] = rl(outp_key[j]); outp_key[j] = loclass_rl(outp_key[j]);
} }
return; return;
} }
static mbedtls_des_context ctx_enc; static mbedtls_des_context loclass_ctx_enc;
static mbedtls_des_context ctx_dec; static mbedtls_des_context loclass_ctx_dec;
static void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) { static void loclass_desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
uint8_t key_std_format[8] = {0}; uint8_t key_std_format[8] = {0};
permutekey_rev(iclass_key, key_std_format); loclass_permutekey_rev(iclass_key, key_std_format);
mbedtls_des_setkey_dec(&ctx_dec, key_std_format); mbedtls_des_setkey_dec(&loclass_ctx_dec, key_std_format);
mbedtls_des_crypt_ecb(&ctx_dec, input, output); mbedtls_des_crypt_ecb(&loclass_ctx_dec, input, output);
} }
static void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) { static void loclass_desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
uint8_t key_std_format[8] = {0}; uint8_t key_std_format[8] = {0};
permutekey_rev(iclass_key, key_std_format); loclass_permutekey_rev(iclass_key, key_std_format);
mbedtls_des_setkey_enc(&ctx_enc, key_std_format); mbedtls_des_setkey_enc(&loclass_ctx_enc, key_std_format);
mbedtls_des_crypt_ecb(&ctx_enc, input, output); mbedtls_des_crypt_ecb(&loclass_ctx_enc, input, output);
} }
/** /**
* @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select. * @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select.
* @param key unpermuted custom key * @param key unpermuted custom key
* @param hash1 hash1 * @param loclass_hash1 loclass_hash1
* @param key_sel output key_sel=h[hash1[i]] * @param key_sel output key_sel=h[loclass_hash1[i]]
*/ */
void hash2(uint8_t *key64, uint8_t *outp_keytable) { void hash2(uint8_t *key64, uint8_t *outp_keytable) {
/** /**
@ -211,18 +211,18 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) {
key64_negated[i] = ~key64[i]; key64_negated[i] = ~key64[i];
// Once again, key is on iclass-format // Once again, key is on iclass-format
desencrypt_iclass(key64, key64_negated, z[0]); loclass_desencrypt_iclass(key64, key64_negated, z[0]);
uint8_t y[8][8] = {{0}, {0}}; uint8_t y[8][8] = {{0}, {0}};
// y[0]=DES_dec(z[0],~key) // y[0]=DES_dec(z[0],~key)
// Once again, key is on iclass-format // Once again, key is on iclass-format
desdecrypt_iclass(z[0], key64_negated, y[0]); loclass_desdecrypt_iclass(z[0], key64_negated, y[0]);
for (i = 1; i < 8; i++) { for (i = 1; i < 8; i++) {
rk(key64, i, temp_output); loclass_rk(key64, i, temp_output);
desdecrypt_iclass(temp_output, z[i - 1], z[i]); loclass_desdecrypt_iclass(temp_output, z[i - 1], z[i]);
desencrypt_iclass(temp_output, y[i - 1], y[i]); loclass_desencrypt_iclass(temp_output, y[i - 1], y[i]);
} }
if (outp_keytable != NULL) { if (outp_keytable != NULL) {

View File

@ -38,21 +38,21 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
void permutekey(const uint8_t key[8], uint8_t dest[8]); void loclass_permutekey(const uint8_t key[8], uint8_t dest[8]);
/** /**
* Permutes a key from iclass specific format to NIST format * Permutes a key from iclass specific format to NIST format
* @brief permutekey_rev * @brief loclass_permutekey_rev
* @param key * @param key
* @param dest * @param dest
*/ */
void permutekey_rev(const uint8_t key[8], uint8_t dest[8]); void loclass_permutekey_rev(const uint8_t key[8], uint8_t dest[8]);
/** /**
* Hash1 takes CSN as input, and determines what bytes in the keytable will be used * Hash1 takes CSN as input, and determines what bytes in the keytable will be used
* when constructing the K_sel. * when constructing the K_sel.
* @param csn the CSN used * @param csn the CSN used
* @param k output * @param k output
*/ */
void hash1(const uint8_t *csn, uint8_t *k); void loclass_hash1(const uint8_t *csn, uint8_t *k);
void hash2(uint8_t *key64, uint8_t *outp_keytable); void loclass_hash2(uint8_t *key64, uint8_t *outp_keytable);
#endif #endif

View File

@ -39,18 +39,18 @@ From "Dismantling iclass":
algorithm intends to circumvent weaknesses in the cipher by preventing the algorithm intends to circumvent weaknesses in the cipher by preventing the
usage of certain weak keys. In order to compute a diversified key, the iClass usage of certain weak keys. In order to compute a diversified key, the iClass
reader first encrypts the card identity id with the master key K, using single reader first encrypts the card identity id with the master key K, using single
DES. The resulting ciphertext is then input to a function called hash0 which DES. The resulting ciphertext is then input to a function called loclass_hash0 which
outputs the diversified key k. outputs the diversified key k.
k = hash0(DES enc (id, K)) k = loclass_hash0(DES enc (id, K))
Here the DES encryption of id with master key K outputs a cryptogram c Here the DES encryption of id with master key K outputs a cryptogram c
of 64 bits. These 64 bits are divided as c = x, y, z [0] , . . . , z [7] F 82 × F 82 × (F 62 ) 8 of 64 bits. These 64 bits are divided as c = x, y, z [0] , . . . , z [7] F 82 × F 82 × (F 62 ) 8
which is used as input to the hash0 function. This function introduces some which is used as input to the loclass_hash0 function. This function introduces some
obfuscation by performing a number of permutations, complement and modulo obfuscation by performing a number of permutations, complement and modulo
operations, see Figure 2.5. Besides that, it checks for and removes patterns like operations, see Figure 2.5. Besides that, it checks for and removes patterns like
similar key bytes, which could produce a strong bias in the cipher. Finally, the similar key bytes, which could produce a strong bias in the cipher. Finally, the
output of hash0 is the diversified card key k = k [0] , . . . , k [7] (F 82 ) 8 . output of loclass_hash0 is the diversified card key k = k [0] , . . . , k [7] (F 82 ) 8 .
**/ **/
#include "optimized_ikeys.h" #include "optimized_ikeys.h"
@ -61,7 +61,7 @@ From "Dismantling iclass":
#include <mbedtls/des.h> #include <mbedtls/des.h>
#include "optimized_cipherutils.h" #include "optimized_cipherutils.h"
static uint8_t pi[35] = { static const uint8_t loclass_pi[35] = {
0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D, 0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D,
0x2E, 0x33, 0x35, 0x39, 0x36, 0x3A, 0x3C, 0x47, 0x2E, 0x33, 0x35, 0x39, 0x36, 0x3A, 0x3C, 0x47,
0x4B, 0x4D, 0x4E, 0x53, 0x55, 0x56, 0x59, 0x5A, 0x4B, 0x4D, 0x4E, 0x53, 0x55, 0x56, 0x59, 0x5A,
@ -69,8 +69,6 @@ static uint8_t pi[35] = {
0x72, 0x74, 0x78 0x72, 0x74, 0x78
}; };
static mbedtls_des_context ctx_enc;
/** /**
* @brief The key diversification algorithm uses 6-bit bytes. * @brief The key diversification algorithm uses 6-bit bytes.
* This implementation uses 64 bit uint to pack seven of them into one * This implementation uses 64 bit uint to pack seven of them into one
@ -82,7 +80,7 @@ static mbedtls_des_context ctx_enc;
* @param n bitnumber * @param n bitnumber
* @return * @return
*/ */
static uint8_t getSixBitByte(uint64_t c, int n) { static uint8_t loclass_getSixBitByte(uint64_t c, int n) {
return (c >> (42 - 6 * n)) & 0x3F; return (c >> (42 - 6 * n)) & 0x3F;
} }
@ -92,7 +90,7 @@ static uint8_t getSixBitByte(uint64_t c, int n) {
* @param z the value to place there * @param z the value to place there
* @param n bitnumber. * @param n bitnumber.
*/ */
static void pushbackSixBitByte(uint64_t *c, uint8_t z, int n) { static void loclass_pushbackSixBitByte(uint64_t *c, uint8_t z, int n) {
//0x XXXX YYYY ZZZZ ZZZZ ZZZZ //0x XXXX YYYY ZZZZ ZZZZ ZZZZ
// ^z0 ^z7 // ^z0 ^z7
//z0: 1111 1100 0000 0000 //z0: 1111 1100 0000 0000
@ -117,16 +115,16 @@ static void pushbackSixBitByte(uint64_t *c, uint8_t z, int n) {
* @param c * @param c
* @return * @return
*/ */
static uint64_t swapZvalues(uint64_t c) { static uint64_t loclass_swapZvalues(uint64_t c) {
uint64_t newz = 0; uint64_t newz = 0;
pushbackSixBitByte(&newz, getSixBitByte(c, 0), 7); loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 0), 7);
pushbackSixBitByte(&newz, getSixBitByte(c, 1), 6); loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 1), 6);
pushbackSixBitByte(&newz, getSixBitByte(c, 2), 5); loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 2), 5);
pushbackSixBitByte(&newz, getSixBitByte(c, 3), 4); loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 3), 4);
pushbackSixBitByte(&newz, getSixBitByte(c, 4), 3); loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 4), 3);
pushbackSixBitByte(&newz, getSixBitByte(c, 5), 2); loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 5), 2);
pushbackSixBitByte(&newz, getSixBitByte(c, 6), 1); loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 6), 1);
pushbackSixBitByte(&newz, getSixBitByte(c, 7), 0); loclass_pushbackSixBitByte(&newz, loclass_getSixBitByte(c, 7), 0);
newz |= (c & 0xFFFF000000000000); newz |= (c & 0xFFFF000000000000);
return newz; return newz;
} }
@ -134,58 +132,58 @@ static uint64_t swapZvalues(uint64_t c) {
/** /**
* @return 4 six-bit bytes chunked into a uint64_t,as 00..00a0a1a2a3 * @return 4 six-bit bytes chunked into a uint64_t,as 00..00a0a1a2a3
*/ */
static uint64_t ck(int i, int j, uint64_t z) { static uint64_t loclass_ck(int i, int j, uint64_t z) {
if (i == 1 && j == -1) { if (i == 1 && j == -1) {
// ck(1, 1, z [0] . . . z [3] ) = z [0] . . . z [3] // loclass_ck(1, 1, z [0] . . . z [3] ) = z [0] . . . z [3]
return z; return z;
} else if (j == -1) { } else if (j == -1) {
// ck(i, 1, z [0] . . . z [3] ) = ck(i 1, i 2, z [0] . . . z [3] ) // loclass_ck(i, 1, z [0] . . . z [3] ) = loclass_ck(i 1, i 2, z [0] . . . z [3] )
return ck(i - 1, i - 2, z); return loclass_ck(i - 1, i - 2, z);
} }
if (getSixBitByte(z, i) == getSixBitByte(z, j)) { if (loclass_getSixBitByte(z, i) == loclass_getSixBitByte(z, j)) {
//ck(i, j 1, z [0] . . . z [i] ← j . . . z [3] ) //loclass_ck(i, j 1, z [0] . . . z [i] ← j . . . z [3] )
uint64_t newz = 0; uint64_t newz = 0;
int c; int c;
for (c = 0; c < 4; c++) { for (c = 0; c < 4; c++) {
uint8_t val = getSixBitByte(z, c); uint8_t val = loclass_getSixBitByte(z, c);
if (c == i) if (c == i)
pushbackSixBitByte(&newz, j, c); loclass_pushbackSixBitByte(&newz, j, c);
else else
pushbackSixBitByte(&newz, val, c); loclass_pushbackSixBitByte(&newz, val, c);
} }
return ck(i, j - 1, newz); return loclass_ck(i, j - 1, newz);
} else { } else {
return ck(i, j - 1, z); return loclass_ck(i, j - 1, z);
} }
} }
/** /**
Definition 8. Definition 8.
Let the function check : (F 62 ) 8 (F 62 ) 8 be defined as Let the function check : (F 62 ) 8 (F 62 ) 8 be defined as
check(z [0] . . . z [7] ) = ck(3, 2, z [0] . . . z [3] ) · ck(3, 2, z [4] . . . z [7] ) check(z [0] . . . z [7] ) = loclass_ck(3, 2, z [0] . . . z [3] ) · loclass_ck(3, 2, z [4] . . . z [7] )
where ck : N × N × (F 62 ) 4 (F 62 ) 4 is defined as where loclass_ck : N × N × (F 62 ) 4 (F 62 ) 4 is defined as
ck(1, 1, z [0] . . . z [3] ) = z [0] . . . z [3] loclass_ck(1, 1, z [0] . . . z [3] ) = z [0] . . . z [3]
ck(i, 1, z [0] . . . z [3] ) = ck(i 1, i 2, z [0] . . . z [3] ) loclass_ck(i, 1, z [0] . . . z [3] ) = loclass_ck(i 1, i 2, z [0] . . . z [3] )
ck(i, j, z [0] . . . z [3] ) = loclass_ck(i, j, z [0] . . . z [3] ) =
ck(i, j 1, z [0] . . . z [i] j . . . z [3] ), if z [i] = z [j] ; loclass_ck(i, j 1, z [0] . . . z [i] j . . . z [3] ), if z [i] = z [j] ;
ck(i, j 1, z [0] . . . z [3] ), otherwise loclass_ck(i, j 1, z [0] . . . z [3] ), otherwise
otherwise. otherwise.
**/ **/
static uint64_t check(uint64_t z) { static uint64_t loclass_check(uint64_t z) {
//These 64 bits are divided as c = x, y, z [0] , . . . , z [7] //These 64 bits are divided as c = x, y, z [0] , . . . , z [7]
// ck(3, 2, z [0] . . . z [3] ) // loclass_ck(3, 2, z [0] . . . z [3] )
uint64_t ck1 = ck(3, 2, z); uint64_t ck1 = loclass_ck(3, 2, z);
// ck(3, 2, z [4] . . . z [7] ) // loclass_ck(3, 2, z [4] . . . z [7] )
uint64_t ck2 = ck(3, 2, z << 24); uint64_t ck2 = loclass_ck(3, 2, z << 24);
//The ck function will place the values //The loclass_ck function will place the values
// in the middle of z. // in the middle of z.
ck1 &= 0x00000000FFFFFF000000; ck1 &= 0x00000000FFFFFF000000;
ck2 &= 0x00000000FFFFFF000000; ck2 &= 0x00000000FFFFFF000000;
@ -193,28 +191,28 @@ static uint64_t check(uint64_t z) {
return ck1 | ck2 >> 24; return ck1 | ck2 >> 24;
} }
static void permute(BitstreamIn_t *p_in, uint64_t z, int l, int r, BitstreamOut_t *out) { static void loclass_permute(LoclassBitstreamIn_t *p_in, uint64_t z, int l, int r, LoclassBitstreamOut_t *out) {
if (bitsLeft(p_in) == 0) if (loclass_bitsLeft(p_in) == 0)
return; return;
bool pn = tailBit(p_in); bool pn = loclass_tailBit(p_in);
if (pn) { // pn = 1 if (pn) { // pn = 1
uint8_t zl = getSixBitByte(z, l); uint8_t zl = loclass_getSixBitByte(z, l);
push6bits(out, zl + 1); loclass_push6bits(out, zl + 1);
permute(p_in, z, l + 1, r, out); loclass_permute(p_in, z, l + 1, r, out);
} else { // otherwise } else { // otherwise
uint8_t zr = getSixBitByte(z, r); uint8_t zr = loclass_getSixBitByte(z, r);
push6bits(out, zr); loclass_push6bits(out, zr);
permute(p_in, z, l, r + 1, out); loclass_permute(p_in, z, l, r + 1, out);
} }
} }
/** /**
* @brief * @brief
*Definition 11. Let the function hash0 : F 82 × F 82 × (F 62 ) 8 (F 82 ) 8 be defined as *Definition 11. Let the function loclass_hash0 : F 82 × F 82 × (F 62 ) 8 (F 82 ) 8 be defined as
* hash0(x, y, z [0] . . . z [7] ) = k [0] . . . k [7] where * loclass_hash0(x, y, z [0] . . . z [7] ) = k [0] . . . k [7] where
* z'[i] = (z[i] mod (63-i)) + i i = 0...3 * z'[i] = (z[i] mod (63-i)) + i i = 0...3
* z'[i+4] = (z[i+4] mod (64-i)) + i i = 0...3 * z'[i+4] = (z[i+4] mod (64-i)) + i i = 0...3
* = check(z'); * = check(z');
@ -222,8 +220,8 @@ static void permute(BitstreamIn_t *p_in, uint64_t z, int l, int r, BitstreamOut_
* @param k this is where the diversified key is put (should be 8 bytes) * @param k this is where the diversified key is put (should be 8 bytes)
* @return * @return
*/ */
void hash0(uint64_t c, uint8_t k[8]) { void loclass_hash0(uint64_t c, uint8_t k[8]) {
c = swapZvalues(c); c = loclass_swapZvalues(c);
//These 64 bits are divided as c = x, y, z [0] , . . . , z [7] //These 64 bits are divided as c = x, y, z [0] , . . . , z [7]
// x = 8 bits // x = 8 bits
@ -234,30 +232,30 @@ void hash0(uint64_t c, uint8_t k[8]) {
uint64_t zP = 0; uint64_t zP = 0;
for (int n = 0; n < 4 ; n++) { for (int n = 0; n < 4 ; n++) {
uint8_t zn = getSixBitByte(c, n); uint8_t zn = loclass_getSixBitByte(c, n);
uint8_t zn4 = getSixBitByte(c, n + 4); uint8_t zn4 = loclass_getSixBitByte(c, n + 4);
uint8_t _zn = (zn % (63 - n)) + n; uint8_t _zn = (zn % (63 - n)) + n;
uint8_t _zn4 = (zn4 % (64 - n)) + n; uint8_t _zn4 = (zn4 % (64 - n)) + n;
pushbackSixBitByte(&zP, _zn, n); loclass_pushbackSixBitByte(&zP, _zn, n);
pushbackSixBitByte(&zP, _zn4, n + 4); loclass_pushbackSixBitByte(&zP, _zn4, n + 4);
} }
uint64_t zCaret = check(zP); uint64_t zCaret = loclass_check(zP);
uint8_t p = pi[x % 35]; uint8_t p = loclass_pi[x % 35];
if (x & 1) //Check if x7 is 1 if (x & 1) //Check if x7 is 1
p = ~p; p = ~p;
BitstreamIn_t p_in = { &p, 8, 0 }; LoclassBitstreamIn_t p_in = { &p, 8, 0 };
uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamOut_t out = {outbuffer, 0, 0}; LoclassBitstreamOut_t out = {outbuffer, 0, 0};
permute(&p_in, zCaret, 0, 4, &out); //returns 48 bits? or 6 8-bytes loclass_permute(&p_in, zCaret, 0, 4, &out); //returns 48 bits? or 6 8-bytes
//Out is now a buffer containing six-bit bytes, should be 48 bits //Out is now a buffer containing six-bit bytes, should be 48 bits
// if all went well // if all went well
//Shift z-values down onto the lower segment //Shift z-values down onto the lower segment
uint64_t zTilde = x_bytes_to_num(outbuffer, sizeof(outbuffer)); uint64_t zTilde = loclass_x_bytes_to_num(outbuffer, sizeof(outbuffer));
zTilde >>= 16; zTilde >>= 16;
@ -274,7 +272,7 @@ void hash0(uint64_t c, uint8_t k[8]) {
// First, place y(7-i) leftmost in k // First, place y(7-i) leftmost in k
k[i] |= (y << (7 - i)) & 0x80 ; k[i] |= (y << (7 - i)) & 0x80 ;
uint8_t zTilde_i = getSixBitByte(zTilde, i); uint8_t zTilde_i = loclass_getSixBitByte(zTilde, i);
// zTildeI is now on the form 00XXXXXX // zTildeI is now on the form 00XXXXXX
// with one leftshift, it'll be // with one leftshift, it'll be
// 0XXXXXX0 // 0XXXXXX0
@ -304,18 +302,20 @@ void hash0(uint64_t c, uint8_t k[8]) {
* @param key * @param key
* @param div_key * @param div_key
*/ */
void diversifyKey(uint8_t *csn, const uint8_t *key, uint8_t *div_key) { void loclass_diversifyKey(uint8_t *csn, const uint8_t *key, uint8_t *div_key) {
mbedtls_des_context loclass_ctx_enc;
// Prepare the DES key // Prepare the DES key
mbedtls_des_setkey_enc(&ctx_enc, key); mbedtls_des_setkey_enc(&loclass_ctx_enc, key);
uint8_t crypted_csn[8] = {0}; uint8_t crypted_csn[8] = {0};
// Calculate DES(CSN, KEY) // Calculate DES(CSN, KEY)
mbedtls_des_crypt_ecb(&ctx_enc, csn, crypted_csn); mbedtls_des_crypt_ecb(&loclass_ctx_enc, csn, crypted_csn);
//Calculate HASH0(DES)) //Calculate HASH0(DES))
uint64_t c_csn = x_bytes_to_num(crypted_csn, sizeof(crypted_csn)); uint64_t c_csn = loclass_x_bytes_to_num(crypted_csn, sizeof(crypted_csn));
hash0(c_csn, div_key); loclass_hash0(c_csn, div_key);
} }

View File

@ -39,8 +39,8 @@
/** /**
* @brief * @brief
*Definition 11. Let the function hash0 : F 82 × F 82 × (F 62 ) 8 (F 82 ) 8 be defined as *Definition 11. Let the function loclass_hash0 : F 82 × F 82 × (F 62 ) 8 (F 82 ) 8 be defined as
* hash0(x, y, z [0] . . . z [7] ) = k [0] . . . k [7] where * loclass_hash0(x, y, z [0] . . . z [7] ) = k [0] . . . k [7] where
* z'[i] = (z[i] mod (63-i)) + i i = 0...3 * z'[i] = (z[i] mod (63-i)) + i i = 0...3
* z'[i+4] = (z[i+4] mod (64-i)) + i i = 0...3 * z'[i+4] = (z[i+4] mod (64-i)) + i i = 0...3
* = check(z'); * = check(z');
@ -48,7 +48,7 @@
* @param k this is where the diversified key is put (should be 8 bytes) * @param k this is where the diversified key is put (should be 8 bytes)
* @return * @return
*/ */
void hash0(uint64_t c, uint8_t k[8]); void loclass_hash0(uint64_t c, uint8_t k[8]);
/** /**
* @brief Performs Elite-class key diversification * @brief Performs Elite-class key diversification
* @param csn * @param csn
@ -56,7 +56,7 @@ void hash0(uint64_t c, uint8_t k[8]);
* @param div_key * @param div_key
*/ */
void diversifyKey(uint8_t *csn, const uint8_t *key, uint8_t *div_key); void loclass_diversifyKey(uint8_t *csn, const uint8_t *key, uint8_t *div_key);
/** /**
* @brief Permutes a key from standard NIST format to Iclass specific format * @brief Permutes a key from standard NIST format to Iclass specific format
* @param key * @param key