Skip to content

fix(pkcs12): validate kdf iteration count >= 1#2285

Merged
baloo merged 1 commit intoRustCrypto:masterfrom
MarkAtwood:pkcs12-kdf-validate
Apr 13, 2026
Merged

fix(pkcs12): validate kdf iteration count >= 1#2285
baloo merged 1 commit intoRustCrypto:masterfrom
MarkAtwood:pkcs12-kdf-validate

Conversation

@MarkAtwood
Copy link
Copy Markdown
Contributor

Summary

  • derive_key, derive_key_bmp, and derive_key_utf8 all accept rounds: i32 with no validation
  • The iteration loop for _ in 1..rounds silently degenerates to a single hash application when rounds <= 0, producing wrong output with no error
  • RFC 7292 Appendix C defines iterations INTEGER (1..MAX) — zero and negative values are out-of-spec

Fix

Add a rounds < 1 guard at the top of each function returning Err(ErrorKind::Value { tag: Tag::Integer }). derive_key and derive_key_bmp return types change from Vec<u8> to der::Result<Vec<u8>> to carry the error.

Tests

  • pkcs12_key_derive_rounds_one_boundary — verifies rounds=1 produces the correct output for EncryptionKey and Mac key types (SHA-256, vectors generated with openssl kdf … -kdfopt iter:1 … PKCS12KDF and hardcoded)
  • pkcs12_key_derive_zero_rounds_errors — asserts that rounds=0, rounds=-1, and rounds=i32::MIN all return Err

Breaking change note

derive_key and derive_key_bmp are public API. Changing their return type from Vec<u8> to der::Result<Vec<u8>> is a breaking change. Given that the previous behaviour was silently incorrect for rounds <= 0, and pkcs12 is still pre-release (0.2.0-pre.0), this seems justified. Happy to discuss alternatives (e.g. u32 parameter, or a separate validated wrapper).

RFC 7292 Appendix C defines iterations as INTEGER (1..MAX).
The loop `for _ in 1..rounds` silently degenerates to a single
hash application for rounds <= 0, producing wrong output without
signalling failure.

Add a rounds < 1 guard to derive_key, derive_key_bmp, and
derive_key_utf8 returning ErrorKind::Value { tag: Tag::Integer }.
Change derive_key and derive_key_bmp return types to der::Result.

Add tests: rounds=1 boundary vectors (verified against OpenSSL
PKCS12KDF), and rounds=0/-1/i32::MIN error cases.
@baloo baloo merged commit 7165ae8 into RustCrypto:master Apr 13, 2026
11 checks passed
Comment thread pkcs12/src/kdf.rs
/// `pass` must be a Unicode (UTF-16BE) byte array in big-endian order without a byte-order mark
/// and with two terminating zero bytes.
///
/// `rounds` must be ≥ 1 (RFC 7292 Appendix C defines `iterations INTEGER (1..MAX)`).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change makes sense to me (and I already merged it), but I can't actually find the text referred here in the RFC7292. Am I missing something?

@MarkAtwood

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants