Skip to content

Possible incompatibility with OpenSSL FIPS mode #13475

@cjpatton

Description

@cjpatton

I have an application in scope of FIPS that needs to validate JWT tokens of type RS256. My best guess is that the jwt is trying to use a low level API that OpenSSL disables when running in FIPS mode. I'm reporting here because I couldn't find another API in cryptography for verifying an RSA signature.

RS256 is RSA with PKCS#1 v1.5 padding and SHA256. I believe this should be FIPS compliant --- the public key in the test below has a 4096-bit modulus. The test also fails with PS256, which is RSA-PSS.

I'm on ARM64 and am building the OpenSSL 3.1.2 FIPS module. My backend is:

(.venv) root@4ea79d5dcc51:/w# OPENSSL_CONF=fips.cnf python
Python 3.13.5 (main, Jun 25 2025, 18:55:22) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from cryptography.hazmat.backends import default_backend
>>> default_backend()
<OpenSSLBackend(version: OpenSSL 3.5.3 16 Sep 2025, FIPS: True, Legacy: True)>

Thanks in advance for any help!

Steps to reproduce

Jump into a container

docker run --rm -it -v "$PWD:/w" -w /w debian:trixie

Start virtual environment, install prerequisites

apt update && apt install -y openssl python3 python3-venv vim wget build-essential
python3 -m venv .venv && source .venv/bin/activate
pip install PyJWT cryptography

Install FIPS module

As described here.

wget https://www.openssl.org/source/openssl-3.1.2.tar.gz
tar -xf openssl-3.1.2.tar.gz
cd openssl-3.1.2
./Configure enable-fips
make
make install_fips

Control test

python test.py  # expect success

Expected output:

(.venv) root@4ea79d5dcc51:/w# python test.py
FIPS: False
success

Test with FIPS enabled

OPENSSL_CONF=fips.cnf python test.py  # expect ES256 success, but RS256 failure

Expected output:

(.venv) root@4ea79d5dcc51:/w# OPENSSL_CONF=fips.cnf python test.py
FIPS: True
RS256 failed:
Unknown OpenSSL error. This error is commonly encountered
                    when another library is not cleaning up the OpenSSL error
                    stack. If you are using cryptography with another library
                    that uses OpenSSL try disabling it before reporting a bug.
                    Otherwise please file an issue at
                    https://github.com/pyca/cryptography/issues with
                    information on how to reproduce this. (error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:375:Global default library context, Algorithm (SHA256 : 102), Properties (), error:03000086:digital envelope routines:evp_md_init_internal:initialization error:crypto/evp/digest.c:271:)

test.py

from cryptography.exceptions import InvalidSignature, InternalError
from cryptography.hazmat.backends.openssl.backend import backend
from jwt.algorithms import get_default_algorithms

print('FIPS:', backend._fips_enabled)

failures = 0

verifier = get_default_algorithms()["ES256"]
pk = verifier.from_jwk({
    "kty":"EC",
    "crv":"P-256",
    "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
    "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
    "use":"sig",
    "kid":"1",
})
try:
    verifier.verify(b"some message", pk, b"invalid signature")
except InvalidSignature:
    pass  # We don't have a valid signature, so expect this to fail.
except InternalError as e:
    print('ES256 failed:')
    print(e)
    failures += 1

verifier = get_default_algorithms()["RS256"]
pk = verifier.from_jwk({
    "kty": "RSA",
    "n": "tHbYl75dwWTcdrRBODUipsQ7qFfF7uGHGnP0eYI33dk0OW3lG_qh09dyPHQUeEXlcHBoWf-K08ofpl0jhequ5vvvN92PU-wL0qYNMXk2FCtLneUM8FzDEyLoKG_mMsrU-qnwvlw83vqdp9FPa8Ja2ImPooma_amsr3oW7vYhFYhr4R7F5Ph9CgIO4Lu8zkl1ZzqRdlIRkpjW-IDVKZlPZ2alNJlTUiqeS3rOdNn8y5ez9EUOreUhfsS8m39FbrJvNQEsA0DHeuVnIG_eDmKZ928HCcJh2CNOL4gY2cD9qoWOYx4e3RHUaXQn_p6MEmjxql4vL6-K99oOQYDN6ZdDr7gjHiSen7D5PZQtzJohIZBEqTEU2yLh8U8vQPqP5OqCx87hwwEqoHc80SLY4qSQhJOf1CayuuZQsBie3Sp21SsGXLLr9jCNPogKGbmOmpWaspXRdpFr6ep_DUpi3-qFO4_xBUkKj_08GsBW9sDj8btyhI2Wygc7n8D_PyQy8cWOc4we8E2xQ8mJwIevVE0--HoIy-M8QxdBly5igZalbOUx-qoPMOOdi07JA5o13HbTjdJA68XCBB3mWsqaiufGbjLlHaZ-tRnL1VNWopDHwLkIQmIFkGtpkt9aivMiRsnNK3pzg420rfOqbeCeWEl3mXYM_9v0BezbQg2OKlbn9Xc",
    "e": "AQAB"
})
try:
    verifier.verify(b"some message", pk, b"invalid signature")
except InvalidSignature:
    pass  # We don't have a valid signature, so expect this to fail.
except InternalError as e:
    print('RS256 failed:')
    print(e)
    failures += 1

if failures == 0:
    print('success')

fips.cnf

config_diagnostics = 1
openssl_conf = openssl_init

.include /usr/local/ssl/fipsmodule.cnf

[openssl_init]
providers = provider_sect
alg_section = algorithm_sect

[provider_sect]
fips = fips_sect
base = base_sect

[base_sect]
activate = 1

[algorithm_sect]
default_properties = fips=yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions