Topic: [C++] WolfSSL + Qt
Hello everyone!
I was write a simple SSL-client/server in Visual Studio, using WolfSSL. It work fine.
For now I try to write a simple SSL server, using Qt and based on QTcpServer.
But I didn't find any information about WolfSSL + Qt.
There is source code:
SslServer.h
#ifndef SSLSERVER_H
#define SSLSERVER_H
#include <QTcpServer>
#define WC_NO_HARDEN
#include <wolfssl/ssl.h>
#define CERT_SERVER_CERT "Certs\\server-cert.pem"
#define CERT_SERVER_KEY "Certs\\server-key.pem"
#define CERT_SERVER_DH "Certs\\dh2048.pem"
class SslServer : public QTcpServer
{
Q_OBJECT
public:
explicit SslServer(QObject* parent = nullptr);
virtual ~SslServer() override;
protected:
virtual void incomingConnection(qintptr socketDescriptor) override final;
private:
WOLFSSL_CTX* m_CTX;
};
#endif // SSLSERVER_H
SslServer.cpp
#include "SslServer.h"
#include "SslSocket.h"
#include <QDebug>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "AdvAPI32.lib")
SslServer::SslServer(QObject* parent) :
QTcpServer(parent),
m_CTX(nullptr)
{
WSADATA wsa_data = { 0 };
WSAStartup(MAKEWORD(2, 0), &wsa_data);
wolfSSL_Init();
m_CTX = wolfSSL_CTX_new(wolfTLSv1_2_server_method());
if (m_CTX)
{
if (wolfSSL_CTX_use_certificate_file(m_CTX, CERT_SERVER_CERT, SSL_FILETYPE_PEM) == SSL_SUCCESS)
{
if (wolfSSL_CTX_use_PrivateKey_file(m_CTX, CERT_SERVER_KEY, SSL_FILETYPE_PEM) == SSL_SUCCESS)
{
if (wolfSSL_CTX_SetTmpDH_file(m_CTX, CERT_SERVER_DH, SSL_FILETYPE_PEM) == SSL_SUCCESS)
{
qDebug() << "SslServer::SslServer -> init SSL is OK";
}
}
}
}
}
SslServer::~SslServer()
{
if (m_CTX)
{
wolfSSL_CTX_free(m_CTX);
m_CTX = nullptr;
}
wolfSSL_Cleanup();
WSACleanup();
}
void SslServer::incomingConnection(qintptr socketDescriptor)
{
qDebug() << "SslServer::incomingConnection";
SslSocket* sock = new SslSocket(this);
WOLFSSL* ssl = wolfSSL_new(m_CTX);
if (ssl)
{
wolfSSL_set_fd(ssl, socketDescriptor);
for (;;)
{
// loop because accept didn't work immediately
int r = wolfSSL_accept(ssl);
if (r == -1)
{
r = wolfSSL_get_error(ssl, r);
if (r == SSL_ERROR_WANT_READ)
{
Sleep(10);
continue;
}
}
break;
}
sock->setSocketDescriptor(socketDescriptor);
sock->SetSSL(ssl);
qDebug() << "SslServer::incomingConnection -> make SSL socket";
}
this->addPendingConnection(sock);
}
Then I was write SSLSocket
There is source code:
SslSocket.h
#ifndef SslSocket_H
#define SslSocket_H
#include <QTcpSocket>
#define WC_NO_HARDEN
#include <wolfssl/ssl.h>
class SslSocket : public QTcpSocket
{
Q_OBJECT
public:
explicit SslSocket(QObject* parent = nullptr);
virtual ~SslSocket() override;
void SetSSL(WOLFSSL* ssl);
qint64 read(char* data, qint64 maxlen);
QByteArray read(qint64 maxlen);
qint64 write(const char* data, qint64 len);
private:
WOLFSSL* m_SSL;
};
#endif // SslSocket_H
SslSocket.cpp
#include "SslSocket.h"
#include <QDebug>
SslSocket::SslSocket(QObject* parent) :
QTcpSocket(parent),
m_SSL(nullptr)
{
}
SslSocket::~SslSocket()
{
if (m_SSL)
{
wolfSSL_shutdown(m_SSL);
wolfSSL_free(m_SSL);
m_SSL = nullptr;
}
}
void SslSocket::SetSSL(WOLFSSL* ssl)
{
m_SSL = ssl;
}
qint64 SslSocket::read(char* data, qint64 maxlen)
{
qDebug() << "SslSocket::read 1";
if (m_SSL && data && maxlen > 0)
{
return wolfSSL_read(m_SSL, data, maxlen);
}
return 0;
}
QByteArray SslSocket::read(qint64 maxlen)
{
QByteArray data;
qDebug() << "SslSocket::read 2, SSL = " << m_SSL;
if (m_SSL && maxlen > 0)
{
data.resize(maxlen);
maxlen = wolfSSL_read(m_SSL, (void*)data.data(), maxlen);
if (maxlen > 0)
{
data.resize(maxlen);
}
else
{
data.clear();
}
}
return std::move(data);
}
qint64 SslSocket::write(const char* data, qint64 len)
{
qDebug() << "SslSocket::write";
if (m_SSL && data && len > 0)
{
return wolfSSL_write(m_SSL, data, len);
}
return 0;
}
Server listen port and accept connections is fine.
But a have a problem to receive data from client at this line:
maxlen = wolfSSL_read(m_SSL, (void*)data.data(), maxlen);
Function wolfSSL_read return -1, but method bytesAvailable() in SSLSocket say to there is data to read in socket.
What I do wrong?
How a correct receive data over WolfSSL in Qt?
Thank you!