In TPMCmd/tpm/src/support/TableDrivenMarshal.c, the TPM2BS_MTYPE branch of Unmarshal() has what looks like a copy-paste mistake on line 620:
if((m2bst->modifiers & PROPAGATE_NULL) && (typeIndex & typeIndex))
index |= NULL_FLAG;
The condition typeIndex & typeIndex is a tautology; it always equals typeIndex, so the check reduces to just (m2bst->modifiers & PROPAGATE_NULL). The intended check is typeIndex & NULL_FLAG, which tests whether the outer caller flagged null as permitted before propagating it inward. The LIST_MTYPE branch 30 lines later at line 651 does this correctly:
if((mlt->modifiers & PROPAGATE_NULL) && (typeIndex & NULL_FLAG))
index |= NULL_FLAG;
The result is that NULL_FLAG gets unconditionally set on the inner type index whenever PROPAGATE_NULL is present in the descriptor, regardless of whether the outer context actually allowed null. In practice, TPM2B_PUBLIC_DATA is the only TPM2BS_MTYPE entry in TableMarshalData.c with ELEMENT_PROPAGATE set, so this affects TPMT_PUBLIC unmarshal - nameAlg = TPM_ALG_NULL passes marshal-layer validation unconditionally when it should not. PublicAttributesValidation() in Object_spt.c catches this downstream for the standard create/load commands, so I don't believe this is directly exploitable today. However the marshal layer is supposed to be the primary validation boundary, not a secondary check, and the current behavior undermines that for any future command consuming TPM2B_PUBLIC without an independent guard.
Fix is a one-word change on line 620: (typeIndex & typeIndex) to (typeIndex & NULL_FLAG). Only relevant when TABLE_DRIVEN_MARSHAL is set to YES.
In TPMCmd/tpm/src/support/TableDrivenMarshal.c, the TPM2BS_MTYPE branch of Unmarshal() has what looks like a copy-paste mistake on line 620:
The condition typeIndex & typeIndex is a tautology; it always equals typeIndex, so the check reduces to just (m2bst->modifiers & PROPAGATE_NULL). The intended check is typeIndex & NULL_FLAG, which tests whether the outer caller flagged null as permitted before propagating it inward. The LIST_MTYPE branch 30 lines later at line 651 does this correctly:
The result is that NULL_FLAG gets unconditionally set on the inner type index whenever PROPAGATE_NULL is present in the descriptor, regardless of whether the outer context actually allowed null. In practice, TPM2B_PUBLIC_DATA is the only TPM2BS_MTYPE entry in TableMarshalData.c with ELEMENT_PROPAGATE set, so this affects TPMT_PUBLIC unmarshal - nameAlg = TPM_ALG_NULL passes marshal-layer validation unconditionally when it should not. PublicAttributesValidation() in Object_spt.c catches this downstream for the standard create/load commands, so I don't believe this is directly exploitable today. However the marshal layer is supposed to be the primary validation boundary, not a secondary check, and the current behavior undermines that for any future command consuming TPM2B_PUBLIC without an independent guard.
Fix is a one-word change on line 620: (typeIndex & typeIndex) to (typeIndex & NULL_FLAG). Only relevant when TABLE_DRIVEN_MARSHAL is set to YES.