Source code

Revision control

Copy as Markdown

// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qcoapsecurityconfiguration.h"
#include <QtCore/QByteArray>
#include <QtCore/QIODevice>
#include <QtCore/QList>
#include <QtNetwork/QSslCertificate>
QT_BEGIN_NAMESPACE
class QCoapPrivateKeyPrivate : public QSharedData
{
public:
QByteArray key;
Qt::HANDLE opaqueKey = nullptr;
QSsl::KeyAlgorithm algorithm = QSsl::Opaque;
QSsl::EncodingFormat encodingFormat;
QByteArray passPhrase;
};
class QCoapSecurityConfigurationPrivate : public QSharedData
{
public:
QByteArray identity;
QByteArray preSharedKey;
QString defaultCipherString;
QList<QSslCertificate> caCertificates;
QList<QSslCertificate> localCertificateChain;
QCoapPrivateKey privateKey;
};
/*!
\class QCoapPrivateKey
\inmodule QtCoap
\brief The QCoapPrivateKey class provides an interface for managing
CoAP security keys.
A QCoapPrivateKey packages a private key used in negotiating CoAP connections
securely. It holds the information required for authentication using
\c pre-shared keys and X.509 certificates.
\section1 Security Considerations
QCoapPrivateKey stores the private key and its passphrase internally using
general-purpose data types (QByteArray) that do not guarantee secure erasure
of their contents from memory on destruction. This material may persist in
freed heap pages, core dumps, swap files, or process memory after a
QCoapPrivateKey object is destroyed or cleared. Because QByteArray is
implicitly shared, copies of the key or passphrase may exist in several
locations and cannot be wiped deterministically.
Where the security back-end supports it, constructing the key from a native
handle (the \c{Qt::HANDLE} overload) keeps the key material outside Qt's
general-purpose containers. Applications with strict requirements for
credential hygiene should take this into account when deciding how and where
to use QCoapPrivateKey.
*/
/*!
\fn void QCoapPrivateKey::swap(QCoapPrivateKey &other)
Swaps this private key with \a other. This operation is very fast and never fails.
*/
/*!
Constructs an empty instance of QCoapPrivateKey.
*/
QCoapPrivateKey::QCoapPrivateKey()
: d(new QCoapPrivateKeyPrivate)
{
}
/*!
Constructs a QCoapPrivateKey from the byte array \a key using
the specified \a algorithm and encoding \a format.
If the key is encrypted then \a passPhrase is required to decrypt it.
*/
QCoapPrivateKey::QCoapPrivateKey(const QByteArray &key, QSsl::KeyAlgorithm algorithm,
QSsl::EncodingFormat format, const QByteArray &passPhrase)
: d(new QCoapPrivateKeyPrivate)
{
d->key = key;
d->opaqueKey = nullptr;
d->algorithm = algorithm;
d->encodingFormat = format;
d->passPhrase = passPhrase;
}
/*!
Constructs a QCoapPrivateKey from a native key \a handle.
*/
QCoapPrivateKey::QCoapPrivateKey(const Qt::HANDLE &handle)
: d(new QCoapPrivateKeyPrivate)
{
d->opaqueKey = handle;
d->algorithm = QSsl::Opaque;
}
/*!
Copies the contents of \a other into this key, making the two keys
identical.
*/
QCoapPrivateKey::QCoapPrivateKey(const QCoapPrivateKey &other)
: d(other.d)
{
}
/*!
Move-constructs a QCoapPrivateKey, making it point to the same
object as \a other was pointing to.
*/
QCoapPrivateKey::QCoapPrivateKey(QCoapPrivateKey &&other) noexcept
: d(other.d)
{
other.d = nullptr;
}
/*!
Releases any resources held by QCoapPrivateKey.
*/
QCoapPrivateKey::~QCoapPrivateKey()
{
}
/*!
Copies the contents of \a other into this key, making the two keys
identical.
Returns a reference to this QCoapPrivateKey.
*/
QCoapPrivateKey &QCoapPrivateKey::operator=(const QCoapPrivateKey &other)
{
d = other.d;
return *this;
}
/*!
Returns \c true if the private key is null, returns \c false otherwise.
*/
bool QCoapPrivateKey::isNull() const
{
return d->algorithm == QSsl::Opaque ? !d->opaqueKey : d->key.isEmpty();
}
/*!
Returns the encoded private key.
*/
QByteArray QCoapPrivateKey::key() const
{
return d->key;
}
/*!
Returns a pointer to the native key handle.
*/
Qt::HANDLE QCoapPrivateKey::handle() const
{
return d->opaqueKey;
}
/*!
Returns the key algorithm.
*/
QSsl::KeyAlgorithm QCoapPrivateKey::algorithm() const
{
return d->algorithm;
}
/*!
Returns the encoding format of the key.
*/
QSsl::EncodingFormat QCoapPrivateKey::encodingFormat() const
{
return d->encodingFormat;
}
/*!
Returns the passphrase for the key.
*/
QByteArray QCoapPrivateKey::passPhrase() const
{
return d->passPhrase;
}
/*!
\class QCoapSecurityConfiguration
\inmodule QtCoap
\brief The QCoapSecurityConfiguration class holds configuration
options during the authentication process.
It holds information such as client identity, pre shared key, information
about certificates, and so on.
\section1 Security Considerations
QCoapSecurityConfiguration stores sensitive credential material, such as the
pre-shared key, the pre-shared key identity, and the private key, internally
using general-purpose data types (QByteArray, QString) that do not guarantee
secure erasure of their contents from memory on destruction. This material
may persist in freed heap pages, core dumps, swap files, or process memory
after a QCoapSecurityConfiguration object is destroyed or cleared. Because
these types are implicitly shared, copies of the same secret may exist in
several locations and cannot be wiped deterministically.
Provisioning, rotation, and storage of credential material are the
responsibility of the application. Applications with strict requirements for
credential hygiene should take this into account when deciding how and where
to use QCoapSecurityConfiguration.
\sa QCoapPrivateKey
*/
/*!
\fn void QCoapSecurityConfiguration::swap(QCoapSecurityConfiguration &other)
Swaps this security configuration with \a other. This operation is very fast
and never fails.
*/
/*!
Constructs a new QCoapSecurityConfiguration.
*/
QCoapSecurityConfiguration::QCoapSecurityConfiguration()
: d(new QCoapSecurityConfigurationPrivate)
{
}
/*!
Copies the configuration and state of \a other.
*/
QCoapSecurityConfiguration::QCoapSecurityConfiguration(const QCoapSecurityConfiguration &other)
: d(other.d)
{
}
/*!
Move-constructs a QCoapSecurityConfiguration, making it point to the same
object as \a other was pointing to.
*/
QCoapSecurityConfiguration::QCoapSecurityConfiguration(
QCoapSecurityConfiguration &&other) noexcept
: d(other.d)
{
other.d = nullptr;
}
/*!
Copies the configuration and state of \a other.
*/
QCoapSecurityConfiguration &QCoapSecurityConfiguration::operator=(
const QCoapSecurityConfiguration &other)
{
d = other.d;
return *this;
}
/*!
Releases any resources held by QCoapSecurityConfiguration.
*/
QCoapSecurityConfiguration::~QCoapSecurityConfiguration()
{
}
/*!
Sets the PSK client identity (to be advised to the server) to \a identity.
\sa preSharedKeyIdentity()
*/
void QCoapSecurityConfiguration::setPreSharedKeyIdentity(const QByteArray &identity)
{
d->identity = identity;
}
/*!
Returns the PSK client identity.
\sa setPreSharedKeyIdentity()
*/
QByteArray QCoapSecurityConfiguration::preSharedKeyIdentity() const
{
return d->identity;
}
/*!
Sets the pre shared key to \a preSharedKey.
\sa preSharedKey()
*/
void QCoapSecurityConfiguration::setPreSharedKey(const QByteArray &preSharedKey)
{
d->preSharedKey = preSharedKey;
}
/*!
Returns the pre shared key.
\sa setPreSharedKey()
*/
QByteArray QCoapSecurityConfiguration::preSharedKey() const
{
return d->preSharedKey;
}
/*!
Sets the SSL cipher string to \a cipherString.
The security back-end (for example OpenSSL) might not include ciphers required
for \l{https://tools.ietf.org/html/rfc7252#section-9}{RFC 7252} by default.
This method specifies which ciphers the back-end should use.
For example to enable CCM ciphers required by RFC, "AESCCM" can be passed
as \a cipherString.
{OpenSSL docs} for more information about cipher strings.
\sa defaultCipherString()
*/
void QCoapSecurityConfiguration::setDefaultCipherString(const QString &cipherString)
{
d->defaultCipherString = cipherString;
}
/*!
Returns the default cipher string.
\sa setDefaultCipherString()
*/
QString QCoapSecurityConfiguration::defaultCipherString() const
{
return d->defaultCipherString;
}
/*!
Sets \a certificates as the certificate authority database for the connection.
\sa caCertificates()
*/
void QCoapSecurityConfiguration::setCaCertificates(const QList<QSslCertificate> &certificates)
{
d->caCertificates = certificates;
}
/*!
Returns this connection's certificate authority certificate database.
\sa setCaCertificates()
*/
QList<QSslCertificate> QCoapSecurityConfiguration::caCertificates() const
{
return d->caCertificates;
}
/*!
Sets \a localChain as the certificate chain to present to the peer
during the handshake.
\sa localCertificateChain()
*/
void QCoapSecurityConfiguration::setLocalCertificateChain(const QList<QSslCertificate> &localChain)
{
d->localCertificateChain = localChain;
}
/*!
Returns the certificate chain to be presented to the peer during the handshake.
\sa setLocalCertificateChain()
*/
QList<QSslCertificate> QCoapSecurityConfiguration::localCertificateChain() const
{
return d->localCertificateChain;
}
/*!
Sets the connection's private key to \a key.
\sa privateKey(), setLocalCertificateChain()
*/
void QCoapSecurityConfiguration::setPrivateKey(const QCoapPrivateKey &key)
{
d->privateKey = key;
}
/*!
Returns the private key assigned to the connection.
\sa setPrivateKey(), localCertificateChain()
*/
QCoapPrivateKey QCoapSecurityConfiguration::privateKey() const
{
return d->privateKey;
}
QT_END_NAMESPACE