fix length check when reading a dictionary file
[RRG-proxmark3.git] / client / deps / id48 / id48_data.c
blobcb87bc61479d2e1a5b8395a35010d4b1c13552fc
1 /**
2 * The MIT License (MIT)
4 * Copyright (c) 2024 by Henry Gabryjelski
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
26 #include "id48_internals.h"
27 #define COUNT_OF_POTENTIAL_INPUTS (0x100000ul) // thus the lookup parameter is uint20_t...
29 /// initial_idx = (l0 << 7) | (l4 << 6) | (l6 << 5) | (m1 << 4) | (m3 << 3) | (r0 << 2) | (r3 << 1) | (r5 << 0)
30 static const uint8_t small_lut_initial[32] = { // aka 256 bits
31 0x44, 0xff, 0x4f, 0x4f, 0x55, 0xff, 0x55, 0x55,
32 0xcc, 0xff, 0xcf, 0x4f, 0xcc, 0xff, 0xcc, 0x44,
33 0x00, 0x00, 0x0f, 0x0f, 0x55, 0x55, 0x55, 0x55,
34 0xcc, 0x00, 0xcf, 0x0f, 0xcc, 0x00, 0xcc, 0x00,
36 /// g1_idx = (a << 4) | (l2 << 3) | (l3 << 2) | (l0 << 1) | (l6 << 0)
37 static const uint8_t small_lut_group1[4] = { // aka 32 bits
38 0x4f, 0x92, 0xa1, 0x7c,
40 /// g2_idx = (l5 << 4) | (b << 3) | (m0 << 2) | (l4 << 1) | (m1 << 0)
41 static const uint8_t small_lut_group2[4] = { // aka 32 bits
42 0x8f, 0x52, 0x61, 0xbc,
44 /// g3_idx = (m5 << 4) | (c << 3) | (r1 << 2) | (m3 << 1) | (r3 << 0)
45 static const uint8_t small_lut_group3[4] = { // aka 32 bits
46 0x8f, 0x34, 0x61, 0xda,
48 /// g4_idx = (r2 << 4) | (r4 << 3) | (r6 << 2) | (r0 << 1) | (r5 << 0)
49 static const uint8_t small_lut_group4[4] = { // aka 32 bits
50 0x8f, 0x34, 0x52, 0xe9,
53 static inline bool get_bit(const uint8_t *table_start, uint32_t bit_idx) {
54 const uint32_t byte = bit_idx / 8u;
55 const uint8_t mask = 1u << (bit_idx % 8u);
56 return (table_start[byte] & mask) != 0;
60 // NOTE: Additional optimizations possible, but not pursued.
61 // Could spend a lot of time to define more optimized version that directly
62 // takes ID48LIBX_STATE_REGISTERS as input. These optimizations may include
63 // changing the order of the bits in each intermediate lookup index (indices).
64 // Optimizations may also include modifying where a/b/c are stored in the
65 // ID48LIBX_STATE_REGISTER, such as shifting a/b/c from being stored at
66 // bits [03,02,01] to being stored at bit [61,60,59].
68 // Q: Maybe move a/b/c to upper 32 bits?
69 // This would allow all bits and bitshifting to occur using only upper 32-bits.
71 // Note: Each set of bits for the lookup tables can be in any order,
72 // so long as the lookup tables are adjusted accordingly.
74 // Which bits are used for which small lookup table indixes?
76 // Bit: ₆₃ ₆₂ ₆₁ ₆₀ ₅₉ ₅₈ ₅₇ ₅₆ ₅₅ ₅₄ ₅₃ ₅₂ ₅₁ ₅₀ ₄₉ ₄₈ ₄₇ ₄₆ ₄₅ ₄₄ ₄₃ ₄₂ ₄₁ ₄₀ ₃₉ ₃₈ ₃₇ ₃₆ ₃₅ ₃₄ ₃₃ ₃₂
77 // Reg: i j r₀₆ r₀₅ r₀₄ r₀₃ r₀₂ r₀₁ r₀₀ m₀₆ m₀₅ m₀₄ m₀₃ m₀₂ m₀₁ m₀₀ l₀₆ l₀₅ l₀₄ l₀₃ l₀₂ l₀₁ l₀₀ g₂₂ g₂₁ g₂₀ g₁₉ g₁₈ g₁₇ g₁₆ g₁₅ g₁₄
78 // i_v i_v i_v i_v i_v i_v i_v i_v
79 // AAA AAA AAA AAA
80 // BBB BBB BBB BBB
81 // CCC CCC CCC CCC
82 // DDD DDD DDD DDD DDD
84 // Bit: ₃₁ ₃₀ ₂₉ ₂₈ ₂₇ ₂₆ ₂₅ ₂₄ ₂₃ ₂₂ ₂₁ ₂₀ ₁₉ ₁₈ ₁₇ ₁₆ ₁₅ ₁₄ ₁₃ ₁₂ ₁₁ ₁₀ ₀₉ ₀₈ ₀₇ ₀₆ ₀₅ ₀₄ ₀₃ ₀₂ ₀₁ ₀₀
85 // Reg: g₁₃ g₁₂ g₁₁ g₁₀ g₀₉ g₀₈ g₀₇ g₀₆ g₀₅ g₀₄ g₀₃ g₀₂ g₀₁ g₀₀ h₁₂ h₁₁ h₁₀ h₀₉ h₀₈ h₀₇ h₀₆ h₀₅ h₀₄ h₀₃ h₀₂ h₀₁ h₀₀ _ a b c 0
86 // AAA BBB CCC
88 // Example minor optimization of initial 8-bit lookup:
89 // ===================================================
90 // i_v depends on ==> r₀₅ ... r₀₃ ... ... r₀₀ ... ... ... m₀₃ ... m₀₁ ... l₀₆ ... ... l₀₄ ... ... ... l₀₀
91 // So can reduce the number of operations somewhat as follows:
92 // ... r₀₅ ... r₀₃ ... ... ... ...
93 // r₀₀ ... ... ... m₀₃ ... ... ...
94 // ... ... ... ... ... m₀₁ ... l₀₆
95 // ... ... l₀₄ ... ... ... l₀₀ ...
96 // Resulting in the following (slightly-improved) bit order for the lookup table index:
97 // r₀₀ r₀₅ l₀₄ r₀₃ m₀₃ m₀₁ l₀₀ l₀₆
99 // alt_initial_v = // r₀₀ r₀₅ l₀₄ r₀₃ m₀₃ m₀₁ l₀₀ l₀₆
100 // ((uint8_t)((r & (R05_BIT | R03_BIT)) >> (58 - 4))) |
101 // ((uint8_t)((r & (R00_BIT | M03_BIT)) >> (51 - 3))) |
102 // ((uint8_t)((r & (M01_BIT | L06_BIT)) >> (47 - 0))) |
103 // ((uint8_t)((r & (L04_BIT | L00_BIT)) >> (41 - 1))) ;
106 static bool output_lookup_small_lut(uint32_t output_index) {
107 if (output_index >= COUNT_OF_POTENTIAL_INPUTS) { return false; }
108 // 1 1 1 1 1 1 1 1 1 1
109 // 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
110 // Fₒ( a b c l₀ l₂ l₃ l₄ l₅ l₆ m₀ m₁ m₃ m₅ r₀ r₁ r₂ r₃ r₄ r₅ r₆ )
112 const uint8_t initial_v = // i_v
113 ((output_index >> 9) & 0x80u) | // (l0 << 7)
114 ((output_index >> 7) & 0x40u) | // (l4 << 6)
115 ((output_index >> 6) & 0x20u) | // (l6 << 5)
116 ((output_index >> 5) & 0x10u) | // (m1 << 4)
117 ((output_index >> 5) & 0x08u) | // (m3 << 3)
118 ((output_index >> 4) & 0x04u) | // (r0 << 2)
119 ((output_index >> 2) & 0x02u) | // (r3 << 1)
120 ((output_index >> 1) & 0x01u) ; // (r5 << 0)
121 const uint8_t g1_v = // AAA
122 ((output_index >> 15) & 0x10u) | // ( a << 4) |
123 ((output_index >> 12) & 0x08u) | // (l2 << 3) |
124 ((output_index >> 12) & 0x04u) | // (l3 << 2) |
125 ((output_index >> 15) & 0x02u) | // (l0 << 1) |
126 ((output_index >> 11) & 0x01u) ; // (l6 << 0) ;
127 const uint8_t g2_v = // BBB
128 ((output_index >> 8) & 0x10u) | // (l5 << 4) |
129 ((output_index >> 15) & 0x08u) | // ( b << 3) |
130 ((output_index >> 8) & 0x04u) | // (m0 << 2) |
131 ((output_index >> 12) & 0x02u) | // (l4 << 1) |
132 ((output_index >> 9) & 0x01u) ; // (m1 << 0) ;
133 const uint8_t g3_v = // CCC
134 ((output_index >> 3) & 0x10u) | // (m5 << 4) |
135 ((output_index >> 14) & 0x08u) | // ( c << 3) |
136 ((output_index >> 3) & 0x04u) | // (r1 << 2) |
137 ((output_index >> 7) & 0x02u) | // (m3 << 1) |
138 ((output_index >> 3) & 0x01u) ; // (r3 << 0) ;
139 const uint8_t g4_v = // DDD
140 ((output_index >> 0) & 0x10u) | // (r2 << 4) |
141 ((output_index << 1) & 0x08u) | // (r4 << 3) |
142 ((output_index << 2) & 0x04u) | // (r6 << 2) |
143 ((output_index >> 5) & 0x02u) | // (r0 << 1) |
144 ((output_index >> 1) & 0x01u) ; // (r5 << 0) ;
145 bool result = get_bit(small_lut_initial, initial_v);
146 if (get_bit(small_lut_group1, g1_v)) result = !result;
147 if (get_bit(small_lut_group2, g2_v)) result = !result;
148 if (get_bit(small_lut_group3, g3_v)) result = !result;
149 if (get_bit(small_lut_group4, g4_v)) result = !result;
150 return result;
153 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
154 // ******************************************************************************************************************** //
155 // *** Everything above this line in the file is declared static, *** //
156 // *** which avoids polluting the global namespace. *** //
157 // *** Everything below is technically visible, but not necessarily an exported API. *** //
158 // *** In C++, this separation is much more easily achieved using an anonymous namespace. C'est la vie! *** //
159 // ******************************************************************************************************************** //
160 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
162 bool id48libx_output_lookup(uint32_t output_index) {
163 return output_lookup_small_lut(output_index);