-/*
- * Hitag2 emulation
- *
- * Contains state and functions for an emulated Hitag2 tag. Offers an entry
- * point to handle commands, needs a callback to send response.
- *
- * (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
- */
-
-#include <proxmark3.h>
-#include <stdint.h>
-
+//-----------------------------------------------------------------------------
+// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Hitag2 emulation
+//
+// Contains state and functions for an emulated Hitag2 tag. Offers an entry
+// point to handle commands, needs a callback to send response.
+//-----------------------------------------------------------------------------
+
+#include "proxmark3.h"
#include "apps.h"
+#include "util.h"
#include "hitag2.h"
+#include "string.h"
struct hitag2_cipher_state {
uint64_t state;
struct hitag2_tag {
uint32_t uid;
- enum {
+ enum {
TAG_STATE_RESET, // Just powered up, awaiting GetSnr
TAG_STATE_ACTIVATING, // In activation phase (password mode), sent UID, awaiting reader password
TAG_STATE_AUTHENTICATING, // In activation phase (crypto mode), awaiting reader authentication
data = temp;
}
-
+
handle_command_retry:
switch(tag.state) {
case TAG_STATE_RESET:
/* transmission error */
DbpString("Transmission error (write) in activated state");
}
- }
-
+ }
+
}
case TAG_STATE_WRITING:
if(length == 32) {
done=1;
}
}
-
+
if(!done && !retry) {
/* We didn't respond, maybe our state is faulty. Reset and try again. */
retry=1;
static u32 _f20 (const u64 x)
{
u32 i5;
-
+
i5 = ((ht2_f4a >> i4 (x, 1, 2, 4, 5)) & 1)* 1
+ ((ht2_f4b >> i4 (x, 7,11,13,14)) & 1)* 2
+ ((ht2_f4b >> i4 (x,16,20,22,25)) & 1)* 4
+ ((ht2_f4b >> i4 (x,27,28,30,32)) & 1)* 8
+ ((ht2_f4a >> i4 (x,33,42,43,45)) & 1)*16;
-
+
return (ht2_f5c >> i5) & 1;
}
{
u32 i;
u64 x = ((key & 0xFFFF) << 32) + serial;
-
+
for (i = 0; i < 32; i++)
{
x >>= 1;
static u64 _hitag2_round (u64 *state)
{
u64 x = *state;
-
+
x = (x >> 1) +
((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6)
^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22)
^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41)
^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47);
-
+
*state = x;
return _f20 (x);
}
-// Bitslice Hitag2 functions:
-
-#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b))
-#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b)))
-#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c))))
-
-#define uf20bs u32 // choose your own type/width
-
-static uf20bs _f20bs (const uf20bs *x)
-{
- return ht2bs_5c (
- ht2bs_4a(x[ 1],x[ 2],x[ 4],x[ 5]),
- ht2bs_4b(x[ 7],x[11],x[13],x[14]),
- ht2bs_4b(x[16],x[20],x[22],x[25]),
- ht2bs_4b(x[27],x[28],x[30],x[32]),
- ht2bs_4a(x[33],x[42],x[43],x[45]));
-}
-
-static void _hitag2bs_init (uf20bs *x, const uf20bs *key, const uf20bs *serial, const uf20bs *IV)
-{
- u32 i, r;
-
- for (i = 0; i < 32; i++) x[i] = serial[i];
- for (i = 0; i < 16; i++) x[32+i] = key[i];
-
- for (r = 0; r < 32; r++)
- {
- for (i = 0; i < 47; i++) x[i] = x[i+1];
- x[47] = _f20bs (x) ^ IV[i] ^ key[16+i];
- }
-}
-
-static uf20bs _hitag2bs_round (uf20bs *x)
-{
- uf20bs y;
- u32 i;
-
- y = x[ 0] ^ x[ 2] ^ x[ 3] ^ x[ 6] ^ x[ 7] ^ x[ 8] ^ x[16] ^ x[22]
- ^ x[23] ^ x[26] ^ x[30] ^ x[41] ^ x[42] ^ x[43] ^ x[46] ^ x[47];
-
- for (i = 0; i < 47; i++) x[i] = x[i+1];
- x[47] = y;
-
- return _f20bs (x);
-}
-
static u32 _hitag2_byte (u64 * x)
{
u32 i, c;
-
+
for (i = 0, c = 0; i < 8; i++) c += (u32) _hitag2_round (x) << (i^7);
return c;
}