Wszystkie badania

Czy FIPS 140-3 wyłącza postkwantowy TLS? Cicho obniża poziom zabezpieczeń

Tabela prawdy TLS dla FIPS-140-3: Go usuwa ochronę postkwantową, OpenSSL zachowuje niezatwierdzoną hybrydę.

Krótka odpowiedź na pytanie „czy FIPS wyłącza postkwantowy TLS” brzmi: nie zapewnia on zgodnego z normami postkwantowego TLS i może go po cichu wyłączyć. W naszym własnym laboratorium, bezpośrednio w ruchu sieciowym, dwa główne stosy zachowały się przeciwstawnie po przełączeniu w tryb FIPS, i żaden z nich domyślnie nie oferował zatwierdzonej przez FIPS grupy postkwantowej. Go 1.24, pod GODEBUG=fips140=on oraz =only, usunął wszystkie grupy postkwantowe z komunikatu ClientHello i po cichu wynegocjował klasyczną grupę P-256. W efekcie połączenie, które „zakończyło się sukcesem”, nie zawierało żadnej odpornej na komputery kwantowe wymiany kluczy. Dostawca FIPS w OpenSSL 3.5.2 zrobił coś odwrotnego: nadal oferował i negocjował X25519MLKEM768, hybrydę, której część X25519 nie jest zatwierdzona przez FIPS. Dostawca FIPS przepuszcza tę część przez wskaźnik zatwierdzenia zamiast ją zablokować. Postkwantowy TLS w FIPS 140-3 kończy więc w jednym z dwóch trybów awarii: włączenie FIPS powoduje wyłączenie ochrony postkwantowej (Go) albo pozostawienie niezgodnej grupy (OpenSSL). Ochrona przed zagrożeniem „zbieraj teraz, odszyfruj później” jest po cichu błędnie skonfigurowana dokładnie u tych regulowanych organizacji, które mają obowiązek stosowania FIPS.

Wersja wprost „FIPS włączone” to nie to samo co „postkwantowość włączona”. Go 1.24 w trybie FIPS całkowicie usuwa hybrydę postkwantową i bez żadnego błędu powraca do klasycznego P-256. OpenSSL 3.5 w trybie FIPS zachowuje X25519MLKEM768, którego klasyczna połowa nie znajduje się na liście zatwierdzonych przez FIPS. Żaden z nich nie oferuje SecP256r1MLKEM768, czyli hybrydy faktycznie zgodnej z FIPS, dopóki nie skonfigurujesz jej ręcznie.

Co odkryliśmy po włączeniu przełącznika FIPS

Zbudowaliśmy dwa klienty i dwa serwery, jedną parę w Go 1.24 i jedną w OpenSSL 3.5.2, a następnie obserwowaliśmy ich uścisk dłoni TLS 1.3 w ruchu sieciowym z wyłączonym i włączonym trybem FIPS. TLS 1.3 przesyła rozszerzenia supported_groups oraz key_share tekstem jawnym, więc ClientHello stanowi bezwzględne źródło prawdy. Można odczytać dokładnie, które grupy wymiany kluczy klient jest gotów zastosować i dla której przygotował udział klucza (key share). Bez zgadywania z dokumentacji biblioteki, wyłącznie bajty wysłane na gniazdo.

W przypadku Go 1.24 w trybie FIPS komunikat ClientHello został zredukowany wyłącznie do krzywych NIST. Lista supported_groups zawierała secp256r1, secp384r1, secp521r1 i nic więcej: żadnego czystego x25519, żadnego X25519MLKEM768, a co istotne, nawet zatwierdzonego przez FIPS SecP256r1MLKEM768. Wartością key_share było secp256r1, a wynegocjowaną grupą secp256r1, czyli klasyczny algorytm Diffiego-Hellmana na krzywych eliptycznych całkowicie bez elementu postkwantowego. Zachowanie było identyczne dla fips140=on oraz bardziej rygorystycznego fips140=only. Serwer Go w trybie FIPS, któremu partner nieobsługujący FIPS zaoferował grupę postkwantową, odpowiedział komunikatem HelloRetryRequest i wymusił obniżenie uścisku dłoni do secp256r1. W każdym przypadku uścisk dłoni zakończył się sukcesem. I to jest właśnie niebezpieczne: nic nie zgłosiło błędu, brak było ostrzeżeń, połączenie po prostu cicho straciło odporność kwantową.

W przypadku OpenSSL 3.5.2 dostawca FIPS zadziałał w drugą stronę. Komunikat ClientHello w trybie FIPS rozpoczynał się od X25519MLKEM768 i zawierał dla niego wartość key_share, a następnie grupy P-256, P-384, P-521 oraz grupy oparte na ciałach skończonych. W porównaniu z bazową konfiguracją bez FIPS, jedynymi grupami usuniętymi przez tryb FIPS były samodzielne krzywe x25519 oraz x448. Natomiast hybryda X25519MLKEM768 pozostała na szczycie listy z aktywnym key_share i wynegocjowała tę grupę z partnerem, który ją obsługiwał. Serwer OpenSSL również zaakceptował X25519MLKEM768. Zatem OpenSSL w trybie FIPS nadal oferuje grupę, której klasycznej połowy nie pozwala użyć samodzielnie.

Tabela prawdy w ruchu sieciowym

Oto każdy zmierzony przypadek wraz z grupami zaoferowanymi przez każdy stos, wynegocjowaną grupą oraz konsekwencjami. Wiersze dotyczące Go oraz OpenSSL mówią same za siebie: ten sam zamiar („zapewnienie zgodności TLS z FIPS”) dał przeciwstawne rezultaty.

Zachowanie TLS w FIPS-140-3 zmierzone w ruchu sieciowym, test laboratoryjny 2026-08-04
StosRolaTryb FIPSOferowane grupyWynegocjowana grupaWynik
Go 1.24Klientfips140=on / =onlysecp256r1, secp384r1, secp521r1secp256r1Tylko klasyczne, brak postkwantowości
Go 1.24Serwerfips onKrzywe NIST; wysyła HelloRetryRequestsecp256r1Wymusza obniżenie u partnera do kryptografii klasycznej
OpenSSL 3.5.2Klientfips onX25519MLKEM768, secp256r1/384/521, ffdhe2048/3072X25519MLKEM768Postkwantowe, ale hybryda niezatwierdzona
OpenSSL 3.5.2Serwerfips onAkceptuje X25519MLKEM768X25519MLKEM768Postkwantowe, ale hybryda niezatwierdzona
OpenSSL 3.5.2Oba, wymuszonefips onX25519MLKEM768 (wymuszone)X25519MLKEM768Uścisk dłoni powodzi się w FIPS
OpenSSL 3.5.2Oba, wymuszonefips onSecP256r1MLKEM768 (wymuszone)SecP256r1MLKEM768Zatwierdzona hybryda działa, ale nigdy domyślnie

Zestawienie ostatnich dwóch wierszy z powyższymi wskazuje jasne wnioski. Obie hybrydy postkwantowe przechodzą uścisk dłoni bez problemu z oboma partnerami w trybie FIPS, w tym w pełni zatwierdzona SecP256r1MLKEM768. Stosy są zdolne do poprawnego działania. Po prostu nie wybierają tego rozwiązania domyślnie: Go usuwa wszystkie z nich, a OpenSSL domyślnie wybiera opcję niezatwierdzoną.

Jak to zmierzyliśmy, aby sceptyk mógł zaufać wynikom

Zbiór danych jest nasz własny, zbudowany na naszych systemach i zawiera wyłącznie dane zagregowane. Uruchomiliśmy wszystko w przygotowanych przez nas kontenerach Docker na ulotnej maszynie wirtualnej w chmurze, komunikujących się przez loopback. Nie naruszono żadnego serwera podmiotu trzeciego, nie łączono się z zewnętrznymi punktami końcowymi i nie zbierano żadnych danych osobowych. To test laboratoryjny, a nie skanowanie cudzej infrastruktury.

Zastosowaliśmy trzy niezależne metody weryfikacji, aby nie polegać na ślepo na żadnym pojedynczym narzędziu:

Dlaczego FIPS tak działa: X25519 nie jest zatwierdzony, ML-KEM jest

Mechanizm ten wynika z rozbieżności między tym, co zatwierdzają standardy, a tym, co jest domyślne w ekosystemie. Zgodnie z zasadami uzgadniania kluczy NIST zawartymi w SP 800-56A, X25519 nie jest schematem zatwierdzonym przez FIPS, dlatego rygorystyczny moduł odrzuca go, gdy występuje samodzielnie. ML-KEM, znormalizowany jako FIPS 203, jest zatwierdzony. Jedyną szeroko zdefiniowaną hybrydą zgodną z FIPS w obu częściach jest SecP256r1MLKEM768: NIST P-256 (zatwierdzona krzywa) połączona z ML-KEM-768. Konkurencyjna hybryda X25519MLKEM768 łączy zatwierdzony ML-KEM-768 z niezatwierdzonym X25519, więc połowa z niej znajduje się poza listą.

Problem polega na tym, że przeglądarki, Go i OpenSSL domyślnie stosują X25519MLKEM768, a nie zatwierdzony SecP256r1MLKEM768, ponieważ X25519 jest szybki i powszechny poza światem FIPS. Obie hybrydy są zdefiniowane w tym samym projekcie IETF dotyczącym wymiany kluczy ECDHE-MLKEM. Zatem przełącznik FIPS, który usuwa X25519, usuwa również zbudowaną na nim hybrydę postkwantową, chyba że dany stos specjalnie traktuje taką hybrydę. To dokładnie to rozgałęzienie, które zmierzyliśmy. Go nakłada zbyt duże ograniczenia: odrzuca każdą grupę postkwantową i powraca do kryptografii klasycznej, co jest bezpieczne z punktu widzenia zgodności z normami, ale odrzuca odporność kwantową. OpenSSL nakłada zbyt małe ograniczenia: utrzymuje niezatwierdzoną hybrydę jako aktywną, przepuszczając ją przez wskaźnik zatwierdzenia FIPS zamiast ją zablokować, co stanowi projekt opisany w openssl/openssl #27061. Żadne z tych zachowań nie jest błędem w tradycyjnym rozumieniu. Obie decyzje twórców bibliotek można uzasadnić, jednak dają one nieoczywisty rezultat po przeanalizowaniu ruchu sieciowego. Zachowanie Go omówiono w golang/go #78178 oraz #78298, a obsługa postkwantowa w OpenSSL 3.5 pojawiła się w wydaniu z kwietnia 2025 r..

Co zrobić, jeśli stosujesz FIPS i dbasz o ochronę przed „zbieraj teraz, odszyfruj później”

Głównym celem hybrydy postkwantowej jest ochrona przed atakującym stosującym strategię „zbieraj teraz, odszyfruj później” (harvest now, decrypt later), czyli takim, który rejestruje ruch TLS dzisiaj i odszyfruje go, gdy pojawią się komputery kwantowe. Przełącznik FIPS, który po cichu usuwa tę ochronę, niweczy ten cel w przypadku organizacji najbardziej narażonych na ataki. Jeśli używasz FIPS, nie zakładaj, że sam przełącznik załatwił sprawę.

Czego to nie dowodzi

Wynik bez określenia jego ograniczeń to marketing, dlatego oto ograniczenia tego badania.

Często zadawane pytania

Czy włączenie trybu FIPS wyłącza postkwantowy TLS?

Może i w naszym laboratorium tak się stało. W przypadku Go 1.24 pod GODEBUG=fips140=on lub fips140=only, komunikat ClientHello odrzucił każdą grupę postkwantową, a połączenie wynegocjowało klasyczne P-256, więc udany uścisk dłoni nie zawierał żadnej odpornej na komputery kwantowe wymiany kluczy. OpenSSL 3.5.2 zrobił coś odwrotnego: jego dostawca FIPS nadal oferował i negocjował X25519MLKEM768, którego część X25519 nie jest zatwierdzona przez FIPS. Żaden ze stosów nie oferował domyślnie zatwierdzonej przez FIPS grupy postkwantowej.

Czy X25519 jest zatwierdzony przez FIPS?

Nie. X25519 nie jest zatwierdzonym schematem uzgadniania kluczy według NIST SP 800-56A, więc rygorystyczny moduł FIPS traktuje go jako niezatwierdzony. Potwierdziliśmy to bezpośrednio: w przypadku dostawcy FIPS w OpenSSL 3.5.2 samodzielna generacja klucza X25519 nie powiodła się z powodu braku obsługi z niezerowym kodem wyjścia, podczas gdy ta sama operacja zakończyła się sukcesem pod dostawcą domyślnym.

Czy X25519MLKEM768 jest zatwierdzony przez FIPS?

Nie jednoznacznie. Jest to hybryda: część ML-KEM-768 jest zatwierdzona przez FIPS 203, ale część X25519 nie jest zatwierdzona do uzgadniania kluczy. Dostawca FIPS w OpenSSL nie blokuje tej hybrydy; przepuszcza ją przez wskaźnik zatwierdzenia FIPS i nadal oferuje oraz negocjuje ją domyślnie. Grupa działa w trybie FIPS, ale jej część klasyczna znajduje się poza listą zatwierdzonych.

Jaka jest zatwierdzona przez FIPS postkwantowa grupa TLS?

Szeroko zdefiniowaną hybrydą zgodną z FIPS jest SecP256r1MLKEM768: NIST P-256 (krzywa zatwierdzona według SP 800-56A) połączona z ML-KEM-768 z FIPS 203. Obie części są zatwierdzone. W naszym laboratorium wymuszenie SecP256r1MLKEM768 przy obu partnerach w trybie FIPS doprowadziło do pomyślnego uścisku dłoni, ale ani Go 1.24, ani OpenSSL 3.5.2 nie oferowały tej grupy domyślnie.

Dlaczego uścisk dłoni TLS w Go zmienia się przy GODEBUG=fips140?

Ponieważ tryb FIPS w Go 1.24 ogranicza oferowane krzywe do zestawu NIST. Pod fips140=on lub fips140=only, zarejestrowany komunikat ClientHello ogłaszał jedynie secp256r1, secp384r1 oraz secp521r1, bez x25519 i bez hybrydy postkwantowej, negocjując klasyczne P-256. Serwer Go w trybie FIPS wysłał HelloRetryRequest, aby wymusić obniżenie u partnera do secp256r1. Uścisk dłoni nadal kończy się sukcesem, więc obniżenie poziomu następuje po cichu, chyba że sprawdzisz wynegocjowaną grupę.

Czy FIPS narusza ochronę przed „zbieraj teraz, odszyfruj później”?

W testowanych przez nas domyślnych konfiguracjach tak, w istotnym zakresie. Go w trybie FIPS usunął całą postkwantową wymianę kluczy i powrócił do kryptografii klasycznej, czyli dokładnie do takiego ruchu, jaki atakujący stosujący strategię „zbieraj teraz, odszyfruj później” chce zarejestrować i odszyfrować w przyszłości. OpenSSL zachował postkwantową wymianę kluczy, ale za pośrednictwem hybrydy, której klasyczna część nie jest zatwierdzona przez FIPS, co stanowi problem ze zgodnością z normami, a nie kryptograficzny. W obu przypadkach włączenie FIPS domyślnie nie zapewniło zgodnej z normami ochrony postkwantowej.

Powiązane artykuły

Korzystasz z FIPS i zakładasz, że obsłużył postkwantowość?

Nasza weryfikacja za $100 odczytuje Twoją rzeczywistą postawę kryptograficzną w taki sposób, w jaki rejestruje ją atakujący, w zakresie, którego własność zweryfikowano i upoważniono na piśmie, z udziałem doświadczonego specjalisty podczas omówienia. To, co Twoje usługi faktycznie negocjują w ruchu sieciowym, stanowi część tej powierzchni ataku.

Zamów weryfikację za $100