El protocolo TLS Handshake Protocol opera sobre el Record
Protocol, que es el encargado de ofrecer una transferencia de
datos segura. El Handshake Protocol se encarga de establecer y
terminar las conexiones TLS.
Las aplicaciones (como por ej. un Web browser, un servidor Web,
un servidor de e-mail, etc.) usan el Handshake Protocol para
abrir y cerrar conexiones seguras, y se requiere que las
aplicaciones estén diseñadas para soportar TLS (por ej., pueden
usar la biblioteca SSLPlus).
Este protocolo es responsable de la negociación de una sesión, que consiste de los siguientes items:
Session Indentifier: una sequencia de bytes arbitrarios elegidos por el servidor para identificar un estado de sesión activa o reiniciable. | |
Peer Certificate: Es el certificado X509v3 del par. | |
Compression Method: un método de compresión (el algoritmo a utilizar antes de la encriptación). | |
Cipher Spec: Especifica el algoritmo de encriptación de datos, (por ejemplo NULL, DES, etc.) y un algoritmo de MAC (como MD5 o SHA). También define atributos criptograficos como el hash_size. | |
Master Secret: un secreto compartido de 48 bytes entre el cliente y el servidor. | |
is resumable: es un flag para indicar si la sesión puede usarse para iniciar nuevas conexiones. |
Estos items se usan también para crear parámetros de
seguridad que serán utilizados por el Record Layer cuando se
protegen los datos de la aplicación.
Muchas conexiones pueden instanciarse usando la misma sesión a
través de la característica de reinicialización.
Como ya sabemos, el Handshake Protocol opera sobre el Record
Protocol. Para que un cliente y un server puedan empezar a
comunicarse, ellos primero se ponen de acuerdo en la versión del
protocolo (TLS puede interoperar con SSL), seleccionar los
algoritmos criptográficos a usar para la privacidad de sus
datos, autenticarse (opcionalmente) uno con el otro, y usan
tecnicas de criptografia de clave pública para generar secretos
compartidos.
Para ver una serie de pasos más detallada sobre el handshake
usado para iniciar una conexión segura, clickee aquí.
Los subprotocolos utilizados por el Handshake Protocol son :
Change Cipher Spec Protocol : Existe para señalar transiciones en estrategias de codificación. | |
Alert Protocol : Los mensajes de Alerta se componen de la gravedad del mismo y una descripción del alerta. Estos con un nivel de resultado fatal resultan en la terminación inmediata de la conexión. |
A continuación, presentaremos la secuencia de pasos (en forma narrada) que componen el handshake de la apertura de una conexión segura usando el TLS Handshake Protocol, la cual fue adaptada de [6] y [7]:
Paso 1 : El cliente le envía al server el número de versión de TLS (o bien de SSL), los cipher que quiere usar, datos generados aleatoriamente, y otros tipos de información que el server necesita para comunicarse con el cliente usando TLS. (para detalles ver Mensaje ClientHello). | |
Paso 2 : El server le envía al cliente el número de versión del TLS (o SSL) del server, los cipher que quiere usar, datos generados aleatoriamente, y otros tipos de información que el cliente necesita para comunicarse con el server vía TLS (para detalles ver Mensaje ServerHello). El server también manda su propio certificado X.509 (para detalles ver Mensaje Server Certificate) y, si el server está prestando un servicio que requiera autenticación del cliente, le pide (al cliente) su certificado X.509 (para detalles ver Mensaje CertificateRequest). | |
Paso 3 : El cliente usa parte de la información enviada por el server para autenticarlo (ver Autenticación del Server para conocer detalles). Si el server no puede ser autenticado, se le avisa del problema al usuario y se le informa que no se puede establecer una conexión encriptada y autenticada con ese server. Si el server puede ser autenticado satisfactoriamente, el cliente va al Paso 4. | |
Paso 4 : Usando todos los datos generados en el handshake hasta ahora, el cliente (con la cooperación del server, y dependiendo del cipher siendo usado) crea el premaster secret para esta sesión, lo encripta con la clave pública del server (la cual se obtuvo del certificado del server que éste mandó en el Paso 2), y envía el premaster secret encriptado hacia el server (para detalles ver Mensaje ClientKeyExchange). | |
Paso 5 : Si el server requirió la autenticación del cliente (un paso opcional en el handshake), el cliente también firma (digitalmente) otra pieza de datos que es única a este handshake y conocida por ambas partes. En este caso, el cliente manda los datos firmados y su propio certificado al server, junto con el premaster secret encriptado (para detalles ver Mensaje CertificateVerify). | |
Paso 6 : Si el server requirió la autenticación del cliente, el server intenta autenticar el cliente (ver Autenticación del Cliente para conocer detalles). Si el cliente no puede ser autenticado, la sesión es terminada. Si el cliente puede ser satisfactoriamente autenticado, el server usa su clave privada para desencriptar el premaster secret, luego lleva a cabo una serie de cálculos (los cuales el cliente también ejecuta, empezando por el premaster secret) para generar el master secret. | |
Paso 7 : Ambas partes (cliente y server) usan el master secret para generar session keys (las claves de la sesión), las cuales son claves simétricas usadas para encriptar y desencriptar la información intercambiada durante la sesión TLS y para verificar su integridad (esto es, detectar cambios en los datos mientras éstos viajaban por la red, antes de ser recibidos por la conexión TLS). | |
Paso 8 : El cliente envía un mensaje al server informandole que mensajes futuros desde el cliente serán encriptados con la session key (para detalles ver change cipher spec Protocol). Luego éste manda un mensaje (encriptado) separado indicando que la parte cliente del handshake ha terminado (para detalles ver Mensaje Finished). | |
Paso 9 : El server manda un mensaje hacia el cliente informandole que los futuros mensajes desde el server serán encriptados con la session key (para detalles ver change cipher spec Protocol). Luego éste manda un mensaje (encriptado) separado indicando que la parte server del handshake ha terminado (para detalles ver Mensaje Finished). | |
Paso 10: En este momento, el handshake TLS esta completo, y la sesión TLS ha empezado. El cliente y el server usan las session keys para encriptar y desencriptar los datos que se mandan uno con otro y para validar su integridad. |
En la Figura 1, se muestran en un gráfico los pasos detallados arriba:
Los mensajes marcados con un (*) significan que son opcionales. Por ejemplo, se vé que la autenticación de las partes involucradas en el handshaking es opcional.
Para los lectores que tengan problemas en entender cómo se autentica un dato, o cuales son las técnicas de autenticación más comunes, o cómo se encriptan datos con una infraestructura de encriptación de clave pública, se recomienda leer [4].
Este protocolo consiste en un simple mensaje, que es
encriptado y comprimido bajo el estado de conexión corriente (no
pendiente) .El mensaje consiste en un solo byte con valor 1.
El mensaje Change Cipher Spec es enviado por ambos, el cliente y
servidor para notificar la política (party) de recepción de los
subsiguientes registros los cuales estarán protegidos bajo la
nueva negociación del ChiperSpec y las claves.
La recepción de estos mensajes causa que el receptor ordene al
Record Layer que copie inmediatamente el estado de lectura
pendiente en estado de lectura corriente. Inmediatamente de
enviar este mensaje, el emisor deberá ordenar al Record Layer
que marque el estado de escritura pendiente en estado de
escritura activa.
struct { enum { change_cipher_spec(1), (255) } type; } ChangeCipherSpec;
El mensaje Change Cipher Spec es enviado durante el Handshake después que los parámetros de seguridad hayan sido agregados, pero antes el mensaje finished verificador es enviado.
Uno de los content types soportados por TLS Record LAyer es el tipo Alert. Los mensajes de alerta transfieren la severidad de los mensajes y la descripcion del alerta. Los mensajes con un nivel fatal resultan la terminación inmediata de la conección. En este caso, otras conexiones correspondientes a esta sesión pueden continuar, pero session identifier deberá ser invalidado , previniendo que la sesion falle al ser usada para establecer nuevas conexiones. Igual que otros mensajes, los mensajes de alerta son encriptados y comprimidos, como especificados por el estado de conexión corriente.
enum { warning(1), fatal(2), (255) } AlertLevel;
enum { close_notify(0), unexpected_message(10), bad_record_mac(20), decryption_failed(21), record_overflow(22), decompression_failure(30), handshake_failure(40), bad_certificate(42), unsupported_certificate(43), certificate_revoked(44), certificate_expired(45), certificate_unknown(46), illegal_parameter(47), unknown_ca(48), access_denied(49), decode_error(50), decrypt_error(51), export_restriction(60), protocol_version(70), insufficient_security(71), internal_error(80), user_canceled(90), no_renegotiation(100), (255) } AlertDescription;
struct { AlertLevel level; AlertDescription description; } Alert;
Este protocolo implementa Alertas de Clausura o Fin (Closure alerts) y Alertas de Error (Error alerts).
El cliente y el servidor podrán conocer que la conexión está terminando en orden para evitar un ataque de truncación. Otra política puede iniciar el intercambio de mensajes de cierre.
Close_notify: Este
mensaje notifica al que recibe que el que envía no
enviará mas mensajes en esta conexión. La sesión se
convierte en no reanudable si cualquier conexión es
terminada sin su propio mensaje close_notify con un nivel
igual a advertencia (warning). Cualquier dato recibido después del alerta de clausura es ignorado. Cualquier parte puede iniciar el cierre enviando el alerta close_notify. Cada parte es requerida para enviar un alerta close_notify antes del cierre del lado que esta escribiendo en la conexión. Esto requiere que la otra parte responda con un alerta de close_notify emitida por él y cierre la conexión inmediatamente, descartando todas las escrituras pendientes. Esta espera de respuesta del alerta close_notify no es requerido por el que inicia el cierre ante el cierre de una lectura de la conexión. Si el protocolo de aplicación usado por TLS provee que cualquier dato puede ser llevado sobre el transporte subyacente (underlying) después que la conexión TLS está cerrada, la implementación TLS deberá recibir la respuesta del alerta close_notify antes que la capa de aplicación indique que la conexión TLS ha terminado. Si el protocolo de aplicación no transferirá ningún dato adicional, pero podrá sólo cerrar la conexión de transporte subyacente, entonces la implementación puede elegir cerrar el transporte sin esperar la respuesta del close_notify. No parte de este estandard debe ser tomado para dictar la manera en que un perfil de uso de TLS maneja el transporte de datos, incluyendo cuando las conexiones son abiertas o cerradas. |
Nota: Se asume que el cierre de una conexión entrega confiablemente los datos pendientes antes de la destrucción del transporte.
Cuando un error es detectado, la parte detectora envía un
mensaje a la otra parte. Ante la transmisión o recepción de un
mensaje de alerta fatal, ambas partes inmediatamente cierran la
conexión.
Servidores y clientes requieren que se desechen cualquier
session_identifiers, claves y secretos asociados a la conexión
fallada.
Se definen los siguientes alertas de errores:
unexpected_message (mensaje inesperado): un mensaje inapropiado puede ser recibido, esta alerta es siempre fatal y nunca debe ser vista en comunicaciones entre implementaciones apropiadas. | |
bad_record_mac: este mensaje es retornado si el registro es recibido con un MAC incorrecto, es siempre fatal. | |
decryption_failed: el TLSCipherText ha sido desencriptado en forma invalida, la longitud del bloque no ha sido múltiplo par, o los valores de padding no han sido correctos al chequearse, es siempre fatal. | |
record_overflow: el registro TLSCipherText ha sido recibido con una longitud mayor a 2^14 + 2048 bytes, o el registro TLSCompressed desencriptado con mas de 2^14 + 1024 bytes. Es siempre fatal. | |
decompression_failure: la función de descompresión recibe una entrada impropia, por ejemplo el dato que expandirá tiene una longitud excesiva. Es siempre fatal. | |
handshake_failure: la recepción de este mensaje indica que el transmisor no está capacitado para negociar un conjunto aceptable de parámetros de seguridad dados por las opciones disponibles. Este es un error fatal. | |
bad_certificate: el certificado está corrupto, las firmas que contiene no dan una verificación correcta. | |
unsupported_certificate: el certificado tiene un tipo no soportado. | |
certificate_revoked: Un certificado fue revocado por su firmante. | |
certificate_expired: el certificado ha expirado o no es válido actualmente. | |
certificate_unknown: algún otro tema (no especificado) originándose en el procesamiento de un certificado es interpretado como no aceptable. | |
illegal_parameter: un campo del handshake está fuera de rango o es inconsistente con otros campos. Es fatal. | |
unknown_ca: una cadena de certificados válidos es recibida, pero el certif. no es aceptado porque el certificado CA no puede ser localizado o no puede ser macheado con el conocido, el CA verdadero. Este mensaje es fatal. | |
access_denied: un certif. válido es recibido, pero cuando cundo el control de acceso es aplicado, el transmisor decide no proceder con la negociación. Es fatal. | |
decode_error: un mensaje no podrá ser decodificado porque algún campo está fuera del rango especificado o la longitud la longitud del mensaje es incorrecta. Es fatal. | |
decrypt_error: la operación criptográfica del handshake ha fallado, incluyendo incapacidad de una verificación de firmas correctas, decriptación de una clave de intercambio, o validación de un mensaje de fin (finished message). | |
export_restriction: una negociación en desacuerdo con las restricciones de exportación es detectada, por ejemplo, atentar transferir 1024 bit de clave RSA efímera por el método handshake RSA_EXPORT. El mensaje es fatal. | |
protocol_version: la version del protocolo está intentando negociar el reconocimiento, pero no es soportado. Por ejemplo, una version de protocolo vieja debe ser evitada por razones de seguridad. El mensaje es fatal. | |
insufficient_security: retornada en lugar de handshake_failure cuando una negociación ha fallado específicamente porque el server requiere ciphers mas seguros que los soportados por el cliente. Es fatal. | |
internal_error: un error interno no relacionado con el par o el protocolo correctísimo hace imposible continuar (tal como una falla en la alocación de memoria). | |
user_canceled: Este handshake esta siendo cancelado por alguna razón no relacionada con una falla del protocolo. Si el usuario cancela una operación después de que el handshake está completo, simplemente cerrar la conexión enviando un close_notify es mas apropiado. Esta alerta deberá ser seguida por el close_notify. Este mensaje es generalmente de aviso. | |
no_renegotiation: enviado por el cliente en respuesta a un hello request, o por un server en respuesta a un client hello despues de la inicialización del diálogo. Alguno de ellos puede dirigir normalmente la renegociación, cuando ésta no es apropiada, el que recibe deberá responder con este alerta, en este punto, el requeridor original puede decidir proseguir o no con la conexión.Este mensaje es siempre de aviso. |
Todos los errores que no tiene un nivel de alerta especificado, la parte que envía puede decidir entre un error fatal o no, si un alerta con nivel de aviso es recibido, la parte que recibe puede decidir tratarlo como error fatal o no. De cualquier modo, todos los mensajes que son transmitidos con un nivel fatal deben ser tratados como mensajes fatales.
Este mensaje puede ser enviado por el servidor en cualquier
momento. El mensaje consiste en una simple
notificación para que el cliente comience nuevamente el proceso
de negociación enviando un mensaje ClientHello, cuando lo crea
conveniente. Este mensaje debe ser ignorado por el cliente
si éste ya se encuentra negociando una sesión, o si no
desea renegociar una sesión, o podría responder con un
mensaje de alerta de no_renegociación. Si el server envía
un mensaje HelloRequest pero no recibe a un mensaje HelloClient
en contestación, puede cerrar la conexión con una alarma fatal.
Después de enviar un mensaje HelloRequest el server no debería
repetir el requerimiento hasta que la negociación subsecuente
del handshake se haya completado.
Enviar este mensaje es opcional, dado que si el server no lo
envía, pero el cliente envía un mensaje ClientHello, y el
server responde, el protocolo inicia igual la negociación de los
parámetros de seguridad para establecer la comunicación.
Este mensaje tiene una estructura vacía: struct { }
HelloRequest;
Figura 2
msg_type | Este campo pertene a la estructura del protocolo Handshake e indica el mensaje que será enviado. |
length | Este campo también pertenece a la estructura del protocolo Handshake e indica la cantidad de bytes en el mensaje. |
Cuando un cliente conecta primero a un
server éste le exige enviar el clientHello como su primer
mensaje. El cliente también puede enviar un clientHello en
contestación a un mensaje HelloRequest, o como iniciativa
para renegociar los parámetros de seguridad en una conexión
existente.
Después de enviar el mensaje ClientHello,
el cliente espera el mensaje ServerHello del server. Si se
retorna como respuesta cualquier otro mensaje del handshake,
excepto un HelloRequest se considera en error fatal.
El mensaje HelloClient no es opcional y su
estructura es la siguiente:
Figura 3
msg_type | Este campo pertene a la estructura del protocolo Handshake e indica el mensaje que será enviado. |
length | Este campo también pertenece a la estructura del protocolo Handshake e indica la cantidad de bytes en el mensaje. |
client_version | Se trata de la versión del protocolo TLS, por la cuál el cliente se comunica durante una sesión. Esta debe ser la última versión soportada por el cliente. |
gmt_unix_time | La hora y fecha actuales en formato UNIX Standard 32-bit (segundos desde el arranque de la media noche Ene 1, 1970, GMT) según el reloj interno del que envía. No se exige poner los relojes correctamente para el Protocolo de TLS básico;los protocolos de nivel más alto o aplicación pueden definir requisitos adicionales. |
random_bytes | Se trata de 28 bytes generados por un generador seguro de números aleatorios |
session_id | Se trata del ID de una sesión que el cliente
desea usar para esta conexión. Este campo debe
estar vacío si ningún session_id está disponible o el
cliente desea generar nuevos parámetros de
seguridad. El mensaje clientHello incluye un identificador de sesión de longitud variable. Si no es vacío, el valor identifica una sesión entre el mismo cliente y servidor cuyo parámetros de seguridad del cliente desea reusar. El identificador de la sesión puede ser de una conexión anterior, ésta conexión, u otra conexión actualmente activa. La segunda opción es útil si el cliente sólo desea poner al día las estructuras random y los valores derivados de una conexión, mientras la tercera opción hace posible establecer varias conexiones seguras independientes sin repitir el protocolo Handshake completo. Estas conexiones independientes pueden ocurrir secuencialmente o simultáneamente; un SessionID se recibe válida cuando el protocolo Handshake que lo negocia completa el intercambio de Mensajes de finalización y persiste hasta ser removido debido a envejecer o porque un error fatal se encontró en una conexión asociada con la sesión. El contenido actual del SessionID lo define el servidor. Advertencia: Dado que el SessionID se transmite sin encriptación o protección inmediata del MAC, los servidores no deben poner información confidencial en identificadores de la sesión o permitir que los contenidos del identificador de la sesión imitado cause cualquier brecha de seguridad. (Note que el volumen del protocolo Handshake en conjunto, incluso el SessionID, es protegido por los mensajes de finalización intercambiados al final del protocolo Handshake. |
cipher_suites | Ésta es una lista de las opciones de criptografia
soportadas por el cliente, con la primera preferencia del
cliente en el primer lugar. Si el campo del session_id no
está vacío (implicando una reasunción del
requerimiento de la sesión) este vector debe incluir el
cipher_suite por lo menos de esa sesión. La lista de CipherSuite, pasada del cliente al server en el mensaje clientHello, contiene las combinaciones de algoritmos de criptografía soportados por el cliente en orden de preferencia del cliente (la opción favorita primero). Cada CipherSuite define un algoritmo de intercambio de claves, un algoritmo de encriptacion de contenidos (incluso la longitud de la clave secreta) y un algoritmo de MAC. El server seleccionará un cipher suite o, si ninguna opción aceptable se presenta, devuelva un alerta de fracaso y cierra la conexión. |
compression_methods | Ésta es una lista de los métodos de compresión soportada por el cliente, ordenada de acuerdo con la preferencia del cliente. Si el campo del session_id es no vacío (implicando un requerimiento de reasunción de la sesión) debe incluir el compression_method de esa sesión. Este vector debe contener, y todas las aplicaciones deben soportar, CompressionMethod.null. Así, un cliente y servidor siempre serán capaces de estar de acuerdo en un método de compresión. |
Nota de compatibilidad:
Para brindar compatibilidad, se permite para un mensaje
clientHello incluir datos extras después de los métodos de
compresión. Estos datos deben ser incluidos en los hashes del
protocolo Handshake, pero deben ignorarse para otra parte. Éste
es el único mensaje del protocolo Handshake para qué esto sea
legal; para todos los otros mensajes, la cantidad de datos en la
descripción del mensaje debe emparejarse precisamente.
El servidor enviará este mensaje en contestación a un
mensaje clientHello cuando pudo encontrar un conjunto aceptable
de algoritmos. Si no puede encontrar un par semejante,
responderá con un alerta de fracaso del protocolo Handshake.
Este mensaje, en consecuencia no es opcional.
La estructura de este mensaje se presenta en la siguiente figura:
Figura 4
msg_type | Este campo pertene a la estructura del protocolo Handshake e indica el mensaje que será enviado. |
length | Este campo también pertenece a la estructura del protocolo Handshake e indica la cantidad de bytes en el mensaje. |
server_version | Este campo contendrá la versión más baja sugerida por el cliente en el mensaje clienteHello y la versión más alta soportada por el servidor. |
gmt_unix_time | La hora y fecha actuales en formato UNIX Standard 32-bit (segundos desde el arranque de la media noche Ene 1, 1970, GMT). No se exige poner los relojes correctamente para el Protocolo de TLS básico;los protocolos de nivel más alto o aplicación pueden definir requisitos adicionales. |
random_bytes | Se trata de 28 bytes generados por un generador seguro de números aleatorios. Esta estructura (random, formada por este valor y el gmt_unix_time) la genera el server y deber ser diferente de (e independiente de ) el ClientHello.random. |
session_id | Ésta es la identificación de la sesión que corresponde a esta conexión. Si el ClientHello.session_id no está vacío, el server mostrará su session cache para una pareja. Si se encuentra una pareja y el server quiere establecer la nueva conexión usando el estado de la sesión especificada, el server responderá con el mismo valor tal como fue proporcionado por el cliente. Esto indica una sesión reasumida y dictamina que las partes deben proceder directamente a los mensajes de finalización. Por otra parte este campo contendrá un valor diferente que identifica la nueva sesión. El server puede devolver un session_id vacío para indicar que la sesión no será escondida y por consiguiente no puede reasumirse. Si una sesión es reasumida, esto debe hacerse usando el mismo cipher suite con la que fue originalmente negociada. |
cipher_suite | El cipher suite seleccionado por el servidor de la lista indicada en el ClientHello.cipher_suites. Para las sesiones reasumidas este campo es el valor del estado de la sesión a reasumirse. |
compression_method | El algoritmo de compresión seleccionado por el server desde la lista en el ClientHello.compression_methods. Para las sesiones reasumidas este campo es el valor del estado de la sesión a reasumirse. |
El servidor debe enviar un certificado siempre
que esté de acuerdo en que el método de intercambio de clave no
es uno anónimo. Este mensaje siempre requiere que inmediatamente
siga el mensaje serverHello.
El tipo del certificado debe ser apropiado para el algoritmo de
intercambio de clave del cipher suite seleccionado, y
generalmente es un certificado X.509v3. Debe contener una clave
que empareje el metodo de intercambio, como se indica a
continuación. A menos que otra parte lo especifique, el
algoritmo de firma para el certificado debe ser el mismo
que el algoritmo para la clave del certificado. A menos que otra
parte lo especifique, la clave pública puede ser de cualquier
longitud.
Todos los perfiles del certificado, la clave y los formatos de
la criptografía son definidos por el grupo de
trabajo IETF PKIX. Cuando se presenta una clave con extensión,
el bit del digitalSignature debe setearse para la clave que será
elegida para firmar, como se describió anteriormente, y el bit
del keyEncipherment debe estar presente para permitir la
encriptación, como se describió anteriormente. El bit del
keyAgreement debe setearse sobre certificados de Diffie-Hellman.
Como los CipherSuites especifican nuevos métodos del
intercambio de claves para el Protocolo de TLS, ellos
implicarán el formato del certificado y la información
codificada que se requiera. Los posibles algoritmos de
intercambio de clave soportados por este protocolo se detallan a
continuación:
Algoritmo de Intercambio de clave | Tipo de clave del certificado |
RSA | Clave pública RSA; el certificado debe autorizar la clave que se usará en la encriptación. |
RSA_EXPORT | La clave pùblica RSA de longitud mayor que 512 bits que pueden usarse para firmar, o una clave de 512 bits o más corta, que puede usarse para la encriptacion o el firmado. |
DHE_DSS | Clave pública DSS. |
DHE_DSS_EXPORT | Clave pública DSS. |
DHE_RSA | Clave pública RSA, la que puede usarse para firmar. |
DHE_RSA_EXPORT | Clave pública RSA, la que puede usarse para firmar. |
DH_DSS | Clave Diffie Hellman. El algoritmo usado para firmar el certificado debería ser DSS. |
DH_RSA | Clave Diffie Hellman. El algoritmo usado para firmar el certificado debería ser RSA. |
msg_type | Este campo pertene a la estructura del protocolo Handshake e indica el mensaje que será enviado. |
length | Este campo también pertenece a la estructura del protocolo Handshake e indica la cantidad de bytes en el mensaje. |
certificate_list | Se trata de una secuencia de certificados X.509v3. El certificado del que envía el mensaje debe encontrarse primero en la lista. Cada certificado siguiente debe validar directamente el certificado precedente. Dado que la aprobación del certificado requiere que las root keys se distribuyan independientemente, el certificado firmado, el cual especifica el certificado autorizado del root, puede omitirse opcionalmente de la secuencia, bajo la aceptación que la otra parte de la conexión ya lo posea en orden para validarlo en cualquier caso. |
Se usarán el mismo tipo de mensaje y estructura para la
contestación del cliente a un mensaje de demanda de
certificado. Note que un cliente puede no envíar ningún
certificado si no tiene un certificado apropiado para enviar en
contestación a la demanda de la autenticación del servidor.
Este mensaje es opcional.
Este mensaje se enviará inmediatamente después del mensaje
certificate del server (o el mensaje HelloServer, si se trata
de una negociación anónima).
El mensaje ServerKeyExchange sólo es enviado por el servidor
cuando el mensaje certificate del server (si se envió) no
contiene bastantes datos para permitirle al cliente intercambiar
un premaster secret. Esto es válido para los siguientes
métodos de intercambio de clave:
RSA_EXPORT (si la clave pública en el certificado del servidor es mayor a 512 bits) | |
DHE_DSS | |
DHE_DSS_EXPORT | |
DHE_RSA | |
DHE_RSA_EXPORT | |
DH_anon |
No es válido enviar el mensaje ServerKeyExchange para los siguientes métodos del intercambio de clave:
RSA | |
RSA_EXPORT (cuando la llave pública en el certificado del servidor es menor o igual a 512 bits en longitud) | |
DH_DSS | |
DH_RSA |
Este mensaje lleva información criptografica para permitir al
cliente comunicar el premaster secret: cualquier clave
pública RSA para encriptar el premaster secret, o una
clave pública de Diffie-Hellman con la que el cliente
puede completar un intercambio de claves (cuyo resultado es
el premaster secret.)
Cuando se definen CipherSuites adicionales para TLS que incluyen
un nuevo algoritmo de intercambio de clave, el mensaje de
ServerKeyExchange se enviará si y sólo si el tipo
del certificado asociado con el algoritmo de intercambio de
clave no mantiene bastante información para el cliente
para intercambiar un premaster secret.
La estructura de este mensaje es:
Figura 5
msg_type | Este campo pertene a la estructura del protocolo Handshake e indica el mensaje que será enviado. |
length | Este campo también pertenece a la estructura del protocolo Handshake e indica la cantidad de bytes en el mensaje. |
KeyExchangeAlgorithm | Indica el tipo de algoritmo que se utilizará (Diffie_Hellman o RSA). La estructura de este mensaje varía de acuerdo con elección de este algoritmo. |
Figura 6
DH_p | Se trata del primer módulo usado para la operación de Diffie-Hellman |
DH_g | Se trata del generador usado para la operación de Diffie-Hellman |
DH_ys | Es el valor público Diffie_Hellman del server (g^ x mod p) |
RSA_modulus | Es el módulo de la clave RSA temporal del server |
RSA_exponent | Es el exponente público de la clave RSA temporal del server |
signed_params | Se usa para el intercambio de clave con firma. Se trata de un hash de los valores de los parámetros con la firma apropiada para que éste pueda aplicarse. |
Los algoritmos para la firma pueden ser: RSA, DSA, o uno anónimo. La estructura de este campo para cada uno de estos algoritmos es la siguiente:
Anónimo | Sin estructura | |
RSA | md5_hash[16] | MD5(ClientHello.random+ServerHello.random+ServerParams) |
sha_hash[20] | SHA(ClientHello.random+ServerHello.random+ServerParams) | |
DSA | sha_hash[20] | SHA(ClientHello.random+ServerHello.random+ServerParams) |
Nota: Según la ley actual de exportación de los E.E.U.U., el módulo de RSA más grande que 512 bits no puede usarse para el intercambio de la clave en software exportado desde EE.UU.
Se trata de un mensaje opcional. Este mensaje se envía cuando
un server conocido requiere un certificado del cliente,
inmediatamente después del mensaje ServerKeyExchange, si éste
se envía.
Su estructura es la siguiente:
Figura 7
msg_type | Este campo pertene a la estructura del protocolo Handshake e indica el mensaje que será enviado. |
length | Este campo también pertenece a la estructura del protocolo Handshake e indica la cantidad de bytes en el mensaje. |
certificate_types | Este campo contiene una lista de los tipos de certificados requeridos, en orden de preferencias de acuerdo con el server. |
certificate_authorities | Una lista de nombres de certificados de autorización aceptables. Estos nombres distinguidos pueden especificar un nombre deseado para root CA o para un CA subordinado. Así, este mensaje puede usarse para describir roots conocidos y espacios deseados de autorización. |
Este mensaje es enviado por el server para indicar la
finalización de los mensajes ServerHello y sus asociados.
Despúes de enviarlo el server esperará una respuesta del
cliente. No es un mensaje opcional. Se envía para
significar que el server a terminado con los mensajes para
soportar el intercambio de claves, y que el cliente puede
proceder con su parte. Luego de recibir el ServerHelloDone,
el cliente debería verificar la condición de que el
server requiera un certificado válido y chequear que los
parámetros del mensaje sean aceptables.
Se trata de un mensaje sin estructura adicional a la protocolo
Handshake (igual al mensaje HelloRequest).
Este es el primer mensaje que el cliente puede enviar luego de recibir el mensaje ServerHelloDone. Se trata de un mensaje opcional. Solamente se envía si el server requiere un certificado. Si no existe un certificado adecuado disponible, el cliente debería enviar un mensaje sin certificado. Si el server requiere la autenticación del cliente para continuar con el protocolo Handshake, el cliente puede responder con un mensaje de alerta de fallo fatal del Handshake. Los certificado del cliente se envían usando la estructura ya definida en el mensaje ServerCertificate.
Se trata de un mensaje no opcional, enviado por el cliente
inmediatamente después del mensaje ClientCertificate, si éste
es enviado. De otro modo, este mensaje será el primero
enviado por el cliente después de recibir el mensaje
ServerHelloDone.
Con este mensaje se establece el premaster secret, por la
transmisión directa del secreto encriptado RSA, o por la
transmisión de los parámetros de Diffie-Hellman los que
permitirán a cada parte acordar el mismo premaster secret.
Cuando el método de intercambio de clave es DH_RSA o DH_DSS, se
requerirá la certificación del cliente. Este será capaz
de responder con un certificado conteniendo una clave pública
Diffie-Hellman cuyos parámetros (el grupo y el generador) fueron
especificados por el server en sus certificados, y este mensaje
no contendrá ningún dato.
La estructura de este mensaje dependerá de qué método para el
intercambio de claves se haya elegido.
Figura 8
msg_type | Este campo pertene a la estructura del protocolo Handshake e indica el mensaje que será enviado. |
length | Este campo también pertenece a la estructura del protocolo Handshake e indica la cantidad de bytes en el mensaje. |
KeyExchangeAlgorithm | Indica el tipo de algoritmo que se utilizará (Diffie_Hellman o RSA). La estructura de este mensaje varía de acuerdo con elección de este algoritmo. |
Figura 9
Figura 10
Este mensaje se usa para proveer la verificación explícita
de un certificado del cliente. Sòlo se envía siguiendo a
un certificado de cliente que tiene la capacidad de firma (por
ejemplo, todos los certificados excepto aquellos que contienen
parámetros fijos de Diffie-Hellman) . Cuando se envía, es
inmediatamente seguido por el mensaje ClientKeyExchange.
La estructura de este mensaje es:
Figura 11
El campo signature define su estructura como:
Anónimo | Sin estructura | |
RSA | md5_hash[16] | MD5(Handshake_messages) |
sha_hash[20] | SHA(Handshake_messages) | |
DSA | sha_hash[20] | SHA(Handshake_messages) |
Este mensaje se envía siempre después del mensaje
ChangeCipherSpec para verificar que el intercambio de claves y el
proceso de autenticación se llevaron a cabo
satisfactoriamente. Para esto es esencial que el mensaje
ChangeCipherSpec se reciba entre otro mensaje del Handshake
y el mensaje Finished. Este mensaje es el primero protegido
con los algoritmos negociados, claves, y secretos. Los
destinatarios de los mensajes de finalización deben verificar
que los contenidos sean correctos. Una vez que una parte envía
el mensaje de finalización y recibe y valida el mensaje de
finalización de la otra parte, pueden comenzar a enviar y
recibir los datos de la aplicación sobre la conección. Se
trata de un mensaje no opcional. Si este mensaje no es
precedido por el mensaje ChangeCipherSpec en el momento indicado
en el handshake se produce un error fatal.
Su estructura es la siguiente:
Figura 12
msg_type | Este campo pertene a la estructura del protocolo Handshake e indica el mensaje que será enviado. |
length | Este campo también pertenece a la estructura del protocolo Handshake e indica la cantidad de bytes en el mensaje. |
finished_label | Contiene "Client Finished" para mensajes enviados por el cliente y "Server Finished" para mensajes enviados por el server. |
handshake_messages | Todos los datos de todos los mensajes sin incluir este mensaje. Este es un dato visible sólo para la capa del handshake y sin incluir los headers de la capa de registro. |