RFC 8446 | Протокол безопасности транспортного уровня (TLS) версии 1.3

Резюме

В этом документе указана версия 1.3 протокола безопасности транспортного уровня (TLS). TLS позволяет приложениям клиент-сервер взаимодействовать через Интернет таким образом, чтобы предотвратить подслушивание, вмешательство и подделку сообщений.

Этот документ обновляет RFCs 5705 и 6066 и устаревает RFCs 5077, 5246 и 6961. В этом документе также указаны новые требования к реализациям TLS 1.2.
Скачать оригинальный документ на английском языке RFC 8446 PDF

Оглавление

1. Введение
1.1. Конвенции и терминология
1.2. Основные отличия от TLS 1.2
1.3. Обновления, влияющие на TLS 1.2
2. Обзор протокола
2.1. Неправильная доля DHE
2.2. Возобновление и предварительный ключ (PSK)
2.3. Данные 0-RTT
3. Язык презентации
3.1. Размер основного блока
3.2. Смешанный (разнообразный)
3.3. Числа
3.4. Векторы
3.5. Перечисления
3.6. Построенные типы
3.7. Константы
3.8. Варианты
4. Протокол рукопожатия
4.1. Сообщения об обмене ключами
4.1.1. Криптографические переговоры
4.1.2. Приветствие клиента — Client Hello
4.1.3. Приветствие сервера — Server Hello
4.1.4. Запрос Hello Retry
4.2. Расширения
4.2.1. Поддерживаемые версии
4.2.2. Печенье — Cookie
4.2.3. Алгоритмы подписи
4.2.4. Органы по сертификации
4.2.5. Фильтры OID
4.2.6. Аутентификация клиента после рукопожатия
4.2.7. Поддерживаемые группы
4.2.8. Основная доля
4.2.8.1. Параметры Диффи-Хелмана
4.2.8.2. Параметры ECDHE
4.2.9. Режимы обмена с предварительным обменом ключами
4.2.10. Ранняя индикация данных
4.2.11. Расширение предварительного ключа
4.2.11.1. Возраст билета
4.2.11.2. PSK связыватель
4.2.11.3. Порядок обработки
4.3. Параметры сервера
4.3.1. Шифрованные расширения
4.3.2. Запрос сертификата
4.4. Сообщения об аутентификации
4.4.1. Стенограмма-стенограмма
4.4.2. Сертификат
4.4.2.1. Статус OCSP и расширения SCT
4.4.2.2. Выбор сертификата сервера
4.4.2.3. Выбор сертификата клиента
4.4.2.4. Получение сообщения сертификата
4.4.3. Проверка сертификата
4.4.4. Закончено
4.5. Конец ранних данных
4.6. Сообщения после рукопожатия
4.6.1. Сообщение о новом сеансе связи
4.6.2. Аутентификация после авторизации
4.6.3. Обновление вектора ключей и инициализации
5. Протокол записи
5.1. Рекордный уровень (Уровень записи)
5.2. Запись полезной нагрузки
5.3. Одноразовая пре-запись
5.4. Заполнение записи
5.5. Пределы использования ключа
6. Протокол оповещений
6.1. Оповещения о закрытии
6.2. Предупреждения об ошибках
7. Криптографические вычисления
7.1. Ключевое расписание
7.2. Обновление секретов трафика
7.3. Расчет ключа трафика
7.4. (EC) Общий секретный расчет DHE
7.4.1. Конечное поле Диффи-Хеллман
7.4.2. Эллиптическая кривая Диффи-Хелман
7.5. Экспортеры
8. 0-RTT и Anti-Replay
8.1. Одноразовые билеты
8.2. Запись приветствия клиента
8.3. Проверка свежести
9. Соответствие требованиям
9.1. Обязательно-реализованные шифровальные люксы
9.2. Обязательные для реализации расширения
9.3. Инварианты протокола
10. Вопросы безопасности
11. Вопросы IANA
12. Ссылки
12.1. Нормативные ссылки
12.2. Информативные ссылки

Приложение A. Машина состояния
A.1. Клиент
А.2. Сервер

Приложение B. Структуры данных протокола и постоянные значения
B.1. Рекордный уровень
B.2. Предупреждающие сообщения
B.3. Протокол рукопожатия
B.3.1. Сообщения об обмене ключами
B.3.1.1. Расширение версии
B.3.1.2. Расширение файлов cookie
B.3.1.3. Расширение алгоритма подписи
B.3.1.4. Поддерживаемые расширения групп
B.3.2. Сообщения параметров сервера
B.3.3. Сообщения об аутентификации
B.3.4. Создание билета
B.3.5. Обновление ключей
В.4. Наборы шифров

Приложение C. Замечания по осуществлению
C.1. Генерация случайных чисел и засеивание
С.2. Сертификаты и аутентификация
С.3. Подводные камни реализации
С.4. Предотвращение отслеживания клиентов
С.5. Неаутентифицированная работа

Приложение D. Обратная совместимость
D.1. Ведение переговоров с более старым сервером
D.2. Ведение переговоров с более старым клиентом
D.3. 0-RTT Обратная совместимость
D.4. Режим совместимости Middlebox
D.5. Ограничения безопасности, связанные с обратной совместимостью

Приложение E. Обзор свойств безопасности
E.1. Рукопожатие
Е.1.1. Вывод ключей и HKDF
Е.1.2. Аутентификация клиента
Е.1.3. 0-RTT
Е.1.4. Независимость экспортера
E.1.5. Безопасность после компромисса
E.1.6. Внешние ссылки
Е.2. Слой записи
Е.2.1. Внешние ссылки
Е.3. Анализ трафика
Е.4. Атаки на боковых каналах
Е.5. Повторные атаки на 0-RTT
Е.5.1. Воспроизведение и экспортеры
Е.6. Идентификация персональной информации PSK
E.7. Обмен PSKs
E.8. Нападения на статическую RSA

Соавторы
Авторы адреса

Статус этой заметки

Это документ курса стандартов Интернета.

Этот документ является продуктом Целевой группы Internet Engineering Task Force (IETF). Он представляет собой консенсус сообщества IETF. Он получил публичный обзор и был одобрен для публикации Руководящей группой Internet Engineering Steering Group (IESG). Дополнительная информация о стандартах Интернета приведена в разделе 2 RFC 7841.

Информация о текущем состоянии этого документа, любые ошибки и способы предоставления обратной связи по нему могут быть получены по адресу https://www.rfc-editor.org/info/rfc8446.

Уведомление об авторских правах

Copyright (c) 2018 IETF Trust и лица, идентифицированные как авторы документа. Все права защищены.

Этот документ подлежит BCP 78 и правовым положениям IETF Trust, относящимся к документам IETF (https://trustee.ietf.org/license-info), действующим на дату публикации этого документа. Пожалуйста, внимательно ознакомьтесь с этими документами, поскольку они описывают ваши права и ограничения в отношении этого документа. Компоненты кода, извлеченные из этого документа, должны включать в себя упрощенный текст лицензии BSD, как описано в разделе 4.e Доверенных правовых положений, и предоставляются без гарантии, как описано в упрощенной лицензии BSD.

Этот документ может содержать материалы из документов IETF или IETF Contributions, опубликованные или опубликованные до 10 ноября 2008 года. Лицо (лица), контролирующие авторское право в некоторых из этих материалов, возможно, не предоставило IETF Trust право разрешать модификации такого материала вне процесса стандартов IETF.

Без получения адекватной лицензии от лица (лиц), контролирующего авторское право в таких материалах, этот документ не может быть изменен за пределами Процесса стандартов IETF, и его производные работы не могут создаваться вне процесса стандартов IETF, за исключением того, чтобы отформатировать его для публикации в качестве RFC или для перевода на другие языки, кроме английского.

1. Введение

Основная цель TLS — обеспечить безопасный канал между двумя сообщающимися одно-ранговыми узлами; единственным требованием от базового транспорта является надежный упорядоченный поток данных. В частности, защищенный канал должен обеспечивать следующие свойства:

  • Аутентификация (Authentication): серверная сторона канала всегда аутентифицирована; клиентская сторона может быть аутентифицирована. Аутентификация может происходить через асимметричную криптографию (например, RSA [RSA], Алгоритм цифровой подписи эллиптической кривой (ECDSA) [ECDSA] или алгоритм цифровой подписи Edwards (EdDSA) [RFC8032]) или симметричный предварительно общий ключ (PSK).
  • Конфиденциальность (Confidentiality): данные, передаваемые по каналу после установления, видны только конечным точкам. TLS не скрывает длину передаваемых данных, хотя конечные точки могут заполнять записи TLS, чтобы затенять длины и улучшить защиту от методов анализа трафика.
  • Целостность (Integrity): данные, отправленные по каналу, после установления, не могут быть изменены злоумышленниками без обнаружения.

Эти свойства должны быть истинными даже перед лицом злоумышленника, который имеет полный контроль над сетью, как описано в [RFC3552]. См. Приложение E для более полного описания соответствующих свойств безопасности.

TLS состоит из двух основных компонентов:

  • Протокол рукопожатия (раздел 4), который аутентифицирует связующие стороны, согласовывает криптографические режимы и параметры и устанавливает общий ключевой материал. Протокол рукопожатия предназначен для защиты от несанкционированного доступа; активный атакующий не должен заставлять сверстников согласовывать разные параметры, чем они были бы, если соединение не подвергалось атаке.
  • Протокол записи (раздел 5), который использует параметры, установленные протоколом подтверждения, для защиты трафика между сообщающимися одно-ранговыми узлами. Протокол записи делит трафик на ряд записей, каждый из которых независимо защищен с использованием ключей трафика.

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

В этом документе определяется версия TLS 1.3. Хотя TLS 1.3 несовместима с предыдущими версиями, все версии TLS включают механизм управления версиями, который позволяет клиентам и серверам взаимодействовать с общей версией, если один из них поддерживается обоими одно-ранговыми узлами.

Этот документ заменяет и устаревает предыдущие версии TLS, включая версию 1.2 [RFC5246]. Он также устаревает механизм билета (тикета) TLS, определенный в [RFC5077], и заменяет его механизмом, определенным в разделе 2.2. Поскольку TLS 1.3 изменяет способ получения ключей, он обновляет [RFC5705], как описано в разделе 7.5. Он также изменяет, как переносятся сообщения протокола состояния протокола (OCSP), и, следовательно, обновляет [RFC6066] и устаревает [RFC6961], как описано в разделе 4.4.2.1.

1.1. Конвенции и терминология

Ключевыми словами «MUST», «MUST NOT», «REQUIRED», «SHALL», «SHALL NOT», «SHOULD», «SHOULD NOT», «RECOMMENDED», «NOT RECOMMENDED», «MAY», and «OPTIONAL» в этом документе должны интерпретироваться, как описано в BCP 14 [RFC2119] [RFC8174], когда и только тогда, когда они отображаются во всех столицах, как показано здесь.

Используются следующие термины:

client: Конечная точка, инициирующая соединение TLS.

connection: соединение транспортного уровня между двумя конечными точками.

endpoint (конечная точка): либо клиент, либо сервер соединения.

handshake (рукопожатие): начальное согласование между клиентом и сервером, которое устанавливает параметры их последующих взаимодействий в TLS.

peer: Конечная точка. При обсуждении конкретной конечной точки «сверстник» относится к конечной точке, которая не является основным предметом обсуждения.

receiver (приемник): Конечная точка, которая принимает записи.

sender (отправитель): конечная точка, которая передает записи.

server: Конечная точка, которая не инициировала соединение TLS.

1.2. Основные отличия от TLS 1.2

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

Список поддерживаемых симметричных алгоритмов шифрования был обрезан всеми алгоритмами, которые считаются устаревшими. Те, которые остаются, — это все алгоритмы аутентифицированного шифрования с ассоциированными данными (AEAD). Концепция набора шифров была изменена, чтобы отделить механизмы аутентификации и обмена ключами от алгоритма защиты записи (включая длину секретного ключа) и хэш, который будет использоваться как с функцией деривации ключа, так и с кодом аутентификации сообщения подтверждения (MAC).

Был добавлен режим zero round-trip time с нулевым временем округления (0-RTT), который был сохранен в ходе настройки соединения для некоторых данных приложения за счет определенных свойств безопасности.

Удалены статические шифровальные комплекты RSA и Diffie-Hellman; все механизмы обмена ключами на основе открытого ключа теперь обеспечивают прямую секретность.

Все сообщения об установлении связи после ServerHello теперь зашифрованы. Недавно появившееся сообщение EncryptedExtensions позволяет различным расширениям, ранее отправленным в clear в ServerHello, также пользоваться защитой конфиденциальности.

Основные функции вывода были переработаны. Новый дизайн позволяет легче анализировать криптографы из-за их улучшенных свойств разделения ключей. В качестве базового примитива используется функция дифференцирования ключа и расширением HMAC (HKDF).

Аппарат управления рукопожатием был значительно реструктурирован, чтобы быть более последовательным и удалять лишние сообщения, такие как ChangeCipherSpec (за исключением случаев, когда это необходимо для совместимости со средним полем).

Алгоритмы эллиптической кривой теперь находятся в базовой спецификации, и включены новые алгоритмы подписи, такие как EdDSA. TLS 1.3 удаляет согласование формата точки в пользу единого точечного формата для каждой кривой.

Были сделаны другие криптографические улучшения, в том числе изменение дополнения RSA для использования схемы вероятностной подписи RSA (RSASSA-PSS) и удаление сжатия, алгоритм цифровой подписи (DSA) и пользовательские группы Ephemeral Diffie-Hellman (DHE).

Механизм согласования версии TLS 1.2 устарел в пользу списка версий в расширении. Это повышает совместимость с существующими серверами, которые неправильно реализовали согласование версий.

Возобновление сеанса с и без серверного состояния, а также на основе шифрования PSK более ранних версий TLS было заменено одним новым обменом PSK.

Ссылки были обновлены, чтобы указать на обновленные версии RFC, в зависимости от ситуации (например, RFC 5280, а не RFC 3280).

1.3. Обновления, влияющие на TLS 1.2

В этом документе определены несколько изменений, которые необязательно влияют на реализацию TLS 1.2, включая те, которые также не поддерживают TLS 1.3:

  • Механизм защиты от ухудшения версии описан в разделе 4.1.3.
  • Схемы подписки RSASSA-PSS определены в разделе 4.2.3.
  • Расширение ClientHello «supported_versions» может использоваться для согласования версии TLS для использования, вместо поля legacy_version для ClientHello.
  • Расширение «signature_algorithms_cert» позволяет клиенту указывать, какие алгоритмы подписей он может проверять в сертификатах X.509.

Кроме того, в этом документе разъясняются некоторые требования к соблюдению для более ранних версий TLS; см. раздел 9.3.

2. Обзор протокола

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

Неисправность рукопожатия или другой ошибки протокола вызывает завершение соединения, необязательно предшествующее предупреждающему сообщению (раздел 6).

TLS поддерживает три основных режима обмена ключами:

  • (EC) DHE (Диффи-Хеллман над любыми конечными полями или эллиптическими кривыми)
  • Только PSK
  • PSK с (EC) DHE

На рисунке 1 ниже показано базовое полное рукопожатие TLS:

Рисунок 1 - Поток сообщений для полного подтверждения TLS
Рисунок 1 — Поток сообщений для полного подтверждения TLS

+ — Указывает примечательные расширения, отправленные в ранее отмеченном сообщении.

* — Указывает необязательные или зависящие от ситуации сообщения / расширения, которые не всегда отправляются.

{} — Указывает на сообщения, защищенные с помощью ключей, полученных от [отправителя] _handshake_traffic_secret.

[] — Указывает на сообщения, защищенные с использованием ключей, полученных из [sender] _application_traffic_secret_N.

Рукопожатие можно рассматривать как имеющее три фазы (указанные на диаграмме выше):

  • Key Exchange (Обмен ключами): установите общий ключевой материал и выберите криптографические параметры. Все после этой фазы зашифровано.
  • Server Parameters (Параметры сервера): установить другие параметры подтверждения (будь то аутентификация клиента, поддержка протокола прикладного уровня и т. Д.)
  • Authentication (Аутентификация). Аутентификация сервера (и, необязательно, клиента), а также подтверждение ключа и подтверждение подтверждения.

На этапе обмена ключами клиент отправляет сообщение ClientHello (Раздел 4.1.2), которое содержит случайное значение nonce (ClientHello.random); его предлагаемые версии протокола; список симметричных шифра / HKDF-хеш-пар; либо набор ключей ключа Diffie-Hellman (в расширении «key_share» (раздел 4.2.8)), набор предварительно разделяемых ярлыков клавиш (в расширении «pre_shared_key» (раздел 4.2.11)) или оба; и потенциально дополнительные расширения. Дополнительные поля и / или сообщения могут также присутствовать для совместимости с медиа-сервером.

Сервер обрабатывает ClientHello и определяет соответствующие криптографические параметры для соединения. Затем он отвечает своим собственным ServerHello (раздел 4.1.3), который указывает согласованные параметры соединения. Комбинация ClientHello и ServerHello определяет общие ключи. Если используется ключ ECE (EC), то ServerHello содержит расширение «key_share» с эфемерной долей Диффи-Хеллмана сервера; доля сервера ДОЛЖНА быть в той же группе, что и одна из акций клиента. Если используется создание ключа PSK, то ServerHello содержит расширение «pre_shared_key», указывающее, какой из предложенных PSK клиентов был выбран. Обратите внимание, что реализации могут использовать (EC) DHE и PSK вместе, и в этом случае оба расширения будут поставляться.

Затем сервер отправляет два сообщения для установки параметров сервера:

  • EncryptedExtensions: ответы на расширения ClientHello, которые не требуются для определения криптографических параметров, отличных от тех, которые относятся к отдельным сертификатам. [Раздел 4.3.1]
  • CertificateRequest: если требуется аутентификация на основе сертификата, требуемые параметры для этого сертификата. Это сообщение опускается, если не требуется аутентификация клиента. [Раздел 4.3.2]

Наконец, клиент и сервер обмениваются сообщениями об аутентификации. TLS использует тот же набор сообщений каждый раз, когда требуется проверка подлинности на основе сертификатов. (Аутентификация на основе PSK происходит как побочный эффект обмена ключами.) В частности:

  • Certificate (Сертификат): сертификат конечной точки и любые расширения для каждого сертификата. Это сообщение опускается сервером, если оно не аутентифицируется сертификатом и клиентом, если сервер не отправил CertificateRequest (что указывает на то, что клиент не должен аутентифицироваться сертификатом). Обратите внимание, что если используются необработанные общедоступные ключи [RFC7250] или расширение кешированной информации [RFC7924], это сообщение не будет содержать сертификат, а некоторое другое значение, соответствующее длинному ключу сервера. [Раздел 4.4.2]
  • CertificateVerify: подпись во всем рукопожатии с использованием закрытого ключа, соответствующего открытому ключу в сообщении сертификата. Это сообщение опускается, если конечная точка не аутентифицируется через сертификат. [Раздел 4.4.3]
  • Finished (Закончено): MAC (Message Authentication Code) в течение всего рукопожатия. Это сообщение предоставляет подтверждение ключа, связывает идентификацию конечной точки с обменными ключами, а в режиме PSK также аутентифицирует рукопожатие. [Раздел 4.4.4]

После получения сообщений сервера клиент отвечает своими сообщениями об аутентификации, а именно сертификатом и сертификатом (по запросу) и «Готово».

На этом этапе рукопожатие завершено, и клиент и сервер получают материал, необходимый для слоя записи, для обмена данными уровня приложения, защищенными с помощью аутентифицированного шифрования. Данные приложения НЕ ДОЛЖНЫ быть отправлены до отправки сообщения «Готово», за исключением случаев, указанных в Разделе 2.3. Обратите внимание, что, хотя сервер может отправлять данные приложения до получения сообщений об аутентификации клиента, любые отправленные данные в этот момент, конечно, отправляются неавторизованному одно-ранговому узлу.

2.1. Неправильная доля DHE

Если клиент не предоставил достаточное расширение «key_share» (например, он включает в себя только группы DHE или ECDHE, неприемлемые или неподдерживаемые сервером), сервер исправляет несоответствие с помощью HelloRetryRequest, и клиенту необходимо перезапустить рукопожатие с соответствующим расширение «key_share», как показано на рисунке 2. Если общие криптографические параметры не могут быть согласованы, сервер ДОЛЖЕН отменить рукопожатие с соответствующим предупреждением.

Рисунок 2 - Поток сообщений для полного рукопожатия с несогласованными параметрами
Рисунок 2 — Поток сообщений для полного рукопожатия с несогласованными параметрами

Примечание. В протоколе рукопожатия используется начальный обмен ClientHello / HelloRetryRequest; он не сбрасывается с новым ClientHello.

TLS также позволяет несколько оптимизированных вариантов базового рукопожатия, как описано в следующих разделах.

2.2. Возобновление и предварительный ключ (PSK)

Хотя TLS PSK могут быть установлены вне диапазона, PSK также можно установить в предыдущем соединении, а затем использовать для установления нового соединения («возобновление сеанса — session resumption»  или «возобновление — resuming» с помощью PSK). Как только рукопожатие завершено, сервер может отправить клиенту идентификатор PSK, который соответствует уникальному ключу, полученному из первоначального рукопожатия (см. Раздел 4.6.1). Затем клиент может использовать эту идентификацию PSK в будущих рукопожатиях для обсуждения использования связанного PSK. Если сервер принимает PSK, контекст безопасности нового соединения криптографически привязан к исходному соединению, а ключ, полученный из первоначального рукопожатия, используется для загрузки криптографического состояния вместо полного рукопожатия. В TLS 1.2 и ниже эта функциональность была предоставлена «идентификаторами сеанса» и «сеансовыми билетами» [RFC5077]. Оба механизма устаревают в TLS 1.3.

PSK можно использовать с обменом ключами DHE (EC), чтобы обеспечить прямую секретность в сочетании с разделяемыми ключами или использовать их самостоятельно, за счет потери секретности для данных приложения.

На рисунке 3 показана пара рукопожатий, в которых первое рукопожатие устанавливает PSK, а второе рукопожатие использует его:

Рисунок 3 - Поток сообщений для возобновления и PSK
Рисунок 3 — Поток сообщений для возобновления и PSK

Поскольку сервер аутентифицируется через PSK, он не отправляет сертификат или сообщение CertificateVerify. Когда клиент предлагает возобновление через PSK, он ДОЛЖЕН также предоставить расширение «key_share» на сервер, чтобы сервер мог отказаться от возобновления и вернуться к полному рукопожатию, если это необходимо. Сервер отвечает расширением «pre_shared_key», чтобы договориться об использовании установки ключа PSK и может (как показано здесь) ответить расширением «key_share» для создания ключа ECE (EC), тем самым обеспечивая прямую секретность.

Когда PSK предоставляются вне полосы частот, идентификатор PSK и алгоритм хеширования KDF, который будет использоваться с PSK, также должны быть предоставлены.

Примечание. При использовании предустановленного секретного кода вне зоны, критически важным является использование достаточной энтропии во время генерации ключа, как описано в [RFC4086]. Получение общего секретного пароля с помощью пароля или других источников с низкой энтропией не является безопасным. Секрет с низкой энтропией или пароль подвергаются атакам по словарю на основе связующего PSK. Указанная аутентификация PSK не является надежным аутентифицированным ключом на основе пароля, даже когда используется с установлением ключа Diffie-Hellman. В частности, это не мешает злоумышленнику, который может наблюдать рукопожатие от выполнения атаки грубой силы на ключ пароля / предварительного доступа.

2.3. Данные 0-RTT

Когда клиенты и серверы совместно используют PSK (либо полученные извне, либо через предыдущее рукопожатие), TLS 1.3 позволяет клиентам отправлять данные в первый полет («ранние данные»). Клиент использует PSK для аутентификации сервера и для шифрования ранних данных.

Как показано на рисунке 4, данные 0-RTT просто добавляются к рукопожатию 1-RTT в первом полете. В остальной части рукопожатия используются те же сообщения, что и для рукопожатия 1-RTT с возобновлением PSK.

Рисунок 4 - Поток сообщений для рукопожатия 0-RTT
Рисунок 4 — Поток сообщений для рукопожатия 0-RTT

+ Указывает на заметные расширения, отправленные в ранее отмеченном сообщении.
* Указывает необязательные или зависящие от ситуации сообщения / расширения, которые не всегда отправляются.
() Указывает на сообщения, защищенные с использованием ключей, полученных из client_early_traffic_secret.
{} Указывает на сообщения, защищенные с помощью ключей, полученных из [отправителя] _handshake_traffic_secret.
[] Указывает на сообщения, защищенные с использованием ключей, полученных из [sender] _application_traffic_secret_N.

ВАЖНОЕ ПРИМЕЧАНИЕ. Свойства безопасности для данных с 0-RTT слабее, чем для других видов данных TLS. В частности:

  1. Эти данные не передаются в секрете, поскольку они зашифрованы исключительно под ключами, полученными с использованием предлагаемого PSK.
  2. Нет гарантий отсутствия повтора между соединениями. Защита от повторного воспроизведения для обычных данных TLS 1.3 1-RTT предоставляется через случайное значение сервера, но данные 0-RTT не зависят от ServerHello и, следовательно, имеют более низкие гарантии. Это особенно актуально, если данные аутентифицируются либо с помощью аутентификации клиента TLS, либо внутри протокола приложения. Те же предупреждения применяются к любому использованию функции early_exporter_master_secret.

Данные 0-RTT не могут быть дублированы в соединении (т. Е. Сервер не будет обрабатывать одни и те же данные дважды для одного и того же соединения), и злоумышленник не сможет сделать данные с 0-RTT показателями 1-RTT (потому что он защищен разными ключами). Приложение E.5 содержит описание потенциальных атак, а в Разделе 8 описаны механизмы, которые сервер может использовать для ограничения воздействия повтора.

3. Язык презентации

В этом документе рассматривается форматирование данных во внешнем представлении. Будет использоваться следующий очень простой и несколько случайно определенный синтаксис представления.

3.1. Размер основного блока

Явное указание представления всех элементов данных. Основной размер блока данных составляет один байт (т. Е. 8 бит). Многобайтовые элементы данных представляют собой конкатенации байтов слева направо сверху вниз. Из потока байтов формируется многобайтовый элемент (числовой в следующем примере) (с использованием обозначения C):

value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) | … | byte[n-1];

Этот порядок байтов для многобайтовых значений — это обычный порядок байтов в сети или формат большой буквы.

3.2. Смешанный (разнообразный)

Комментарии начинаются с «/ *» и заканчиваются на «* /».

Дополнительные компоненты обозначаются путем их включения в «[[]]» (двойные скобки).

Одно-байтовые объекты, содержащие неинтерпретированные данные, непрозрачны.

Тип псевдонима T ‘для существующего типа T определяется: T T’;

3.3. Числа

Основным числовым типом данных является беззнаковый байт (uint8). Все более крупные числовые типы данных строятся из серии байтов с фиксированной длиной, объединенных, как описано в разделе 3.1, и также не имеют знака. Предустановлены следующие числовые типы.

uint8 uint16 [2];
uint8 uint24 [3];
uint8 uint32 [4];
uint8 uint64 [8];

Все значения, здесь и в другом месте в спецификации, передаются в сетевом байтовом (big-endian) порядке; uint32, представленный шестнадцатеричными байтами 01 02 03 04, эквивалентен десятичному значению 16909060.

3.4. Векторы

Вектор (одномерный массив) представляет собой поток однородных элементов данных. Размер вектора может быть указан во время документа или оставлен неопределенным до времени выполнения. В любом случае длина объявляет количество байтов, а не количество элементов, в векторе. Синтаксис для указания нового типа T ‘, который является вектором фиксированной длины типа T, является

T T’[n];

Здесь T’ занимает n байтов в потоке данных, где n кратно размеру T. Длина вектора не включена в кодированный поток.

В следующем примере Datum определяется как три последовательных байта, которые протокол не интерпретирует, а Data — три последовательных Datum, потребляющих в общей сложности девять байт.

opaque Datum[3]; /* three uninterpreted bytes */
Datum Data[9]; /* three consecutive 3-byte vectors */

Векторы переменной длины определяются путем указания поддиапазона допустимых длин, включительно, с использованием обозначения <floor..ceiling>. Когда они закодированы, фактическая длина предшествует содержимому вектора в потоке байтов. Длина будет в виде количества, потребляющего столько байтов, сколько требуется, чтобы удерживать указанную максимальную (потолочную) длину вектора. Вектор переменной длины с полем нулевой нулевой длины называется пустым вектором.

T T’<floor..ceiling>;

В следующем примере «обязательный» — это вектор, который должен содержать от 300 до 400 байт типа непрозрачного. Он никогда не может быть пустым. Поле фактической длины потребляет два байта, uint16, что достаточно для представления значения 400 (см. Раздел 3.3). Аналогично, «дольше» может представлять до 800 байтов данных или 400 элементов uint16, и может быть пустым. Его кодировка будет включать в себя двухбайтовое поле фактической длины, добавленное к вектору. Длина закодированного вектора должна быть точной кратной длине одного элемента (например, 17-байтовый вектор uint16 был бы незаконным).

opaque mandatory<300..400>;
/* length field is two bytes, cannot be empty */
uint16 longer<0..800>;
/* zero to 400 16-bit unsigned integers */

3.5. Перечисления

Доступен дополнительный разреженный тип данных, называемый «enum» или «enumerated». Каждое определение является другим типом. Только перечисления того же типа могут быть назначены или сопоставлены. Каждому элементу перечисления должно быть присвоено значение, как показано в следующем примере. Так как элементы перечисления не упорядочены, им может быть присвоено любое уникальное значение в любом порядке.

enum { e1(v1), e2(v2), … , en(vn) [[, (n)]] } Te;

Будущие расширения или дополнения к протоколу могут определять новые значения. Реализации должны иметь возможность анализировать и игнорировать неизвестные значения, если в определении поля не указано иначе.

Перечисленное занимает столько места в байтовом потоке, как и его максимальное заданное порядковое значение. Следующее определение приведет к тому, что один байт будет использоваться для переноса полей типа Color.

enum { red(3), blue(5), white(7) } Color;

Можно дополнительно указать значение без связанного с ним тега, чтобы заставить определение ширины без указания избыточного элемента.

В следующем примере Taste будет потреблять два байта в потоке данных, но может принимать только значения 1, 2 или 4 в текущей версии протокола.

enum { sweet(1), sour(2), bitter(4), (32000) } Taste;

Имена элементов перечисления ограничены определенным типом. В первом примере полной ссылкой на второй элемент перечисления будет Color.blue. Такая квалификация не требуется, если цель задания хорошо указана.

Color color = Color.blue; /* overspecified, legal */
Color color = blue; /* correct, type implicit */

Имена, назначенные для перечислений, не обязательно должны быть уникальными. Численное значение может описывать диапазон, в котором применяется одно и то же имя. Значение включает минимальные и максимальные включительные значения в этом диапазоне, разделенные двумя символами периода. Это принципиально полезно для резервирования областей пространства.

enum { sad(0), meh(1..254), happy(255) } Mood;

3.6. Построенные типы

Для удобства структурные типы могут быть построены из примитивных типов. Каждая спецификация объявляет новый, уникальный тип. Синтаксис, используемый для определений, очень похож на синтаксис C.

struct {
T1 f1;
T2 f2;

Tn fn;
} T;

Векторные поля с фиксированной и переменной длиной разрешены с использованием стандартного векторного синтаксиса. Это демонстрируют структуры V1 и V2 в примере вариантов (раздел 3.8).

Поля внутри структуры могут быть квалифицированы с использованием имени типа с синтаксисом, подобным тому, который доступен для перечислений. Например, T.f2 относится ко второму полю предыдущего объявления.

3.7. Константы

Полям и переменным может быть присвоено фиксированное значение с помощью «=», как в:

struct {
T1 f1 = 8; /* T.f1 всегда должно быть 8 */
T2 f2;
} T;

3.8. Варианты

Определенные структуры могут иметь варианты, основанные на некоторых знаниях, доступных в среде. Селектор должен быть перечисленным типом, который определяет возможные варианты, которые определяет структура. Каждый рычаг select (ниже) указывает тип поля этого варианта и необязательную метку поля. Механизм выбора варианта во время выполнения не предписывается языком презентации.

struct {
T1 f1;
T2 f2;
….
Tn fn;
select (E) {
case e1: Te1 [[fe1]];
case e2: Te2 [[fe2]];

case en: Ten [[fen]];
};
} Tv;

Например:

enum { apple(0), orange(1) } VariantTag;
struct {
uint16 number;
opaque string<0..10>; /* variable length */
} V1;
struct {
uint32 number;
opaque string[10]; /* fixed length */
} V2;
struct {
VariantTag type;
select (VariantRecord.type) {
case apple: V1;
case orange: V2;
};
} VariantRecord;

4. Протокол рукопожатия (Handshake)

Протокол рукопожатия используется для согласования параметров безопасности соединения. Сообщения установления связи подаются на уровень записи TLS, где они инкапсулированы в одну или несколько структур TLSPlaintext или TLSCiphertext, которые обрабатываются и передаются в соответствии с текущим состоянием активного соединения.

Протокол рукопожатия
Протокол рукопожатия

Сообщения протокола ДОЛЖНЫ быть отправлены в порядке, определенном в Разделе 4.4.1, и показаны на диаграммах в Разделе 2. Одно-ранговый узел, который получает сообщение подтверждения связи в непредвиденном порядке, ДОЛЖЕН прервать рукопожатие с предупреждением «неожиданного сообщения — unexpected_message».

Новые типы сообщений рукопожатия назначаются IANA, как описано в разделе 11.

4.1. Сообщения об обмене ключами

Сообщения обмена ключами используются для определения возможностей безопасности клиента и сервера и для создания общих секретов, включая ключи трафика, используемые для защиты остальной части рукопожатия и данных.

4.1.1. Криптографические переговоры

В TLS криптографическое согласование выполняется клиентом, предлагающим следующие четыре набора опций в ClientHello:

  • Список наборов шифров, которые указывают алгоритмы AEAD / HKDF-хеш-пары, которые поддерживает клиент.
  • Расширение «supported_groups» (раздел 4.2.7), которое указывает группы DHE DHCP, которые поддерживает клиент, и расширение «key_share» (раздел 4.2.8), которое содержит (EC) DHE-акции для некоторых или всех этих групп ,
  • Расширение «signature_algorithms» (раздел 4.2.3), которое указывает алгоритмы подписи, которые клиент может принять. Расширение «signature_algorithms_cert» (раздел 4.2.3) также может быть добавлено для указания алгоритмов сигнатур, специфичных для сертификата.
  • Расширение «pre_shared_key» (раздел 4.2.11), которое содержит список идентификаторов симметричного ключа, известных клиенту, и расширение «psk_key_exchange_modes» (раздел 4.2.9), которое указывает режимы обмена ключами, которые могут использоваться с PSK.

Если сервер не выбирает PSK, то первые три из этих параметров полностью ортогональны: сервер самостоятельно выбирает набор шифров, группу DHE (EC) и ключевой ресурс для установления ключей, а также пару сигнатур / сертификат для аутентификации самому клиенту. Если между полученными «поддерживаемыми_группами» и группами, поддерживаемыми сервером, не существует совпадений, тогда сервер ДОЛЖЕН прервать рукопожатие с предупреждением «handshake_failure» или «недостаточно-безопасности».

Если сервер выбирает PSK, тогда он ДОЛЖЕН также выбрать режим установления ключа из набора, указанного расширением «psk_key_exchange_modes» клиента (в настоящее время, PSK самостоятельно или с (EC) DHE). Обратите внимание, что если PSK можно использовать без (EC) DHE, то неперекрывающиеся в параметрах «supported_groups» необязательно должны быть фатальными, как в случае, отличном от PSK, обсуждаемом в предыдущем абзаце.

Если сервер выбирает группу DHE (EC), и клиент не предлагал совместимое расширение «key_share» в исходном ClientHello, сервер ДОЛЖЕН отвечать сообщением HelloRetryRequest (раздел 4.1.4).

Если сервер успешно выбирает параметры и не требует HelloRetryRequest, он указывает выбранные параметры в ServerHello следующим образом:

  • Если используется PSK, сервер отправит расширение «pre_shared_key», указывающее выбранный ключ.
  • Когда используется (EC) DHE, сервер также будет предоставлять расширение «key_share». Если PSK не используется, то (EC) DHE и аутентификация на основе сертификатов всегда используются.
  • При аутентификации через сертификат сервер отправляет сообщения Certificate (Section 4.4.2) и CertificateVerify (Раздел 4.4.3). В TLS 1.3, как определено в этом документе, всегда используется PSK или сертификат, но не оба. Будущие документы могут определять, как их использовать вместе.

Если сервер не может согласовать поддерживаемый набор параметров (т. Е. Не существует перекрытия между параметрами клиента и сервера), он ДОЛЖЕН прервать рукопожатие с помощью факсимильного предупреждения «handshake_failure» или «lack_security» (см. Раздел 6).

4.1.2. Приветствие клиента — Client Hello

Когда клиент сначала подключается к серверу, ТРЕБУЕТСЯ отправить ClientHello в качестве своего первого сообщения TLS. Клиент также отправит ClientHello, когда сервер откликнется на ClientHello с помощью HelloRetryRequest. В этом случае клиент ДОЛЖЕН отправить тот же ClientHello без изменений, за исключением следующего:

  • Если в HelloRetryRequest было добавлено расширение «key_share», заменив список акций на список, содержащий один KeyShareEntry из указанной группы.
  • Удаление расширения «early_data» (раздел 4.2.10), если оно присутствовало. Ранние данные не разрешаются после HelloRetryRequest.
  • Включая расширение «cookie», если оно было предоставлено в HelloRetryRequest.
  • Обновление расширения «pre_shared_key», если оно имеется, путем пересчета значений «obfuscated_ticket_age» и связующего и (необязательно) удаления любых PSK, которые несовместимы с указанным набором шифров сервера.
  • Необязательно добавление, удаление или изменение длины расширения «дополнение» [RFC7685].
  • Другие модификации, которые могут быть разрешены расширением, определенным в будущем и присутствующим в HelloRetryRequest.

Поскольку TLS 1.3 запрещает повторное согласование, если сервер согласовал TLS 1.3 и получает клиентское имя в любое другое время, он ДОЛЖЕН прекратить соединение с предупреждением «неожиданное_помощь».

Если сервер установил TLS-соединение с предыдущей версией TLS и получает TLS 1.3 ClientHello в ходе пересмотра, он ДОЛЖЕН сохранить предыдущую версию протокола. В частности, он НЕ ДОЛЖЕН согласовывать TLS 1.3.

Структура этого сообщения:

uint16 ProtocolVersion;
opaque Random[32];
uint8 CipherSuite[2]; /* Cryptographic suite selector */
struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id<0..32>;
CipherSuite cipher_suites<2..2^16-2>;
opaque legacy_compression_methods<1..2^8-1>;
Extension extensions<8..2^16-1>;
} ClientHello;

  • legacy_version: в предыдущих версиях TLS это поле использовалось для согласования версий и представляло наивысший номер версии, поддерживаемый клиентом. Опыт показал, что многие серверы не выполняют должным образом согласование версий, что приводит к «нетерпимости версий — version intolerance», в которой сервер отказывается от другого приемлемого ClientHello с номером версии выше, чем он поддерживает. В TLS 1.3 клиент указывает свои предпочтения в версии расширения «supported_versions» (раздел 4.2.1), а поле legacy_version ДОЛЖНО быть установлено в 0x0303, что является номером версии для TLS 1.2. TLS 1.3 ClientHellos идентифицируются как имеющие legacy_version 0x0303 и поддерживаемое расширение версии, присутствующее с 0x0304 в качестве наивысшей версии, указанной в нем. (Подробнее об обратной совместимости см. В приложении D).
  • random: 32 байта, генерируемых генератором случайных чисел. Дополнительную информацию см. В Приложении C.
  • legacy_session_id: Версии TLS до того, как TLS 1.3 поддерживает функцию возобновления сеанса, которая была объединена с предварительно разделенными ключами в этой версии (см. раздел 2.2). Клиент, у которого есть кешированный идентификатор сеанса, установленный сервером pre-TLS 1.3, ДОЛЖЕН установить это поле в это значение. В режиме совместимости (см. Приложение D.4) это поле ДОЛЖНО быть непустым, поэтому клиент, не предлагающий сеанс pre-TLS 1.3, ДОЛЖЕН создать новое 32-байтовое значение. Это значение не должно быть случайным, но ДОЛЖНО быть непредсказуемым, чтобы избежать фиксации реализаций по определенному значению (также известному как оссификация). В противном случае он ДОЛЖЕН быть установлен как вектор нулевой длины (т. Е. Поле с нулевой длиной одиночного байта).
  • cipher_suites: список опций симметричного шифрования, поддерживаемых клиентом, в частности алгоритм защиты записи (включая длину секретного ключа) и хэш, который будет использоваться с HKDF, в порядке убывания предпочтений клиента. Значения определены в Приложении B.4. Если список содержит номера шифров, которые сервер не распознает, не поддерживает или не хочет использовать, сервер ДОЛЖЕН игнорировать эти комплекты шифров и обрабатывать остальные, как обычно. Если клиент пытается создать ключевое слово PSK, ему ДОЛЖНО рекламировать хотя бы один набор шифров, обозначающий хеш, связанный с PSK.
  • legacy_compression_methods: Версии TLS до 1,3 поддерживаемого сжатия, при этом список поддерживаемых методов сжатия отправляется в этом поле. Для каждого TLS 1.3 ClientHello этот вектор ДОЛЖЕН содержать ровно один байт, установленный на ноль, что соответствует «нулевому» методу сжатия в предыдущих версиях TLS. Если TLS 1.3 ClientHello получен с любым другим значением в этом поле, сервер ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр». Обратите внимание, что серверы TLS 1.3 могут получать TLS 1.2 или ранее ClientHellos, которые содержат другие методы сжатия, и (при согласовании такой предыдущей версии) ДОЛЖНЫ следовать процедурам для соответствующей предыдущей версии TLS.
  • extensions: клиенты запрашивают расширенную функциональность с серверов, отправляя данные в поле расширения. Фактический формат «Расширение» определен в разделе 4.2. В TLS 1.3 использование определенных расширений является обязательным, поскольку функциональность переместилась в расширения, чтобы сохранить совместимость ClientHello с предыдущими версиями TLS. Серверы ДОЛЖНЫ игнорировать непризнанные расширения.

Все версии TLS позволяют дополнительно расширять поле с дополнительным полем compression_methods. Сообщения TLS 1.3 ClientHello всегда содержат расширения (минимально «поддерживаемые_версии», в противном случае они будут интерпретироваться как сообщения TLS 1.2 ClientHello). Однако серверы TLS 1.3 могут получать сообщения ClientHello без поля расширений из предыдущих версий TLS. Наличие расширений можно обнаружить, определив, есть ли байты после поля compression_methods в конце ClientHello. Обратите внимание, что этот метод обнаружения необязательных данных отличается от обычного метода TLS наличием поля переменной длины, но он используется для совместимости с TLS до того, как были определены расширения. Серверы TLS 1.3 должны выполнить эту проверку сначала и только попытаться согласовать TLS 1.3, если присутствует расширение «supported_versions». Если согласовать версию TLS до 1.3, сервер ДОЛЖЕН проверить, что сообщение не содержит данных после legacy_compression_methods или что оно содержит допустимый блок расширения без последующих данных. Если нет, то он ДОЛЖЕН прервать рукопожатие с предупреждением «decode_error».

В случае, если клиент запрашивает дополнительные функции с использованием расширений, и эта функциональность не предоставляется сервером, клиент МОЖЕТ прервать рукопожатие.

После отправки сообщения ClientHello клиент ждет сообщения ServerHello или HelloRetryRequest. Если ранние данные используются, клиент может передать ранние данные приложения (раздел 2.3), ожидая следующего сообщения подтверждения.

4.1.3. Приветствие сервера — Server Hello

Сервер отправит это сообщение в ответ на сообщение ClientHello, чтобы продолжить рукопожатие, если оно способно согласовать приемлемый набор параметров установления связи на основе ClientHello.

struct {
ProtocolVersion legacy_version = 0x0303; /* TLS v1.2 */
Random random;
opaque legacy_session_id_echo<0..32>;
CipherSuite cipher_suite;
uint8 legacy_compression_method = 0;
Extension extensions<6..2^16-1>;
} ServerHello;

  • legacy_version: в предыдущих версиях TLS это поле использовалось для согласования версий и представляло выбранный номер версии для соединения. К сожалению, некоторые средние регистры терпят неудачу при представлении новых значений. В TLS 1.3 сервер TLS указывает свою версию с использованием расширения «supported_versions» (раздел 4.2.1), а поле legacy_version ДОЛЖНО быть установлено в 0x0303, что является номером версии для TLS 1.2. (Подробнее об обратной совместимости см. В приложении D).
  • random: 32 байта, генерируемых генератором случайных чисел. Дополнительную информацию см. В Приложении C. Последние 8 байтов ДОЛЖНЫ быть перезаписаны, как описано ниже, если согласовать TLS 1.2 или TLS 1.1, но остальные байты ДОЛЖНЫ быть случайными. Эта структура создается сервером и ДОЛЖНА быть создана независимо от ClientHello.random.
  • legacy_session_id_echo: содержимое поля legacy_session_id клиента. Обратите внимание, что это поле отражается, даже если значение клиента соответствует кэшированному сеансу pre-TLS 1.3, который сервер решил не возобновлять. Клиент, который получает поле legacy_session_id_echo, которое не соответствует тому, что он отправил в ClientHello, ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр».
  • cipher_suite: единственный набор шифров, выбранный сервером из списка в ClientHello.cipher_suites. Клиент, который получает набор шифров, который не был предложен, ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр».
  • legacy_compression_method: Один байт, который ДОЛЖЕН иметь значение 0.
  • extensions: список расширений. ServerHello ДОЛЖЕН включать только расширения, необходимые для установления криптографического контекста и согласования версии протокола. Все сообщения TLS 1.3 ServerHello ДОЛЖНЫ содержать расширение «supported_versions». Текущие сообщения ServerHello дополнительно содержат либо расширение «pre_shared_key», либо расширение «key_share», или оба (при использовании ключа PSK с (EC) DHE). Другие расширения (см. Раздел 4.2) отправляются отдельно в сообщении EncryptedExtensions.

По соображениям обратной совместимости со средними блоками (см. Приложение D.4) сообщение HelloRetryRequest использует ту же структуру, что и ServerHello, но с Random задано специальное значение SHA-256 «HelloRetryRequest»:

CF 21 AD 74 E5 9A 61 11 BE 1D 8C 02 1E 65 B8 91
C2 A2 11 16 7A BB 8C 5E 07 9E 09 E2 C8 A8 33 9C

Получив сообщение с типом server_hello, реализации должны сначала проверить значение Random и, если оно соответствует этому значению, обработать его, как описано в разделе 4.1.4).

TLS 1.3 имеет механизм защиты от понижения, встроенный в случайное значение сервера. Серверы TLS 1.3, которые согласовывают TLS 1.2 или ниже в ответ на ClientHello, ДОЛЖНЫ установить последние 8 байтов своего случайного значения специально в своем ServerHello.

Если переговариваются TLS 1.2, серверы TLS 1.3 ДОЛЖНЫ установить последние 8 байтов своего случайного значения в байты:

44 4F 57 4E 47 52 44 01

Если согласовываются TLS 1.1 или ниже, серверы TLS 1.3 ДОЛЖНЫ и серверы TLS 1.2 СЛЕДУЕТ, установите последние 8 байтов своего значения ServerHello.Random в байтах:

44 4F 57 4E 47 52 44 00

Клиенты TLS 1.3, получающие ServerHello, указывающие TLS 1.2 или ниже, ДОЛЖНЫ проверить, что последние 8 байтов не равны ни одному из этих значений. Клиенты TLS 1.2 СЛЕДУЕТ также проверить, что последние 8 байтов не равны второму значению, если ServerHello указывает TLS 1.1 или ниже. Если совпадение найдено, клиент ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр». Этот механизм обеспечивает ограниченную защиту от атак с понижением по сравнению с тем, что предоставляется обменом Finished: поскольку ServerKeyExchange, сообщение, присутствующее в TLS 1.2 и ниже, включает в себя подпись по обе случайным значениям, для активного злоумышленника невозможно изменить случайные значения без обнаружения, если используются эфемерные шифры. Он не обеспечивает защиту от понижения, когда используется статический RSA.

Примечание. Это изменение от [RFC5246], поэтому на практике многие клиенты и серверы TLS 1.2 не будут вести себя так, как указано выше.

Унаследованный клиент TLS, выполняющий перезаключение с TLS 1.2 или ранее и который получает сервер TLS 1.3 ServerHello во время пересмотра, ДОЛЖЕН отменить рукопожатие с предупреждением «protocol_version». Обратите внимание, что повторное согласование невозможно при обсуждении TLS 1.3.

4.1.4. Запрос Hello Retry

Сервер отправит это сообщение в ответ на сообщение ClientHello, если он сможет найти приемлемый набор параметров, но ClientHello не содержит достаточной информации для продолжения рукопожатия. Как обсуждалось в разделе 4.1.3, HelloRetryRequest имеет тот же формат, что и сообщение ServerHello, а поля legacy_version, legacy_session_id_echo, cipher_suite и legacy_compression_method имеют одинаковое значение. Однако для удобства мы обсуждаем «HelloRetryRequest» во всем этом документе, как если бы это было четкое сообщение.

Расширения сервера ДОЛЖНЫ содержать «поддерживаемые_версии». Кроме того, он ДОЛЖЕН содержать минимальный набор расширений, необходимых клиенту для создания правильной пары ClientHello. Как и в случае с ServerHello, HelloRetryRequest НЕ ДОЛЖЕН содержать никаких расширений, которые ранее не предлагались клиентом в ClientHello, за исключением, возможно, расширения «cookie» (см. Раздел 4.2.2).

После получения HelloRetryRequest клиент ДОЛЖЕН проверять legacy_version, legacy_session_id_echo, cipher_suite и legacy_compression_method, как указано в разделе 4.1.3, а затем обрабатывать расширения, начиная с определения версии с помощью «supported_versions». Клиенты ДОЛЖНЫ прервать рукопожатие с предупреждением «незаконный_параметр», если HelloRetryRequest не приведет к каким-либо изменениям в ClientHello. Если клиент получает второе HelloRetryRequest в том же соединении (то есть, когда ClientHello сам был в ответ на HelloRetryRequest), он ДОЛЖЕН прервать рукопожатие с предупреждением «неожиданный_message».

В противном случае клиент ДОЛЖЕН обрабатывать все расширения в HelloRetryRequest и отправлять второй обновленный ClientHello. Расширения HelloRetryRequest, определенные в этой спецификации:

  • supported_versions (see Section 4.2.1)
  • cookie (see Section 4.2.2)
  • key_share (see Section 4.2.8)

Клиент, который получает набор шифров, который не был предложен, ДОЛЖЕН отменить рукопожатие. Серверы ДОЛЖНЫ обеспечить, чтобы они согласовывали один и тот же набор шифров при получении обновленного клиента ClientHello (если сервер выбирает набор шифров в качестве первого шага в переговорах, тогда это произойдет автоматически). После получения ServerHello клиенты ДОЛЖНЫ проверить, что набор шифров, поставляемый в ServerHello, такой же, как и в HelloRetryRequest, и в противном случае отменяет рукопожатие с предупреждением «незаконный_параметр».

Кроме того, в обновленном ClientHello клиент НЕ ДОЛЖЕН предлагать какие-либо предварительно разделяемые ключи, связанные с хешем, отличным от хэша выбранного набора шифров. Это позволяет клиенту избежать вычисления частичных хэш-расшифров для множественных хэшей во втором ClientHello.

Значение selected_version в расширении HelloFetryRequest «supported_versions» ДОЛЖНО сохраняться в ServerHello, и клиент ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр», если значение изменяется.

4.2. Расширения

Несколько сообщений TLS содержат структуры расширений с расширением длины тега.

struct {
ExtensionType extension_type;
opaque extension_data<0..2^16-1>;
} Extension;

enum {
server_name(0), /* RFC 6066 */
max_fragment_length(1), /* RFC 6066 */
status_request(5), /* RFC 6066 */
supported_groups(10), /* RFC 8422, 7919 */
signature_algorithms(13), /* RFC 8446 */
use_srtp(14), /* RFC 5764 */
heartbeat(15), /* RFC 6520 */
application_layer_protocol_negotiation(16), /* RFC 7301 */
signed_certificate_timestamp(18), /* RFC 6962 */
client_certificate_type(19), /* RFC 7250 */
server_certificate_type(20), /* RFC 7250 */
padding(21), /* RFC 7685 */
pre_shared_key(41), /* RFC 8446 */
early_data(42), /* RFC 8446 */
supported_versions(43), /* RFC 8446 */
cookie(44), /* RFC 8446 */
psk_key_exchange_modes(45), /* RFC 8446 */
certificate_authorities(47), /* RFC 8446 */
oid_filters(48), /* RFC 8446 */
post_handshake_auth(49), /* RFC 8446 */
signature_algorithms_cert(50), /* RFC 8446 */
key_share(51), /* RFC 8446 */
(65535)
} ExtensionType;

Здесь:

  • «extension_type» идентифицирует конкретный тип расширения.
  • «extension_data» содержит информацию, относящуюся к конкретному типу расширения.

Список типов расширений поддерживается IANA, как описано в Разделе 11.

Расширения, как правило, структурированы в режиме запроса / ответа, хотя некоторые расширения — это просто указания без соответствующего ответа. Клиент отправляет свои запросы на расширение в сообщении ClientHello, и сервер отправляет ответы на добавление в сообщениях ServerHello, EncryptedExtensions, HelloRetryRequest и Certificate. Сервер отправляет запросы на расширение в сообщении CertificateRequest, которое клиент МОЖЕТ ответить на сообщение с сертификатом. Сервер МОЖЕТ также отправлять незапрашиваемые расширения в NewSessionTicket, хотя клиент не отвечает на них напрямую.

Реализации НЕ ДОЛЖНЫ отправлять ответы на добавление, если удаленная конечная точка не отправила соответствующие запросы расширения, за исключением расширения «cookie» в HelloRetryRequest. После получения такого расширения конечная точка ДОЛЖНА отменить рукопожатие с предупреждением «unsupported_extension».

В приведенной ниже таблице указаны сообщения, в которых может отображаться данное расширение, используя следующие обозначения: CH (ClientHello), SH (ServerHello), EE (EncryptedExtensions), CT (сертификат), CR (CertificateRequest), NST (NewSessionTicket) и HRR (HelloRetryRequest). Если реализация получает расширение, которое оно распознает и которое не указано для сообщения, в котором оно появляется, оно ДОЛЖНО отменить рукопожатие с предупреждением «незаконный_параметр».

Сообщения, в которых может отображаться расширение cookie
Сообщения, в которых может отображаться расширение cookie

Когда присутствуют несколько расширений разных типов, расширения могут появляться в любом порядке, за исключением «pre_shared_key» (раздел 4.2.11), который ДОЛЖЕН быть последним расширением в ClientHello (но может появляться в любом месте блока расширения ServerHello) , Там НЕ ДОЛЖНО быть более одного расширения одного и того же типа в данном блоке расширения.

В TLS 1.3, в отличие от TLS 1.2, расширения согласовываются для каждого рукопожатия даже в режиме возобновления-PSK. Однако параметры 0-RTT — это те, которые были согласованы в предыдущем рукопожатии; несоответствиям может потребоваться отклонение 0-RTT (см. раздел 4.2.10).

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

  • Некоторые случаи, когда сервер не согласен с расширением, являются условиями ошибки (например, рукопожатие не может продолжаться), а некоторые просто отказываются поддерживать определенные функции. В общем случае предупреждения об ошибках должны использоваться для первого и поля в ответе на расширение сервера для последнего.
  • Расширения должны, насколько это возможно, быть разработаны, чтобы предотвратить любую атаку, которая вынуждает использовать (или не использовать) конкретную функцию манипулированием сообщениями подтверждения. Этот принцип следует соблюдать независимо от того, считается ли эта функция проблемой безопасности. Часто тот факт, что поля расширения включены во входные данные для хэшей сообщений Finished, будет достаточным, но крайне необходимо проявлять особую осторожность, когда расширение изменяет значение сообщений, отправленных на этапе подтверждения. Дизайнеры и разработчики должны знать, что до тех пор, пока подтверждение авторизации не будет завершено, активные злоумышленники могут изменять сообщения и вставлять, удалять или заменять расширения.

4.2.1. Поддерживаемые версии

struct {
select (Handshake.msg_type) {
case client_hello:
ProtocolVersion versions<2..254>;
case server_hello: /* and HelloRetryRequest */
ProtocolVersion selected_version;
};
} SupportedVersions;

Расширение «supported_versions» используется клиентом, чтобы указать, какие версии TLS он поддерживает, и сервером указать, какую версию он использует. Расширение содержит список поддерживаемых версий в порядке предпочтения, с самой предпочтительной версией. Реализации этой спецификации ДОЛЖНЫ отправить это расширение в ClientHello, содержащее все версии TLS, которые они готовы согласовать (для этой спецификации это означает минимально 0x0304, но если предыдущие версии TLS разрешены для переговоров, они ДОЛЖНЫ присутствовать также ).

Если этого расширения нет, серверы, которые соответствуют этой спецификации и которые также поддерживают TLS 1.2, ДОЛЖНЫ согласовать TLS 1.2 или ранее, как указано в [RFC5246], даже если ClientHello.legacy_version является 0x0304 или новее. Серверы МОГУТ прервать рукопожатие после получения ClientHello с legacy_version 0x0304 или новее.

Если это расширение присутствует в ClientHello, серверы НЕ ДОЛЖНЫ использовать значение ClientHello.legacy_version для согласования версий и ДОЛЖНЫ использовать только расширение «supported_versions» для определения предпочтений клиента. Серверы ДОЛЖНЫ только выбрать версию TLS, присутствующую в этом расширении, и ДОЛЖНЫ игнорировать любые неизвестные версии, которые присутствуют в этом расширении. Обратите внимание, что этот механизм позволяет согласовать версию до TLS 1.2, если одна сторона поддерживает разреженный диапазон. Реализации TLS 1.3, которые предпочитают поддерживать предыдущие версии TLS, ДОЛЖНЫ поддерживать TLS 1.2. Серверы ДОЛЖНЫ быть готовы получить ClientHellos, которые включают это расширение, но не включают 0x0304 в список версий.

Сервер, который согласовывает версию TLS перед TLS 1.3, ДОЛЖЕН установить ServerHello.version и НЕ ДОЛЖЕН отправлять расширение «supported_versions». Сервер, который согласовывает TLS 1.3, должен ответить, отправив расширение «supported_versions», содержащее значение выбранной версии (0x0304). Он ДОЛЖЕН установить для поля ServerHello.legacy_version значение 0x0303 (TLS 1.2). Клиенты ДОЛЖНЫ проверять это расширение до обработки остальной части ServerHello (хотя для считывания расширения им потребуется проанализировать ServerHello). Если это расширение присутствует, клиенты ДОЛЖНЫ игнорировать значение ServerHello.legacy_version и ДОЛЖНЫ использовать только расширение «supported_versions» для определения выбранной версии. Если расширение «supported_versions» в ServerHello содержит версию, не предложенную клиентом, или содержит версию до TLS 1.3, клиент ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр».

struct {
opaque cookie<1..2^16-1>;
} Cookie;

Куки-файлы служат для двух основных целей:

  • Позволить серверу заставить клиента продемонстрировать достижимость по их кажущемуся сетевому адресу (тем самым обеспечивая меру защиты DoS). Это в первую очередь полезно для транспорта, не связанного с подключением (см. [RFC6347]).
  • Разрешить серверу разгружать состояние клиенту, что позволяет ему отправлять HelloRetryRequest без сохранения какого-либо состояния. Сервер может сделать это, сохранив хэш ClientHello в cookie HelloRetryRequest (защищенный с помощью подходящего алгоритма защиты целостности).

При отправке HelloRetryRequest сервер МОЖЕТ предоставить клиенту расширение «cookie» (это исключение из обычного правила, что единственными расширениями, которые могут быть отправлены, являются те, которые появляются в ClientHello). При отправке нового ClientHello клиент ДОЛЖЕН скопировать содержимое расширения, полученного в HelloRetryRequest, в расширение «cookie» в новом ClientHello. Клиенты НЕ ДОЛЖНЫ использовать файлы cookie в своем исходном ClientHello в последующих подключениях.

Когда сервер работает без учета состояния, он может получить незащищенную запись типа change_cipher_spec между первым и вторым ClientHello (см. Раздел 5). Поскольку сервер не сохраняет какое-либо состояние, это будет выглядеть так, как если бы это было первое сообщение. Серверы, работающие без учета состояния, ДОЛЖНЫ игнорировать эти записи.

4.2.3. Алгоритмы подписи

TLS 1.3 предоставляет два расширения для указания, какие сигнатурные алгоритмы могут использоваться в цифровых подписях. Расширение «signature_algorithms_cert» применяется к сигнатурам в сертификатах, а расширение «signature_algorithms», которое первоначально появилось в TLS 1.2, применяется к подписям в сообщениях CertificateVerify. Ключи, найденные в сертификатах, ДОЛЖНЫ также быть подходящего типа для алгоритмов подписи, с которыми они используются. Это особая проблема для ключей RSA и подписи PSS, как описано ниже. Если расширение «signature_algorithms_cert» отсутствует, расширение «signature_algorithms» также применяется к сигнатурам, появляющимся в сертификатах. Клиенты, которые хотят, чтобы сервер аутентифицировался через сертификат, ДОЛЖНЫ отправить расширение «signature_algorithms». Если сервер аутентифицируется через сертификат и клиент не отправил расширение «signature_algorithms», то сервер ДОЛЖЕН отменить рукопожатие с предупреждением «missing_extension» (см. Раздел 9.2).

Расширение «signature_algorithms_cert» было добавлено, чтобы позволить реализациям, которые поддерживали различные наборы алгоритмов для сертификатов и самого TLS, чтобы четко сигнализировать о своих возможностях. Реализации TLS 1.2 ДОЛЖНЫ также обрабатывать это расширение. Реализации, которые имеют одну и ту же политику в обоих случаях, МОГУТ опустить расширение «signature_algorithms_cert».

Поле «extension_data» этих расширений содержит значение SignatureSchemeList:

enum {
/* RSASSA-PKCS1-v1_5 algorithms */
rsa_pkcs1_sha256(0x0401),
rsa_pkcs1_sha384(0x0501),
rsa_pkcs1_sha512(0x0601),
/* ECDSA algorithms */
ecdsa_secp256r1_sha256(0x0403),
ecdsa_secp384r1_sha384(0x0503),
ecdsa_secp521r1_sha512(0x0603),
/* RSASSA-PSS algorithms with public key OID rsaEncryption */
rsa_pss_rsae_sha256(0x0804),
rsa_pss_rsae_sha384(0x0805),
rsa_pss_rsae_sha512(0x0806),
/* EdDSA algorithms */
ed25519(0x0807),
ed448(0x0808),
/* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
rsa_pss_pss_sha256(0x0809),
rsa_pss_pss_sha384(0x080a),
rsa_pss_pss_sha512(0x080b),
/* Legacy algorithms */
rsa_pkcs1_sha1(0x0201),
ecdsa_sha1(0x0203),
/* Reserved Code Points */
private_use(0xFE00..0xFFFF),
(0xFFFF)
} SignatureScheme;
struct {
SignatureScheme supported_signature_algorithms<2..2^16-2>;
} SignatureSchemeList;

Примечание. Это перечисление называется «SignatureScheme», поскольку в TLS 1.2 уже существует тип «SignatureAlgorithm», который это заменяет. В тексте мы используем термин «алгоритм подписи».

Каждое значение SignatureScheme содержит единый алгоритм подписи, который клиент хочет проверить. Значения указаны в порядке убывания предпочтения. Обратите внимание, что алгоритм подписи принимает на входе сообщение произвольной длины, а не дайджест. Алгоритмы, которые традиционно действуют на дайджесте, должны быть определены в TLS для первого хэш-ввода с заданным алгоритмом хеширования, а затем действовать как обычно. Перечисленные выше коды кодовых точек имеют следующие значения:

  • Алгоритмы RSASSA-PKCS1-v1_5: Указывает алгоритм подписи с использованием RSASSA-PKCS1-v1_5 [RFC8017] с соответствующим алгоритмом хеширования, как определено в [SHS]. Эти значения относятся исключительно к сигнатурам, которые отображаются в сертификатах (см. Раздел 4.4.2.2), и не определены для использования в подписанных сообщениях подтверждения TLS, хотя они МОГУТ появляться в «signature_algorithms» и «signature_algorithms_cert» для обратной совместимости с TLS 1.2.
  • Алгоритмы ECDSA: Указывает алгоритм подписи с использованием ECDSA [ECDSA], соответствующую кривую, как определено в ANSI X9.62 [ECDSA] и FIPS 186-4 [DSS], и соответствующий алгоритм хеширования, как определено в [SHS]. Подпись представляется в виде DER-кодированной структуры [X690] ECDSA-Sig-Value.
  • Алгоритмы RSASSA-PSS RSAE: Указывает алгоритм подписи с использованием RSASSA-PSS [RFC8017] с функцией генерации маски 1. Сборник, используемый в функции генерации маски и подписанного дайджеста, является как соответствующим алгоритмом хеширования, определенным в [SHS]. Длина Соли ДОЛЖНА быть равна длине выхода алгоритма дайджеста. Если открытый ключ хранится в сертификате X.509, он ДОЛЖЕН использовать идентификатор rsaEncryption OID [RFC5280].
  • Алгоритмы EdDSA: Указывает алгоритм подписи с использованием EdDSA, как определено в [RFC8032] или его преемниках. Обратите внимание, что они соответствуют алгоритмам «PureEdDSA», а не «предварительным» вариантам.
  • Алгоритмы RSASSA-PSS PSS: Указывает алгоритм подписи с использованием RSASSA-PSS [RFC8017] с функцией генерации маски 1. Сборник, используемый в функции генерации маски и подписанного дайджеста, является как соответствующим алгоритмом хеширования, определенным в [SHS]. Длина Соли ДОЛЖНА быть равна длине алгоритма дайджеста. Если открытый ключ переносится сертификатом X.509, он ДОЛЖЕН использовать RSASSA-PSS OID [RFC5756]. При использовании в сигнатурах сертификатов параметры алгоритма ДОЛЖНЫ быть закодированы DER. Если присутствуют соответствующие параметры открытого ключа, то параметры в подписи ДОЛЖНЫ быть идентичны параметрам открытого ключа.
  • Устаревшие алгоритмы: Указывает алгоритмы, которые устаревают, потому что они используют алгоритмы с известными недостатками, в частности SHA-1, который используется в этом контексте с (1) RSA с использованием RSASSA-PKCS1-v1_5 или (2) ECDSA. Эти значения относятся исключительно к сигнатурам, которые отображаются в сертификатах (см. Раздел 4.4.2.2), и не определены для использования в подписанных сообщениях подтверждения TLS, хотя они МОГУТ появляться в «signature_algorithms» и «signature_algorithms_cert» для обратной совместимости с TLS 1.2. Конечные точки НЕ ДОЛЖНЫ согласовывать эти алгоритмы, но им разрешено делать это исключительно для обратной совместимости. Клиенты, предлагающие эти значения, ДОЛЖНЫ перечислять их как самый низкий приоритет (указанный после всех других алгоритмов в SignatureSchemeList). Серверы TLS 1.3 НЕ ДОЛЖНЫ предлагать подписанный сертификат SHA-1, если без него не может быть создана действительная цепочка сертификатов (см. Раздел 4.4.2.2).

Подписи на сертификатах, которые являются самозаверяющими, или сертификаты, которые являются привязками доверия, не проверяются, поскольку они начинают путь сертификации (см. [RFC5280], раздел 3.2). Сертификат, который начинает путь сертификации, МОЖЕТ использовать алгоритм подписи, который не рекламируется как поддерживаемый в расширении «signature_algorithms».

Обратите внимание, что TLS 1.2 определяет это расширение по-разному. Реализации TLS 1.3, желающие согласовать TLS 1.2, должны вести себя в соответствии с требованиями [RFC5246] при обсуждении этой версии. Особенно:

  • TLS 1.2 ClientHellos МОЖЕТ пропустить это расширение.
  • В TLS 1.2 расширение содержало пары hash / signature. Пар кодируется в двух октетах, поэтому значения SignatureScheme были выделены для согласования с кодировкой TLS 1.2. Некоторые старые пары остаются нераспределенными. Эти алгоритмы устарели от TLS 1.3. Они НЕ ДОЛЖНЫ предлагаться или обсуждаться с помощью какой-либо реализации. В частности, MD5 [SLOTH], SHA-224 и DSA НЕ ДОЛЖНЫ использоваться.
  • Схемы подписи ECDSA согласуются с парами хэша / подписи ECDSA TLS 1.2. Однако старая семантика не ограничивала кривую подписи. Если TLS 1.2 обсуждается, реализации ДОЛЖНЫ быть готовы принять подпись, которая использует любую кривую, которую они рекламируют в расширении «supported_groups».
  • Реализации, которые рекламируют поддержку RSASSA-PSS (что является обязательным в TLS 1.3), ДОЛЖНЫ быть готовы принять подпись, используя эту схему, даже когда TLS 1.2 обсуждается. В TLS 1.2 RSASSA-PSS используется с наборами шифрования RSA.

4.2.4. Органы по сертификации

Расширение «certificate_authorities» используется для указания полномочий сертификатов (CA), которые поддерживает конечная точка и которые ДОЛЖНЫ использоваться конечной точкой приема для указания выбора сертификата.

Тело расширения «certificate_authorities» состоит из структуры CertificateAuthoritiesExtension.

opaque DistinguishedName<1..2^16-1>;
struct {
DistinguishedName authorities<3..2^16-1>;
} CertificateAuthoritiesExtension;

  • authorities (полномочия): список отличительных имен [X501] приемлемых органов сертификации, представленных в формате DER-кодированного [X690]. Эти отличительные имена указывают желаемое различающееся имя для привязки доверия или подчиненного ЦС; таким образом, это сообщение может использоваться для описания известных доверительных привязок, а также для требуемого пространства авторизации.

Клиент МОЖЕТ отправить расширение «certificate_authorities» в сообщении ClientHello. Сервер МОЖЕТ отправить его в сообщении CertificateRequest.

Расширение «trusted_ca_keys» [RFC6066], которое работает с аналогичной целью, но более сложное, не используется в TLS 1.3 (хотя оно может появляться в сообщениях ClientHello от клиентов, которые предлагают предыдущие версии TLS).

4.2.5. Фильтры OID

Расширение «oid_filters» позволяет серверам предоставлять набор пар OID / value, которым он должен соответствовать сертификат клиента. Это расширение, если оно предоставляется сервером, ДОЛЖНО быть отправлено только в сообщении CertificateRequest.

struct {
opaque certificate_extension_oid<1..2^8-1>;
opaque certificate_extension_values<0..2^16-1>;
} OIDFilter;
struct {
OIDFilter filters<0..2^16-1>;
} OIDFilterExtension;

  • filters: Список OID расширений сертификатов [RFC5280] с их допустимыми значениями и представлен в формате DIR-кодированного [X690]. Некоторые идентификаторы расширения сертификатов допускают несколько значений (например, расширенное использование ключа). Если на сервере включен список непустых фильтров, сертификат клиента, включенный в ответ, ДОЛЖЕН содержать все указанные OID расширения, которые клиент распознает. Для каждого идентификатора OID расширения, распознанного клиентом, все указанные значения ДОЛЖНЫ присутствовать в сертификате клиента (но сертификат МОЖЕТ иметь и другие значения). Однако клиент ДОЛЖЕН игнорировать и пропускать любые нераспознанные OID-расширения расширений сертификатов. Если клиент проигнорировал некоторые из требуемых идентификаторов расширений сертификатов и предоставил сертификат, который не удовлетворяет запросу, сервер МОЖЕТ по своему усмотрению либо продолжить соединение без аутентификации клиента, либо прервать рукопожатие с предупреждением «unsupported_certificate». Любой заданный OID НЕ ДОЛЖЕН появляться более одного раза в списке фильтров.

PKIX RFC определяют множество OID расширений сертификатов и их соответствующие типы значений. В зависимости от типа соответствующие значения расширения сертификатов необязательно побитообразны. Ожидается, что реализации TLS будут полагаться на свои библиотеки PKI для выполнения выбора сертификатов с использованием OID расширений сертификатов.

В этом документе определяются правила соответствия для двух стандартных расширений сертификата, определенных в [RFC5280]:

  • Расширение использования ключа в сертификате соответствует запросу, когда все биты использования ключа, указанные в запросе, также указываются в расширении сертификата использования ключа.
  • Расширение расширенного ключа в сертификате соответствует запросу, когда все идентификаторы OID с ключевыми целями, присутствующие в запросе, также находятся в расширении сертификата расширенного ключа. Специальный запрос anyExtendedKeyUsage НЕ ДОЛЖЕН использоваться в запросе.

Отдельные спецификации могут определять правила соответствия для других расширений сертификата.

4.2.6. Аутентификация клиента после рукопожатия

Расширение «post_handshake_auth» используется, чтобы указать, что клиент готов выполнить аутентификацию после установления связи (раздел 4.6.2). Серверы НЕ ДОЛЖНЫ посылать заказ-подтверждение по рукопожатию клиентам, которые не предлагают это расширение. Серверы НЕ ДОЛЖНЫ отправлять это расширение.

struct {} PostHandshakeAuth;

Поле «extension_data» расширения «post_handshake_auth» равно нулю.

4.2.7. Поддерживаемые группы

При отправке клиентом расширение «supported_groups» указывает на именованные группы, которые клиент поддерживает для обмена ключами, упорядоченные с наиболее предпочтительной наименее предпочтительной.

Примечание. В версиях TLS до TLS 1.3 это расширение было названо «эллиптические_курсы» и содержало только группы эллиптических кривых. См. [RFC8422] и [RFC7919]. Это расширение также использовалось для согласования кривых ECDSA. Алгоритмы подписей теперь согласованы независимо (см. Раздел 4.2.3).

Поле «extension_data» этого расширения содержит значение «NamedGroupList»:

enum {
/* Elliptic Curve Groups (ECDHE) */
secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
x25519(0x001D), x448(0x001E),
/* Finite Field Groups (DHE) */
ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
ffdhe6144(0x0103), ffdhe8192(0x0104),
/* Reserved Code Points */
ffdhe_private_use(0x01FC..0x01FF),
ecdhe_private_use(0xFE00..0xFEFF),
(0xFFFF)
} NamedGroup;
struct {
NamedGroup named_group_list<2..2^16-1>;
} NamedGroupList;

  • Эллиптические кривые группы (ECDHE): Указывает поддержку соответствующей именованной кривой, определенной в FIPS 186-4 [DSS] или [RFC7748]. Значения 0xFE00 — 0xFEFF зарезервированы для частного использования [RFC8126].
  • Конечные группы полей (DHE): указывает поддержку соответствующей конечной группы полей, определенной в [RFC7919]. Значения 0x01FC через 0x01FF зарезервированы для личного использования.

Элементы в named_group_list упорядочиваются в соответствии с предпочтениями отправителя (наиболее предпочтительный выбор в первую очередь).

Начиная с TLS 1.3, серверам разрешено отправлять расширение «supported_groups» клиенту. Клиенты НЕ ДОЛЖНЫ воздействовать на любую информацию, найденную в «поддерживаемых группах» до успешного завершения рукопожатия, но МОЖЕТ использовать информацию, полученную из успешного завершенного рукопожатия, чтобы изменить, какие группы они используют в своем расширении «key_share» в последующих соединениях. Если сервер имеет группу, он предпочитает те, что в расширении «key_share», но по-прежнему готов принять ClientHello, он ДОЛЖЕН отправить «supported_groups», чтобы обновить представление клиента о его предпочтениях; это расширение ДОЛЖНО содержать все группы, поддерживаемые сервером, независимо от того, поддерживаются ли они в настоящее время клиентом.

4.2.8. Основная доля

Расширение «key_share» содержит криптографические параметры конечной точки.

Клиенты МОГУТ отправить пустой вектор client_shares, чтобы запросить отбор группы с сервера, за дополнительную дополнительную поездку туда и обратно (см. Раздел 4.1.4).

struct {
NamedGroup group;
opaque key_exchange<1..2^16-1>;
} KeyShareEntry;

  • group: Именованная группа для обмена ключа.
  • key_exchange: информация об обмене ключами. Содержимое этого поля определяется указанной группой и ее соответствующим определением. Параметры конечного поля Diffie-Hellman [DH76] описаны в разделе 4.2.8.1; Эллиптическая кривая Параметры Диффи-Хеллмана описаны в разделе 4.2.8.2.

В сообщении ClientHello поле «extension_data» этого расширения содержит значение «KeyShareClientHello»:

struct {
KeyShareEntry client_shares<0..2^16-1>;
} KeyShareClientHello;

  • client_shares: список предлагаемых значений KeyShareEntry в порядке убывания предпочтений клиента.

Этот вектор МОЖЕТ быть пустым, если клиент запрашивает HelloRetryRequest. Каждое значение KeyShareEntry ДОЛЖНО соответствовать группе, предлагаемой в расширении «supported_groups», и ДОЛЖНО отображаться в том же порядке. Однако значения МОГУТ быть несмежным подмножеством расширения «supported_groups» и МОГУ опустить наиболее предпочтительные группы. Такая ситуация может возникнуть, если наиболее предпочтительные группы являются новыми и вряд ли будут поддерживаться в достаточном количестве, чтобы обеспечить для них повышение эффективности ключевых акций.

Клиенты могут предлагать столько значений KeyShareEntry, сколько количество поддерживаемых групп, которые они предлагают, каждый из которых представляет один набор параметров обмена ключами. Например, клиент может предлагать акции для нескольких эллиптических кривых или нескольких групп FFDHE. Значения key_exchange для каждого KeyShareEntry ДОЛЖНЫ генерироваться независимо. Клиенты НЕ ДОЛЖНЫ предлагать несколько значений KeyShareEntry для одной и той же группы. Клиенты НЕ ДОЛЖНЫ предлагать значения KeyShareEntry для групп, не указанных в расширении «supported_groups» клиента. Серверы МОГУТ проверить наличие нарушений этих правил и отменить рукопожатие с предупреждением «незаконный_параметр», если он нарушен.

В сообщении HelloRetryRequest поле «extension_data» этого расширения содержит значение KeyShareHelloRetryRequest:

struct {
NamedGroup selected_group;
} KeyShareHelloRetryRequest;

  • selected_group: взаимно поддерживаемая группа, на которой сервер намерен вести переговоры, и запрашивает повторный запрос ClientHello / KeyShare.

После получения этого расширения в HelloRetryRequest клиент ДОЛЖЕН проверить, что (1) поле selected_group соответствует группе, которая была предоставлена в расширении «supported_groups» в исходном ClientHello и (2) поле selected_group не соответствует группе который был предоставлен в расширении «key_share» в оригинале ClientHello. Если какая-либо из этих проверок не удалась, клиент ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр». В противном случае при отправке нового ClientHello клиент ДОЛЖЕН заменить исходное расширение «key_share» на один, содержащий только новый KeyShareEntry для группы, указанной в поле selected_group запуска HelloRetryRequest.

В сообщении ServerHello поле «extension_data» этого расширения содержит значение KeyShareServerHello:

struct {
KeyShareEntry server_share;
} KeyShareServerHello;

  • server_share: Единственное значение KeyShareEntry, которое находится в той же группе, что и одна из акций клиента.

Если вы используете (EC) DHE-ключ, серверы предоставляют серверу только один ключ KeyShareEntry. Это значение ДОЛЖНО находиться в той же группе, что и значение KeyShareEntry, предлагаемое клиентом, которое сервер выбрал для согласованного обмена ключами. Серверы НЕ ДОЛЖНЫ отправлять KeyShareEntry для любой группы, не указанной в расширении «supported_groups» клиента, и НЕ ДОЛЖНЫ отправлять KeyShareEntry при использовании «psk_ke» PskKeyExchangeMode. Если клиент (DHL) использует (EC) DHE-ключ и HelloRetryRequest, содержащий расширение «key_share», клиент должен ДОЛЖНО проверить, что выбранная NamedGroup в ServerHello такая же, как в HelloRetryRequest. Если эта проверка не удалась, клиент ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр».

4.2.8.1. Параметры Диффи-Хелмана

Параметры Diffie-Hellman [DH76] для клиентов и серверов кодируются в непрозрачном поле key_exchange KeyShareEntry в структуре KeyShare. Непрозрачное значение содержит общедоступное значение Diffie-Hellman (Y = g ^ X mod p) для указанной группы (см. [RFC7919] для определений групп), закодированное как целое число большого конца и дополненное слева нулями до размера p в байтах.

Примечание. Для данной группы Diffie-Hellman заполнение приводит к тому, что все открытые ключи имеют одинаковую длину.

Peers ДОЛЖНЫ проверять открытый ключ друг друга Y, гарантируя, что 1 <Y <p-1. Эта проверка гарантирует, что удаленный одноранговый узел правильно ведет себя и не заставляет локальную систему в небольшую подгруппу.

4.2.8.2. Параметры ECDHE

Параметры ECDHE для клиентов и серверов кодируются в непрозрачном поле key_exchange KeyShareEntry в структуре KeyShare.

Для secp256r1, secp384r1 и secp521r1, содержимое представляет собой сериализованное значение следующей структуры:

struct {
uint8 legacy_form = 4;
opaque X[coordinate_length];
opaque Y[coordinate_length];
} UncompressedPointRepresentation;

X и Y, соответственно, являются двоичными представлениями значений x и y в сетевом порядке байтов. Внутренних маркеров длины нет, поэтому каждое числовое представление занимает столько октетов, что подразумевается параметрами кривой. Для P-256 это означает, что каждый из X и Y использует 32 октета, при необходимости заполняя слева нулями. Для P-384 они занимают по 48 октетов. Для P-521 они занимают по 66 октетов.

Для кривых secp256r1, secp384r1 и secp521r1, сверстники ДОЛЖНЫ проверять общедоступное значение Q другого пользователя, гарантируя, что точка является действительной точкой на эллиптической кривой. Соответствующие процедуры проверки определяются в разделе 4.3.7 [ECDSA] и, как вариант, в разделе 5.6.2.3 [KEYAGREEMENT]. Этот процесс состоит из трех этапов: (1) проверить, что Q не является точкой на бесконечности (O), (2) проверить, что для Q = (x, y) оба целых числа x и y находятся в правильном интервале и (3 ), убедитесь, что (x, y) является правильным решением уравнения эллиптической кривой. Для этих кривых разработчикам не нужно проверять членство в правильной подгруппе.

Для X25519 и X448 содержимое общедоступного значения представляет собой входы и выходы строки байтов соответствующих функций, определенных в [RFC7748]: 32 байта для X25519 и 56 байтов для X448.

Примечание: Версии TLS до 1.3 разрешенных согласований формата точки; TLS 1.3 удаляет эту функцию в пользу одноточечного формата для каждой кривой.

4.2.9. Режимы обмена с предварительным обменом ключами

Чтобы использовать PSK, клиенты ДОЛЖНЫ также отправить расширение «psk_key_exchange_modes». Семантика этого расширения заключается в том, что клиент поддерживает только использование PSK с этими режимами, что ограничивает использование PSK, предлагаемых в этом ClientHello, и те, которые сервер может предоставить через NewSessionTicket.

Клиент должен предоставить расширение «psk_key_exchange_modes», если он предлагает расширение «pre_shared_key». Если клиенты предлагают «pre_shared_key» без расширения «psk_key_exchange_modes», серверы ДОЛЖНЫ отменить рукопожатие. Серверы НЕ ДОЛЖНЫ выбирать режим обмена ключами, который не указан клиентом. Это расширение также ограничивает режимы для возобновления PSK. Серверы НЕ ДОЛЖНЫ отправлять NewSessionTicket с билетами, которые не совместимы с рекламируемыми режимами; однако, если сервер делает это, влияние будет заключаться только в том, что попытки клиента по возобновлению не выполняются.

Сервер НЕ ДОЛЖЕН отправлять расширение «psk_key_exchange_modes».

enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
struct {
PskKeyExchangeMode ke_modes<1..255>;
} PskKeyExchangeModes;

  • psk_ke: создание ключа только для PSK. В этом режиме сервер НЕ ДОЛЖЕН поставлять значение «key_share».
  • psk_dhe_ke: PSK с установкой ключа DHE (EC). В этом режиме клиент и сервер ДОЛЖНЫ поставлять значения «key_share», как описано в разделе 4.2.8.

Любые будущие значения, которые выделяются, должны гарантировать, что переданные сообщения протокола однозначно определяют, какой режим был выбран сервером; В настоящее время это подтверждается наличием «key_share» в ServerHello.

4.2.10. Ранняя индикация данных

Когда используется PSK и ранние данные разрешены для этого PSK, клиент может отправлять данные приложения в свой первый полет сообщений. Если клиент захочет сделать это, он ДОЛЖЕН предоставить расширения «pre_shared_key» и «early_data».

Поле «extension_data» этого расширения содержит значение «EarlyDataIndication».

struct {} Empty;
struct {
select (Handshake.msg_type) {
case new_session_ticket: uint32 max_early_data_size;
case client_hello: Empty;
case encrypted_extensions: Empty;
};
} EarlyDataIndication;

Подробнее об использовании поля max_early_data_size см. В разделе 4.6.1.

Параметры для данных 0-RTT (версия, набор симметричных шифров, протокол протокола протокола Application-Layer (ALPN) [RFC7301] и т. Д.) — это те, которые связаны с используемым PSK. Для внешних PSK, связанных с внешними ресурсами, связанными значениями являются те, которые предоставляются вместе с ключом. Для PSK, созданных с помощью сообщения NewSessionTicket, связанными значениями являются те, которые были согласованы в соединении, которое установило PSK. PSK, используемый для шифрования ранних данных, ДОЛЖЕН быть первым PSK, указанным в расширении «pre_shared_key» клиента.

Для PSK, предоставленных через NewSessionTicket, сервер ДОЛЖЕН подтвердить, что возраст билета для выбранного идентификатора PSK (вычисленный путем вычитания ticket_age_add из PskIentity.obfuscated_ticket_age по модулю 2 ^ 32) находится в пределах небольшого допуска времени с момента выдачи билета (см. Раздел 8 ). Если это не так, сервер ДОЛЖЕН продолжить рукопожатие, но отклонить 0-RTT, и НЕ ДОЛЖЕН предпринимать никаких других действий, предполагающих, что этот ClientHello свежий.

Сообщения 0-RTT, отправленные в первом полете, имеют одинаковые (зашифрованные) типы контента как сообщения того же типа, отправленные в других рейсах (рукопожатие и приложение_данные), но защищены под разными ключами. После получения завершенного сообщения сервера, если сервер принял ранние данные, для указания изменения ключа будет отправлено сообщение EndOfEarlyData. Это сообщение будет зашифровано с помощью ключей трафика 0-RTT.

Сервер, который получает расширение «early_data», ДОЛЖЕН вести себя одним из трех способов:

  • Игнорировать расширение и вернуть регулярный ответ 1-RTT. Затем сервер пропускает предыдущие данные, пытаясь удалить защищенные записи с помощью ключа подтверждения рукопожатия, отбрасывая записи, которые не позволяют скрыть защиту (вплоть до настроенного max_early_data_size). Как только запись успешно удалена, она рассматривается как начало второго полета клиента, и сервер работает так же, как с обычным рукопожатием 1 RTT.
  • Запросите, чтобы клиент отправил другой ClientHello, ответив HelloRetryRequest. Клиент НЕ ДОЛЖЕН включать расширение «early_data» в своем последующем ClientHello. Затем сервер игнорирует ранние данные, пропуская все записи с типом внешнего контента «application_data» (указывая, что они зашифрованы), вплоть до настроенного max_early_data_size.
  • Верните собственное расширение «early_data» в EncryptedExtensions, указав, что оно намерено обрабатывать ранние данные. Сервер не может принимать только подмножество ранних сообщений данных. Несмотря на то, что сервер отправляет сообщение, принимающее ранние данные, фактические ранние данные могут уже находиться в полете к моменту, когда сервер генерирует это сообщение.

Чтобы принять ранние данные, сервер ДОЛЖЕН принять набор шифров PSK и выбрал первый ключ, предложенный в расширении «pre_shared_key» клиента. Кроме того, он ДОЛЖЕН проверить, что следующие значения такие же, как те, которые связаны с выбранным PSK:

  • Номер версии TLS
  • Выбранный набор шифров
  • Выбранный протокол ALPN [RFC7301], если таковой имеется

Эти требования являются надмножеством тех, которые необходимы для выполнения рукопожатия 1 RTT с использованием PSK. Для внешних PSK, связанных с ними, связаны значения, которые предоставляются вместе с ключом. Для PSK, установленных через сообщение NewSessionTicket, связанными значениями являются те, которые согласованы в соединении, в течение которого был установлен билет.

Будущие расширения ДОЛЖНЫ определить их взаимодействие с 0-RTT.

Если какая-либо из этих проверок терпит неудачу, сервер НЕ ДОЛЖЕН отвечать расширением и должен отбросить все данные первого полета с использованием одного из первых двух механизмов, перечисленных выше (таким образом, возврат к 1-RTT или 2-RTT). Если клиент пытается выполнить рукопожатие 0-RTT, но сервер отклоняет его, сервер, как правило, не будет иметь ключей защиты от записи 0-RTT и должен вместо этого использовать пробное дешифрование (либо с помощью ключей подтверждения 1 RTT, либо путем поиска открытого текста ClientHello в случае HelloRetryRequest), чтобы найти первое сообщение, отличное от 0-RTT.

Если сервер решает принять расширение «early_data», он ДОЛЖЕН соблюдать те же требования к обработке ошибок, которые указаны для всех записей при обработке ранних записей данных. В частности, если сервер не может расшифровать запись 0-RTT после принятого расширения «early_data», он ДОЛЖЕН прекратить соединение с предупреждением «bad_record_mac» в соответствии с разделом 5.2.

Если сервер отклоняет расширение «early_data», клиентское приложение МОЖЕТ выбрать повторную передачу данных приложения, ранее отправленных в ранние данные, после того, как рукопожатие будет завершено. Обратите внимание, что автоматическая повторная передача ранних данных может привести к неверным предположениям относительно статуса соединения. Например, когда согласованное соединение выбирает другой протокол ALPN из того, что использовалось для ранних данных, приложение может потребоваться для создания разных сообщений. Аналогичным образом, если ранние данные предполагают что-либо о состоянии соединения, он может быть отправлен по ошибке после завершения рукопожатия.

Внедрение TLS НЕ ДОЛЖНО автоматически повторно отправлять ранние данные; приложения находятся в лучшем положении, чтобы решить, когда повторная передача является подходящей. Реализация TLS НЕ ДОЛЖНА автоматически повторно отправлять ранние данные, если согласованное соединение не выбирает один и тот же протокол ALPN.

4.2.11. Расширение предварительного ключа

Расширение «pre_shared_key» используется для согласования идентификатора предварительно разделяемого ключа, который будет использоваться с данным рукопожатием в связи с установлением ключа PSK.

Поле «extension_data» этого расширения содержит значение «PreSharedKeyExtension»:

struct {
opaque identity<1..2^16-1>;
uint32 obfuscated_ticket_age;
} PskIdentity;
opaque PskBinderEntry<32..255>;
struct {
PskIdentity identities<7..2^16-1>;
PskBinderEntry binders<33..2^16-1>;
} OfferedPsks;
struct {
select (Handshake.msg_type) {
case client_hello: OfferedPsks;
case server_hello: uint16 selected_identity;
};
} PreSharedKeyExtension;

  • identity: метка для ключа. Например, билет (как определено в Приложении B.3.4) или ярлык для предварительно открытого ключа, установленного извне.
  • obfuscated_ticket_age: запутанная версия возраста ключа. В разделе 4.2.11.1 описывается, как сформировать это значение для идентификаторов, установленных через сообщение NewSessionTicket. Для идентификаторов, установленных извне, необходимо использовать obfuscated_ticket_age из 0, а серверы ДОЛЖНЫ игнорировать значение.
  • identities: список идентификаторов, которые клиент хочет согласовать с сервером. Если он отправлен вместе с расширением «early_data» (см. Раздел 4.2.10), первым идентификатором является тот, который используется для данных с 0-RTT.
  • binders: серия значений HMAC, по одному для каждого значения в списке идентификаторов и в том же порядке, рассчитанная, как описано ниже.
  • selected_identity: выбранная пользователем идентификация, выраженная в виде индекса (0) в идентификаторы в списке клиентов.

Каждый PSK связан с одним алгоритмом Хэша. Для PSK, установленных через механизм билета (раздел 4.6.1), это алгоритм KDF Hash на соединении, в котором был установлен билет. Для внешних PSK, алгоритм Hash ДОЛЖЕН быть установлен, когда PSK установлен или по умолчанию SHA-256, если такой алгоритм не определен. Сервер ДОЛЖЕН гарантировать, что он выбирает совместимый PSK (если есть) и набор шифров.

В версиях TLS перед TLS 1.3 значение идентификатора сервера (SNI) предназначалось для связи с сеансом (раздел 3 из [RFC6066]), при этом серверу требуется обеспечить, чтобы значение SNI, связанное с сеансом, соответствовало указанный в возобновлении рукопожатия. Однако на практике реализации не были согласованы с тем, какой из двух предоставленных значений SNI они будут использовать, что приведет к тому, что требования согласованности будут фактически соблюдены клиентами. В TLS 1.3 значение SNI всегда указывается явно в рукопожатии возобновления, и серверу не нужно связывать значение SNI с билетом. Клиенты, однако, СЛЕДУЕТ хранить SNI с PSK для выполнения требований Раздела 4.6.1.

Примечание разработчика. Когда возобновление сеанса является основным вариантом использования PSK, самым простым способом реализации требований соответствия PSK / cipher Suite является сначала согласование набора шифров, а затем исключение любых несовместимых PSK. Любые неизвестные PSK (например, те, которые не находятся в базе данных PSK или зашифрованы неизвестным ключом) ДОЛЖНЫ просто игнорироваться. Если приемлемых PSK не найдено, сервер ДОЛЖЕН выполнить, если это возможно, квитирование, отличное от PSK. Если важна обратная совместимость, предоставляемые клиентом, созданные извне ПСК должны влиять на выбор набора шифров.

До принятия установки ключа PSK сервер ДОЛЖЕН проверять соответствующее значение связующего (см. Раздел 4.2.11.2 ниже). Если это значение отсутствует или не подтверждается, сервер ДОЛЖЕН прервать рукопожатие. Серверу НЕ ДОЛЖНЫ пытаться проверить несколько связующих; скорее, они ДОЛЖНЫ выбирать один PSK и проверять только связующее, которое соответствует этому PSK. См. Раздел 8.2 и приложение E.6 для обоснования безопасности для этого требования. Чтобы принять назначение ключа PSK, сервер отправляет расширение «pre_shared_key», указывающее на выбранный идентификатор.

Клиенты ДОЛЖНЫ проверять, что выбранная_идентификация сервера находится в пределах диапазона, предоставленного клиентом, что сервер выбрал набор шифров, обозначающий хеш, связанный с PSK, и что расширение сервера «key_share» присутствует, если это требуется расширением Clientlello «psk_key_exchange_modes» , Если эти значения несовместимы, клиент ДОЛЖЕН отменить рукопожатие с предупреждением «незаконный_параметр».

Если сервер поставляет расширение «early_data», клиент ДОЛЖЕН проверять, что выбранный_identity сервера равен 0. Если какое-либо другое значение возвращается, клиент ДОЛЖЕН прервать рукопожатие с предупреждением «незаконный_параметр».

Расширение «pre_shared_key» ДОЛЖНО быть последним расширением в ClientHello (это облегчает реализацию, как описано ниже). Серверы ДОЛЖНЫ проверить, что это последнее расширение, и, в противном случае, не удается выполнить рукопожатие с предупреждением «незаконный_параметр».

4.2.11.1. Возраст билета

Взгляд клиента на возраст билета — это время с момента получения сообщения NewSessionTicket. Клиенты НЕ ДОЛЖНЫ пытаться использовать билеты, возраст которых превышает значение «ticket_lifetime», которое было предоставлено с помощью билета. Поле obfuscated_ticket_age каждого PskIdentity содержит запутанную версию возраста билета, образованного путем достижения возраста в миллисекундах и добавления значения «ticket_age_add», которое было включено в билет (см. Раздел 4.6.1), по модулю 2 ^ 32. Это добавление не позволяет пассивным наблюдателям сопоставлять соединения, если билеты не используются повторно. Обратите внимание, что поле «ticket_lifetime» в сообщении NewSessionTicket находится в секундах, но «obfuscated_ticket_age» находится в миллисекундах. Поскольку срок службы билетов ограничен до недели, 32 бита достаточно, чтобы представить какой-либо правдоподобный возраст, даже в миллисекундах.

4.2.11.2. PSK Binder

Значение связующего PSK формирует привязку между PSK и текущим рукопожатием, а также привязку между рукопожатием, в котором был создан PSK (если через сообщение NewSessionTicket) и текущим рукопожатием. Каждая запись в списке связующих вычисляется как HMAC поверх хэша транскрипта (см. Раздел 4.4.1), содержащего частичный ClientHello до и включая поле PreSharedKeyExtension.identities. То есть он включает в себя все ClientHello, но не список переплетов. Поля длины для сообщения (включая общую длину, длину блока расширений и длину расширения «pre_shared_key») задаются так, как будто в нем присутствуют связующие правильные длины.

PskBinderEntry вычисляется так же, как и сообщение Finished (раздел 4.4.4), но с базовым ключом, являющимся ключом binder_key, выведенным по расписанию ключей из соответствующего PSK, который предлагается (см. Раздел 7.1).

Если рукопожатие включает HelloRetryRequest, исходные ClientHello и HelloRetryRequest включены в стенограмму вместе с новым ClientHello. Например, если клиент отправляет ClientHello1, его связующее будет вычисляться следующим образом:

Transcript-Hash(Truncate(ClientHello1))

Где Truncate () удаляет список вложений из ClientHello.

Если сервер отвечает HelloRetryRequest, а клиент отправляет ClientHello2, его связующее будет вычисляться по:

Transcript-Hash(ClientHello1,
HelloRetryRequest,
Truncate(ClientHello2))

Полный ClientHello1 / ClientHello2 включен во все другие хеш-вычисления рукопожатия. Обратите внимание, что в первом полете Truncate (ClientHello1) хэшируется напрямую, но во втором полете ClientHello1 хешируется, а затем повторно вводится как сообщение «message_hash», как описано в разделе 4.4.1.

4.2.11.3. Порядок обработки

Клиентам разрешено «передавать» данные 0-RTT до тех пор, пока они не получат завершенный сервер, а затем отправят сообщение EndOfEarlyData, а затем остальное рукопожатие. Чтобы избежать взаимоблокировок, при принятии «early_data» серверы ДОЛЖНЫ обрабатывать клиентский клиент ClientHello, а затем немедленно отправлять свой полет сообщений, а не ждать сообщения клиента EndOfEarlyData перед отправкой его ServerHello.

4.3. Параметры сервера

Следующие два сообщения с сервера: EncryptedExtensions и CertificateRequest содержат информацию с сервера, которая определяет остальную часть рукопожатия. Эти сообщения зашифровываются ключами, полученными из server_handshake_traffic_secret.

4.3.1. Шифрованные расширения

Во всех рукопожатиях сервер ДОЛЖЕН отправить сообщение EncryptedExtensions сразу после сообщения ServerHello. Это первое сообщение, которое зашифровывается под ключами, полученными из server_handshake_traffic_secret.

Сообщение EncryptedExtensions содержит расширения, которые могут быть защищены, то есть любые, которые не нужны для установления криптографического контекста, но которые не связаны с отдельными сертификатами. Клиент ДОЛЖЕН проверять EncryptedExtensions на наличие каких-либо запрещенных расширений, и если они обнаружены, ДОЛЖЕН прервать рукопожатие с предупреждением «незаконный_параметр».

Структура этого сообщения:

struct {
Extension extensions<0..2^16-1>;
} EncryptedExtensions;

extensions: список расширений. Для получения дополнительной информации см. Таблицу в разделе 4.2.

4.3.2. Запрос сертификата

Сервер, который аутентифицируется с сертификатом, МОЖЕТ опционально запрашивать сертификат у клиента. Это сообщение, если отправлено, ДОЛЖНО следовать EncryptedExtensions.

Структура этого сообщения:

struct {
opaque certificate_request_context<0..2^8-1>;
Extension extensions<2..2^16-1>;
} CertificateRequest;

  • certificate_request_context: непрозрачная строка, которая идентифицирует запрос сертификата и которая будет отображаться в сообщении сертификата клиента. Сертификат_request_context ДОЛЖЕН быть уникальным в рамках этого соединения (таким образом предотвращая повторение сообщений ClientVerify клиента). Это поле ДОЛЖНО быть нулевой длиной, если оно не используется для обменов аутентификации после установления связи, описанных в разделе 4.6.2. При запросе аутентификации после установления подлинности сервер ДОЛЖЕН сделать контекст непредсказуемым для клиента (например, произвольно его генерируя), чтобы предотвратить злоумышленник, у которого есть временный доступ к закрытому ключу клиента из предварительно вычисляющих допустимые сообщения CertificateVerify.
  • extensions: набор расширений, описывающих параметры запрашиваемого сертификата. Расширение «signature_algorithms» ДОЛЖНО указываться, и другие расширения могут быть необязательно включены, если они определены для этого сообщения. Клиенты ДОЛЖНЫ игнорировать непризнанные расширения.

В предыдущих версиях TLS в сообщении CertificateRequest содержался список алгоритмов подписи и органов сертификации, которые сервер принял бы. В TLS 1.3 первая выражается путем отправки «сигнатурных алгоритмов» и, возможно, расширений «signature_algorithms_cert». Последнее выражается путем отправки расширения «certificate_authorities» (см. Раздел 4.2.4).

Серверы, которые аутентифицируются с помощью PSK, НЕ ДОЛЖНЫ отправлять сообщение CertificateRequest в основное рукопожатие, хотя они МОГУТ отправить его в аутентификацию после установления связи (см. Раздел 4.6.2) при условии, что клиент отправил расширение post_handshake_auth (см. Раздел 4.2.6).

4.4. Сообщения об аутентификации

Как обсуждалось в Разделе 2, TLS обычно использует общий набор сообщений для аутентификации, подтверждения ключа и целостности квитирования: Certificate, CertificateVerify и Finished. (Связывание PSK также выполняет ключевое подтверждение аналогичным образом.) Эти три сообщения всегда отправляются в качестве последних сообщений в их рукопожатии. Сообщения Certificate и CertificateVerify отправляются только при определенных обстоятельствах, как определено ниже. Сообщение «Готово» всегда отправляется как часть блока проверки подлинности. Эти сообщения зашифровываются под ключами, полученными из [отправителя] _handshake_traffic_secret.

Вычисления для сообщений аутентификации равномерно принимают следующие значения:

  • Используемый сертификат и ключ подписи.
  • Контекст рукопожатия, состоящий из набора сообщений, которые должны быть включены в хэширование транскрипта.
  • Базовый ключ, который будет использоваться для вычисления ключа MAC.

На основе этих данных сообщения затем содержат:

  • Certificate: сертификат, который будет использоваться для аутентификации, и любые подтверждающие сертификаты в цепочке. Обратите внимание, что аутентификация клиента на основе сертификата недоступна в потоках квитирования PSK (включая 0-RTT).
  • CertificateVerify: подпись над значением Transcript-Hash (контекст подтверждения, сертификат).
  • Finished: MAC над значением Transcript-Hash (контекст подтверждения, сертификат, CertificateVerify) с использованием ключа MAC, полученного из базового ключа.

В следующей таблице определяется контекст подтверждения и базовый ключ MAC для каждого сценария:

Контекст подтверждения и базовый ключ MAC для каждого сценария
Контекст подтверждения и базовый ключ MAC для каждого сценария

4.4.1. Стенограмма-стенограмма

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

Transcript-Hash(M1, M2, … Mn) = Hash(M1 || M2 || … || Mn)

В качестве исключения из этого общего правила, когда сервер отвечает на ClientHello с помощью HelloRetryRequest, значение ClientHello1 заменяется специальным синтетическим сообщением рукопожатия типа рукопожатия «message_hash», содержащим Hash (ClientHello1). т.е.,

Transcript-Hash(ClientHello1, HelloRetryRequest, … Mn) =
Hash(message_hash || /* Handshake type */
00 00 Hash.length || /* Handshake message length (bytes) */
Hash(ClientHello1) || /* Hash of ClientHello1 */
HelloRetryRequest || … || Mn)

Причиной такой конструкции является предоставление серверу безжалостного HelloRetryRequest, сохраняя только хэш ClientHello1 в cookie, вместо того, чтобы требовать от него экспорта всего промежуточного хэш-состояния (см. Раздел 4.2.2).

Для конкретности хэш-запись транскрипта всегда берется из следующей последовательности сообщений подтверждения, начиная с первого ClientHello и включая только те сообщения, которые были отправлены:

ClientHello, HelloRetryRequest, ClientHello, ServerHello, EncryptedExtensions, server CertificateRequest, server Certificate, server CertificateVerify, server Finished, EndOfEarlyData, client Certificate, client CertificateVerify, client Finished.

В целом реализации могут реализовать транскрипт, сохраняя текущее значение хэширования транскрипта на основе согласованного хэша. Обратите внимание, однако, что последующая аутентификация после установления связи не включает друг друга, а только сообщения через конец основного рукопожатия.

4.4.2. Сертификат

Это сообщение передает цепочку сертификатов конечной точки партнеру.

Сервер ДОЛЖЕН отправлять сообщение «Сертификат» всякий раз, когда согласованный метод обмена ключами использует сертификаты для аутентификации (сюда относятся все методы обмена ключами, определенные в этом документе, кроме PSK).

Клиент ДОЛЖЕН отправлять сообщение сертификата тогда и только тогда, когда сервер запросил аутентификацию клиента через сообщение CertificateRequest (раздел 4.3.2). Если сервер запрашивает аутентификацию клиента, но подходящий сертификат не доступен, клиент ДОЛЖЕН отправить сообщение сертификата, не содержащее сертификатов (т. Е. С полем «certificate_list», имеющим длину 0). Завершенное сообщение ДОЛЖНО быть отправлено независимо от того, пустое сообщение сертификата.

enum {
X509(0),
RawPublicKey(2),
(255)
} CertificateType;
struct {
select (certificate_type) {
case RawPublicKey:
/* From RFC 7250 ASN.1_subjectPublicKeyInfo */
opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;
case X509:
opaque cert_data<1..2^24-1>;
};
Extension extensions<0..2^16-1>;
} CertificateEntry;
struct {
opaque certificate_request_context<0..2^8-1>;
CertificateEntry certificate_list<0..2^24-1>;
} Certificate;

  • certificate_request_context: Если это сообщение находится в ответ на CertificateRequest, значение certificate_request_context в этом сообщении. В противном случае (в случае аутентификации сервера) это поле ДОЛЖНО иметь нулевую длину.
  • certificate_list: последовательность (цепочка) структур CertificateEntry, каждая из которых содержит один сертификат и набор расширений.
  • extensions: набор значений расширения для CertificateEntry. Формат «Расширение» определен в разделе 4.2. Допустимые расширения для сертификатов сервера в настоящее время включают расширение статуса OCSP [RFC6066] и расширение SignedCertificateTimestamp [RFC6962]; будущие расширения могут быть определены и для этого сообщения. Расширения в сообщении сертификата с сервера ДОЛЖНЫ соответствовать сообщениям из сообщения ClientHello. Расширения в сообщении сертификата от клиента ДОЛЖНЫ соответствовать расширениям в сообщении CertificateRequest с сервера. Если расширение применяется ко всей цепочке, оно ДОЛЖНО быть включено в первую CertificateEntry.

Если соответствующее расширение типа сертификата («server_certificate_type» или «client_certificate_type») не обсуждалось в EncryptedExtensions или не согласовано с типом сертификата X.509, то каждый CertificateEntry содержит сертификат X.509, закодированный DER. Сертификат отправителя ДОЛЖЕН войти в первую CertificateEntry в списке. Каждому следующему сертификату СЛЕДУЕТ сразу же подтвердить тот, который находится непосредственно перед ним. Поскольку проверка сертификата требует, чтобы доверительные привязки распределялись независимо друг от друга, сертификат, который указывает привязку доверия, МОЖЕТ быть исключен из цепочки, при условии, что поддерживаемые одноранговые узлы имеют какие-либо пропущенные сертификаты.

Примечание. До TLS 1.3, «сертификат_list» заказывал, чтобы каждый сертификат сертифицировал тот, который был непосредственно перед ним; однако некоторые реализации позволили сделать некоторую гибкость. Серверы иногда отправляют как текущее, так и устаревшее промежуточное звено для переходных целей, а другие просто настроены неправильно, но эти случаи, тем не менее, могут быть правильно проверены. Для максимальной совместимости все реализации ДОЛЖНЫ быть готовы обрабатывать потенциально посторонние сертификаты и произвольные заказы из любой версии TLS, за исключением сертификата конечного объекта, который ДОЛЖЕН быть первым.

Если тип сертификата RawPublicKey был согласован, тогда сертификат_файл ДОЛЖЕН содержать не более одного CertificateEntry, который содержит значение ASN1_subjectPublicKeyInfo, определенное в [RFC7250], раздел 3.

Тип сертификата OpenPGP [RFC6091] НЕ ДОЛЖЕН использоваться с TLS 1.3.

Серверный_сертификат сервера ДОЛЖЕН всегда быть непустым. Клиент отправит пустой сертификат, если у него нет соответствующего сертификата для отправки в ответ на запрос аутентификации сервера.

4.4.2.1. Статус OCSP и расширения SCT

[RFC6066] и [RFC6961] предоставляют расширения для согласования сервера, отправляющего ответы OCSP клиенту. В TLS 1.2 и ниже сервер отвечает пустым расширением, чтобы указать согласование этого расширения, а информация OCSP переносится в сообщении CertificateStatus. В TLS 1.3 информация OCSP сервера переносится в расширение в CertificateEntry, содержащем соответствующий сертификат. В частности, тело расширения status_request с сервера ДОЛЖНО быть структурой CertificateStatus, как определено в [RFC6066], которая интерпретируется, как определено в [RFC6960].

Примечание. Расширение status_request_v2 [RFC6961] устарело. Серверы TLS 1.3 НЕ ДОЛЖНЫ воздействовать на его присутствие или информацию в нем при обработке сообщений ClientHello; в частности, они НЕ ДОЛЖНЫ отправлять расширение status_request_v2 в сообщениях EncryptedExtensions, CertificateRequest или Certificate. Серверы TLS 1.3 ДОЛЖНЫ обрабатывать сообщения ClientHello, которые включают его, поскольку он МОЖЕТ быть отправлен клиентами, которые хотят использовать его в более ранних версиях протокола.

Сервер МОЖЕТ запросить, чтобы клиент представил ответ OCSP с его сертификатом, посылая пустое расширение «status_request» в своем сообщении CertificateRequest. Если клиент выбирает ответ OCSP, тело его расширения status_request ДОЛЖНО быть структурой CertificateStatus, как определено в [RFC6066].

Аналогичным образом, [RFC6962] предоставляет механизм для сервера, который отправляет отметку времени подписанного сертификата (SCT) в качестве расширения в ServerHello в TLS 1.2 и ниже. В TLS 1.3 информация SCT сервера передается в расширении в CertificateEntry.

4.4.2.2. Выбор сертификата сервера

Для сертификатов, отправленных сервером, применяются следующие правила:

  • Тип сертификата ДОЛЖЕН быть X.509v3 [RFC5280], если явно не оговорено иначе (например, [RFC7250]).
  • Открытый ключ сертификата конечного объекта сервера (и связанные ограничения) ДОЛЖНЫ быть совместимы с выбранным алгоритмом аутентификации с расширением «signature_algorithms» клиента (в настоящее время RSA, ECDSA или EdDSA).
  • Сертификат ДОЛЖЕН разрешить использовать ключ для подписания (то есть бит digitalSignature ДОЛЖЕН быть установлен, если присутствует расширение использования ключа) с использованием схемы подписи, указанной в расширениях «signature_algorithms» / «signature_algorithms_cert» клиента (см. Раздел 4.2. 3).
  • Расширения «server_name» [RFC6066] и «certificate_authorities» используются для выбора сертификатов. Поскольку серверы МОГУТ требовать наличия расширения «имя_сервера», клиенты ДОЛЖНЫ отправлять это расширение, когда это применимо.

Все сертификаты, предоставляемые сервером, ДОЛЖНЫ быть подписаны алгоритмом подписи, объявленным клиентом, если он может обеспечить такую цепочку (см. Раздел 4.2.3). Сертификаты, которые являются самоподписавшимися или сертификатами, которые, как ожидается, будут доверенными, не проверяются как часть цепочки и поэтому МОГУТ быть подписаны с любым алгоритмом.

Если сервер не может создать цепочку сертификатов, подписанную только с помощью указанных поддерживаемых алгоритмов, тогда она ДОЛЖНА продолжить рукопожатие, отправив клиенту цепочку сертификатов по своему выбору, которая может включать в себя алгоритмы, которые, как известно, не поддерживаются клиентом. Эта резервная цепочка НЕ ДОЛЖНА использовать устаревший алгоритм хэширования SHA-1 в целом, но МОЖЕТ сделать это, если разрешить рекламу клиента, и НЕ ДОЛЖЕН делать это иначе.

Если клиент не может создать приемлемую цепочку с использованием предоставленных сертификатов и решает прервать рукопожатие, он ДОЛЖЕН прервать рукопожатие с соответствующим предупреждением о сертификате (по умолчанию «unsupported_certificate», см. Раздел 6.2 для получения дополнительной информации).

Если сервер имеет несколько сертификатов, он выбирает один из них на основе вышеупомянутых критериев (в дополнение к другим критериям, таким как конечная точка транспортного уровня, локальная конфигурация и предпочтения).

4.4.2.3. Выбор сертификата клиента

К сертификатам, отправленным клиентом, относятся следующие правила:

  • Тип сертификата ДОЛЖЕН быть X.509v3 [RFC5280], если явно не оговорено иначе (например, [RFC7250]).
  • Если присутствовало расширение «certificate_authorities» в сообщении CertificateRequest, по крайней мере один из сертификатов в цепочке сертификатов ДОЛЖЕН быть выпущен одним из перечисленных ЦС.
  • Сертификаты ДОЛЖНЫ быть подписаны с использованием приемлемого алгоритма подписи, как описано в разделе 4.3.2. Обратите внимание, что это ослабляет ограничения на алгоритмы подписи сертификата, найденные в предыдущих версиях TLS.
  • Если в сообщении CertificateRequest содержалось непустое расширение «oid_filters», сертификат конечного объекта ДОЛЖЕН соответствовать идентификаторам расширения, которые распознаются клиентом, как описано в разделе 4.2.5.
4.4.2.4. Получение сообщения сертификата

В целом, подробные процедуры проверки сертификатов выходят за рамки TLS (см. [RFC5280]). В этом разделе приведены требования к TLS.

Если сервер отправляет пустое сообщение сертификата, клиент ДОЛЖЕН отменить рукопожатие с предупреждением «decode_error».

Если клиент не отправляет какие-либо сертификаты (т. Е. Отправляет пустое сообщение сертификата), сервер МОЖЕТ по своему усмотрению либо продолжить рукопожатие без аутентификации клиента, либо прервать рукопожатие с предупреждением «certificate_required». Кроме того, если какой-либо аспект цепочки сертификатов был неприемлемым (например, он не был подписан известным, доверенным ЦС), сервер МОЖЕТ по своему усмотрению либо продолжать рукопожатие (учитывая, что клиент не прошел проверку подлинности), либо прервал рукопожатие.

Любая конечная точка, получающая какой-либо сертификат, который потребуется для проверки с использованием любого алгоритма подписи с использованием MD5-хэша, ДОЛЖНА отменить рукопожатие с предупреждением «bad_certificate». SHA-1 устарел, и РЕКОМЕНДОВАНО, что любая конечная точка, получающая какой-либо сертификат, который ему понадобится для проверки с использованием любого алгоритма подписи с использованием хэша SHA-1, отменяет рукопожатие с предупреждением «bad_certificate». Для ясности это означает, что конечные точки могут принимать эти алгоритмы для сертификатов, которые являются самозаверяющими или являются якорями доверия.

Все конечные точки РЕКОМЕНДУЕТСЯ перейти на SHA-256 или лучше как можно скорее, чтобы поддерживать совместимость с реализациями, которые в настоящее время находятся в процессе поэтапного отказа от поддержки SHA-1.

Обратите внимание, что сертификат, содержащий ключ для одного алгоритма подписи, МОЖЕТ быть подписан с использованием другого алгоритма подписи (например, ключ RSA, подписанный ключом ECDSA).

4.4.3. Проверка сертификата

Это сообщение используется для предоставления явного доказательства того, что конечная точка имеет закрытый ключ, соответствующий его сертификату. Сообщение CertificateVerify также обеспечивает целостность для рукопожатия до этого момента. Серверы ДОЛЖНЫ отправить это сообщение при аутентификации через сертификат. Клиенты ДОЛЖНЫ отправлять это сообщение при аутентификации через сертификат (т. Е. Когда сообщение сертификата не пусто). При отправке это сообщение ДОЛЖНО появляться сразу после сообщения «Сертификат» и непосредственно перед сообщением «Готово».

Структура этого сообщения:

struct {
SignatureScheme algorithm;
opaque signature<0..2^16-1>;
} CertificateVerify;

Поле алгоритма указывает используемый алгоритм подписи (см. Раздел 4.2.3 для определения этого типа). Подпись представляет собой цифровую подпись с использованием этого алгоритма. Содержимое, которое подпадает под подпись, является хеш-выходом, как описано в разделе 4.4.1, а именно:

Transcript-Hash(Handshake Context, Certificate)

Затем цифровая подпись вычисляется по конкатенации:

  • Строка, состоящая из октета 32 (0x20), повторяющаяся 64 раза
  • Строка контекста
  • Один 0 байт, который служит в качестве разделителя
  • Подписываемый контент

Эта структура предназначена для предотвращения атаки на предыдущие версии TLS, в которых формат ServerKeyExchange означает, что злоумышленники могли получить подпись сообщения с выбранным 32-байтовым префиксом (ClientHello.random). Исходный 64-байтовый блок очищает этот префикс вместе с серверным сервером ServerHello.random.

Строка контекста для сигнатуры сервера — «TLS 1.3, server CertificateVerify». Строка контекста для клиентской подписи — «TLS 1.3, client CertificateVerify». Он используется для обеспечения разделения между сигнатурами, выполненными в разных контекстах, что помогает избежать возможных межконтрактных атак.

Например, если хэширование транскрипта составляло 32 байта 01 (эта длина имела бы смысл для SHA-256), то контент, закрываемый цифровой подписью для сервера CertificateVerify, будет следующее:

2020202020202020202020202020202020202020202020202020202020202020
2020202020202020202020202020202020202020202020202020202020202020
544c5320312e332c207365727665722043657274696669636174655665726966
79
00
0101010101010101010101010101010101010101010101010101010101010101

На стороне отправителя процесс вычисления поля подписи сообщения CertificateVerify берется как вход:

  • Содержание, охватываемое цифровой подписью
  • Закрытый ключ подписи, соответствующий сертификату, отправленному в предыдущем сообщении

Если сообщение CertificateVerify отправляется сервером, алгоритм подписи ДОЛЖЕН быть тем, который предлагается в расширении «signature_algorithms» клиента, если только целая цепочка сертификатов не может быть создана без неподдерживаемых алгоритмов (см. Раздел 4.2.3).
Если отправлено клиентом, алгоритм подписи, используемый в сигнатуре, ДОЛЖЕН быть одним из присутствующих в поле supported_signature_algorithms расширения «signature_algorithms» в сообщении CertificateRequest.

Кроме того, алгоритм подписи ДОЛЖЕН быть совместимым с ключом в сертификате конечного объекта отправителя. Подписи RSA ДОЛЖНЫ использовать алгоритм RSASSA-PSS, независимо от того, появляются ли алгоритмы RSASSA-PKCS1-v1_5 в «сигнатурных алгоритмах». Алгоритм SHA-1 НЕ ДОЛЖЕН использоваться в любых подписях сообщений CertificateVerify.

Все алгоритмы подписи SHA-1 в этой спецификации определены исключительно для использования в устаревших сертификатах и недействительны для подписей CertificateVerify.

Получатель сообщения CertificateVerify ДОЛЖЕН проверить поле подписи. Процесс проверки принимает в качестве входных данных:

  • Содержание, охватываемое цифровой подписью
  • Открытый ключ, содержащийся в сертификате конечного объекта, найденном в соответствующем сообщении сертификата
  • Цифровая подпись, полученная в поле подписи сообщения CertificateVerify

Если проверка не удалась, приемник ДОЛЖЕН прекратить квитирование с предупреждением «decrypt_error».

4.4.4. Закончено

Сообщение Закончено является окончательным сообщением в блоке проверки подлинности. Это важно для обеспечения аутентификации рукопожатия и вычисленных ключей.

Получатели завершенных сообщений ДОЛЖНЫ проверять правильность содержимого и, если это неверно, ДОЛЖНЫ прекратить соединение с предупреждением «decrypt_error».

После того как сторона отправила свое сообщение Finished и получила и подтвердила сообщение Finished от своего однорангового узла, оно может начать отправлять и получать данные приложения по соединению. Существуют две настройки, в которых разрешено отправлять данные до получения завершенного партнера:

  1. Клиенты, отправляющие данные 0-RTT, как описано в разделе 4.2.10.
  2. Серверы МОГУТ отправить данные после отправки своего первого рейса, но поскольку рукопожатие еще не завершено, у них нет уверенности ни в идентичности сверстника, ни в его жизнеспособности (т. Е. ClientHello, возможно, был воспроизведен).

Ключ, используемый для вычисления завершенного сообщения, вычисляется из базового ключа, определенного в разделе 4.4, с использованием HKDF (см. Раздел 7.1).

В частности:

finished_key =
HKDF-Expand-Label(BaseKey, «finished», «», Hash.length)
Structure of this message:
struct {
opaque verify_data[Hash.length];
} Finished;
The verify_data value is computed as follows:
verify_data =
HMAC(finished_key,
Transcript-Hash(Handshake Context,
Certificate*, CertificateVerify*))
* Only included if present.

В HMAC [RFC2104] используется алгоритм Hash для рукопожатия. Как отмечено выше, вход HMAC обычно может быть реализован с помощью хоста, то есть только хеша рукопожатия в этот момент.

В предыдущих версиях TLS проверка_данных всегда составляла 12 октетов. В TLS 1.3 это размер вывода HMAC для хеша, используемого для рукопожатия.

Примечание. Оповещения и любые другие типы записей, не поддерживающие квитирование, не являются сообщениями об установлении связи и не включаются в вычисления хэша.

Любые записи, следующие за завершенным сообщением, ДОЛЖНЫ быть зашифрованы под соответствующим ключом трафика приложения, как описано в Разделе 7.2. В частности, это включает в себя любые предупреждения, отправленные сервером в ответ на сообщения Client Certificate и CertificateVerify.

4.5. Конец ранних данных

struct {} EndOfEarlyData;

Если сервер отправил расширение «early_data» в EncryptedExtensions, клиент ДОЛЖЕН отправить сообщение EndOfEarlyData после получения завершенного сервера. Если сервер не отправляет расширение «early_data» в EncryptedExtensions, клиент НЕ ДОЛЖЕН отправлять сообщение EndOfEarlyData. Это сообщение указывает, что все сообщения 0-RTT application_data, если таковые имеются, были переданы и что следующие записи защищены ключами подтверждения handshake. Серверы НЕ ДОЛЖНЫ отправлять это сообщение, а клиенты, получающие его, ДОЛЖНЫ завершить соединение с предупреждением «неожиданное_массе». Это сообщение зашифровывается под ключами, полученными из client_early_traffic_secret.

4.6. Сообщения после рукопожатия

TLS также позволяет отправлять другие сообщения после основного рукопожатия. Эти сообщения используют тип содержимого рукопожатия и шифруются под соответствующим ключом трафика приложения.

4.6.1. Сообщение о новом сеансе связи

В любое время после того, как сервер получил сообщение «Готово» клиента, он МОЖЕТ отправить сообщение NewSessionTicket. Это сообщение создает уникальную связь между стоимостью билета и секретным PSK, полученным из секретного ключа возобновления (см. Раздел 7).

Клиент МОЖЕТ использовать этот PSK для будущих рукопожатий, включив стоимость билета в расширение «pre_shared_key» в своем ClientHello (раздел 4.2.11). Серверы МОГУТ отправить несколько билетов на одно соединение либо сразу после друг друга, либо после определенных событий (см. Приложение C.4). Например, сервер может отправить новый билет после аутентификации после установления связи, чтобы инкапсулировать дополнительное состояние проверки подлинности клиента. Несколько билетов полезны для клиентов в самых разных целях, в том числе:

  • Открытие нескольких параллельных HTTP-соединений.
  • Выполнение стыковки между интерфейсами и семействами адресов через (например) Happy Eyeballs [RFC8305] или связанные с ними методы.

Любой билет ДОЛЖЕН быть возобновлен с помощью набора шифров, который имеет тот же алгоритм хеширования KDF, что и для установления исходного соединения.

Клиенты ДОЛЖНЫ только возобновиться, если новое значение SNI является действительным для сертификата сервера, представленного в исходном сеансе, и СЛЕДУЕТ возобновить, только если значение SNI совпадает с значением, используемым в исходном сеансе. Последнее — оптимизация производительности: обычно нет причин ожидать, что разные серверы, на которые распространяется один сертификат, смогут принимать билеты друг друга; следовательно, попытка возобновления в этом случае будет тратить билет на один билет. Если такое указание предоставляется (извне или любым другим способом), клиенты МОГУТ возобновить с другим значением SNI.

При возобновлении, если сообщать о значении SNI вызывающему приложению, реализации ДОЛЖНЫ использовать значение, отправленное при возобновлении ClientHello, а не значение, отправленное в предыдущем сеансе. Обратите внимание, что если реализация сервера отклоняет все идентификаторы PSK с разными значениями SNI, эти два значения всегда одинаковы.

Примечание. Несмотря на то, что главный секрет возобновления зависит от второго рейса клиента, сервер, который не запрашивает аутентификацию клиента, МОЖЕТ вычислить остаток транскрипта самостоятельно, а затем отправить NewSessionTicket сразу же после отправки Finished, а не ждать завершения клиента. Это может быть уместно в тех случаях, когда клиент, как ожидается, будет открывать несколько подключений TLS параллельно, и, например, выиграет от сокращения накладных расходов при возобновлении рукопожатия.

struct {
uint32 ticket_lifetime;
uint32 ticket_age_add;
opaque ticket_nonce<0..255>;
opaque ticket<1..2^16-1>;
Extension extensions<0..2^16-2>;
} NewSessionTicket;

  • ticket_lifetime: Указывает время жизни в секундах как 32-разрядное целое число без знака в сетевом порядке байта с момента выдачи билета. Серверы НЕ ДОЛЖНЫ использовать любое значение, превышающее 604800 секунд (7 дней). Значение нуля указывает, что билет должен быть немедленно отброшен. Клиенты НЕ ДОЛЖНЫ кэшировать билеты дольше 7 дней, независимо от срока действия ticket_lifetime, и МОЖЕТЕ удалять билеты раньше, основываясь на местной политике. Сервер МОЖЕТ рассматривать билет как действительный в течение более короткого периода времени, чем тот, который указан в ticket_lifetime.
  • ticket_age_add: безопасное генерируемое случайное 32-битное значение, которое используется для сглаживания возраста билета, который клиент включает в расширение «pre_shared_key». Возраст билета клиентской стороны добавляется к этому значению по модулю 2 ^ 32 для получения значения, которое передается клиентом. Сервер ДОЛЖЕН создать новое значение для каждого отправленного им билета.
  • ticket_nonce: ценность за билет, которая является уникальной для всех билетов, выпущенных по этому соединению.
  • ticket: значение билета, которое будет использоваться в качестве идентификатора PSK. Сам билет — непрозрачный ярлык. Это МОЖЕТ быть либо ключ поиска базы данных, либо самозашиваемое и самоидентифицируемое значение.
  • extensions: набор значений расширения для билета. Формат «Расширение» определен в разделе 4.2. Клиенты ДОЛЖНЫ игнорировать непризнанные расширения.

Единственным расширением, которое в настоящее время определено для NewSessionTicket, является «early_data», указывая, что билет может использоваться для отправки данных с 0-RTT (раздел 4.2.10). Он содержит следующее значение:

  • max_early_data_size: Максимальный объем данных 0-RTT, которые клиент может отправлять при использовании этого билета, в байтах. Рассчитывается только полезная нагрузка прикладных данных (т. Е. Открытый текст, но не заполнение или внутренний байт типа содержимого). Сервер, получающий больше байтов max_early_data_size данных 0-RTT, ДОЛЖЕН прекратить соединение с предупреждением «неожиданный_механизм». Обратите внимание, что серверы, которые отбрасывают ранние данные из-за отсутствия криптографического материала, не смогут отличить отступы от контента, поэтому клиенты НЕ ДОЛЖНЫ зависеть от возможности отправки больших количеств заполнения в ранние записи данных.

PSK, связанный с билетом, вычисляется как:

HKDF-Expand-Label(resumption_master_secret, «resumption», ticket_nonce, Hash.length)

Поскольку значение ticket_nonce отличается для каждого сообщения NewSessionTicket, для каждого билета будет получен другой PSK.

Обратите внимание, что в принципе можно продолжить выпуск новых билетов, которые на неопределенный срок продлевают срок службы материала для ключей, первоначально полученного из первоначального рукопожатия без PSK (который, скорее всего, был привязан к сертификату сверстника). РЕКОМЕНДОВАНО, что в реализациях устанавливаются ограничения на общий срок службы такого ключевого материала; эти лимиты должны учитывать срок действия сертификата партнера, вероятность промежуточного отзыва и время, прошедшее с момента подписания подписей подпишимого сертификата.

4.6.2. Аутентификация после авторизации

Когда клиент отправил расширение «post_handshake_auth» (см. Раздел 4.2.6), сервер МОЖЕТ запросить аутентификацию клиента в любое время после того, как рукопожатие завершилось, отправив сообщение CertificateRequest. Клиент ДОЛЖЕН отвечать соответствующими сообщениями об аутентификации (см. Раздел 4.4). Если клиент хочет выполнить аутентификацию, он ДОЛЖЕН отправить сертификат, CertificateVerify и Finished. Если он отклоняется, он ДОЛЖЕН отправить сообщение сертификата, не содержащее сертификатов, за которым следует Готово. Все сообщения клиента для данного ответа ДОЛЖНЫ появляться последовательно на проводе без промежуточных сообщений других типов.

Клиент, который получает сообщение CertificateRequest, не отправив расширение «post_handshake_auth», ДОЛЖЕН отправить фатальное предупреждение «неожиданное_message».

Примечание. Поскольку аутентификация клиента может потребовать запроса пользователя, серверы ДОЛЖНЫ быть подготовлены к некоторой задержке, включая получение произвольного количества других сообщений между отправкой CertificateRequest и получением ответа. Кроме того, клиенты, которые получают несколько сертификационных запросов в тесной последовательности, могут ответить на них в другом порядке, чем они были получены (значение certificate_request_context позволяет серверу устранять неоднозначность ответов).

4.6.3. Обновление вектора ключей и инициализации

Сообщение подтверждения KeyUpdate используется для указания того, что отправитель обновляет свои отправляющие криптографические ключи. Это сообщение может быть отправлено либо одноранговым узлом после отправки сообщения «Готово». Реализации, которые получают сообщение KeyUpdate до получения завершенного сообщения, ДОЛЖНЫ завершить соединение с предупреждением «неожиданное_месяца». После отправки сообщения KeyUpdate отправитель отправляет весь свой трафик с использованием следующего поколения ключей, рассчитанных, как описано в разделе 7.2. После получения KeyUpdate приемник ДОЛЖЕН обновлять свои принимающие ключи.

enum {
update_not_requested(0), update_requested(1), (255)
} KeyUpdateRequest;
struct {
KeyUpdateRequest request_update;
} KeyUpdate;

  • request_update: Указывает, должен ли получатель KeyUpdate отвечать собственным KeyUpdate. Если реализация получает любое другое значение, она ДОЛЖНА завершить соединение с предупреждением «незаконный_параметр».

Если для поля request_update установлено значение «update_requested», то ресивер ДОЛЖЕН отправить собственный ключевой файл с параметром request_update, установленным на «update_not_requested», перед отправкой следующей записи данных приложения. Этот механизм позволяет обеим сторонам принудительно обновлять все соединение, но вызывает реализацию, которая получает несколько ключевых слов, пока она не дает ответа на одно обновление. Обратите внимание, что реализации могут получать произвольное количество сообщений между отправкой KeyUpdate с параметром request_update, установленным на «update_requested», и получением ключевого ключа, поскольку эти сообщения могут уже находиться в полете. Однако, поскольку ключи отправки и получения производятся из независимых секретов трафика, сохранение секретности трафика приема не угрожает прямой секретности данных, отправленных до того, как отправитель изменил ключи.

Если реализации самостоятельно отправляют свои собственные KeyUpdates с параметром request_update, установленным на «update_requested», и они пересекаются в полете, тогда каждая сторона также отправит ответ, в результате каждая сторона будет увеличиваться на два поколения.

И отправитель, и получатель ДОЛЖНЫ шифровать свои сообщения KeyUpdate старыми ключами. Кроме того, обе стороны ДОЛЖНЫ обеспечить, чтобы KeyUpdate со старым ключом принимался до принятия любых сообщений, зашифрованных новым ключом. Несоблюдение этого требования может привести к усечению сообщений.

5. Протокол записи

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

Набраны записи TLS, которые позволяют мультиплексировать несколько протоколов более высокого уровня на один и тот же уровень записи. В этом документе указаны четыре типа содержимого: рукопожатие, application_data, alert и change_cipher_spec. Запись change_cipher_spec используется только для целей совместимости (см. Приложение D.4).

Реализация может получить незашифрованную запись типа change_cipher_spec, состоящую из однобайтового значения 0x01 в любое время после того, как первое сообщение ClientHello было отправлено или получено, и до того, как получено сообщение завершенного партнера, и ДОЛЖНО просто отказаться от него без дальнейшей обработки. Обратите внимание, что эта запись может отображаться в точке рукопожатия, где реализация ожидает защищенные записи, и поэтому необходимо обнаружить это условие до попытки снятия защиты с записи. Реализация, которая получает любое другое значение change_cipher_spec или которая получает защищенную запись change_cipher_spec, ДОЛЖНА прервать рукопожатие с предупреждением «неожиданное_месяца». Если реализация обнаруживает запись change_cipher_spec, полученную до первого сообщения ClientHello или после сообщения завершенного партнера, оно ДОЛЖНО рассматриваться как тип неожиданной записи (хотя серверы без состояния не могут отличить эти случаи от разрешенных случаев).

Реализации НЕ ДОЛЖНЫ отправлять типы записей, не определенные в этом документе, если не согласованы каким-либо расширением. Если реализация TLS получает непредвиденный тип записи, она ДОЛЖНА прекратить соединение с предупреждением «неожиданное_помощь». Значения типа нового значения записи назначаются IANA в реестре TLS ContentType, как описано в Разделе 11.

5.1. Рекордный уровень

Уровень записи фрагментирует информационные блоки в записи TLSPlaintext, несущие данные в кусках 2 ^ 14 байтов или меньше. Границы сообщений обрабатываются по-разному в зависимости от базового ContentType. Любые будущие типы содержимого ДОЛЖНЫ указывать соответствующие правила. Обратите внимание, что эти правила более строгие, чем в TLS 1.2.

Сообщения подтверждения могут быть объединены в одну запись TLSPlaintext или фрагментированы по нескольким записям при условии, что:

  • Сообщения подтверждения не должны чередоваться с другими типами записей. То есть, если сообщение для рукопожатия разделено на две или более записей, НЕ ДОЛЖНО быть никаких других записей между ними.
  • Сообщения подтверждения не должны включать изменения ключа. Реализации ДОЛЖНЫ проверять, чтобы все сообщения, непосредственно предшествующие изменению ключа, соответствовали границе записи; если нет, то они ДОЛЖНЫ прекратить соединение с предупреждением «неожиданное_помощь». Поскольку сообщения ClientHello, EndOfEarlyData, ServerHello, Finished и KeyUpdate могут непосредственно предшествовать изменению ключа, реализации должны ДОЛЖНЫ отправить эти сообщения в соответствие с границей записи.

Реализации НЕ ДОЛЖНЫ отправлять фрагменты нулевой длины типов Handshake, даже если эти фрагменты содержат отступы.

Предупреждающие сообщения (раздел 6) НЕ ДОЛЖНЫ быть фрагментированы в разных записях, а несколько предупреждающих сообщений НЕ ДОЛЖНЫ объединяться в одну запись TLSPlaintext. Другими словами, запись с типом предупреждения должна содержать только одно сообщение.

Сообщения данных приложения содержат данные, непрозрачные для TLS. Сообщения данных приложения всегда защищены. Фрагменты нулевой длины данных приложения могут быть отправлены, поскольку они потенциально полезны в качестве контрмера анализа трафика. Фрагменты данных приложения МОГУТ быть разделены на несколько записей или объединены в одну запись.

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

struct {
ContentType type;
ProtocolVersion legacy_record_version;
uint16 length;
opaque fragment[TLSPlaintext.length];
} TLSPlaintext;

  • type: протокол более высокого уровня, используемый для обработки закрытого фрагмента.
  • legacy_record_version: ДОЛЖНО быть установлено в 0x0303 для всех записей, сгенерированных реализацией TLS 1.3, отличной от первоначальной ClientHello (то есть, не созданной после HelloRetryRequest), где она МОЖЕТ быть также 0x0301 для целей совместимости. Это поле устарело и ДОЛЖНО быть проигнорировано для всех целей. Предыдущие версии TLS будут использовать другие значения в этой области при некоторых обстоятельствах.
  • length: длина (в байтах) следующего TLSPlaintext.fragment. Длина НЕ ДОЛЖНА превышать 2 ^ 14 байт. Конечная точка, которая получает запись, которая превышает эту длину, ДОЛЖНА завершить соединение с предупреждением «record_overflow».
  • fragment: передаваемые данные. Это значение является прозрачным и рассматривается как независимый блок, который должен обрабатываться протоколом высшего уровня, заданным полем типа.

В этом документе описывается TLS 1.3, который использует версию 0x0304. Значение этой версии является историческим, исходя из использования 0x0301 для TLS 1.0 и 0x0300 для SSL 3.0. Чтобы максимизировать обратную совместимость, запись, содержащая исходный ClientHello SHOULD, имеет версию 0x0301 (отражающую TLS 1.0), а запись, содержащая второй ClientHello или ServerHello, ДОЛЖНА иметь версию 0x0303 (отражающую TLS 1.2). При обсуждении предыдущих версий TLS конечные точки следуют процедуре и требованиям, приведенным в Приложении D.

5.2. Резервная защита полезной нагрузки

Функции защиты записи преобразуют структуру TLSPlaintext в структуру TLSCiphertext. Функции снятия защиты реверсируют процесс. В TLS 1.3, в отличие от предыдущих версий TLS, все шифры моделируются как «Authenticated Encryption with Associated Data» (AEAD) [RFC5116]. Функции AEAD обеспечивают единую операцию шифрования и аутентификации, которая превращает открытый текст в аутентифицированный зашифрованный текст и обратно. Каждая зашифрованная запись состоит из заголовка открытого текста, за которым следует зашифрованное тело, которое содержит тип и необязательное дополнение.

struct {
opaque content[TLSPlaintext.length];
ContentType type;
uint8 zeros[length_of_padding];
} TLSInnerPlaintext;

struct {
ContentType opaque_type = application_data; /* 23 */
ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
uint16 length;
opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;

  • content: значение TLSPlaintext.fragment, содержащее байтовую кодировку рукопожатия или предупреждающее сообщение или необработанные байты данных приложения для отправки.
  • type: Значение TLSPlaintext.type, содержащее тип содержимого записи.
  • zeros: произвольная длина нулевых байтов может появляться в открытом тексте после поля типа. Это дает возможность отправителям помещать любую запись TLS на выбранную сумму, пока общее количество останется в пределах размера записи. См. Раздел 5.4 для более подробной информации.
  • opaque_type: внешнее поле opaque_type в записи TLSCiphertext всегда устанавливается в значение 23 (application_data) для внешней совместимости со средними ячейками, привыкшими к синтаксическому анализу предыдущих версий TLS. Фактический тип содержимого записи находится в TLSInnerPlaintext.type после дешифрования.
  • legacy_record_version: Поле legacy_record_version всегда равно 0x0303. TLS 1.3 TLSCiphertexts не генерируются до тех пор, пока TLS 1.3 не будет согласован, поэтому нет проблем с исторической совместимостью, когда могут быть получены другие значения. Обратите внимание, что протокол установления связи, включая сообщения ClientHello и ServerHello, проверяет подлинность версии протокола, поэтому это значение является избыточным.
  • length: длина (в байтах) следующего TLSCiphertext.encrypted_record, которая представляет собой сумму длин содержимого и дополнения, плюс один для внутреннего типа контента, плюс любое расширение, добавленное алгоритмом AEAD. Длина НЕ ДОЛЖНА превышать 2 ^ 14 + 256 байт. Конечная точка, которая получает запись, которая превышает эту длину, ДОЛЖНА завершить соединение с предупреждением «record_overflow».
  • encrypted_record: зашифрованная форма AEAD сериализованной структуры TLSInnerPlaintext.

Алгоритмы AEAD принимают в качестве входных данных один ключ, nonce, открытый текст и «дополнительные данные», которые должны быть включены в проверку аутентификации, как описано в разделе 2.1 [RFC5116]. Ключом является либо client_write_key, либо server_write_key, а nonce — из порядкового номера и client_write_iv или server_write_iv (см. Раздел 5.3), а дополнительный ввод данных — это заголовок записи.

additional_data = TLSCiphertext.opaque_type ||
TLSCiphertext.legacy_record_version ||
TLSCiphertext.length

Ввод открытого текста в алгоритм AEAD представляет собой кодированную структуру TLSInnerPlaintext. Вывод ключей трафика определяется в разделе 7.3.

Выход AEAD состоит из вывода шифротекста из операции шифрования AEAD. Длина открытого текста больше соответствующей TLSPlaintext.length из-за включения TLSInnerPlaintext.type и любого дополнения, предоставленного отправителем. Длина вывода AEAD обычно будет больше, чем открытый текст, но на величину, которая зависит от алгоритма AEAD.

Так как шифры могут включать прописку, количество накладных расходов может варьироваться в зависимости от длины текста. Символично,

AEADEncrypted =AEAD-Encrypt(write_key, nonce, additional_data, plaintext)

Поле encrypted_record для TLSCiphertext установлено в AEADEncrypted.

Чтобы расшифровать и проверить, шифр принимает в качестве входных данных ключ, nonce, дополнительные данные и значение AEADEncrypted. Результатом является либо открытый текст, либо ошибка, указывающая на невозможность дешифрования. Нет отдельной проверки целостности. Символично,

plaintext of encrypted_record =
AEAD-Decrypt(peer_write_key, nonce,
additional_data, AEADEncrypted)

Если дешифрование не удается, приемник ДОЛЖЕН прекратить соединение с предупреждением «bad_record_mac».

Алгоритм AEAD, используемый в TLS 1.3, НЕ ДОЛЖЕН производить расширение, превышающее 255 октетов. Конечная точка, получающая запись от своего однорангового узла с TLSCiphertext.length, превышающим 2 ^ 14 + 256 октетов, ДОЛЖНА завершить соединение с предупреждением «record_overflow». Этот предел получен из максимальной длины TLSInnerPlaintext длиной 2 ^ 14 октетов + 1 октет для ContentType + максимального расширения AEAD 255 октетов.

5.3. Per-Record Nonce

64-разрядный порядковый номер поддерживается отдельно для чтения и записи записей. Соответствующий порядковый номер увеличивается на один после чтения или записи каждой записи. Каждый номер последовательности устанавливается в ноль в начале соединения и всякий раз, когда изменяется ключ; первая запись, передаваемая под определенным ключом трафика, ДОЛЖНА использовать порядковый номер 0.

Поскольку размер порядковых номеров составляет 64 бит, их не следует обертывать. Если для реализации TLS потребуется обернуть порядковый номер, он ДОЛЖЕН либо выполнить ключ (раздел 4.6.3), либо прекратить соединение.

Каждый алгоритм AEAD задает диапазон возможных длин для каждой записи без записи: от N_MIN до байтов N_MAX ввода [RFC5116]. Длина TLS per-record nonce (iv_length) установлена на большее значение из 8 байтов и N_MIN для алгоритма AEAD (см. [RFC5116], раздел 4). Алгоритм AEAD, где N_MAX меньше 8 байтов, НЕ ДОЛЖЕН использоваться с TLS. Персонализация для конструкции AEAD формируется следующим образом:

  • 64-разрядный порядковый номер записи кодируется в сетевом порядке байтов и дополняется слева нулями до iv_length.
  • Пронумерованный порядковый номер имеет XORed либо с static client_write_iv, либо с server_write_iv (в зависимости от роли).

Результирующее количество (длины iv_length) используется как non-record.

Примечание. Это отличается от конструкции в TLS 1.2, в которой указано частично явное исключение.

5.4. Заполнение записи

Все зашифрованные записи TLS могут быть дополнены, чтобы раздуть размер TLSCiphertext. Это позволяет отправителю скрыть размер трафика от наблюдателя.

При создании записи TLSCiphertext реализации МОГУТ выбрать пэд. Незакрепленная запись (unpadded record) — это всего лишь запись с длиной заполнения, равной нулю. Заполнение (Padding) — это строка нулевых байтов, добавленных в поле ContentType перед шифрованием. Реализации ДОЛЖНЫ установить октеты заполнения для всех нулей перед шифрованием.

Записи данных приложения могут содержать TLSInnerPlaintext.content с нулевой длиной, если желает отправитель. Это позволяет генерировать правдоподобное покрытие покрытия в контекстах, где присутствие или отсутствие активности может быть чувствительным. Реализации НЕ ДОЛЖНЫ отправлять записи Handshake и Alert с нулевым TLSInnerPlaintext.content; если такое сообщение получено, принимающая реализация ДОЛЖНА прекратить соединение с предупреждением «неожиданный_месяц».

Отправленное заполнение автоматически проверяется механизмом защиты записи; при успешном расшифровке TLSCiphertext.encrypted_record принимающая реализация сканирует поле с конца на начало, пока не найдет ненулевой октет. Этот ненулевой октет является типом содержимого сообщения. Эта схема дополнений была выбрана, поскольку она позволяет заполнять любую зашифрованную запись TLS произвольным размером (от нуля до TLS), не вводя новые типы контента. Конструкция также обеспечивает использование всех нулевых октетов заполнения, что позволяет быстро обнаруживать ошибки заполнения.

Реализации ДОЛЖНЫ ограничивать их сканирование до открытого текста, полученного из расшифровки AEAD. Если принимающая реализация не находит ненулевой октет в открытом тексте, он ДОЛЖЕН прекратить соединение с предупреждением «неожиданное_месяц».

Наличие отступов не изменяет общие ограничения размера записи: полный закодированный TLSInnerPlaintext НЕ ДОЛЖЕН превышать 2 ^ 14 + 1 октет. Если максимальная длина фрагмента уменьшается — как, например, с помощью расширения record_size_limit из [RFC8449] — тогда приведенный предел применяется к полному открытому тексту, включая тип контента и дополнение.

Выбор политики дополнений, которая подсказывает, когда и сколько пэдов является сложной темой и выходит за рамки этой спецификации. Если протокол прикладного уровня поверх TLS имеет собственное дополнение, может быть предпочтительнее записывать записи TLS приложения Data Application на уровне приложения. Однако заполнение зашифрованных записей Handshake или Alert должно выполняться на уровне TLS. Более поздние документы могут определять алгоритмы выбора отступов или определять механизм запроса политики дополнений через расширения TLS или некоторые другие средства.

5.5. Пределы использования ключа

Существуют криптографические ограничения на количество открытого текста, который можно безопасно зашифровать под заданным набором ключей. [AEAD-LIMITS] дает анализ этих ограничений в предположении, что базовый примитив (AES или ChaCha20) не имеет недостатков. Реализации ДОЛЖНЫ выполнять ключевое обновление, как описано в разделе 4.6.3, до достижения этих ограничений.

Для AES-GCM до 2 ^ 24,5 полноразмерных записей (около 24 миллионов) могут быть зашифрованы по данному соединению, сохраняя при этом безопасный запас около 2 ^ -57 для безопасности аутентифицированного шифрования (AE). Для ChaCha20 / Poly1305 порядковый номер записи будет завершен до достижения предела безопасности.

6. Протокол оповещений

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

Сообщения оповещения передают описание предупреждения и устаревшего поля, которые передавали уровень серьезности сообщения в предыдущих версиях TLS. Оповещения делятся на два класса: предупреждения о закрытии и предупреждения об ошибках. В TLS 1.3 серьезность подразумевается в типе отправляемого оповещения, и поле «уровень» можно смело игнорировать. Предупреждение «close_notify» используется для указания упорядоченного закрытия одного направления соединения. После получения такого предупреждения, TLS-реализация ДОЛЖНА указывать конечные данные для приложения.

Предупреждения об ошибках указывают на неправильное закрытие соединения (см. Раздел 6.2). После получения предупреждения об ошибке, реализация TLS ДОЛЖНА указывать на ошибку для приложения и НЕ ДОЛЖНА разрешать отправку или получение каких-либо дополнительных данных в соединении. Серверы и клиенты ДОЛЖНЫ забыть секретные значения и ключи, установленные в неудачных соединениях, за исключением PSK, связанных с сеансовыми билетами, которые ДОЛЖНЫ быть отброшены, если это возможно.

Все предупреждения, перечисленные в разделе 6.2, ДОЛЖНЫ быть отправлены с AlertLevel = fatal и ДОЛЖНЫ быть обработаны как предупреждения об ошибках, когда они получены независимо от AlertLevel в сообщении. Неизвестные типы предупреждений ДОЛЖНЫ рассматриваться как оповещения об ошибках.

Примечание: TLS определяет два общих предупреждения (см. Раздел 6) для использования при сбое в анализе сообщения. Одноранговые узлы, которые получают сообщение, которое не может быть проанализировано в соответствии с синтаксисом (например, имеют длину, выходящую за границы сообщения или содержащую внеполосную длину), ДОЛЖНЫ завершить соединение с предупреждением «decode_error». Одноранговые узлы, которые получают синтаксически корректное, но семантически недействительное сообщение (например, доля DHE в p-1 или недопустимое перечисление), ДОЛЖНЫ завершить соединение с предупреждением «незаконный_параметр».

enum { warning(1), fatal(2), (255) } AlertLevel;
enum {
close_notify(0),
unexpected_message(10),
bad_record_mac(20),
record_overflow(22),
handshake_failure(40),
bad_certificate(42),
unsupported_certificate(43),
certificate_revoked(44),
certificate_expired(45),
certificate_un