Revision control

++ // 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