Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Apéndice I: Crypto-Policies — Arquitectura Interna, Subpolíticas y Referencia Completa de Parámetros

Alcance: Este apéndice documenta el funcionamiento interno del framework crypto-policies de RHEL 8/9/10 — desde la definición de políticas hasta la generación de los archivos de configuración de cada back-end. Cubre todos los parámetros del lenguaje de políticas, el sistema de ámbitos, la creación de subpolíticas .pmod, políticas completas .pol, las irregularidades de cada back-end y el flujo real del update-crypto-policies.


I.1 Por Qué Existe Este Apéndice

Los capítulos 10, 23 y 31 de este tutorial presentan lo que las crypto-policies hacen, cómo alternar entre ellas y cómo diagnosticar problemas. Este apéndice va más allá: describe cómo funciona el sistema internamente, cuál es la sintaxis exacta aceptada en los archivos .pol y .pmod, qué parámetros existen, cómo cada uno afecta a cada back-end y qué trampas concretas esperan al administrador que crea políticas personalizadas.


I.2 Arquitectura Interna — El Pipeline Completo

El comando update-crypto-policies es un wrapper shell (/usr/bin/update-crypto-policies) que invoca el script Python update-crypto-policies.py. Todo el procesamiento real ocurre en Python, usando los módulos cryptopolicies (parsing de la política) y policygenerators (generación de back-ends).

Cuando el administrador ejecuta update-crypto-policies --set DEFAULT:NO-SHA1, el sistema recorre las siguientes etapas:

┌──────────────────────────────────────────────────────────────────┐
│  1. LECTURA DE LA POLÍTICA BASE                                  │
│     La clase UnscopedCryptoPolicy busca DEFAULT.pol en este      │
│     orden:                                                       │
│       1. Directorio actual                                       │
│       2. policies/ (relativo)                                    │
│       3. /etc/crypto-policies/policies/                          │
│       4. /usr/share/crypto-policies/policies/                    │
│     El primer archivo encontrado es usado.                       │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  2. LECTURA Y CONCATENACIÓN DE LAS SUBPOLÍTICAS                  │
│     Busca NO-SHA1.pmod en modules/ en las mismas rutas de        │
│     arriba.                                                      │
│                                                                  │
│     Las directivas de DEFAULT.pol y NO-SHA1.pmod se concatenan   │
│     en una lista secuencial de objetos Directive(prop_name,      │
│     scope, operation, value).                                    │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  3. PREPROCESAMIENTO (preprocess_text)                           │
│     Antes del parsing, el texto bruto pasa por:                  │
│     a) Eliminación de comentarios (#)                            │
│     b) Resolución de continuaciones de línea (\)                 │
│     c) Normalización de espacios                                 │
│     d) Conversión de parámetros obsoletos a equivalentes         │
│        modernos (ej: min_tls_version=TLS1.2 →                    │
│        protocol@TLS = -SSL2.0 -SSL3.0 -TLS1.0 -TLS1.1)           │
│     e) Renombramiento de valores (ej: X25519-MLKEM768 →          │
│        MLKEM768-X25519)                                          │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  4. PARSING (parse_line → parse_rhs)                             │
│     Cada línea se convierte en Directives con operaciones:       │
│     - RESET:    "cipher ="          → limpia la lista            │
│     - APPEND:   "cipher = AES-*"    → añade al final             │
│     - PREPEND:  "cipher = +AES-*"   → inserta al inicio          │
│     - OMIT:     "cipher = -RC4-*"   → elimina de la lista        │
│     - SET_INT:  "min_rsa_size=2048" → define entero              │
│     - SET_ENUM: "__ems = ENFORCE"   → define enumeración         │
│     Los wildcards (*) se expanden contra las listas conocidas    │
│     de algoritmos (alg_lists.py).                                │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  5. RESOLUCIÓN POR ÁMBITOS (ScopedPolicy)                        │
│     Para cada back-end, la lista de Directives se evalúa con     │
│     los ámbitos relevantes de ese back-end. Una directiva solo   │
│     tiene efecto si su ScopeSelector corresponde a los ámbitos   │
│     del back-end. Ej: cipher@SSH solo afecta a {'ssh','openssh'}.│
│     El resultado son listas de algoritmos .enabled y .disabled   │
│     más los valores de .integers y .enums.                       │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  6. GENERACIÓN DE LOS BACK-ENDS (PolicyGenerators)               │
│     13 clases generadoras convierten la ScopedPolicy en configs: │
│                                                                  │
│     ┌─────────────────────────┬────────────────────────────┐     │
│     │ Clase Generadora        │ Archivo .config            │     │
│     ├─────────────────────────┼────────────────────────────┤     │
│     │ OpenSSLGenerator        │ opensslcnf.config          │     │
│     │ OpenSSLFIPSGenerator    │ openssl_fips.config        │     │
│     │ GnuTLSGenerator         │ gnutls.config              │     │
│     │ NSSGenerator            │ nss.config                 │     │
│     │ OpenSSHClientGenerator  │ openssh.config             │     │
│     │ OpenSSHServerGenerator  │ opensshserver.config       │     │
│     │ LibsshGenerator         │ libssh.config              │     │
│     │ KRB5Generator           │ krb5.config                │     │
│     │ LibreswanGenerator      │ libreswan.config           │     │
│     │ BindGenerator           │ bind.config                │     │
│     │ JavaGenerator           │ java.config                │     │
│     │ SequoiaGenerator        │ sequoia.config             │     │
│     │ RPMSequoiaGenerator     │ rpm-sequoia.config         │     │
│     └─────────────────────────┴────────────────────────────┘     │
│     Cada generador traduce los nombres genéricos de algoritmos   │
│     a los nombres específicos de la biblioteca usando tablas de  │
│     mapeo (cipher_map, sign_map, group_map, etc.).               │
│     Cada generador también PRUEBA la config generada ejecutando  │
│     el binario real de la biblioteca (openssl ciphers,           │
│     gnutls-cli -l, ssh -G, sshd -T) para validar que no hay      │
│     errores.                                                     │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  4. GENERACIÓN DE LOS BACK-ENDS                                  │
│     Para cada biblioteca/aplicación soportada, un generador de   │
│     configuración específico (policy generator) convierte la     │
│     política efectiva en un formato que la biblioteca entiende:  │
│                                                                  │
│     ┌────────────┬──────────────────────────────────────────┐    │
│     │ Back-end   │ Archivo generado                         │    │
│     ├────────────┼──────────────────────────────────────────┤    │
│     │ OpenSSL    │ opensslcnf.config                        │    │
│     │ GnuTLS     │ gnutls.config                            │    │
│     │ NSS        │ nss.config                               │    │
│     │ OpenSSH    │ openssh.config, opensshserver.config     │    │
│     │ libssh     │ libssh.config                            │    │
│     │ Kerberos   │ krb5.config                              │    │
│     │ Libreswan  │ libreswan.config                         │    │
│     │ BIND       │ bind.config                              │    │
│     │ Java/JDK   │ java.config                              │    │
│     │ Sequoia    │ sequoia.config                           │    │
│     │ RPM-Seqoia │ rpm-sequoia.config                       │    │
│     └────────────┴──────────────────────────────────────────┘    │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  7. INSTALACIÓN DE LOS BACK-ENDS                                 │
│     Los archivos generados se escriben atómicamente en:          │
│       /etc/crypto-policies/back-ends/                            │
│     (vía mkstemp + os.rename para evitar corrupción)             │
│                                                                  │
│     Si la política no usa subpolíticas Y no existe local.d/,     │
│     se crea un SYMLINK hacia los back-ends pregenerados en       │
│     /usr/share/crypto-policies/<POLICY>/ (optimización).         │
│                                                                  │
│     Si existe contenido en /etc/crypto-policies/local.d/,        │
│     se CONCATENA al final del back-end correspondiente.          │
│                                                                  │
│     El archivo /etc/crypto-policies/config se actualiza.         │
│     El archivo /etc/crypto-policies/state/CURRENT.pol recibe     │
│     el volcado legible de la política efectiva expandida.        │
│     El archivo /etc/crypto-policies/state/current recibe el      │
│     nombre de la política activa (ej: "DEFAULT:NO-SHA1").        │
└──────────────────────┬───────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  8. RECARGA DE LOS SERVICIOS                                     │
│     Si --no-reload NO fue utilizado, el script ejecuta           │
│     /usr/share/crypto-policies/reload-cmds.sh que contiene       │
│     comandos de recarga para cada servicio afectado.             │
│     Ejemplo: "systemctl try-restart sshd.service" para SSH.      │
│     Otras bibliotecas (OpenSSL, GnuTLS, NSS) solo aplican        │
│     la nueva política cuando la aplicación se reinicia.          │
└──────────────────────────────────────────────────────────────────┘

Punto crítico: Las aplicaciones (Apache, NGINX, Postfix, etc.) no leen la política directamente. Utilizan bibliotecas (OpenSSL, GnuTLS, NSS) que a su vez leen los archivos de back-end. El cambio de política solo tiene efecto cuando el proceso que usa la biblioteca se reinicia.


I.3 Jerarquía Completa de Archivos

/usr/share/crypto-policies/
├── policies/                          # Políticas base del paquete
│   ├── DEFAULT.pol
│   ├── LEGACY.pol
│   ├── FUTURE.pol
│   ├── FIPS.pol
│   ├── BSI.pol
│   ├── EMPTY.pol
│   ├── NEXT.pol                       # Alias para DEFAULT
│   └── modules/                       # Subpolíticas del paquete
│       ├── AD-SUPPORT.pmod
│       ├── NO-SHA1.pmod
│       ├── NO-CAMELLIA.pmod
│       ├── NO-ENFORCE-EMS.pmod
│       ├── GOST.pmod
│       └── ...
├── DEFAULT/                           # Back-ends pregenerados para DEFAULT
│   ├── opensslcnf.config
│   ├── gnutls.config
│   ├── nss.config
│   └── ...
├── LEGACY/                            # Back-ends pregenerados para LEGACY
│   └── ...
├── FUTURE/                            # Back-ends pregenerados para FUTURE
│   └── ...
└── FIPS/                              # Back-ends pregenerados para FIPS
    └── ...

/etc/crypto-policies/
├── config                             # Texto con nombre de la política activa
│                                      # Ej: "DEFAULT:NO-SHA1"
├── back-ends/                         # Back-ends activos (enlaces o copias)
│   ├── opensslcnf.config
│   ├── openssl_fips.config            # Configuración del módulo FIPS de OpenSSL
│   ├── gnutls.config
│   ├── nss.config
│   ├── openssh.config
│   ├── opensshserver.config
│   ├── libssh.config
│   ├── krb5.config
│   ├── libreswan.config
│   ├── bind.config
│   ├── java.config
│   ├── sequoia.config
│   └── rpm-sequoia.config
├── local.d/                           # Overrides locales por back-end
│   ├── opensslcnf-extra.config        # Concatenado al opensslcnf.config
│   ├── gnutls-extra.config
│   └── ...
├── state/
│   └── current -> /usr/share/crypto-policies/DEFAULT  # Enlace simbólico
├── policies/                          # Políticas personalizadas locales
│   ├── MYPOLICY.pol                   # Política personalizada completa
│   └── modules/                       # Subpolíticas personalizadas locales
│       └── MY-MODULE.pmod
└── state/
    └── CURRENT.pol                    # Política efectiva expandida

Prioridad de búsqueda: Cuando update-crypto-policies busca un archivo .pol o .pmod, verifica primero /etc/crypto-policies/policies/ y después /usr/share/crypto-policies/policies/. Esto permite sobrescribir políticas del paquete localmente.


I.4 Formato de Definición de Política — Sintaxis Completa

Los archivos .pol y .pmod usan una sintaxis INI simple: clave = valor.

I.4.1 Reglas Generales de Sintaxis

# Los comentarios comienzan con '#'
# Todo lo que aparece después de '#' en la línea se ignora

# Continuación de línea con '\'
cipher = AES-256-GCM AES-128-GCM \
         CHACHA20-POLY1305

# Asignación directa — define la lista completa
cipher = AES-256-GCM AES-128-GCM CHACHA20-POLY1305

# Modificación incremental — añade y elimina de la lista existente
# '+' al inicio = prepend (insertar al comienzo de la lista, mayor prioridad)
# sin prefijo al final = append (insertar al final de la lista)
# '-' = eliminar de la lista
cipher = +AES-256-GCM -CAMELLIA-256-GCM AES-128-CCM+

# Lista vacía — deshabilita todo en esa categoría
cipher =

# Valores enteros
min_rsa_size = 3072

# Valores booleanos (0 o 1)
sha1_in_certs = 0

Regla fundamental de la modificación incremental:

Prefijo/SufijoSignificadoEjemplo
+VALOR (prefijo +)Prepend — inserta al inicio de la lista (mayor prioridad)cipher = +AES-256-GCM
VALOR+ (sufijo +)Append — inserta al final de la lista (menor prioridad)cipher = AES-128-CCM+
-VALOR (prefijo -)Remove — retira de la listacipher = -CAMELLIA-256-GCM
VALOR (sin prefijo, asignación directa)Reset — sustituye la lista enteracipher = AES-256-GCM AES-128-GCM

Asignación directa y modificación incremental NO pueden combinarse en la misma directiva.

I.4.2 Wildcards

El carácter * sirve como comodín para coincidencia en nombres de algoritmos:

# Eliminar TODOS los algoritmos SHA1 de firma
sign = -*-SHA1

# Eliminar todos los ciphers AES-128
cipher = -AES-128-*

# Eliminar todas las cifras Camellia
cipher = -CAMELLIA-*

Precaución: Los wildcards en directivas de adición (+) pueden habilitar algoritmos futuros que aún no existen en la versión actual. Utilice wildcards con - (eliminación) por seguridad.

I.4.3 Ámbitos (@scope) — Directivas Por Back-end

Los ámbitos permiten que una directiva afecte solo a back-ends específicos:

# Sintaxis: opción@ámbito = valor

# Solo para SSH
cipher@SSH = -AES-128-CBC

# Solo para TLS
protocol@TLS = TLS1.3 TLS1.2

# Solo para IKE (IPsec)
protocol@IKE = IKEv2

# Múltiples ámbitos
cipher@{SSH,TLS} = -CAMELLIA-*

# Negación de ámbito — aplica a todos EXCEPTO el especificado
cipher@!SSH = -AES-128-CBC

# Negación con múltiples ámbitos
cipher@!{SSH,Kerberos} = -AES-128-CBC

Ámbitos disponibles (lista completa extraída del código fuente, ALL_SCOPES):

ÁmbitoBack-ends afectadosNotas
tls, sslOpenSSL, GnuTLS, NSS (nss-tls), JavaSinónimos
opensslSolo OpenSSLMás específico que tls
gnutlsSolo GnuTLSMás específico que tls
java-tlsSolo Java/OpenJDKMás específico que tls
nssNSS (todos los subámbitos)Ámbito raíz NSS
nss-tlsNSS para TLSHereda de nss
sshOpenSSH (client+server), libsshÁmbito genérico SSH
opensshOpenSSH (client+server)Más específico que ssh
openssh-clientSolo OpenSSH clienteHereda de openssh
openssh-serverSolo OpenSSH servidorHereda de openssh
libsshSolo libsshMás específico que ssh
ipsec, ikeLibreswanSinónimos
libreswanSolo LibreswanMás específico que ipsec
kerberos, krb5MIT KerberosSinónimos
dnssec, bindBINDSinónimos
sequoiaSequoia PGPOpenPGP
rpm, rpm-sequoiaRPM vía SequoiaVerificación de paquetes RPM
pkcs12NSS — PKCS#12Hereda de nss
pkcs12-importNSS — importación PKCS#12Hereda de nss-pkcs12
nss-pkcs12NSS — PKCS#12Sinónimo funcional
nss-pkcs12-importNSS — importación PKCS#12Más permisivo
smimeNSS — S/MIMEHereda de nss
smime-importNSS — importación S/MIMEHereda de nss-smime
nss-smimeNSS — S/MIMESinónimo funcional
nss-smime-importNSS — importación S/MIMEMás permisivo

Los selectores de ámbito son case-insensitive. Soportan globbing (*) y negación (!). Múltiples ámbitos entre llaves: @{SSH,TLS}. Negación múltiple: @!{SSH,Kerberos}.

Jerarquía de herencia: Ver sección I.13 para la jerarquía completa de ámbitos con relaciones padre-hijo.


I.5 Referencia Completa de Parámetros

I.5.1 Parámetros de Lista (múltiples valores)

cipher — Cifras Simétricas

Define qué algoritmos de criptografía simétrica (y modos de operación) están permitidos.

cipher = AES-256-GCM AES-256-CCM AES-256-CBC \
         AES-128-GCM AES-128-CCM AES-128-CBC \
         CHACHA20-POLY1305

Valores reconocidos:

ValorDescripciónTamaño Clave
AES-256-GCMAES 256-bit, modo Galois/Counter (autenticado)256 bits
AES-256-CCMAES 256-bit, modo Counter with CBC-MAC256 bits
AES-256-CBCAES 256-bit, modo Cipher Block Chaining256 bits
AES-256-CTRAES 256-bit, modo Counter256 bits
AES-128-GCMAES 128-bit, modo GCM128 bits
AES-128-CCMAES 128-bit, modo CCM128 bits
AES-128-CBCAES 128-bit, modo CBC128 bits
AES-128-CTRAES 128-bit, modo CTR128 bits
CHACHA20-POLY1305ChaCha20 con Poly1305 AEAD256 bits
CAMELLIA-256-GCMCamellia 256-bit, modo GCM256 bits
CAMELLIA-256-CBCCamellia 256-bit, modo CBC256 bits
CAMELLIA-128-GCMCamellia 128-bit, modo GCM128 bits
CAMELLIA-128-CBCCamellia 128-bit, modo CBC128 bits
AES-192-GCMAES 192-bit, modo GCM192 bits
AES-192-CCMAES 192-bit, modo CCM192 bits
AES-192-CBCAES 192-bit, modo CBC192 bits
AES-192-CTRAES 192-bit, modo CTR192 bits
AES-256-OCBAES 256-bit, modo OCB (Sequoia)256 bits
AES-128-OCBAES 128-bit, modo OCB (Sequoia)128 bits
AES-256-EAXAES 256-bit, modo EAX (Sequoia)256 bits
AES-128-EAXAES 128-bit, modo EAX (Sequoia)128 bits
AES-256-CFBAES 256-bit, modo CFB (Sequoia/RPM)256 bits
AES-128-CFBAES 128-bit, modo CFB (Sequoia/RPM)128 bits
3DES-CBCTriple DES, modo CBC168 bits (efectivo: 112)
RC4-128RC4 stream cipher128 bits
RC4-40RC4 con clave de 40 bits40 bits
RC2-CBCRC2 modo CBCVariable
DES-CBCDES modo CBC56 bits
DES40-CBCDES modo CBC con clave de 40 bits40 bits
IDEA-CBCIDEA modo CBC128 bits
SEED-CBCSEED modo CBC128 bits
NULLSin cifrado (solo integridad)0 bits

Nota: Algoritmos como AES-*-OCB, AES-*-EAX y AES-*-CFB se usan principalmente por los back-ends Sequoia y RPM (OpenPGP). Algoritmos como DES-CBC, RC4-40, RC2-CBC, DES40-CBC, IDEA-CBC y SEED-CBC existen solo para soporte de importación de archivos PKCS#12 heredados en la política LEGACY.

Impacto por back-end:

  • OpenSSL: Traducido en lista de Ciphersuites y CipherString en el opensslcnf.config. La eliminación de AES-128-GCM deshabilita TODOS los ciphers AES-128 (no es posible deshabilitar selectivamente un modo aislado).
  • GnuTLS: Lista de cifras en la priority string del gnutls.config.
  • NSS: Lista de ciphersuites en el nss.config.
  • OpenSSH: Lista de Ciphers en el openssh.config y opensshserver.config.
  • Kerberos: Tipos de cifrado permitidos (permitted_enctypes) en el krb5.config.

mac — Algoritmos MAC

Define qué Message Authentication Codes están permitidos.

mac = HMAC-SHA2-256 HMAC-SHA2-384 HMAC-SHA2-512 \
      HMAC-SHA1 AEAD \
      UMAC-128 UMAC-64

Valores reconocidos:

ValorDescripción
HMAC-SHA2-256HMAC con SHA-256
HMAC-SHA2-384HMAC con SHA-384
HMAC-SHA2-512HMAC con SHA-512
HMAC-SHA1HMAC con SHA-1
AEADMACs integrados en cifras AEAD (GCM, Poly1305)
UMAC-64UMAC con tag de 64 bits (SSH)
UMAC-128UMAC con tag de 128 bits (SSH)
HMAC-MD5HMAC con MD5 (inseguro — solo heredado)

Impacto por back-end:

  • OpenSSH: Genera lista MACs (hmac-sha2-256, hmac-sha2-512, umac-128-etm@openssh.com, etc.).
  • OpenSSL: Afecta indirectamente — ciphers CBC requieren HMAC-SHA1 y AES-256-CBC en la lista para estar habilitados.
  • GnuTLS: HMAC-SHA2-256 y HMAC-SHA2-384 como MACs standalone están deshabilitados debido a preocupaciones con la implementación constant-time; solo AEAD se usa en la práctica para TLS 1.3.

hash — Algoritmos de Hash (Message Digest)

Define qué funciones de hash criptográficas están permitidas para uso general (diferente de firmas).

hash = SHA2-256 SHA2-384 SHA2-512 \
       SHA3-256 SHA3-384 SHA3-512 \
       SHA2-224 SHA1

Valores reconocidos:

ValorSalida (bits)Uso Común
SHA1160Heredado (inseguro para firmas)
SHA2-224224Raro
SHA2-256256Estándar moderno
SHA2-384384TLS 1.3, certificados
SHA2-512512Alta seguridad
SHA3-256256Estándar NIST alternativo
SHA3-384384Estándar NIST alternativo
SHA3-512512Estándar NIST alternativo
SHA3-224224SHA-3 con salida reducida
SHAKE-128VariableFunción extensible (XOF)
SHAKE-256VariableFunción extensible (XOF)
MD5128Inseguro — solo heredado extremo

Relación hash vs sign: El parámetro hash controla el uso general (HMAC, derivación de clave, DNSSec). Para controlar qué hashes se aceptan en firmas, use sign.

sign — Algoritmos de Firma

Define qué combinaciones de algoritmo+hash de firma están permitidas.

sign = RSA-PSS-SHA2-256 RSA-PSS-SHA2-384 RSA-PSS-SHA2-512 \
       RSA-SHA2-256 RSA-SHA2-384 RSA-SHA2-512 \
       ECDSA-SHA2-256 ECDSA-SHA2-384 ECDSA-SHA2-512 \
       EDDSA-ED25519 EDDSA-ED448

Valores reconocidos:

ValorDescripción
RSA-SHA1RSA PKCS#1 v1.5 con SHA-1
RSA-SHA2-224RSA PKCS#1 v1.5 con SHA-224
RSA-SHA2-256RSA PKCS#1 v1.5 con SHA-256
RSA-SHA2-384RSA PKCS#1 v1.5 con SHA-384
RSA-SHA2-512RSA PKCS#1 v1.5 con SHA-512
RSA-PSS-SHA2-256RSA-PSS con SHA-256
RSA-PSS-SHA2-384RSA-PSS con SHA-384
RSA-PSS-SHA2-512RSA-PSS con SHA-512
ECDSA-SHA1ECDSA con SHA-1
ECDSA-SHA2-224ECDSA con SHA-224
ECDSA-SHA2-256ECDSA con SHA-256
ECDSA-SHA2-384ECDSA con SHA-384
ECDSA-SHA2-512ECDSA con SHA-512
EDDSA-ED25519EdDSA usando curva Ed25519
EDDSA-ED448EdDSA usando curva Ed448
DSA-SHA1DSA con SHA-1 (heredado)
DSA-SHA2-256DSA con SHA-256
ECDSA-SHA2-256-FIDOECDSA con SHA-256 vía FIDO (WebAuthn)
EDDSA-ED25519-FIDOEdDSA Ed25519 vía FIDO (WebAuthn)
RSA-PSS-RSAE-SHA2-256RSA-PSS (clave RSAE) con SHA-256
RSA-PSS-RSAE-SHA2-384RSA-PSS (clave RSAE) con SHA-384
RSA-PSS-RSAE-SHA2-512RSA-PSS (clave RSAE) con SHA-512
RSA-SHA3-256RSA PKCS#1 v1.5 con SHA3-256
RSA-PSS-SHA3-256RSA-PSS con SHA3-256
ECDSA-SHA3-256ECDSA con SHA3-256
MLDSA44ML-DSA-44 (postcuántico NIST, nivel 2)
MLDSA65ML-DSA-65 (postcuántico NIST, nivel 3)
MLDSA87ML-DSA-87 (postcuántico NIST, nivel 5)
MLDSA65-ED25519ML-DSA-65 + Ed25519 híbrido (OpenPGP RFC 9980)
MLDSA87-ED448ML-DSA-87 + Ed448 híbrido (OpenPGP RFC 9980)
SLHDSA-SHAKE-128SSLH-DSA con SHAKE-128 small (OpenPGP RFC 9980)
SLHDSA-SHAKE-128FSLH-DSA con SHAKE-128 fast (OpenPGP RFC 9980)
SLHDSA-SHAKE-256SSLH-DSA con SHAKE-256 small (OpenPGP RFC 9980)

Impacto práctico: Si un certificado X.509 fue firmado con RSA-SHA1 y la política activa no incluye RSA-SHA1 en sign, la verificación de la cadena de confianza del certificado fallará. Esta es la causa más común de “certificate verify failed” tras cambiar de LEGACY a DEFAULT.

Nota PQ: Los algoritmos ML-DSA se incluyen por defecto en DEFAULT, FUTURE y FIPS. Los algoritmos híbridos y SLH-DSA se incluyen solo para los ámbitos sequoia y RPM (OpenPGP), conforme a RFC 9980.

key_exchange — Métodos de Intercambio de Claves

key_exchange = ECDHE DHE RSA PSK DHE-RSA DHE-DSS
ValorDescripciónForward Secrecy
ECDHEElliptic Curve Diffie-Hellman EphemeralSí
DHEDiffie-Hellman EphemeralSí
DHE-RSADHE autenticado con RSASí
DHE-DSSDHE autenticado con DSS/DSASí
RSAIntercambio de clave RSA estáticoNo
PSKPre-Shared KeyDepende
ECDHE-GSSECDHE con GSSAPI (SSH)Sí
DHE-GSSDHE con GSSAPI (SSH)Sí
KEM-ECDHKey Encapsulation Mechanism con ECDH (postcuántico)Sí
SNTRUPNTRU Prime con X25519 (SSH postcuántico)Sí
RSA-PSKPre-Shared Key con autenticación RSANo
ECDHE-PSKECDHE con Pre-Shared KeySí
DHE-PSKDHE con Pre-Shared KeySí

Nota: La política FUTURE elimina RSA y DHE-DSS del intercambio de claves — esto significa que servidores usando certificados con claves DSA no podrán establecer conexiones.

Nota sobre Libreswan: El parámetro key_exchange no afecta la configuración generada para Libreswan. Para limitar DH/ECDH en IPsec, use el parámetro group.

group — Grupos/Curvas para Intercambio de Claves

Define qué curvas elípticas y grupos Diffie-Hellman están permitidos.

group = MLKEM768-X25519 P256-MLKEM768 P384-MLKEM1024 MLKEM1024-X448 \
        X25519 X448 SECP256R1 SECP384R1 SECP521R1 \
        FFDHE-2048 FFDHE-3072 FFDHE-4096 FFDHE-6144 FFDHE-8192

Grupos postcuánticos (híbridos):

ValorTipoDescripción
MLKEM768-X25519PQ HíbridoML-KEM-768 combinado con X25519
P256-MLKEM768PQ HíbridoML-KEM-768 combinado con NIST P-256
P384-MLKEM1024PQ HíbridoML-KEM-1024 combinado con NIST P-384
MLKEM1024-X448PQ HíbridoML-KEM-1024 combinado con X448

Grupos clásicos:

ValorTipoTamañoDescripción
X25519Curva Bernstein~128-bit seg.Curva moderna, rápida
X448Curva Goldilocks~224-bit seg.Curva moderna, alta seguridad
SECP256R1NIST P-256256 bitsCurva NIST estándar
SECP384R1NIST P-384384 bitsCurva NIST alta seguridad
SECP521R1NIST P-521521 bitsCurva NIST máxima seguridad
FFDHE-1024Finite Field DH1024 bitsGrupo DH heredado (solo LEGACY)
FFDHE-1536Finite Field DH1536 bitsGrupo DH (solo LEGACY)
FFDHE-2048Finite Field DH2048 bitsGrupo DH estandarizado (RFC 7919)
FFDHE-3072Finite Field DH3072 bitsGrupo DH estandarizado
FFDHE-4096Finite Field DH4096 bitsGrupo DH estandarizado
FFDHE-6144Finite Field DH6144 bitsGrupo DH estandarizado
FFDHE-8192Finite Field DH8192 bitsGrupo DH estandarizado

Nota sobre OpenSSL: El orden de los valores de group solo se respeta dentro de las “clases” PQ (postcuántico) y clásica. Todos los grupos PQ se ordenan automáticamente por encima de los clásicos. En el opensslcnf.config, el formato es Groups = *pq_group1:pq_group2/*classic_group1:classic_group2 donde * indica clases de grupos y / separa clases.

Nota sobre NSS: El orden de los valores de group es ignorado — NSS usa su orden interno incorporado.

Nota sobre FIPS y PQ: En la política FIPS, ML-KEM es soportado para grupos TLS pero deshabilitado por ámbito para OpenSSL (no soportado en el FIPS provider), Sequoia/RPM y parcialmente OpenSSH.

protocol — Versiones de Protocolo Permitidas

protocol = TLS1.3 TLS1.2 DTLS1.2 IKEv2
ValorDescripción
SSL3.0SSLv3 (eliminado de las bibliotecas — no puede habilitarse)
TLS1.0TLS 1.0
TLS1.1TLS 1.1
TLS1.2TLS 1.2
TLS1.3TLS 1.3
DTLS0.9DTLS 0.9
DTLS1.0DTLS 1.0
DTLS1.2DTLS 1.2
IKEv1IKE versión 1 (IPsec heredado)
IKEv2IKE versión 2 (IPsec moderno)

Limitación: Algunos back-ends (OpenSSL, NSS) no permiten deshabilitar versiones de protocolo selectivamente — usan la versión más antigua de la lista como límite inferior. Deshabilitar todas las versiones TLS y/o DTLS resulta en los valores predeterminados de la biblioteca siendo aplicados.

I.5.2 Parámetros Enteros

ParámetroDescripciónEjemploImpacto
min_rsa_sizeTamaño mínimo de clave RSA en bits2048Conexiones con claves RSA menores son rechazadas. Afecta a TODOS los back-ends.
min_dh_sizeTamaño mínimo de parámetros DH en bits2048Intercambio de claves DH con parámetros menores es rechazado.
min_dsa_sizeTamaño mínimo de clave DSA en bits2048Claves DSA menores son rechazadas.
min_ec_sizeTamaño mínimo de clave EC en bits256Se aplica solo al back-end Java/OpenJDK.

Cómo OpenSSL aplica tamaños mínimos: OpenSSL no tiene granularidad fina para tamaños mínimos — usa el mecanismo @SECLEVEL que define rangos de seguridad. min_rsa_size = 2048 corresponde a @SECLEVEL=2. min_rsa_size = 3072 corresponde a @SECLEVEL=3. Esto significa que no todos los valores arbitrarios son posibles.

SECLEVELRSA mínDH mínECC mínHash mínSeguridad
0000-Todo permitido
110241024160SHA-180 bits
220482048224SHA-224112 bits
330723072256SHA-256128 bits
476807680384SHA-384192 bits
51536015360512SHA-512256 bits

I.5.3 Parámetros Booleanos (0 o 1)

ParámetroDescripciónPredeterminado (DEFAULT)Impacto
sha1_in_certsPermite SHA-1 en firmas de certificados0Se aplica solo al back-end GnuTLS. Si 0, los certificados firmados con SHA-1 son rechazados en la validación de cadena.
arbitrary_dh_groupsPermite grupos DH arbitrarios (no estandarizados)0Si 0, solo se aceptan grupos FFDHE estandarizados (RFC 7919). Si 1, acepta parámetros DH arbitrarios generados por el servidor.
ssh_certsPermite autenticación por certificados OpenSSH1Si 0, deshabilita el mecanismo de certificados de OpenSSH (no confundir con certificados X.509).

I.5.4 Parámetros de Enumeración

ParámetroValoresDescripción
etmANY, DISABLE_ETM, DISABLE_NON_ETMControla Encrypt-then-MAC vs Encrypt-and-MAC. Implementado solo para SSH. Úselo con ámbito @SSH. ANY permite ambos. DISABLE_ETM fuerza Encrypt-and-MAC (E&M). DISABLE_NON_ETM fuerza Encrypt-then-MAC (EtM).
__emsDEFAULT, ENFORCE, RELAXInterno. Controla Extended Master Secret (RFC 7627). ENFORCE es usado por la política FIPS para forzar EMS. RELAX deshabilita el requisito (subpolítica NO-ENFORCE-EMS). Afecta a OpenSSL y GnuTLS. Ver sección I.14 para detalles.

I.5.5 Parámetros Obsoletos

Los siguientes parámetros aún funcionan pero deben ser migrados. El código fuente (preprocess_text en cryptopolicies.py) hace la conversión automáticamente y emite un FutureWarning:

ObsoletoConversión Automática ExactaMotivo
min_tls_version = TLS1.2protocol@TLS = -SSL2.0 -SSL3.0 -TLS1.0 -TLS1.1Sustituido por eliminación incremental
min_tls_version = TLS1.3protocol@TLS = -SSL2.0 -SSL3.0 -TLS1.0 -TLS1.1 -TLS1.2Ídem
min_dtls_version = DTLS1.2protocol@TLS = -DTLS0.9 -DTLS1.0Ídem
ike_protocol = IKEv2protocol@IKE = IKEv2Renombrado a ámbito
tls_cipher = ...cipher@TLS = ...Renombrado a ámbito
ssh_cipher = ...cipher@SSH = ...Renombrado a ámbito
ssh_group = ...group@SSH = ...Renombrado a ámbito
sha1_in_dnssec = 0hash@DNSSec = -SHA1 + sign@DNSSec = -RSA-SHA1 -ECDSA-SHA1Separación en dos parámetros
sha1_in_dnssec = 1hash@DNSSec = SHA1+ + sign@DNSSec = RSA-SHA1+ ECDSA-SHA1+Ídem
ssh_etm = 0etm@SSH = DISABLE_ETMRenombrado a enum
ssh_etm = 1etm@SSH = ANYÍdem
ssh_etm@<scope> = 0etm@<scope> = DISABLE_ETMSoporta ámbito

Además, el valor X25519-MLKEM768 se convierte automáticamente a MLKEM768-X25519 (renombramiento de algoritmo, RHEL-99813).

El parámetro protocol (sin ámbito) aún funciona pero emite warning — debe ser sustituido por protocol@TLS.


I.6 Diferencia Entre .pol y .pmod

Archivo .pol — Política Completa

  • Define todos los parámetros desde cero.
  • Se usa como política base.
  • Se aplica con update-crypto-policies --set MYPOLICY.
  • Debe contener valores para todas las opciones relevantes (en caso contrario, quedan vacías/predeterminadas de la biblioteca).
  • No evoluciona con actualizaciones del paquete crypto-policies — si Red Hat añade nuevos back-ends o parámetros, su política personalizada no los incluirá automáticamente.

Archivo .pmod — Subpolítica/Módulo Modificador

  • Modifica selectivamente una política base existente.
  • No necesita definir todos los parámetros — solo los que quiere alterar.
  • Se aplica con update-crypto-policies --set BASE:MYPOLICY.
  • Evoluciona con actualizaciones — como solo modifica la base, cuando la base se actualiza por el paquete, las modificaciones permanecen y se aplican sobre la nueva versión.
  • Múltiples módulos pueden apilarse: --set DEFAULT:MOD1:MOD2:MOD3.

Red Hat recomienda encarecidamente el uso de subpolíticas (.pmod) en vez de políticas completas (.pol) personalizadas. Esto garantiza que las actualizaciones de seguridad en las políticas base se propaguen automáticamente.

Mecanismo de Concatenación

Cuando la política efectiva es DEFAULT:NO-SHA1:MY-MODULE, el sistema concatena los archivos en este orden:

DEFAULT.pol + NO-SHA1.pmod + MY-MODULE.pmod

Cada directiva posterior sobrescribe o modifica la anterior. Si DEFAULT.pol define:

hash = SHA2-256 SHA2-384 SHA2-512 SHA1

Y NO-SHA1.pmod define:

hash = -SHA1
sign = -RSA-SHA1 -RSA-PSS-SHA1 -ECDSA-SHA1

La política efectiva resultante tendrá hash sin SHA1 y sign sin ningún algoritmo basado en SHA-1.


I.7 Creando Subpolíticas Personalizadas — Guía Paso a Paso

Ejemplo 1: Exigir Claves RSA de 4096 bits Mínimo

sudo tee /etc/crypto-policies/policies/modules/RSA-4096.pmod << 'EOF'
min_rsa_size = 4096
min_dh_size = 4096
EOF

sudo update-crypto-policies --set DEFAULT:RSA-4096

Efecto: Cualquier certificado con clave RSA menor que 4096 bits será rechazado. Cualquier intercambio de claves DH con parámetros menores que 4096 bits será rechazado. Esto es extremadamente restrictivo — la mayoría de los certificados comerciales usa 2048 o 4096 bits.

Ejemplo 2: Política para Entorno Solo TLS 1.3

sudo tee /etc/crypto-policies/policies/modules/TLS13-ONLY.pmod << 'EOF'
protocol@TLS = TLS1.3
protocol@!TLS = -TLS1.0 -TLS1.1
cipher@TLS = AES-256-GCM AES-128-GCM CHACHA20-POLY1305
key_exchange = ECDHE
EOF

sudo update-crypto-policies --set DEFAULT:TLS13-ONLY

Efecto: Solo TLS 1.3 está permitido para conexiones TLS. Solo cifras AEAD (las únicas que TLS 1.3 soporta). Intercambio de claves solo por ECDHE.

Ejemplo 3: Compatibilidad con Active Directory

sudo tee /etc/crypto-policies/policies/modules/AD-COMPAT.pmod << 'EOF'
cipher@Kerberos = +AES-128-CBC +AES-256-CBC +RC4-128
hash = SHA1 SHA2-256 SHA2-384 SHA2-512+
group = +FFDHE-1024
min_dh_size = 1024
sha1_in_certs = 1
EOF

sudo update-crypto-policies --set DEFAULT:AD-COMPAT

Efecto: Habilita ciphers necesarios para Kerberos con AD heredado, permite SHA-1 en certificados (necesario para DCs antiguos), acepta parámetros DH de 1024 bits.

Ejemplo 4: Seguridad Máxima para Entorno Financiero

sudo tee /etc/crypto-policies/policies/modules/FINANCE-SEC.pmod << 'EOF'
protocol@TLS = TLS1.3 TLS1.2
cipher = AES-256-GCM CHACHA20-POLY1305
cipher@SSH = AES-256-GCM AES-256-CTR CHACHA20-POLY1305
mac = HMAC-SHA2-256 HMAC-SHA2-384 HMAC-SHA2-512 AEAD
hash = SHA2-256 SHA2-384 SHA2-512
sign = RSA-PSS-SHA2-256 RSA-PSS-SHA2-384 RSA-PSS-SHA2-512 \
       ECDSA-SHA2-256 ECDSA-SHA2-384 ECDSA-SHA2-512 \
       EDDSA-ED25519 EDDSA-ED448
key_exchange = ECDHE DHE
group = X25519 X448 SECP384R1 SECP521R1 FFDHE-4096 FFDHE-8192
min_rsa_size = 4096
min_dh_size = 4096
sha1_in_certs = 0
arbitrary_dh_groups = 0
ssh_certs = 1
etm@SSH = DISABLE_NON_ETM
EOF

sudo update-crypto-policies --set FUTURE:FINANCE-SEC

Ejemplo 5: Módulo para Deshabilitar CBC en Todo

sudo tee /etc/crypto-policies/policies/modules/NO-CBC.pmod << 'EOF'
cipher = -AES-256-CBC -AES-128-CBC -CAMELLIA-256-CBC -CAMELLIA-128-CBC
EOF

sudo update-crypto-policies --set DEFAULT:NO-CBC

I.8 Creando una Política Completa (.pol) Desde Cero

Para escenarios donde ninguna política base satisface y las subpolíticas no son suficientes:

sudo cp /usr/share/crypto-policies/policies/DEFAULT.pol \
        /etc/crypto-policies/policies/MYORG.pol

sudo vi /etc/crypto-policies/policies/MYORG.pol

Ejemplo de política completa:

# /etc/crypto-policies/policies/MYORG.pol
# Política organizacional personalizada

# Protocolos permitidos
protocol = TLS1.3 TLS1.2 DTLS1.2 IKEv2

# Cifras simétricas
cipher = AES-256-GCM AES-128-GCM CHACHA20-POLY1305
cipher@Kerberos = AES-256-CBC AES-128-CBC+

# MACs
mac = HMAC-SHA2-256 HMAC-SHA2-384 HMAC-SHA2-512 AEAD UMAC-128
mac@SSH = HMAC-SHA2-256 HMAC-SHA2-512 AEAD UMAC-128

# Hashes
hash = SHA2-256 SHA2-384 SHA2-512

# Firmas
sign = ECDSA-SHA2-256 ECDSA-SHA2-384 ECDSA-SHA2-512 \
       RSA-PSS-SHA2-256 RSA-PSS-SHA2-384 RSA-PSS-SHA2-512 \
       RSA-SHA2-256 RSA-SHA2-384 RSA-SHA2-512 \
       EDDSA-ED25519 EDDSA-ED448

# Intercambio de claves
key_exchange = ECDHE DHE

# Grupos/Curvas
group = X25519 X448 SECP256R1 SECP384R1 SECP521R1 \
        FFDHE-3072 FFDHE-4096 FFDHE-6144 FFDHE-8192

# Tamaños mínimos de clave
min_rsa_size = 3072
min_dh_size = 3072
min_dsa_size = 3072

# Opciones booleanas
sha1_in_certs = 0
arbitrary_dh_groups = 0
ssh_certs = 1

Aplicar:

sudo update-crypto-policies --set MYORG

Atención: Con una política .pol personalizada, las actualizaciones futuras del paquete crypto-policies que mejoren la política DEFAULT no se propagarán a MYORG. Usted es responsable de mantener su política actualizada.


I.9 El Mecanismo local.d — Overrides Por Back-end

El directorio /etc/crypto-policies/local.d/ permite añadir configuración extra que se concatena al final del archivo de back-end generado. Esto NO modifica la política — modifica directamente el archivo de configuración de la biblioteca.

# Ejemplo: Añadir configuración extra a OpenSSL
sudo tee /etc/crypto-policies/local.d/opensslcnf-extra.config << 'EOF'
# Configuración extra concatenada al opensslcnf.config
# (Formato de configuración OpenSSL, no formato de política)
EOF

Convención de nombres: El archivo debe seguir el patrón <backend>-<sufijo>.config, donde <backend> corresponde al nombre del back-end (sin la extensión .config).

Uso recomendado: Situaciones extremas donde la política no ofrece el control necesario sobre un back-end específico. Este es un mecanismo de último recurso — prefiera subpolíticas.


I.10 Cómo Cada Back-end Consume la Política

OpenSSL (OpenSSLGenerator + OpenSSLFIPSGenerator)

El generador crea dos archivos: opensslcnf.config (configuración general) y openssl_fips.config (configuración del módulo FIPS). OpenSSL lee /etc/crypto-policies/back-ends/opensslcnf.config durante la inicialización vía la directiva .include en el archivo openssl.cnf principal. Los ámbitos aplicados son {'tls', 'ssl', 'openssl'}.

Traducción de parámetros:

Parámetro de PolíticaConfiguración OpenSSL
cipherCiphersuites (TLS 1.3) y CipherString (TLS 1.2)
min_rsa_size, min_dh_size@SECLEVEL=N al inicio de CipherString
protocolTLS.MinProtocol, TLS.MaxProtocol, DTLS.MinProtocol, DTLS.MaxProtocol
groupGroups (PQ y clásico separados por /)
signSignatureAlgorithms (con prefijo ? para tolerancia a algoritmos desconocidos)
__emsOptions = RHNoEnforceEMSinFIPS si RELAX
__openssl_block_sha1_signaturesrh-allow-sha1-signatures = yes/no
min_rsa_sizedefault_bits en la sección [req] (mínimo 2048)

Irregularidades OpenSSL:

  1. La lista de ciphers TLS 1.2 (CipherString) se genera por sustracción — comienza listando los key_exchange habilitados, después elimina los ciphers, key exchanges y MACs de la lista de deshabilitados. Esto difiere del modelo de allowlist usado por GnuTLS.
  2. La CipherString siempre excluye -SHA384, -CAMELLIA, -ARIA, -AESCCM8 y -CBC (cuando todos los CBC están deshabilitados) por hardcoding en el generador.
  3. Para deshabilitar ciphers CCM, tanto AES-128-CCM como AES-256-CCM necesitan ser eliminados; el generador usa la keyword -AESCCM.
  4. Todos los SignatureAlgorithms se prefijan con ? (?RSA+SHA256) para que OpenSSL tolere algoritmos que no conoce (ej: postcuánticos en versiones antiguas).

GnuTLS (GnuTLSGenerator)

El generador crea un archivo de configuración en modo allowlist (ya no priority strings como en versiones antiguas). Los ámbitos aplicados son {'tls', 'ssl', 'gnutls'}. La configuración se lee de /etc/crypto-policies/back-ends/gnutls.config vía la variable GNUTLS_SYSTEM_PRIORITY_FILE (o la ruta predeterminada compilada).

Traducción:

Parámetro de PolíticaConfiguración GnuTLS
ciphertls-enabled-cipher = AES-256-GCM, etc.
mactls-enabled-mac = AEAD, tls-enabled-mac = SHA512
hashsecure-hash = SHA256, etc.
signsecure-sig = RSA-SHA256 + secure-sig-for-cert = RSA-SHA256
sha1_in_certssecure-sig-for-cert = rsa-sha1/dsa-sha1/ecdsa-sha1 adicionales
grouptls-enabled-group = GROUP-X25519 + enabled-curve = X25519
key_exchangetls-enabled-kx = ECDHE-RSA, tls-enabled-kx = ECDHE-ECDSA
protocolenabled-version = TLS1.3, etc.
min_rsa_size, min_dh_sizemin-verification-profile
__emstls-session-hash = require/request

Irregularidades GnuTLS:

  1. sha1_in_certs es el único back-end que respeta este parámetro directamente (añadiendo SHA-1 solo a secure-sig-for-cert).
  2. HMAC-SHA2-256 y HMAC-SHA2-384 como MACs standalone están mapeados a None en el código y por tanto nunca se habilitan, por preocupaciones de vulnerabilidad a Lucky13 (ver GnuTLS issue #503). Solo AEAD y HMAC-SHA2-512 funcionan.
  3. Los PSK key exchanges (PSK, DHE-PSK, ECDHE-PSK, RSA-PSK) están comentados en el generador y por tanto nunca se habilitan vía crypto-policies, aunque la política los liste.
  4. El ECDHE key exchange se expande en dos tipos kex: ECDHE-RSA y ECDHE-ECDSA en el generador.
  5. Las curvas necesitan habilitarse por separado de los grupos. El generador extrae las curvas de los grupos y de las firmas (ej: EdDSA-Ed25519 → enabled-curve = Ed25519).

NSS (Network Security Services)

El generador crea un archivo de política NSS en /etc/crypto-policies/back-ends/nss.config.

Irregularidades NSS:

  1. El orden de group es ignorado — NSS usa su orden interno.
  2. Es el único back-end que respeta los ámbitos pkcs12, pkcs12-import, smime y smime-import.
  3. pkcs12 implica pkcs12-import — no es posible permitir exportación sin permitir importación.
  4. Esos ámbitos no pueden habilitar algoritmos de firma que no fueron habilitados en la configuración general.
  5. Deshabilitar todas las versiones TLS/DTLS resulta en los valores predeterminados de la biblioteca.

OpenSSH (OpenSSHClientGenerator + OpenSSHServerGenerator)

El generador crea dos archivos separados con ámbitos diferentes:

  • Cliente: openssh.config — ámbitos {'ssh', 'openssh', 'openssh-client'}
  • Servidor: opensshserver.config — ámbitos {'ssh', 'openssh', 'openssh-server'}

Traducción:

Parámetro de PolíticaConfiguración OpenSSH
cipher@SSHCiphers
mac@SSH + etmMACs (EtM y no-EtM en orden según enum etm)
key_exchange × group × hashKexAlgorithms (producto cartesiano filtrado por la tabla kx_map)
key_exchange × hash + arbitrary_dh_groupsKexAlgorithms vía gx_map (group exchange)
signPubkeyAcceptedAlgorithms, HostbasedAcceptedAlgorithms, CASignatureAlgorithms
sign (servidor)HostKeyAlgorithms (solo servidor)
ssh_certs + signSufijos -cert-v01@openssh.com añadidos a PubkeyAcceptedAlgorithms
min_rsa_sizeRequiredRSASize (si > 0)
key_exchange (GSS)GSSAPIKexAlgorithms o GSSAPIKeyExchange no

Irregularidades OpenSSH:

  1. DH group 1 (1024 bits) es siempre eliminado en el servidor, aunque la política permita DH de 1024 bits. El código del servidor explícitamente hace del local_kx_map[('DHE', 'FFDHE-1024', 'SHA1')].
  2. HostKeyAlgorithms se define solo para el servidor. Configurarlo en el cliente rompería el manejo de entradas known_hosts existentes.
  3. El KexAlgorithms se construye mediante un producto cartesiano de (key_exchange, group, hash), filtrado contra la tabla kx_map. Solo las combinaciones con mapeo definido producen salida.
  4. GSSAPIKeyExchange no se emite si ningún GSS kex es habilitado por la política.
  5. CASignatureAlgorithms no incluye variantes de certificado, solo algoritmos base.
  6. Cuando ssh_certs = 1, el generador añade certificados incluyendo el nuevo ssh-mldsa44-ed25519@openssh.com (postcuántico).
  7. El comando de recarga del servidor es systemctl try-restart sshd.service (restart, no reload, porque systemd necesita releer opciones de línea de comando).

Libreswan (IPsec/IKE)

Irregularidades Libreswan:

  1. El parámetro key_exchange no afecta la configuración generada para Libreswan.
  2. Para controlar DH vs ECDH en IPsec, use el parámetro group.

Kerberos (MIT krb5)

El generador crea /etc/crypto-policies/back-ends/krb5.config con la lista permitted_enctypes.

Traducción: Los ciphers se mapean a enctypes Kerberos (aes256-cts-hmac-sha384-192, aes128-cts-hmac-sha256-128, etc.).

Java/OpenJDK

El generador crea /etc/crypto-policies/back-ends/java.config que configura las Java Security Properties.

Nota: El parámetro min_ec_size se aplica solo al back-end Java.


I.11 Algoritmos Eliminados vs Deshabilitados

Hay una distinción fundamental entre algoritmos eliminados de las bibliotecas y algoritmos deshabilitados por las políticas:

Eliminados Completamente de las Bibliotecas Core

Estos algoritmos fueron eliminados del código fuente de las bibliotecas criptográficas y no pueden habilitarse por ninguna política, ni siquiera LEGACY:

Algoritmo/ProtocoloMotivo
DES (no 3DES)Completamente inseguro (56 bits)
Export-grade cipher suitesInseguros por diseño
MD5 en firmasColisiones demostradas
SSLv2Múltiples vulnerabilidades fatales
SSLv3Vulnerable a POODLE
Curvas ECC < 224 bitsInseguras
Curvas ECC de campo binarioNo estandarizadas / sospechosas

Deshabilitados en TODAS las Políticas Predefinidas (pero disponibles)

Estos algoritmos existen en las bibliotecas pero están deshabilitados en todas las políticas. Una política personalizada .pol podría habilitarlos (no recomendado):

Algoritmo/ProtocoloRiesgo
DH con parámetros < 1024 bitsAtaque Logjam
RSA con clave < 1024 bitsFactorizable con hardware moderno
CamelliaNo ampliamente probado
RC4Múltiples sesgos conocidos
ARIAUso limitado, poca auditoría
SEEDUso limitado fuera de Corea
IDEAObsoleto
Ciphersuites de solo integridadSin cifrado
TLS CBC con HMAC SHA-384Implementaciones problemáticas
AES-CCM8 (tag corto)Tag de autenticación insuficiente
Curvas ECC incompatibles con TLS 1.3 (incluida secp256k1)Fuera del estándar TLS 1.3
IKEv1Sustituido por IKEv2

I.12 Aplicaciones y Bibliotecas NO Cubiertas

Las crypto-policies cubren solo datos en tránsito (data-in-transit). Las siguientes situaciones no están controladas:

No CubiertoMotivo
Aplicaciones GoEl runtime Go no lee las crypto-policies del sistema
GnuPG-2Usa su propio sistema de configuración
Datos en reposo (disk encryption)LUKS, dm-crypt tienen configuración independiente
Ubicaciones de certificadosGestionado por cada servicio individualmente
CA trust storeGestionado por update-ca-trust, no por crypto-policies
Emisión de certificadosNo controlado (CA/certmonger/certbot)
Aplicaciones que fuerzan sus propias configuracionesSi la app define ciphers explícitamente en el código, la política del sistema se ignora

I.13 Jerarquía de Ámbitos — Visión del Código Fuente

El código fuente (cryptopolicies.py) define una jerarquía de ámbitos donde cada back-end recibe un conjunto de ámbitos y opcionalmente hereda de un ámbito padre. La siguiente tabla muestra exactamente qué ámbitos se aplican para cada back-end al generar su configuración:

Back-end (volcable)Ámbito padreConjunto de ámbitos aplicados
bind—bind, dnssec
gnutls—gnutls, tls, ssl
java-tls—java-tls, tls, ssl
krb5—krb5, kerberos
libreswan—ipsec, ike, libreswan
libssh—libssh, ssh
nss—nss
nss-tlsnssnss, nss-tls, tls, ssl
nss-pkcs12nssnss, pkcs12, nss-pkcs12
nss-pkcs12-importnss-pkcs12nss, pkcs12, pkcs12-import, nss-pkcs12, nss-pkcs12-import
nss-smimenssnss, smime, nss-smime
nss-smime-importnss-smimenss, smime, smime-import, nss-smime, nss-smime-import
openssh—openssh, ssh
openssh-clientopensshopenssh-client, openssh, ssh
openssh-serveropensshopenssh-server, openssh, ssh
openssl—openssl, tls, ssl
sequoia—sequoia
rpm—rpm, rpm-sequoia

Cómo funciona: Cuando el generador del servidor OpenSSH solicita la configuración, pasa el conjunto {'ssh', 'openssh', 'openssh-server'} al ScopedPolicy. Cada directiva en la política se evalúa contra esos ámbitos: cipher@SSH coincide (porque ssh está en el conjunto), cipher@TLS no coincide, cipher@!SSH no coincide. La directiva cipher@{SSH,TLS} coincidiría porque ssh está en el conjunto.

Herencia padre-hijo: Cuando el volcado de la política se genera para CURRENT.pol, el sistema muestra propiedades específicas de ámbito solo si difieren del ámbito padre. Por ejemplo, cipher@openssh-server solo aparece si difiere de cipher@openssh.


I.14 Parámetros Internos (No Documentados Públicamente)

El código fuente define parámetros con prefijo __ (double underscore) que se usan internamente por las políticas proporcionadas por el sistema. Estos parámetros no están documentados en la man page y no deben usarse en políticas personalizadas, pero entenderlos es importante para comprender el comportamiento real:

__openssl_block_sha1_signatures

INT_DEFAULTS = {
    ...
    '__openssl_block_sha1_signatures': 1,
}

Controla si OpenSSL bloquea la verificación de firmas SHA-1. Valor predeterminado 1 (bloquear). En el generador de OpenSSL, esto se traduce a la directiva rh-allow-sha1-signatures = yes/no en la sección [evp_properties] del opensslcnf.config. Esta es una extensión específica de Red Hat de OpenSSL, no presente en el OpenSSL upstream.

La política LEGACY define __openssl_block_sha1_signatures = 0, permitiendo la verificación de firmas SHA-1 en OpenSSL. Todas las demás políticas mantienen el valor 1.

__ems (Extended Master Secret)

ENUMS = {
    'etm': ('ANY', 'DISABLE_ETM', 'DISABLE_NON_ETM'),
    '__ems': ('DEFAULT', 'ENFORCE', 'RELAX'),
}

Controla el requisito de Extended Master Secret (RFC 7627) en TLS. Tres valores posibles:

ValorEfecto en OpenSSLEfecto en GnuTLS
DEFAULTSin acción (biblioteca decide)Sin acción (tls-session-hash no configurado)
ENFORCESin acción (FIPS ya fuerza)tls-session-hash = require
RELAXOptions = RHNoEnforceEMSinFIPS + config FIPS con tls1-prf-ems-check = 0tls-session-hash = request

La política FIPS define __ems = ENFORCE. La subpolítica NO-ENFORCE-EMS define __ems = RELAX.

El generador OpenSSL también crea un archivo separado openssl_fips.config que configura el módulo FIPS de OpenSSL:

[fips_sect]
tls1-prf-ems-check = 1  # o 0 si __ems == RELAX
activate = 1

I.15 Algoritmos Postcuánticos en el Código Fuente

El código fuente (alg_lists.py) ya define listas extensas de algoritmos postcuánticos, marcados como experimentales:

Grupos (Key Encapsulation — ML-KEM)

Los siguientes grupos postcuánticos están definidos en las políticas actuales (DEFAULT, FUTURE, FIPS, LEGACY):

GrupoTipoDescripción
MLKEM768-X25519HíbridoML-KEM-768 con X25519 (estándar NIST + clásico)
P256-MLKEM768HíbridoML-KEM-768 con NIST P-256
P384-MLKEM1024HíbridoML-KEM-1024 con NIST P-384
MLKEM1024-X448HíbridoML-KEM-1024 con X448

Grupos marcados como experimentales (presentes en el código pero no en las políticas estándar):

GrupoEstado
MLKEM512, X25519-MLKEM512, P256-MLKEM512Experimentales
MLKEM768, X448-MLKEM768Experimentales (variantes solo/alternativas)
MLKEM1024, P521-MLKEM1024Experimentales

Firmas (ML-DSA, FALCON, SPHINCS+, SLH-DSA)

Firmas postcuánticas en las políticas estándar:

AlgoritmoPresente en DEFAULTPresente en FIPS
MLDSA44 (ML-DSA-44)SíSí
MLDSA65 (ML-DSA-65)SíSí
MLDSA87 (ML-DSA-87)SíSí

Firmas experimentales en el código (no en las políticas estándar):

P256-MLDSA44, RSA3072-MLDSA44, MLDSA44-PSS2048, MLDSA44-RSA2048,
MLDSA44-ED25519, MLDSA44-P256, MLDSA44-BP256,
P384-MLDSA65, MLDSA65-PSS3072, MLDSA65-RSA3072,
FALCON512, FALCONPADDED512, FALCON1024, FALCONPADDED1024,
SPHINCSSHA2128FSIMPLE, SPHINCSSHA2128SSIMPLE, SPHINCSSHAKE128FSIMPLE,
... y más variantes híbridas

Firmas PQ para OpenPGP (Sequoia/RPM), añadidas con sign@{sequoia,RPM} en todas las políticas estándar:

MLDSA65-ED25519, MLDSA87-ED448,
SLHDSA-SHAKE-128S, SLHDSA-SHAKE-128F, SLHDSA-SHAKE-256S

Cómo OpenSSL gestiona grupos PQ: El generador de OpenSSL separa los grupos en dos clases — PQ y clásica — y los formatea como *pq_groups/classic_groups en la directiva Groups. Esto hace que los servidores prefieran cualquier grupo PQ sobre cualquier grupo clásico cuando ambos son soportados, y los clientes envíen key shares para el grupo PQ de mayor prioridad Y el grupo clásico de mayor prioridad.


I.16 FIPS Auto-Bind-Mount — El Mecanismo de Arranque

Cuando el kernel se inicia con fips=1, un módulo dracut y/o un servicio systemd automáticamente hacen bind-mount de:

/usr/share/crypto-policies/back-ends/FIPS/  →  /etc/crypto-policies/back-ends/
/usr/share/crypto-policies/default-fips-config  →  /etc/crypto-policies/config

Esto garantiza que la política FIPS esté activa desde el primer momento del arranque, antes incluso de que update-crypto-policies pueda ejecutarse.

El script update-crypto-policies.py detecta esta situación verificando /proc/self/mountinfo:

is_fips_auto_bind_mounted():
  Verifica si /etc/crypto-policies/config está montado desde
  .../crypto-policies/default-fips-config
  Y si /etc/crypto-policies/back-ends está montado desde
  .../crypto-policies/back-ends/FIPS

Comportamiento cuando el auto-bind está activo:

  • --show: Funciona normalmente (lee el contenido montado).
  • --set FIPS:SUBPOLICY: Desmonta los bind-mounts con umount y entonces aplica la nueva política con la subpolítica. Esto permite personalizar FIPS con subpolíticas.
  • --set DEFAULT (u otra no-FIPS): Emite aviso de que el sistema ya no será FIPS-compliant, desmonta y aplica.
  • Sin --set: Avisa que los archivos en local.d/ serán ignorados mientras el auto-bind esté activo.

Implicación práctica: Si necesita FIPS con una subpolítica (ej: FIPS:NO-ENFORCE-EMS), ejecute update-crypto-policies --set FIPS:NO-ENFORCE-EMS — esto elimina el bind-mount automático y aplica una política FIPS personalizada persistente.


I.17 Lo Que Cada Política Realmente Define — Anotación del Código Fuente

Las siguientes anotaciones se extraen directamente de los archivos .pol del repositorio upstream.

DEFAULT.pol — Anotaciones

# Seguridad de 112 bits con excepción de SHA-1 en DNSSec

# Incluye ML-KEM y ML-DSA (postcuánticos) en los primeros lugares de las listas
group = MLKEM768-X25519 P256-MLKEM768 P384-MLKEM1024 MLKEM1024-X448 \
        X25519 SECP256R1 X448 SECP521R1 SECP384R1 \
        FFDHE-2048 FFDHE-3072 FFDHE-4096 FFDHE-6144 FFDHE-8192

# SHA-1 y DSA-SHA1 permitidos solo en DNSSec y RPM (por ámbito)
hash@DNSSec = SHA1+
sign@DNSSec = RSA-SHA1+ ECDSA-SHA1+
sign@RPM = DSA-SHA1+
hash@RPM = SHA1+
min_dsa_size@RPM = 1024   # RPM necesita aceptar paquetes antiguos con DSA 1024

# CBC deshabilitado en SSH por ámbito (vulnerable a plaintext recovery)
cipher@SSH = -*-CBC

# RSA está ANTES de DHE en key_exchange por cuestión de interoperabilidad
key_exchange = KEM-ECDH ECDHE RSA DHE DHE-RSA PSK DHE-PSK ECDHE-PSK RSA-PSK \
               ECDHE-GSS DHE-GSS

# arbitrary_dh_groups = 1 → acepta parámetros DH del servidor
# (necesario para compatibilidad con servidores que no usan FFDHE)
arbitrary_dh_groups = 1

FUTURE.pol — Diferencias Respecto a DEFAULT

# Seguridad de 128 bits — preparación para postcuántico

# HMAC-SHA1 ELIMINADO de la lista de MACs
mac = AEAD HMAC-SHA2-256 UMAC-128 HMAC-SHA2-384 HMAC-SHA2-512
# (DEFAULT incluye HMAC-SHA1)

# SHA2-224 y SHA3-224 ELIMINADOS de hash
hash = SHA2-256 SHA2-384 SHA2-512 SHA3-256 SHA3-384 SHA3-512 SHAKE-256

# Sin SHA-1 en NINGÚN ámbito (sin excepción para DNSSec)
# SHA-224 ELIMINADO de sign
# RSA ELIMINADO de key_exchange (sin intercambio de clave RSA estático)
key_exchange = KEM-ECDH ECDHE DHE DHE-RSA PSK DHE-PSK ECDHE-PSK ECDHE-GSS DHE-GSS

# Solo cifras de 256 bits y AEAD en TLS
cipher@TLS = AES-256-GCM AES-256-CCM CHACHA20-POLY1305

# FFDHE-2048 ELIMINADO (mínimo 3072)
group = ... FFDHE-3072 FFDHE-4096 FFDHE-6144 FFDHE-8192

# Tamaños mínimos aumentados
min_dh_size = 3072
min_dsa_size = 3072
min_rsa_size = 3072

LEGACY.pol — Diferencias Respecto a DEFAULT

# Seguridad de 64 bits — máxima compatibilidad

# SHA1 incluido en hash (para uso general, no solo DNSSec)
hash = ... SHA1

# DSA y SHA-1 PERMITIDOS en firmas
sign = ... DSA-SHA2-256 DSA-SHA2-384 DSA-SHA2-512 DSA-SHA2-224 \
       ECDSA-SHA1 RSA-PSS-SHA1 RSA-SHA1 DSA-SHA1

# 3DES-CBC habilitado en cipher y cipher@TLS
cipher = ... 3DES-CBC
cipher@TLS = ... 3DES-CBC

# CBC HABILITADO en SSH (diferente de DEFAULT/FUTURE/FIPS)
cipher@SSH = AES-256-GCM CHACHA20-POLY1305 AES-256-CTR AES-256-CBC \
    AES-128-GCM AES-128-CTR AES-128-CBC 3DES-CBC

# DHE-DSS habilitado, FFDHE-1536 incluido, FFDHE-1024 para SSH
group@SSH = FFDHE-1024+
key_exchange = ... DHE-DSS ...

# TLS 1.0 y 1.1 habilitados, DTLS 1.0 habilitado
protocol@TLS = TLS1.3 TLS1.2 TLS1.1 TLS1.0 DTLS1.2 DTLS1.0

# Tamaños mínimos reducidos
min_dh_size = 1024
min_dsa_size = 1024
min_rsa_size = 1024

# SHA-1 permitido en certificados (GnuTLS)
sha1_in_certs = 1

# OpenSSL NO bloquea firmas SHA-1
__openssl_block_sha1_signatures = 0

# PKCS#12 acepta DES, RC4, RC2, SEED (heredado extremo)
cipher@pkcs12 = AES-256-CBC AES-192-CBC AES-128-CBC \
    CAMELLIA-256-CBC ... 3DES-CBC DES-CBC RC4-128 DES40-CBC RC2-CBC SEED-CBC

FIPS.pol — Diferencias Respecto a DEFAULT

# Conformidad FIPS 140 — NO garantiza FIPS por sí solo

# Sin CHACHA20-POLY1305 (no aprobado FIPS)
cipher@TLS = AES-256-GCM AES-256-CCM AES-256-CBC \
    AES-128-GCM AES-128-CCM AES-128-CBC

# Sin X25519 y X448 en los grupos (no aprobados FIPS como curvas standalone)
# ML-KEM bloqueado para OpenSSL (no soportado en el FIPS provider aún)
# ML-KEM bloqueado para Sequoia/RPM
group@openssl = +P256-MLKEM768  # despriorizar X25519-MLKEM768
group@{sequoia,rpm} = -MLKEM768-X25519 -P256-MLKEM768 -P384-MLKEM1024
group@openssh = -MLKEM768-X25519

# Sin EdDSA, sin FIDO, sin SHA-224 en firmas
# Sin variantes RSA-PSS-RSAE SHA3

# PSK sin RSA-PSK (no aprobado)
key_exchange = KEM-ECDH ECDHE DHE DHE-RSA PSK DHE-PSK ECDHE-PSK

# Extended Master Secret obligatorio
__ems = ENFORCE

I.18 Mapeo de Algoritmos en los Generadores — Tablas del Código Fuente

OpenSSH: Mapeo de Cifras

El generador openssh.py mapea nombres genéricos de cifras a los nombres usados por OpenSSH:

PolíticaOpenSSH
AES-256-GCMaes256-gcm@openssh.com
AES-256-CTRaes256-ctr
AES-128-GCMaes128-gcm@openssh.com
AES-128-CTRaes128-ctr
CHACHA20-POLY1305chacha20-poly1305@openssh.com
AES-256-CBCaes256-cbc
AES-128-CBCaes128-cbc
3DES-CBC3des-cbc
AES-256-CCM(no soportado)
CAMELLIA-*(no soportado)

Las cifras sin mapeo en OpenSSH se ignoran silenciosamente.

OpenSSH: Mapeo de Key Exchange

El generador construye la lista KexAlgorithms a partir de combinaciones (key_exchange, group, hash):

Combinación (key_exchange, group, hash)KexAlgorithm SSH
ECDHE, X25519, SHA2-256curve25519-sha256, curve25519-sha256@libssh.org
ECDHE, SECP256R1, SHA2-256ecdh-sha2-nistp256
ECDHE, SECP384R1, SHA2-384ecdh-sha2-nistp384
ECDHE, SECP521R1, SHA2-512ecdh-sha2-nistp521
DHE, FFDHE-2048, SHA2-256diffie-hellman-group14-sha256
DHE, FFDHE-4096, SHA2-512diffie-hellman-group16-sha512
DHE, FFDHE-8192, SHA2-512diffie-hellman-group18-sha512
KEM-ECDH, MLKEM768-X25519, SHA2-256mlkem768x25519-sha256
KEM-ECDH, P256-MLKEM768, SHA2-256mlkem768nistp256-sha256
KEM-ECDH, P384-MLKEM1024, SHA2-384mlkem1024nistp384-sha384

El servidor siempre elimina ('DHE', 'FFDHE-1024', 'SHA1') (diffie-hellman-group1-sha1), aunque la política lo permita.

OpenSSL: Mecanismo de SECLEVEL

El generador de OpenSSL (openssl.py) determina el @SECLEVEL directamente de los parámetros min_dh_size y min_rsa_size:

if min_dh_size < 1023 or min_rsa_size < 1023:
    s = '@SECLEVEL=0'
elif min_dh_size < 2048 or min_rsa_size < 2048:
    s = '@SECLEVEL=1'
elif min_dh_size < 3072 or min_rsa_size < 3072:
    s = '@SECLEVEL=2'
else:
    s = '@SECLEVEL=3'

Esto significa que si min_rsa_size = 2048 y min_dh_size = 2048, OpenSSL recibirá @SECLEVEL=2. No hay forma de definir un valor intermedio (ej: RSA 2048 pero DH 3072 resultaría en SECLEVEL=2 por causa del RSA).

OpenSSL: Generación de Ciphers TLS 1.3

El generador construye la directiva Ciphersuites (TLS 1.3) por separado de la CipherString (TLS 1.2). Para TLS 1.3, existe un mapeo directo:

CiphersuiteRequiere cipherRequiere hash
TLS_AES_256_GCM_SHA384AES-256-GCMSHA2-384
TLS_AES_128_GCM_SHA256AES-128-GCMSHA2-256
TLS_CHACHA20_POLY1305_SHA256CHACHA20-POLY1305SHA2-256
TLS_AES_128_CCM_SHA256AES-128-CCMSHA2-256

OpenSSL: SHA-1 y la Sección rh-allow-sha1-signatures

El generador siempre añade una sección especial al opensslcnf.config:

[openssl_init]
alg_section = evp_properties

[evp_properties]
rh-allow-sha1-signatures = no   # o yes para LEGACY

Esta es una extensión Red Hat que controla si OpenSSL acepta verificar firmas basadas en SHA-1. La lógica en el código es:

sha1_sig = not policy.integers['__openssl_block_sha1_signatures']
s += RH_SHA1_SECTION.format('yes' if sha1_sig else 'no')

Solo la política LEGACY define __openssl_block_sha1_signatures = 0.

GnuTLS: Modo Allowlist

El generador de GnuTLS (gnutls.py) genera configuración en modo allowlist (lista blanca):

[global]
override-mode = allowlist

[overrides]
secure-hash = SHA256
secure-hash = SHA384
...
tls-enabled-mac = AEAD
tls-enabled-mac = SHA512
...
tls-enabled-group = GROUP-X25519
tls-enabled-group = GROUP-SECP256R1
...
secure-sig = RSA-SHA256
secure-sig = ECDSA-SHA256
...
secure-sig-for-cert = RSA-SHA256
...
enabled-curve = X25519
enabled-curve = SECP256R1
...
tls-enabled-cipher = AES-256-GCM
...
tls-enabled-kx = ECDHE-RSA
tls-enabled-kx = ECDHE-ECDSA
...
enabled-version = TLS1.3
enabled-version = TLS1.2
...
min-verification-profile = medium   # o high, ultra, etc.

[priorities]
SYSTEM=NONE

El min-verification-profile se deriva de los tamaños mínimos de clave:

min_dh_size / min_rsa_sizeProfile
≤ 768very_weak
≤ 1024low
≤ 2048medium
≤ 3072high
≤ 8192ultra
> 8192future

Cuando sha1_in_certs = 1, el generador añade explícitamente:

secure-sig-for-cert = rsa-sha1
secure-sig-for-cert = dsa-sha1
secure-sig-for-cert = ecdsa-sha1

GnuTLS: MACs Deshabilitados por Seguridad

El mac_map de GnuTLS mapea HMAC-SHA2-256 y HMAC-SHA2-384 a None:

mac_map = {
    'HMAC-SHA2-256': None,  # not allowlisted over concerns that
    'HMAC-SHA2-384': None,  # implementation might be vulnerable to Lucky13
    'HMAC-SHA2-512': 'SHA512',
}

Esto significa que aunque la política habilite HMAC-SHA2-256, GnuTLS no lo activará como MAC standalone. Solo HMAC-SHA2-512 y AEAD funcionan como MACs TLS en GnuTLS. La referencia en el código apunta a GnuTLS issue #503.


I.19 Validación en el Generador — Pruebas Automáticas de Configuración

Cada generador contiene un método test_config() que valida la configuración generada ejecutando el binario real de la biblioteca. Esto ocurre durante el update-crypto-policies:

GeneradorComando de PruebaQué Valida
OpenSSLGeneratoropenssl ciphers <CipherString>Verifica si la CipherString es válida y no contiene ADH
GnuTLSGeneratorgnutls-cli -l (con GNUTLS_SYSTEM_PRIORITY_FILE apuntando al config)Verifica si la priority string es válida
OpenSSHClientGeneratorssh -G -F <config> bogus_serverVerifica si las opciones SSH son válidas
OpenSSHServerGeneratorsshd -T -h <hostkey> -f <config>Genera una host key RSA 3072 temporal y prueba sshd

Si el binario de la biblioteca no está instalado, la prueba se omite silenciosamente. Las variables de entorno OLD_OPENSSH=1 y OLD_GNUTLS=1 también omiten las pruebas (para compatibilidad con versiones antiguas durante builds).


El script update-crypto-policies.py usa escritura atómica para evitar corrupción:

  1. Crea un archivo temporal con mkstemp() en el directorio destino.
  2. Escribe el contenido, hace fsync(), define permisos 0o644.
  3. Hace os.rename() del temporal al nombre final (operación atómica en el mismo filesystem).

Optimización de symlinks: Si la política no tiene subpolíticas Y no existen archivos en local.d/, el script crea un symlink de /etc/crypto-policies/back-ends/<backend>.config a /usr/share/crypto-policies/<POLICY>/<backend>.txt en vez de copiar el contenido. Esto ahorra espacio y permite que las actualizaciones del paquete se propaguen automáticamente para políticas simples (sin módulos).

Si existen archivos local.d/, el symlink no puede usarse porque el contenido necesita concatenarse. En ese caso, el archivo se escribe directamente y el contenido de local.d/ se añade al final.


I.21 Verificación y Diagnóstico de la Política Efectiva

Comandos de Verificación

# Política activa (nombre)
update-crypto-policies --show

# Verificar si la política está realmente aplicada
# (compara timestamps y contenido de state/current vs config,
#  y verifica si no hay FIPS auto-bind-mount activo)
update-crypto-policies --is-applied

# Verificar si los archivos generados corresponden a la política configurada
# (regenera en directorio temporal y compara byte a byte)
update-crypto-policies --check

# Política efectiva expandida (resultado de la concatenación base + submódulos)
cat /etc/crypto-policies/state/CURRENT.pol

# Contenido del archivo de config de cada back-end
cat /etc/crypto-policies/back-ends/opensslcnf.config
cat /etc/crypto-policies/back-ends/gnutls.config
cat /etc/crypto-policies/back-ends/nss.config
cat /etc/crypto-policies/back-ends/openssh.config
cat /etc/crypto-policies/back-ends/opensshserver.config

# Fecha del último cambio de política
ls -l /etc/crypto-policies/back-ends/
ls -l /etc/crypto-policies/config

# Ciphers disponibles en OpenSSL bajo la política actual
openssl ciphers -v

# Probar conexión TLS real y verificar cipher negociado
openssl s_client -connect localhost:443

# Verificar si algún servicio está sobrescribiendo la política
grep -r "SSLProtocol\|SSLCipherSuite" /etc/httpd/ 2>/dev/null
grep -r "ssl_protocols\|ssl_ciphers" /etc/nginx/ 2>/dev/null

Validando una Subpolítica Antes de Aplicar

# Verificar sintaxis — update-crypto-policies reportará errores
sudo update-crypto-policies --set DEFAULT:MY-NEW-MODULE 2>&1

# Si hay error de sintaxis, la salida indicará el problema

# Comparar back-ends antes/después
diff <(cat /etc/crypto-policies/back-ends/opensslcnf.config) \
     <(sudo update-crypto-policies --set DEFAULT:MY-NEW-MODULE && \
       cat /etc/crypto-policies/back-ends/opensslcnf.config)

# Verificar la política efectiva expandida
cat /etc/crypto-policies/state/CURRENT.pol

I.22 Diferencias Entre Versiones de RHEL

AspectoRHEL 8RHEL 9RHEL 10
OpenSSL1.1.13.0.x / 3.2.x3.x
Subpolíticas .pmodIntroducidas en RHEL 8.2Totalmente soportadasTotalmente soportadas
Ámbitos @scopeBásicos (RHEL 8.5+)CompletosCompletos
Wildcards *RHEL 8.2+SíSí
Negación de ámbito @!scopeLimitadoSíSí
Política BSINoSí (Fedora/RHEL 9+)Sí
Postcuántico (ML-KEM, ML-DSA)NoParcial (tardío)Sí
DEFAULT bloquea SHA-1En firmas (excepto DNSSec)Más agresivoMás agresivo
Política FIPSFIPS 140-2FIPS 140-3FIPS 140-3
NEXT como alias de DEFAULTNoSíSí
Sequoia/RPM back-endsNoSíSí

I.23 Subpolíticas Proporcionadas por el Sistema

Las siguientes subpolíticas vienen instaladas con el paquete crypto-policies:

NO-SHA1

hash = -SHA1
sign = -RSA-PSS-SHA1 -RSA-SHA1 -ECDSA-SHA1 -EDDSA-ED25519

Elimina SHA-1 de hashes y firmas. Bloqueo total de SHA-1 en el sistema.

AD-SUPPORT

Habilita algoritmos necesarios para interoperabilidad con Active Directory y entornos Windows heredados.

NO-CAMELLIA

cipher = -CAMELLIA-*

Elimina todas las cifras Camellia.

NO-ENFORCE-EMS (RHEL 9+)

Deshabilita el requisito de Extended Master Secret (EMS) en TLS. Necesario para compatibilidad con bibliotecas TLS antiguas que no soportan RFC 7627.

GOST

Habilita algoritmos criptográficos GOST (estándar ruso GOST R 34.10-2012, GOST R 34.11-2012). Necesario para conformidad con estándares de criptografía de la Federación Rusa.


I.24 Ejemplos Prácticos de Diagnóstico

“certificate verify failed” Tras Cambio de Política

Causa probable:
  - Certificado firmado con SHA-1 → sign no incluye RSA-SHA1/ECDSA-SHA1
  - Certificado con clave RSA 1024-bit → min_rsa_size rechaza
  - CA intermedia con SHA-1 → sha1_in_certs = 0 (GnuTLS)

Diagnóstico:
  openssl x509 -in cert.pem -noout -text | grep "Signature Algorithm"
  openssl x509 -in cert.pem -noout -text | grep "Public-Key"
  update-crypto-policies --show
  cat /etc/crypto-policies/state/CURRENT.pol | grep -E "sign|min_rsa|sha1"

Corrección:
  Si es certificado heredado → reemitir con SHA-256 y RSA 2048+
  Si es temporal → crear subpolítica permitiendo el algoritmo necesario

SSH Rechaza Conexión con “no matching cipher found”

Causa probable:
  - Servidor o cliente ofrece solo ciphers CBC y la política los deshabilitó
  - Cliente antiguo soporta solo AES-128-CBC

Diagnóstico:
  ssh -vvv user@host 2>&1 | grep -i cipher
  cat /etc/crypto-policies/back-ends/openssh.config
  cat /etc/crypto-policies/back-ends/opensshserver.config

Corrección:
  Crear subpolítica que rehabilita el cipher necesario:
  cipher@SSH = +AES-128-CBC

IPsec/VPN Falla al Negociar

Causa probable:
  - Grupo DH del otro extremo no está en la lista 'group'
  - Protocolo IKEv1 bloqueado

Diagnóstico:
  cat /etc/crypto-policies/back-ends/libreswan.config
  journalctl -u ipsec | grep -i "no proposal"

Corrección:
  group = +FFDHE-1024   # Si el otro extremo usa DH 1024
  protocol@IKE = IKEv1 IKEv2+  # Si el otro extremo usa IKEv1

I.25 Matriz Resumen: Parámetro × Back-end

ParámetroOpenSSLGnuTLSNSSOpenSSHlibsshKerberosLibreswanBINDJava
cipherSíSíSíSíSíSíSí-Sí
macParcialParcial-SíSí----
hashSíSíSí---SíSíSí
signSíSíSíSíSí-SíSíSí
key_exchangeSíSíSíSíSí-No-Sí
groupSíSíSíSíSí-Sí-Sí
protocolSíSíSí---Sí-Sí
min_rsa_sizeSECLEVELProfileSí-----Sí
min_dh_sizeSECLEVELProfileSí-----Sí
min_dsa_sizeSECLEVELProfileSí-----Sí
min_ec_size--------Sí
sha1_in_certs-Sí-------
arbitrary_dh_groupsSíSí-------
ssh_certs---Sí-----
etm---SíSí----
__emsSíSí-------
__openssl_block_sha1_signaturesSí--------

Leyenda: Sí = totalmente implementado, Parcial = implementación indirecta o limitada, No = explícitamente no afecta, - = no aplicable.

Nota: Los parámetros con prefijo __ son internos y no están documentados públicamente. Ver sección I.14 para detalles.


I.26 Recomendaciones de Arquitectura

Cuándo Usar Cada Enfoque

NecesidadEnfoqueMotivo
Ajuste fino sobre política existenteSubpolítica .pmod sobre DEFAULTEvoluciona con actualizaciones
Control totalPolítica .pol personalizadaNinguna evolución automática — responsabilidad del admin
Override de una sola aplicaciónlocal.d/ o configuración explícita en la appNo afecta al resto del sistema
Compatibilidad temporalLEGACY por tiempo limitadoRiesgo de seguridad — documentar y planificar salida
Conformidad regulatoriaFIPS + subpolítica si es necesarioAutomatizado por fips-mode-setup

Flujo de Decisión para Política Personalizada

¿Necesito cambiar configuraciones criptográficas?
    │
    ├─ ¿Solo una aplicación específica?
    │   └─ Sí → Configurar directamente en la app O usar local.d/
    │
    ├─ ¿Quiero deshabilitar algo system-wide?
    │   └─ Sí → Crear .pmod con directivas '-'
    │           Aplicar con DEFAULT:MY-MODULE
    │
    ├─ ¿Quiero habilitar algo que DEFAULT bloquea?
    │   └─ Sí → Crear .pmod con directivas '+'
    │           Aplicar con DEFAULT:MY-MODULE
    │           ⚠️ Documentar por qué es necesario
    │
    ├─ ¿Quiero control absoluto de todo?
    │   └─ Sí → Crear .pol completa (copiar de DEFAULT.pol)
    │           ⚠️ Responsable del mantenimiento continuo
    │
    └─ ¿Ninguna de las anteriores?
        └─ Usar DEFAULT y no tocar nada

I.27 Referencia de Archivos y Comandos

Comandos Esenciales

# Ver política activa
update-crypto-policies --show

# Cambiar política
sudo update-crypto-policies --set <POLÍTICA>[:MÓDULO1][:MÓDULO2]

# Listar políticas base disponibles
ls /usr/share/crypto-policies/policies/*.pol

# Listar subpolíticas disponibles
ls /usr/share/crypto-policies/policies/modules/*.pmod

# Listar subpolíticas locales
ls /etc/crypto-policies/policies/modules/*.pmod 2>/dev/null

# Ver política efectiva (expandida)
cat /etc/crypto-policies/state/CURRENT.pol

# Ver back-end de una biblioteca específica
cat /etc/crypto-policies/back-ends/<backend>.config

# Verificar si cambió recientemente
stat /etc/crypto-policies/config

Resumen de Directorios

DirectorioPropósitoQuién Gestiona
/usr/share/crypto-policies/policies/Políticas base del paquete RPMPaquete crypto-policies
/usr/share/crypto-policies/policies/modules/Subpolíticas del paquete RPMPaquete crypto-policies
/etc/crypto-policies/policies/Políticas personalizadas localesAdministrador
/etc/crypto-policies/policies/modules/Subpolíticas personalizadas localesAdministrador
/etc/crypto-policies/back-ends/Configs generadas para cada bibliotecaupdate-crypto-policies
/etc/crypto-policies/local.d/Overrides extras por back-endAdministrador
/etc/crypto-policies/state/Estado actual (enlace simbólico, política expandida)update-crypto-policies
/etc/crypto-policies/configNombre textual de la política activaupdate-crypto-policies

I.28 Fuentes y Referencias

Documentación

  • Man page oficial: man 7 crypto-policies — fuente primaria y canónica para todos los parámetros, ámbitos y comportamientos documentados en este apéndice.
  • Man page: man 8 update-crypto-policies — uso del comando.
  • Documentación de políticas en disco: /usr/share/doc/crypto-policies/
  • Red Hat Developer: Enhance security with system-wide crypto policies in RHEL 9
  • FOSDEM 2020: Custom crypto policies — presentación del mantenedor original, Tomáš Mráz.
  • Red Hat Knowledge Base: Article 3642912 — referencia para crypto-policies.
  • RFC 7457: Summarizing Known Attacks on Transport Layer Security (TLS) — motivación para la obsolescencia de algoritmos.
  • RFC 7627: Transport Layer Security (TLS) Session Hash and Extended Master Secret Extension.
  • RFC 9980: Post-Quantum Public Key Algorithm Extension for the OpenPGP Standard (ML-DSA, SLH-DSA).

Código Fuente (Repositorio Upstream)

Licencia

El proyecto fedora-crypto-policies se distribuye bajo la licencia LGPL-2.1-or-later. Copyright © 2019 Red Hat, Inc. — Tomáš Mráz y colaboradores.