Сбой рукопожатия TLS 1.3 — Клиент сообщает о «Слишком длинном заголовке»

#ssl #openssl #client-side #tls1.3

Вопрос:

Я в процессе обновления клиента для поддержки TLS 1.3. При попытке подключиться к серверу TLS 1.3 клиент сообщает о «Внутренней ошибке». Трассировки Wireshark показывают, что сервер ответил Verify Certificate, Finished сообщением. Но клиенту не удается сгенерировать ключи со следующим стеком вызовов —

  libcrypto-1_1.dll!ASN1_get_object(const unsigned char * * pp, long * plength, int * ptag, int * pclass, long omax) Line 101
 libcrypto-1_1.dll!asn1_item_embed_d2i(ASN1_VALUE_st * * pval, const unsigned char * * in, long len, const ASN1_ITEM_st * it, int tag, int aclass, char opt, ASN1_TLC_st * ctx, int depth) Line 287
 [Inline Frame] libcrypto-1_1.dll!ASN1_item_ex_d2i(ASN1_VALUE_st * *) Line 124
 libcrypto-1_1.dll!ASN1_item_d2i(ASN1_VALUE_st * * pval, const unsigned char * * in, long len, const ASN1_ITEM_st * it) Line 114
 libcrypto-1_1.dll!d2i_X509_SIG(X509_sig_st * * a, const unsigned char * * in, long len) Line 21    
 MyCode.dll!PrivateKeyOperationCallback(ssl_st * pSSL, unsigned int type, unsigned int rsakeysize, const unsigned char * hash, unsigned int hashlen, unsigned char * sig, unsigned int sigmaxlen, unsigned int * siglen)
 [Inline Frame] MyCode.dll!My_RSA_private_encrypt1(ssl_st *)
 MyCode.dll!My_RSA_private_encrypt(int flen, const unsigned char * from, unsigned char * to, rsa_st * rsa, int padding)
 libcrypto-1_1.dll!pkey_rsa_sign(evp_pkey_ctx_st * ctx, unsigned char * sig, unsigned int * siglen, const unsigned char * tbs, unsigned int tbslen) Line 185
 libcrypto-1_1.dll!EVP_PKEY_sign(evp_pkey_ctx_st * ctx, unsigned char * sig, unsigned int * siglen, const unsigned char * tbs, unsigned int tbslen) Line 66
 libcrypto-1_1.dll!EVP_DigestSignFinal(evp_md_ctx_st * ctx, unsigned char * sigret, unsigned int * siglen) Line 148
 libcrypto-1_1.dll!EVP_DigestSign(evp_md_ctx_st * ctx, unsigned char * sigret, unsigned int * siglen, const unsigned char * tbs, unsigned int tbslen) Line 170
 libssl-1_1.dll!tls_construct_cert_verify(ssl_st * s, wpacket_st * pkt) Line 307
 libssl-1_1.dll!write_state_machine(ssl_st * s) Line 843
 libssl-1_1.dll!state_machine(ssl_st * s, int server) Line 443
 libssl-1_1.dll!ossl_statem_connect(ssl_st * s) Line 250
 libssl-1_1.dll!SSL_do_handshake(ssl_st * s) Line 3661
 libssl-1_1.dll!SSL_connect(ssl_st * s) Line 1662
 

ASN1_get_object возвращает «Заголовок слишком длинный». Один и тот же клиент может подключаться к одному и тому же серверу с помощью TLS 1.2 и даже может подключаться к одному и тому же серверу из браузера с помощью TLS 1.3.

Проблема конкретно связана с MTLS (не с TLS).

Комментарии:

1. Вы говорите, что тот же код не работает на 1.3 И может подключиться к 1.3. Вы действительно имели в виду что-то другое, например 1.2?

2. Опечатка. Исправленный.

Ответ №1:

Этот путь кода не является уникальным для TLS 1.3 и присутствует в OpenSSL / libcrypto довольно долгое время.

Ошибка возникает из-за того, что объект ASN.1, закодированный в сертификате, имеет определенную длину, превышающую длину предоставленных данных. Либо данные сертификата повреждены, либо сервер отправляет неверные данные.

Если вы сами внедряете клиент TLS 1.3, возможно, ваш код неправильно обрабатывает шифрование сертификатов, что приводит к отправке искаженных данных в пути кода синтаксического анализа ASN.1. Без дополнительной информации (дампов Wireshark и самого сертификата) невозможно узнать, в чем заключается конкретная ошибка.

Комментарии:

1. Какое шифрование сертификата? Вы имеете в виду создание цифровой подписи?

2. TLS 1.3 шифрует все после сервера. Это включает в себя сертификат. Поведение описано в RFC8446 .

3. Я не вижу здесь никаких свидетельств какого-либо сертификата. ‘MyCode.dll’ вызывается, чтобы сделать ОГА подписания (что OpenSSL для истерика изюма иногда называет RSA_private_encrypt) и почему-то называет d2i_X509_SIG что бы разобрать DigestInfo (не целую CERT) и я не вижу никаких вменяемых причин ОГА подписания нибудь разобрать DigestInfo — за исключением, возможно, он получит закрытый ключ из двух: pkcs12 с Mac. Я бы посмотрел на код в ‘MyCode.dll».

4. На высоком уровне последовательность одинакова, но код TLS 1.3 отличается в нескольких местах, таких как get_cert_verify_tbs_data и в нескольких других местах. Поскольку браузер может подключаться к одному и тому же серверу с помощью TLS 1.3, поэтому меньше шансов, что сервер отправляет поврежденные или неправильные данные. Даже если сервер отправляет неверные данные, браузер справляется с этим хорошо.