RHEL 8 & RHEL 9 System-Wide Cryptographic Policies


1. What is System-Wide Crypto Policy?

RHEL centralizes cryptographic settings through system-wide cryptographic policies. Instead of configuring every application individually, supported applications (OpenSSL, GnuTLS, OpenSSH, Java, Libreswan, NSS, etc.) inherit a common policy. Please review Official Redhat docs for more details.

Benefits:

  • Consistent security posture
  • Easier compliance
  • Centralized administration
  • Reduced configuration drift

2. Policy Levels

PolicyPurposeTypical Use
LEGACYMaximum compatibilityOld environments only
DEFAULTRed Hat recommendedProduction default
FUTUREStronger algorithms onlySecurity-focused environments
FIPSFIPS validated algorithmsRegulated environments

Change policy:

sudo update-crypto-policies --set DEFAULT

Reboot is recommended because long-running services may continue using previously loaded cryptographic settings until restarted.

📘

Important:

The exact algorithms permitted by these policies can change between RHEL releases. Therefore, do not assume that DEFAULT or FUTURE has identical contents on RHEL 8 and RHEL 9. Red Hat documents the predefined policies and recommends using update-crypto-policies to manage them.

When troubleshooting a vulnerability scan or cryptographic configuration, distinguish these three questions:

  • Does the software support the algorithm?
  • Does the RHEL crypto policy permit the algorithm?
  • Does the running service actually offer/accept the algorithm?

For example:

It lists cipher algorithms supported by the installed OpenSSH implementation.

ssh -Q cipher

It should not, by itself, be used to conclude that every listed cipher is enabled by the SSH server.

Similarly:

openssl ciphers -v

provides information about ciphers available through OpenSSL, but it does not by itself prove that an Apache, Nginx, HAProxy, or another TLS service is actually offering every displayed cipher.

Therefore, cryptographic validation should include:

Software capability
        |
System crypto policy
        |
Application configuration
        |
Effective service configuration
        |
Network/negotiation testing


3. Checking the Current Crypto Policy


Check the active policy:

update-crypto-policies --show

Also inspect the configured policy:

cat /etc/crypto-policies/config

Check the generated backend configuration:

ls -l /etc/crypto-policies/back-ends/

The files in this directory are generated from the selected system-wide policy for supported cryptographic backends.

Do not manually edit generated files in this directory as the normal method of managing system-wide policy.


CURRENT.pol – Checking the Effective Policy:


One of the most useful files when troubleshooting crypto-policy configuration is:

cat /etc/crypto-policies/state/CURRENT.pol
grep '^cipher' /etc/crypto-policies/state/CURRENT.pol
grep '^min_rsa_size' /etc/crypto-policies/state/CURRENT.pol

This file contains the settings of the currently applied system-wide cryptographic policy after wildcard expansion.


4. Subpolicies

Why Custom Subpolicies Are Needed:


Changing the entire system from DEFAULT to FUTURE may be more restrictive than the actual security requirement. For example, assume a security requirement says:

Disable CBC ciphers for SSH.

Changing the entire operating system to another policy level just to satisfy one SSH requirement may unnecessarily affect other cryptographic consumers.

RHEL supports custom policy modules, allowing specific modifications to an existing base policy.

For example: DEFAULT:NO-SSH-CBC can represent: Use DEFAULT + apply an additional policy restriction for SSH CBC ciphers.

Examples:

update-crypto-policies --set DEFAULT:SHA1
update-crypto-policies --set DEFAULT:NO-SHA1

Common use cases:

  • SHA1 – temporary compatibility with legacy systems.
  • NO-SHA1 – explicitly disables SHA-1.

.pol vs .pmod

There are two important concepts.

Complete custom policy: A complete custom policy uses ".pol" and is stored under /etc/crypto-policies/policies/

Example:

/etc/crypto-policies/policies/MYPOLICY.pol

It can be activated with:

update-crypto-policies --set MYPOLICY

Policy module / subpolicy

A policy module uses ".pmod" and is stored under /etc/crypto-policies/policies/modules/. It modifies an existing policy.

Example:

DEFAULT:NO-SSH-CBC

For most cases where only a small security adjustment is required, a policy module avoids maintaining an entire replacement policy.



5. Creating a Custom Policy Module

Policy modules should be placed under "/etc/crypto-policies/policies/modules/"

Red Hat requires policy-module filenames to use uppercase letters.

Example:

# cd /etc/crypto-policies/policies/modules/
# touch NO-SSH-CBC.pmod
# vi /etc/crypto-policies/policies/modules/NO-SSH-CBC.pmod

Add below and save 

cipher@SSH = -*-CBC


6. Understanding the Directive

Consider:

cipher@SSH = -*-CBC

Break it down:

cipher: Means the directive operates on cipher algorithms.

@SSH: Limits the directive to the SSH scope.

-CBC: Removes matching CBC algorithms.

The wildcard * : Allows matching algorithm names.

📘

Important:

The "cipher@SSH" is scoped. It does not mean disable CBC everywhere on the operating system. It means the policy adjustment applies to the SSH scope.




7. Applying the Custom Policy

Record the existing policy:

# update-crypto-policies --show
DEFAULT

Then apply the custom module:

update-crypto-policies --set DEFAULT:NO-SSH-CBC

Verify:

# update-crypto-policies --show
DEFAULT:NO-SSH-CBC

It is recommended to restart the system after changing the system-wide cryptographic policy so that already-running applications use the new configuration.

shutdown -r now "Immediate reboot triggered for crypto policy update"

📘

Important:

Before changing SSH cryptography on a remote server, ensure that you have a tested recovery/console-access method and confirm that required SSH clients remain compatible with the resulting policy.



8. Verification

Verify active policy

update-crypto-policies --show
cat /etc/crypto-policies/config

Check the generated effective policy:

grep '^cipher@SSH' /etc/crypto-policies/state/CURRENT.pol

The exact expanded value can depend on the RHEL release and installed crypto-policies package.

For that reason, do not document a hard-coded expected cipher list without checking the target system.

Instead, inspect the generated policy on that server "grep -i 'CBC' /etc/crypto-policies/state/CURRENT.pol"


9. Validate the Effective SSH Server Configuration

List available ciphers:

sshd -T | grep '^ciphers '
sshd -T | grep '^macs '
sshd -T | grep '^kexalgorithms'
ssh -Q cipher

External SSH Validation

nmap -sV -p 22 --script ssh2-enum-algos <server-ip>

Review the reported:

encryption_algorithms
mac_algorithms
kex_algorithms
server_host_key_algorithms

This tests the SSH service from the network side and helps answer:

  • What algorithms is the running SSH endpoint actually advertising?
  • Do not rely on only one validation layer.

Why ssh -Q cipher Can Be Misleading


 ssh -Q cipher
The output might contain:

aes128-cbc
aes192-cbc
aes256-cbc
aes128-ctr
aes192-ctr
aes256-ctr
...

This does not by itself demonstrate that the SSH server currently accepts CBC.

It demonstrates that those algorithms are recognized/supported by the installed OpenSSH implementation. Therefore "ssh -Q" should be treated as a capability query, not as the sole test of the effective server-side crypto policy.

For effective server configuration, check "sshd -T" and, where appropriate, verify the endpoint from another system.


11. TLS Requires the Same Distinction

The same principle applies to TLS.

openssl ciphers -v

The output does not prove that a particular web server offers every displayed cipher.

A TLS connection can be affected by:

RHEL crypto policy
+
cryptographic library
+
application configuration
+
TLS protocol version
+
certificate/key capabilities

Therefore, if a vulnerability scanner reports a TLS cipher, validate the actual listening TLS service, not only the OpenSSL library.

Test TLS handshake:

openssl s_client -connect example.com:443

Force TLS version:

openssl s_client -connect example.com:443 -tls1_2

Force a specific cipher (useful when troubleshooting):

openssl s_client -connect example.com:443 -cipher AES128-SHA

Test your websites TLS using a 3rd-party website to identify weak ciphers.

Expected result:

  • Success if the client policy and server support the cipher.
  • "handshake failure" or "no shared cipher" if blocked by policy or unsupported.

12. Create a Local TLS Test Server

Generate a temporary certificate:

openssl req -x509 -newkey rsa:4096 -nodes \
-keyout server.key \
-out server.crt \
-days 365

Start a local server:

openssl s_server \
-key server.key \
-cert server.crt \
-accept 8443

Connect:

openssl s_client -connect localhost:8443


9. Scenario

Problem

A legacy application stops connecting after upgrading to RHEL 9.

Checklist

update-crypto-policies --show
openssl s_client -connect server:443
journalctl -xe
ssh -vvv server
nmap --script ssl-enum-ciphers -p443 server

Possible Root Cause

  • Peer only supports SHA-1 signatures or deprecated algorithms.

Temporary Mitigation

sudo update-crypto-policies --set DEFAULT:SHA1

Permanent Fix

Upgrade the peer or replace the certificate so compatibility exceptions can be removed.

Review - Configuring RHEL 8 for compliance with crypto-policy related to Cipher Block Chaining


10. Bypassing the System Policy

Prefer application-specific exceptions over weakening the entire system.

Appropriate cases:

  • Legacy appliances
  • Older Java runtimes
  • Unsupported embedded devices
  • Temporary migration windows

Avoid switching the entire system to LEGACY unless there is a documented business requirement.


11. Troubleshooting Flow

Handshake Failure
      |
      v
update-crypto-policies --show
      |
      v
openssl s_client
      |
      v
nmap ssl-enum-ciphers
      |
      v
Identify unsupported cipher/signature
      |
      +--> Temporary compatibility (e.g. DEFAULT:SHA1)
      |
      +--> Permanent remediation (upgrade peer/certificate)

12. Best Practices

  • Keep DEFAULT unless a justified exception exists.
  • Use FUTURE only after compatibility testing.
  • Use FIPS only when compliance requires it.
  • Prefer application-level exceptions over global policy changes.
  • Document every temporary compatibility change and remove it after remediation.

References


Did this page help you?