diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..b465c38 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 496070c..5e109db 100644 --- a/.gitignore +++ b/.gitignore @@ -175,3 +175,7 @@ cython_debug/ # Docs site public/ + +# MacOS +.DS_Store +**/.DS_Store diff --git a/src/desfire/schemas/card_version.py b/src/desfire/schemas/card_version.py index 6db1dbb..1f770e0 100644 --- a/src/desfire/schemas/card_version.py +++ b/src/desfire/schemas/card_version.py @@ -31,9 +31,36 @@ def __init__(self, data: list[int]): def __repr__(self) -> str: temp = "--- Desfire Card Details ---\r\n" - temp += f"Hardware Version: {self.hardware_minor_version}.{self.hardware_minor_version}\r\n" + temp += f"Hardware Version: {self.hardware_major_version}.{self.hardware_minor_version}\r\n" temp += f"Software Version: {self.software_major_version}.{self.software_minor_version}\r\n" - temp += f"EEPROM size: {1 << (self.hardware_storage_size - 1)} bytes\r\n" + + # EEPROM size calculation according to NXP documentation, + # see https://www.nxp.com/docs/en/application-note/AN10833.pdf + # Formula is in Figure 1 on page 4, lower right corner of the table, but a bit unclear. + # . Examples are in the table itself below some card types, e.g. MIFARE DESFire + # see also https://www.nxp.com/docs/en/data-sheet/NTAG213_215_216.pdf + # on page 36, Table 28 and notes below + # + # Meaning and encoding of 'hardware_storage_size': + # Bit 0 (LSB) indicates the size encoding method + # Bit 1..7 are the 'size' value used in the formula below + # + # Formula: + # if bit 0 = 1, then storageBytes = 2^(size // 2) up to storageBytes = 2^(size // 2 + 1) + # if bit 0 = 0, then storageBytes = 2^(size // 2) + # + # Examples: + # Ultralight Family, e.g. Ultralight C has bit 0 = 1, e.g. 0x0B (for 48 Byte) or 0x0E (128 Byte) + # MIFARE DESFire Family has bit 0 = 0, e.g. 0x16: 2K, 0x18: 4K, 0x1A: 8K, 0x1C: 16K, 0x1E: 32K + # + # LSB indicates size encoding method + if (self.hardware_storage_size & 0x01) == 0x01: # typical for Ultralight C, and EV1 + temp += ( + f"EEPROM size: {1 << (self.hardware_storage_size >> 1)} up to " + f"{1 << ((self.hardware_storage_size >> 1) + 1)} bytes\r\n" + ) + else: # typical for DESFire EV1, EV2, and EV3 + temp += f"EEPROM size: {1 << (self.hardware_storage_size >> 1)} bytes\r\n" temp += f"Production: week {self.production_date_cw:X}, year 20{self.production_date_year:02X}\r\n" temp += f"UID no: {to_hex_string(self.uid)}\r\n" temp += f"Batch no: {to_hex_string(self.batch_no)}\r\n" diff --git a/tests/tests_test_card_version_repr.py b/tests/tests_test_card_version_repr.py new file mode 100644 index 0000000..f6a5603 --- /dev/null +++ b/tests/tests_test_card_version_repr.py @@ -0,0 +1,61 @@ +from desfire.schemas.card_version import CardVersion + + +def test_card_version_repr_hardware_major_minor(): + # Prepare data for real MIFARE DESFire EV1 card with 4K from 2013 + data = [ + 0x04, # first block, hardware vendor id + 0x01, + 0x01, + 0x01, + 0x00, + 0x18, + 0x05, + 0x04, # second block, software vendor id + 0x01, + 0x01, + 0x01, + 0x04, + 0x18, + 0x05, + 0x04, # third block, starts with UID + 0x4D, + 0x70, + 0xBA, + 0x5F, + 0x35, + 0x80, + 0xBA, + 0x44, + 0x97, + 0xD6, + 0x70, + 0x28, + 0x13, + ] + cv = CardVersion(data) + s = repr(cv) + assert "Hardware Version: 1.0" in s + assert "Software Version: 1.4" in s + print(s) + + +""" +output with current code was: +--- Desfire Card Details --- +Hardware Version: 0.0 +Software Version: 1.4 +EEPROM size: 8388608 bytes +Production: week 28, year 2013 +UID no: 04 4D 70 BA 5F 35 80 +Batch no: BA 44 97 D6 + +new code produces following output: +--- Desfire Card Details --- +Hardware Version: 1.0 +Software Version: 1.4 +EEPROM size: 4096 bytes +Production: week 28, year 2013 +UID no: 04 4D 70 BA 5F 35 80 +Batch no: BA 44 97 D6 +"""