ffi: add rnp_key_protect_ex() with Argon2 + AEAD support - #2432
Merged
Conversation
| unsigned iterations = 0; | ||
| pgp_s2k_specifier_t s2k_specifier = PGP_S2KS_ITERATED_AND_SALTED; | ||
| pgp_s2k_usage_t s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED; | ||
| pgp_aead_alg_t aead_alg = PGP_AEAD_NONE; |
| pgp_s2k_specifier_t s2k_specifier = PGP_S2KS_ITERATED_AND_SALTED; | ||
| pgp_s2k_usage_t s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED; | ||
| pgp_aead_alg_t aead_alg = PGP_AEAD_NONE; | ||
| uint8_t argon2_t = 0; |
| pgp_s2k_usage_t s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED; | ||
| pgp_aead_alg_t aead_alg = PGP_AEAD_NONE; | ||
| uint8_t argon2_t = 0; | ||
| uint8_t argon2_p = 0; |
| pgp_aead_alg_t aead_alg = PGP_AEAD_NONE; | ||
| uint8_t argon2_t = 0; | ||
| uint8_t argon2_p = 0; | ||
| uint8_t argon2_m = 0; |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2432 +/- ##
==========================================
- Coverage 85.36% 85.09% -0.28%
==========================================
Files 126 126
Lines 22861 22942 +81
==========================================
+ Hits 19516 19523 +7
- Misses 3345 3419 +74 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
ronaldtse
force-pushed
the
pqc-standalone-and-argon2-ffi
branch
from
August 10, 2026 02:09
90e6f55 to
56a427c
Compare
ronaldtse
force-pushed
the
pqc-standalone-and-argon2-ffi
branch
from
August 20, 2026 10:11
56a427c to
ef392af
Compare
Adds a new public FFI function rnp_key_protect_ex() that lets callers opt into Argon2 S2K and AEAD encryption of secret-key material. The existing rnp_key_protect() function exposes only the legacy iterated-and-salted + CFB path; the Argon2 + AEAD path was reachable only via JSON keygen, which is awkward for non-JSON callers. New public types: - rnp_protection_params_t with fields for cipher, cipher_mode, hash, iterations, s2k_type, aead_alg, argon2_t/p/m_kib. Behaviour: - s2k_type = "Argon2" forces AEAD usage (per RFC 9580 crypto refresh) and requires ENABLE_CRYPTO_REFRESH at build time. Without it, the function returns RNP_ERROR_NOT_SUPPORTED. - aead_alg can be specified independently for non-Argon2 AEAD. - All string fields accept NULL for sensible defaults (mirrors rnp_key_protect()). - The Argon2 memory parameter is given in KiB and converted to the on-wire log2(bytes) representation. Test: test_ffi_key_protect_ex_argon2_roundtrip generates a fresh RSA key, protects it with explicit Argon2 parameters (small m/t/p for CI speed), unlocks with wrong (fails) and correct (succeeds) passwords, and confirms the key is still usable for signing after the round-trip. Standalone PQC keygen (ML-DSA, ML-KEM standalone; SLH-DSA 192f/192s/ 256f) is intentionally NOT in this PR. Adding it requires: - Allocating new PGP_PKA_* codepoints per draft-ietf-openpgp-pqc - Verifying wire-format details against the latest draft - Material parsing/serialisation in key_material.cpp - New fixtures from the draft test vector appendix The Botan backend already supports these parameter sets (SLHDSA192Small/Fast, SLHDSA256Fast); only the OpenPGP wire layer is missing. Tracked as a follow-up.
ronaldtse
force-pushed
the
pqc-standalone-and-argon2-ffi
branch
from
August 20, 2026 10:37
ef392af to
6fd3b62
Compare
2 tasks
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
Addresses the second of two gaps flagged in PR #2431's "out of scope" section: the FFI did not expose Argon2 S2K for
rnp_key_protect. This PR addsrnp_key_protect_ex()and a new publicrnp_protection_params_tstruct that lets callers opt into Argon2 + AEAD protection.What's in this PR
include/rnp/rnp.h: new public structrnp_protection_params_tand new FFI functionrnp_key_protect_ex(handle, password, params). Wrapped in#ifndef RNP_PROTECTION_PARAMS_T_DEFINEDbecausernp.hlacks a top-level include guard (the existing internalrnp_key_protection_params_tlives insrc/lib/types.h).src/lib/rnp.cpp: full implementation. Strings are resolved to the internal enums (PGP_S2KS_ARGON2,PGP_AEAD_OCBetc.); defaults mirrorrnp_key_protect(). Argon2 memory is given in KiB and converted to the on-wirelog2(bytes)representation. On builds withoutENABLE_CRYPTO_REFRESH, requests for Argon2 or explicit AEAD returnRNP_ERROR_NOT_SUPPORTED.src/tests/ffi-enc.cpp: new testtest_ffi_key_protect_ex_argon2_roundtrip— generates a fresh RSA key, protects with explicit small Argon2 parameters, verifies wrong-password fails and correct-password succeeds, signs and verifies.Why
The Argon2 + AEAD path was previously reachable only via the JSON keygen parser. Callers building keys via the regular FFI (
rnp_op_generate+rnp_key_protect) had no way to request Argon2 S2K — they were stuck with iterated-and-salted + CFB even on v6 keys where the library forces Argon2 anyway, but only for v6.This is also a prerequisite for the Thunderbird key-backup proposal (Kai Engert's
key-backup-recovery-strategy.md) — it stores the recovery private key under "normal Thunderbird key protection", and being able to specify Argon2 via FFI matches the v6 expectation.Standalone PQC variants — DEFERRED
The first "out of scope" gap from #2431 was standalone ML-DSA / ML-KEM / additional SLH-DSA variants (192f, 192s, 256f). This PR does NOT address them. Reasons:
PGP_PKA_*codepoints requires verifying against the currentdraft-ietf-openpgp-pqc(the merged Update PQC Draft to Version 12 #2355 covered the draft-12 codepoints 30–36; the missing variants need codepoints that the draft may or may not have registered with IANA yet).SLHDSA192Small,SLHDSA192Fast,SLHDSA256Fast); only the OpenPGP wire layer is missing.src/lib/crypto/ec.cpp:202(usesBotan::EC_Groupmembers that became opaque in 3.12), so I cannot verify PQC changes locally without first fixing that.I'll open a follow-up issue/PR for standalone PQC once the codepoint question is resolved with the spec author.
Test plan
test_ffi_key_protect_ex_argon2_roundtrippasses (CI will run it; local build blocked by the Botan 3.12 issue mentioned above)Out of scope for follow-up PRs
rnp.htop-level include guard (would touch the public header globally)rnp_key_protect's parameter list with the new struct (would be API-breaking; current approach is additive)