Todas las investigaciones

¿FIPS 140-3 deshabilita TLS poscuántico? Te degrada silenciosamente

Tabla de verdad TLS en FIPS-140-3: Go elimina lo poscuántico, OpenSSL mantiene el híbrido no aprobado.

La respuesta corta a "¿FIPS deshabilita TLS poscuántico?" es: no te proporciona TLS poscuántico en conformidad, y puede desactivarlo silenciosamente. En nuestro propio laboratorio, analizando el tráfico en la red, dos de los principales stacks hicieron cosas opuestas una vez que los pusimos en modo FIPS, y ninguno ofreció el grupo poscuántico aprobado por FIPS de forma predeterminada. Go 1.24, bajo GODEBUG=fips140=on y =only, eliminó todos los grupos poscuánticos de su ClientHello y negoció silenciosamente el algoritmo clásico P-256, por lo que una conexión que "tuvo éxito" no incluyó ningún intercambio de claves resistente a la computación cuántica. El proveedor FIPS de OpenSSL 3.5.2 hizo lo contrario: siguió ofreciendo y negociando X25519MLKEM768, el híbrido cuya mitad X25519 no está aprobada por FIPS. Su proveedor FIPS controla esa mitad mediante un indicador de aprobación en lugar de bloquearla. Por lo tanto, TLS poscuántico en FIPS 140-3 cae en uno de dos modos de fallo: al activar FIPS, la protección poscuántica se desactiva (Go) o bien se mantiene activo un grupo que no cumple con la normativa (OpenSSL). La protección frente a ataques de captura ahora y descifrado después ("harvest-now-decrypt-later") queda desconfigurada silenciosamente justo en las organizaciones reguladas obligadas a utilizar FIPS.

La versión sin rodeos "FIPS activado" no significa "poscuántico activado". Go 1.24 en modo FIPS elimina por completo el híbrido poscuántico y recurre al clásico P-256 sin generar ningún error. OpenSSL 3.5 en modo FIPS conserva X25519MLKEM768, cuya mitad clásica no está en la lista de aprobados por FIPS. Ninguno de los dos ofrece SecP256r1MLKEM768, el híbrido que realmente cumple con FIPS, a menos que lo configures manualmente.

Lo que descubrimos al activar el conmutador FIPS

Construimos dos clientes y dos servidores, un par en Go 1.24 y otro en OpenSSL 3.5.2, y observamos sus handshakes TLS 1.3 en la red con el modo FIPS desactivado y luego activado. TLS 1.3 envía las extensiones supported_groups y key_share en texto plano, por lo que el ClientHello es la prueba definitiva: puedes leer exactamente qué grupos de intercambio de claves está dispuesto a usar un cliente y para cuál preparó un fragmento ("share"). Sin adivinar a partir de la documentación de una librería, solo los bytes que colocó en el socket.

Con Go 1.24 en modo FIPS, el ClientHello se redujo únicamente a las curvas NIST. La lista supported_groups fue secp256r1, secp384r1, secp521r1 y nada más: ni x25519 individual, ni X25519MLKEM768, ni tan siquiera, notablemente, el grupo SecP256r1MLKEM768 aprobado por FIPS. El key_share fue secp256r1 y el grupo negociado fue secp256r1, Diffie-Hellman de curva elíptica clásico sin ningún componente poscuántico. El comportamiento fue idéntico para fips140=on y para la opción más estricta fips140=only. Un servidor de Go en modo FIPS, al recibir una oferta de un grupo poscuántico por parte de un par que no utilizaba FIPS, respondió con un HelloRetryRequest y forzó el handshake hacia secp256r1. En todos los casos, el handshake se completó con éxito. Esa es la parte peligrosa: nada falló, no hubo advertencias, la conexión simplemente perdió en silencio su resistencia cuántica.

Con OpenSSL 3.5.2 el proveedor FIPS actuó de forma opuesta. Su ClientHello en modo FIPS encabezaba con X25519MLKEM768 e incluía un key_share para este, seguido de P-256, P-384, P-521 y los grupos de campo finito. En comparación con su configuración base sin FIPS, los únicos grupos que el modo FIPS eliminó fueron las curvas independientes x25519 y x448; la opción híbrida X25519MLKEM768 se mantuvo en la parte superior de la lista con un key_share activo, y negoció dicho grupo frente a un par que lo soportaba. El servidor OpenSSL también aceptó X25519MLKEM768. Por lo tanto, OpenSSL en modo FIPS sigue ofreciendo un grupo cuya mitad clásica no te permite usar de forma aislada.

La tabla de verdad en la red

Aquí se muestra cada uno de los casos que medimos, junto con los grupos que ofreció cada stack, el grupo negociado y lo que esto implica para ti. Las filas de Go y OpenSSL resumen la historia: la misma intención, "hacer que TLS cumpla con FIPS", y el resultado opuesto.

Comportamiento TLS FIPS-140-3 medido en la red, ejecución en laboratorio 2026-08-04
StackRolModo FIPSGrupos ofrecidosGrupo negociadoResultado
Go 1.24Clientefips140=on / =onlysecp256r1, secp384r1, secp521r1secp256r1Solo clásico, sin poscuántico
Go 1.24Servidorfips onCurvas NIST; envía HelloRetryRequestsecp256r1Fuerza al par a degradar a clásico
OpenSSL 3.5.2Clientefips onX25519MLKEM768, secp256r1/384/521, ffdhe2048/3072X25519MLKEM768Poscuántico, pero híbrido no aprobado
OpenSSL 3.5.2Servidorfips onAcepta X25519MLKEM768X25519MLKEM768Poscuántico, pero híbrido no aprobado
OpenSSL 3.5.2Ambos, forzadofips onX25519MLKEM768 (forzado)X25519MLKEM768Handshake exitoso bajo FIPS
OpenSSL 3.5.2Ambos, forzadofips onSecP256r1MLKEM768 (forzado)SecP256r1MLKEM768El híbrido aprobado funciona, pero nunca es por defecto

Compara las dos últimas filas con todo lo anterior. Ambos híbridos poscuánticos realizan el handshake correctamente con ambos pares en modo FIPS, incluido el SecP256r1MLKEM768 totalmente aprobado. Los stacks son capaces de hacer lo correcto. Simplemente no lo eligen por ti: Go los elimina todos y OpenSSL selecciona por defecto el no aprobado.

Cómo lo medimos, para que un escéptico pueda confiar en los números

El conjunto de datos es propio, generado en nuestros propios sistemas y únicamente agregado. Ejecutamos todo en contenedores Docker construidos por nosotros, en una máquina virtual efímera en la nube, comunicándose entre sí a través de loopback. No se tocó el servidor de ningún tercero, no se contactó con ningún endpoint externo y no se recopiló información sobre ningún individuo. Esto es un laboratorio, no un escaneo de la infraestructura de nadie.

Utilizamos tres comprobaciones independientes para no tener que confiar a ciegas en una sola herramienta:

Por qué FIPS actúa así: X25519 no está aprobado, ML-KEM sí

El mecanismo radica en una discrepancia entre lo que aprueban los estándares y lo que el ecosistema utiliza por defecto. Bajo las reglas de acuerdo de claves del NIST en SP 800-56A, X25519 no es un esquema aprobado por FIPS, motivo por el cual un módulo estricto lo rechaza de forma aislada. ML-KEM, estandarizado como FIPS 203, está aprobado. El único híbrido ampliamente especificado que cumple con FIPS en ambas mitades es SecP256r1MLKEM768: NIST P-256, una curva aprobada, vinculada a ML-KEM-768. El híbrido competidor X25519MLKEM768 combina ML-KEM-768 aprobado con X25519 no aprobado, por lo que la mitad queda fuera de la lista.

El problema es que los navegadores, Go y OpenSSL utilizan por defecto X25519MLKEM768, no el aprobado SecP256r1MLKEM768, porque X25519 es rápido y está omnipresente fuera del ámbito de FIPS. Ambos híbridos están especificados en el mismo borrador de la IETF para intercambio de claves ECDHE-MLKEM. Así, un conmutador FIPS que elimina X25519 también elimina el híbrido poscuántico basado en él, a menos que el stack trate dicho híbrido como un caso especial. Esa es exactamente la bifurcación que medimos. Go restringe en exceso: descarta todos los grupos poscuánticos y vuelve a la criptografía clásica, lo cual es seguro para el cumplimiento normativo pero desecha la resistencia cuántica. OpenSSL restringe por defecto de forma insuficiente: mantiene activo el híbrido no aprobado, regulándolo mediante un indicador de aprobación FIPS en lugar de bloquearlo, un diseño registrado en openssl/openssl #27061. Ninguno de los dos comportamientos es un error en el sentido habitual; ambos son decisiones razonables en una librería que producen un resultado no evidente una vez que observas el tráfico en la red. El comportamiento de Go se analiza en golang/go #78178 y #78298, y el soporte poscuántico de OpenSSL 3.5 llegó en su lanzamiento de abril de 2025.

Qué hacer si ejecutas FIPS y te preocupa la amenaza de captura ahora y descifrado después

El objetivo principal de un híbrido poscuántico es frustrar a un adversario que aplique "captura ahora, descifra después", alguien que graba tu tráfico TLS hoy para descifrarlo cuando exista un ordenador cuántico. Un conmutador FIPS que elimina esa protección silenciosamente anula ese propósito para las organizaciones con mayor probabilidad de ser objetivo de ataques. Si ejecutas FIPS, no asumas que la opción lo resolvió automáticamente.

Lo que esto no demuestra

Un resultado sin sus límites es solo marketing, por lo que aquí están los márgenes de este análisis.

Preguntas frecuentes

¿Activar el modo FIPS deshabilita TLS poscuántico?

Puede hacerlo, y en nuestro laboratorio lo hizo. Con Go 1.24 bajo GODEBUG=fips140=on o fips140=only, el ClientHello descartó todos los grupos poscuánticos y la conexión negoció P-256 clásico, por lo que un handshake que tuvo éxito carecía de intercambio de claves resistente a la computación cuántica. OpenSSL 3.5.2 hizo lo contrario: su proveedor FIPS siguió ofreciendo y negociando X25519MLKEM768, cuya mitad X25519 no está aprobada por FIPS. Ninguno de los dos stacks ofreció el grupo poscuántico aprobado por FIPS de forma predeterminada.

¿Está X25519 aprobado por FIPS?

No. X25519 no es un esquema de acuerdo de claves aprobado según NIST SP 800-56A, por lo que un módulo FIPS estricto lo trata como no aprobado. Lo confirmamos directamente: bajo el proveedor FIPS de OpenSSL 3.5.2, la generación de claves X25519 independientes falló por no estar soportada con un código de salida distinto de cero, mientras que la misma operación tuvo éxito con el proveedor predeterminado.

¿Está X25519MLKEM768 aprobado por FIPS?

No del todo. Es un híbrido: la mitad ML-KEM-768 está aprobada por FIPS 203, pero la mitad X25519 no está aprobada para el acuerdo de claves. El proveedor FIPS de OpenSSL no bloquea el híbrido; lo regula mediante un indicador de aprobación FIPS y continúa ofreciéndolo y negociándolo por defecto. El grupo funciona bajo FIPS, pero su mitad clásica está fuera de la lista de aprobados.

¿Cuál es el grupo TLS poscuántico aprobado por FIPS?

El híbrido especificado ampliamente y conforme a FIPS es SecP256r1MLKEM768: NIST P-256, una curva aprobada por SP 800-56A, combinada con ML-KEM-768 de FIPS 203. Ambas mitades están aprobadas. En nuestro laboratorio, forzar SecP256r1MLKEM768 con ambos pares en modo FIPS produjo un handshake exitoso, pero ni Go 1.24 ni OpenSSL 3.5.2 lo ofrecieron por defecto.

¿Por qué cambia mi handshake TLS en Go bajo GODEBUG=fips140?

Porque el modo FIPS de Go 1.24 restringe las curvas ofrecidas al conjunto de NIST. Bajo fips140=on o fips140=only, el ClientHello que capturamos del cliente anunció únicamente secp256r1, secp384r1 y secp521r1, sin x25519 y sin híbrido poscuántico, y negoció P-256 clásico. Un servidor de Go en modo FIPS envió un HelloRetryRequest para forzar al par a degradar a secp256r1. El handshake sigue teniendo éxito, por lo que la degradación es silenciosa a menos que inspecciones el grupo negociado.

¿FIPS rompe la protección frente a captura ahora y descifrado después?

En las configuraciones predeterminadas que probamos, sí, en el aspecto determinante. Go en modo FIPS eliminó todo intercambio de claves poscuántico y volvió a la criptografía clásica, que es exactamente el tráfico que un adversario que busca capturar ahora y descifrar después quiere registrar y romper más adelante. OpenSSL mantuvo el intercambio de claves poscuántico pero mediante un híbrido cuya mitad clásica no está aprobada por FIPS, lo que constituye un problema de cumplimiento en lugar de criptográfico. En cualquier caso, activar FIPS no ofreció una protección poscuántica en conformidad de forma predeterminada.

Lecturas relacionadas

¿Ejecutas FIPS y asumes que resolvió lo poscuántico?

Nuestra revisión de $100 analiza tu postura criptográfica real de la misma forma en que la registraría un atacante, sobre un alcance cuya titularidad hayas verificado y autorizado por escrito, con la explicación a cargo de un operador senior. Lo que tus servicios negocian realmente en la red forma parte de esa superficie.

Reserva una revisión de $100