fix length check when reading a dictionary file
[RRG-proxmark3.git] / client / deps / id48 / id48.h
blobaa8b753b66e22c40b483fdc8d432f8c9c9f06ffc
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.
25 #if !defined(ID48_H__)
26 #define ID48_H__
28 // This file defines only the structs and API surface.
29 // There are no dependencies on any external code.
30 #include <stdint.h>
31 #include <string.h>
32 #include <stdbool.h>
33 #if defined(NDEBUG)
34 #define ASSERT(x) ((void)0)
35 #elif defined(ID48_NO_STDIO)
36 #define ASSERT(x) ((void)0)
37 #else // neither NDEBUG nor ID48_NO_STDIO defined
38 #include <stdio.h>
39 #include <assert.h>
40 #define ASSERT(x) assert((x))
41 #endif
44 #if defined(__cplusplus)
45 extern "C" {
46 #endif
48 /// <summary>
49 /// [0..11] stores K₉₅..K₀₀
50 /// </summary>
51 /// <remarks>
52 /// Big-endian, "native" bit order, when viewed linearly from k[ 0..11]
53 /// Mapping to the indices used in the research paper:
54 /// k[ 0] :== K₉₅..K₈₈
55 /// k[ 1] :== K₈₇..K₈₀
56 /// k[ 2] :== K₇₉..K₇₂
57 /// k[ 3] :== K₇₁..K₆₄
58 /// k[ 4] :== K₆₃..K₅₆
59 /// k[ 5] :== K₅₅..K₄₈
60 /// k[ 6] :== K₄₇..K₄₀
61 /// k[ 7] :== K₃₉..K₃₂
62 /// k[ 8] :== K₃₁..K₂₄
63 /// k[ 9] :== K₂₃..K₁₆
64 /// k[10] :== K₁₅..K₀₈
65 /// k[11] :== K₀₇..K₀₀
66 /// </remarks>
67 typedef struct _ID48LIB_KEY { // 96-bit
68 uint8_t k[12];
69 } ID48LIB_KEY;
70 /// <summary>
71 /// [0..6] stores N₅₅..N₀₀
72 /// </summary>
73 /// <remarks>
74 /// Big-endian, "native" bit order, when viewed linearly from rn[0..6]
75 /// Mapping to the indices used in the research paper:
76 /// rn[ 0] :== N₅₅..N₄₈
77 /// rn[ 1] :== N₄₇..N₄₀
78 /// rn[ 2] :== N₃₉..N₃₂
79 /// rn[ 3] :== N₃₁..N₂₄
80 /// rn[ 4] :== N₂₃..N₁₆
81 /// rn[ 5] :== N₁₅..N₀₈
82 /// rn[ 6] :== N₀₇..N₀₀
83 /// </remarks>
84 typedef struct _ID48LIB_NONCE { // 56-bit
85 uint8_t rn[7];
86 } ID48LIB_NONCE;
87 /// <summary>
88 /// [0..3] stores O₀₀..O₂₇ 0000
89 /// </summary>
90 /// <remarks>
91 /// Big-endian, "bitstream" bit order, when viewed linearly from frn[0..3]
92 /// This is the order in which the research paper typically lists the bits.
93 /// Mapping to the indices used in the research paper,
94 /// where ( O₀₀ .. O₂₇ ) :== output(s₀₇,k₃₂..k₀₅ )
95 /// then:
96 /// frn[ 0] :== O₀₀..O₀₇
97 /// frn[ 1] :== O₀₈..O₁₅
98 /// frn[ 2] :== O₁₆..O₂₃
99 /// frn[ 3] :== O₂₄..O₂₇ 0000
100 /// </remarks>
101 typedef struct _ID48LIB_FRN {
102 uint8_t frn[4];
103 } ID48LIB_FRN;
104 /// <summary>
105 /// [0..3] stores O₂₈..O₄₇ (12x 0)
106 /// </summary>
107 /// <remarks>
108 /// Native format if viewed linearly from frn[0..6].
109 /// Mapping to the indices used in the research paper,
110 /// where ( O₂₈ .. O₅₅ ) :== output( s₃₅, k₀₄..k₀₀ (15x 0) ) == grn
112 /// then:
113 /// rn[ 0] :== O₂₈ .. O₃₅
114 /// rn[ 1] :== O₃₆ .. O₄₃
115 /// rn[ 2] :== O₄₄..O₄₇ 0000
116 /// rn[ 3] :== 0000 0000
117 /// </remarks>
118 typedef struct _ID48LIB_GRN {
119 uint8_t grn[3];
120 } ID48LIB_GRN;
122 /// <summary>
123 /// When provided a key and nonce, will calculate
124 /// the frn and grn values and store in caller-provided
125 /// output parameters.
126 /// </summary>
127 /// <remarks>
128 /// Note: In C++, each parameter would be a reference (not pointer).
129 /// </remarks>
130 void id48lib_generator(
131 const ID48LIB_KEY *key_96bit,
132 const ID48LIB_NONCE *nonce_56bit,
133 ID48LIB_FRN *frn28_out,
134 ID48LIB_GRN *grn20_out
137 /// <summary>
138 /// Initializes to allow iterative recovery
139 /// of multiple potential keys. After calling
140 /// this init() function, can repeatedly call
141 /// the next() function until it returns false
142 /// to obtain all potential keys.
143 /// </summary>
144 /// <param name="input_partial_key">
145 /// Top 48 bits of the key, such as those discovered
146 /// using the proxmark3 command `lf em 4x70 brute`.
147 /// Only k[0..5] are used from this parameter,
148 /// corresponding to K₉₅..K₄₈.
149 /// </param>
150 /// <param name="input_nonce">
151 /// The nonce value.
152 /// Typically from a sniffed authentication.
153 /// </param>
154 /// <param name="input_frn">
155 /// The challenge sent from the reader (e.g., car)
156 /// to the tag (e.g., key).
157 /// Typically from a sniffed authentication.
158 /// </param>
159 /// <param name="input_grn">
160 /// The response sent from the tag (e.g., key)
161 /// to the car (e.g., car).
162 /// Typically from a sniffed authentication.
163 /// </param>
164 /// <remarks>
165 /// Note: In C++, each parameter would be a reference (not pointer).
166 /// </remarks>
167 void id48lib_key_recovery_init(
168 const ID48LIB_KEY *input_partial_key,
169 const ID48LIB_NONCE *input_nonce,
170 const ID48LIB_FRN *input_frn,
171 const ID48LIB_GRN *input_grn
173 /// <summary>
174 /// This can be repeated called (after calling init())
175 /// to find the next potential key for the given
176 /// partial key + nonce + frn + grn values.
177 /// I've seen combinations that have up to six
178 /// potential keys available, although typically
179 /// there are 1-3 results.
180 /// Each call to this function will return a single
181 /// value. Call repeatedly until the function returns
182 /// false to get all potential keys.
183 /// </summary>
184 /// <param name="potential_key_output">
185 /// When the function returns true, this caller-provided
186 /// value will be filled with the 96-bit key that, when
187 /// programmed to the tag, should authenticate against
188 /// the nonce+frn values, with tag returning the grn value.
189 /// </param>
190 /// <returns>
191 /// true when another potential key has been found.
192 /// false if no additional potential keys have been found.
193 /// </returns>
194 /// <remarks>
195 /// Note: In C++, each parameter would be a reference (not pointer).
196 /// </remarks>
197 bool id48lib_key_recovery_next(
198 ID48LIB_KEY *potential_key_output
201 #if defined(__cplusplus)
203 #endif
205 #endif // !defined(ID48_H__)