Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qcryptographichash.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru>
3// Copyright (C) 2013 Richard J. Moore <rich@kde.org>.
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5// Qt-Security score:critical reason:cryptography
6
7#include <qcryptographichash.h>
8#include <qmessageauthenticationcode.h>
9
10#include <QtCore/private/qsmallbytearray_p.h>
11#include <qiodevice.h>
12#include <qmutex.h>
13#include <private/qlocking_p.h>
14
15#include <array>
16#include <climits>
17#include <numeric>
18
19#include "../../3rdparty/sha1/sha1.cpp"
20
21// Header from rfc6234
22#include "../../3rdparty/rfc6234/sha.h"
23
24#if !QT_CONFIG(openssl_hash)
25#include "../../3rdparty/md5/md5.h"
26#include "../../3rdparty/md5/md5.cpp"
27#include "../../3rdparty/md4/md4.h"
28#include "../../3rdparty/md4/md4.cpp"
29#endif // !QT_CONFIG(openssl_hash)
30
31typedef unsigned char BitSequence;
32typedef unsigned long long DataLength;
33typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn;
34
35#ifdef Q_OS_RTEMS
36# undef ALIGN
37#endif
38
39#include "../../3rdparty/sha3/KeccakSponge.c"
40typedef spongeState hashState;
41
42#include "../../3rdparty/sha3/KeccakNISTInterface.c"
43
44/*
45 This lets us choose between SHA3 implementations at build time.
46 */
47typedef spongeState SHA3Context;
48typedef HashReturn (SHA3Init)(hashState *state, int hashbitlen);
49typedef HashReturn (SHA3Update)(hashState *state, const BitSequence *data, DataLength databitlen);
50typedef HashReturn (SHA3Final)(hashState *state, BitSequence *hashval);
51
52#if Q_PROCESSOR_WORDSIZE == 8 // 64 bit version
53
54#include "../../3rdparty/sha3/KeccakF-1600-opt64.c"
55
56Q_CONSTINIT static SHA3Init * const sha3Init = Init;
57Q_CONSTINIT static SHA3Update * const sha3Update = Update;
58Q_CONSTINIT static SHA3Final * const sha3Final = Final;
59
60#else // 32 bit optimised fallback
61
62#include "../../3rdparty/sha3/KeccakF-1600-opt32.c"
63
64Q_CONSTINIT static SHA3Init * const sha3Init = Init;
65Q_CONSTINIT static SHA3Update * const sha3Update = Update;
66Q_CONSTINIT static SHA3Final * const sha3Final = Final;
67
68#endif
69
70#if !QT_CONFIG(openssl_hash)
71/*
72 These 2 functions replace macros of the same name in sha224-256.c and
73 sha384-512.c. Originally, these macros relied on a global static 'addTemp'
74 variable. We do not want this for 2 reasons:
75
76 1. since we are including the sources directly, the declaration of the 2 conflict
77
78 2. static variables are not thread-safe, we do not want multiple threads
79 computing a hash to corrupt one another
80*/
81static int SHA224_256AddLength(SHA256Context *context, unsigned int length);
82static int SHA384_512AddLength(SHA512Context *context, unsigned int length);
83
84// Sources from rfc6234, with 4 modifications:
85// sha224-256.c - commented out 'static uint32_t addTemp;' on line 68
86// sha224-256.c - appended 'M' to the SHA224_256AddLength macro on line 70
87#include "../../3rdparty/rfc6234/sha224-256.c"
88// sha384-512.c - commented out 'static uint64_t addTemp;' on line 302
89// sha384-512.c - appended 'M' to the SHA224_256AddLength macro on line 304
90#include "../../3rdparty/rfc6234/sha384-512.c"
91
92static inline int SHA224_256AddLength(SHA256Context *context, unsigned int length)
93{
94 uint32_t addTemp;
95 return SHA224_256AddLengthM(context, length);
96}
97static inline int SHA384_512AddLength(SHA512Context *context, unsigned int length)
98{
99 uint64_t addTemp;
100 return SHA384_512AddLengthM(context, length);
101}
102#endif // !QT_CONFIG(opensslv30)
103
104#if QT_CONFIG(system_libb2)
105#include <blake2.h>
106#else
107QT_WARNING_PUSH
108QT_WARNING_DISABLE_CLANG("-Wunused-function")
109QT_WARNING_DISABLE_GCC("-Wunused-function")
110QT_WARNING_DISABLE_MSVC(4505)
111#include "../../3rdparty/blake2/src/blake2b-ref.c"
112#include "../../3rdparty/blake2/src/blake2s-ref.c"
114#endif
115
116#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(openssl_hash)
117#define USING_OPENSSL30
118#include <openssl/evp.h>
119#include <openssl/provider.h>
120#endif
121
123
124static constexpr int hashLengthInternal(QCryptographicHash::Algorithm method) noexcept
125{
126 switch (method) {
127#define CASE(Enum, Size)
128 case QCryptographicHash:: Enum :
129 return Size
130 /*end*/
131 CASE(Sha1, 20);
132 CASE(Md4, 16);
133 CASE(Md5, 16);
134 CASE(Sha224, SHA224HashSize);
135 CASE(Sha256, SHA256HashSize);
136 CASE(Sha384, SHA384HashSize);
137 CASE(Sha512, SHA512HashSize);
138 CASE(Blake2s_128, 128 / 8);
139 case QCryptographicHash::Blake2b_160:
140 case QCryptographicHash::Blake2s_160:
141 return 160 / 8;
142 case QCryptographicHash::RealSha3_224:
143 case QCryptographicHash::Keccak_224:
144 case QCryptographicHash::Blake2s_224:
145 return 224 / 8;
146 case QCryptographicHash::RealSha3_256:
147 case QCryptographicHash::Keccak_256:
148 case QCryptographicHash::Blake2b_256:
149 case QCryptographicHash::Blake2s_256:
150 return 256 / 8;
151 case QCryptographicHash::RealSha3_384:
152 case QCryptographicHash::Keccak_384:
153 case QCryptographicHash::Blake2b_384:
154 return 384 / 8;
155 case QCryptographicHash::RealSha3_512:
156 case QCryptographicHash::Keccak_512:
157 case QCryptographicHash::Blake2b_512:
158 return 512 / 8;
159#undef CASE
160 case QCryptographicHash::NumAlgorithms: ;
161 // fall through
162 // Q_UNREACHABLE() would be BiC here, as hashLength(~~invalid~~) worked in 6.4
163 }
164 return 0;
165}
166
167static constexpr int maxHashLength()
168{
169 int result = 0;
170 using A = QCryptographicHash::Algorithm;
171 for (int i = 0; i < A::NumAlgorithms; ++i)
172 result = std::max(result, hashLengthInternal(A(i)));
173 return result;
174}
175
176using HashResult = QSmallByteArray<maxHashLength()>;
177
178#ifdef USING_OPENSSL30
179static constexpr const char * methodToName(QCryptographicHash::Algorithm method) noexcept
180{
181 switch (method) {
182#define CASE(Enum, Name)
183 case QCryptographicHash:: Enum :
184 return Name
185 /*end*/
186 CASE(Sha1, "SHA1");
187 CASE(Md4, "MD4");
188 CASE(Md5, "MD5");
189 CASE(Sha224, "SHA224");
190 CASE(Sha256, "SHA256");
191 CASE(Sha384, "SHA384");
192 CASE(Sha512, "SHA512");
193 CASE(RealSha3_224, "SHA3-224");
194 CASE(RealSha3_256, "SHA3-256");
195 CASE(RealSha3_384, "SHA3-384");
196 CASE(RealSha3_512, "SHA3-512");
197 CASE(Blake2b_512, "BLAKE2B512");
198 CASE(Blake2s_256, "BLAKE2S256");
199 // not supported by OpenSSL:
200 CASE(Keccak_224, nullptr);
201 CASE(Keccak_256, nullptr);
202 CASE(Keccak_384, nullptr);
203 CASE(Keccak_512, nullptr);
204 CASE(Blake2b_160, nullptr);
205 CASE(Blake2b_256, nullptr);
206 CASE(Blake2b_384, nullptr);
207 CASE(Blake2s_128, nullptr);
208 CASE(Blake2s_160, nullptr);
209 CASE(Blake2s_224, nullptr);
210 CASE(NumAlgorithms, nullptr);
211#undef CASE
212 }
213 return nullptr;
214}
215#endif // USING_OPENSSL30
216
218{
219public:
225 {
226 state.destroy(method);
227 }
228
229 void reset() noexcept;
230 void addData(QByteArrayView bytes) noexcept;
231 bool addData(QIODevice *dev);
232 void finalize() noexcept;
233 // when not called from the static hash() function, this function needs to be
234 // called with finalizeMutex held (finalize() will do that):
235 void finalizeUnchecked() noexcept;
236 QSpan<uchar> finalizeUnchecked(QSpan<uchar> buffer) noexcept;
237
238 // END functions that need to be called with finalizeMutex held
239 QByteArrayView resultView() const noexcept { return result.toByteArrayView(); }
240 static bool supportsAlgorithm(QCryptographicHash::Algorithm method);
241
242#ifdef USING_OPENSSL30
243 struct EVP_MD_CTX_deleter {
244 void operator()(EVP_MD_CTX *ctx) const noexcept {
246 }
247 };
248 struct EVP_MD_deleter {
249 void operator()(EVP_MD *md) const noexcept {
251 }
252 };
253 struct OSSL_PROVIDER_deleter {
254 void operator()(OSSL_PROVIDER *provider) const noexcept {
256 }
257 };
258
262 struct EVP {
268
270 void reset() noexcept;
271 void finalizeUnchecked(QSpan<uchar> buffer) noexcept;
272 };
273#endif
274
275 union State {
278#ifdef USING_OPENSSL30
279 ~State() {}
280#endif
281
285
286 Sha1State sha1Context;
287#ifdef USING_OPENSSL30
288 EVP evp;
289#else
292 SHA224Context sha224Context;
293 SHA256Context sha256Context;
294 SHA384Context sha384Context;
295 SHA512Context sha512Context;
296#endif
298
299 enum class Sha3Variant { Sha3, Keccak };
300 static void sha3Finish(SHA3Context &ctx, QSpan<uchar> result, Sha3Variant sha3Variant);
301 blake2b_state blake2bContext;
302 blake2s_state blake2sContext;
303 } state;
304 // protects result in finalize()
307
309};
310
311void QCryptographicHashPrivate::State::sha3Finish(SHA3Context &ctx, QSpan<uchar> result,
312 Sha3Variant sha3Variant)
313{
314 /*
315 FIPS 202 §6.1 defines SHA-3 in terms of calculating the Keccak function
316 over the original message with the two-bit suffix "01" appended to it.
317 This variable stores that suffix (and it's fed into the calculations
318 when the hash is returned to users).
319
320 Only 2 bits of this variable are actually used (see the call to sha3Update
321 below). The Keccak implementation we're using will actually use the
322 *leftmost* 2 bits, and interpret them right-to-left. In other words, the
323 bits must appear in order of *increasing* significance; and as the two most
324 significant bits of the byte -- the rightmost 6 are ignored. (Yes, this
325 seems self-contradictory, but it's the way it is...)
326
327 Overall, this means:
328 * the leftmost two bits must be "10" (not "01"!);
329 * we don't care what the other six bits are set to (they can be set to
330 any value), but we arbitrarily set them to 0;
331
332 and for an unsigned char this gives us 0b10'00'00'00, or 0x80.
333 */
334 static const unsigned char sha3FinalSuffix = 0x80;
335
336 switch (sha3Variant) {
338 sha3Update(&ctx, reinterpret_cast<const BitSequence *>(&sha3FinalSuffix), 2);
339 break;
341 break;
342 }
343
344 sha3Final(&ctx, result.data());
345}
346
347/*!
348 \class QCryptographicHash
349 \inmodule QtCore
350
351 \brief The QCryptographicHash class provides a way to generate cryptographic hashes.
352
353 \since 4.3
354
355 \ingroup tools
356 \reentrant
357
358 QCryptographicHash can be used to generate cryptographic hashes of binary or text data.
359
360 Refer to the documentation of the \l QCryptographicHash::Algorithm enum for a
361 list of the supported algorithms.
362*/
363
364/*!
365 \enum QCryptographicHash::Algorithm
366
367 \note In Qt versions before 5.9, when asked to generate a SHA3 hash sum,
368 QCryptographicHash actually calculated Keccak. If you need compatibility with
369 SHA-3 hashes produced by those versions of Qt, use the \c{Keccak_}
370 enumerators. Alternatively, if source compatibility is required, define the
371 macro \c QT_SHA3_KECCAK_COMPAT.
372
373 \value Md4 Generate an MD4 hash sum
374 \value Md5 Generate an MD5 hash sum
375 \value Sha1 Generate an SHA-1 hash sum
376 \value Sha224 Generate an SHA-224 hash sum (SHA-2). Introduced in Qt 5.0
377 \value Sha256 Generate an SHA-256 hash sum (SHA-2). Introduced in Qt 5.0
378 \value Sha384 Generate an SHA-384 hash sum (SHA-2). Introduced in Qt 5.0
379 \value Sha512 Generate an SHA-512 hash sum (SHA-2). Introduced in Qt 5.0
380 \value Sha3_224 Generate an SHA3-224 hash sum. Introduced in Qt 5.1
381 \value Sha3_256 Generate an SHA3-256 hash sum. Introduced in Qt 5.1
382 \value Sha3_384 Generate an SHA3-384 hash sum. Introduced in Qt 5.1
383 \value Sha3_512 Generate an SHA3-512 hash sum. Introduced in Qt 5.1
384 \value Keccak_224 Generate a Keccak-224 hash sum. Introduced in Qt 5.9.2
385 \value Keccak_256 Generate a Keccak-256 hash sum. Introduced in Qt 5.9.2
386 \value Keccak_384 Generate a Keccak-384 hash sum. Introduced in Qt 5.9.2
387 \value Keccak_512 Generate a Keccak-512 hash sum. Introduced in Qt 5.9.2
388 \value Blake2b_160 Generate a BLAKE2b-160 hash sum. Introduced in Qt 6.0
389 \value Blake2b_256 Generate a BLAKE2b-256 hash sum. Introduced in Qt 6.0
390 \value Blake2b_384 Generate a BLAKE2b-384 hash sum. Introduced in Qt 6.0
391 \value Blake2b_512 Generate a BLAKE2b-512 hash sum. Introduced in Qt 6.0
392 \value Blake2s_128 Generate a BLAKE2s-128 hash sum. Introduced in Qt 6.0
393 \value Blake2s_160 Generate a BLAKE2s-160 hash sum. Introduced in Qt 6.0
394 \value Blake2s_224 Generate a BLAKE2s-224 hash sum. Introduced in Qt 6.0
395 \value Blake2s_256 Generate a BLAKE2s-256 hash sum. Introduced in Qt 6.0
396 \omitvalue RealSha3_224
397 \omitvalue RealSha3_256
398 \omitvalue RealSha3_384
399 \omitvalue RealSha3_512
400 \omitvalue NumAlgorithms
401*/
402
403/*!
404 Constructs an object that can be used to create a cryptographic hash from data using \a method.
405*/
406QCryptographicHash::QCryptographicHash(Algorithm method)
407 : d(new QCryptographicHashPrivate{method})
408{
409}
410
411/*!
412 \fn QCryptographicHash::QCryptographicHash(QCryptographicHash &&other)
413
414 Move-constructs a new QCryptographicHash from \a other.
415
416 \note The moved-from object \a other is placed in a
417 partially-formed state, in which the only valid operations are
418 destruction and assignment of a new value.
419
420 \since 6.5
421*/
422
423/*!
424 Destroys the object.
425*/
426QCryptographicHash::~QCryptographicHash()
427{
428 delete d;
429}
430
431/*!
432 \fn QCryptographicHash &QCryptographicHash::operator=(QCryptographicHash &&other)
433
434 Move-assigns \a other to this QCryptographicHash instance.
435
436 \note The moved-from object \a other is placed in a
437 partially-formed state, in which the only valid operations are
438 destruction and assignment of a new value.
439
440 \since 6.5
441*/
442
443/*!
444 \fn void QCryptographicHash::swap(QCryptographicHash &other)
445 \memberswap{cryptographic hash}
446 \since 6.5
447*/
448
449/*!
450 Resets the object.
451*/
452void QCryptographicHash::reset() noexcept
453{
454 d->reset();
455}
456
457/*!
458 Returns the algorithm used to generate the cryptographic hash.
459
460 \since 6.5
461*/
462QCryptographicHash::Algorithm QCryptographicHash::algorithm() const noexcept
463{
464 return d->method;
465}
466
467#ifdef USING_OPENSSL30
468
469QCryptographicHashPrivate::State::State(QCryptographicHash::Algorithm method)
470{
471 switch (method) {
472 case QCryptographicHash::Keccak_224:
473 case QCryptographicHash::Keccak_256:
474 case QCryptographicHash::Keccak_384:
475 case QCryptographicHash::Keccak_512:
476 new (&sha3Context) SHA3Context;
477 reset(method);
478 break;
479 case QCryptographicHash::Blake2b_160:
480 case QCryptographicHash::Blake2b_256:
481 case QCryptographicHash::Blake2b_384:
482 new (&blake2bContext) blake2b_state;
483 reset(method);
484 break;
485 case QCryptographicHash::Blake2s_128:
486 case QCryptographicHash::Blake2s_160:
487 case QCryptographicHash::Blake2s_224:
488 new (&blake2sContext) blake2s_state;
489 reset(method);
490 break;
491 case QCryptographicHash::Sha1:
492 case QCryptographicHash::Md4:
493 case QCryptographicHash::Md5:
494 case QCryptographicHash::Sha224:
495 case QCryptographicHash::Sha256:
496 case QCryptographicHash::Sha384:
497 case QCryptographicHash::Sha512:
498 case QCryptographicHash::RealSha3_224:
499 case QCryptographicHash::RealSha3_256:
500 case QCryptographicHash::RealSha3_384:
501 case QCryptographicHash::RealSha3_512:
502 case QCryptographicHash::Blake2b_512:
503 case QCryptographicHash::Blake2s_256:
504 new (&evp) EVP(method);
505 break;
506 case QCryptographicHash::NumAlgorithms:
507 Q_UNREACHABLE();
508 }
509}
510
511void QCryptographicHashPrivate::State::destroy(QCryptographicHash::Algorithm method)
512{
513 switch (method) {
514 case QCryptographicHash::Keccak_224:
515 case QCryptographicHash::Keccak_256:
516 case QCryptographicHash::Keccak_384:
517 case QCryptographicHash::Keccak_512:
518 case QCryptographicHash::Blake2b_160:
519 case QCryptographicHash::Blake2b_256:
520 case QCryptographicHash::Blake2b_384:
521 case QCryptographicHash::Blake2s_128:
522 case QCryptographicHash::Blake2s_160:
523 case QCryptographicHash::Blake2s_224:
524 return;
525 case QCryptographicHash::Sha1:
526 case QCryptographicHash::Md4:
527 case QCryptographicHash::Md5:
528 case QCryptographicHash::Sha224:
529 case QCryptographicHash::Sha256:
530 case QCryptographicHash::Sha384:
531 case QCryptographicHash::Sha512:
532 case QCryptographicHash::RealSha3_224:
533 case QCryptographicHash::RealSha3_256:
534 case QCryptographicHash::RealSha3_384:
535 case QCryptographicHash::RealSha3_512:
536 case QCryptographicHash::Blake2b_512:
537 case QCryptographicHash::Blake2s_256:
538 evp.~EVP();
539 break;
540 case QCryptographicHash::NumAlgorithms:
541 Q_UNREACHABLE();
542 }
543}
544
545QCryptographicHashPrivate::EVP::EVP(QCryptographicHash::Algorithm method)
546 : initializationFailed{true}
547{
548 if (method == QCryptographicHash::Md4) {
549 /*
550 * We need to load the legacy provider in order to have the MD4
551 * algorithm available.
552 */
553 legacyProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_try_load(nullptr, "legacy", /*retain_fallbacks=*/1));
554
555 if (!legacyProvider)
556 return;
557 }
558
559 /*
560 * Load with retain_fallbacks=1 so that loading these providers - and the
561 * unload performed by OSSL_PROVIDER_deleter - does not disable OpenSSL's
562 * fallback auto-loading of the default provider in the global library
563 * context. Plain OSSL_PROVIDER_load() disables that fallback, which then
564 * leaves later OpenSSL users (e.g. the TLS backend) without a default
565 * provider once we unload, breaking RAND seeding. See QTBUG-136223.
566 */
567 defaultProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_try_load(nullptr, "default", /*retain_fallbacks=*/1));
568 if (!defaultProvider)
569 return;
570
571 context = EVP_MD_CTX_ptr(EVP_MD_CTX_new());
572
573 if (!context) {
574 return;
575 }
576
577 /*
578 * Using the "-fips" option will disable the global "fips=yes" for
579 * this one lookup and the algorithm can be fetched from any provider
580 * that implements the algorithm (including the FIPS provider).
581 */
582 algorithm = EVP_MD_ptr(EVP_MD_fetch(nullptr, methodToName(method), "-fips"));
583 if (!algorithm) {
584 return;
585 }
586
587 initializationFailed = !EVP_DigestInit_ex(context.get(), algorithm.get(), nullptr);
588}
589
590#else // USING_OPENSSL30
591
592QCryptographicHashPrivate::State::State(QCryptographicHash::Algorithm method)
593{
594 switch (method) {
595 case QCryptographicHash::Sha1:
596 new (&sha1Context) Sha1State;
597 break;
598 case QCryptographicHash::Md4:
599 new (&md4Context) md4_context;
600 break;
601 case QCryptographicHash::Md5:
602 new (&md5Context) MD5Context;
603 break;
604 case QCryptographicHash::Sha224:
605 new (&sha224Context) SHA224Context;
606 break;
607 case QCryptographicHash::Sha256:
608 new (&sha256Context) SHA256Context;
609 break;
610 case QCryptographicHash::Sha384:
611 new (&sha384Context) SHA384Context;
612 break;
613 case QCryptographicHash::Sha512:
614 new (&sha512Context) SHA512Context;
615 break;
616 case QCryptographicHash::RealSha3_224:
617 case QCryptographicHash::Keccak_224:
618 case QCryptographicHash::RealSha3_256:
619 case QCryptographicHash::Keccak_256:
620 case QCryptographicHash::RealSha3_384:
621 case QCryptographicHash::Keccak_384:
622 case QCryptographicHash::RealSha3_512:
623 case QCryptographicHash::Keccak_512:
625 break;
626 case QCryptographicHash::Blake2b_160:
627 case QCryptographicHash::Blake2b_256:
628 case QCryptographicHash::Blake2b_384:
629 case QCryptographicHash::Blake2b_512:
630 new (&blake2bContext) blake2b_state;
631 break;
632 case QCryptographicHash::Blake2s_128:
633 case QCryptographicHash::Blake2s_160:
634 case QCryptographicHash::Blake2s_224:
635 case QCryptographicHash::Blake2s_256:
636 new (&blake2sContext) blake2s_state;
637 break;
638 case QCryptographicHash::NumAlgorithms:
639 Q_UNREACHABLE();
640 }
641 reset(method);
642}
643
645{
646 static_assert(std::is_trivially_destructible_v<State>); // so nothing to do here
647}
648#endif // !USING_OPENSSL30
649
651{
652 result.clear();
653 state.reset(method);
654}
655
656#ifdef USING_OPENSSL30
657
658void QCryptographicHashPrivate::State::reset(QCryptographicHash::Algorithm method) noexcept
659{
660 switch (method) {
661 case QCryptographicHash::Keccak_224:
662 case QCryptographicHash::Keccak_256:
663 case QCryptographicHash::Keccak_384:
664 case QCryptographicHash::Keccak_512:
665 sha3Init(&sha3Context, hashLengthInternal(method) * 8);
666 break;
667 case QCryptographicHash::Blake2b_160:
668 case QCryptographicHash::Blake2b_256:
669 case QCryptographicHash::Blake2b_384:
670 blake2b_init(&blake2bContext, hashLengthInternal(method));
671 break;
672 case QCryptographicHash::Blake2s_128:
673 case QCryptographicHash::Blake2s_160:
674 case QCryptographicHash::Blake2s_224:
675 blake2s_init(&blake2sContext, hashLengthInternal(method));
676 break;
677 case QCryptographicHash::Sha1:
678 case QCryptographicHash::Md4:
679 case QCryptographicHash::Md5:
680 case QCryptographicHash::Sha224:
681 case QCryptographicHash::Sha256:
682 case QCryptographicHash::Sha384:
683 case QCryptographicHash::Sha512:
684 case QCryptographicHash::RealSha3_224:
685 case QCryptographicHash::RealSha3_256:
686 case QCryptographicHash::RealSha3_384:
687 case QCryptographicHash::RealSha3_512:
688 case QCryptographicHash::Blake2b_512:
689 case QCryptographicHash::Blake2s_256:
690 evp.reset();
691 break;
692 case QCryptographicHash::NumAlgorithms:
693 Q_UNREACHABLE();
694 }
695}
696
697void QCryptographicHashPrivate::EVP::reset() noexcept
698{
699 if (!initializationFailed) {
700 Q_ASSERT(context);
701 Q_ASSERT(algorithm);
702 // everything already set up - just reset the context
703 EVP_MD_CTX_reset(context.get());
704 initializationFailed = !EVP_DigestInit_ex(context.get(), algorithm.get(), nullptr);
705 }
706 // if initializationFailed first time around, it will not succeed this time, either
707}
708
709#else // USING_OPENSSL30
710
711void QCryptographicHashPrivate::State::reset(QCryptographicHash::Algorithm method) noexcept
712{
713 switch (method) {
714 case QCryptographicHash::Sha1:
715 sha1InitState(&sha1Context);
716 break;
717 case QCryptographicHash::Md4:
718 md4_init(&md4Context);
719 break;
720 case QCryptographicHash::Md5:
721 MD5Init(&md5Context);
722 break;
723 case QCryptographicHash::Sha224:
724 SHA224Reset(&sha224Context);
725 break;
726 case QCryptographicHash::Sha256:
727 SHA256Reset(&sha256Context);
728 break;
729 case QCryptographicHash::Sha384:
730 SHA384Reset(&sha384Context);
731 break;
732 case QCryptographicHash::Sha512:
733 SHA512Reset(&sha512Context);
734 break;
735 case QCryptographicHash::RealSha3_224:
736 case QCryptographicHash::Keccak_224:
737 case QCryptographicHash::RealSha3_256:
738 case QCryptographicHash::Keccak_256:
739 case QCryptographicHash::RealSha3_384:
740 case QCryptographicHash::Keccak_384:
741 case QCryptographicHash::RealSha3_512:
742 case QCryptographicHash::Keccak_512:
743 sha3Init(&sha3Context, hashLengthInternal(method) * 8);
744 break;
745 case QCryptographicHash::Blake2b_160:
746 case QCryptographicHash::Blake2b_256:
747 case QCryptographicHash::Blake2b_384:
748 case QCryptographicHash::Blake2b_512:
749 blake2b_init(&blake2bContext, hashLengthInternal(method));
750 break;
751 case QCryptographicHash::Blake2s_128:
752 case QCryptographicHash::Blake2s_160:
753 case QCryptographicHash::Blake2s_224:
754 case QCryptographicHash::Blake2s_256:
755 blake2s_init(&blake2sContext, hashLengthInternal(method));
756 break;
757 case QCryptographicHash::NumAlgorithms:
758 Q_UNREACHABLE();
759 }
760}
761
762#endif // USING_OPENSSL30
763
764#if QT_DEPRECATED_SINCE(6, 4)
765/*!
766 Adds the first \a length chars of \a data to the cryptographic
767 hash.
768
769 \obsolete
770 Use the QByteArrayView overload instead.
771*/
772void QCryptographicHash::addData(const char *data, qsizetype length)
773{
774 Q_ASSERT(length >= 0);
775 addData(QByteArrayView{data, length});
776}
777#endif
778
779/*!
780 Adds the characters in \a bytes to the cryptographic hash.
781
782 \note In Qt versions prior to 6.3, this function took QByteArray,
783 not QByteArrayView.
784*/
785void QCryptographicHash::addData(QByteArrayView bytes) noexcept
786{
787 d->addData(bytes);
788}
789
790void QCryptographicHashPrivate::addData(QByteArrayView bytes) noexcept
791{
792 state.addData(method, bytes);
793 result.clear();
794}
795
796#ifdef USING_OPENSSL30
797
798void QCryptographicHashPrivate::State::addData(QCryptographicHash::Algorithm method,
799 QByteArrayView bytes) noexcept
800{
801 const char *data = bytes.data();
802 auto length = bytes.size();
803 // all functions take size_t length, so we don't need to loop around them:
804 switch (method) {
805 case QCryptographicHash::Keccak_224:
806 case QCryptographicHash::Keccak_256:
807 case QCryptographicHash::Keccak_384:
808 case QCryptographicHash::Keccak_512:
809 sha3Update(&sha3Context, reinterpret_cast<const BitSequence *>(data), uint64_t(length) * 8);
810 break;
811 case QCryptographicHash::Blake2b_160:
812 case QCryptographicHash::Blake2b_256:
813 case QCryptographicHash::Blake2b_384:
814 blake2b_update(&blake2bContext, reinterpret_cast<const uint8_t *>(data), length);
815 break;
816 case QCryptographicHash::Blake2s_128:
817 case QCryptographicHash::Blake2s_160:
818 case QCryptographicHash::Blake2s_224:
819 blake2s_update(&blake2sContext, reinterpret_cast<const uint8_t *>(data), length);
820 break;
821 case QCryptographicHash::Sha1:
822 case QCryptographicHash::Md4:
823 case QCryptographicHash::Md5:
824 case QCryptographicHash::Sha224:
825 case QCryptographicHash::Sha256:
826 case QCryptographicHash::Sha384:
827 case QCryptographicHash::Sha512:
828 case QCryptographicHash::RealSha3_224:
829 case QCryptographicHash::RealSha3_256:
830 case QCryptographicHash::RealSha3_384:
831 case QCryptographicHash::RealSha3_512:
832 case QCryptographicHash::Blake2b_512:
833 case QCryptographicHash::Blake2s_256:
834 if (!evp.initializationFailed)
835 EVP_DigestUpdate(evp.context.get(), (const unsigned char *)data, length);
836 break;
837 case QCryptographicHash::NumAlgorithms:
838 Q_UNREACHABLE();
839 }
840}
841
842#else // USING_OPENSSL30
843
844void QCryptographicHashPrivate::State::addData(QCryptographicHash::Algorithm method,
845 QByteArrayView bytes) noexcept
846{
847 const char *data = bytes.data();
848 auto length = bytes.size();
849
850#if QT_POINTER_SIZE == 8
851 // feed the data UINT_MAX bytes at a time, as some of the methods below
852 // take a uint (of course, feeding more than 4G of data into the hashing
853 // functions will be pretty slow anyway)
854 for (auto remaining = length; remaining; remaining -= length, data += length) {
855 length = qMin(qsizetype(std::numeric_limits<uint>::max()), remaining);
856#else
857 {
858#endif
859 switch (method) {
860 case QCryptographicHash::Sha1:
861 sha1Update(&sha1Context, (const unsigned char *)data, length);
862 break;
863 case QCryptographicHash::Md4:
864 md4_update(&md4Context, (const unsigned char *)data, length);
865 break;
866 case QCryptographicHash::Md5:
867 MD5Update(&md5Context, (const unsigned char *)data, length);
868 break;
869 case QCryptographicHash::Sha224:
870 SHA224Input(&sha224Context, reinterpret_cast<const unsigned char *>(data), length);
871 break;
872 case QCryptographicHash::Sha256:
873 SHA256Input(&sha256Context, reinterpret_cast<const unsigned char *>(data), length);
874 break;
875 case QCryptographicHash::Sha384:
876 SHA384Input(&sha384Context, reinterpret_cast<const unsigned char *>(data), length);
877 break;
878 case QCryptographicHash::Sha512:
879 SHA512Input(&sha512Context, reinterpret_cast<const unsigned char *>(data), length);
880 break;
881 case QCryptographicHash::RealSha3_224:
882 case QCryptographicHash::Keccak_224:
883 case QCryptographicHash::RealSha3_256:
884 case QCryptographicHash::Keccak_256:
885 case QCryptographicHash::RealSha3_384:
886 case QCryptographicHash::Keccak_384:
887 case QCryptographicHash::RealSha3_512:
888 case QCryptographicHash::Keccak_512:
889 sha3Update(&sha3Context, reinterpret_cast<const BitSequence *>(data), uint64_t(length) * 8);
890 break;
891 case QCryptographicHash::Blake2b_160:
892 case QCryptographicHash::Blake2b_256:
893 case QCryptographicHash::Blake2b_384:
894 case QCryptographicHash::Blake2b_512:
895 blake2b_update(&blake2bContext, reinterpret_cast<const uint8_t *>(data), length);
896 break;
897 case QCryptographicHash::Blake2s_128:
898 case QCryptographicHash::Blake2s_160:
899 case QCryptographicHash::Blake2s_224:
900 case QCryptographicHash::Blake2s_256:
901 blake2s_update(&blake2sContext, reinterpret_cast<const uint8_t *>(data), length);
902 break;
903 case QCryptographicHash::NumAlgorithms:
904 Q_UNREACHABLE();
905 }
906 }
907}
908#endif // !USING_OPENSSL30
909
910/*!
911 Reads the data from the open QIODevice \a device until it ends
912 and hashes it. Returns \c true if reading was successful.
913 \since 5.0
914 */
915bool QCryptographicHash::addData(QIODevice *device)
916{
917 return d->addData(device);
918}
919
920bool QCryptographicHashPrivate::addData(QIODevice *device)
921{
922 if (!device->isReadable())
923 return false;
924
925 if (!device->isOpen())
926 return false;
927
928 char buffer[1024];
929 qint64 length;
930
931 while ((length = device->read(buffer, sizeof(buffer))) > 0)
932 addData({buffer, qsizetype(length)}); // length always <= 1024
933
934 return device->atEnd();
935}
936
937
938/*!
939 Returns the final hash value.
940
941 \sa resultView(), QByteArray::toHex()
942*/
943QByteArray QCryptographicHash::result() const
944{
945 return resultView().toByteArray();
946}
947
948/*!
949 \since 6.3
950
951 Returns the final hash value.
952
953 Note that the returned view remains valid only as long as the QCryptographicHash object is
954 not modified by other means.
955
956 \sa result()
957*/
958QByteArrayView QCryptographicHash::resultView() const noexcept
959{
960 // resultView() is a const function, so concurrent calls are allowed; protect:
961 d->finalize();
962 // resultView() remains(!) valid even after we dropped the mutex in finalize()
963 return d->resultView();
964}
965
966/*!
967 \internal
968
969 Calls finalizeUnchecked(), if needed, under finalizeMutex protection.
970*/
972{
973 const auto lock = qt_scoped_lock(finalizeMutex);
974 // check that no other thread already finalizeUnchecked()'ed before us:
975 if (!result.isEmpty())
976 return;
978}
979
980/*!
981 \internal
982
983 Must be called with finalizeMutex held (except from static hash() function,
984 where no sharing can take place).
985*/
987{
988 result.resizeForOverwrite(hashLengthInternal(method));
989 state.finalizeUnchecked(method, result);
990}
991
992/*!
993 \internal
994
995 Must be called with finalizeMutex held, except when called from the static
996 hash() function, where no sharing can take place.
997*/
999{
1000 buffer = buffer.first(hashLengthInternal(method));
1001 state.finalizeUnchecked(method, buffer);
1002 Q_ASSERT(result.size() == 0); // internal buffer wasn't used
1003 return buffer;
1004}
1005
1006#ifdef USING_OPENSSL30
1007void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
1008 QSpan<uchar> result) noexcept
1009{
1010 switch (method) {
1011 case QCryptographicHash::Keccak_224:
1012 case QCryptographicHash::Keccak_256:
1013 case QCryptographicHash::Keccak_384:
1014 case QCryptographicHash::Keccak_512: {
1015 SHA3Context copy = sha3Context;
1016 sha3Finish(copy, result, Sha3Variant::Keccak);
1017 break;
1018 }
1019 case QCryptographicHash::Blake2b_160:
1020 case QCryptographicHash::Blake2b_256:
1021 case QCryptographicHash::Blake2b_384: {
1022 const auto length = hashLengthInternal(method);
1023 blake2b_state copy = blake2bContext;
1024 blake2b_final(&copy, result.data(), length);
1025 break;
1026 }
1027 case QCryptographicHash::Blake2s_128:
1028 case QCryptographicHash::Blake2s_160:
1029 case QCryptographicHash::Blake2s_224: {
1030 const auto length = hashLengthInternal(method);
1031 blake2s_state copy = blake2sContext;
1032 blake2s_final(&copy, result.data(), length);
1033 break;
1034 }
1035 case QCryptographicHash::Sha1:
1036 case QCryptographicHash::Md4:
1037 case QCryptographicHash::Md5:
1038 case QCryptographicHash::Sha224:
1039 case QCryptographicHash::Sha256:
1040 case QCryptographicHash::Sha384:
1041 case QCryptographicHash::Sha512:
1042 case QCryptographicHash::RealSha3_224:
1043 case QCryptographicHash::RealSha3_256:
1044 case QCryptographicHash::RealSha3_384:
1045 case QCryptographicHash::RealSha3_512:
1046 case QCryptographicHash::Blake2b_512:
1047 case QCryptographicHash::Blake2s_256:
1048 evp.finalizeUnchecked(result);
1049 break;
1050 case QCryptographicHash::NumAlgorithms:
1051 Q_UNREACHABLE();
1052 }
1053}
1054
1055void QCryptographicHashPrivate::EVP::finalizeUnchecked(QSpan<uchar> result) noexcept
1056{
1057 if (!initializationFailed) {
1058 EVP_MD_CTX_ptr copy = EVP_MD_CTX_ptr(EVP_MD_CTX_new());
1059 EVP_MD_CTX_copy_ex(copy.get(), context.get());
1060 Q_ASSERT(result.size() == EVP_MD_get_size(algorithm.get()));
1061 EVP_DigestFinal_ex(copy.get(), result.data(), nullptr);
1062 }
1063}
1064
1065#else // USING_OPENSSL30
1066
1067void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
1068 QSpan<uchar> result) noexcept
1069{
1070 switch (method) {
1071 case QCryptographicHash::Sha1: {
1072 Sha1State copy = sha1Context;
1073 sha1FinalizeState(&copy);
1074 sha1ToHash(&copy, result.data());
1075 break;
1076 }
1077 case QCryptographicHash::Md4: {
1078 md4_context copy = md4Context;
1079 md4_final(&copy, result.data());
1080 break;
1081 }
1082 case QCryptographicHash::Md5: {
1083 MD5Context copy = md5Context;
1084 MD5Final(&copy, result.data());
1085 break;
1086 }
1087 case QCryptographicHash::Sha224: {
1088 SHA224Context copy = sha224Context;
1089 SHA224Result(&copy, result.data());
1090 break;
1091 }
1092 case QCryptographicHash::Sha256: {
1093 SHA256Context copy = sha256Context;
1094 SHA256Result(&copy, result.data());
1095 break;
1096 }
1097 case QCryptographicHash::Sha384: {
1098 SHA384Context copy = sha384Context;
1099 SHA384Result(&copy, result.data());
1100 break;
1101 }
1102 case QCryptographicHash::Sha512: {
1103 SHA512Context copy = sha512Context;
1104 SHA512Result(&copy, result.data());
1105 break;
1106 }
1107 case QCryptographicHash::RealSha3_224:
1108 case QCryptographicHash::RealSha3_256:
1109 case QCryptographicHash::RealSha3_384:
1110 case QCryptographicHash::RealSha3_512: {
1111 SHA3Context copy = sha3Context;
1112 sha3Finish(copy, result, Sha3Variant::Sha3);
1113 break;
1114 }
1115 case QCryptographicHash::Keccak_224:
1116 case QCryptographicHash::Keccak_256:
1117 case QCryptographicHash::Keccak_384:
1118 case QCryptographicHash::Keccak_512: {
1119 SHA3Context copy = sha3Context;
1120 sha3Finish(copy, result, Sha3Variant::Keccak);
1121 break;
1122 }
1123 case QCryptographicHash::Blake2b_160:
1124 case QCryptographicHash::Blake2b_256:
1125 case QCryptographicHash::Blake2b_384:
1126 case QCryptographicHash::Blake2b_512: {
1127 const auto length = hashLengthInternal(method);
1128 blake2b_state copy = blake2bContext;
1129 blake2b_final(&copy, result.data(), length);
1130 break;
1131 }
1132 case QCryptographicHash::Blake2s_128:
1133 case QCryptographicHash::Blake2s_160:
1134 case QCryptographicHash::Blake2s_224:
1135 case QCryptographicHash::Blake2s_256: {
1136 const auto length = hashLengthInternal(method);
1137 blake2s_state copy = blake2sContext;
1138 blake2s_final(&copy, result.data(), length);
1139 break;
1140 }
1141 case QCryptographicHash::NumAlgorithms:
1142 Q_UNREACHABLE();
1143 }
1144}
1145#endif // !USING_OPENSSL30
1146
1147/*!
1148 Returns the hash of \a data using \a method.
1149
1150 \note In Qt versions prior to 6.3, this function took QByteArray,
1151 not QByteArrayView.
1152
1153 \sa hashInto()
1154*/
1155QByteArray QCryptographicHash::hash(QByteArrayView data, Algorithm method)
1156{
1157 QByteArray ba(hashLengthInternal(method), Qt::Uninitialized);
1158 [[maybe_unused]] const auto r = hashInto(ba, data, method);
1159 Q_ASSERT(r.size() == ba.size());
1160 return ba;
1161}
1162
1163/*!
1164 \since 6.8
1165 \fn QCryptographicHash::hashInto(QSpan<char> buffer, QSpan<const QByteArrayView> data, Algorithm method);
1166 \fn QCryptographicHash::hashInto(QSpan<uchar> buffer, QSpan<const QByteArrayView> data, Algorithm method);
1167 \fn QCryptographicHash::hashInto(QSpan<std::byte> buffer, QSpan<const QByteArrayView> data, Algorithm method);
1168 \fn QCryptographicHash::hashInto(QSpan<char> buffer, QByteArrayView data, Algorithm method);
1169 \fn QCryptographicHash::hashInto(QSpan<uchar> buffer, QByteArrayView data, Algorithm method);
1170 \fn QCryptographicHash::hashInto(QSpan<std::byte> buffer, QByteArrayView data, Algorithm method);
1171
1172 Returns the hash of \a data using \a method, using \a buffer to store the result.
1173
1174 If \a data is a span, adds all the byte array views to the hash, in the order given.
1175
1176 The return value will be a sub-span of \a buffer, unless \a buffer is of
1177 insufficient size, in which case a null QByteArrayView is returned.
1178
1179 \sa hash()
1180*/
1181QByteArrayView QCryptographicHash::hashInto(QSpan<std::byte> buffer,
1182 QSpan<const QByteArrayView> data,
1183 Algorithm method) noexcept
1184{
1185 if (buffer.size() < hashLengthInternal(method))
1186 return {}; // buffer too small
1187
1188 QCryptographicHashPrivate hash(method);
1189 for (QByteArrayView part : data)
1190 hash.addData(part);
1191 auto span = QSpan{reinterpret_cast<uchar *>(buffer.data()), buffer.size()};
1192 return hash.finalizeUnchecked(span); // no mutex needed: no-one but us has access to 'hash'
1193}
1194
1195/*!
1196 Returns the size of the output of the selected hash \a method in bytes.
1197
1198 \since 5.12
1199*/
1200int QCryptographicHash::hashLength(QCryptographicHash::Algorithm method)
1201{
1202 return hashLengthInternal(method);
1203}
1204
1205/*!
1206 Returns whether the selected algorithm \a method is supported and if
1207 result() will return a value when the \a method is used.
1208
1209 \note OpenSSL will be responsible for providing this information when
1210 used as a provider, otherwise \c true will be returned as the non-OpenSSL
1211 implementation doesn't have any restrictions.
1212 We return \c false if we fail to query OpenSSL.
1213
1214 \since 6.5
1215*/
1216
1217
1218bool QCryptographicHash::supportsAlgorithm(QCryptographicHash::Algorithm method)
1219{
1220 return QCryptographicHashPrivate::supportsAlgorithm(method);
1221}
1222
1223#ifdef USING_OPENSSL30
1224bool QCryptographicHashPrivate::supportsAlgorithm(QCryptographicHash::Algorithm method)
1225{
1226 // OpenSSL doesn't support Keccak*, Blake2b{160,256,384} and Blake2s{128,160,224},
1227 // and these would automatically return FALSE in that case, while they are
1228 // actually supported by our non-OpenSSL implementation.
1229 switch (method) {
1230 case QCryptographicHash::Keccak_224:
1231 case QCryptographicHash::Keccak_256:
1232 case QCryptographicHash::Keccak_384:
1233 case QCryptographicHash::Keccak_512:
1234 case QCryptographicHash::Blake2b_160:
1235 case QCryptographicHash::Blake2b_256:
1236 case QCryptographicHash::Blake2b_384:
1237 case QCryptographicHash::Blake2s_128:
1238 case QCryptographicHash::Blake2s_160:
1239 case QCryptographicHash::Blake2s_224:
1240 return true;
1241 case QCryptographicHash::Sha1:
1242 case QCryptographicHash::Md4:
1243 case QCryptographicHash::Md5:
1244 case QCryptographicHash::Sha224:
1245 case QCryptographicHash::Sha256:
1246 case QCryptographicHash::Sha384:
1247 case QCryptographicHash::Sha512:
1248 case QCryptographicHash::RealSha3_224:
1249 case QCryptographicHash::RealSha3_256:
1250 case QCryptographicHash::RealSha3_384:
1251 case QCryptographicHash::RealSha3_512:
1252 case QCryptographicHash::Blake2b_512:
1253 case QCryptographicHash::Blake2s_256: {
1254 // retain_fallbacks=1: don't disable the global default-provider fallback
1255 // auto-load (see QTBUG-136223 and the EVP constructor above).
1256 auto legacyProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_try_load(nullptr, "legacy", /*retain_fallbacks=*/1));
1257 auto defaultProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_try_load(nullptr, "default", /*retain_fallbacks=*/1));
1258
1259 const char *restriction = "-fips";
1260 EVP_MD_ptr algorithm = EVP_MD_ptr(EVP_MD_fetch(nullptr, methodToName(method), restriction));
1261
1262 return algorithm != nullptr;
1263
1264 }
1265 case QCryptographicHash::NumAlgorithms:
1266 ;
1267 }
1268 return false;
1269
1270}
1271#else
1272bool QCryptographicHashPrivate::supportsAlgorithm(QCryptographicHash::Algorithm method)
1273{
1274 switch (method) {
1275 case QCryptographicHash::Sha1:
1276 case QCryptographicHash::Md4:
1277 case QCryptographicHash::Md5:
1278 case QCryptographicHash::Sha224:
1279 case QCryptographicHash::Sha256:
1280 case QCryptographicHash::Sha384:
1281 case QCryptographicHash::Sha512:
1282 case QCryptographicHash::RealSha3_224:
1283 case QCryptographicHash::Keccak_224:
1284 case QCryptographicHash::RealSha3_256:
1285 case QCryptographicHash::Keccak_256:
1286 case QCryptographicHash::RealSha3_384:
1287 case QCryptographicHash::Keccak_384:
1288 case QCryptographicHash::RealSha3_512:
1289 case QCryptographicHash::Keccak_512:
1290 case QCryptographicHash::Blake2b_160:
1291 case QCryptographicHash::Blake2b_256:
1292 case QCryptographicHash::Blake2b_384:
1293 case QCryptographicHash::Blake2b_512:
1294 case QCryptographicHash::Blake2s_128:
1295 case QCryptographicHash::Blake2s_160:
1296 case QCryptographicHash::Blake2s_224:
1297 case QCryptographicHash::Blake2s_256:
1298 return true;
1299 case QCryptographicHash::NumAlgorithms: ;
1300 };
1301 return false;
1302}
1303#endif // !USING_OPENSSL3
1304
1305static constexpr int qt_hash_block_size(QCryptographicHash::Algorithm method)
1306{
1307 switch (method) {
1308 case QCryptographicHash::Sha1:
1309 return SHA1_Message_Block_Size;
1310 case QCryptographicHash::Md4:
1311 return 64;
1312 case QCryptographicHash::Md5:
1313 return 64;
1314 case QCryptographicHash::Sha224:
1315 return SHA224_Message_Block_Size;
1316 case QCryptographicHash::Sha256:
1317 return SHA256_Message_Block_Size;
1318 case QCryptographicHash::Sha384:
1319 return SHA384_Message_Block_Size;
1320 case QCryptographicHash::Sha512:
1321 return SHA512_Message_Block_Size;
1322 case QCryptographicHash::RealSha3_224:
1323 case QCryptographicHash::Keccak_224:
1324 return 144;
1325 case QCryptographicHash::RealSha3_256:
1326 case QCryptographicHash::Keccak_256:
1327 return 136;
1328 case QCryptographicHash::RealSha3_384:
1329 case QCryptographicHash::Keccak_384:
1330 return 104;
1331 case QCryptographicHash::RealSha3_512:
1332 case QCryptographicHash::Keccak_512:
1333 return 72;
1334 case QCryptographicHash::Blake2b_160:
1335 case QCryptographicHash::Blake2b_256:
1336 case QCryptographicHash::Blake2b_384:
1337 case QCryptographicHash::Blake2b_512:
1338 return BLAKE2B_BLOCKBYTES;
1339 case QCryptographicHash::Blake2s_128:
1340 case QCryptographicHash::Blake2s_160:
1341 case QCryptographicHash::Blake2s_224:
1342 case QCryptographicHash::Blake2s_256:
1343 return BLAKE2S_BLOCKBYTES;
1344 case QCryptographicHash::NumAlgorithms:
1345#if !defined(Q_CC_GNU_ONLY) || Q_CC_GNU >= 900
1346 // GCC 8 has trouble with Q_UNREACHABLE() in constexpr functions
1347 Q_UNREACHABLE();
1348#endif
1349 break;
1350 }
1351 return 0;
1352}
1353
1354constexpr int maxHashBlockSize()
1355{
1356 int result = 0;
1357 using A = QCryptographicHash::Algorithm;
1358 for (int i = 0; i < A::NumAlgorithms ; ++i)
1359 result = std::max(result, qt_hash_block_size(A(i)));
1360 return result;
1361}
1362
1363[[maybe_unused]]
1364constexpr int minHashBlockSize()
1365{
1366 int result = INT_MAX;
1367 using A = QCryptographicHash::Algorithm;
1368 for (int i = 0; i < A::NumAlgorithms ; ++i)
1369 result = std::min(result, qt_hash_block_size(A(i)));
1370 return result;
1371}
1372
1373[[maybe_unused]]
1374constexpr int gcdHashBlockSize()
1375{
1376 int result = 0;
1377 using A = QCryptographicHash::Algorithm;
1378 for (int i = 0; i < A::NumAlgorithms ; ++i)
1379 result = std::gcd(result, qt_hash_block_size(A(i)));
1380 return result;
1381}
1382
1383using HashBlock = QSmallByteArray<maxHashBlockSize()>;
1384
1385static HashBlock xored(const HashBlock &block, quint8 val) noexcept
1386{
1387 // some hints for the optimizer:
1388 Q_ASSERT(block.size() >= minHashBlockSize());
1389 Q_ASSERT(block.size() <= maxHashBlockSize());
1390 Q_ASSERT(block.size() % gcdHashBlockSize() == 0);
1391 HashBlock result;
1392 result.resizeForOverwrite(block.size());
1393 for (qsizetype i = 0; i < block.size(); ++i)
1394 result[i] = block[i] ^ val;
1395 return result;
1396}
1397
1399{
1400public:
1405
1408
1409 void setKey(QByteArrayView k) noexcept;
1410 void initMessageHash() noexcept;
1411 void finalize();
1412
1413 // when not called from the static hash() function, this function needs to be
1414 // called with messageHash.finalizeMutex held:
1415 void finalizeUnchecked() noexcept;
1416 // END functions that need to be called with finalizeMutex held
1417};
1418
1419/*!
1420 \internal
1421
1422 Transforms key \a newKey into a block-sized format and stores it in member
1423 \c key.
1424
1425 This function assumes it can use messageHash (i.e. it's in its initial
1426 state (reset() has been called)).
1427*/
1428void QMessageAuthenticationCodePrivate::setKey(QByteArrayView newKey) noexcept
1429{
1430 const int blockSize = qt_hash_block_size(messageHash.method);
1431
1432 if (newKey.size() > blockSize) {
1433 messageHash.addData(newKey);
1434 messageHash.finalizeUnchecked();
1435 static_assert([] {
1436 using A = QCryptographicHash::Algorithm;
1437 for (int i = 0; i < A::NumAlgorithms; ++i) {
1438 if (hashLengthInternal(A(i)) > qt_hash_block_size(A(i)))
1439 return false;
1440 }
1441 return true;
1442 }(), "this code assumes that a hash's result always fits into that hash's block size");
1443 key = messageHash.result;
1444 messageHash.reset();
1445 } else {
1446 key.assign(newKey);
1447 }
1448
1449 if (key.size() < blockSize)
1450 key.resize(blockSize, '\0');
1451
1453}
1454
1455/*!
1456 \internal
1457
1458 Seeds messageHash from \c key.
1459
1460 This function assumes that messageHash is in its initial state (reset() has
1461 been called).
1462*/
1464{
1465 messageHash.addData(xored(key, 0x36));
1466}
1467
1468/*!
1469 \class QMessageAuthenticationCode
1470 \inmodule QtCore
1471
1472 \brief The QMessageAuthenticationCode class provides a way to generate
1473 hash-based message authentication codes.
1474
1475 \since 5.1
1476
1477 \ingroup tools
1478 \reentrant
1479
1480 Use the QMessageAuthenticationCode class to generate hash-based message
1481 authentication codes (HMACs). The class supports all cryptographic
1482 hash algorithms from \l QCryptographicHash (see also
1483 \l{QCryptographicHash::Algorithm}).
1484
1485 To generate a message authentication code, pass a suitable hash
1486 algorithm and secret key to the constructor. Then process the message
1487 data by calling \l addData() one or more times. After the full
1488 message has been processed, get the final authentication code
1489 via the \l result() function:
1490
1491 \snippet qmessageauthenticationcode/main.cpp 0
1492 \dots
1493 \snippet qmessageauthenticationcode/main.cpp 1
1494
1495 For simple cases like above, you can also use the static
1496 \l hash() function:
1497
1498 \snippet qmessageauthenticationcode/main.cpp 2
1499
1500
1501 \note The cryptographic strength of the HMAC depends upon the
1502 size of the secret key, and the security of the
1503 underlying hash function.
1504
1505 \sa QCryptographicHash, QCryptographicHash::Algorithm
1506*/
1507
1508/*!
1509 Constructs an object that can be used to create a cryptographic hash from data
1510 using method \a method and key \a key.
1511
1512//! [qba-to-qbav-6.6]
1513 \note In Qt versions prior to 6.6, this function took its arguments as
1514 QByteArray, not QByteArrayView. If you experience compile errors, it's
1515 because your code is passing objects that are implicitly convertible to
1516 QByteArray, but not QByteArrayView. Wrap the corresponding argument in
1517 \c{QByteArray{~~~}} to make the cast explicit. This is backwards-compatible
1518 with old Qt versions.
1519//! [qba-to-qbav-6.6]
1520*/
1521QMessageAuthenticationCode::QMessageAuthenticationCode(QCryptographicHash::Algorithm method,
1522 QByteArrayView key)
1523 : d(new QMessageAuthenticationCodePrivate(method))
1524{
1525 d->setKey(key);
1526}
1527
1528/*!
1529 Destroys the object.
1530*/
1531QMessageAuthenticationCode::~QMessageAuthenticationCode()
1532{
1533 delete d;
1534}
1535
1536/*!
1537 \fn QMessageAuthenticationCode::QMessageAuthenticationCode(QMessageAuthenticationCode &&other)
1538
1539 Move-constructs a new QMessageAuthenticationCode from \a other.
1540
1541 \note The moved-from object \a other is placed in a
1542 partially-formed state, in which the only valid operations are
1543 destruction and assignment of a new object.
1544
1545 \since 6.6
1546*/
1547
1548/*!
1549 \fn QMessageAuthenticationCode &QMessageAuthenticationCode::operator=(QMessageAuthenticationCode &&other)
1550
1551 Move-assigns \a other to this QMessageAuthenticationCode instance.
1552
1553 \note The moved-from object \a other is placed in a
1554 partially-formed state, in which the only valid operations are
1555 destruction and assignment of a new object.
1556
1557 \since 6.6
1558*/
1559
1560/*!
1561 \fn void QMessageAuthenticationCode::swap(QMessageAuthenticationCode &other)
1562 \memberswap{message authentication code}
1563 \since 6.6
1564*/
1565
1566/*!
1567 Resets message data. Calling this function doesn't affect the key.
1568*/
1569void QMessageAuthenticationCode::reset() noexcept
1570{
1571 d->messageHash.reset();
1572 d->initMessageHash();
1573}
1574
1575/*!
1576 Sets secret \a key. Calling this function automatically resets the object state.
1577
1578 For optimal performance, call this function only to \e change the active key,
1579 not to set an \e initial key, as in
1580
1581 \code
1582 QMessageAuthenticationCode mac(method);
1583 mac.setKey(key); // does extra work
1584 use(mac);
1585 \endcode
1586
1587 Prefer to pass initial keys as the constructor argument:
1588
1589 \code
1590 QMessageAuthenticationCode mac(method, key); // OK, optimal
1591 use(mac);
1592 \endcode
1593
1594 You can use std::optional to delay construction of a
1595 QMessageAuthenticationCode until you know the key:
1596
1597 \code
1598 std::optional<QMessageAuthenticationCode> mac;
1599 ~~~
1600 key = ~~~;
1601 mac.emplace(method, key);
1602 use(*mac);
1603 \endcode
1604
1605 \include qcryptographichash.cpp {qba-to-qbav-6.6}
1606*/
1607void QMessageAuthenticationCode::setKey(QByteArrayView key) noexcept
1608{
1609 d->messageHash.reset();
1610 d->setKey(key);
1611}
1612
1613/*!
1614 \overload
1615 Adds the first \a length chars of \a data to the message.
1616*/
1617void QMessageAuthenticationCode::addData(const char *data, qsizetype length)
1618{
1619 d->messageHash.addData({data, length});
1620}
1621
1622/*!
1623 Adds \a data to the message.
1624
1625 \include qcryptographichash.cpp {qba-to-qbav-6.6}
1626
1627 \sa resultView(), result()
1628*/
1629void QMessageAuthenticationCode::addData(QByteArrayView data) noexcept
1630{
1631 d->messageHash.addData(data);
1632}
1633
1634/*!
1635 Reads the data from the open QIODevice \a device until it ends
1636 and adds it to message. Returns \c true if reading was successful.
1637
1638 \note \a device must be already opened.
1639 */
1640bool QMessageAuthenticationCode::addData(QIODevice *device)
1641{
1642 return d->messageHash.addData(device);
1643}
1644
1645/*!
1646 \since 6.6
1647
1648 Returns the final hash value.
1649
1650 Note that the returned view remains valid only as long as the
1651 QMessageAuthenticationCode object is not modified by other means.
1652
1653 \sa result()
1654*/
1655QByteArrayView QMessageAuthenticationCode::resultView() const noexcept
1656{
1657 d->finalize();
1658 return d->messageHash.resultView();
1659}
1660
1661/*!
1662 Returns the final authentication code.
1663
1664 \sa resultView(), QByteArray::toHex()
1665*/
1666QByteArray QMessageAuthenticationCode::result() const
1667{
1668 return resultView().toByteArray();
1669}
1670
1672{
1673 const auto lock = qt_scoped_lock(messageHash.finalizeMutex);
1674 if (!messageHash.result.isEmpty())
1675 return;
1677}
1678
1680{
1681 messageHash.finalizeUnchecked();
1682 const HashResult hashedMessage = messageHash.result;
1683
1684 messageHash.reset();
1685 messageHash.addData(xored(key, 0x5c));
1686 messageHash.addData(hashedMessage);
1687 messageHash.finalizeUnchecked();
1688}
1689
1690/*!
1691 Returns the authentication code for the message \a message using
1692 the key \a key and the method \a method.
1693
1694 \include qcryptographichash.cpp {qba-to-qbav-6.6}
1695
1696 \sa hashInto()
1697*/
1698QByteArray QMessageAuthenticationCode::hash(QByteArrayView message, QByteArrayView key,
1699 QCryptographicHash::Algorithm method)
1700{
1701 QByteArray ba(hashLengthInternal(method), Qt::Uninitialized);
1702 [[maybe_unused]] const auto r = hashInto(ba, message, key, method);
1703 Q_ASSERT(r.size() == ba.size());
1704 return ba;
1705}
1706
1707/*!
1708 \since 6.8
1709 \fn QMessageAuthenticationCode::hashInto(QSpan<char> buffer, QSpan<const QByteArrayView> messageParts, QByteArrayView key, QCryptographicHash::Algorithm method);
1710 \fn QMessageAuthenticationCode::hashInto(QSpan<uchar> buffer, QSpan<const QByteArrayView> messageParts, QByteArrayView key, QCryptographicHash::Algorithm method);
1711 \fn QMessageAuthenticationCode::hashInto(QSpan<std::byte> buffer, QSpan<const QByteArrayView> messageParts, QByteArrayView key, QCryptographicHash::Algorithm method);
1712 \fn QMessageAuthenticationCode::hashInto(QSpan<char> buffer, QByteArrayView message, QByteArrayView key, QCryptographicHash::Algorithm method);
1713 \fn QMessageAuthenticationCode::hashInto(QSpan<uchar> buffer, QByteArrayView message, QByteArrayView key, QCryptographicHash::Algorithm method);
1714 \fn QMessageAuthenticationCode::hashInto(QSpan<std::byte> buffer, QByteArrayView message, QByteArrayView key, QCryptographicHash::Algorithm method);
1715
1716 Returns the authentication code for the message (\a message or, for the
1717 QSpan overloads, the concatenation of \a messageParts) using the key \a key
1718 and the method \a method.
1719
1720 The return value will be a sub-span of \a buffer, unless \a buffer is of
1721 insufficient size, in which case a null QByteArrayView is returned.
1722
1723 \sa hash()
1724*/
1725QByteArrayView QMessageAuthenticationCode::hashInto(QSpan<std::byte> buffer,
1726 QSpan<const QByteArrayView> messageParts,
1727 QByteArrayView key,
1728 QCryptographicHash::Algorithm method) noexcept
1729{
1730 QMessageAuthenticationCodePrivate mac(method);
1731 mac.setKey(key);
1732 for (QByteArrayView part : messageParts)
1733 mac.messageHash.addData(part);
1734 mac.finalizeUnchecked();
1735 auto result = mac.messageHash.resultView();
1736 if (buffer.size() < result.size())
1737 return {}; // buffer too small
1738 // ### optimize: have the method directly write into `buffer`
1739 memcpy(buffer.data(), result.data(), result.size());
1740 return buffer.first(result.size());
1741}
1742
1743QT_END_NAMESPACE
1744
1745#ifndef QT_NO_QOBJECT
1746#include "moc_qcryptographichash.cpp"
1747#endif
void addData(QByteArrayView bytes) noexcept
QCryptographicHashPrivate(QCryptographicHash::Algorithm method) noexcept
QByteArrayView resultView() const noexcept
static bool supportsAlgorithm(QCryptographicHash::Algorithm method)
QSpan< uchar > finalizeUnchecked(QSpan< uchar > buffer) noexcept
QMessageAuthenticationCodePrivate(QCryptographicHash::Algorithm m) noexcept
void setKey(QByteArrayView k) noexcept
Combined button and popup list for selecting options.
#define CASE(E, member)
constexpr int maxHashBlockSize()
QT_WARNING_PUSH QT_WARNING_POP static QT_BEGIN_NAMESPACE constexpr int hashLengthInternal(QCryptographicHash::Algorithm method) noexcept
static constexpr int qt_hash_block_size(QCryptographicHash::Algorithm method)
static HashBlock xored(const HashBlock &block, quint8 val) noexcept
static constexpr int maxHashLength()
constexpr int minHashBlockSize()
constexpr int gcdHashBlockSize()
@ BAD_HASHLEN
unsigned long long DataLength
spongeState SHA3Context
unsigned char BitSequence
spongeState hashState
QMutex QBasicMutex
Definition qmutex.h:360
static void sha3Finish(SHA3Context &ctx, QSpan< uchar > result, Sha3Variant sha3Variant)
void addData(QCryptographicHash::Algorithm method, QByteArrayView data) noexcept
void finalizeUnchecked(QCryptographicHash::Algorithm method, QSpan< uchar > buffer) noexcept
void destroy(QCryptographicHash::Algorithm method)
State(QCryptographicHash::Algorithm method)
void reset(QCryptographicHash::Algorithm method) noexcept