Repository: LudovicRousseau/pyscard (language: python)

Issue:
ATR clock rates and bit rates
I'm beginning to review the ATR code to test it, and it _looks_ like some of the constants are sourced from ISO 7816-3. However, I'm not sure if I'm reading this right and want to confirm.

I think I'm looking at the 2006 edition of 7816-3, which may affect correctness.

# Clock rate conversion integers

Screenshot of clock conversion rate integers, from section 8.3:

> ![image](https://github.com/user-attachments/assets/9be9a0c6-1143-4dc6-a95c-27e0834bcbf4)

Current Python code, formatted into groups of 8:

```python
clockrateconversion = [
    372,   372, 558, 744,  1116, 1488, 1860,  "RFU",
    "RFU", 512, 768, 1024, 1536, 2048, "RFU", "RFU",

    "RFU",  # <-- This looks like it's not part of the spec
]
```

_Analysis: It looks like there's an extra "RFU" trailing at the end of the Python code, and that it could be removed._

# Baud rate adjustment integers

Screenshot of baud rate adjustment integers, from section 8.3:

> ![image](https://github.com/user-attachments/assets/b5306013-d093-455c-9927-63ecc00b9ac6)

Current Python code, formatted into groups of 8:

```python
bitratefactor = [
    "RFU", 1,  2,     4,     8,     16,    32,    "RFU",
#                                                 ^^^^^ looks like this should be 64
    12,    20, "RFU", "RFU", "RFU", "RFU", "RFU", "RFU",
]
```

_Analysis: It looks like one of the `"RFU"` values should be 64._

----

I'm working to understand what ATRs represent, and wanted to confirm that I'm reading the correct specification (ISO 7816-3 2006) in the correct section (8.3) and comparing that with the correct code (`ATR.py`).

Thanks for any insight you can offer!


Discussion / hints:
You are right. The tables have been updated in a later ISO 7816-3 document. The Python code should be updated.

See https://blog.apdu.fr/posts/2016/04/atr-statistics-ta1-global-encodes-fi/

Fix patch:
diff --git a/ChangeLog b/ChangeLog
index 6e531746..1a533925 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,7 @@ Unreleased changes
    * Build the docs as a part of the test suite
    * Begin to add type annotations to the package
    * Deprecate the `HexListToBinString`, `BinStringToHexList`, `hl2bs`, and `bs2hl` utility functions
+   * Support "64" as an ATR baud rate adjustment integer (ISO 7816-3 2006)
 
 2.1.1 (September 2024)
 ======================
diff --git a/src/smartcard/ATR.py b/src/smartcard/ATR.py
index d65f6681..daffd4fe 100644
--- a/src/smartcard/ATR.py
+++ b/src/smartcard/ATR.py
@@ -46,7 +46,6 @@ class ATR:
         2048,
         "RFU",
         "RFU",
-        "RFU",
     ]
     bitratefactor = [
         "RFU",
@@ -56,7 +55,7 @@ class ATR:
         8,
         16,
         32,
-        "RFU",
+        64,
         12,
         20,
         "RFU",


Test patch:
diff --git a/test/test_ATR.py b/test/test_ATR.py
index a50a7234..9509af8e 100644
--- a/test/test_ATR.py
+++ b/test/test_ATR.py
@@ -156,3 +156,19 @@ def test_atr_get():
     assert a.getHistoricalBytes(), [0x36 == 0x06]
     assert a.isT15Supported() is False
     assert str(a) == atr
+
+
+@pytest.mark.parametrize(
+    "field, expected_length",
+    (
+        ("clockrateconversion", 16),
+        ("bitratefactor", 16),
+    ),
+)
+def test_map_lengths(field, expected_length):
+    """Verify ATR class fields have expected lengths.
+
+    This doesn't validate values, but simply ensures the lengths match expectations.
+    """
+
+    assert len(getattr(ATR, field)) == expected_length