jlim
jlim

Reputation: 1039

Python Cryptography Pass MD5 Digest with OpenSSL FIPS mode

I build this Dockerfile located in https://github.com/egibs/python-fips.git. I have successfully build the python 3.11 with fips mode. Everything seems to work and python doesn't allow me to import hashlib with MD5. But when I import crytopgraphy with the following code snippet, the MD5 digest works.

Python 3.11.9 (main, Dec 25 2024, 20:45:45) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from cryptography.hazmat.primitives import hashes
>>> digest = hashes.Hash(hashes.MD5())     
>>> digest.update(b"111")
>>> digest.finalize()
b'i\x8dQ\xa1\x9d\x8a\x12\x1c\xe5\x81I\x9d{p\x16h'

Is there something I need to tweak in the Dockerfile to make sure cryptography library must be FIPS compliant and fail any MD5 digest ?

Validation

a97ec8a76233:/fips# openssl md5 /dev/null
Error setting digest
20101885FFFF0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:373:Global default library context, Algorithm (MD5 : 102), Properties ()
20101885FFFF0000:error:03000086:digital envelope routines:evp_md_init_internal:initialization error:crypto/evp/digest.c:254:

a97ec8a76233:/fips# openssl sha1 /dev/null
SHA1(/dev/null)= da39a3ee5e6b4b0d3255bfef95601890afd80709

OpenSSL Info

openssl list -providers
Providers:
  base
    name: OpenSSL Base Provider
    version: 3.0.9
    status: active
  fips
    name: OpenSSL FIPS Provider
    version: 3.0.9
    status: active

----

OpenSSL 3.0.9 30 May 2023 (Library: OpenSSL 3.0.9 30 May 2023)
built on: Wed Dec 25 20:34:22 2024 UTC
platform: linux-aarch64
options:  bn(64,64)
compiler: gcc -fPIC -pthread -Wa,--noexecstack -Wall -O3 -DOPENSSL_USE_NODELETE -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG
OPENSSLDIR: "/usr/local/ssl"
ENGINESDIR: "/usr/local/ssl/lib/engines-3"
MODULESDIR: "/usr/local/ssl/lib/ossl-modules"
Seeding source: os-specific
CPUINFO: OPENSSL_armcap=0xfd

----

openssl list -digest-commands
sha1              sha224            sha256            sha3-224          
sha3-256          sha3-384          sha3-512          sha384            
sha512            sha512-224        sha512-256        shake128          
shake256   

Dockerfile


ARG PYTHON_VERSION="3.11.9"

RUN apk update \
    && apk add --no-cache \
    patch \
    wget

WORKDIR /fips

COPY fips_3.11.patch fips.patch
RUN wget https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz \
    && tar -xzf Python-${PYTHON_VERSION}.tgz \
    && cd Python-${PYTHON_VERSION} \
    && patch -p1 < ../fips.patch \
    && cd -

# Main stage
FROM --platform=$TARGETPLATFORM cgr.dev/chainguard/wolfi-base@sha256:3eff851ab805966c768d2a8107545a96218426cee1e5cc805865505edbe6ce92 as build

USER root

ARG OPENSSL_BASE_FIPS_VERSION="3.0.9"
ARG OPENSSL_FIPS_VERSION="openssl-${OPENSSL_BASE_FIPS_VERSION}"
ARG OPENSSL_VERSION="openssl-${OPENSSL_BASE_VERSION}"
ARG PYTHON_VERSION="3.11.9"
ARG TARGETPLATFORM

ENV OPENSSL_FIPS=1

WORKDIR /fips

COPY --from=patch /fips/Python-${PYTHON_VERSION} ./Python-${PYTHON_VERSION}

# Install dependencies
RUN apk update \
    && apk add --no-cache \
    autoconf \
    automake \
    bzip2-dev \
    diffutils \
    gcc \
    glibc \
    glibc-dev \
    ld-linux \
    libffi \
    libffi-dev \
    libjpeg-dev \
    libssh-dev \
    libtool \
    libxml2-dev \
    libxslt-dev \
    make \
    perl \
    wget \
    zlib-dev

# Download archives
RUN wget https://www.openssl.org/source/old/3.0/${OPENSSL_FIPS_VERSION}.tar.gz

# Extract archives
RUN tar -xzf ${OPENSSL_FIPS_VERSION}.tar.gz

# Create directories not present in Wolfi
# and other necessary directories
RUN mkdir -p /etc/ld.so.conf.d \
    && mkdir -p /opt/python-fips \
    && mkdir -p /usr/local/bin \
    && mkdir -p /usr/local/ssl

# Allow for libraries to be sourced from /etc/ld.so.conf.d
RUN echo "include /etc/ld.so.conf.d/*.conf"  > /etc/ld.so.conf

# Build and Install OpenSSL
RUN cd ${OPENSSL_FIPS_VERSION} \
    && ./Configure enable-fips shared --prefix=/usr/local/ssl --openssldir=/usr/local/ssl \
    && make depend \
    && make \
    && make install \
    && echo "/usr/local/ssl/lib" > /etc/ld.so.conf.d/${OPENSSL_FIPS_VERSION}.conf \
    && ln -s -f /usr/local/ssl/bin/openssl /usr/bin/openssl \
    && ln -s -f /usr/local/ssl/bin/openssl /usr/local/bin/openssl \
    && ldconfig -v \
    && cd -

# Build and Install Python
RUN cd Python-${PYTHON_VERSION} \
    && LDFLAGS="-L/usr/local/lib/ -L/usr/local/lib64/ -Wl,-rpath=/opt/python-fips/lib" LD_LIBRARY_PATH="/usr/local/lib/:/usr/local/lib64/" CPPFLAGS="-I/usr/local/include -I/usr/local/ssl/include" ./configure --enable-shared --enable-optimizations --with-builtin-hashlib-hashes=sha1,sha256,sha512,sha3 --prefix=/opt/python-fips --with-openssl=/usr/local/ssl --with-openssl-rpath=/usr/local/ssl/lib --with-ssl-default-suites=openssl \
    && make \
    && make install \
    && echo "/opt/python-fips/lib" > /etc/ld.so.conf.d/python.conf \
    && ldconfig -v \
    && ln -s -f /opt/python-fips/bin/python3.11 /usr/bin/python3 \
    && ln -s -f /opt/python-fips/bin/python3.11 /usr/local/bin/python3 \
    && cd -

# Install Python dependencies
RUN python3 -m pip install wheel \
    && python3 -m pip install --upgrade pip setuptools \
    && CRYPTOGRAPHY_DONT_BUILD_RUST=1 CFLAGS="-I/usr/local/ssl/include" LDFLAGS="-L/usr/local/ssl/lib" python3 -m pip install cryptography

# Overwrite the default OpenSSL configuration
COPY openssl3.cnf /usr/local/ssl/openssl.cnf

RUN addgroup python && adduser -D -G python python \
    && install -d -o python -g python /home/python

USER python

Upvotes: 1

Views: 57

Answers (1)

jlim
jlim

Reputation: 1039

It turns out I need to specify where the openssl.cnf is located. Once I perform the following:-

$ export OPENSSL_CONF=<ssl dir location>
$ pip install cryptography
$ python3
Python 3.11.11 (tags/v3.11.11-0-gd03b868-dirty:d03b868, Dec  4 2024, 19:55:37) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from cryptography.hazmat.primitives import hashes
>>> digest = hashes.Hash(hashes.MD5())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
cryptography.exceptions.InternalError: 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:355:Global default library context, Algorithm (MD5 : 100), Properties (), error:03000086:digital envelope routines:evp_md_init_internal:initialization error:crypto/evp/digest.c:271:)

Upvotes: 0

Related Questions