Control: reassign -1 openssl

On Wed, Jun 17, 2026 at 09:00:09AM -0400, Michael Hamill wrote:
> Package: apt
> Version: 3.0.3
> Severity: important
> 
> Dear Maintainer,
> 
> With OpenSSL configured in FIPS-only mode (only the "base" and "fips"
> providers
> active; the "default" provider disabled), "apt-get update"/"install"
> against an
> HTTPS repository intermittently fails with:
> 
>   Err:N https://...repo...
>     OpenSSL error: error:0308010C:digital envelope routines::unsupported
>     Error reading from server - read (5: Input/output error)
> 
> Root cause
> ----------
> During the TLS handshake, libssl performs an implicit EVP_MD_fetch() for the
> legacy MD5 / MD5-SHA1 digests (used for pre-TLS-1.2 handshake signing and
> the
> TLS 1.0/1.1 PRF). Under a FIPS-only provider configuration those digests are
> unavailable (they exist only in the default provider), so the fetch fails
> and
> leaves "error:0308010C ... unsupported" on the thread's OpenSSL error queue.
> 
> This is benign: the handshake completes fine. "openssl s_client" to the same
> host under the identical FIPS config connects successfully with the very
> same
> failed MD5/MD5-SHA1 fetches (verifiable with an LD_PRELOAD trace of
> EVP_MD_fetch).
> 
> The actual failure is that apt does not clear the OpenSSL error queue
> before its
> TLS I/O. In methods/connect.cc, TlsFd::Read() and TlsFd::Write() call
> SSL_read()/SSL_write() and then HandleError() -> SSL_get_error() WITHOUT a
> preceding ERR_clear_error(). When SSL_read() later returns <= 0 for a benign
> reason, SSL_get_error() consults the non-empty error queue, returns
> SSL_ERROR_SSL, and apt reports the stale MD5 error as a fatal read failure
> (errno = EIO -> "Error reading from server").
> 
> This violates the documented precondition in SSL_get_error(3): "The current
> thread's error queue must be empty before the TLS/SSL I/O operation is
> attempted, [...] as the SSL_get_error() function uses the error queue
> [...]."
> 
> PostgreSQL fixed the identical class of bug (stale FIPS-mode error-queue
> entry
> misreported later) by calling ERR_clear_error() "on the way in"; libpq
> already
> does this around its OpenSSL I/O.
> 
> This did not occur before Debian 13 / apt 3.0: apt 2.6 (bookworm) used
> GnuTLS
> for its TLS transport, which does not touch OpenSSL's providers or error
> queue.
> 
> Reproduction (Debian 13)
> ------------------------------
> Minimal, self-contained Dockerfile. The build itself fails at the final RUN
> (installing Docker from an HTTPS repo) -- "docker build ." is the whole
> repro:
> 
>     FROM debian:13-slim
>     SHELL ["/bin/bash", "-o", "pipefail", "-c"]
> 
>     # FIPS-only OpenSSL: install the FIPS provider, then activate base +
> fips and
>     # disable the default provider.
>     RUN apt-get update --yes \
>      && apt-get install --yes --no-install-recommends \
>             ca-certificates openssl openssl-provider-fips \
>      && MODULES_DIR="$(openssl version -m | cut -d'"' -f2)" \
>      && openssl fipsinstall -out /etc/ssl/fipsmodule.cnf -module
> "${MODULES_DIR}/fips.so"
>     RUN sed -i 's|^#\s*\.include\s\+fipsmodule.cnf|.include
> /etc/ssl/fipsmodule.cnf|' /etc/ssl/openssl.cnf \
>      && sed -i 's/^default\s*=\s*default_sect/# default = default_sect/'
> /etc/ssl/openssl.cnf \
>      && sed -i 's/^#\s*fips\s*=\s*fips_sect/fips = fips_sect\nbase =
> base_sect\n\n[base_sect]\nactivate = 1/' /etc/ssl/openssl.cnf
>     # ("openssl list -providers" now shows only base + fips.)
> 
>     # Install Docker from its official HTTPS apt repo (any HTTPS repo
> triggers it;
>     # this is just a convenient public one). This RUN fails:
>     #   OpenSSL error: error:0308010C ... Error reading from server
>     #   E: Package 'docker-ce' has no installation candidate
>     RUN apt-get install --no-install-recommends -y ca-certificates curl
> gnupg \
>      && install -m 0755 -d /etc/apt/keyrings \
>      && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg
> --dearmor -o /etc/apt/keyrings/docker.gpg \
>      && echo "deb [signed-by=/etc/apt/keyrings/docker.gpg]
> https://download.docker.com/linux/debian trixie stable" \
>           > /etc/apt/sources.list.d/docker.list \
>      && apt-get update \
>      && apt-get install --no-install-recommends -y docker-ce docker-ce-cli
> containerd.io
> 
> Build it:
> 
>     docker build .
> 
> The build fails at the final RUN with the error:0308010C / "Error reading
> from
> server" message above. (The underlying trigger is a read returning <= 0
> while
> the stale error is queued, so in principle a fluke pass is possible; in
> practice
> fetching the Docker repo over HTTPS this way fails on essentially every
> build,
> matching what we see in CI. If a build does pass, rebuild with --no-cache.)
> 
> For contrast, the connection itself is fine and the failed MD5 fetch is
> benign --
> both of these succeed under the identical FIPS config:
> 
>     # same handshake, succeeds, proving MD5 is not actually needed:
>     openssl s_client -connect download.docker.com:443 -servername
> download.docker.com </dev/null
>     # and apt works if the default provider is made available:
>     OPENSSL_CONF=/dev/null apt-get update     # (with the docker.list
> source above)
> 
> System information
> ------------------
> Debian release: 13 (trixie), amd64
> 
> Versions of relevant packages:
>   apt          3.0.3
>   libssl3t64   3.5.6-1~deb13u2   (OpenSSL; apt's TLS backend in 3.0)
>   openssl      3.5.6-1~deb13u2
>   libc6        2.41-12+deb13u3
> 
> Reproduced in a stock debian:13-slim container (see Dockerfile above).
> 
> Suggested fix
> -------------
> Clear the OpenSSL error queue immediately before each
> SSL_read()/SSL_write() in
> methods/connect.cc, mirroring libpq:
> 
>     ssize_t Read(void *buf, size_t count) override {
>        assert(ssl);
>     +  ERR_clear_error();
>        return HandleError(SSL_read(ssl, buf, count));
>     }
>     ssize_t Write(void *buf, size_t count) override {
>        assert(ssl);
>     +  ERR_clear_error();
>        return HandleError(SSL_write(ssl, buf, count));
>     }
> 
> This makes apt robust to any benign leftover OpenSSL error, not just the
> FIPS/MD5 case.

Thanks for your bug report.

This seems to be a bug in OpenSSL, and the proposed workaround is
wholly inappropriate. This also points out there is _another_ bug
somewhere, as we _should_ have raised this error _before_ we enter
the Read/Write functions.

You'll find you often need to patch OpenSSL to use it in a FIPS
setting, and relying on the packaged version is insufficient.

Thanks!

-- 
debian developer - deb.li/jak | jak-linux.org - free software dev
ubuntu core developer                              i speak de, en

Reply via email to