QCryptographicHash: move EVP struct into the contexts union

... making it just another context.

Well, except the EVP struct has non-trivial SMFs, so adding it to the
union deletes all the union's SMFs, too. To restore them, we need to
give the union a class name (State). Since we anyway need to provide
ctors, inline all init() functions into them.

State having a ctor means we need to call it, with the method
argument, in the Private ctor-init-list. That requires the State
member to have a name.

Since the union thus no longer defines variant members within Private,
move most of the functions that operated on the variant members into
State or EVP to avoid having to sprinkle state./evp.-prefixes all over
the code.

This gives the opportunity to re-share some code that was duplicated
when we dragged #ifdef USING_OPENSSL3 out of the functions into
namespace scope. The move of the functions into State robs them of
their access to other Private members, to wit, 'method' and 'result',
so we have to pass them as arguments now.

I tried to split this up into smaller patches, but it kinda has to
happen all at once, sorry.

Pick-to: 6.5
Change-Id: If864d4d46075d00420f6e849cd68c4b824c1a50a
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
bb10
Marc Mutz 2023-02-24 14:47:51 +01:00
parent b1919f01c8
commit e80fc16cec
1 changed files with 80 additions and 40 deletions

View File

@ -296,13 +296,14 @@ class QCryptographicHashPrivate
{
public:
explicit QCryptographicHashPrivate(QCryptographicHash::Algorithm method) noexcept
: method(method)
: state(method), method(method)
{
init();
reset();
}
~QCryptographicHashPrivate()
{
state.destroy(method);
}
void init();
void reset() noexcept;
void addData(QByteArrayView bytes) noexcept;
bool addData(QIODevice *dev);
@ -330,18 +331,30 @@ public:
struct EVP {
EVP_MD_ptr algorithm;
EVP_MD_CTX_ptr context;
bool initializationFailed = false;
bool initializationFailed;
void init(QCryptographicHash::Algorithm method);
explicit EVP(QCryptographicHash::Algorithm method);
void reset() noexcept;
void finalizeUnchecked(HashResult &result) noexcept;
} evp;
};
#endif
union {
union State {
explicit State(QCryptographicHash::Algorithm method);
void destroy(QCryptographicHash::Algorithm method);
#ifdef USING_OPENSSL30
~State() {}
#endif
void reset(QCryptographicHash::Algorithm method) noexcept;
void addData(QCryptographicHash::Algorithm method, QByteArrayView data) noexcept;
void finalizeUnchecked(QCryptographicHash::Algorithm method, HashResult &result) noexcept;
Sha1State sha1Context;
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
#ifndef USING_OPENSSL30
#ifdef USING_OPENSSL30
EVP evp;
#else
MD5Context md5Context;
md4_context md4Context;
SHA224Context sha224Context;
@ -349,21 +362,14 @@ public:
SHA384Context sha384Context;
SHA512Context sha512Context;
SHA3Context sha3Context;
enum class Sha3Variant { Sha3, Keccak };
void sha3Finish(HashResult &result, int bitCount, Sha3Variant sha3Variant);
#endif
blake2b_state blake2bContext;
blake2s_state blake2sContext;
#endif
};
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
#ifndef USING_OPENSSL30
enum class Sha3Variant
{
Sha3,
Keccak
};
void sha3Finish(int bitCount, Sha3Variant sha3Variant);
#endif
#endif
} state;
// protects result in finalize()
QBasicMutex finalizeMutex;
HashResult result;
@ -373,7 +379,8 @@ public:
#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
#ifndef USING_OPENSSL30
void QCryptographicHashPrivate::sha3Finish(int bitCount, Sha3Variant sha3Variant)
void QCryptographicHashPrivate::State::sha3Finish(HashResult &result, int bitCount,
Sha3Variant sha3Variant)
{
/*
FIPS 202 §6.1 defines SHA-3 in terms of calculating the Keccak function
@ -539,27 +546,38 @@ QCryptographicHash::Algorithm QCryptographicHash::algorithm() const noexcept
#ifdef USING_OPENSSL30
void QCryptographicHashPrivate::init()
QCryptographicHashPrivate::State::State(QCryptographicHash::Algorithm method)
{
if (method == QCryptographicHash::Blake2b_160 ||
method == QCryptographicHash::Blake2b_256 ||
method == QCryptographicHash::Blake2b_384) {
new (&blake2bContext) blake2b_state;
reset(method);
} else if (method == QCryptographicHash::Blake2s_128 ||
method == QCryptographicHash::Blake2s_160 ||
method == QCryptographicHash::Blake2s_224) {
new (&blake2sContext) blake2s_state;
reset(method);
} else {
evp.init(method);
new (&evp) EVP(method);
}
}
void QCryptographicHashPrivate::EVP::init(QCryptographicHash::Algorithm method)
void QCryptographicHashPrivate::State::destroy(QCryptographicHash::Algorithm method)
{
Q_ASSERT(!context);
initializationFailed = true;
if (method != QCryptographicHash::Blake2b_160 &&
method != QCryptographicHash::Blake2b_256 &&
method != QCryptographicHash::Blake2b_384 &&
method != QCryptographicHash::Blake2s_128 &&
method != QCryptographicHash::Blake2s_160 &&
method != QCryptographicHash::Blake2s_224) {
evp.~EVP();
}
}
QCryptographicHashPrivate::EVP::EVP(QCryptographicHash::Algorithm method)
: initializationFailed{true}
{
if (method == QCryptographicHash::Md4) {
/*
* We need to load the legacy provider in order to have the MD4
@ -592,7 +610,7 @@ void QCryptographicHashPrivate::EVP::init(QCryptographicHash::Algorithm method)
#else // USING_OPENSSL30
void QCryptographicHashPrivate::init()
QCryptographicHashPrivate::State::State(QCryptographicHash::Algorithm method)
{
switch (method) {
case QCryptographicHash::Sha1:
@ -648,15 +666,25 @@ void QCryptographicHashPrivate::init()
case QCryptographicHash::NumAlgorithms:
Q_UNREACHABLE();
}
reset(method);
}
void QCryptographicHashPrivate::State::destroy(QCryptographicHash::Algorithm)
{
static_assert(std::is_trivially_destructible_v<State>); // so nothing to do here
}
#endif // !USING_OPENSSL30
#ifdef USING_OPENSSL30
void QCryptographicHashPrivate::reset() noexcept
{
result.clear();
state.reset(method);
}
#ifdef USING_OPENSSL30
void QCryptographicHashPrivate::State::reset(QCryptographicHash::Algorithm method) noexcept
{
if (method == QCryptographicHash::Blake2b_160 ||
method == QCryptographicHash::Blake2b_256 ||
method == QCryptographicHash::Blake2b_384) {
@ -684,9 +712,8 @@ void QCryptographicHashPrivate::EVP::reset() noexcept
#else // USING_OPENSSL30
void QCryptographicHashPrivate::reset() noexcept
void QCryptographicHashPrivate::State::reset(QCryptographicHash::Algorithm method) noexcept
{
result.clear();
switch (method) {
case QCryptographicHash::Sha1:
sha1InitState(&sha1Context);
@ -771,9 +798,16 @@ void QCryptographicHash::addData(QByteArrayView bytes) noexcept
d->addData(bytes);
}
void QCryptographicHashPrivate::addData(QByteArrayView bytes) noexcept
{
state.addData(method, bytes);
result.clear();
}
#ifdef USING_OPENSSL30
void QCryptographicHashPrivate::addData(QByteArrayView bytes) noexcept
void QCryptographicHashPrivate::State::addData(QCryptographicHash::Algorithm method,
QByteArrayView bytes) noexcept
{
const char *data = bytes.data();
auto length = bytes.size();
@ -791,12 +825,12 @@ void QCryptographicHashPrivate::addData(QByteArrayView bytes) noexcept
EVP_DigestUpdate(evp.context.get(), (const unsigned char *)data, length);
}
}
result.clear();
}
#else // USING_OPENSSL30
void QCryptographicHashPrivate::addData(QByteArrayView bytes) noexcept
void QCryptographicHashPrivate::State::addData(QCryptographicHash::Algorithm method,
QByteArrayView bytes) noexcept
{
const char *data = bytes.data();
auto length = bytes.size();
@ -865,7 +899,6 @@ void QCryptographicHashPrivate::addData(QByteArrayView bytes) noexcept
Q_UNREACHABLE();
}
}
result.clear();
}
#endif // !USING_OPENSSL30
@ -945,8 +978,14 @@ void QCryptographicHashPrivate::finalize() noexcept
Must be called with finalizeMutex held (except from static hash() function,
where no sharing can take place).
*/
#ifdef USING_OPENSSL30
void QCryptographicHashPrivate::finalizeUnchecked() noexcept
{
state.finalizeUnchecked(method, result);
}
#ifdef USING_OPENSSL30
void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
HashResult &result) noexcept
{
if (method == QCryptographicHash::Blake2b_160 ||
method == QCryptographicHash::Blake2b_256 ||
@ -979,7 +1018,8 @@ void QCryptographicHashPrivate::EVP::finalizeUnchecked(HashResult &result) noexc
#else // USING_OPENSSL30
void QCryptographicHashPrivate::finalizeUnchecked() noexcept
void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
HashResult &result) noexcept
{
switch (method) {
case QCryptographicHash::Sha1: {
@ -1035,14 +1075,14 @@ void QCryptographicHashPrivate::finalizeUnchecked() noexcept
case QCryptographicHash::RealSha3_256:
case QCryptographicHash::RealSha3_384:
case QCryptographicHash::RealSha3_512: {
sha3Finish(8 * hashLengthInternal(method), Sha3Variant::Sha3);
sha3Finish(result, 8 * hashLengthInternal(method), Sha3Variant::Sha3);
break;
}
case QCryptographicHash::Keccak_224:
case QCryptographicHash::Keccak_256:
case QCryptographicHash::Keccak_384:
case QCryptographicHash::Keccak_512: {
sha3Finish(8 * hashLengthInternal(method), Sha3Variant::Keccak);
sha3Finish(result, 8 * hashLengthInternal(method), Sha3Variant::Keccak);
break;
}
case QCryptographicHash::Blake2b_160: