hf seos - added the skeleton for future use
[RRG-proxmark3.git] / armsrc / wiegand.c
blobcd4fb3eb671ece40cea4f27fc7beba602377076d
1 //-----------------------------------------------------------------------------
2 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
3 // at your option, any later version. See the LICENSE.txt file for the text of
4 // the license.
5 //-----------------------------------------------------------------------------
6 // Wiegand functions
7 //-----------------------------------------------------------------------------
9 #include "wiegand.h"
12 * @brief getParity
13 * @param bits pointer to the source bitstream of binary values 0|1
14 * @param len how long shall parity be calculated
15 * @param type use the defined values EVEN|ODD
16 * @return parity bit required to match type
18 uint8_t getParity(uint8_t *bits, uint8_t len, uint8_t type) {
19 uint8_t x = 0;
20 for (; len > 0; --len)
21 x += bits[len - 1];
23 return (x & 1) ^ type;
26 // by marshmellow
27 /* pass bits to be tested in bits, length bits passed in bitLen, and parity type EVEN|ODD in type
28 * @brief checkParity
29 * @param bits pointer to the source bitstream of binary values 0|1
30 * @param len number of bits to be checked
31 * @param type use the defined values EVEN|ODD
32 * @return 1 if passed
34 uint8_t checkParity(uint32_t bits, uint8_t len, uint8_t type);
36 // by marshmellow
37 // takes a array of binary values, start position, length of bits per parity (includes parity bit),
38 // Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run)
39 size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) {
40 uint32_t parityWd = 0;
41 size_t j = 0, bitcount = 0;
42 for (int word = 0; word < (bLen); word += pLen) {
43 for (int bit = 0; bit < pLen; ++bit) {
44 parityWd = (parityWd << 1) | bits[startIdx + word + bit];
45 bits[j++] = (bits[startIdx + word + bit]);
47 j--; // overwrite parity with next data
48 // if parity fails then return 0
49 switch (pType) {
50 case 3:
51 if (bits[j] == 1) return 0;
52 break; //should be 0 spacer bit
53 case 2:
54 if (bits[j] == 0) return 0;
55 break; //should be 1 spacer bit
56 default: //test parity
57 if (parityTest(parityWd, pLen, pType) == 0) return 0;
58 break;
60 bitcount += (pLen - 1);
61 parityWd = 0;
63 // if we got here then all the parities passed
64 //return ID start index and size
65 return bitcount;
69 // by marshmellow
70 // takes a array of binary values, length of bits per parity (includes parity bit),
71 // Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
72 // Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
74 * @brief addParity
75 * @param src pointer to the source bitstream of binary values
76 * @param dest pointer to the destination where parities together with bits are added.
77 * @param sourceLen number of
78 * @param pLen length bits to be checked
79 * @param pType EVEN|ODD|2 (always 1's)|3 (always 0's)
80 * @return
82 size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) {
83 uint32_t parityWd = 0;
84 size_t j = 0, bitCnt = 0;
85 for (int word = 0; word < sourceLen; word += pLen - 1) {
86 for (int bit = 0; bit < pLen - 1; ++bit) {
87 parityWd = (parityWd << 1) | src[word + bit];
88 dest[j++] = (src[word + bit]);
91 // if parity fails then return 0
92 switch (pType) {
93 case 3:
94 dest[j++] = 0;
95 break; // marker bit which should be a 0
96 case 2:
97 dest[j++] = 1;
98 break; // marker bit which should be a 1
99 default:
100 dest[j++] = parityTest(parityWd, pLen - 1, pType) ^ 1;
101 break;
103 bitCnt += pLen;
104 parityWd = 0;
106 // if we got here then all the parities passed
107 //return ID start index and size
108 return bitCnt;
111 // by marshmellow
113 * add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
114 * @brief wiegand_add_parity
115 * @param source pointer to source of binary data
116 * @param dest pointer to the destination where wiegandparity has been appended
117 * @param len number of bits which wiegand parity shall be calculated over. This number is without parities, so a wiegand 26 has 24 bits of data
119 void wiegand_add_parity(uint8_t *source, uint8_t *dest, uint8_t len) {
121 // Copy to destination, shifted one step to make room for EVEN parity
122 memcpy(dest + 1, source, length);
124 // half length, Even and Odd is calculated to the middle.
125 uint8_t len_h2 = length >> 1;
127 // add EVEN parity at the beginning
128 *(dest) = GetParity(source, EVEN, len_h2);
130 dest += length + 1;
132 // add ODD parity at the very end
133 *(dest) = GetParity(source + len_h2, ODD, len_h2);
136 //uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
137 #define MAX_BITS_TXX55 6*4*8
138 #define MAX_BYTES_TXX55 6*4
140 * @brief num_to_wiegand_bytes
141 * @param oem Sometimes call FF Fixfield, SiteCode. Used in a few formats
142 * @param fc Facility code
143 * @param cn Card number
144 * @param dest pointer to the destination where wiegand bytes will be stored
145 * @param formatlen
147 void num_to_wiegand_bytes(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen) {
149 uint8_t data[MAX_BITS_TXX55] = {0};
150 memset(data, 0, sizeof(data));
152 num_to_wiegand_bits(oem, fc, cn, data, formatlen);
154 // loop
155 // (formatlen / 32 ) + 1
156 // (formatlen >> 5) + 1
157 for (int i = 0; i < formatlen ; ++i) {
158 uint32_t value = bytebits_to_byte(data + (i * 32), 32);
159 num_to_bytes(value, 32, dest + (i * 4));
164 * @brief num_to_wiegand_bits
165 * @param oem Sometimes call FF Fixfield, SiteCode. Used in a few formats
166 * @param fc Facility code
167 * @param cn Card number
168 * @param dest pointer to the destination where wiegand bits will be stored
169 * @param formatlen
171 void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen) {
173 uint8_t bits[MAX_BITS_TXX55] = {0};
174 memset(bits, 0, sizeof(bits));
175 uint8_t *temp = bits;
176 uint64_t value = 0;
178 switch (formatlen) {
179 case 26 : // 26bit HID H10301
180 fc &= 0xFF; // 8bits
181 cn &= 0xFFFF; // 16bits
182 value = fc << 16 | cn;
183 num_to_bytebits(value, 24, temp);
184 wiegand_add_parity(temp, dest, 24);
185 break;
186 case 261: // 26bit Indala
187 fc &= 0xFFF; // 12bits
188 cn &= 0xFFF; // 12bits
189 value = fc << 12 | cn;
190 num_to_bytebits(value, 24, temp);
191 wiegand_add_parity(temp, dest, 24);
192 break;
193 case 34 : // 34bits HID
194 fc &= 0xFFFF; // 16bits
195 cn &= 0xFFFF; // 16bits
196 value = fc << 16 | cn;
197 num_to_bytebits(value, 32, temp);
198 wiegand_add_parity(temp, dest, 32);
199 break;
200 case 35 : // 35bits HID
201 fc &= 0xFFF; // 12bits
202 cn &= 0xFFFFFF; // 20bits
203 value = fc << 20 | cn;
204 num_to_bytebits(value, 32, temp);
205 wiegand_add_parity(temp, dest, 32);
206 break;
207 case 37 : // H10304
208 fc &= 0xFFFF; // 16bits
209 cn &= 0x7FFFF; // 19bits
210 value = fc << 19 | cn;
211 num_to_bytebits(value, 35, temp);
212 wiegand_add_parity(temp, dest, 35);
213 break;
214 case 39 : // 39bit KERI System Pyramid
215 fc &= 0x1FFFF; // 17bits
216 cn &= 0xFFFFFFFF; // 20bits
217 value = fc << 20 | cn;
218 num_to_bytebits(value, 37, temp);
219 wiegand_add_parity(temp, dest, 37);
220 break;
221 case 44 : // 44bit KERI system Pyramid
222 oem &= 0xFF; // 8bits
223 fc &= 0xFFF; // 12bits
224 cn &= 0xFFFFFFFF; // 21bits
225 value = oem << 20 | fc << 12 | cn;
226 num_to_bytebits(value, 42, temp);
227 wiegand_add_parity(temp, dest, 42);
228 break;
229 case 50 : // AWID 50 RBH
230 fc &= 0xFFFF; // 16bits
231 cn &= 0xFFFFFFFF; // 32bits
232 value = fc << 32 | cn;
233 num_to_bytebits(value, 48, temp);
234 wiegand_add_parity(temp, dest, 48); // verify!
235 break;
236 default:
237 break;