Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions misc/images/openssh-static/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,28 @@

FROM ubuntu:noble-20260210.1 AS builder

# Non-FIPS builds use a regular AWS-LC release tag.
ARG AWS_LC_VERSION=v1.54.0
# FIPS builds MUST use a tag from a FIPS branch, not a regular release tag.
# Passing -DFIPS=1 against an arbitrary release produces a "FIPS-style" module
# (self-tests + integrity check) that is NOT the NIST-validated module, so it
# provides no actual FIPS 140-3 compliance.
#
# AWS-LC-FIPS-2.0.x -> NIST cert #4816 (static), but does NOT include EdDSA.
# AWS-LC-FIPS-3.x -> adds EdDSA/Ed25519 to the module boundary.
#
# We pin the 3.x line because Materialize's SSH connection keys are Ed25519
# (see mz-ssh-util keys.rs), so Ed25519 must be inside the validated boundary.
# NOTE: AWS-LC-FIPS 3.x is currently "in process" with NIST CMVP (the static
# module is in Comment Resolution), not yet certified. This image is therefore
# NOT production-FIPS-ready until that certificate is awarded. Track status:
# https://csrc.nist.gov/Projects/cryptographic-module-validation-program/modules-in-process/modules-in-process-list
#
# Ed25519 also only executes inside the module with OpenSSH >= 10.0, which
# routes ed25519 through libcrypto instead of OpenSSH's bundled implementation.
ARG AWS_LC_FIPS=0
ARG OPENSSH_VERSION=V_9_9_P2
ARG AWS_LC_FIPS_VERSION=AWS-LC-FIPS-3.3.0
ARG OPENSSH_VERSION=V_10_3_P1

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
autoconf \
Expand All @@ -47,7 +66,8 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-ins
# Build AWS-LC as a static library.
# When AWS_LC_FIPS=1, enables FIPS mode (requires Go for the delocator).
WORKDIR /build/aws-lc
RUN git clone --depth 1 --branch ${AWS_LC_VERSION} https://github.com/aws/aws-lc.git . \
RUN AWS_LC_REF="$([ "$AWS_LC_FIPS" = "1" ] && echo "$AWS_LC_FIPS_VERSION" || echo "$AWS_LC_VERSION")" \
&& git clone --depth 1 --branch "$AWS_LC_REF" https://github.com/aws/aws-lc.git . \
&& cmake -GNinja -B build \
$([ "$AWS_LC_FIPS" = "1" ] && echo "-DFIPS=1") \
-DBUILD_SHARED_LIBS=0 \
Expand All @@ -63,21 +83,22 @@ RUN git clone --depth 1 --branch ${AWS_LC_VERSION} https://github.com/aws/aws-lc
WORKDIR /build/openssh
RUN git clone --depth 1 --branch ${OPENSSH_VERSION} https://github.com/openssh/openssh-portable.git . \
&& autoreconf \
# OpenSSH >= 10 stubs BN_set_flags() for AWS-LC, so no -DBN_FLG_CONSTTIME
# shim is needed. Use a plain configure + make: a `make CFLAGS=...` override
# would clobber configure's hardening flags. --disable-pkcs11 avoids link
# errors from ssh-pkcs11.c referencing RSA/EC APIs that AWS-LC omits.
&& ./configure \
--with-ssl-dir=/opt/aws-lc \
--with-zlib \
--with-ldflags=-static \
--without-pam \
--without-libedit \
--disable-pkcs11 \
# AWS-LC does not define the legacy OpenSSL BN_FLG_CONSTTIME flag.
# Setting it to 0 satisfies #ifdef checks in OpenSSH source code.
# This is safe: AWS-LC handles constant-time bignum operations
# internally and does not rely on this flag.
# --disable-pkcs11 avoids link errors from ssh-pkcs11.c calling
# RSA_meth_dup/EC_KEY_METHOD_get_sign which AWS-LC does not provide.
&& make -j"$(nproc)" ssh CFLAGS="-DBN_FLG_CONSTTIME=0" \
&& strip ssh
&& make -j"$(nproc)" ssh \
# Stripping removes the symbols the FIPS integrity self-test needs to locate
# the module boundary, so a stripped FIPS binary fails its power-on
# self-test at the first crypto operation. Only strip non-FIPS builds.
&& if [ "$AWS_LC_FIPS" != "1" ]; then strip ssh; fi

# Verify the binary is not dynamically linked and is functional.
RUN ! ldd ssh 2>/dev/null \
Expand Down
9 changes: 8 additions & 1 deletion src/ssh-util/src/tunnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,20 @@ fn fips_mode_enabled() -> bool {
/// approved choices only. Returns the path to the config file.
fn write_fips_ssh_config(dir: &std::path::Path) -> Result<std::path::PathBuf, anyhow::Error> {
let config_path = dir.join("ssh_config");
// EdDSA/Ed25519 is FIPS-approved under FIPS 186-5 and is in the AWS-LC-FIPS
// 3.x module boundary, so ssh-ed25519 is permitted for both the bastion host
// key (HostKeyAlgorithms) and our own client key (PubkeyAcceptedAlgorithms).
// Materialize's SSH connection keys are Ed25519 (see keys.rs), so omitting
// ssh-ed25519 from PubkeyAcceptedAlgorithms would break authentication; both
// lists must include it for parity. Requires the openssh-static binary built
// against AWS-LC-FIPS 3.x with OpenSSH >= 10.0 (ed25519 via libcrypto).
let config_contents = "\
# FIPS 140-3 compliant SSH configuration.
# Only NIST-approved algorithms are permitted.
Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
KexAlgorithms ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512
HostKeyAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-256,rsa-sha2-512
HostKeyAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-256,rsa-sha2-512,ssh-ed25519
PubkeyAcceptedAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-256,rsa-sha2-512,ssh-ed25519
";
fs::write(&config_path, config_contents)?;
Expand Down
Loading