Merge pull request #2616 from jmichelp/fix14b
[RRG-proxmark3.git] / armsrc / wiegand.c
blob4de79b8aced802e1727c17adf98d418c09a91c40
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Generic Wiegand Calculation code
17 //-----------------------------------------------------------------------------
19 #include "wiegand.h"
22 * @brief getParity
23 * @param bits pointer to the source bitstream of binary values 0|1
24 * @param len how long shall parity be calculated
25 * @param type use the defined values EVEN|ODD
26 * @return parity bit required to match type
28 uint8_t getParity(const uint8_t *bits, uint8_t len, uint8_t type) {
29 uint8_t x = 0;
30 for (; len > 0; --len)
31 x += bits[len - 1];
33 return (x & 1) ^ type;
36 // by marshmellow
37 /* pass bits to be tested in bits, length bits passed in bitLen, and parity type EVEN|ODD in type
38 * @brief checkParity
39 * @param bits pointer to the source bitstream of binary values 0|1
40 * @param len number of bits to be checked
41 * @param type use the defined values EVEN|ODD
42 * @return 1 if passed
44 uint8_t checkParity(uint32_t bits, uint8_t len, uint8_t type);
46 // by marshmellow
47 // takes a array of binary values, start position, length of bits per parity (includes parity bit),
48 // Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run)
49 size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) {
50 uint32_t parityWd = 0;
51 size_t j = 0, bitcount = 0;
52 for (int word = 0; word < (bLen); word += pLen) {
53 for (int bit = 0; bit < pLen; ++bit) {
54 parityWd = (parityWd << 1) | bits[startIdx + word + bit];
55 bits[j++] = (bits[startIdx + word + bit]);
57 j--; // overwrite parity with next data
58 // if parity fails then return 0
59 switch (pType) {
60 case 3:
61 if (bits[j] == 1) return 0;
62 break; //should be 0 spacer bit
63 case 2:
64 if (bits[j] == 0) return 0;
65 break; //should be 1 spacer bit
66 default: //test parity
67 if (parityTest(parityWd, pLen, pType) == 0) return 0;
68 break;
70 bitcount += (pLen - 1);
71 parityWd = 0;
73 // if we got here then all the parities passed
74 //return ID start index and size
75 return bitcount;
79 // by marshmellow
80 // takes a array of binary values, length of bits per parity (includes parity bit),
81 // Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
82 // Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
84 * @brief addParity
85 * @param src pointer to the source bitstream of binary values
86 * @param dest pointer to the destination where parities together with bits are added.
87 * @param sourceLen number of
88 * @param pLen length bits to be checked
89 * @param pType EVEN|ODD|2 (always 1's)|3 (always 0's)
90 * @return
92 size_t addParity(const uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) {
93 uint32_t parityWd = 0;
94 size_t j = 0, bitCnt = 0;
95 for (int word = 0; word < sourceLen; word += pLen - 1) {
96 for (int bit = 0; bit < pLen - 1; ++bit) {
97 parityWd = (parityWd << 1) | src[word + bit];
98 dest[j++] = (src[word + bit]);
101 // if parity fails then return 0
102 switch (pType) {
103 case 3:
104 dest[j++] = 0;
105 break; // marker bit which should be a 0
106 case 2:
107 dest[j++] = 1;
108 break; // marker bit which should be a 1
109 default:
110 dest[j++] = parityTest(parityWd, pLen - 1, pType) ^ 1;
111 break;
113 bitCnt += pLen;
114 parityWd = 0;
116 // if we got here then all the parities passed
117 //return ID start index and size
118 return bitCnt;
121 // by marshmellow
123 * add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
124 * @brief wiegand_add_parity
125 * @param source pointer to source of binary data
126 * @param dest pointer to the destination where wiegandparity has been appended
127 * @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
129 void wiegand_add_parity(uint8_t *source, uint8_t *dest, uint8_t len) {
131 // Copy to destination, shifted one step to make room for EVEN parity
132 memcpy(dest + 1, source, length);
134 // half length, Even and Odd is calculated to the middle.
135 uint8_t len_h2 = length >> 1;
137 // add EVEN parity at the beginning
138 *(dest) = GetParity(source, EVEN, len_h2);
140 dest += length + 1;
142 // add ODD parity at the very end
143 *(dest) = GetParity(source + len_h2, ODD, len_h2);
146 //uint32_t bytebits_to_byte(uint8_t* src, size_t numbits);
147 #define MAX_BITS_TXX55 6*4*8
148 #define MAX_BYTES_TXX55 6*4
150 * @brief num_to_wiegand_bytes
151 * @param oem Sometimes call FF Fixfield, SiteCode. Used in a few formats
152 * @param fc Facility code
153 * @param cn Card number
154 * @param dest pointer to the destination where wiegand bytes will be stored
155 * @param formatlen
157 void num_to_wiegand_bytes(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen) {
159 uint8_t data[MAX_BITS_TXX55] = {0};
160 memset(data, 0, sizeof(data));
162 num_to_wiegand_bits(oem, fc, cn, data, formatlen);
164 // loop
165 // (formatlen / 32 ) + 1
166 // (formatlen >> 5) + 1
167 for (int i = 0; i < formatlen ; ++i) {
168 uint32_t value = bytebits_to_byte(data + (i * 32), 32);
169 num_to_bytes(value, 32, dest + (i * 4));
174 * @brief num_to_wiegand_bits
175 * @param oem Sometimes call FF Fixfield, SiteCode. Used in a few formats
176 * @param fc Facility code
177 * @param cn Card number
178 * @param dest pointer to the destination where wiegand bits will be stored
179 * @param formatlen
181 void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen) {
183 uint8_t bits[MAX_BITS_TXX55] = {0};
184 memset(bits, 0, sizeof(bits));
185 uint8_t *temp = bits;
186 uint64_t value = 0;
188 switch (formatlen) {
189 case 26 : // 26bit HID H10301
190 fc &= 0xFF; // 8bits
191 cn &= 0xFFFF; // 16bits
192 value = fc << 16 | cn;
193 num_to_bytebits(value, 24, temp);
194 wiegand_add_parity(temp, dest, 24);
195 break;
196 case 261: // 26bit Indala
197 fc &= 0xFFF; // 12bits
198 cn &= 0xFFF; // 12bits
199 value = fc << 12 | cn;
200 num_to_bytebits(value, 24, temp);
201 wiegand_add_parity(temp, dest, 24);
202 break;
203 case 34 : // 34bits HID
204 fc &= 0xFFFF; // 16bits
205 cn &= 0xFFFF; // 16bits
206 value = fc << 16 | cn;
207 num_to_bytebits(value, 32, temp);
208 wiegand_add_parity(temp, dest, 32);
209 break;
210 case 35 : // 35bits HID
211 fc &= 0xFFF; // 12bits
212 cn &= 0xFFFFFF; // 20bits
213 value = fc << 20 | cn;
214 num_to_bytebits(value, 32, temp);
215 wiegand_add_parity(temp, dest, 32);
216 break;
217 case 37 : // H10304
218 fc &= 0xFFFF; // 16bits
219 cn &= 0x7FFFF; // 19bits
220 value = fc << 19 | cn;
221 num_to_bytebits(value, 35, temp);
222 wiegand_add_parity(temp, dest, 35);
223 break;
224 case 39 : // 39bit KERI System Pyramid
225 fc &= 0x1FFFF; // 17bits
226 cn &= 0xFFFFFFFF; // 20bits
227 value = fc << 20 | cn;
228 num_to_bytebits(value, 37, temp);
229 wiegand_add_parity(temp, dest, 37);
230 break;
231 case 44 : // 44bit KERI system Pyramid
232 oem &= 0xFF; // 8bits
233 fc &= 0xFFF; // 12bits
234 cn &= 0xFFFFFFFF; // 21bits
235 value = oem << 20 | fc << 12 | cn;
236 num_to_bytebits(value, 42, temp);
237 wiegand_add_parity(temp, dest, 42);
238 break;
239 case 50 : // AWID 50 RBH
240 fc &= 0xFFFF; // 16bits
241 cn &= 0xFFFFFFFF; // 32bits
242 value = fc << 32 | cn;
243 num_to_bytebits(value, 48, temp);
244 wiegand_add_parity(temp, dest, 48); // verify!
245 break;
246 default:
247 break;