Skip to content

[rest]: Disable TLS session tickets to avoid AES-CTR panic under FIPS#163

Open
Griffin-micas wants to merge 1 commit into
sonic-net:masterfrom
Griffin-micas:bugfix-fips-tls-session-ticket
Open

[rest]: Disable TLS session tickets to avoid AES-CTR panic under FIPS#163
Griffin-micas wants to merge 1 commit into
sonic-net:masterfrom
Griffin-micas:bugfix-fips-tls-session-ticket

Conversation

@Griffin-micas

Copy link
Copy Markdown

Under sonic_fips=1 the symcrypt OpenSSL provider has no AES-CTR, which crypto/tls uses only for session tickets; the golang- fips backend panics on every TLS handshake, so rest_server resets all connections. Disabling session tickets removes the only AES- CTR call path and restores RESTCONF.

Why I did it

On a FIPS image (sonic_fips=1), every RESTCONF request fails: the TLS handshake completes but the server resets the connection before any HTTP response, so curl reports SSL_read: Connection reset by peer. It reproduces for 100% of requests, any method/path, with or without credentials, even from localhost.

Root cause is a panic in crypto/tls:

rest-server http: panic serving <peer>: crypto/cipher: unsupported cipher: AES-128
  vendor/github.com/golang-fips/openssl/v2.newCipherCtx      cipher.go
  vendor/github.com/golang-fips/openssl/v2.(*evpCipher).newCTR
  crypto/cipher.NewCTR                                       ctr.go:49
  crypto/tls.(*Config).encryptTicket                         ticket.go
  crypto/tls.(*Conn).sendSessionTicket                       handshake_server_tls13.go
  net/http.(*conn).serve

crypto/tls uses AES-CTR in exactly one place — encrypting TLS session tickets (ticket.go). The server sends a NewSessionTicket at the end of every TLS 1.3 handshake, so every connection hits it. Under FIPS the golang-fips OpenSSL backend fetches ciphers with an implicit fips=yes property, and the symcrypt provider does not implement AES-CTR (it has ECB/CBC/CFB/GCM/CCM/XTS only — upstream microsoft/SymCrypt-OpenSSL has no p_scossl_aes_ctr.c). The fetch returns NULL and newCipherCtx panics. net/http recovers the panic and drops the connection, so rest_server never exits — it looks healthy (high uptime, no supervisord restart) yet serves nothing.

AES-CTR is a FIPS-approved mode (NIST SP 800-38A) and SymCrypt implements it internally; only the OpenSSL provider shim lacks it. The proper long-term fix is to add AES-CTR to SCOSSL — tracked in issue #. This PR is the mitigation on the rest_server side.

How I did it

crypto/tls only needs AES-CTR to encrypt/decrypt session tickets, and shouldSendSessionTickets() / checkForResumption() both short-circuit on Config.SessionTicketsDisabled. Setting it removes the only code path that steps outside the algorithms symcrypt provides.

rest/main/main.go:

        tlsConfig := tls.Config{
                ClientAuth:               getTLSClientAuthType(),
                Certificates:             prepareServerCertificate(),
                ClientCAs:                prepareCACertificates(),
                MinVersion:               tls.VersionTLS12,
                PreferServerCipherSuites: true,
                SessionTicketsDisabled:   true, // FIPS: symcrypt has no AES-CTR (used only for session tickets)
        }

The only functional effect is loss of TLS session resumption. For a request/response REST/HTTP2 server this is negligible, and disabling session tickets is itself a common hardening step (ticket keys are a forward-secrecy weak point), so it does not weaken security. Applied unconditionally to keep the code simple; it is a no-op-cost change on non-FIPS images.

How to verify it

On a sonic_fips=1 image (grep sonic_fips=1 /proc/cmdline):

Before:

curl -k --noproxy '*' -u admin:<pw> https://<dut>/restconf/data/ietf-yang-library:modules-state
# curl: (56) OpenSSL SSL_read: Connection reset by peer
sudo grep 'unsupported cipher' /var/log/syslog     # one panic per connection

After: the request returns a normal RESTCONF response (200/401/404) and there are no new unsupported cipher panics in syslog.

Confirming the underlying gap (symcrypt has no AES-CTR), in the mgmt-framework container:

openssl list -cipher-algorithms | grep -i symcrypt | grep -ci ctr   # 0

In-process reproduction of the FIPS fetch (fails only for CTR; CBC/GCM/EC-P256/X25519 all succeed):

printf 'openssl_conf=oi\n[oi]\nproviders=ps\nalg_section=as\n[as]\ndefault_properties=fips=yes\n[ps]\ndefault=ds\nsymcryptprovider=ss\n[ds]\nactivate=1\n[ss]\nactivate=1\n' > /tmp/fp.cnf
OPENSSL_CONF=/tmp/fp.cnf openssl speed -evp AES-128-CTR
# error:0308010C:...:inner_evp_generic_fetch:unsupported: Algorithm (AES-128-CTR : 128)

Under sonic_fips=1 the symcrypt OpenSSL provider has no AES-CTR, which crypto/tls uses only for session tickets; the golang-
fips backend panics on every TLS handshake, so rest_server resets all connections. Disabling session tickets removes the only AES-
CTR call path and restores RESTCONF.

Signed-off-by: Griffin Gao <griffin@micasnetworks.com>
@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@mssonicbld

Copy link
Copy Markdown

Hi, there are workflow run(s) waiting for approval, you may be first-time contributor. I will notify maintainers to help approve once PR is approved. Thanks!

---Powered by SONiC BuildBot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants