RustCrypto / RustCrypto/signatures
XMSSMT OID parsing bug
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 661
- Forks
- 196
- Avg merge
- 1h 45m
- Merged PRs (30d)
- 1
Description
The first four bytes of an XMSS/XMSSMT public key correspond to the OID, which identifies the parameter set. XMSS and XMSSMT's OIDs are defined separatly, meaning they both start from zero and hence have colliding OIDs.
The library distinguishes XMSS and XMSSMT's OIDs by adding an offset to XMSSMT's OIDs, in the definition of the XmssOid enum in the file xmss/src/param.rs.
When verifying signatures using a public key imported as raw bytes, the public key has to be parsed into a VerifyingKey<P>, with P corresponding to the parameter set used. This is done by using the method VerifyingKey::<P>::try_from(bytes). This method begins by calling the function parse_oid_and_params(bytes), which parses the XmssOid from the raw byte prefix.
However, parse_oid_and_params(bytes) first attempts to parse the OID as an XMSS one, by directly calling the method XmssOid::try_from(value). If that last method fails, it will fall back to XmssOid::from_xmssmt_raw_oid(oid) which attempts to parse the OID as an XMSSMT one. This method will add the XMSSMT OID offset before calling XmssOid::try_from(value).
The problem arises when importing an XMSSMT public key whose OID collides with an XMSS one. Since parse_oid_and_params(bytes) attempts to parse the OID as an XMSS one first, it will wrongly return the XmssOid of the colliding XMSS parameter set, instead of the actual XMSSMT one with the added offset. As a result, in VerifyingKey::<P>::try_from(bytes) the check if oid != expected_oid at line 225 will fail. XMSSMT parameter sets that have an OID that collides with an XMSS one can not be used if the public key is imported.
The tests in xmss/src/lib.rs only include one XMSSMT parameter set. It does have a colliding OID but the public key is generated with KeyPair::<XmssMtSha2_20_2_256>::generate(&mut rand::rng()) and not imported from raw bytes.
In the attached file example.md, there is first an example of a valid XMSSMT public key with a non colliding OID=22, which is successfully parsed. Then there is an example of a valid XMSSMT public key with a colliding OID=21, which causes the described OID parsing bug.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in xmss/src/param.rs with the XmssOid enum and then trace parse_oid_and_params through the VerifyingKey::try_from check around line 225. Compare the colliding and non-colliding XMSSMT examples in example.md, and review the existing XMSSMT coverage in xmss/src/lib.rs. Done means imported raw XMSSMT public keys with colliding OIDs parse as their expected parameter set and the regression is covered by tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cryptography
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100