Интегрированные сети ISDN

         

Протокол записей TLS


6. Протокол записей TLS



Протокол записей TLS является послойным. На каждом уровне, сообщения могут включать поля длины, описания и содержимого. Протокол записей берет сообщения, подлежащие пересылке, разбивает их на блоки, опционно сжимает данные, применяет MAC, шифрует и передает результат. Полученные данные дешифруются, верифицируются, декомпрессируются, восстанавливается их первоначальный вид, результат передается клиентам верхнего уровня.

Четыре протокола описаны в данном документе: протокол диалога, протокол уведомления, протокол спецификации изменения шифра, и прикладной информационный протокол. Для того чтобы позволить расширение протокола TLS, разрешена поддержка протоколом дополнительных типов записей. Любые новые типы записей должны размещать значения типа немедленно за величинами ContentType четырех типов, описанных здесь (смотри Приложение A.2). Если реализация TLS получает рекорд нераспознаваемого типа, она должна его игнорировать. Любой протокол, предназначенный для использования поверх TLS, должен быть тщательно сконфигурирован, для того чтобы противостоять любым атакам. Заметим, что из-за того, что тип и длина записи не защищены шифрованием, следует принимать меры, чтобы минимизировать трафик анализа этих величин.

6.1. Состояния соединений

Состояние соединения TLS является операционной средой протокола записей TLS. Оно специфицирует алгоритмы сжатия, шифрования и MAC. Кроме того, известны параметры этих алгоритмов: секретный код MAC, а также ключи шифрования и IV соединения для направлений чтения и записи. Логически существует четыре состояния соединения: текущие состояния чтения и записи, и отложенные состояния чтения и записи. Все записи обрабатываются в текущих состояниях чтения или записи. Параметры безопасности для отложенных состояний могут быть установлены протоколом диалога TLS. Протокол диалога может селективно переводить любое отложенное состояние в текущее, при этом соответствующее текущее состояние становится отложенным. Не допускается формировать состояние, которое не инициализировано с учетом параметров безопасности текущего состояния.
Исходное текущее состояние всегда специфицировано без компрессии, шифрования или MAC. Параметры безопасности для состояния чтения и записи соединения TLS задаются путем определения следующих величин:



Конец соединения Клиент или сервер участник соединения.
Алгоритм массового шифрования Алгоритм, используемый для массового шифрования. Эта спецификация включает размер ключа алгоритма, степень секретности ключа, является ли этот шифр блочным или поточным, размер блока и является ли шифр экспортным.
Алгоритм MAC Алгоритм аутентификации сообщений. Эта спецификация включает размер хэша, который возвращается алгоритмом MAC.
Алгоритм сжатия Алгоритм сжатия данных. Эта спецификация должна включать всю информацию, необходимую для выполнения компрессии.
Секретный код сервера (master secret) 48 байтовый секретный код, общий для обоих партеров в соединении.
Случайный код клиента 32 байтный код, предоставляемый клиентом.
Случайный код сервера 32 байтный код, предоставляемый сервером.
Эти параметры определены в языке представления в виде:

enum { server, client } ConnectionEnd;

enum { null, rc4, rc2, des, 3des, des40 } BulkCipherAlgorithm;

enum { stream, block } CipherType;

enum { true, false } IsExportable;

enum { null, md5, sha } MACAlgorithm;

enum { null(0), (255) } CompressionMethod;

/* Алгоритмы, специфицированные в CompressionMethod, BulkCipherAlgorithm и MACAlgorithm могут быть добавлены. */

struct { ConnectionEnd entity;
BulkCipherAlgorithm bulk_cipher_algorithm;
CipherType cipher_type;
uint8 key_size;
uint8 key_material_length;
IsExportable is_exportable;
MACAlgorithm mac_algorithm;
uint8 hash_size;
CompressionMethod compression_algorithm;
Opaque master_secret[48];
opaque client_random[32];
opaque server_random[32];} SecurityParameters;
Уровень записей будет использовать параметры безопасности для формирования следующих шести объектов:

Секретный код MAC записи клиента

>Секретный код MAC записи сервера



>Ключ записи клиента

Ключ записи сервера

IV записи клиента (только для блочного шифра)

IV записи сервера (только для блочного шифра)

Параметры записи клиента используются сервером при получении и обработке записей и наоборот. Алгоритм, использованный для генерирования этих объектов с помощью параметров безопасности, описан в разделе 6.3. Раз параметры безопасности определены и ключи сформированы, состояния соединения могут быть в любой момент реализованы путем перевода их в текущее состояние. Эти текущие состояния должны актуализоваться после обработки каждой записи. Каждое состояние соединения включает в себя следующие элементы:

Состояние сжатия Текущее состояние алгоритма сжатия.
Состояние шифра Текущее состояние алгоритма шифрования. Оно состоит из текущего ключа для данного соединения. Кроме того, для блочного шифра, работающего в режиме CBC (единственный режим, специфицированный в TLS), оно в исходный момент содержит IV для данного состояния соединения и должно актуализоваться, чтобы содержать текст последнего шифрованного или дешифрованного блока. Для поточных шифров, оно содержит всю необходимую информацию для продолжения шифрования или дешифрования данных.
Секретный код MAC Секретный код MAC для данного соединения.
Номер по порядку Каждое состояние соединения содержит номер по порядку, который поддерживается независимо для состояний чтения и записи. Номер по порядку должен быть установлен равным нулю, как только соединение переведено в активное состояние. Номера по порядку имеют тип uint64 и не может превышать 264-1. Номер по порядку инкрементируется после прихода каждой записи: в частности, первая запись, передаваемая через некоторое соединение, имеет порядковый номер 0.
6.2. Уровень записей



Уровень записей TLS получает не интерпретированные данные от верхних уровней в непустых блоках произвольного размера.



6.2.1. Фрагментация



Уровень записей фрагментирует информационные блоки и превращают их в записи TLSPlaintext, несущие данные в виде последовательностей длиной 214 байтов или меньше.


Границы сообщения клиента на уровне записей не сохраняются (т.e., несколько сообщений клиента одного и того же ContentType могут быть объединены в одну запись TLSPlaintext, или одно сообщение может быть фрагментировано).

struct { uint8 major, minor;} ProtocolVersion;

enum { change_cipher_spec(20), alert(21), handshake(22),
application_data(23), (255)
} ContentType;
struct { ContentType type;

ProtocolVersion version;
uint16 length;
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;
type Протокол верхнего уровня, использованный для обработки вложенного фрагмента .
version Версия примененного протокола. В данном документе описывается TLS версии 1.0, который использует версию { 3, 1 }. Значение версии 3.1 является исторической: TLS версии 1.0 является минимальной модификацией протокола SSL 3.0, который несет значение версии 3.0. (Смотри приложение A.1).
length Длина (в байтах) следующего TLSPlaintext.fragment. Длина не должна превосходить 214.
Fragment Прикладные данные. Эти данные прозрачны и обрабатываются как независимые блоки, с которыми должен работать протокол верхнего уровня, который специфицирован полем тип.
Данные различных типов содержимого уровня записей TLS могут перекрываться. Прикладные данные вообще имеют более низкий приоритет при передаче, чем другие типы содержимого.



6.2.2. Сжатие и восстановление записи



Все записи сжаты с использованием алгоритма сжатия, определенным состоянием текущей сессии. Всегда имеется активный алгоритм сжатия; однако в исходный момент он определен как CompressionMethod.null. Алгоритм сжатия преобразует структуру TLSPlaintext в структуру TLSCompressed. Функции сжатия инициализируются информацией по умолчанию при переходе соединения в активное состояние.

Должно использоваться сжатие без потерь, а длина содержимого не может стать больше чем 1024 байт. Если функция восстановления встречает фрагмент TLSCompressed.fragment, длина которого окажется больше 214 байт, она должна выдать уведомление о фатальной ошибке преобразования.



Struct { ContentType type; /* то же самое, что и TLSPlaintext.type */
ProtocolVersion version; /* то же самое, что и TLSPlaintext.version */
uint16 length;
opaque fragment[TLSCompressed.length];
} TLSCompressed;
length Длина (в байтах) следующего TLSCompressed.fragment. Длина не должна превосходить 214 + 1024.
Fragment Сжатая форма TLSPlaintext.fragment.
Операция CompressionMethod.null является идентификационной; ни одно из полей не изменено.

Функции декомпрессии (восстановления) отвечают за то, что внутренний буфер не будет переполнен при обработке сообщения.



6.2.3. Защита поля данных записи



Функции шифрования и MAC преобразуют структуру TLSCompressed в TLSCiphertext. Функции дешифрования выполняют обратную процедуру. MAC записи включает также номер по порядку, чтобы было можно детектировать лишние или повторные сообщения.

Struct { ContentType type;
ProtocolVersion version;
uint16 length;
select (CipherSpec.cipher_type) {
case stream: GenericStreamCipher;
case block: GenericBlockCipher; } fragment;
} TLSCiphertext;
type Поле тип идентично TLSCompressed.type.
Version Поле версия идентично TLSCompressed.version.
length Длина (в байтах) последующего TLSCiphertext.fragment. Длина не может превосходить 214 + 2048.
Fragment Зашифрованная форма TLSCompressed.fragment, с MAC.
6.2.3.1. Нуль или стандартный поточный шифр



Поточные шифры (включая BulkCipherAlgorithm.null - смотри приложение A.6) преобразуют структуры TLSCompressed.fragment в (или из) структуры TLSCiphertext.fragment.

stream-ciphered struct { opaque content[TLSCompressed.length];

opaque MAC[CipherSpec.hash_size];} GenericStreamCipher;

MAC генерируется как:

HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +

TLSCompressed.version + TLSCompressed.length + TLSCompressed.fragment));

где "+" означает объединение (слияние).

seq_num Номер по порядку для данной записи.
hash Алгоритм хэширования, специфицированный в SecurityParameters.mac_algorithm.
<


/p> Заметим, что MAC вычисляется до шифрования. Поточный шифр преобразует весь блок, включая MAC. Для поточных шифров, которые не используют вектор синхронизации (такой как RC4), состояние шифра записи используется в последующих пакетах. Если CipherSuite равен TLS_NULL_WITH_NULL_NULL, шифрование представляет собой операцию идентичного преобразования (т.e., данные не шифруются, а размер MAC равен нулю, что говорит о том, что MAC не используется). TLSCiphertext.length равна TLSCompressed.length плюс CipherSpec.hash_size.



6.2.3.2. Блочный шифр CBC



Для блочных шифров (таких как RC2 или DES), функции шифрования и MAC преобразуют структуры TLSCompressed.fragment в блоки структур TLSCiphertext.fragment или обратно.

block-ciphered struct {

opaque content[TLSCompressed.length];
opaque MAC[CipherSpec.hash_size];
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;
} GenericBlockCipher;
MAC генерируется, как это описано в разделе 6.2.3.1.

Padding Заполнитель, который добавлен, чтобы сделать длину исходного текста целой кратной длине блока блочного шифра. Заполнитель может иметь длину вплоть до 255 байт. Длины больше необходимой могут оказаться желательными, для того чтобы блокировать атаки на протокол, базирующийся на анализе длин сообщений. Каждый uint8 в векторе заполняющих данных должен быть заполнен значением длины.
padding_length Длина заполнения должна быть такой, чтобы общий размер структуры GenericBlockCipher являлся кратным длине блока шифра. Диапазон легальных значений лежит в диапазоне 0-255, включительно. Эта длина специфицирует длину поля заполнителя, исключая само поле padding_length.
Длина шифрованных данных (TLSCiphertext.length) на единицу больше чем сумма TLSCompressed.length, CipherSpec.hash_size и padding_length.

Пример. Если длина блока равна 8 байт, длина содержимого (TLSCompressed.length) равна 61 байтов, а длина MAC равна 20 байтов, длина до заполнения составляет 82 байта. Таким образом, длина заполнения по модулю 8 должна быть равна 6, для того чтобы сделать полную длину четной, кратной 8 байтам (длина блока).


Длина заполнения может быть 6, 14, 22 и т.д. до 254. Если бы длина заполнения была минимально необходимой (6), заполнитель имел бы 6 байтов, каждый из которых содержал число 6. Таким образом, последние 8 октетов GenericBlockCipher до блочного шифрования были бы xx 06 06 06 06 06 06 06, где xx последний октет MAC.

Для блочного шифра в режиме CBC (Cipher Block Chaining) вектор инициализации (IV) для первой записи генерируется с другими ключами и секретными кодами, когда параметры безопасности заданы. IV для последующих записей равен последнему блоку шифрованного текста предыдущей записи.



6.3. Вычисление ключа



Протокол записей требует алгоритма для генерации ключей, IV и секретных кодов MAC из параметров безопасности, поставляемых протоколом диалога.

Мастерный секретный код (master secret) хэшируется в последовательность байтов, которая присваивается секретным кодам MAC, ключам и IV, требуемых текущим состоянием соединения (смотри приложение A.6). CipherSpecs требует чтобы клиент записал секретный код MAC, чтобы сервер записал секретный код MAC, клиент и сервер записали ключ и IV, которые сформированы из мастерного секретного кода в указанном порядке. Не использованные значения остаются пустыми.

Для генерации ключей вычисляется

key_block = PRF(SecurityParameters.master_secret, "key expansion",

SecurityParameters.server_random + SecurityParameters.client_random);

до тех пор пока не будет сформирован выход. Затем key_block позиционируется следующим образом:

client_write_MAC_secret[SecurityParameters.hash_size]

server_write_MAC_secret[SecurityParameters.hash_size]

client_write_key[SecurityParameters.key_material_length]

>server_write_key[SecurityParameters.key_material_length]

client_write_IV[SecurityParameters.IV_size]

server_write_IV[SecurityParameters.IV_size]

Значения client_write_IV и server_write_IV генерируются только для не экспортных блочных шифров. Для экспортируемых блочных шифров, векторы инициализации генерируются позже, как это описано ниже.


Любой лишний материал key_block отбрасывается.

Спецификация шифра, которая определена в данном документе, требует 2 x 24 байтовых ключей, 2 x 20 байтовых секретных кодов MAC, и 2 x 8 байтов IV, для 104 байтов материала ключей.

Алгоритмы экспортируемого шифрования (для которого CipherSpec.is_exportable равно 'истинно') требуют дополнительной обработки для получения ключей записи, как это показано ниже:

final_client_write_key =

PRF(SecurityParameters.client_write_key,

"client write key",
SecurityParameters.client_random +
SecurityParameters.server_random);
final_server_write_key =

PRF(SecurityParameters.server_write_key,

"server write key",
SecurityParameters.client_random +
SecurityParameters.server_random);
Алгоритмы экспортируемого шифрования получают свои IV исключительно из случайных кодов сообщений hello:

iv_block = PRF("", "IV block", SecurityParameters.client_random +

SecurityParameters.server_random);
Блок iv_block делится на два инициализационных векторов, как это делалось выше для key_block:

client_write_IV[SecurityParameters.IV_size]

server_write_IV[SecurityParameters.IV_size]

Заметим, что PRF используется в этом случае без секретного кода: это означает, что секретный код имеет длину нуль байт и не вносит ничего в хэширование PRF.



6.3.1. Пример генерации экспортного ключа



TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 требует пяти случайных байт для каждого из двух ключей шифрования и 16 байт для каждого ключа MAC, что составляет 42 байта ключевого материала. Выход PRF запоминается в key_block. Блок key_block делится, а ключи записи запоминаются, так как это алгоритм экспортного шифрования.

key_block = PRF(master_secret,
"key expansion",
server_random +
client_random)[0..41]
client_write_MAC_secret = key_block[0..15]
server_write_MAC_secret = key_block[16..31]
client_write_key = key_block[32..36]
server_write_key = key_block[37..41]
final_client_write_key = PRF(client_write_key,
"client write key",
client_random +
server_random)[0..15]
final_server_write_key = PRF(server_write_key,
"server write key",
client_random +
server_random)[0..15]
iv_block = PRF("", "IV block", client_random +
server_random)[0..15]
client_write_IV = iv_block[0..7]
server_write_IV = iv_block[8..15]



Содержание раздела