Alert протокол
Одним из протоколов, лежащих выше протокола Записи, является протокол Аlert. Содержимым протокола является либо фатальное, либо предупреждающее сообщение. Фатальное сообщение должно приводить к немедленному разрыву данного соединения. В этом случае другие соединения, соответствующие данной сессии, могут быть продолжены, но идентификатор сессии должен быть сделан недействительным для предотвращения использования данной сессии для установления новых соединений. Подобно другим сообщениям, сообщения Alert зашифрованы и сжаты, как определено в текущем состоянии соединения.
Alerts ошибок
В расширении протокола определены новые Alerts ошибок, использующиеся вместе с данными расширениями TLS.
Во избежание нарушения работы существующих клиентов и серверов эти Alerts не должны посылаться до тех пор, пока отправляющий их участник не получит расширенное сообщение Hello от другого участника.
unsupported_extension – данный Alert посылается клиентом, который получил расширенный Server Hello, содержащий расширение, которое он не указывал в соответствующем Client Hello. Данное сообщение всегда фатально.unrecognized_name – данный Alert посылается сервером, который получил запрос с расширением server_name, но не распознал имя сервера. Данное сообщение может быть фатальным.certificate_unobtainable – данный Alert посылается сервером, который не может получить цепочку сертификатов из URL, предоставленного клиентом. Данное сообщение может быть фатальным – например, если серверу требуется аутентификация клиента для продолжения Рукопожатия и сервер не может восстановить цепочку сертификатов, он может послать фатальный Alert.bad_certificate_status_response – данный Alert посылается клиентом, который получил ответ с недействительным статусом сертификата. Данное сообщение всегда фатально.bad_certificate_hash_value – данный Alert посылается сервером, если хэш сертификата не соответствует предоставленному клиентом certificate_hash. Данное сообщение всегда фатально.
Ошибки обрабатываются в протоколе Рукопожатия следующим образом. Когда один из участников соединения обнаруживает ошибку, он посылает соответствующее сообщение другому участнику. При передаче или получении сообщения фатального Alert оба участника немедленно закрывают соединение. Сервер и клиент должны сбросить все идентификаторы сессии, ключи и секреты, связанные с этим соединением.
Для всех ошибок, у которых уровень Alert явно не задан, посылающая сторона сама может определять, является ошибка фатальной или нет. Если получен Alert с уровнем предупреждения, получающая сторона может решать, интерпретировать ли сообщение как фатальное.
Unexpected_message | Получено неожидаемое сообщение. Этот Alert всегда фатальный и никогда не должен возникать во взаимодействии корректных реализаций |
Bad_record_mac | Данный Alert возвращается, если полученная запись имеет некорректный МАС. Данное сообщение всегда фатально |
Decryption_failed | TLSCiphertext дешифрован недопустимым способом: некратная длина блока или недопустимые добавленные значения. Данное сообщение всегда фатально |
Record_overflow | Полученная TLSCiphertext запись имеет длину больше 214 + 2048 байт, или дешифрованная TLSCompressed запись имеет длину больше 214 + 1024 байт. Данное сообщение всегда фатально |
Decompression_failure | Функция декомпрессии получила неправильные входные данные. Данное сообщение всегда фатально |
Handshake_failure | Получение сообщения handshake_failure Alert говорит о том, что отправитель не смог договориться о приемлемом наборе параметров безопасности. Данное сообщение всегда фатально |
Bad_certificate | Сертификат испорчен, например содержит некорректную подпись |
Unsupported_certificate | Сертификат неподдерживаемого типа |
Certificate_revoked | Сертификат отменен тем, кто его подписал |
Certificate_expird | Срок действия сертификата истек и в настоящее время он недействителен |
Certificate_unknown | Другой результат (неопределенный), полученный в результате обработки сертификата, сертификат не принимается |
Illegal_parameter | Некоторое поле находится вне диапазона или не согласуется с другими полями. Данное сообщение всегда фатально |
Unknown_ca | Получена цепочка законных сертификатов или некоторая часть цепочки, но сертификат не принимается, потому что сертификат СА не соответствует известному СА, с которым установлены доверительные отношения. Данное сообщение всегда фатально |
Access_denied | Получен законный сертификат, но при применении контроля доступа отправитель решил не продолжать переговоры. Данное сообщение всегда фатально |
Decode_error | Сообщение не может быть декодировано, потому что некоторое поле находится вне специфицированного диапазона или некорректна длина сообщения. Данное сообщение всегда фатально |
Decrypt_error | Не выполнена криптогафическая операция Рукопожатия, которая включает проверку подписи, дешифрование обмена ключа и проверку правильности завершающего сообщения |
Export_restriction | Переговоры не выполнены из-за экспортных ограничений; например, попытка передать 1024-битный ключ RSA для метода Рукопожатия RSA_EXPORT. Данное сообщение всегда фатально |
Protocol_version | Версия протокола, с которой клиент пытается вести переговоры, распознана, но не поддерживается. Например, старая версия протокола не должна использоваться по причинам безопасности. Данное сообщение всегда фатально |
Insufficient_security | Возвращается вместо handshake_failure, когда переговоры прекращаются из-за того, что сервер требует более безопасных алгоритмов, чем предложены клиентом. Данное сообщение всегда фатально |
Internal_error | Внутренняя ошибка, не относящаяся к участникам, но делающая невозможным дальнейшее ведение переговоров (например, невозможность распределения памяти). Данное сообщение всегда фатально |
User_canceled | Данное Рукопожатие прервано по некоторой причине, не относящейся к падению протокола. Если пользователь прервал операцию после завершения Рукопожатия, то для закрытия соединения больше подходит сообщение close_notify. Данное сообщение обычно является предупреждающим |
No_renegotiation | Посылается клиентом в ответ на запрос Hello или сервером в ответ на Hello клиента после начала Рукопожатия. Это приводит к невозможности вести новые переговоры; в этой точке тот, кто осуществил первоначальный запрос, может решить продолжать ли использовать данное соеди нение. Одним из случаев, который может соответствовать данной ситуации, может быть порождение сервером нового процесса для удовлетворения запроса; процесс должен при старте получить параметры безопасности (длину ключа, аутентификацию и т.д.), и возможности внести изменения в параметры после этой точки быть не должно. Данное сообщение всегда является предупреждающим |
Безопасность client_certificate_url
Для данного расширения существует две проблемы.
Первая проблема связана с тем, что необходимо определить, должен ли клиент включать хэши сертификатов при посылке URLs сертификатов.
Если в аутентификации клиента используется *without* в расширении client_certificate_url, цепочка сертификатов клиента охватывается хэшем сообщения Finished. Цель включения хэшей и проверки их при получении цепочки сертификатов состоит в том, чтобы гарантировать, что определенное свойство, указанное в данном расширении, используется, например, что вся информация в цепочке сертификатов, полученная сервером, соответствует той, что посылал клиент.
С другой стороны, у клиента могут быть ежедневно выпускаемые сертификаты, которые хранятся по фиксированному URL, и нет необходимости предоставлять их клиенту. Клиенты, которые решили опускать хэши сертификатов, должны учитывать возможность атак, при которых злоумышленник посылает действительный сертификат ключа клиента, отличный от сертификата, который предоставляет клиент.
Вторая проблема состоит в том, что для client_certificate_url сервер начинает действовать от имени клиента. Таким образом сервер становится источником проблем, связанных с безопасностью, как и клиент для схемы с URL. Кроме того, следует помнить, что клиент может попытаться заставить сервер соединяться с некоторым, возможно несуществующим, URL.
В общем случае это означает, что атакующий может использовать сервер для непрямых атак на другой хост, который уязвим в отношении определенного потока. Также возникает возможность DoS-атак, при которых атакующий создает много соединений с сервером, каждое из которых является результатом попытки сервера соединиться с целью, определенной атакующим.
Заметим, что сервер может быть расположен за firewall или иметь возможность доступа к хостам, которые не имеют прямого выхода в Internet. Это может обострить потенциальные проблемы безопасности и проблемы, связанные с отказом сервиса, при существовании внутренних хостов, от которых требуется получать подтверждение и которые могут быть недоступны.
Таким образом, рекомендуется, чтобы необходимость расширения client_certificate_url указывалась администратором сервера, а не по умолчанию.
URLs, которые указывают порты, отличные от заданных по умолчанию, могут иметь различные проблемы, так же, как и очень длинные URLs (что может быть связано с переполнением буфера).
Кроме того, следует заметить, что в Internet часто используются НТТР кэширующие proxy, и некоторые из них не проверяют самую последнюю версию. Если запрос, использующий НТТР (или другой кэширующий протокол), сконфигурирован неправильно или прерван proxy, proxy сервер может возвратить ответ, не соотетствующий текущему запросу.
Безопасность max_fragment_length
Максимальная длина фрагмента должна учитываться уже сообщениями Рукопожатия. Однако это не приводит к каким-то дополнительным проблемам безопасности, так как существует требование, чтобы реализации имели возможность фрагментировать сообщения Рукопожатия.
Реальная максимальная длина фрагмента зависит от набора алгоритмов шифрования и метода сжатия. Это должно учитываться и при определении размера буферов и проверки буфера на предмет переполнения.
Безопасность server_name
Если единственный сервер обслуживает несколько доменов, то очевидно, что владельцу каждого домена необходимо гарантировать, что все соответствует его требованиям безопасности.
Обязательно нужно гарантировать, что не происходит переполнения буфера, независимо от значения поля длины в server_name.
Хотя в настоящий момент неконкретизировано представление для интернационализации hostnames в расширении server_name, это не связано с проблемами безопасности, сопряженными с использованием интернационализированных hostnames – в частности, "выдуманными" именами, которые неотличимы от другого имени при просмотре или печати. Рекомендуется, чтобы сертификаты сервера не выпускались для интернационализированных hostnames, если существует риск выдуманных имен.
Безопасность status_request
Если клиент запросил ответы OCSP, он должен предполагать, что сервер атакующего, используя скомпрометированный ключ, может притвориться, будто он не поддерживает расширение. Клиент, которому требуется проверка действительности сертификатов с помощью OCSP, должен либо сам контактировать с сервером OCSP, либо прервать Рукопожатие.
Использование расширения запроса nonce OCSP может усилить защиту в отношении атак, при которых осуществляется попытка повторить ответы OCSP.
Безопасность truncated_hmac
Очевидно, что урезанные МАСs в целом являются более слабыми, чем полные МАСs. Тем не менее, на сегодня неизвестны особенно уязвимые места для НМАС как с MD5, так и с SHA-1, урезанных до 80 бит.
Заметим, что длина выхода НМАС не должна быть такой же, как длина ключа симметричного шифрования, так как подделка значений МАС не может быть выполнена off-line: в TLS единственный неверный МАС приводит к немедленному завершению сессии TLS.
Безопасность trusted_ca_keys
В некоторых случаях ключи корневых СА, которые предоставил клиент, могут рассматриваться как конфиденциальная информация. Следовательно, ключ корневого СА в расширении должен применяться с осторожностью.
Использование в качестве альтернативы SHA-1 хэшей сертификатов гарантирует недвусмысленность каждого сертификата.
Фрагментация
Уровень Записи фрагментирует блоки в записи TLSPlaintext, поддерживая цепочки данных длиной не более 214 байт. Границы записей протоколов более высокого уровня не сохраняются на уровне Записи, т.е. несколько сообщений протокола более высокого уровня некоторого ContentType могут быть размещены в одной записи TLSPlaintext или единственное сообщение может быть фрагментировано в несколько записей.
Используемые расширения
Рассмотрим используемые расширения TLS.
Заметим, что любые сообщения, соответствующие этим расширениям, посылаются при Рукопожатии и должны включаться в вычисления хэша в сообщение Finished.
Сначала рассмотрим расширение, позволяющее клиенту указать сервер, с которым он соединяется. Затем опишем расширение для указания максимальной длины фрагмента. Далее опишем расширение, которое позволяет клиенту указать URLs сертификатов, и расширение, позволяющее указать ключи корневых СА. Наконец, опишем расширение, которое позволяет задействовать урезанный HMAC, и расширение, поддерживающее интеграцию сообщения с информацией о статусе сертификата в Рукопожатие TLS.
Компрессия и декомпрессия
Все записи сжимаются с использованием алгоритма сжатия, определенного в текущем состоянии сессии. Первоначально он определяется как CompressionMethod.null. Алгоритм сжатия преобразует TLSPlaintext-структуру в TLSCompressed-структуру.
Если функция декомпрессии определяет, что длина декомпрессированного фрагмента превышает 214 байтов, возникает фатальная ошибка декомпрессии.
struct { ContentType type; /* same as TLSPlaintext.type */
ProtocolVersion version; /* same as TLSPlaintext.version */
uint16 length; opaque fragment[TLSCompressed.length]; } TLSCompressed;
length – длина (в байтах) следующего TLSCompressed.fragment.
fragment – сжатая форма TLSPlaintext.fragment.
Криптографические операции
Определены четыре криптографические операции: цифровая подпись, поточное шифрование, блочное шифрование и шифрование с открытым ключом.
В операции цифровой подписи входом в алгоритм подписи является результат применения односторонней хэш-функции к подписываемым данным. Длина входа определяется алгоритмом подписи.
При использовании алгоритма RSA подписывается 36-байтная структура, состоящая из конкатенации 20 байтов хэш-кода SHA-1 и 16 байтов хэш-кода MD5.
При использовании DSS 20 байтов хэш-кода SHA-1 подаются на вход алгоритму DSA без дополнительного хэширования. При этом создается два значения: r и s.
При поточном шифровании для незашифрованного текста выполняется операция XOR с тем же количеством значений, созданных криптографически безопасным (с ключом) генератором псевдослучайных чисел.
При блочном шифровании каждый блок незашифрованного текста шифруется, в результате чего создается блок зашифрованного текста. Все алгоритмы блочного шифрования выполняются в режиме СВС, и длина всех шифруемых элементов должна быть кратна длине блока алгоритма шифрования.
При шифровании с открытым ключом используется алгоритм открытого ключа, при этом данные могут быть дешифрованы только с помощью соответствующего закрытого ключа.
НМАС и псевдослучайная функция
Для получения МАС используется НМАС, поэтому если не знать секрета МАС, подделать МАС невозможно.
НМАС может использоваться с различными хэш-алгоритмами. TLS задействует при Рукопожатии два алгоритма, MD5 и SHA-1, обозначаемых как HMAC_MD5 (secret, data) и HMAC_SHA (secret, data). Могут быть определены дополнительные хэш-алгоритмы, но в настоящей версии используются только MD5 и SHA-1.
В алгоритме определена функция, которая расширяет секрет до нужной длины для создания всех необходимых ключей. Такая псевдослучайная функция, PRF, получает в качестве входа секрет, "зерно" (seed – значение, которое с одной стороны является случайным, а с другой стороны не является секретным, т.е. может стать известно оппоненту) и идентификационную метку, и создает выход требуемой длины.
Для того чтобы сделать PRF как можно более безопасной, используются два безопасных хэш-алгоритма.
Во-первых, определяется функция расширения данных P_hash (secret, data), которая применяет единственную хэш-функцию для расширения секрета и "зерна":
P_hash (secret, seed) = HMAC_hash (secret, A(1) + seed) + HMAC_hash (secret, A(2) + seed) + HMAC_hash (secret, A(3) + seed) + ...
Где
+ – обозначает конкатенацию.
А () – определяется следующим образом:
А (0) = seed
A (i) = HMAC_hash (secret, A (i – 1))
P_hash может иметь столько итераций, сколько необходимо для создания требуемого количества данных. Например, если P_SHA-1 используется для создания 64 байтов данных, то количество итераций должно быть равно 4, при этом будет создано 80 байтов данных; последние 16 байтов заключительной итерации будут отброшены, чтобы оставить только 64 байта выходных данных.
PRF создается путем расщепления секрета на две половины, одна половина используется для создания данных с помощью P_MD5, а другая – для создания данных с помощью P_SHA-1, после чего оба выхода этих функций складываются по модулю 2.
PRF определяется как результат сложения по модулю 2 этих двух псевдослучайных значений.
PRF (secret, label, seed) = P_MD5 (S1, label + seed)
P_SHA-1 (S2, label + seed);
Label является фиксированной текстовой строкой.
Заметим, что поскольку MD5 создает 16-байтные значения, а SHA-1 создает 20-байтные значения, то границы внутренних итераций не будут совпадать. Например, для создания 80-байтного значения необходимо выполнить 5 итераций P_MD5 и 4 итерации P_SHA-1.
Общие механизмы расширений
Рассмотрим общие механизмы расширений для сообщений Рукопожатия Client Hello и Server Hello.
Эти общие механизмы расширений необходимы для того, чтобы клиенты и серверы имели возможность вести переговоры об использовании конкретных расширений.
Сначала опишем формат расширенного сообщения Client Hello, затем формат расширенного сообщения Server Hello и формат реально используемого расширения.
Обсуждение проблем безопасности
Проанализируем безопасность для каждого расширения, определенного в данном документе.
Обзор протокола Рукопожатия
Криптографические параметры состояния сессии создаются протоколом Рукопожатия, который выполняется выше протокола Записи. Когда клиент и сервер начинают взаимодействовать, они согласовывают версию протокола, выбирают криптографические алгоритмы, могут аутентифицировать друг друга и используют технологию шифрования с открытым ключом для создания разделяемых секретов.
Протокол Рукопожатия включает следующие шаги:
Обмен сообщениями Hello для согласования алгоритмов, обмен случайными значениями и проверка возобновляемости сессии.Обмен необходимыми криптографическими параметрами, которые позволяют клиенту и серверу согласовать премастер-секрет (клиент посылает премастер секрет серверу).Обмен сертификатами и криптографической информацией, что позволяет клиенту и серверу аутентифицировать друг друга.Предоставление параметров безопасности на уровень Записи.Возможность клиенту и серверу проверить, что они вычислили одни и те же параметры безопасности и что Рукопожатие произошло без вмешательства злоумышленника.
Заметим, что протоколы более высокого уровня всегда должны считать, что TLS выберет наиболее сильное соединение между двумя участниками. Протокол разработан для минимизации риска атак типа встреча посередине, но защита от атак, при которых злоумышленник может блокировать доступ к порту, где функционирует сервис безопасности, и попытаться стать участником переговоров аутентифицированного соединения, не предусмотрена. Фундаментальное правило состоит в том, что протоколы более высокого уровня должны учитывать свои требования к безопасности и никогда не передавать информацию по менее безопасному каналу, чем требуется. Протокол TLS является безопасным, и выбранный набор алгоритмов обеспечивает соответствующий уровень безопасности. Например, если в результате переговоров были выбраны 3DES, 1024-битный ключ RSA и сертификат сервера проверен, соединение можно считать безопасным.
Данные цели достигаются протоколом Рукопожатия, который можно просуммировать следующим образом.
Клиент посылает сообщение Client Hello, на которое сервер должен ответить сообщением Server Hello или фатальной ошибкой и прерыванием соединения. Client Hello и Server Hello используются для определения максимального уровня безопасности между клиентом и сервером. Client Hello и Server Hello устанавливают следующие атрибуты: Protocol Version, Session ID, Cipher Suite и Compression Method. Дополнительно создаются и передаются два случайных значения: ClientHello.random и ServerHello.random.
Аутентификация и обмен общим секретом осуществляются в четырех сообщениях: сертификат сервера, обмен ключа сервера, сертификат клиента и обмен ключа клиента. Общий секрет должен быть достаточно большим; текущие методы распределения ключа обмениваются секретами, длина которых находится в диапазоне от 48 до 126 байт.
После сообщений Hello сервер посылает сертификат для аутентификации. Дополнительно может быть послано сообщение обмена ключа сервера, если сервер не имеет сертификата или его сертификат служит только для подписи. Если сервер аутентифицирован, он может запросить сертификат клиента, если того требует установленная политика безопасности. Теперь сервер посылает сообщение Server Hello Done, указывающее на то, что фаза Hello-сообщений Рукопожатия завершена. Затем сервер ждет ответа клиента. Если сервер послал сообщение запроса сертификата, клиент должен послать сообщение Certificate. После этого посылается сообщение обмена ключа клиента, содержимое этого сообщения зависит от выбранного алгоритма открытого ключа в сообщениях Client Hello и Server Hello. Если клиент имеет сертификат для подписывания, то посылается сообщение цифровой подписи для явной проверки всех сообщений Рукопожатия.
В данной точке клиентом посылается сообщение об изменении состояния, и клиент копирует ожидаемое состояние в текущее состояние. После этого клиент посылает заключительное сообщение с использованием новых алгоритмом, ключей и секретов. В ответ сервер посылает свое сообщение об изменении состояния, преобразует ожидаемое состояние в текущее состояние и посылает заключительное сообщение с использованием новых алгоритмов и ключей.
Переговоры о максимальной длине фрагмента
Прежняя версия TLS указывает, что максимальная длина незашифрованного фрагмента равна 214 байт. Для некоторых клиентов может потребоваться вести переговоры о меньшей максимальной длине фрагмента из-за ограничений памяти или ограничений ширины полосы пропускания.
Для этого клиент может указать расширение типа max_fragment_length в Client Hello. Поле extension_data данного расширения должно содержать:
enum{ 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) } MaxFragmentLength;
значение которого является требуемой максимальной длиной фрагмента. Допустимыми значениями для данного поля являются: 29, 210, 211 и 212.
Сервер, получивший расширенный Client Hello с расширением max_fragment_length, может принять эту длину, включая расширение типа max_fragment_length в Server Hello. Поле extension_data данного расширения должно содержать MaxFragmentLength, которое является тем же самым, что и запрошенная максимальная длина фрагмента.
Если запрошена недопустимая длина фрагмента, сервер должен прервать Рукопожатие с Alert illegal_parameter. Аналогично, если клиент получил ответ с максимальной длиной фрагмента, отличной от запрошенной, он также должен прервать Рукопожатие с Alert illegal_parameter.
После того, как стороны успешно договорились о максимальной длине фрагмента, отличной от 214, клиент и сервер должны немедленно начать фрагментировать сообщения (включая сообщения Рукопожатия), чтобы гарантировать, что не посылаются сегменты большей длины, чем та, о которой договорились. Заметим, что TLS требует, чтобы клиенты и серверы поддерживали фрагментацию сообщений Рукопожатия.
Новая длина применяется для продолжения сессии, включая возобновляющиеся сессии.
Процедура определения новых расширений
Традиционно IANA руководит определением новых значений, RFCs обычно определяют процедуру, используемую IANA. Однако могут возникнуть трудности при взаимодействии в данном протоколе между новыми и существующими возможностями, что может привести к снижению общей безопасности.
Следовательно, запросы на определение новых расширений должны утверждаться стандартными действиями IETF.
При определении новых расширений следует помнить:
Все расширения следуют соглашению, в соответствии с которым для каждого расширения, которое запросил клиент и которое понимает сервер, сервер отвечает расширением того же типа.Расширения должны быть разработаны с учетом того, чтобы предотвращать атаки, связанные с манипулированием сообщениями Рукопожатия.
Часто бывает достаточно того, что поля расширения включаются в вычисление хэша в сообщении Finished. Всегда следует помнить, что пока Рукопожатие не аутентифицировано, активные атакующие могут модифицировать сообщения и вставить, удалить или заменить расширения.
Технически возможно использовать расширения для изменения главных аспектов разработки TLS, например при разработке переговоров о наборе шифрования. Этого делать не рекомендуется, лучше определить новую версию TLS, так как алгоритмы Рукопожатия TLS имеют специальную защиту против атак rollback, основанных на номере версии, и возможность обратной передачи версии следует тщательно обдумать.
Протокол изменения шифрования
Протокол состоит из единственного сообщения, которое зашифровано и сжато, как определено в текущем (не ожидаемом) состоянии соединения.
Идентификатор сессии | Произвольная последовательность байтов, выбираемая сервером для идентификации активного или возобновляемого состояния сессии |
Сертификат участника | Х.509 v3 сертификат участника. Этот элемент может быть нулевым |
Метод сжатия | Алгоритм, используемый для сжатия данных перед шифрованием |
Набор алгоритмов | Алгоритм симметричного шифрования данных (такой как null, DES и т.д.), МАС-алгоритм (такой как MD5 или SHA) и различные криптографические атрибуты, такие как hash_size |
Мастер-секрет | 48-байтный секрет, разделямый клиентом и сервером |
Возобновляемо | Флаг, определяющий, может ли данная сессия использоваться для создания нового соединения |
Сообщение об изменении шифрования может посылаться как клиентом, так и сервером для уведомления получающей стороны о том, что следующие записи будут защищены алгоритмами и ключами, о которых стороны только что договорились. При поступлении данного сообщения получатель должен информировать протокол Записи о немедленном копировании ожидаемого состояния чтения в текущее состояние чтения. Сразу после посылки данного сообщения отправитель должен информировать протокол Записи на своем конце соединения о немедленном копировании ожидаемого состояния записи в текущее состояние записи. Сообщение об изменении шифрования посылается при Рукопожатии после того, как параметры безопасности согласованы, но перед тем как посылается заключительное верифицирующее сообщение.
Протокол Рукопожатия
Протокол Рукопожатия является одним из протоколов, определенных выше протокола Записи. Данный протокол используется для переговоров об атрибутах безопасности сессии. Сообщения Рукопожатия передаются протоколу Записи, где они инкапсулируются в одну или более структур TLSPlaintext, которые обрабатываются и передаются, как определено текущим активным состоянием сессии.
Сообщения протокола Рукопожатия представлены ниже в том порядке, в котором они должны посылаться. При нарушении данного порядка возникает фатальная ошибка. Тем не менее необязательные сообщения Рукопожатия можно опустить. Из этого правила существует одно исключение: сообщение Cеrtificate используется дважды при Рукопожатии (от сервера к клиенту, затем от клиента к серверу), но описано оно только один раз. Единственным сообщением, которое не связано данными правилами упорядоченности, является сообщение Hello Request. Оно может быть послано в любое время, но должно игнорироваться клиентом, если поступает в середине Рукопожатия.
Сервер | ||
ClientHello | ||
ServerHello | ||
[ ChangeCipherSpec ] | ||
? | Finished | |
[ ChangeCipherSpec ] | ||
Finished | ||
Прикладные данные | Прикладные данные |
Протокол Рукопожатия TLS
Протокол Рукопожатия состоит из трех протоколов, использование которых позволяет участникам согласовать параметры безопасности для протокола Записи, аутентифицировать друг друга, договориться о параметрах безопасности и сообщить друг другу о возникновении тех или иных ошибок.
В результате выполнения протокола Рукопожатия будут созданы элементы сессии показанные в таблице 21.3.
Протокол Записи
Протокол Записи состоит из нескольких уровней. На каждом уровне сообщения могут включать поля длины, описания и содержимого. Протокол Записи фрагментирует сообщение на блоки нужной длины, осуществляет сжатие данных, применяет МАС и зашифровывает их, после чего результат передается по сети. На другом конце соединения полученные данные дешифруются, проверяется их целостность, далее они декомпрессируются, дефрагментируются и передаются протоколам более высокого уровня.
Выше протокола Записи могут располагаться следующие протоколы: протокол Рукопожатия, Аlert-протокол, протокол изменения шифрования и протокол прикладных данных. Для того чтобы иметь возможность расширения протокола TLS, протокол Записи допускает создание новых типов записей. Если реализация TLS получает тип записи, который она не понимает, она просто игнорирует его. Заметим, что тип и длина записи не зашифрованы, следовательно эти значения не должны содержать секретных данных.
Проверка целостности с помощью сертификата клиента
Данное сообщение используется для обеспечения явной проверки целостности сообщений Рукопожатия с помощью сертификата клиента. Оно посылается только в том случае, если сертификат клиента имеет возможность подписывания (т.е. все сертификаты, за исключением тех, которые используют алгоритм Диффи-Хеллмана). Если оно посылается, то должно следовать непосредственно за сообщением Client Key Exchange.
Здесь handshake_messages означает все сообщения Рукопожатия, посланные или полученные во время Рукопожатия, начиная с Client Hello, но не включая данное сообщение. Включаются поля типа и длины сообщений Рукопожатия. Хэш вычисляется от конкатенации всех структур, посланных и полученных в сообщениях Рукопожатия.
Расширения Hello
Формат расширения для Client Hello и Server Hello следующий:
struct { ExtensionType extension_type; opaque extension_data<0..2^16-1>; } Extension;
Где:
extension_type определяет конкретный тип расширения;extension_data содержит информацию, относящуюся к конкретному типу расширения. Определены следующие типы расширений:
enum { server_name(0), max_fragment_length(1), client_certificate_url(2), trusted_ca_keys(3), truncated_hmac(4), status_request(5), (65535) } ExtensionType;
Заметим, что для всех типов расширений (включая и те, которые будут определены в дальнейшем) тип расширения не должен появляться в расширенном Server Hello, пока не появится в соответствующем Client Hello. Таким образом, клиенты должны прерывать Рукопожатия, если получили расширенный тип в расширенном Server Hello, который не был запрошен в соответствующем Client Hello.
Расширения, инициируемые сервером (server initiated), могут присутствовать в будущем в рамках данного протокола, при этом требуется, чтобы клиент первым посылал пустое расширение, указывая тем самым, что он готов принимать подобное расширение.
Если в расширенном Client Hello или расширенном Server Hello присутствует несколько расширений различных типов, они могут появляться в произвольном порядке. Не должно быть более одного расширения каждого типа.
Наконец, заметим, что все расширения, определенные в настоящий момент, относятся только к инициализации сессии. Однако клиент, который послал запрос на возобновление сессии, не знает, будет ли принят данный запрос, и, следовательно, должен послать расширенный Client Hello, если это необходимо для новой сессии. Если запрос на возобновление отвергнут, будут вестись переговоры о новом множестве расширений. Если, с другой стороны, старая сессия возобновляется, то сервер должен игнорировать расширения, появившиеся в Client Hello, и послать Server Hello, не содержащий расширений. В этом случае используется расширение, о котором участники договорились при инициализации исходной сессии, возобновлением которой является данная сессия.
Расширения в протоколе Рукопожатия
Поддерживается использование двух новых сообщений Рукопожатия: CertificateURL и CertificateStatus. Новая структура сообщения рукопожатия:
enum { hello_request(0), client_hello(1), server_hello(2), certificate(11), server_key_exchange (12), certificate_request(13), server_hello_done(14), certificate_verify(15), client_key_exchange(16), finished(20), certificate_url(21), certificate_status(22), (255) } HandshakeType; struct { HandshakeType msg_type; /* handshake type */ uint24 length; /* bytes in message */ select (HandshakeType) { case hello_request: HelloRequest; case client_hello: ClientHello; case server_hello: ServerHello; case certificate: Certificate; case server_key_exchange: ServerKeyExchange; case certificate_request: CertificateRequest; case server_hello_done: ServerHelloDone; case certificate_verify: CertificateVerify; case client_key_exchange: ClientKeyExchange; case finished: Finished; case certificate_url: CertificateURL; case certificate_status: CertificateStatus; } body; } Handshake;
Расширенный Client Hello
Клиент может запросить расширенную функциональность от сервера, посылая расширенный формат сообщения Client Hello вместо обычного формата сообщения Client Hello. Расширенный формат сообщения Client Hello следующий:
struct { ProtocolVersion client_version; Random random; SessionID session_id; CipherSuite cipher_suites<2..2^16-1>; CompressionMethod compression_methods<1..2^8-1>; Extension client_hello_extension_list<0..2^16-1>; } ClientHello;
Здесь новое поле client_hello_extension_list содержит список расширений.
Если клиент запросил дополнительную функциональность, используя расширенный Client Hello, и данная функциональность не поддерживается сервером, клиент может прервать Рукопожатие.
Заметим, что TLS допускает дополнительную информацию в сообщении Client Hello. Таким образом, использование расширенного Client Hello не должно приводить к разрыву соединения с существующими серверами TLS.
Сервер, который поддерживает механизм расширений, должен принимать как исходный формат, так и расширенный формат Client Hello, и (как и для всех остальных сообщений) проверять, соответствует ли количество данных в сообщении одному из этих форматов; если это не так, он должен послать фатальный Alert decode_error.
Расширенный Server Hello
Расширенный формат сообщения Server Hello может быть послан вместо сообщения Server Hello, когда клиент запросил дополнительную функциональность с помощью расширенного сообщения Server Hello. Расширенный формат сообщения Server Hello следующий:
struct { ProtocolVersion server_version; Random random; SessionID session_id; CipherSuite cipher_suite; CompressionMethod compression_method; Extension server_hello_extension_list<0..2^16-1>; } ServerHello;
Здесь новое поле server_hello_extension_list содержит список расширений. Реальный формат расширения будет определен ниже.
Заметим, что расширенное сообщение Server Hello посылается только в ответ на расширенное сообщение Client Hello. Это позволит избежать ситуации, при которой расширенное сообщение Server Hello не даст установить соединение с существующими клиентами TLS 1.0.
Сертификат клиента
Это первое сообщение, которое клиент посылает после получения сообщения Server Hello Done. Оно посылается только в том случае, если сервер требует сертификат. Если подходящий сертификат недоступен, клиент должен послать сообщение Certificate, не содержащее сертификатов. Если сервер требует аутентификации клиента для продолжения Рукопожатия, он может ответить фатальным handshake failure Alert. Структура сертификатов клиента такая же, как и сервера.
Если применяется метод обмена ключа, основанный на алгоритме Диффи-Хеллмана (DH_DSS или DH_RSA) и требуется аутентификация клиента, то группа и генератор Диффи-Хеллмана, содержащиеся в сертификате клиента, должны соответствовать параметрам Диффи-Хеллмана, определенным для сервера, если параметры клиента используются для обмена ключа.
Сертификат сервера
Сервер должен посылать сертификат, если метод обмена ключей не является анонимным. Данное сообщение всегда следует сразу за сообщением Server Hello.
Тип сертификата должен соответствовать выбранному алгоритму обмена ключа. Обычно это сертификат X.509v3. Он должен содержать ключ, который соответствует методу обмена ключа. Если не указано иное, то алгоритм подписывания должен быть тем же самым, что и алгоритм для обмена ключа. Если не указано иное, то открытый ключ может иметь произвольную длину.
Все профили сертификатов, ключи и криптографические форматы определены рабочей группой IETF PKIX. Если допускается различное использование ключа, то должен быть установлен бит digitalSignature для ключа, который может применяться для подписывания, и должен быть установлен бит keyEncipherment для ключа, которым можно шифровать. Бит keyAgreement должен быть установлен для сертификатов Диффи-Хеллмана.
Могут быть определены новые методы обмена ключа. Они должны иметь соответствующий формат сертификата и информации о ключе.
Предполагается, что сертификатами являются сертификаты Х.509 v3. Отправитель сертификата должен быть первым в списке. Каждый последующий сертификат должен непосредственно сертифицировать предыдущий. Так как для действительности сертификата требуется, чтобы ключи корневого сертификата распределялись независимо, корневой сертификат может быть опущен, исходя из предположения, что он известен получателю.
Точно такое же сообщение используется для ответа клиента при запросе его сертификата. Клиент может не посылать сертификата, если он его не имеет.
Server Hello Done
Сообщение Server Hello Done посылается сервером для обозначения окончания фазы Server Hello и связанных с ней сообщений. После посылки данного сообщения сервер ждет ответа клиента.
Данное сообщение означает, что сервер завершил отправку сообщений, поддерживающих обмен ключа.
Алгоритм обмена ключа | Тип ключа сертификата |
RSA | Открытый ключ RSA; сертификат должен позволять задействовать ключ для шифрования |
RSA_EXPORT | Учтены экспортные ограничения, т.е. открытый ключ RSA длиной больше 512 бит может использоваться для подписывания, ключ 512 бит и короче может использоваться как для подписи, так и для шифрования. В первом случае следущим сообщением должно быть ServerKeyExchange, в котором этим ключом будут подписаны открытые ключи Диффи-Хеллмана или другой открытый ключ RSA |
DH_DSS | Открытый ключ DSS. Обмен ключа осуществляется по алгоритму Диффи-Хеллмана |
DH_RSA | Открытый ключ RSA, который может использоваться для подписывания. Обмен ключа осуществляется по алгоритму Диффи-Хеллмана |
При получении сообщения Server Hello Done клиент должен убедиться, что сервер предоставил законный сертификат и что Hello параметры сервера приемлемы для клиента.
Сообщение Client Key Exchange
Данное сообщение посылается клиентом всегда. Оно следует сразу за сообщением Client Certificate, если таковое посылается. В противном случае это первое сообщение, посланное клиентом после получения сообщения Server Hello Done.
В данном сообщении устанавливается премастер-секрет, который передается либо с помощью RSA шифрования, либо с использованием алгоритма Диффи-Хеллмана, что позволяет каждой стороне вычислить один и тот же премастер-секрет. Когда методом обмена ключа является DH_RSA или DH_DSS и сертификат клиента запрашивается, клиент может ответить сертификатом, содержащим открытый ключ Диффи-Хеллмана, чьи параметры (группа и генератор) должны соответствовать тем, которые специфицированы в сертификате сервера. Никаких других данных это сообщение не содержит.
Структура сообщения зависит от выбранного метода обмена ключа.
Если для согласования общего секрета и аутентификации используется RSA, клиент создает 48-байтный премастер-секрет, шифрует его с использованием открытого ключа из сертификата сервера или временного ключа RSA, полученного в сообщении Server Key Exchange.
Сообщение Finished
Сообщение Finished всегда посылается непосредственно после сообщения Сhange Сipher Spec для проверки успешного выполнения обмена ключа и процессов аутентификации. Причем сообщение Change Cipher Spec должно быть получено после остальных сообщений Рукопожатия и перед Finished-сообщением.
Finished-сообщение является первым сообщением, защищенным с помощью только что обговоренных алгоритмов, ключей и секретов. Получатели Finished-сообщения должны убедиться, что его содержимое корректно. После того как одна сторона послала свое Finished-сообщение, получила и проверила Finished сообщение другой стороны, она может начинать посылать и получать прикладные данные по этому соединению.
Возникает фатальная ошибка, если сообщению Finished не предшествует сообщение Change Cipher Spec.
Хэш, содержащийся в сообщениях Finished, посылается сервером в Sender.server и клиентом – в Sender.client. Значение handshake_message включает все сообщения Рукопожатия, начиная от Client Hello, но не включая данное Finished-сообщение. Это может отличаться от handshake_message, которые включают сообщение проверки сертификата (если он посылается). Также handshake_message в сообщении Finished, посылаемом сервером, отличается от сообщения Finished, посылаемом клиентом, потому что сервер посылает его вторым, включая предшествующее сообщение.
Напомним, что сообщения о смене шифратора, Alerts и другие типы записей не являются сообщениями Рукопожатия и в вычисление хэша не включаются. Сообщения Hello Request в хэшах Рукопожатия также опущены.
Сообщение сервера обмена ключа
Данное сообщение посылается непосредственно после сообщения Server Certificate (или сообщения Server Hello, если переговоры анонимные).
Сообщение сервера обмена ключа посылается сервером только тогда, когда сообщение Server Certificate (если оно послано) не содержит достаточно данных, чтобы клиент мог осуществить обмен премастер-секретом. Это верно для следующих методов обмена ключа:
RSA_EXPORT (если открытый ключ в сертификате сервера длиннее 512 бит)DH_DSSDH_RSADH_anon
Данное сообщение передает криптографическую информацию, которая позволяет клиенту передавать премастер-секрет: премастер-секрет шифруется либо открытым ключом RSA, либо открытым ключом Диффи-Хеллмана, с помощью которого клиент может завершить обмен ключа.
Таким образом, сообщение сервера обмена ключа будет послано тогда и только тогда, когда тип сертификата, связанный с алгоритмом обмена ключа, не предоставляет достаточно информации клиенту для обмена премастер-секретом.
Сообщения Hello
Сообщения фазы Hello используются для обмена возможностями установления безопасного соединения между клиентом и сервером. Когда начинается новая сессия, алгоритмы шифрования, хэширования и сжатия состояния соединения протокола Записи инициализируются в null. Параметры текущего состояния соединения используются при повторных переговорах.
Hello Request
Сообщение Hello Request может быть послано сервером в любое время.
Hello Request является просто уведомлением о том, что клиент должен начать процесс переговоров заново посылкой сообщения Hello. Данное сообщение будет игнорироваться клиентом, если он находится в состоянии переговоров. Данное сообщение может игнорироваться клиентом, если он не хочет вести новые переговоры, при этом клиент может ответить no_renegotiation Alert. Если сервер посылает Hello Request, но не получает в ответ Client Hello, он может закрыть соединение с фатальным Alert.
После посылки Hello Request сервер не должен повторять запрос до тех пор, пока последующие переговоры Рукопожатия не будут завершены.
Замечание: данное сообщение никогда не должно включаться в хэши сообщений, которые вычисляются при Рукопожатии и используются в завершающих сообщениях и сообщении проверки сертификата.
Client Hello
Данное сообщение посылается, когда клиент в первый раз соединяется с сервером. В качестве первого сообщения требуется посылать Client Hello. Клиент также может послать Client Hello в ответ на Hello Request или по собственной инициативе, чтобы начать новые переговоры о параметрах безопасности для существующего соединения.
Сообщение Client Hello содержит случайные числа, которые используются при создании мастер-секрета.
Сообщение Client Hello может включать идентификатор сессии. Его значение определяет сессию между теми же клиентом и сервером, чьи параметры безопасности клиент хочет использовать. Идентификатор сессии может быть получен из ранее установленного соединения или другого текущего активного соединения. Это дает возможность установить несколько независимых безопасных соединений без повторения полного протокола Рукопожатия.
Эти независимые соединения могут существовать как последовательно, так и одновременно. SessionID может использоваться после того, как протокол Рукопожатия завершится обменом Finished-сообщениями и сохраняется до тех пор, пока не будет удален или не произойдет фатальная ошибка в соединении, связанном с данной сессией.
Следует заметить, что, так как SessionID передается без шифрования и МАС- защиты, серверы не должны помещать конфиденциальную информацию в идентификаторы сессии или позволять поддельным идентификаторам сессии вызывать нарушения безопасности. Заметим, что содержимое всего Рукопожатия, включая SessionID, защищено Finished-сообщениями, которыми участники обмениваются в конце Рукопожатия.
Список CipherSuite, передаваемый от клиента серверу в сообщении Client Hello, содержит комбинации криптографических алгоритмов, поддерживаемых клиентом, упорядоченные согласно предпочтениям клиента. Каждый CipherSuite определяет алгоритм обмена ключа, алгоритм основного шифрования (включая длину секретного ключа) и алгоритм МАС. Сервер будет выбирать набор шифрования или, если приемлемый выбор невозможен, возвратит Alert падения Рукопожатия и закроет соединение.
Сlient Hello включает также список алгоритмов сжатия, поддерживаемых клиентом, упорядоченный согласно предпочтениям клиента.
После посылки сообщения Client Hello клиент ждет сообщения Server Hello. Любое другое сообщение, возвращаемое сервером, за исключением Hello Request, трактуется как фатальная ошибка.
Замечание о совместимости: в интересах совместимости с последующими реализациями допускается в сообщение Client Hello включать внешние данные после методов сжатия. Эти данные должны быть включены в вычисление хэшей Рукопожатия, но в других отношениях они должны игнорироваться. Это возможно только для сообщения Рукопожатия; для всех других сообщений количество данных в сообщении должно точно соответствовать описанию сообщения.
Server Hello
Сервер посылает данное сообщение в ответ на сообщение Client Hello, для того чтобы выбрать конкретный набор алгоритмов.Если он не может сделать такой выбор, он отвечает handshake failure Alert.
Сообщения закрытия
Клиент и сервер должны оба узнать о том, что соединение завершается. Каждый участник может инициировать обмен сообщениями закрытия.
Сообщение close_notify уведомляет получателя о том, что отправитель не будет больше посылать никаких сообщений по данному соединению. Сессия становится невозобновляемой, если хотя бы одно соединение завершено без соответствующего предупреждающего сообщения close_notify.
Каждый участник может инициировать закрытие посылкой сообщения Alert типа close_notify. Любые данные, отправленные после Alert-закрытия, игнорируются.
Требуется, чтобы каждый участник посылал close_notify Alert перед закрытием стороны записи соединения. Это означает, что при получении ответа другого участника с Alert типа close_notify соединение немедленно закрывается и все ожидаемые состояния сбрасываются. Инициатору закрытия не обязательно ждать ответного close_notify Alert перед закрытием стороны чтения соединения.
Если прикладной протокол, использующий TLS, предполагает, что какие-либо данные могут передаваться нижележащим транспортом после того как соединение TLS закрыто, реализация TLS должна получать ответный Alert типа close_notify перед тем как сообщать прикладному уровню, что соединение TLS завершено. Если прикладной протокол не будет передавать никаких дополнительных данных, а будет только закрывать нижележащее транспортное соединение, реализация может закрыть соединение без ожидания ответного close_notify. В стандарте TLS не определен способ, которым управляются данные транспорта, включая открытие и закрытие соединений.
Замечание: предполагается, что при закрытии соединения ожидающие доставки данные надежно доставляются перед разрушением транспорта.
Состояния соединения
Вводится понятие состояния соединения, которое определяет параметры выполнения протокола Записи. Такими параметрами являются алгоритм сжатия, алгоритм шифрования и МАС-алгоритм, а также параметры этих алгоритмов, т.е. секреты МАС, ключи алгоритма шифрования и инициализационные вектора. Для каждого направления (соответственно чтение или запись) параметры соединения могут различаться. Существует четыре состояния соединения: текущие состояния чтения и записи и ожидаемые состояния чтения и записи. Параметры безопасности для ожидаемых состояний устанавливаются протоколом Рукопожатия, а протокол Изменения шифрования может делать ожидаемое состояние текущим, при этом соответствующее текущее состояние сбрасывается и заменяется ожидаемым. Ожидаемое состояние в этом случае инициализируется в пустое состояние. Разработчики не должны допускать возможности сделать текущим состояние, которое не было инициализировано параметрами безопасности. Начальное текущее состояние всегда определяется без использования шифрования, сжатия и МАС.
Параметры безопасности для состояний чтения и записи устанавливаются с помощью следующих значений (см. таб. 21.1).
Уровень записи использует параметры безопасности для создания следующих шести элементов:
client write MAC secret
server write MAC secret
client write key
server write key
client write IV – только для блочных алгоритмов
server write IV – только для блочных алгоритмов
Параметры client write используются сервером, когда он получает сообщения и клиентом, когда тот посылает их. Параметры server write применяются сервером, когда он посылает сообщения и клиентом, когда он получает их. После того как параметры безопасности установлены и ключи созданы, ожидаемые состояния соединения могут быть сделаны текущими.
Конец соединения | Каждый участник является либо "клиентом", либо "сервером" |
Алгоритм симметричного шифрования | Алгоритм, используемый для симметричного шифрования. Данное описание включает размер ключа алгоритма, тип алгоритма (блочный или поточный), размер блока алгоритма и информацию о том, является ли он "экспортируемым" |
МАС алгоритм | Алгоритм, используемый для проверки целостности сообщения. Это описание включает размер хэша, который возвращается МАС-алгоритмом |
Алгоритм сжатия | Алгоритм, используемый для сжатия данных. Данное описание включает всю информацию, необходимую алгоритму сжатия |
Мастер-секрет | 48-байтный секрет, разделяемый обоими участниками соединения |
Случайное число клиента | 32-байтное значение, создаваемое клиентом |
Случайное число сервера | 32-байтное значение, создаваемое сервером |
Алгоритм МАС | МАС-секрет |
Последовательный номер | Каждое состояние соединения содержит последовательный номер, который вычисляется независимо для состояний чтения и записи. Последовательный номер должен устанавливаться в ноль всякий раз, когда состояние соединения становится активным, т.е. текущим или ожидаемым. Последовательные номера не могут быть больше 264 - 1. Последовательный номер возрастает после каждой записи |
Указание доверенного СА
Клиенты, которые имеют ограниченную память, обладают только небольшим количеством ключей корневого СА и им может потребоваться указать серверу, какими корневыми ключами они владеют, чтобы избежать падения Рукопожатия.
Для этого клиенты могут включить расширение типа trusted_ca_keys в Client Hello. Поле extension_data данного расширения должно содержать TrustedAuthorities, где:
struct { TrustedAuthority trusted_authorities_list<0..2^16-1>; } TrustedAuthorities; struct { IdentifierType identifier_type; select (identifier_type) { case pre_agreed: struct {}; case key_sha1_hash: SHA1Hash; case x509_name: DistinguishedName; case cert_sha1_hash: SHA1Hash; } identifier; } TrustedAuthority; enum { pre_agreed(0), key_sha1_hash(1), x509_name(2), cert_sha1_hash(3), (255) } IdentifierType; opaque DistinguishedName<1..2^16-1>;
Здесь TrustedAuthorities содержит список идентификаторов ключей корневых СА, которыми владеет клиент. Каждый ключ корневого СА идентифицируется одним из следующих способов:
pre_agreed – не предоставляется никакой идентификации ключа корневого СА.key_sha1_hash – содержит SHA-1 хэш ключа корневого СА. Для ключей DSA и ECDSA это хэш значения subjectPublicKey. Для ключей RSA хэш есть строка байтов модуля без начальных нулевых байтов (аналогично форматам хэша ключа в других окружениях).х509_name – содержит DER представление DN CA.cert_sha1_hash – содержит SHA-1 хэш DER представления Certificate, содержащего ключ корневого СА.
Заметим, что клиенты могут включать в данное расширение несколько или все ключи корневого СА, которыми они владеют, либо ни одного из них.
Также возможна ситуация, при которой хэш ключа или DN по отдельности не идентифицируют выпускающего сертификат – например, если конкретный СА имеет несколько пар ключей – однако здесь мы предполагаем, что в TLS DNs идентифицируют выпускающих сертификаты.
Если данная опция включена, это позволяет клиентам сообщать о наличии у них некоторого предопределенного множества ключей корневого СА.
Сервер, который получил Client Hello с расширением trusted_ca_keys, может использовать информацию, содержащуюся в расширении, в качестве руководства по выбору цепочки сертификатов, возвращаемой клиенту. В данном случае сервер должен включить расширение типа trusted_ca_keys в Server Hello. Поле extension_data данного расширения должно быть пустым.
Указание имени сервера
Исходный протокол не предоставляет механизма, который позволял бы клиенту указать имя сервера, с которым он хочет соединиться. Однако это может требоваться для обеспечения безопасного соединения с хостами, у которых имеется несколько виртуальных серверов на одном сетевом адресе.
Для того чтобы указать имя сервера, клиент может включить расширение типа server_name в Client Hello. Поле extension_data должно содержать ServerNameList:
struct { NameType name_type; select (name_type) { case host_name: HostName; } name; } ServerName; enum { host_name(0), (255) } NameType; opaque HostName<1..2^16-1>; struct { ServerName server_name_list<1..2^16-1> } ServerNameList;
На сегодня в качестве имени сервера поддерживается только DNS hostname. Это не означает какой-либо зависимости TLS от DNS, в дальнейшем могут быть добавлены другие типы имен. TLS может трактовать имена серверов как данные неизвестной структуры (opaque) и передавать их приложению.
HostName содержит полностью определенное DNS hostname сервера. Hostname является байтовой строкой, представленной с использованием UTF-8.
Сервер, который получил сообщение Client Hello, содержащее расширение server_name, может использовать данную информацию для выбора сертификата, возвращаемого клиенту, либо для каких-то других аспектов безопасности. В данном случае сервер должен включить расширение типа server_name в расширенное Server Hello. Поле extension_date данного расширения должно быть пустым.
Если сервер понимает расширение Client Hello, но не смог распознать имя сервера, он должен послать unrecognized_name Alert (который может быть фатальным).
Если приложение провело переговоры об имени сервера с использованием протокола приложения, а затем после модификации TLS было послано расширение server_name, то расширение должно содержать то же самое имя, о котором участники договорились в прикладном протоколе. Если server_name установлено при Рукопожатии TLS, то клиент не должен пытаться запросить на прикладном уровне другое имя сервера.
Урезанный НМАС
В настоящий момент набор шифрования использует в качестве МАС НМАС либо с MD5, либо с SHA-1 для аутентификации соединений уровня записи. Весь выход хэш-функции используется в качестве тега МАС. Однако может быть желательно в некоторых ограниченных окружениях обрезать выход хэш-функции до 80 битов при формировании тегов МАС.
Для того чтобы вести переговоры об использовании 80-битного урезанного МАС, клиенты могут включить расширение типа truncated_hmac в расширенный Client Hello. Поле extension_data данного расширения должно быть пустым.
При получении расширенного Hello, содержащего расширение truncated_hmac, сервер может согласиться использовать урезанный МАС путем включения расширения типа truncated_hmac с пустым extension_data в расширенный Server Hello.
Заметим, что если добавлен новый набор алгоритмов шифрования, который не использует НМАС, и при переговорах выбран один из этих наборов, то данное расширение ни на что не влияет. Рекомендуется, чтобы все новые наборы алгоритмов шифрования, использующие другие МАСs, рассматривали размер МАС как составную часть определения набора шифрования, имея в виду как безопасность, так и ограничения ширины полосы пропускания.
Если переговоры об урезанном МАС успешно завершены, клиент и сервер передают эту информацию на уровень записи в качестве параметров безопасности. Далее в данной сессии клиент и сервер должны использовать урезанный НМАС, соответствующим образом вычисляя его. Это означает, что CipherSpec.hash_size есть 10 байтов, и только первые 10 байтов выхода НМАС передаются и проверяются. Заметим, что данное расширение не влияет на вычисление PRF на часть получения ключа.
Размер урезанного МАС применяется к сессиям, в том числе возобновляемым.
URLs сертификата клиента
TLS требует, чтобы при выполнении аутентификации клиента сертификаты клиента посылались серверу в течение Рукопожатия. Для клиентов, имеющих различные ограничения, может потребоваться посылать URLs сертификата вместо самих сертификатов, чтобы они могли не хранить свои сертификаты и тем самым не занимать память.
Для ведения переговоров о посылке серверу URLs сертификата клиенты могут включать расширение типа client_certificate_url в Client Hello. Поле extension_data данного расширения должно быть пустым.
Заметим, что необходимо вести переговоры об использовании URLs сертификатов клиента, чтобы существующие серверы TLS 1.0 могли функционировать.
Сервер, получивший расширенный Client Hello, содержащий расширение client_certificate_url, может указать, что имеет возможность принимать URLs сертификата, указывая расширение типа client_certificate_url в Server Hello. Поле extension_data данного расширения должно быть пустым.
После успешного завершения переговоров об использовании URLs сертификата клиента клиент может посылать сообщение CertificateURL вместо сообщения Certificate:
enum { individual_certs(0), pkipath(1), (255) } CertChainType; enum { false(0), true(1) } Boolean; struct { CertChainType type; URLAndOptionalHash url_and_hash_list<1..2^16-1>; } CertificateURL; struct { opaque url<1..2^16-1>; Boolean hash_present; select (hash_present) { case false: struct {}; case true: SHA1Hash; } hash; } URLAndOptionalHash; opaque SHA1Hash[20];
Здесь url_and_hash_list содержит последовательность URLs и хэши (необязательно).
При использовании сертификатов Х.509 существует две возможности:
Если Certificate.type есть individual_certs, то каждый URL ссылается на единственный сертификат Х.509v3 в DER-представлении; при этом первым указывается сертификат клиента.Если Certificate.type есть PkiPath, то список содержит единственный URL, ссылающийся на цепочку сертификатов в представлении DER, при этом используется тип PkiPath, описанный ниже.
При использовании любого другого формата спецификация, описывающая применение этого формата, должна определять формат представления сертификатов или цепочки сертификатов и различные ограничения их последовательности.
Хэш, соответствующий каждому URL, либо не присутствует, либо является SHA-1 хэшем сертификата или цепочки сертификатов (в случае сертификатов Х.509 DER-представлением сертификата или DER-представлением PkiPath).
Заметим, что когда используется список URLs для сертификатов Х.509, упорядоченность URLs является той же самой, что и в сообщении Certificate, в противоположность упорядоченности, в которой сертификаты представлены в PkiPath. В любом случае самоподписанный корневой сертификат в цепочке может быть опущен, в предположении, что сервер уже проверил его действительность.
При получении CertificateURL сервер должен пытаться получить цепочку сертификатов клиента из URLs и затем обработать ее обычным образом. Может использоваться кэшированная копия содержимого любого URL из цепочки, проверяя, что SHA-1 хэш присутствует и соответствует хэшу кэшированной копии.
Серверы, которые поддерживают данное расширение, должны поддерживать http:URL схему для URLs сертификатов и могут поддерживать другие схемы.
Если протокол, используемый для получения сертификатов или цепочки сертификатов, возвращает MIME форматированный ответ (как делает НТТР), то должен применяться следующий MIME Content-Type: при возврате единственного сертификата Х.509v3 Content-Type есть application/pkix-cert, при возврате цепочки сертификатов Х.509v3 Content-Type есть application/pkix-pkipath.
Если для URL присутствует SHA-1 хэш, то сервер должен убедиться, что SHA-1 хэш содержимого объекта, полученного из URL (после декодирования произвольного MIME Content-Transfer-Encoding), соответствует данному хэшу. Если полученный объект не имеет корректного SHA-1 хэша, сервер должен прервать Рукопожатие с Alert bad_certificate_hash_value.
Заметим, что клиент может выбрать либо посылку Certificate, либо посылку CertificateURL после успешных переговоров о посылке URLs сертификатов. Опция посылки сертификата обеспечивает клиенту гибкость при обработке нескольких сертификатов.
Если сервер столкнулся с непредвиденной задержкой при получении сертификатов по указанному CertificateURL, он должен при истечении таймаута создать Alert ошибки certificate_unobtainable.
Уровень Записи
Уровень Записи получает данные от более высоких уровней в блоках произвольной длины.
Основная функция протокола TLS состоит
Основная функция протокола TLS состоит в обеспечении защиты и целостности данных между двумя взаимодействующими приложениями, одно из которых является клиентом, а другое – сервером.
Протокол TLS (Transport Layer Security) разрабатывался на основе спецификации протокола SSL 3.0 (Secure Socket Layer), опубликованного корпорацией Netscape. Различия между данным протоколом и SSL 3.0 несущественны, но важно заметить, что TLS 1.0 и SSL 3.0 несовместимы, хотя в TLS 1.0 предусмотрен механизм, который позволяет реализациям TLS иметь обратную совместимость с SSL 3.0.
Перечислим задачи протокола TLS в порядке их приоритета:
Криптографическая безопасность: TLS должен использоваться для установления безопасного соединения между двумя участниками.Интероперабельность: независимые разработчики могут создавать приложения, которые будут взаимодействовать по протоколу TLS, что позволит устанавливать безопасные соединения.Расширяемость: TLS формирует общий каркас, в который могут быть встроены новые алгоритмы открытого ключа и симметричного шифрования. Это также избавляет от необходимости создавать новый протокол, что сопряжено с опасностью появления новых слабых мест, и предотвращает необходимость полностью реализовывать новую библиотеку безопасности.Относительная эффективность: криптографические операции интенсивно используют ЦП, особенно операции с открытым ключом. Для этого вводится понятие сессии, для которой определяются алгоритмы и их параметры. В рамках одной сессии может быть создано несколько соединений (например, ТСР). TLS позволяет кэшировать сессии для уменьшения количества выполняемых действий при установлении соединения. Это снижает нагрузку как на ЦП, так и на трафик.
Протокол состоит из двух уровней. Нижним уровнем, расположенным выше некоторого надежного протокола (а именно, протокола ТСР) является протокол Записи. Протокол Записи обеспечивает безопасность соединения, которая основана на следующих двух свойствах:
Конфиденциальность соединения. Для защиты данных используется один из алгоритмов симметричного шифрования.
Ключ для этого алгоритма создается для каждой сессии и основан на секрете, о котором договариваются в протоколе Рукопожатия. Протокол Записи также может использоваться без шифрования.Целостность соединения. Обеспечивается проверка целостности сообщения с помощью МАС с ключом. Для вычисления МАС используются безопасные хэш-функции SHA-1 и MD5. Протокол Записи может выполняться без вычисления МАС, но обычно функционирует в этом режиме.
Протокол Записи используется для инкапсуляции различных протоколов более высокого уровня. Одним из протоколов более высокого уровня является протокол Рукопожатия, который использует протокол Записи в качестве транспорта для ведения переговоров о параметрах безопасности. Протокол Рукопожатия позволяет серверу и клиенту аутентифицировать друг друга и договориться об алгоритмах шифрования и криптографических ключах до того, как прикладной протокол, выполняющийся на том же уровне, начнет передавать или принимать первые байты данных.
Протокол Рукопожатия обеспечивает безопасность соединения, которая основана на следующих свойствах:
Участники аутентифицированы с использованием криптографии с открытым ключом (т.е. с использованием алгоритмов RSA, DSS и т.д.). Эта аутентификация может быть необязательной, но обычно требуется по крайней мере для сервера.Переговоры о разделяемом секрете безопасны, т.е. этот общий секрет невозможно подсмотреть.Переговоры о разделяемом секрете надежны, если выполнена аутентификация хотя бы одной из сторон. В таком случае атакующий, расположенный в середине соединения, не может модифицировать передаваемый секрет незаметно для участников соединения.
Одно из преимуществ TLS состоит в том, что он независим от прикладного протокола. Протоколы более высокого уровня могут прозрачно располагаться выше протокола TLS.
Данная функциональность позволяет избежать посылки CRL в определенных сетях и тем самым сократить трафик.
Для того чтобы поддерживать перечисленные выше расширения, вводятся дополнительные механизмы для сообщений Hello клиента и сервера.
Описываемые расширения могут использоваться клиентами TLS 1.0 и серверами TLS 1.0. Расширения поддерживают обратную совместимость – это означает, что клиенты TLS 1.0, которые поддерживают расширения, могут общаться с серверами TLS 1.0, не поддерживающими расширения, и наоборот.
Обратная совместимость достигается следующим образом.
Клиент запрашивает использование расширений с помощью расширенного сообщения Client Hello, описанного ниже. TLS 1.0 требует, чтобы серверы принимали расширенные сообщения Client Hello, даже если они не понимают расширения.Для описанных здесь конкретных расширений не требуется обязательного ответа сервера, если клиент запрашивает расширенную функциональность.
Однако заметим, что хотя обратная совместимость поддерживается, некоторые клиенты из-за своих ограниченных возможностей могут не устанавливать соединения с серверами, которые не поддерживают расширения.
Рассмотрим дополнительные функциональности в следующем порядке. Сначала опишем общие механизмы расширений для сообщений Рукопожатия Client Hello и Server Hello. Далее опишем конкретные расширения для TLS 1.0 и новые сообщения об ошибках при использовании расширений TLS.
Ключ для этого алгоритма создается для каждой сессии и основан на секрете, о котором договариваются в протоколе Рукопожатия. Протокол Записи также может использоваться без шифрования.Целостность соединения. Обеспечивается проверка целостности сообщения с помощью МАС с ключом. Для вычисления МАС используются безопасные хэш-функции SHA-1 и MD5. Протокол Записи может выполняться без вычисления МАС, но обычно функционирует в этом режиме.
Протокол Записи используется для инкапсуляции различных протоколов более высокого уровня. Одним из протоколов более высокого уровня является протокол Рукопожатия, который использует протокол Записи в качестве транспорта для ведения переговоров о параметрах безопасности. Протокол Рукопожатия позволяет серверу и клиенту аутентифицировать друг друга и договориться об алгоритмах шифрования и криптографических ключах до того, как прикладной протокол, выполняющийся на том же уровне, начнет передавать или принимать первые байты данных.
Протокол Рукопожатия обеспечивает безопасность соединения, которая основана на следующих свойствах:
Участники аутентифицированы с использованием криптографии с открытым ключом (т.е. с использованием алгоритмов RSA, DSS и т.д.). Эта аутентификация может быть необязательной, но обычно требуется по крайней мере для сервера.Переговоры о разделяемом секрете безопасны, т.е. этот общий секрет невозможно подсмотреть.Переговоры о разделяемом секрете надежны, если выполнена аутентификация хотя бы одной из сторон. В таком случае атакующий, расположенный в середине соединения, не может модифицировать передаваемый секрет незаметно для участников соединения.
Одно из преимуществ TLS состоит в том, что он независим от прикладного протокола. Протоколы более высокого уровня могут прозрачно располагаться выше протокола TLS.
Данная функциональность позволяет избежать посылки CRL в определенных сетях и тем самым сократить трафик.
Для того чтобы поддерживать перечисленные выше расширения, вводятся дополнительные механизмы для сообщений Hello клиента и сервера.
Описываемые расширения могут использоваться клиентами TLS 1.0 и серверами TLS 1.0. Расширения поддерживают обратную совместимость – это означает, что клиенты TLS 1.0, которые поддерживают расширения, могут общаться с серверами TLS 1.0, не поддерживающими расширения, и наоборот.
Обратная совместимость достигается следующим образом.
Клиент запрашивает использование расширений с помощью расширенного сообщения Client Hello, описанного ниже. TLS 1.0 требует, чтобы серверы принимали расширенные сообщения Client Hello, даже если они не понимают расширения.Для описанных здесь конкретных расширений не требуется обязательного ответа сервера, если клиент запрашивает расширенную функциональность.
Однако заметим, что хотя обратная совместимость поддерживается, некоторые клиенты из-за своих ограниченных возможностей могут не устанавливать соединения с серверами, которые не поддерживают расширения.
Рассмотрим дополнительные функциональности в следующем порядке. Сначала опишем общие механизмы расширений для сообщений Рукопожатия Client Hello и Server Hello. Далее опишем конкретные расширения для TLS 1.0 и новые сообщения об ошибках при использовании расширений TLS.
Вычисление ключей
Протокол Записи использует следующий алгоритм для создания ключей, инициализационных векторов и секретов МАС из параметров безопасности, создаваемых протоколом Рукопожатия.
Из мастер-секрета с использованием хэш-функций создается последовательность байтов, которая представляет собой МАС-секреты, ключи и инициализационные вектора: client write MAC secret, server write MAC secret, client write key, server write key, client write IV и server write IV. Если некоторое значение не используется, то оно является пустым.
Для создания ключа вычисляется:
key_block = PRF ( SecurityParameters.master_secret, "key expansion", SecurityParameters.server_random + SecurityParameters.client_random);
Вычисления производятся до тех пор, пока не получится выход заданной длины. Затем key_block разбивается на блоки для получения требуемых ключей следующим образом:
client_write_MAC_secret [ SecurityParameters.hash_size] server_write_MAC_secret [ SecurityParameters.hash_size] client_write_key [ SecurityParameters.key_material_length] server_write_key [ SecurityParameters.key_material_length] client_write_IV [SecurityParameters.IV_size] server_write_IV [SecurityParameters.IV_size]
client_write_IV и server_write_IV создаются только для неэкспортируемых блочных алгоритмов. Для экспортируемых блочных алгоритмов инициализационные вектора создаются другим способом. После выполнения данных вычислений вся информация о мастер-секрете и key_block сбрасывается.
Для экспортируемых алгоритмов шифрования (для которых CipherSpec.is_exportable есть true) требуется дополнительное вычисление ключей записи:
final_client_write_key = PRF (SecurityParameters.client_write_key, "client write key", SecurityParameters.client_random + SecurityParameters.server_random); final_server_write_key = PRF (SecurityParameters.server_write_key, "server write key", SecurityParameters.client_random + SecurityParameters.server_random);
Для экспортируемых алгоритмов шифрования инициализационные вектора вычисляются следующим образом:
iv_block = PRF ("", "IV block", SecurityParameters.client_random + SecurityParameters.server_random);
IV_block разделяется на два инициализационных вектора аналогично key_block:
client_write_IV [SecurityParameters.IV_size] server_write_IV [SecurityParameters.IV_size]
Заметим, что в данном случае PRF используется без секрета: это означает, что секрет имеет нулевую длину и на результат вычисления PRF не влияет.
Вычисление мастер-секрета
Независимо от методов обмена ключа используется следующий алгоритм для преобразования премастер-секрета в мастер-секрет. Премастер секрет должен быть сброшен после того, как вычислен мастер-секрет.
master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random) [0..47];
Длина мастер-секрета всегда равна 48 байтам. Длина премастер-секрета изменяется в зависимости от метода обмена ключа.
RSA
Когда для аутентификации сервера и обмена ключа используется RSA, клиентом создается 48-байтный премастер-секрет, зашифрованный открытым ключом сервера, и посылается серверу. Сервер использует свой закрытый ключ для дешифрования премастер-секрета. Затем оба участника преобразуют премастер-секрет в мастер-секрет, как описано выше.
Диффи-Хеллман
Выполняются обычные вычисления Диффи-Хеллмана. Полученный ключ используется в качестве премастер-секрета для преобразования в мастер-секрет, как описано выше.
Запрос сертификата
Неанонимный сервер может дополнительно запросить сертификат клиента, если это соответствует политике безопасности сервера. Это сообщение, если оно послано, должно следовать сразу же за сообщением Server Key Exchange, если оно послано; в противном случае – за сообщением Server Certificate.
Следует помнить, что запрос идентификации клиента от анонимного сервера является фатальным handshake_failure Alert.
Запрос статуса сертификата
Клиенты, имеющие ограничения, могут захотеть использовать протокол статуса сертификата, такой как OCSP, для проверки действительности сертификатов сервера, чтобы избежать передачи CRLs и тем самым сохранить ширину полосы пропускания в ограниченных сетях.
Для указания возможности получения информации о статусе сертификата клиенты включают расширение типа status_request в Client Hello. Поле extension_data должно содержать CertificateStatusRequest, где:
struct { CertificateStatusType status_type; select (status_type) { case ocsp: OCSPStatusRequest; } request; } CertificateStatusRequest; enum {ocsp(1), (255)} CertificateStatusType; struct { ResponderID responder_id_list<0..2^16-1>; Extensions request_extensions; } OCSPStatusRequest; opaque ResponderID<1..2^16-1>; opaque Extensions<0..2^16-1>;
В OCSPStatusRequest ResponderIDs указывает список отвечающих OCSP, которым доверяет клиент. Последовательность responder_id_list нулевой длины имеет специальное значение, указывающее, что отвечающие неявно известны серверу, например предварительно согласованы. Extensions являются DER-представлением расширений запроса OCSP.
Оба типа ResponderID и Extensions определены в OCSP. Extensions взято из PKI. Значение request_extension нулевой длины означает, что никаких расширений нет.
Сервер, получивший Client Hello с расширением status_request, может вернуть соответствующий статус сертификата вместе со своим сертификатом. При запросе OCSP следует использовать информацию, содержащуюся в расширении, и включать request_extensions в запрос OCSP.
Сервер возвращает ответ сертификата вместе со своим сертификатом, посылая сообщение CertificateStatus сразу после сообщения Certificate (и перед любым из сообщений ServerKeyExchange или CertificateRequest). Если сервер вернул сообщение CertificateStatus, он должен включить расширение типа status_request с пустым extension_data в расширенный Server Hello.
struct { CertificateStatusType status_type; select (status_type) { case ocsp: OCSPResponse; } response; } CertificateStatus; opaque OCSPResponse<1..2^24-1>;
ocsp_response содержит полный OCSP-ответ в DER-представлении. Заметим, что может быть послан только один OCSP-ответ.
Сообщение CertificateStatus передается с использованием сообщения Рукопожатия типа certificate_status.
Заметим, что сервер может решить не посылать сообщение CertificateStatus, даже если он получил расширение status_request в сообщении Client Hello.
Наконец заметим, что сервер не должен посылать сообщение CertificateStatus, если он не получил расширение status_request в сообщении Client Hello.
Клиенты, запрашивающие OCSP-ответ и получающие его в сообщении CertificateStatus, должны проверять OCSP-ответ и прерывать Рукопожатие, если ответ не является удовлетворительным.
Защита полезной информации записи
Функции шифрования и МАС преобразуют TLSCompressed-структуру в TLSCiphertext. Функции дешифрования выполняют обратные преобразования. Применение МАС включает последовательный номер, поэтому потерю или повтор сообщений всегда можно обнаружить.
struct { ContentType type; ProtocolVersion version; uint16 length; select (CipherSpec.cipher_type) { case stream: GenericStreamCipher; case block: GenericBlockCipher; } fragment; } TLSCiphertext;
МАС выполняется перед шифрованием. Потоковый шифратор шифрует весь блок, включая МАС. Если CipherSuite есть TLS_NULL_WITH_NULL_NULL, то шифрование состоит из тождественной операции, т.е. данные не шифруются и МАС не используется. TLSCiphertext.length есть сумма TLSCompressed.length и CipherSpec.hash_size.
Для блочных алгоритмов функции шифрования и МАС преобразуют TLSCompressed.fragment-структуру из блоков TLSCiphertext.fragment-структур.
Длина зашифрованных данных (TLSCiphertext.length) есть сумма TLSCompressed.length, CipherSpec.hash_size и padding_length.
Рассмотрим пример: если длина содержимого (TLSCompressed.length) равна 62 байтам и длина МАС равна 20 байтам, то длина перед добавлением равна 82 байтам. Таким образом, если длина блока равна 8 байтам, то длина добавления должна быть равна 6, чтобы общая длина была кратна 8. Длина добавления может быть 6, 14, 22 и т.д. до 254. Если добавление было сделано минимально необходимым, то добавляется 6 байтов, каждый из которых содержит значение 6.
Для блочных алгоритмов для первой записи при определении параметров безопасности создается инициализационный вектор (IV). IV для следующих записей является последним зашифрованным блоком предыдущей записи.