FIPS deployment profile for SFTP exchanges
This profile is the settings that hold an SFTP exchange's SSH negotiation to FIPS-approved algorithms, what each setting excludes, what happens when the partner's server offers nothing approved, and the one part of the handshake an operator cannot constrain. It is not a validated-module claim; what Alcove claims about module validation is in COMPLIANCE.md.
Scope: the command-line application
SFTP exchanges are conducted by the CLI, so this profile applies to an alcove.yaml-configured CLI run. The web application has no equivalent setting. The console's SFTP connection takes a fixed set of server fields and no transport-tuning block (SERVER_JOB_API.md), so apply the profile to the configuration you graduate to from the console (CONSOLE.md).
What you can constrain, and what you cannot
The SSH handshake negotiates four things. Three are yours to set:
| Negotiated | Constrained by | Operator-settable |
|---|---|---|
| Key exchange | algorithms.kex | Yes |
| Encryption | algorithms.cipher | Yes |
| Message authentication | algorithms.hmac | Yes |
| Host-key type | algorithms.serverHostKey | No -- see Host-key types cannot be constrained |
The three settable lists are sub-keys of the algorithms object inside connection.provider_options, which documents the passthrough: which sub-categories survive its filter, what a partially-surviving or empty list does, and the warnings each emits. This page gives the values.
The settings
Copy this into the connection block of your alcove.yaml:
connection:
channel: sftp
# ... your server, path, and options ...
provider_options:
algorithms:
kex:
- ecdh-sha2-nistp256
- ecdh-sha2-nistp384
- ecdh-sha2-nistp521
- diffie-hellman-group14-sha256
- diffie-hellman-group16-sha512
cipher:
- [email protected]
- [email protected]
- aes256-ctr
- aes192-ctr
- aes128-ctr
hmac:
- [email protected]
- [email protected]
- hmac-sha2-256
- hmac-sha2-512Order is preference order: the negotiation uses the first entry the partner's server also accepts. Drop entries from the end to narrow further; a shorter list reaches fewer partners.
The reference the selection follows
The selection is the approved security functions of FIPS 140-3 Annex A, which incorporates NIST SP 800-140C, the CMVP-approved security functions list. The underlying publication for each category:
- Key exchange -- ECC and finite-field Diffie-Hellman key agreement per SP 800-56A Rev. 3; the NIST curves per FIPS 186-5 / SP 800-186, and the
group14/group16MODP groups per that publication's approved safe-prime groups. - Encryption -- AES (FIPS 197) in GCM (SP 800-38D) and CTR (SP 800-38A) modes.
- Message authentication -- HMAC (FIPS 198-1) over SHA-2 (FIPS 180-4).
Approval at the algorithm-standard level is not module-certificate approval; COMPLIANCE.md keeps the two apart.
What each list excludes
kexexcludescurve25519-sha256and its@libssh.orgspelling: X25519 is not an approved key-agreement algorithm on any OpenSSL Project certificate (fips-provider-surface.md), and certificate 5438, for the Amazon Linux 2023 module the variant image contains, names it in no table, approved or non-approved (CONTAINER_IMAGES.md). It also excludes every SHA-1 key exchange (diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1) and the group-exchange family generally, whose modulus the server chooses at handshake time rather than being one of the approved safe primes.cipherexcludes[email protected](not an approved algorithm),3des-cbc, and the AES-CBC suites. CBC is an approved mode; it is excluded for the SSH-specific plaintext-recovery weakness, not on FIPS grounds, so adding it back for a CBC-only server is a security tradeoff, not a compliance one.hmacexcludes everyhmac-sha1spelling and theumac-*family, which is not FIPS-approved. The[email protected]entries are the same HMAC construction in encrypt-then-MAC order and are listed first.
The hmac list applies only to the non-AEAD fallback
When the negotiation selects an AES-GCM cipher, the MAC list is not used: those suites provide their own integrity, and the handshake records an empty MAC in both directions. The hmac list governs a run that falls back to a CTR cipher. Leaving it unset lets a CTR fallback negotiate hmac-sha1.
A misspelled algorithm name fails the dial
An algorithm name the SSH library does not know is refused when the connection is dialed, with Unsupported algorithm: <name>, rather than dropped from the list. A typo in the block above fails the run rather than widening the offer.
Host-key types cannot be constrained
serverHostKey is dropped from the algorithms passthrough: which host-key types a client accepts is a host-key-trust decision, and Alcove does not let a configuration file weaken it (EXCHANGE_REFERENCE.md). Setting it produces a warning naming the dropped sub-key and changes nothing.
ssh-rsa, which signs with SHA-1, stays in the host-key offer and cannot be excluded from negotiation. On an ordinary runtime a dial made with the profile above offers, in order, ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, rsa-sha2-512, rsa-sha2-256, ssh-rsa, and the server picks from that list; from inside a FIPS-configured image the same dial offers that list without ssh-ed25519 (The default offer measured inside the image). A server that offers only ssh-rsa is negotiated with, and no client-side setting refuses it.
The control available instead is host-key fingerprint pinning. Pin the server's key by its OpenSSH SHA-256 fingerprint, as connection.server.host_key_fingerprint or --server-host-key-fingerprint (CLI.md). With no pin, a non-interactive run does not connect.
- Pinning does bind the exchange to one server key. A different key, including a substituted one, fails the connection before authentication.
- Pinning does not change the signature algorithm. If the negotiation lands on
ssh-rsa, the host-key signature over that handshake is an RSA SHA-1 signature, pinned key or not.
Closing that gap is a server-side change: see What to ask of the partner's server.
When nothing approved overlaps
The run fails at negotiation. It never proceeds on an unapproved algorithm. A partner's server with nothing approved to offer produces a failed exchange, not a downgraded one.
Against a server restricted to a non-approved set in any one of the three categories, the failure arrives before authentication and before any SFTP session exists, so no exchange file is read or written. The message names the category:
| The partner's server accepts only | The run fails with |
|---|---|
curve25519-sha256 | Handshake failed: no matching key exchange algorithm |
[email protected] | Handshake failed: no matching C->S cipher |
hmac-sha1 | Handshake failed: no matching C->S MAC |
The remedy is on the partner's server: enable an approved algorithm in that category (What to ask of the partner's server). Widening your own list to reach them removes the control this profile provides.
Distinguishing this from a runtime that cannot perform the algorithm
Two failures both end a run at the handshake, and their remedies are opposites:
- The partner offers nothing approved -- the messages above, naming a category (
key exchange algorithm,C->S cipher,C->S MAC). The fix is on the partner's server. - Your own runtime cannot perform what was asked -- the error names the missing primitive (today, X25519) rather than a category, and points at the server's administrator or at running from a different host. Alcove withholds from its offer any algorithm the running process cannot perform, so this failure means the server accepts nothing outside that withheld set. The mechanics, including what happens when part or all of a
kexlist is unavailable, are in EXCHANGE_REFERENCE.md.
None of the profile's entries rests on X25519, so the profile itself does not cause the second case.
Running in a FIPS-configured image
In a container configured with an OpenSSL FIPS provider, the provider build decides which SSH algorithms are available at all: the SSH stack reaches node:crypto, which dispatches through the configured provider. Which images include a provider is in RELEASES.md. From the provider measurements in fips-provider-surface.md:
- The profile's algorithms survive every measured provider build. ECDH and finite-field DH are in the key-exchange listing of every build measured (3.0.8, 3.0.9, 3.0.21, and 3.5.7), as are the AES modes and HMAC-SHA-2 the cipher and hmac lists name.
curve25519-sha256is unavailable under a 3.5.x provider, and in the one FIPS image measured end to end. X25519 keypair generation fails under a from-source 3.5.7 provider, while the from-source 3.0.8, 3.0.9, and 3.0.21 builds serve X25519. In the shipped FIPS image, which pairs the 3.5.7 OpenSSL Node links with the certified Amazon Linux provider module, X25519 keypair generation and derivation fail (fips-variant-image.md, reading), andopenssl listin the same image reads the module to contain no X25519 at all. The 3.0.x/3.5.x split is unverified for a mixed base-and-module pairing; confirm X25519 in your own image before depending on it.- MD5 is unavailable under a fips-only configuration. Alcove pins and displays a host key by its SHA-256 fingerprint, so the pin is unaffected, but tooling that produces an MD5 fingerprint (
ssh-keygen -E md5, and some server documentation) cannot be used inside such an image to derive the value you pin.
The default offer measured inside the image
On an Amazon Linux 2023 host with kernel FIPS mode enabled (/proc/sys/crypto/fips_enabled reads 1), the FIPS variant image -- containing the AL2023 FIPS provider module it pinned when the capture was taken, 3.0.8-d694bfa693b76001, under a fips-only OpenSSL configuration -- was dialed at a listener that answers the SSH version banner, decodes the client's first packet (SSH_MSG_KEXINIT), and drops the connection. No key exchange completed. The dial had no algorithms block, so what it offered is the default:
| Negotiated | Offered by default from inside the FIPS image |
|---|---|
| Key exchange | ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group14-sha256, diffie-hellman-group15-sha512, diffie-hellman-group16-sha512, diffie-hellman-group17-sha512, diffie-hellman-group18-sha512 |
| Encryption | [email protected], [email protected], aes128-ctr, aes192-ctr, aes256-ctr |
| Message authentication | [email protected], [email protected], [email protected], hmac-sha2-256, hmac-sha2-512, hmac-sha1 |
| Host-key type | ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, rsa-sha2-512, rsa-sha2-256, ssh-rsa |
The key-exchange field also included ext-info-c and [email protected], which signal protocol extensions rather than naming algorithms.
Four names an ordinary runtime offers are absent:
curve25519-sha256and its@libssh.orgspelling, from the key exchange. X25519 cannot be performed in that image, and Alcove withholds the algorithms built on it (Distinguishing this from a runtime that cannot perform the algorithm).[email protected], from the ciphers.ssh-ed25519, from the host-key offer, which otherwise matches the list under Host-key types cannot be constrained,ssh-rsaincluded.
What follows for an SFTP deployment:
- A FIPS-configured runtime narrows the offer by itself. The ciphers it offers are approved algorithms with nothing set to make them so, and so is every key exchange it offers except
diffie-hellman-group-exchange-sha256, whose modulus the server chooses. The profile'skexlist removes that one and is narrower again. - It does not narrow message authentication or group exchange.
[email protected]andhmac-sha1are offered by default, as isdiffie-hellman-group-exchange-sha256. Without the settings above, a partner's server that accepts onlyhmac-sha1still negotiates it on a CTR fallback, and one that accepts only group exchange still negotiates a modulus it chose. A FIPS-configured image is not a substitute for the settings, and on a host not in FIPS mode the settings are the whole of the control. - The host-key type is beyond the reach of either.
ssh-rsastays in the offer; excluding it is the partner server's to do.
The measurement is one image on one host, and it is what the client offers, not a completed negotiation. The negotiation behavior described elsewhere on this page is verified against a real SSH server on an ordinary runtime. Confirm the offer in your own image when its base image or provider build differs from the one above.
What to ask of the partner's server
Alcove enforces none of the following; it constrains only what this side offers and accepts. Agree on these server-side settings with your partner out of band, alongside the exchange directory and account access (DEPLOYMENT.md):
- Restrict
KexAlgorithms,Ciphers, andMACsto the same approved sets. A server restricted this way and a client running this profile fail closed toward each other. - Restrict
HostKeyAlgorithmsto excludessh-rsa, and offer anecdsa-sha2-nistp256orrsa-sha2-256/rsa-sha2-512host key. This is the only place the SHA-1 host-key signature can be closed. - Publish the host key's SHA-256 fingerprint out of band so the pin can be set before the first run.
A partner who applies none of this is still reachable: the exchange either meets an approved algorithm in each category or does not run.
See also
- COMPLIANCE.md - what Alcove does and does not claim about FIPS 140 validation
- EXCHANGE_REFERENCE.md - the
algorithmspassthrough, its filter, and its warnings - CLI.md - host-key pinning, first-use trust, and rotation
- DEPLOYMENT.md - operating the SFTP server the exchange runs over
- fips-provider-surface.md - the provider measurements this profile's runtime guidance rests on