PDA

View Full Version : Qt and TLSv1.3 with PSK



bibhukalyana
8th August 2021, 13:16
Hi Everyone,

Now I am trying to write a sample server and client application which will use TLSv1.3 with PSK based authentication.
But it is failing during handshake process. During client Hello PSK identity/key is not shared from client side and this is causing the issue.

Error on server is:


Error during SSL handshake: error:14201076:SSL routines:tls_choose_sigalg:no suitable signature algorithm" local: "tcps://127.0.0.1:xxxxx/" remote: "tcps://127.0.0.1:xxxxx/" peer verify name: ""


Client code:



QSslConfiguration sslConfiguration;
sslConfiguration.setPeerVerifyMode(QSslSocket::Ver ifyNone);
//sslConfiguration.setProtocol(QSsl::TlsV1_3); //not required default will be TLSv1.3

sslSocket.setSslConfiguration(sslConfiguration);

QObject::connect(&sslSocket, &QSslSocket::preSharedKeyAuthenticationRequired,
this,
[](QSslPreSharedKeyAuthenticator* authenticator)
{
authenticator->setIdentity("xxxx");
authenticator->setPreSharedKey(QByteArrayLiteral("xxxx"));
}
, Qt::DirectConnection);

sslSocket.connectToHostEncrypted("127.0.0.1", 1234);
if (!sslSocket.waitForEncrypted()) {
qDebug() << sslSocket.errorString();
}



server code:


QSslSocket* sslSocket = qobject_cast<QSslSocket*>(nextPendingConnection()); //just added for reference. it will be part of SSLQTcpServer

QSslConfiguration sslConfiguration;
sslConfiguration.setPeerVerifyMode(QSslSocket::Ver ifyNone);
//sslConfiguration.setProtocol(QSsl::TlsV1_3); //not required default will be TLSv1.3

connect(sslSocket, &QSslSocket::preSharedKeyAuthenticationRequired,
this,
[](QSslPreSharedKeyAuthenticator* authenticator)
{
//QByteArray expectedClientId { xxxxx };
if (expectedClientId == authenticator->identity())
{
authenticator->setPreSharedKey(QByteArrayLiteral(xxxx));
}
}, Qt::DirectConnection);

sslSocket->setSslConfiguration(sslConfiguration);
sslSocket->startServerEncryption();



I tried a lot to figure out the error. But did not get anything. Then I looked into the Qt source code to know what is happening.
I found for TLSv1.3 'q_SSL_set_psk_use_session_callback' is used to register the PSK callback.



//qsslsocket_openssl.cpp
#if OPENSSL_VERSION_NUMBER >= 0x10101006L
// Set the client callback for TLSv1.3 PSK
if (mode == QSslSocket::SslClientMode
&& QSslSocket::sslLibraryBuildVersionNumber() >= 0x10101006L) {
q_SSL_set_psk_use_session_callback(ssl, &q_ssl_psk_use_session_callback); // <--
}
#endif // openssl version >= 0x10101006L


and inside 'q_ssl_psk_use_session_callback' 'q_SSL_set_psk_client_callback' is used to register 'q_ssl_psk_restore_client'.
'q_ssl_psk_restore_client' again used 'q_SSL_set_psk_client_callback' to register 'q_ssl_psk_client_callback'.



//q_ssl_psk_use_session_callback()

// Temporarily rebind the psk because it will be called next. The function will restore it.
q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_restore_client); // <--

return 1; // need to return 1 or else "the connection setup fails."




//q_ssl_psk_restore_client()

q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);


As per my understanding:
During handshake process openssl will call 'q_ssl_psk_use_session_callback' and then it will call 'q_ssl_psk_restore_client' as a fallback. But still it will not get the actual key and it will ignore.

In 'q_ssl_psk_use_session_callback' method instead of 'q_ssl_psk_restore_client' if ' q_ssl_psk_client_callback' is registered then everything will work as expected.


So now I want to know
Is my understanding correct and it is a bug in Qt? If not then what is missing in my side? How can I fix it?

I am using Qt 5.15.2 and it is built with openssl version "OpenSSL 1.1.1g". OS is Ubuntu 18.04.

Thanks,
Bibhu

bibhukalyana
9th August 2021, 14:43
A bug is created.
https://bugreports.qt.io/browse/QTBUG-95670
https://bugreports.qt.io/browse/QTBUG-67463