[Anterior]

[Tabla de Contenidos]

[Siguiente]

TLS Record Protocol

 

Generalidades

En base a lo que se explico en la sección de Conceptos Básicos, este protocolo maneja estados de conexión. Existen dos estados actuales (lectura y escritura) y dos estados pendientes (lectura y escritura). Los registros sólo se procesan bajo el estado actual . Es posible pasar de un estado pendiente de conexión a un estado actual por medio del Handshake Protocol. Cuando esto sucede el estado pendiente es reinicializado a un estado vacío. Es ilegal hacer que un estado no inicializado con los parámetros de seguridad pase a ser un estado actual.

La estructura de los parámetros de seguridad para el estado de lectura y escritura de una conexión TLS puede ser consultada en el Apéndice A.6 de la RFC del Protocolo.

Cada estado de una conexión define los siguientes parámetros de seguridad:

Conexion End: Indica si la entidad es considerada como el cliente o como el servidor (entity).
Bulk Encryption Algorithm: Es el algoritmo que se usará para la encriptación de los datos (bulk_cipher_algorithm). Esta especificación incluye el tamaño de la clave (key_size), cuánto de esa clave es secreta (key_material_length), si se trata de un encriptador por bloque o por stream (cipher_type), el tamaño del bloque del cipher y si el cipher se considera exportable (is_exportable).
MAC Algorithm: El algoritmo que se usará para la autenticación de mensajes (mac_algorithm). Esta especificación incluye el tamaño del hash (hash_size) el cual es retornado por dicho algoritmo.
Compresion Algorithm: Es un algoritmo que se usará para la compresión de datos. Esta especificación debe incluir toda la información que el algoritmo requiera para hacer la compresión.
Master Secret: Un secreto de 48 bytes (master_secret[48]) compartido entre los dos pares de la conexión.
Client Random: Un valor de 32 bytes (client_random[32]) provisto por el cliente.
Server Random: Un valor de 32 bytes (server_random[32]) provisto por el servidor.

Una vez definida la estructura arriba mencionada, el Record Protocol genera el secreto MAC de escritura para el cliente (client_write_MAC_secret) y el servidor (server_write_MAC_secret), la clave de escritura para el cliente (client_write_key) y servidor (server_write_key) y los IVs en caso de que se trate de un cipher por bloques (client_write_IV y server_write_IV). Todos estos parámetros son generados con la función PRF.

Por cada registro procesado se deben actualizar los estados actuales. Cada estado comprende los siguientes elementos:

Estado de la Compresión: es el estado en el que se encuentra el algoritmo de compresión.
Estado del Encriptador: es el estado en el que se encuentra el algoritmo de encriptación. Si se trata de un encriptador por bloques en modo CBC (único modo soportado por TLS), el estado inicial contendrá el IV y deberá ser actualizado con el último bloque de cipherText que se haya generado, según se procesen los registros. En caso de un encriptador por stream, el estado contendrá lo necesario para seguir encriptando o desencriptando según se requiera.
El secreto del MAC: se mantiene el mismo secreto MAC para la conexión conforme se generó arriba.
Número de secuencia: Cada estado de conexión contiene un número de secuencia que se mantiene independientemente para los estados de lectura y escritura. El número de secuencia debe ser seteado a cero cada vez que un estado de conexión pasa a estado activo.

 

Fragmentación

El Record Layer de TLS recibe datos no interpretados de capas superiores en bloques no vacíos de tamaño arbitrario, y los fragmenta en bloques de información de hasta 2^14 bytes o menos. Múltiples mensajes del cliente del mismo ContentType pueden unirse en un solo TLS PlainText record, o un solo mensaje puede fragmentarse en varios registros.

Suponemos que, si dado un bloque de longitud menor a los 2^14 bytes definidos como tamaño máximo para un registro intenta ser enviado, pero otro bloque del mismo ContentType necesita ser enviado también, de manera que la concatenación de los dos supera los 2^14 bytes, entonces se enviarán en registros separados.

Una vez hecha la fragmentación (si es que es necesaria) se introduce la información en una estructura llamada TLSPlaintext, descripta abajo en la Figura 1.

Figura 1

A continuación se describen los campos de la figura:

type Es el protocolo de nivel superior usado procesar el fragmento encapsulado
version Es la version del protocolo que esta siendo utilizado. Para TLS v1, version = {3,1}
Para SSL v3.0, version = {3,0}
length Es la longitud en bytes del TLSPlainText.fragment ( entre 1 y 2^14)
fragment El dato de aplicación. Este dato es transparente y tratado como un bloque independiente para ser distribuido al protocolo de nivel superior especificado por el campo type.

 

Compresión y Descompresión

Cuando se setean los parámetros de la conexión, se puede especificar un algoritmo de compresión y descompresión para poder comprimir los datos de un registro TLSPlainText. Esto es una etapa adicional antes de que los datos sean encriptados. Por defecto cuando se inicia el estado de sesión el algoritmo se define como CompressionMethod.null, lo que significa que no va a haber ninguna compresión como resultado de esta etapa.

Independientemente de esto, se traslada (comprimido o no) la información a un registro tipo TLSCompressed como se muestra en la Figura 2:

Figura 2

A continuación se describen los campos de la figura:

type Idem TLSPlainText
version Idem TLSPlainText
length Es la longitud en bytes del TLSCompressed.fragment ( entre 1 y 2^14 + 1024), donde los 1024 bytes son la máxima cantidad de información que agrega el algoritmo de compresión para poder efectuarse la descompresión.
fragment Es el TLSPlainText.fragment comprimido.

Si al descomprimir, la longitud del fragmento supera los 2^14 bytes, se reporta un mensaje de Alerta de Error , llamado decompression_failure , el cual es fatal.

 

Encriptación de Registros.

El paso final antes de la transmisión de los datos por el medio de transporte (TCP) es la encriptación y autenticación de los mismos.
Las funciones de encriptación y MAC definidas al comienzo del estado de lectura y escritura de una conexión traducen la estructura TLSCompressed a TLSCipherText. Las funciones de desencriptación realizan el proceso inverso. El MAC del registro incluye también un número de secuencia para que los mensajes perdidos, extra o repetidos sean detectados.

Recordemos que la encriptación tiene el propósito de salvaguardar los datos de personas o programas que intentan espiar o robar los datos de la conexión , mientras que el MAC sirve para evitar la falsificación o modificación de los datos transmitidos. Además, recordemos que existen dos tipos de algoritmos de encriptación :

Los Block Cipher, que van encriptando la secuencia de datos en bloques de una longitud fija ( por ej: de a 64 bits), y si la longitud de la secuencia no es múltiplo del tamaño del bloque, se rellena con la cantidad necesaria de bits hasta llegar a completar una longitud múltiplo del tamaño del bloque (se pueden agregar varios bloques de padding o nulos para engañar a algún hacker que pueda estar haciendo análisis de tráfico).
Los Stream Cipher, que van encriptando byte por byte a medida que va procesando la secuencia de datos.

Note que el MAC es computado antes de la encriptación, el cipher encripta el bloque entero (TLSCompressed.fragment), incluyendo el MAC.

TLS soporta los dos tipos de encriptadores (Block y Stream) resultando en dos formas de la estructura TLSCipherText:

TLSCiphertext sin algoritmo de encriptación, o con un algoritmo de tipo Stream
TLSCiphertext con un algoritmo de encriptación de tipo Block con modo de operación CBC

En ambos casos, el MAC se genera como:

HMAC_hash( MAC_write_secret, [seq_num || TLSCompressed.type || TLSCompressed.version || TLSCompressed.length || TLSCompressed.fragment] )

es decir, HMAC_hash( MAC_write_secret, [ seq_num || <UN_REGISTRO_TLSCompressed_COMPLETO> ] ), donde

seq_num es el número de secuencia de este registro, y

hash es el algoritmo de hashing especificado por SecurityParameters.mac_algorithm.

 

TLSCiphertext sin algoritmo de encriptación, o con un algoritmo de tipo Stream

En caso de elegirse un algoritmo de encriptación de tipo Stream, o bien no se elija encriptar los datos, la estructura TLSCiphertext es la siguiente:

Figura 3

 

type Idem TLSCompressed.type.
version Idem TLSCompressed.version
length Es la longitud en bytes de: TLSCompressed.fragment || MAC. Esta longitud no debe exceder de 2^14 + 2048.(*)
content Es el TLSCompressed.fragment encriptado o no.
MAC Es la salida del algoritmo de autenticación.

(*) El TLSCiphertext.length se calcula como TLSCompressed.length + SecurityParameters.hash_size.

 

TLSCiphertext con un algoritmo de encriptación de tipo Block

La estructura TLSCiphertext cuando se utiliza un stream cipher es la que se muestra en la Figura 4:

Figura 4

 

type Idem TLSCompressed
version Idem TLSCompressed
length Es la longitud de todos los datos que van encriptados. Se calcula como:
TLSCiphertext.length = TLSCompressed.length + SecurityParameters.hash_size + padding_length + 1
content Es el TLSCompressed.fragment encriptado.
MAC Es la salida del algoritmo de autenticación.
padding El padding es agregado para forzar la longitud del TLSCompressed.fragment para ser múltiplo de la longitud del bloque del cipher.
padding_length La longitud del padding debe ser tal que el tamaño total de [content || MAC || padding || padding_length] es múltiplo de la longitud del bloque del cipher.

[Anterior]

[Tabla de Contenidos]

[Siguiente]
1