«ошибка дешифрования» спецификации изменения шифра TLS 1.2, но правильно читает MAC - PullRequest
0 голосов
/ 27 сентября 2018

Я пытаюсь обновить старую реализацию TLS 1.0 (которую я не писал) до уровня TLS 1.2.

В качестве первого шага я интегрировал изменение TLS 1.1 в , поставиввектор инициализации открытого текста в записи .Это не было проблемой.Казалось, что это работает достаточно хорошо, чтобы я мог читать https://example.com в TLS 1.1, а также в SSL Labs viewMyClient.html .

Затем я адаптировал TLS 1.2 к изменению псевдослучайной функции(для большинства практических целей) P_SHA256 вместо (более сложного и причудливого) пополам с половиной MD5 / SHA1 ригамароле .Я сделал это неправильно в первый раз и получил недопустимую ошибку MAC, но это была более или менее опечатка с моей стороны, и я исправил ее.Затем недопустимая ошибка MAC исчезла.

Но, несмотря на это, после отправки сообщений ClientKeyExchange-> ChangeCipherSpec я получаю «Ошибка дешифрования» с сервера (ов) (одно и то же предупреждение независимо от того,, https://google.com или что-нибудь, что я пытаюсь) .Я понял, что сообщение ChangeCipherSpec шифрует только один байт , помещает его в сообщение с заполнением, MAC и т. Д.

Если я случайно настрою MAC на один байт, оно возвращается кжалуется на недействительный MAC. Меня смущает то, что сам MAC зашифрован как часть GenericBlockCipher :

struct {
    opaque IV[SecurityParameters.record_iv_length];
    block-ciphered struct {
        opaque content[TLSCompressed.length];
        opaque MAC[SecurityParameters.mac_length]; // <-- server reads this fine!
        uint8 padding[GenericBlockCipher.padding_length];
        uint8 padding_length;
    };
} GenericBlockCipher;

ОБНОВЛЕНИЕ: FWIW, я добавил журнал Wireshark с ошибкой чтения 1.2 из https://example.com, а также журнал работающей сессии 1.1, выполняющей тот же код, не считая обновления MAC P_SHA256:

http://hostilefork.com/media/shared/stackoverflow/example-com-tls-1.2.pcapng (не удается) http://hostilefork.com/media/shared/stackoverflow/example-com-tls-1.1.pcapng (успешно)

Итак, что именно у него возникают проблемы с расшифровкой?Заполнение кажется правильным, как будто добавляя или вычитая 1 к байту, я получаю недопустимую ошибку MAC. (Спецификация гласит: "Получатель ДОЛЖЕН проверить это заполнение и ДОЛЖЕН использовать предупреждение bad_record_mac, чтобы указать на ошибки заполнения.", Так что этого следовало ожидать.) Если я испортил клиент-iv в сообщении от какогоЯ использовал для шифрования (просто поместил плохой байт в переданную версию), это также дает мне Bad Record MAC.Я ожидаю, что это также разрушит дешифрование.

Так что я озадачен, в чем может быть проблема:

  • Сервер демонстрирует различение действительных MAC-адресов, а не нет, поэтомуон должен расшифровать.Как получается правильный MAC - и - иметь ошибку дешифрования?
  • Набор шифров - старый (TLS_RSA_WITH_AES_256_CBC_SHA), но я просто решаю одну проблему за раз ... и если я не ошибаюсь, это не должно иметь значения.

Есть ли у кого-нибудь с соответствующим опытом теория о том, как TLS 1.2 может бросить ключ в код, который в противном случае работает в TLS 1.1? (Возможно, кто-то, кто сделал подобное обновление для кодовой базы и должен был изменить больше, чем две вещи, которые я изменил, чтобы заставить его работать?) Я пропускаю еще одно важное техническое изменение?Что мне нужно выяснить, что делает сервер несчастным?

Ответы [ 2 ]

0 голосов
/ 01 октября 2018

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

Но что сбивает с толку в журнале Wireshark, так это то, чтоСообщение Finished отображается в той же строке журнала, но под именем "EncryptedHandshakeMessage" Это выглядит как какой-то тег или метка, описывающая ChangeCipherSpec, но это не так.Это сообщение на самом деле вообще не зашифровано.

По второй ссылке:

На практике вы увидите незашифрованный клиент Hello, сервер Hello, сертификат, обмен ключами сервера, запрос сертификата, подтверждение сертификата и ключ клиентаОбмен сообщениями.Сообщение «Готовое рукопожатие» зашифровано, поскольку оно появляется после сообщения «Изменить спецификацию шифра».


«Надеюсь, что кто-то имеет опыт обновления TLS 1.0 или 1.1 до 1.2 и, возможно, видел подобноепроблема из-за того, что вы не изменили больше, чем P_SHA256 MAC, и подняли номер версии "

. Они упоминают только два из трех мест, в которых вам нужно обновить комбинацию MD5 / SHA1 в изменениях "из раздела TLS 1.1 " в RFC 5246:

  • Комбинация MD5 / SHA-1 в псевдослучайной функции (PRF) заменена на спецификацию набора шифровPRFs.Все комплекты шифров в этом документе используют P_SHA256.

  • Комбинация MD5 / SHA-1 в элементе с цифровой подписью была заменена одним хешем.Подписанные элементы теперь включают поле, которое явно указывает используемый алгоритм хеширования.

(Примечание. Второе относится к сертификатам, и если вы еще не получили сертификатпроверяя, что вас еще не было в этот момент.)

В этом разделе они не упоминают о том, что третий помещает изменения комбинации MD5 / SHA-1, чтохеш, используемый в начальном числе для verify_data сообщения Finished.Однако этот пункт также является изменением по сравнению с TLS 1.1, описанным гораздо дальше в документе в разделе 7.4.9 :

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

Для формальной спецификации они немного расплывчаты по «хэшу, используемому в качестве основы для PRF» (это HMAC или просто простой хеш?) Но это простой хеш.Таким образом, SHA256, если в спецификации набора шифров не указано иное.

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


«Какой ресурс мне нужен, чтобы узнать, что делает сервер несчастным?»

YMMV.Но я просто создал OpenSSL как статическую библиотеку отладки и связал ее с простым сервером.Затем я добавил точки останова и контрольно-измерительные приборы, чтобы увидеть, что это было расстроено.( GDB по какой-то причине не разрешал мне входить в общую библиотеку .)

Около 30 сентября 2018 года на обычном Linux-компьютере:

  • git://git.openssl.org/openssl.git
  • ./config no-shared no-asm -g3 -O0 -fno-omit-frame-pointer -fno-inline-functions no-ssl2 no-ssl3
  • make

Простой сервер, который я использовал, пришел с Simple TLS Server .Скомпилируйте со статической библиотекой:

  • gcc -g -O0 simple.c -o simple -lssl -lcrypto -ldl -lpthread

Я следовал инструкциям по генерации сертификатов здесь, но изменил AA на localhost

openSSL подписывает сертификат https_client с CA

Затем я изменил cert.pem => rootCA.pem и key.pem => rootCA.key в простом коде сервера.Я смог сделать:

wget https://localhost:4433 --no-check-certificate

И успешно вернуть test в ответ.Так что тогда было просто посмотреть, где мой клиент вызвал сбой.

0 голосов
/ 27 сентября 2018

Я могу вспомнить две разные ситуации, которые создают эту проблему:

  1. Отправка неверна IV.IV влияет только на 1-й блок при дешифровании в режиме CBC, поэтому, если ваш контент больше 16 байт (AES размер блока), MAC часть ваших данных будет правильно расшифрована.
  2. Если вы используете неправильную структуру заполнения, вы можете получить ошибку при расшифровке (потому что проверка заполнения не удалась), но содержимое будет расшифровано правильно.
...