Skip to content

Create the temporary PKCS12 with FIPS-approved algorithms - #483

Draft
miharp wants to merge 2 commits into
puppetlabs:mainfrom
miharp:fips-pkcs12
Draft

miharp wants to merge 2 commits into
puppetlabs:mainfrom
miharp:fips-pkcs12

Conversation

@miharp

@miharp miharp commented Oct 23, 2026 •

Copy link
Copy Markdown

Summary

On a host running in FIPS mode, importing a private key and certificate fails because OpenSSL::PKCS12.create is called with its default arguments. Under OpenSSL 1.1.1 in FIPS mode (Enterprise Linux 8) the default bag encryption is RC2-40 and 3DES and the call raises encrypt error; under an OpenSSL 3 whose FIPS provider has no PKCS12 KDF (for example the one bundled with the FIPS builds of the OpenVox agent) the integrity MAC cannot be derived and it raises mac generation error. In both cases ensure => latest fails with Could not set 'latest' on ensure.

This change adds a pkcs12_create helper to the keytool provider. When OpenSSL.fips_mode is true it asks for PBES2 with AES-256 for both bags (the OpenSSL 3 default, readable by keytool since Java 8u301 and 11.0.12) and skips the MAC; the PKCS12 is a temporary file that keytool reads once, so the MAC adds nothing. Outside FIPS mode the call is unchanged, so hosts whose OpenSSL and Java already agree on a format keep it. Unit tests cover both branches; the README gains a FIPS note under Limitations.

Additional Context

  • Root cause and the steps to reproduce.
    • AlmaLinux 8 container, OPENSSL_FORCE_FIPS_MODE=1, system Ruby: OpenSSL::PKCS12.create(pass, name, key, cert, []) raises PKCS12Error: encrypt error; with 'AES-256-CBC', 'AES-256-CBC', nil, -1 it succeeds and keytool -importkeystore accepts the file.
    • AlmaLinux 9 in FIPS mode with the FIPS build of the OpenVox agent (openvox-agent 9.1.1 redhatfips9, bundled OpenSSL 3.5.9, OpenSSL.fips_mode true): java_ks from main fails with Could not set 'latest' on ensure: mac generation error for both the default (PKCS12) target keystore and storetype => jks; with this branch both imports succeed and a second run reports no changes. Same result with openvox-agent 8.31.1 (OpenSSL 3.0.22).
    • Red Hat's system OpenSSL 3 carries a PKCS12 KDF exception for FIPS mode, so a system Ruby on EL9 does not reproduce the MAC failure; agents with a bundled OpenSSL do.
  • Thought process behind the implementation.
    • The only FIPS-sensitive step in the provider is building the PKCS12 for -importkeystore; keytool itself and the SHA-256 fingerprint comparison (Support for systems running in FIPS mode #160) are fine. The explicit algorithms and the missing MAC are confined to FIPS mode (second commit): with OpenSSL 3 they are the defaults anyway, and on a non-FIPS OpenSSL 1.x host forcing PBES2 would change a working file into one an older keytool may not read, which matters because ensure => latest removes the existing alias before the import.
    • Red Hat's FIPS-configured OpenJDK 21 still accepts JKS keystores with private keys, so no change to the default store type is needed.

Related Issues (if any)

#160 is the only earlier FIPS change (MD5 to SHA-256 fingerprints, 2016). No open issue describes this failure.

Checklist

  • 🟢 Spec tests. (rake spec: 69 examples, 0 failures; rubocop clean)
  • 🟢 Acceptance tests. (not run; no FIPS host in the acceptance matrix)
  • Manually verified. (puppet apply on a FIPS-mode AlmaLinux 9 host with the OpenVox FIPS agent, PKCS12 and JKS target keystores, idempotent second run)

Assisted by Claude.

miharp and others added 2 commits October 22, 2026 10:20
On a host running in FIPS mode, OpenSSL::PKCS12.create with its default
arguments fails with "encrypt error" under OpenSSL 1.1.1 (Enterprise Linux 8),
because the default bag encryption is RC2-40 and 3DES. The PKCS12 integrity
MAC is keyed with the PKCS12 KDF, which the OpenSSL 3 FIPS provider does not
implement either. The provider never sets these arguments, so java_ks cannot
import a private key and certificate on such hosts.

Ask for PBES2 with AES-256 explicitly, which is the OpenSSL 3 default and is
read by keytool since Java 8u301 and 11.0.12, and skip the MAC when OpenSSL
reports FIPS mode. The PKCS12 is a temporary file that keytool reads once, so
the MAC adds nothing.

Reproduced two ways. On AlmaLinux 8 with OPENSSL_FORCE_FIPS_MODE=1 the
current call raises PKCS12Error "encrypt error" and the new call succeeds.
On an AlmaLinux 9 host in FIPS mode with the FIPS build of the OpenVox agent
(openvox-agent 8.31.1 redhatfips9, bundled OpenSSL 3.0.22, OpenSSL.fips_mode
true) the module on main fails with "mac generation error", and with this
change `puppet apply` imports the key into a JKS and into a PKCS12 keystore
and the second run reports no changes. Red Hat's system OpenSSL 3 carries a
PKCS12 KDF exception, so on AlmaLinux 9 with system Ruby both calls succeed.

Signed-off-by: Michael Harp <mike@mikeharp.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The first version asked for PBES2 with AES-256 on every host. That is a
no-op with OpenSSL 3, whose default it is, but on a non-FIPS host with
OpenSSL 1.x it changed the format of a file that older keytools may not
read (PBES2 support arrived in Java 8u301 and 11.0.12), and ensure => latest
removes the existing alias before the import, so a failed import would
also drop the working entry. The explicit algorithms and the missing MAC
are now confined to FIPS mode, where the defaults cannot work at all.

Signed-off-by: Michael Harp <mike@mikeharp.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

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