You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
readdir() in PKCS#11 config file read does not guarantee the expected alphabetical order #322
When using freeslots to store labelled keys in ATECC608B-TFLXTLS the readout of the PKCS#11 configuration is broken since v3.4 (20221027).
As soon as a key is stored in a freeslot (and the according 0.x.conf is created), the ATECC608B is not recognized anymore by PKCS#11 tools.
In 0.conf modify the line "freeslots = 2,3,4" to make these key slots available or key storage (note that slot 1 has fixed content on ATECC608B-TFLXTLS)
Call p11tool --list-keys -> the fixed keys of ATECC608B-TFLXTLS are shown.
Generate a new key with p11tool "pkcs11:token=00ABC" --generate-privkey=ECDSA --bits=288 --curve=secp256r1 --label=testkey -> the config file 0.2.conf is created
Again call p11tool --list-keys -> the PKCS#11 token representing the ATECC608B-TFLXTLS is not found anymore.
Expected behavior
The PKCS#11 token representing the ATECC608B-TFLXTLS is still accessible, the fixed keys and the generated key in keyslot 2 are shown.
This worked as intended in v3.3.3
Additional context
Debug output of crytoauthlib shows
p11tool --list-keys
1024:1024:C_Initialize:141:
1024:1024:pkcs11_config_load_objects:892:Opening Configuration: /var/lib/cryptoauthlib/0.2.conf
1024:1024:pkcs11_config_load_objects:956:Trying to load an object configuration without a slot configuration file
1024:1024:C_Initialize:142:CKR_OK(0)
1024:1024:C_GetInfo:159:
1024:1024:C_GetInfo:160:CKR_CRYPTOKI_NOT_INITIALIZED(190)
1024:1024:C_GetSlotList:184:
1024:1024:C_GetSlotList:185:CKR_CRYPTOKI_NOT_INITIALIZED(190)
warning: no token URL was provided for this operation; the available tokens are:
Issue analysis
The issue is raised by a change in pkcs11_config.c -> pkcs11_config_load_objects() in v3.4, where readdir() is used to enumerate over all configuration files in a loop, while within the loop it is expected that the token configuration file (0.conf) is read and parsed before the keyslot configuration files (0.x.conf).
But the behavior of readdir() is implementation specific and there is no guarantee that it returns an alphabetically ordered list of files in a directory (which would be needed to read 0.conf with the slot_id before all other 0.x.conf files that require the slot_id already been set).
Actually, in a lot of implementations readdir() works in traversal order of file generation history, as it is in our case too.
Reproduced #322 against v3.4.0, and it no longer occurs on v3.6.1 or current main (d49c7d5, the commit the v3.8.0 tag points at).
In v3.4.x each entry is processed inside the readdir() loop (v3.4.0:869), so a child file seen before its base file fails at :954 ("Trying to load an object configuration without a slot configuration file"), and because rv is part of the loop condition the scan stops there and never reaches the base file.
The report's second symptom comes from a different line: v3.4.1:364 is rv = pkcs11_unlock_both(lib_ctx); immediately before return rv;, so C_Initialize() returns CKR_OK over a library whose initialized flag was never set — hence CKR_CRYPTOKI_NOT_INITIALIZED on the next call. On main those unlocks are (void)-cast (d49c7d5:408, :421).
I ran all 24 permutations of {0.conf, 0.2.conf, 0.3.conf, 0.4.conf} through the real loader, no hardware required: v3.4.0 6/24, v3.6.1 24/24, main 24/24.
The 6 is predicted rather than sampled — v3.4.x survives exactly the orders beginning with 0.conf, which is 3! of 4!.
Success is judged by slot_ctx->flags (the fixture declares freeslots = 2,3,4,5 with no 0.5.conf, so a complete load leaves 0x20) rather than by CKR_OK, which only means nothing was fatal.
Sorting is not the fix: strcmp("0.2.conf", "0.conf") < 0 because '2' is 0x32 and 'c' is 0x63, so an ascending sort puts every child ahead of its parent.
v3.6.1 collects the directory first and then opens each base file's children by constructed filename (main:1267, opened at :1284), so enumeration order no longer decides correctness.
The transition is commit 4726296 ("Release v3.6.1 (20230714)"); its parent ec6e64f still opens each file inside the readdir() loop.
Scope: one ext4 filesystem, default single-slot build, observable stops at the config loader. Given the above, can #322 be closed as fixed in v3.6.1?
Activity
andreas-meissner commentedon Dec 19, 2022
BTW: code indentation is a mess in
pkcs11_config_load_objects()and makes it hard to read.learnrahulrai-ui commentedon Aug 14, 2026
Reproduced #322 against v3.4.0, and it no longer occurs on v3.6.1 or current main (d49c7d5, the commit the v3.8.0 tag points at).
In v3.4.x each entry is processed inside the readdir() loop (v3.4.0:869), so a child file seen before its base file fails at :954 ("Trying to load an object configuration without a slot configuration file"), and because rv is part of the loop condition the scan stops there and never reaches the base file.
The report's second symptom comes from a different line: v3.4.1:364 is
rv = pkcs11_unlock_both(lib_ctx);immediately beforereturn rv;, so C_Initialize() returns CKR_OK over a library whoseinitializedflag was never set — hence CKR_CRYPTOKI_NOT_INITIALIZED on the next call. On main those unlocks are (void)-cast (d49c7d5:408, :421).I ran all 24 permutations of {0.conf, 0.2.conf, 0.3.conf, 0.4.conf} through the real loader, no hardware required: v3.4.0 6/24, v3.6.1 24/24, main 24/24.
The 6 is predicted rather than sampled — v3.4.x survives exactly the orders beginning with 0.conf, which is 3! of 4!.
Success is judged by slot_ctx->flags (the fixture declares freeslots = 2,3,4,5 with no 0.5.conf, so a complete load leaves 0x20) rather than by CKR_OK, which only means nothing was fatal.
Sorting is not the fix: strcmp("0.2.conf", "0.conf") < 0 because '2' is 0x32 and 'c' is 0x63, so an ascending sort puts every child ahead of its parent.
v3.6.1 collects the directory first and then opens each base file's children by constructed filename (main:1267, opened at :1284), so enumeration order no longer decides correctness.
The transition is commit 4726296 ("Release v3.6.1 (20230714)"); its parent ec6e64f still opens each file inside the readdir() loop.
Scope: one ext4 filesystem, default single-slot build, observable stops at the config loader. Given the above, can #322 be closed as fixed in v3.6.1?