T. Dierks, E. Rescorla
Протокол безопасности транспортного уровня (TLS)
Версия 1.2
Запрос на комментарии 5246 (RFC 5246)
Август 2008
Часть 2
Данная статья является второй частью перевода протокола безопасности транспортного уровня (TLS) версии 1.2 (RFC 5246). Эта часть содержит описание протокола записи TLS.
Другие части перевода: Часть 1, Часть 3.1, Часть 3.2.
Примечание по терминологии: в данном переводе используется термин «сложение по модулю 2», идентичный в русскоязычной литературе термину «операция исключающего «ИЛИ», оба из которых, в свою очередь, соответствуют англоязычным терминам «exclusive-OR» и «XOR».
Содержание
6. Протокол записи TLS
Протокол записи TLS (англ. TLS Record Protocol) является многоуровневым протоколом (англ. layered protocol). На каждом уровне сообщения могут включать поля со значениями длины сообщения, его описанием и, собственно, содержимым сообщения. Протокол записи обрабатывает сообщения, которые затем отправляются им далее, путем фрагментации данных в оперируемые блоки, присоединения кода аутентификации сообщения (далее – MAC [1]) и шифрования, кроме того, имеется дополнительная возможность сжатия сообщения. При приеме сообщений данные расшифровываются, проверяются, распаковываются (англ. decompressed), пересобираются (англ. reassembled), после чего отправляются клиентам более высоких уровней.
В данном документе описываются 4 протокола, использующие протокол записи: протокол рукопожатия (тж. согласования параметров) (англ. handshake protocol), оповещений (англ. alert protocol), изменения параметров шифрования (англ. change cipher spec protocol) и протокол данных приложения (англ. application data protocol). В целях расширяемости протокола TLS протоколом записи могут поддерживаться дополнительные типы содержимого записей (англ. record content). Новые цифровые коды, соответствующие новым типам содержимого записей, задаются IANA в регистре TLS ContentType (тип содержимого TLS) раздела регистров «Transport Layer Security (TLS) Parameters» по принципу, указанному в Разделе 12 данного документа.
Реализуемые приложения не должны пересылать типы записей, не определенные в этом документе, за исключением случаев, при которых они согласовываются каким-либо расширением. Если приложение, реализующее протокол TLS, получает сообщение с неизвестным (англ. unexpected) типом записи, оно должно отправить обратно сообщение «unexpected_message
» (неизвестное сообщение).
Каждый разрабатываемый протокол, планируемый к использованию поверх TLS, должен строиться с учетом всех потенциальных атак, с которым этот протокол может столкнуться. На практике это означает, что разработчик протокола должен знать какие параметры безопасности предоставляет протокол TLS, а какие – не предоставляет, и не упускать последнее из виду.
В частности, нужно обратить внимание, что тип и длина записи не защищены шифрованием. Если эта ситуация является чувствительной сама по себе, разработчики приложения могут предпринять некоторые шаги (увеличение размера поля, наложение шума) для минимизации утечки подобной информации.
6.1. Состояния соединения
Состояние соединения TLS (англ. TLS connection state) – это рабочая среда протокола записи TLS. Состояние описывает алгоритм сжатия, алгоритм шифрования и алгоритм создания MAC. Вдобавок к этому, параметры этих алгоритмов известны: ключ MAC и ключи канального шифрования (англ. bulk encryption keys) для соединения в обоих направлениях - как для чтения (отправки), так и для записи (приема). Исходя из логики, имеется четыре наиболее заметных состояния соединения: рабочие состояния (англ. current states) чтения и записи, а также состояния ожидания (англ. pending states) чтения и записи. Все записи обрабатываются под рабочими состояниями чтения и записи. Параметры безопасности для состояний ожидания могут быть установлены протоколом рукопожатия, а сообщениеChangeCipherSpec
[2] может выборочно делать одно из двух состояний ожидания рабочим, в результате чего бывшее рабочим состояние выключается (англ. disposed of) и заменяется состоянием ожидания; после этого смененное на рабочее состояние ожидания заново инициализируется как пустое состояние (англ. empty state). Не допускается переводить в рабочее такое состояние, которое было инициализированно без параметров безопасности. Начальное рабочее состояние (англ. initial current state) всегда определяет то, что средой еще не было произведено ни одной из операций шифрования, сжатия или создания кода MAC.
Параметры безопасности для состояния чтения и записи соединения TLS задаются следующими значениями[3]:
connection end
Параметр отвечает за то, чем будет считаться конкретный узел в данном соединении – «клиентом» или «сервером».
PRF algorithm
Алгоритм псевдослучайной функции, используемый для генерации ключей из основного секрета (см. Разделы 5 и 6.3).
bulk encryption algorithm
Алгоритм канального шифрования[4]. Данный параметр определяет размер ключа алгоритма, тип шифрования – блочное, потоковое или AEAD, размер блока шифра (при использовании блочного шифрования), длины явного и неявного векторов инициализации[5] (англ. initialization vectors, IV[6]) (либо nonce-параметров)[7].
MAC algorithm
Алгоритм, используемый для аутентификации сообщения. Данный параметр, помимо прочего, содержит размер кода MAC.
compression algorithm
Алгоритм сжатия данных. Параметр должнен включать всю информацию, требуемую алгоритму для сжатия (компрессии) данных.
master secret
Основной секрет (тж. мастер-секрет). Общее для двух соединяющихся узлов секретное число размером 48 байт.
client random
32-битное случайное значение, генерируемое клиентом.
server random
32-битное случайное значение, генерируемое сервером.
Указанные параметры определены в псевдоязыке представления как:
enum { server, client } ConnectionEnd;
enum { tls_prf_sha256 } PRFAlgorithm;
enum { null, rc4, 3des, aes } BulkCipherAlgorithm;
enum { stream, block, aead } CipherType;
enum { null, hmac_md5, hmac_sha1, hmac_sha256,
hmac_sha384, hmac_sha512} MACAlgorithm;
enum { null(0), (255) } CompressionMethod;
/* В поля CompressionMethod, PRFAlgorithm, BulkCipherAlgorithm и MACAlgorithm могут быть добавлены другие алгоритмы */
Таким образом, структура, содержащая параметры безопасности, выглядит как:
struct {
ConnectionEnd entity;
PRFAlgorithm prf_algorithm;
BulkCipherAlgorithm bulk_cipher_algorithm;
CipherType cipher_type;
uint8 enc_key_length;
uint8 block_length;
uint8 fixed_iv_length;
uint8 record_iv_length;
MACAlgorithm mac_algorithm;
uint8 mac_length;
uint8 mac_key_length;
CompressionMethod compression_algorithm;
opaque master_secret[48];
opaque client_random[32];
opaque server_random[32];
} SecurityParameters;
Уровень записи использует параметры безопасности для генерации следующих шести элементов (некоторые из них не являются обязательными для всех шифров (а именно:client write IV, server write IV
), оставаясь, в таком случае, пустыми):
client write MAC key /* секретный ключ для аутентификации данных, отправляемых клиентом*/
server write MAC key /* секретный ключ для аутентификации данных, отправляемых сервером*/
client write encryption key /* ключ шифрования данных, отправляемых клиентом */
server write encryption key /* ключ шифрования данных, отправляемых сервером */
client write IV /* вектор инициализации для данных, отправляемых клиентом */
server write IV /* вектор инициализации для данных, отправляемых сервером */
Параметры записи клиента (client write
) используются сервером при приеме и обработке записей (англ. records), отправленных клиентом, и наоборот. Алгоритм, используемый для генерации этих элементов из параметров безопасности, описан в Разделе 6.3.
Если параметры безопасности были определены, а ключи – сгенерированы, то состояние соединения может быть преобразовано в рабочее состояние. Рабочие состояния ДОЛЖНЫ обновляться (англ. be updated) при обработке каждой записи. Каждое состояние соединения включает в себя следующие элементы:
compression state
Состояние алгоритма сжатия.
cipher state
Состояние шифрования - текущее состояние алгоритма шифрования. Состоит из назначенного для данного соединения ключа. При использовании потокового шифра в данном параметре будет содержаться любая необходимая алгоритму информация состояния для продолжения шифрования или дешифрования данных.
MAC key
Ключ аутентификации данных для данного соединения.
sequence number
Каждое состояние соединения содержит число число порядка, поддерживаемое отдельно для состояний чтения и записи. Число порядка ДОЛЖНО быть определено как 0 всякий раз, когда состояние соединения становится активным состоянием. Числа порядка имеют тип uint64
и не могут превышать значения 2^64-1
. Числа порядка не обертываются (англ. do not wrap). Если реализации TLS понадобится обернуть такое число, то вместо этого необходимо произвести пересогласование параметров (англ. to renegotiate). Число порядка увеличивается после обработки каждой записи: в частности, первая запись, передаваемая в отдельном соединении, ДОЛЖНА использовать число, равное 0.
6.2. Уровень записей
Протокол записи TLS получает неинтепретированные данные от протоколов верхнего уровня в непустых блоках произвольного размера.
6.2.1. Фрагментация
Уровень записи фрагментирует блоки с информацией в записи типа TLSPlaintext
, передающие данные порциями (англ. chunks) размерами в 2^14 байт (16 кБ) или менее. На уровне записей границы сообщения клиента никак не определены (то есть, множество сообщений клиента, имеющих одинаковое значение типа содержимого (ContentType
) могут быть слиты в одну запись TLSPlaintext
, и в то же время одно сообщение может быть разбито на несколько отдельных записей).
К записям типаTLSPlaintext
присоединяется структура, обозначающая версию используемого протокола TLS, а также перечисление с возможными типами содержимого данного типа записи:
struct {
uint8 major;
uint8 minor;
} ProtocolVersion;
enum {
change_cipher_spec(20), alert(21), handshake(22),
application_data(23), (255)
} ContentType; /* перечисление со значениями типов содержимого*/
/*для которого отводится 1 байт памяти*/
struct {
ContentType type;/* принимает значения 20, 21, 22, 23 в зависимости от типа содержимого*/
ProtocolVersion version;
uint16 length;
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;
Каждая запись типа TLSPlaintext
содержит следующие параметры:
type
Протокол TLS верхнего уровня, используемый для обработки помещаемого внутрь записи типаTLSPlaintext
фрагмента данных.
version
Версия применяемого протокола. Данный документ описывает TLS версии 1.2, который использует значение данного параметра, равное {3,3}
[8]. Значение версии, равное 3,3 – историческое, поскольку для обозначения TLS 1.0 использовалось значение 3.1 (см. Прил. А.1). Обратите внимание, что клиент, поддерживающий несколько версий TLS, может не знать какую ему следует использовать версию до момента, пока не получит сообщение ServerHello
[25]. В Прил. Е рассматриваются вопросы того, какой номер версии следует применять при отправке сообщения ClientHello
.
length
Длина в байтах элемента TLSPlaintext.fragment
[9]. Значение длины не должно превышать 2^14 байт (16 кБ).
fragment
Данные приложения. Такие данные прозрачны и рассматриваются протоколом верхнего уровня, указанным в поле «type
», в качестве независимого блока, требующего обработки.
Реализации протокола НЕ ДОЛЖНЫ посылать фрагменты нулевой длины с типом содержимого ChangeCipherSpec
, Alert
или Handshake
[26]. Фрагменты нулевой длины данных приложения (англ. application data) могут посылаться, поскольку они являются потенциально полезными в качестве контрмеры в отношении анализа трафика.
Примечание. На уровне записи данные различных типов содержимого слоя записи TLS могут перемежаться между собой (англ. be interleaved). Данные приложения, обычно, имеют меньший приоритет для передачи, чем другие типы содержимого. Однако, записи должны быть отправлены в сеть в том порядке, в котором они были обработаны уровнем записи. Реципиенты сообщения ДОЛЖНЫ, в свою очередь, получить и обработать перемежающийся трафик уровня приложения во время рукопожатий, следующих за первым рукопожатием соединения.
6.2.2. Сжатие и распаковка записей
Все записи сжимаются с использованием алгоритма, определенном в рабочем состоянии сессии. В сессии всегда явно указан активный алгоритм сжатия, однако в ее начале в параметрах безопасности алгоритм сжатия указан как CompressionMethod.null
. Алгоритм сжатия переводит структуру TLSPlaintext
в структуру TLSCompressed
. Функции сжатия инициализируются вместе с установленной по умолчанию информацией соединения всякий раз, когда состояние соединения становится активным (рабочим). Алгоритмы сжатия для протокола TLS описаны в [RFC3749][10] .
Сжатие должно происходить без потерь и не должно превышать длину содержимого (т.е. структуры типа TLSPlaintext
) более чем на 1024 байта. Если функция распаковки данных обнаружит элемент TLSCompressed.fragment
, который при распаковке будет иметь длину более 2^14
байт, она ДОЛЖНА выдать сообщение о критической ошибке распаковки (англ. fatal decompression failure error).
Структура TLSCompressed
выглядит как:
struct {
ContentType type; /* такой же тип, как и у TLSPlaintext.type */
ProtocolVersion version; /* такая же версия, как и у */
/*TLSPlaintext.version */
uint16 length;
opaque fragment[TLSCompressed.length];
} TLSCompressed;
Параметры структуры TLSCompressed
:
length
Длина (в байтах) элемента TLSCompressed.fragment
. Длина не должна превышать 2^14 + 1024
байт.
fragment
Сжатая форма элемента TLSPlaintext.fragment
.
Примечание: Операция CompressionMethod.null
является операцией тождества (англ. identity operation). Это означает, что при ее выполнении содержимое полей не меняется.
Примечание для реализаций: Именно на функции распаковки возлагается задача удостовериться в том, что распаковываемые сообщения не вызовут внутреннего переполнения буфера .
6.2.3. Защита записей
Функции шифрования и создания MAC переводят структуру типа TLSCompressed
в структуру типа TLSCiphertext
. Функции расшифровки производят обратную операцию. Mac-код записи, кроме всего прочего, содержит число порядка, что позволяет обнаружить пропавшие, излишние или повторяющиеся записи.
struct {
ContentType type;
ProtocolVersion version;
uint16 length;
select (SecurityParameters.cipher_type) {
case stream: GenericStreamCipher;
сase block: GenericBlockCipher;
case aead: GenericAEADCipher;
} fragment;
} TLSCiphertext;
Как видно, в приведенной выше структуре типа TLSCiphertext
имеется механизм выбора, включающий три варианта шифрования: потоковое (GenericStreamCipher
), блочное (GenericBlockCipher
) либо AEAD-шифрование (с дополнительными данными)(GenericAEADCipher
).
type
Поле с указанием типа. Идентично полю TLSCompressed.type
.
version
Поле с указанием версии. Идентично полю TLSCompressed.version
.
length
Длина (в байтах) элемента TLSCiphertext.fragment
. Длина не должна превышать 2^14 + 2048
байт.
fragment
Зашифрованная форма TLSCompressed.fragment
с присоединенным MAC.
6.2.3.1. Нулевой шифр и стандартный потоковый шифр
Потоковые шифры (включая BulkCipherAlgorithm.null
см. Прил. А.6) превращают структуры TLSCompressed.fragment
в поток структур TLSCiphertext.fragment
и наоборот:
stream-ciphered struct {
opaque content[TLSCompressed.length];
opaque MAC[SecurityParameters.mac_length];
} GenericStreamCipher;
MAC генерируется как:
MAC(MAC_write_key, seq_num +
TLSCompressed.type +
TLSCompressed.version +
TLSCompressed.length +
TLSCompressed.fragment);
где "+" обозначает конкатенацию.
seq_num
Число порядка для данной записи.
MAC
Алгоритм вычисления MAC, указанный в поле SecurityParameters.mac_algorithm
.
Обратите внимание, что MAC вычисляется до шифрования. Потоковый шифр шифрует целый блок данных, включая и MAC. Потоковые шифры не использующие вектор синхронизации (например, RC4[11]), используют состояние шифрования[12], имеющееся в конце одной записи, попросту перенося его на следующий пакет данных. При использовании криптонабора TLS_NULL_WITH_NULL_NULL
(нулевого шифра) шифрование является операцией тождества (т. е. данные не шифруются, размер MAC равен 0, из чего следует, что MAC не используется). При использовании нулевого или потокового шифра поле TLSCiphertext.length,
выражается как:
TLSCiphertext.length = TLSCompressed.length + SecurityParameters.mac_length
где «+» означает операцию сложения [27].
6.2.3.2. Блочный шифр в режиме сцепления блоков (CBC-шифр)
[13]Блочные шифры (такие как 3DES или AES), используя функции шифрования сообщения и создания MAC, превращают структуры TLSCompressed.fragment
в блоки структур TLSCiphertext.fragment
и наоборот:
struct {
opaque IV[SecurityParameters.record_iv_length];
block-ciphered struct {
opaque content[TLSCompressed.length];
opaque MAC[SecurityParameters.mac_length];
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;
};
} GenericBlockCipher;
При этом MAC вычисляется так же, как указано в п. 6.2.3.1.
Структура GenericBlockCipher
имеет следующие параметры:
IV
Вектор инициализации (англ. Initialization Vector) (далее – IV) рекомендуется выбирать случайным образом, в то же время он должен обладать свойством непредсказуемости. Обратите внимание, что в версиях TLS, вышедших до версии 1.1, не было поля IV
, и в качестве IV
использовался последний блок шифротекста предыдущей записи ("CBC-остаток", англ. "CBC residue"). Вектор IV
был введен для предотвращения атаки, описанной в [CBCATT][14]. Длина IV
для блочного шифра указывается в поле SecurityParameters.record_iv_length
, равном значению поля SecurityParameters.block_size
[15].
padding
Дополнительное заполнение (тж. набивка) – используется для того, чтобы длина незашифрованного текста (англ. plaintext) стала целым числом, кратным длине блока блочного шифра. Набивка МОЖЕТ иметь длину от 0 до 255 байт включительно, не имея обязательных требований к её значению. Единственное требование – значение TLSCiphertext.length
в итоге должно быть целым числом кратным длине блока. Значение длины, больше необходимого, может оказаться желательным для противодействия атакам, основанным на анализе длины обмениваемых сообщений. Каждое значение типа uint8
, содержащееся в векторе набивки, должно содержать значение длины набивки. Реципиент должен проверять данные набивки и отправлять сообщение "bad_record_mac"
при возникновении каких-либо ошибок при обработке ее данных.
padding_length
Значение длины набивки – ДОЛЖНО быть таким, чтобы общий размер структуры GenericBlockCipher
был целым числом, кратным длине блока шифра. Значение поля может варьироваться от 0 до 255 включительно. Значение этого поля указывает длину поля padding
за исключением длины самого поля padding_length
.
Длина зашифрованных данных (TLSCiphertext.length
), таким образом, превышает общую сумму полей SecurityParameters.block_length
, TLSCompressed.length
, SecurityParameters.mac_length
и padding_length
.
Пример: при размере блока, равном 8 байт, длина содержимого (TLSCompressed.length
) равна 61 байт, длина MAC – 20 байт. Таким образом, длина незашифрованного сообщения до операции набивки равна 82 байта[16] (не включая IV
). Таким образом, остаток от деления значения длины набивки на 8 должен быть равен 6 для того, чтобы общая длина сообщения была четным числом, кратным 8 (длине блока). Длина набивки, в данном случае, будет равна 6, 14, 22 и тд., вплоть до 254 байт. Если длина набивки будет минимальным необходимым значением (6 байт), то каждый ее байт должен содержать в себе значение 6. Таким образом, последние 8 октетов структуры GenericBlockCipher
до шифрования блока должны иметь форматxx 06 06 06 06 06 06 06
– где xx, последний октет MAC [28].
Обратите внимание: при блочном шифровании в режиме сцепления блоков (Cipher Block Chaining), критически важно, чтобы весь незашифрованный текст записи был известен до того как был передан какой-либо зашифрованный текст. В противном случае возможно осуществить атаку, описанную в [CBCATT] [29].
Заметки для реализации: Canvel и другие в [CBCTIME][17] продемонстрировали атаку тайминга при обработке CBC-набивки, где в качестве уязвимости используется период времени, в который происходит расчет MAC. Для защиты от этой атаки все реализации должны обеспечивать одинаковое время обработки сообщения вне зависимости от того содержит набивка ошибки или нет. В общем случае, наилучшим решением для этого будет расчет MAC в любом случае – вне зависимости от того, корректна набивка или нет, и отбрасывать пакет только после этого расчета. Например, если набивка содержит какие-либо ошибки, конкретное приложение должно присваивать набивке нулевую длину, после чего вычислять MAC. При этом временной канал будет достаточно малым, поскольку обработка MAC, в некоторой степени, зависит от размера фрагмента данных, но и, как думается, не слишком большим для нормального функционирования, так как размер временного интервала будет слишком малым для расчета блока MAC достаточного размера.
6.2.3.3. Шифры AEAD (с дополнительно прикрепляемыми данными)
При работе шифров [AEAD][18] (таких как [CCM][19] или [GCM][20]) функция AEAD превращает структуры TLSCompressed.fragment
в AEAD-структуры TLSCiphertext.fragment
, и наоборот.
Входными данными AEAD-шифров являются: один ключ (write-key
), однократно используемый параметр nonce
, незашифрованное сообщение (plaintext), а также «дополнительные данные», которые включаются в элемент проверки аутентифкации, как это описано в разделе 2.1 [AEAD]. Ключ является либо элементом client_write_key
, либо server_write_key
. При этом MAC-ключ не используется.
Криптонабор на основе AEAD-шифрования ДОЛЖЕН указывать как рассчитывается параметр nonce
, используемый в данном алгоритме, и какова длина параметра GenericAEADCipher.nonce_explicit
, являющегося частью структуры GenericAEADCipher
. Во многих случаях приемлемо использовать технику вычисления частично скрытого nonce
(англ. partially implicit nonce), описанную в п. 3.2.1 [AEAD], в то время как значение record_iv_length
будет длиной открытой части этого параметра. В этом случае РЕКОМЕНДУЕТСЯ, чтобы скрытая часть была производной от блока ключа (key_block
) являясь client_write_iv
и server_write_iv
(как описано в Разделе 6.3), а открытая часть – была включена в GenericAEAEDCipher.nonce_explicit
.
Незашифрованное сообщение - TLSCompressed.fragment
[31].
Дополнительные данные аутентификации, которые мы обозначаем как additional_data
определяются следующим образом:
additional_data = seq_num
[30] + TLSCompressed.type + +TLSCompressed.version + TLSCompressed.length;
где "+" обозначает конкатенацию.
Выходные данные AEAD-шифра (aead_output
) состоят из шифротекста, производимого операцией AEAD-шифрования. Значение длины этих данных, в общем случае, будет больше значения TLSCompressed.length
, но величина этого превышения будет зависеть от типа AEAD-шифра. Поскольку операции шифрования может, также, подвергаться и набивка, общий объем превышения служебных данных, содержащихся в выходном сообщении шифра, может зависеть от значений TLSCompressed.length
. При этом выходные данные любого AEAD-шифра НЕ ДОЛЖНЫ превышать исходные данные более чем на 1024 байт. Символически это может быть записано как:
AEADEncrypted = AEAD-Encrypt(write_key, nonce, plaintext, additional_data)
Для того, чтобы расшифровать и проверить сообщения, в качестве входных данных шифр получает ключ, параметр nonce
, дополнительные данные ("additional_data") и значение AEADEncrypted
. Выходными данными при этом будут либо исходное незашифрованное сообщение, либо ошибка, указывающая на невозможность расшифровки. При этом не происходит отдельной проверки целостности (англ. integrity check):
TLSCompressed.fragment = AEAD-Decrypt(write_key, nonce, AEADEncrypte, additional_data)
При невозможности расшифровки должно быть сгенерировано сообщение критической ошибки «bad_record_mac
».
6.3. Вычисление ключа
Протоколу записи требуется алгоритм генерации ключей, которые необходимы ему для функционирования в рабочем состоянии соединения (см. Прил. А. 6). Сами ключи генерируются из параметров безопасности, предоставляемых протоколом рукопожатия[21].
Основной секрет (англ. master secret) преобразуется в последовательность защищенных байтов, которая затем разделяется на:
client write MAC key
,server write MAC key
(ключи аутентификации данных, отправляемых клиентом и сервером, соответственно);client write encryption key
,server write encryption key
(ключи шифрования данных, отправляемых клиентом и сервером, соответственно).
Каждый из ключей генерируется из байтовой последовательности в указанном порядке. Неиспользуемые значения отбрасываются. Некоторые шифры AEAD могут дополнительно требовать client write IV
и server write IV
(векторы инициализации данных, отправляемых клиентом и сервером, соответственно) (см. п. 6.2.3.3).
После генерации ключей и ключей MAC главный секрет используется как источник энтропии[22].
Вычисление ключевого материала[23] (англ. key material) происходит с использованием следующей псевдослучайной функции (PRF) до того момента, пока не будет вычислен достаточный объем данных:
key_block = PRF(SecurityParameters.master_secret,
"key expansion",
SecurityParameters.server_random +
SecurityParameters.client_random);
[24]После чего key_block
делится на части в следующем порядке:
client_write_MAC_key[SecurityParameters.mac_key_length]
server_write_MAC_key[SecurityParameters.mac_key_length]
client_write_key[SecurityParameters.enc_key_length]
server_write_key[SecurityParameters.enc_key_length]
client_write_IV[SecurityParameters.fixed_iv_length]
server_write_IV[SecurityParameters.fixed_iv_length]
На данный момент client_write_IV
и server_write_IV
вычисляются только при использовании методики скрытого nonce
, описанной в п. 3.2.1 [AEAD] (см. тж. п. 6.2.3.3).
Примечание для реализации: На момент написания стандарта криптонабором, требующим наибольшего размера для значения key_block
, являлся набор AES_256_CBC_SHA256
. Он требует 2 x 32 байт для ключей и 2 x 32 байт для ключей MAC, что в общей сложности составляет 128 байт.
[1] MAC – Message Authentification Code. В русскоязычной литературе также может применяться термин «имитовставка» (Прим. перев.).
[2] Сообщение протокола изменения параметров шифрования. Сам протокол описывается в разделе 7.1 данного Стандарта и является одним из трех подпротоколов процесса рукопожатия (Прим. перев.).
[3] Параметры безопасности TLS предоставляются протоколом рукопожатия (англ. Handshake protocol) (см. тж. Прил. А.6 стандарта) (Прим. перев.).
[4] Канальное шифрование (англ. bulk cipher) определено в Приложении B данного стандарта как: алгоритм симметричного шифрования, используемый для шифрования больших объемов данных.
[5] О неявном и явном задании векторов инициализации см. п. 6.2.3.3. (Прим. перев.).
[6] Вектор инициализации определен в Приложении B данного стандарта как: элемент, который в CBC-режиме блочного шифрования складывается по модулю 2 с первым блоком незашифрованного текста. О CBC-режиме см. прим. 13 (Прим. перев.).
[7] Однократно используемый параметр, одноразовый параметр (англ. nonce) – аббревиатура от англ. «number that can only be used once». Случайное или псевдослучайное число, однократно выбранное системой при создании параметров сетевого соединения (Прим. перев.).
[8] Таким образом, параметр version
задает значения для полей типизированной константы ProtocolVersion
. Значение полей этой константы: major = 3
, значение поля minor = 3
. (см. тж. п. 4. 8 данного стандарта) (Прим. перев.).
[9] Фрагмент незашифрованного сообщения (Прим. перев.).
[10] Hollenbeck, S., "Transport Layer Security Protocol Compression Methods", RFC 3749, May 2004.
[11] В феврале 2015 года вышел документ RFC 7465, запрещающий использование шифра RC4 в криптонаборах протоколов TLS всех версий (Прим. перев.).
[12] Определение состояния шифрования приведено в п. 6.1. Для потокового шифра его состояние шифрования задается параметрами генератора псевдослучайных чисел (ГПСЧ), выдающего гамму (тж. ключевой поток данных, keystream). Гамма складывается по модулю 2 с текстом сообщения (англ. XORed), что дает шифротекст. В этом случае состояние шифрования меняется функцией состояния потокового шифра, задающей новые параметры для ГПСЧ. (Прим. перев.).
[13] CBC, cipher block chaining в приложении B данного стандарта определен как: режим, в котором каждый блок незашифрованного текста складывается по модулю 2 (англ. exclusive-Ored) с предыдущим зашифрованным блоком (либо с вектором инициализации, если этот блок идет первым в последовательности). Для расшифровки каждый блок шифротекста сначала расшифровывается, затем складывается по модулю 2 с предыдущим блоком шифротекста (либо с вектором инициализации).
[14] Moeller, B., "Security of CBC Ciphersuites in SSL/TLS: Problems and Countermeasures", http://www.openssl.org/~bodo/tls-cbc.txt.
[15] Раздел ошибок стандарта содержит указание на неподтвержденную ошибку (ID 6244) в которой говорится, что в блоке SecurityParameters
есть параметр block_length
, но нет параметра block_size
(см. Разд. 6.1.) (Прим. перев.).
[16] Еще один байт данных добавляется для поля padding_length
(Прим. перев.).
[17] Canvel, B., Hiltgen, A., Vaudenay, S., and M. Vuagnoux, "Password Interception in a SSL/TLS Channel", Advances in Cryptology -- CRYPTO 2003, LNCS vol. 2729, 2003.
[18] McGrew, D., "An Interface and Algorithms for Authenticated Encryption", RFC 5116, January 2008.
[19] "NIST Special Publication 800-38C: The CCM Mode for Authentication and Confidentiality", https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38c.pdf
[20] Dworkin, M., NIST Special Publication 800-38D, "Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC", November 2007.
[21] Сами параметры безопасности перечислены в Разд. 6.1 (Прим. перев.).
[22] Энтропия – неопределенность в системе. В данном случае под источником энтропии подразумевается достаточно неопределенное для предсказания значение, которое можно использовать, например, как начальное число (затравка) в генераторе псевдослучайных чисел и т. п. (Прим. перев.).
[23] Прил. C данного стандарта определяет ключевой материал как число байт значения key_block
, необходимое для генерации ключей записи (write key
). В данном определении ключевой материал не включает в себя векторы инициализации (IV
). Как видно, здесь термин «ключевой материал» включает в себя и векторы инициализации. (Прим. перев.).
[24] Раздел 5 стандарта определяет PRF
как PRF(secret, label, seed)
. Таким образом, SecurityParameters.master_secret = secret,
сумма SecurityParameters.server_random + SecurityParameters.client_random = seed
(начальное значение). А строка «key expansion
» является меткой (label
). Подробнее о PRF стандарта TLS см. Разд. 5. (Прим. перев.).
[25] Серверное hello-сообщение рассматривается в п. 7.4.1.2 Стандарта и является одним из сообщений протокола рукопожатия TLS (Прим. перев).
[26]ChangeCipherSpec (
изменение параметров шифрования)
, Alert (
оповещения)
и Handshake (
рукопожатие)
являются тремя подпротоколами процесса рукопожатия TLS и описываются в разделе 7 данного стандарта (Прим. перев.).
[27] Понятно, что при использовании нулевого шифра TLSCiphertext.length = TLSCompressed.length,
так как в этом случае SecurityParameters.mac_length = 0
(Прим. перев).
[28] Как видно, в конце сообщения содержится 6 байт набивки + 1 байт со значением ее длины (Прим. перев.).
[29] См. Прим. 14.
[30] Seq_num - число порядка (см.тж. Разд.6. 1) (Прим. перев.).
[31] Как видно, незашифрованное сообщение является сообщением, подвергнутым операции сжатия (Прим. перев.).