rfc9980: close small compliance gaps (G1+G3+G4) - #2433
Open
ronaldtse wants to merge 1 commit into
Open
Conversation
…ak-hash binding) Audit-driven polish on top of PR #2355 to close the remaining RFC 9980 compliance gaps. Three changes, one story: make rnp's PQC implementation fully RFC 9980-conformant on the receiver and keygen sides. G1 — Preferred AEAD Ciphersuites for PQ keys (RFC 9980 §7.1) UserPrefs::check_defaults() now populates aead_prefs from symm_algs not only for v6 keys (the prior behaviour) but also for any key whose public-key algorithm is PQ. This ensures v4 ML-KEM-768+X25519 keys also advertise AES-256+OCB, satisfying the RFC's SHOULD for all PQ certs rather than just v6. G3 — Reject weak-hash subkey binding signatures over PQ subkeys (RFC 9980 §7.2) Key::validate_binding() now rejects MD5, SHA-1, and RIPEMD-160 in subkey binding signatures (type 0x18) when the subkey's algorithm is one of the PQ(/T) algorithms. The RFC says a receiving implementation MUST treat such signatures as invalid; rnp now does. G4 — Canonical algorithm name strings (RFC 9980 §2.1) rnp_keygen_alg_map in src/lib/keygen.cpp used hardcoded strings with underscore separators ("ML-KEM-768_X25519") and two outdated names that don't match RFC 9980 at all ("Kyber-X448" for alg ID 36 and "Dilithium-ED448" for alg ID 31). Now uses the RNP_ALGNAME_* macros from include/rnp/rnp.h, which already use the canonical RFC 9980 "+" form. This makes both internal maps consistent and matches the wire-spec naming. G2 (deferred): RFC 9980 §7.1 also specifies that a receiver should implicitly append AES-256 to a PQ recipient's preferences if it's missing. rnp does not have a recipient-pref-intersection code path today (callers choose the cipher via rnp_op_encrypt_set_cipher), so there's nothing to add AES-256 to. This item is moot until rnp grows recipient-driven cipher selection.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2433 +/- ##
==========================================
- Coverage 85.37% 85.37% -0.01%
==========================================
Files 126 126
Lines 22789 22787 -2
==========================================
- Hits 19457 19455 -2
Misses 3332 3332 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First of three batched PRs addressing the audit findings in
TODO.rnp-roadmap/26-rfc9980-and-thunderbird-integration.md. Closes the small RFC 9980 compliance gaps on top of PR #2355. The other two batched PRs (revocation service docs, backup/recovery infrastructure) will follow.What's in this PR
Three small changes, one coherent story: "make rnp's PQC implementation fully RFC 9980-compliant on the keygen and receiver sides."
G1 — Preferred AEAD Ciphersuites for PQ keys (RFC 9980 §7.1)
UserPrefs::check_defaults()now populatesaead_prefsfromsymm_algsnot only for v6 keys (the prior behaviour) but also for any key whose public-key algorithm is PQ. Ensures v4ML-KEM-768+X25519keys also advertiseAES-256+OCB, satisfying the RFC's SHOULD for all PQ certs rather than just v6.G3 — Reject weak-hash subkey binding signatures over PQ subkeys (RFC 9980 §7.2)
Key::validate_binding()now rejects MD5, SHA-1, and RIPEMD-160 in subkey binding signatures (type 0x18) when the subkey's algorithm is PQ. The RFC says a receiving implementation MUST treat such signatures as invalid; rnp now does. ReturnsRNP_ERROR_SIG_WEAK_HASH.G4 — Canonical algorithm name strings (RFC 9980 §2.1)
rnp_keygen_alg_mapinsrc/lib/keygen.cppused hardcoded strings with underscore separators ("ML-KEM-768_X25519") and two outdated names that don't match RFC 9980 at all ("Kyber-X448"for alg ID 36,"Dilithium-ED448"for alg ID 31). Now uses theRNP_ALGNAME_*macros frominclude/rnp/rnp.h, which already use the canonical RFC 9980+form. Makes both internal maps consistent and matches the wire-spec naming.Why
Audit against the published RFC 9980 (June 2026) showed rnp's PQC implementation is essentially complete (via #2355), but three small receiver/keygen-side items were not yet enforced. This PR closes them.
What's NOT in this PR (deferred)
G2 — Implicit AES-256 when encrypting to PQ recipients (RFC 9980 §7.1)
RFC 9980 §7.1 also specifies that a receiver should implicitly append AES-256 to a PQ recipient's preferences if it's missing. rnp does not have a recipient-pref-intersection code path today — callers choose the cipher via
rnp_op_encrypt_set_cipher(), so there's nothing to implicitly augment. This item is moot until rnp grows recipient-driven cipher selection.Test plan
test_ffi_security_profileandtest_ffi_security_rule_enumerationstill passtest_ffi_pqc_gen_enc_signwill exercise G1; existing import tests will exercise G4)Related
TODO.rnp-roadmap/26-rfc9980-and-thunderbird-integration.md