1 /*****************************************************************************
2 * This file is part of iClassCipher. It is a reconstructon of the cipher engine
3 * used in iClass, and RFID techology.
5 * The implementation is based on the work performed by
6 * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
7 * Milosch Meriac in the paper "Dismantling IClass".
9 * Copyright (C) 2014 Martin Holst Swende
11 * This is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation.
15 * This file is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
22 ****************************************************************************/
24 #include "cipherutils.h"
32 * @brief Return and remove the first bit (x0) in the stream : <x0 x1 x2 x3 ... xn >
36 bool headBit( BitstreamIn
*stream
)
38 int bytepos
= stream
->position
>> 3; // divide by 8
39 int bitpos
= (stream
->position
++) & 7; // mask out 00000111
40 return (*(stream
->buffer
+ bytepos
) >> (7-bitpos
)) & 1;
43 * @brief Return and remove the last bit (xn) in the stream: <x0 x1 x2 ... xn>
47 bool tailBit( BitstreamIn
*stream
)
49 int bitpos
= stream
->numbits
-1 - (stream
->position
++);
51 int bytepos
= bitpos
>> 3;
53 return (*(stream
->buffer
+ bytepos
) >> (7-bitpos
)) & 1;
56 * @brief Pushes bit onto the stream
60 void pushBit( BitstreamOut
* stream
, bool bit
)
62 int bytepos
= stream
->position
>> 3; // divide by 8
63 int bitpos
= stream
->position
& 7;
64 *(stream
->buffer
+bytepos
) |= (bit
& 1) << (7 - bitpos
);
70 * @brief Pushes the lower six bits onto the stream
71 * as b0 b1 b2 b3 b4 b5 b6
75 void push6bits( BitstreamOut
* stream
, uint8_t bits
)
77 pushBit(stream
, bits
& 0x20);
78 pushBit(stream
, bits
& 0x10);
79 pushBit(stream
, bits
& 0x08);
80 pushBit(stream
, bits
& 0x04);
81 pushBit(stream
, bits
& 0x02);
82 pushBit(stream
, bits
& 0x01);
88 * @return number of bits left in stream
90 int bitsLeft( BitstreamIn
*stream
)
92 return stream
->numbits
- stream
->position
;
97 * @return Number of bits stored in stream
99 int numBits(BitstreamOut
*stream
)
101 return stream
->numbits
;
104 uint8_t reversebytes(uint8_t b
) {
105 b
= (b
& 0xF0) >> 4 | (b
& 0x0F) << 4;
106 b
= (b
& 0xCC) >> 2 | (b
& 0x33) << 2;
107 b
= (b
& 0xAA) >> 1 | (b
& 0x55) << 1;
110 void reverse_arraybytes(uint8_t* arr
, size_t len
)
113 for( i
=0; i
< len
; i
++)
115 arr
[i
] = reversebytes(arr
[i
]);
120 //-----------------------------
121 // Code for testing below
122 //-----------------------------
127 uint8_t input
[] = {0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF};
128 uint8_t output
[] = {0,0,0,0,0,0,0,0};
129 BitstreamIn in
= { input
, sizeof(input
) * 8,0};
130 BitstreamOut out
={ output
, 0,0}
132 while(bitsLeft(&in
) > 0)
134 pushBit(&out
, headBit(&in
));
135 //printf("Bits left: %d\n", bitsLeft(&in));
136 //printf("Bits out: %d\n", numBits(&out));
138 if(memcmp(input
, output
, sizeof(input
)) == 0)
140 printf("Bitstream test 1 ok\n");
143 printf("Bitstream test 1 failed\n");
145 for(i
= 0 ; i
< sizeof(input
) ; i
++)
147 printf("IN %02x, OUT %02x\n", input
[i
], output
[i
]);
154 int testReversedBitstream()
156 uint8_t input
[] = {0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF};
157 uint8_t reverse
[] = {0,0,0,0,0,0,0,0};
158 uint8_t output
[] = {0,0,0,0,0,0,0,0};
159 BitstreamIn in
= { input
, sizeof(input
) * 8,0};
160 BitstreamOut out
={ output
, 0,0};
161 BitstreamIn reversed_in
={ reverse
, sizeof(input
)*8,0};
162 BitstreamOut reversed_out
={ reverse
,0 ,0};
164 while(bitsLeft(&in
) > 0)
166 pushBit(&reversed_out
, tailBit(&in
));
168 while(bitsLeft(&reversed_in
) > 0)
170 pushBit(&out
, tailBit(&reversed_in
));
172 if(memcmp(input
, output
, sizeof(input
)) == 0)
174 printf("Bitstream test 2 ok\n");
177 printf("Bitstream test 2 failed\n");
179 for(i
= 0 ; i
< sizeof(input
) ; i
++)
181 printf("IN %02x, MIDDLE: %02x, OUT %02x\n", input
[i
],reverse
[i
], output
[i
]);
189 int testCipherUtils(void)
192 retval
|= testBitStream();
193 retval
|= testReversedBitstream();