In gpgconf.h, the enum gc_component_id_t has a comment:
/* Component system. Each component is a set of options that can be * configured at the same time. If you change this, don't forget to * update gc_component[] in gpgconf-comp.c. */
it defines an enum value GC_COMPONENT_TPM2DAEMON (6) and GC_COMPONENT_PINENTRY (8).
In gpgconf-comp.c, the table gc_component looks like this:
} gc_component[GC_COMPONENT_NR] = { /* Note: The order of the items must match the order given in the * gc_component_id_t enumeration. The order is often used by * frontends to display the backend options thus do not change the * order without considering the user experience. */ { NULL }, /* DUMMY for GC_COMPONENT_ANY */
but the component-data for the TPM2 daemon is included only if BUILD_WITH_TPM2D is defined. So when that define is off, the gc_component table is one shorter than intended. This has two effects:
- read after the end of the table when looping in gc_component_retrieve_options() .
- mismatch between IDs and the actual entries; in particular, entry 6 in the table is the one for dirmngr, and entry 7 is now pinentry. Code that loops and checks to skip pinentry (enum value 8) now hits pinentry accidentally, as entry 7 in the table.
This yields downstream bug report https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=259775 -- gpg tries to collect options all components, skipping pinentry; the code skips enum value 8, but reaches pinentry in table entry 7 already.
I applied a simple patch that adds
#else { NULL }, /* Another dummy, to keep the enum in sync with this table */ #endif
so there is a null entry in the table at place 6 (where the tpm daemon goes) and the table's length and entries are in-sync with the enum again.