Mifare Classic RFID tag dump: GraphViz block diagram (.dot) source

You can get a dump for testing by the link: https://github.com/zhovner/mfdread/raw/master/dump.mfd

File extension

mfd

KS implementation details

License: BSD-2-Clause
Minimal Kaitai Struct required: 0.9

References

This page hosts a formal specification of Mifare Classic RFID tag dump using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

mifare_classic.dot

digraph {
	rankdir=LR;
	node [shape=plaintext];
	subgraph cluster__mifare_classic {
		label="MifareClassic";
		graph[style=dotted];

		mifare_classic__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
			<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
			<TR><TD PORT="sectors_pos">0</TD><TD PORT="sectors_size">(((i &gt;= 32 ? 4 : 1) * 4) * 16)</TD><TD>Sector</TD><TD PORT="sectors_type">sectors</TD></TR>
			<TR><TD COLSPAN="4" PORT="sectors__repeat">repeat to end of stream</TD></TR>
		</TABLE>>];
		subgraph cluster__key {
			label="MifareClassic::Key";
			graph[style=dotted];

			key__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="key_pos">0</TD><TD PORT="key_size">6</TD><TD></TD><TD PORT="key_type">key</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__sector {
			label="MifareClassic::Sector";
			graph[style=dotted];

			sector__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="manufacturer_pos">0</TD><TD PORT="manufacturer_size">16</TD><TD>Manufacturer</TD><TD PORT="manufacturer_type">manufacturer</TD></TR>
				<TR><TD PORT="data_filler_pos">16</TD><TD PORT="data_filler_size">((_io.size - _io.pos) - 16)</TD><TD>Filler</TD><TD PORT="data_filler_type">data_filler</TD></TR>
				<TR><TD PORT="trailer_pos">...</TD><TD PORT="trailer_size">16</TD><TD>Trailer</TD><TD PORT="trailer_type">trailer</TD></TR>
			</TABLE>>];
			sector__inst__block_size [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>block_size</TD><TD>16</TD></TR>
			</TABLE>>];
			sector__inst__data [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>data</TD><TD>data_filler.data</TD></TR>
			</TABLE>>];
			sector__inst__blocks [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="blocks_pos">0</TD><TD PORT="blocks_size">block_size</TD><TD></TD><TD PORT="blocks_type">blocks</TD></TR>
				<TR><TD COLSPAN="4" PORT="blocks__repeat">repeat to end of stream</TD></TR>
			</TABLE>>];
			sector__inst__values [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="values_pos">0</TD><TD PORT="values_size">...</TD><TD>Values</TD><TD PORT="values_type">values</TD></TR>
			</TABLE>>];
			subgraph cluster__values {
				label="MifareClassic::Sector::Values";
				graph[style=dotted];

				values__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="values_pos">0</TD><TD PORT="values_size">16</TD><TD>ValueBlock</TD><TD PORT="values_type">values</TD></TR>
					<TR><TD COLSPAN="4" PORT="values__repeat">repeat to end of stream</TD></TR>
				</TABLE>>];
				subgraph cluster__value_block {
					label="MifareClassic::Sector::Values::ValueBlock";
					graph[style=dotted];

					value_block__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
						<TR><TD PORT="valuez_pos">0</TD><TD PORT="valuez_size">4</TD><TD>u4le</TD><TD PORT="valuez_type">valuez</TD></TR>
						<TR><TD COLSPAN="4" PORT="valuez__repeat">repeat 3 times</TD></TR>
						<TR><TD PORT="addrz_pos">12</TD><TD PORT="addrz_size">1</TD><TD>u1</TD><TD PORT="addrz_type">addrz</TD></TR>
						<TR><TD COLSPAN="4" PORT="addrz__repeat">repeat 4 times</TD></TR>
					</TABLE>>];
					value_block__inst__addr [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>addr</TD><TD>addrz[0]</TD></TR>
					</TABLE>>];
					value_block__inst__addr_valid [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>addr_valid</TD><TD> ((addrz[0] == ~(addrz[1])) &amp;&amp; (addrz[0] == addrz[2]) &amp;&amp; (addrz[1] == addrz[3])) </TD></TR>
					</TABLE>>];
					value_block__inst__valid [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>valid</TD><TD> ((value_valid) &amp;&amp; (addr_valid)) </TD></TR>
					</TABLE>>];
					value_block__inst__value_valid [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>value_valid</TD><TD> ((valuez[0] == ~(valuez[1])) &amp;&amp; (valuez[0] == valuez[2])) </TD></TR>
					</TABLE>>];
					value_block__inst__value [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>value</TD><TD>valuez[0]</TD></TR>
					</TABLE>>];
				}
			}
			subgraph cluster__filler {
				label="MifareClassic::Sector::Filler";
				graph[style=dotted];

				filler__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="data_pos">0</TD><TD PORT="data_size">_io.size</TD><TD></TD><TD PORT="data_type">data</TD></TR>
				</TABLE>>];
			}
		}
		subgraph cluster__manufacturer {
			label="MifareClassic::Manufacturer";
			graph[style=dotted];

			manufacturer__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="nuid_pos">0</TD><TD PORT="nuid_size">4</TD><TD>u4le</TD><TD PORT="nuid_type">nuid</TD></TR>
				<TR><TD PORT="bcc_pos">4</TD><TD PORT="bcc_size">1</TD><TD>u1</TD><TD PORT="bcc_type">bcc</TD></TR>
				<TR><TD PORT="sak_pos">5</TD><TD PORT="sak_size">1</TD><TD>u1</TD><TD PORT="sak_type">sak</TD></TR>
				<TR><TD PORT="atqa_pos">6</TD><TD PORT="atqa_size">2</TD><TD>u2le</TD><TD PORT="atqa_type">atqa</TD></TR>
				<TR><TD PORT="manufacturer_pos">8</TD><TD PORT="manufacturer_size">8</TD><TD></TD><TD PORT="manufacturer_type">manufacturer</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__trailer {
			label="MifareClassic::Trailer";
			graph[style=dotted];

			trailer__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="key_a_pos">0</TD><TD PORT="key_a_size">6</TD><TD>Key</TD><TD PORT="key_a_type">key_a</TD></TR>
				<TR><TD PORT="access_bits_pos">6</TD><TD PORT="access_bits_size">3</TD><TD>AccessConditions</TD><TD PORT="access_bits_type">access_bits</TD></TR>
				<TR><TD PORT="user_byte_pos">9</TD><TD PORT="user_byte_size">1</TD><TD>u1</TD><TD PORT="user_byte_type">user_byte</TD></TR>
				<TR><TD PORT="key_b_pos">10</TD><TD PORT="key_b_size">6</TD><TD>Key</TD><TD PORT="key_b_type">key_b</TD></TR>
			</TABLE>>];
			trailer__inst__ac_bits [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>ac_bits</TD><TD>3</TD></TR>
			</TABLE>>];
			trailer__inst__acs_in_sector [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>acs_in_sector</TD><TD>4</TD></TR>
			</TABLE>>];
			trailer__inst__ac_count_of_chunks [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>ac_count_of_chunks</TD><TD>(ac_bits * 2)</TD></TR>
			</TABLE>>];
			subgraph cluster__access_conditions {
				label="MifareClassic::Trailer::AccessConditions";
				graph[style=dotted];

				access_conditions__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="raw_chunks_pos">0</TD><TD PORT="raw_chunks_size">4b</TD><TD>b4</TD><TD PORT="raw_chunks_type">raw_chunks</TD></TR>
					<TR><TD COLSPAN="4" PORT="raw_chunks__repeat">repeat _parent.ac_count_of_chunks times</TD></TR>
				</TABLE>>];
				access_conditions__inst__data_acs [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="data_acs_pos">0</TD><TD PORT="data_acs_size">0</TD><TD>DataAc</TD><TD PORT="data_acs_type">data_acs</TD></TR>
					<TR><TD COLSPAN="4" PORT="data_acs__repeat">repeat (_parent.acs_in_sector - 1) times</TD></TR>
				</TABLE>>];
				access_conditions__inst__remaps [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="remaps_pos">0</TD><TD PORT="remaps_size">0</TD><TD>ChunkBitRemap</TD><TD PORT="remaps_type">remaps</TD></TR>
					<TR><TD COLSPAN="4" PORT="remaps__repeat">repeat _parent.ac_bits times</TD></TR>
				</TABLE>>];
				access_conditions__inst__acs_raw [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="acs_raw_pos">0</TD><TD PORT="acs_raw_size">0</TD><TD>Ac</TD><TD PORT="acs_raw_type">acs_raw</TD></TR>
					<TR><TD COLSPAN="4" PORT="acs_raw__repeat">repeat _parent.acs_in_sector times</TD></TR>
				</TABLE>>];
				access_conditions__inst__trailer_ac [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="trailer_ac_pos">0</TD><TD PORT="trailer_ac_size">0</TD><TD>TrailerAc</TD><TD PORT="trailer_ac_type">trailer_ac</TD></TR>
				</TABLE>>];
				access_conditions__inst__chunks [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="chunks_pos">0</TD><TD PORT="chunks_size">0</TD><TD>ValidChunk</TD><TD PORT="chunks_type">chunks</TD></TR>
					<TR><TD COLSPAN="4" PORT="chunks__repeat">repeat _parent.ac_bits times</TD></TR>
				</TABLE>>];
				subgraph cluster__trailer_ac {
					label="MifareClassic::Trailer::AccessConditions::TrailerAc";
					graph[style=dotted];

					trailer_ac__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					</TABLE>>];
					trailer_ac__inst__can_read_key_b [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>can_read_key_b</TD><TD>ac.inv_shift_val &lt;= 2</TD></TR>
					</TABLE>>];
					trailer_ac__inst__can_write_keys [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>can_write_keys</TD><TD> ((((ac.inv_shift_val + 1) % 3) != 0) &amp;&amp; (ac.inv_shift_val &lt; 6)) </TD></TR>
					</TABLE>>];
					trailer_ac__inst__can_write_access_bits [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>can_write_access_bits</TD><TD>ac.bits[2].b</TD></TR>
					</TABLE>>];
					trailer_ac__inst__key_b_controls_write [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>key_b_controls_write</TD><TD>!(can_read_key_b)</TD></TR>
					</TABLE>>];
				}
				subgraph cluster__chunk_bit_remap {
					label="MifareClassic::Trailer::AccessConditions::ChunkBitRemap";
					graph[style=dotted];

					chunk_bit_remap__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					</TABLE>>];
					chunk_bit_remap__inst__shift_value [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>shift_value</TD><TD>(bit_no == 1 ? -1 : 1)</TD></TR>
					</TABLE>>];
					chunk_bit_remap__inst__chunk_no [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>chunk_no</TD><TD>(((inv_chunk_no + shift_value) + _parent._parent.ac_count_of_chunks) % _parent._parent.ac_count_of_chunks)</TD></TR>
					</TABLE>>];
					chunk_bit_remap__inst__inv_chunk_no [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>inv_chunk_no</TD><TD>(bit_no + shift_value)</TD></TR>
					</TABLE>>];
				}
				subgraph cluster__data_ac {
					label="MifareClassic::Trailer::AccessConditions::DataAc";
					graph[style=dotted];

					data_ac__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					</TABLE>>];
					data_ac__inst__read_key_a_required [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>read_key_a_required</TD><TD>ac.val &lt;= 4</TD></TR>
					</TABLE>>];
					data_ac__inst__write_key_b_required [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>write_key_b_required</TD><TD> (( ((!(read_key_a_required)) || (read_key_b_required)) ) &amp;&amp; (!(ac.bits[0].b))) </TD></TR>
					</TABLE>>];
					data_ac__inst__write_key_a_required [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>write_key_a_required</TD><TD>ac.val == 0</TD></TR>
					</TABLE>>];
					data_ac__inst__read_key_b_required [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>read_key_b_required</TD><TD>ac.val &lt;= 6</TD></TR>
					</TABLE>>];
					data_ac__inst__decrement_available [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>decrement_available</TD><TD> (( ((ac.bits[1].b) || (!(ac.bits[0].b))) ) &amp;&amp; (!(ac.bits[2].b))) </TD></TR>
					</TABLE>>];
					data_ac__inst__increment_available [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>increment_available</TD><TD> (( ((!(ac.bits[0].b)) &amp;&amp; (!(read_key_a_required)) &amp;&amp; (!(read_key_b_required))) ) || ( ((!(ac.bits[0].b)) &amp;&amp; (read_key_a_required) &amp;&amp; (read_key_b_required)) )) </TD></TR>
					</TABLE>>];
				}
				subgraph cluster__ac {
					label="MifareClassic::Trailer::AccessConditions::Ac";
					graph[style=dotted];

					ac__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					</TABLE>>];
					ac__inst__bits [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
						<TR><TD PORT="bits_pos">0</TD><TD PORT="bits_size">0</TD><TD>AcBit</TD><TD PORT="bits_type">bits</TD></TR>
						<TR><TD COLSPAN="4" PORT="bits__repeat">repeat _parent._parent.ac_bits times</TD></TR>
					</TABLE>>];
					ac__inst__val [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>val</TD><TD>(((bits[2].n &lt;&lt; 2) | (bits[1].n &lt;&lt; 1)) | bits[0].n)</TD></TR>
					</TABLE>>];
					ac__inst__inv_shift_val [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>inv_shift_val</TD><TD>(((bits[0].n &lt;&lt; 2) | (bits[1].n &lt;&lt; 1)) | bits[2].n)</TD></TR>
					</TABLE>>];
					subgraph cluster__ac_bit {
						label="MifareClassic::Trailer::AccessConditions::Ac::AcBit";
						graph[style=dotted];

						ac_bit__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
							<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
						</TABLE>>];
						ac_bit__inst__n [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
							<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
							<TR><TD>n</TD><TD>((chunk &gt;&gt; i) &amp; 1)</TD></TR>
						</TABLE>>];
						ac_bit__inst__b [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
							<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
							<TR><TD>b</TD><TD>n == 1</TD></TR>
						</TABLE>>];
					}
				}
				subgraph cluster__valid_chunk {
					label="MifareClassic::Trailer::AccessConditions::ValidChunk";
					graph[style=dotted];

					valid_chunk__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					</TABLE>>];
					valid_chunk__inst__valid [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
						<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
						<TR><TD>valid</TD><TD>(inv_chunk ^ chunk) == 15</TD></TR>
					</TABLE>>];
				}
			}
		}
	}
	mifare_classic__seq:sectors_type -> sector__seq [style=bold];
	sector__seq:manufacturer_type -> manufacturer__seq [style=bold];
	sector__seq:data_filler_type -> filler__seq [style=bold];
	sector__seq:trailer_type -> trailer__seq [style=bold];
	filler__seq:data_type -> sector__inst__data [color="#404040"];
	sector__inst__block_size:block_size_type -> sector__inst__blocks:blocks_size [color="#404040"];
	sector__inst__values:values_type -> values__seq [style=bold];
	values__seq:values_type -> value_block__seq [style=bold];
	value_block__seq:addrz_type -> value_block__inst__addr [color="#404040"];
	value_block__seq:addrz_type -> value_block__inst__addr_valid [color="#404040"];
	value_block__seq:addrz_type -> value_block__inst__addr_valid [color="#404040"];
	value_block__seq:addrz_type -> value_block__inst__addr_valid [color="#404040"];
	value_block__seq:addrz_type -> value_block__inst__addr_valid [color="#404040"];
	value_block__seq:addrz_type -> value_block__inst__addr_valid [color="#404040"];
	value_block__seq:addrz_type -> value_block__inst__addr_valid [color="#404040"];
	value_block__inst__value_valid:value_valid_type -> value_block__inst__valid [color="#404040"];
	value_block__inst__addr_valid:addr_valid_type -> value_block__inst__valid [color="#404040"];
	value_block__seq:valuez_type -> value_block__inst__value_valid [color="#404040"];
	value_block__seq:valuez_type -> value_block__inst__value_valid [color="#404040"];
	value_block__seq:valuez_type -> value_block__inst__value_valid [color="#404040"];
	value_block__seq:valuez_type -> value_block__inst__value_valid [color="#404040"];
	value_block__seq:valuez_type -> value_block__inst__value [color="#404040"];
	trailer__seq:key_a_type -> key__seq [style=bold];
	trailer__seq:access_bits_type -> access_conditions__seq [style=bold];
	trailer__seq:key_b_type -> key__seq [style=bold];
	trailer__inst__ac_bits:ac_bits_type -> trailer__inst__ac_count_of_chunks [color="#404040"];
	trailer__inst__ac_count_of_chunks:ac_count_of_chunks_type -> access_conditions__seq:raw_chunks__repeat [color="#404040"];
	access_conditions__inst__data_acs:data_acs_type -> data_ac__seq [style=bold];
	trailer__inst__acs_in_sector:acs_in_sector_type -> access_conditions__inst__data_acs:data_acs__repeat [color="#404040"];
	access_conditions__inst__remaps:remaps_type -> chunk_bit_remap__seq [style=bold];
	trailer__inst__ac_bits:ac_bits_type -> access_conditions__inst__remaps:remaps__repeat [color="#404040"];
	access_conditions__inst__acs_raw:acs_raw_type -> ac__seq [style=bold];
	trailer__inst__acs_in_sector:acs_in_sector_type -> access_conditions__inst__acs_raw:acs_raw__repeat [color="#404040"];
	access_conditions__inst__trailer_ac:trailer_ac_type -> trailer_ac__seq [style=bold];
	access_conditions__inst__chunks:chunks_type -> valid_chunk__seq [style=bold];
	trailer__inst__ac_bits:ac_bits_type -> access_conditions__inst__chunks:chunks__repeat [color="#404040"];
	ac__inst__inv_shift_val:inv_shift_val_type -> trailer_ac__inst__can_read_key_b [color="#404040"];
	ac__inst__inv_shift_val:inv_shift_val_type -> trailer_ac__inst__can_write_keys [color="#404040"];
	ac__inst__inv_shift_val:inv_shift_val_type -> trailer_ac__inst__can_write_keys [color="#404040"];
	ac_bit__inst__b:b_type -> trailer_ac__inst__can_write_access_bits [color="#404040"];
	trailer_ac__inst__can_read_key_b:can_read_key_b_type -> trailer_ac__inst__key_b_controls_write [color="#404040"];
	chunk_bit_remap__params:bit_no_type -> chunk_bit_remap__inst__shift_value [color="#404040"];
	chunk_bit_remap__inst__inv_chunk_no:inv_chunk_no_type -> chunk_bit_remap__inst__chunk_no [color="#404040"];
	chunk_bit_remap__inst__shift_value:shift_value_type -> chunk_bit_remap__inst__chunk_no [color="#404040"];
	trailer__inst__ac_count_of_chunks:ac_count_of_chunks_type -> chunk_bit_remap__inst__chunk_no [color="#404040"];
	trailer__inst__ac_count_of_chunks:ac_count_of_chunks_type -> chunk_bit_remap__inst__chunk_no [color="#404040"];
	chunk_bit_remap__params:bit_no_type -> chunk_bit_remap__inst__inv_chunk_no [color="#404040"];
	chunk_bit_remap__inst__shift_value:shift_value_type -> chunk_bit_remap__inst__inv_chunk_no [color="#404040"];
	ac__inst__val:val_type -> data_ac__inst__read_key_a_required [color="#404040"];
	data_ac__inst__read_key_a_required:read_key_a_required_type -> data_ac__inst__write_key_b_required [color="#404040"];
	data_ac__inst__read_key_b_required:read_key_b_required_type -> data_ac__inst__write_key_b_required [color="#404040"];
	ac_bit__inst__b:b_type -> data_ac__inst__write_key_b_required [color="#404040"];
	ac__inst__val:val_type -> data_ac__inst__write_key_a_required [color="#404040"];
	ac__inst__val:val_type -> data_ac__inst__read_key_b_required [color="#404040"];
	ac_bit__inst__b:b_type -> data_ac__inst__decrement_available [color="#404040"];
	ac_bit__inst__b:b_type -> data_ac__inst__decrement_available [color="#404040"];
	ac_bit__inst__b:b_type -> data_ac__inst__decrement_available [color="#404040"];
	ac_bit__inst__b:b_type -> data_ac__inst__increment_available [color="#404040"];
	data_ac__inst__read_key_a_required:read_key_a_required_type -> data_ac__inst__increment_available [color="#404040"];
	data_ac__inst__read_key_b_required:read_key_b_required_type -> data_ac__inst__increment_available [color="#404040"];
	ac_bit__inst__b:b_type -> data_ac__inst__increment_available [color="#404040"];
	data_ac__inst__read_key_a_required:read_key_a_required_type -> data_ac__inst__increment_available [color="#404040"];
	data_ac__inst__read_key_b_required:read_key_b_required_type -> data_ac__inst__increment_available [color="#404040"];
	ac__inst__bits:bits_type -> ac_bit__seq [style=bold];
	trailer__inst__ac_bits:ac_bits_type -> ac__inst__bits:bits__repeat [color="#404040"];
	ac_bit__inst__n:n_type -> ac__inst__val [color="#404040"];
	ac_bit__inst__n:n_type -> ac__inst__val [color="#404040"];
	ac_bit__inst__n:n_type -> ac__inst__val [color="#404040"];
	ac_bit__inst__n:n_type -> ac__inst__inv_shift_val [color="#404040"];
	ac_bit__inst__n:n_type -> ac__inst__inv_shift_val [color="#404040"];
	ac_bit__inst__n:n_type -> ac__inst__inv_shift_val [color="#404040"];
	ac_bit__params:chunk_type -> ac_bit__inst__n [color="#404040"];
	ac_bit__params:i_type -> ac_bit__inst__n [color="#404040"];
	ac_bit__inst__n:n_type -> ac_bit__inst__b [color="#404040"];
	valid_chunk__params:inv_chunk_type -> valid_chunk__inst__valid [color="#404040"];
	valid_chunk__params:chunk_type -> valid_chunk__inst__valid [color="#404040"];
}