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 \deprecated [6.4]
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 Q_DECL_UNINITIALIZED
929 char buffer[1024];
930 qint64 length;
931
932 while ((length = device->read(buffer, sizeof(buffer))) > 0)
933 addData({buffer, qsizetype(length)}); // length always <= 1024
934
935 return device->atEnd();
936}
937
938
939/*!
940 Returns the final hash value.
941
942 \sa resultView(), QByteArray::toHex()
943*/
944QByteArray QCryptographicHash::result() const
945{
946 return resultView().toByteArray();
947}
948
949/*!
950 \since 6.3
951
952 Returns the final hash value.
953
954 Note that the returned view remains valid only as long as the QCryptographicHash object is
955 not modified by other means.
956
957 \sa result()
958*/
959QByteArrayView QCryptographicHash::resultView() const noexcept
960{
961 // resultView() is a const function, so concurrent calls are allowed; protect:
962 d->finalize();
963 // resultView() remains(!) valid even after we dropped the mutex in finalize()
964 return d->resultView();
965}
966
967/*!
968 \internal
969
970 Calls finalizeUnchecked(), if needed, under finalizeMutex protection.
971*/
973{
974 const auto lock = qt_scoped_lock(finalizeMutex);
975 // check that no other thread already finalizeUnchecked()'ed before us:
976 if (!result.isEmpty())
977 return;
979}
980
981/*!
982 \internal
983
984 Must be called with finalizeMutex held (except from static hash() function,
985 where no sharing can take place).
986*/
988{
989 result.resizeForOverwrite(hashLengthInternal(method));
990 state.finalizeUnchecked(method, result);
991}
992
993/*!
994 \internal
995
996 Must be called with finalizeMutex held, except when called from the static
997 hash() function, where no sharing can take place.
998*/
1000{
1001 buffer = buffer.first(hashLengthInternal(method));
1002 state.finalizeUnchecked(method, buffer);
1003 Q_ASSERT(result.size() == 0); // internal buffer wasn't used
1004 return buffer;
1005}
1006
1007#ifdef USING_OPENSSL30
1008void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
1009 QSpan<uchar> result) noexcept
1010{
1011 switch (method) {
1012 case QCryptographicHash::Keccak_224:
1013 case QCryptographicHash::Keccak_256:
1014 case QCryptographicHash::Keccak_384:
1015 case QCryptographicHash::Keccak_512: {
1016 SHA3Context copy = sha3Context;
1017 sha3Finish(copy, result, Sha3Variant::Keccak);
1018 break;
1019 }
1020 case QCryptographicHash::Blake2b_160:
1021 case QCryptographicHash::Blake2b_256:
1022 case QCryptographicHash::Blake2b_384: {
1023 const auto length = hashLengthInternal(method);
1024 blake2b_state copy = blake2bContext;
1025 blake2b_final(&copy, result.data(), length);
1026 break;
1027 }
1028 case QCryptographicHash::Blake2s_128:
1029 case QCryptographicHash::Blake2s_160:
1030 case QCryptographicHash::Blake2s_224: {
1031 const auto length = hashLengthInternal(method);
1032 blake2s_state copy = blake2sContext;
1033 blake2s_final(&copy, result.data(), length);
1034 break;
1035 }
1036 case QCryptographicHash::Sha1:
1037 case QCryptographicHash::Md4:
1038 case QCryptographicHash::Md5:
1039 case QCryptographicHash::Sha224:
1040 case QCryptographicHash::Sha256:
1041 case QCryptographicHash::Sha384:
1042 case QCryptographicHash::Sha512:
1043 case QCryptographicHash::RealSha3_224:
1044 case QCryptographicHash::RealSha3_256:
1045 case QCryptographicHash::RealSha3_384:
1046 case QCryptographicHash::RealSha3_512:
1047 case QCryptographicHash::Blake2b_512:
1048 case QCryptographicHash::Blake2s_256:
1049 evp.finalizeUnchecked(result);
1050 break;
1051 case QCryptographicHash::NumAlgorithms:
1052 Q_UNREACHABLE();
1053 }
1054}
1055
1056void QCryptographicHashPrivate::EVP::finalizeUnchecked(QSpan<uchar> result) noexcept
1057{
1058 if (!initializationFailed) {
1059 EVP_MD_CTX_ptr copy = EVP_MD_CTX_ptr(EVP_MD_CTX_new());
1060 EVP_MD_CTX_copy_ex(copy.get(), context.get());
1061 Q_ASSERT(result.size() == EVP_MD_get_size(algorithm.get()));
1062 EVP_DigestFinal_ex(copy.get(), result.data(), nullptr);
1063 }
1064}
1065
1066#else // USING_OPENSSL30
1067
1068void QCryptographicHashPrivate::State::finalizeUnchecked(QCryptographicHash::Algorithm method,
1069 QSpan<uchar> result) noexcept
1070{
1071 switch (method) {
1072 case QCryptographicHash::Sha1: {
1073 Sha1State copy = sha1Context;
1074 sha1FinalizeState(&copy);
1075 sha1ToHash(&copy, result.data());
1076 break;
1077 }
1078 case QCryptographicHash::Md4: {
1079 md4_context copy = md4Context;
1080 md4_final(&copy, result.data());
1081 break;
1082 }
1083 case QCryptographicHash::Md5: {
1084 MD5Context copy = md5Context;
1085 MD5Final(&copy, result.data());
1086 break;
1087 }
1088 case QCryptographicHash::Sha224: {
1089 SHA224Context copy = sha224Context;
1090 SHA224Result(&copy, result.data());
1091 break;
1092 }
1093 case QCryptographicHash::Sha256: {
1094 SHA256Context copy = sha256Context;
1095 SHA256Result(&copy, result.data());
1096 break;
1097 }
1098 case QCryptographicHash::Sha384: {
1099 SHA384Context copy = sha384Context;
1100 SHA384Result(&copy, result.data());
1101 break;
1102 }
1103 case QCryptographicHash::Sha512: {
1104 SHA512Context copy = sha512Context;
1105 SHA512Result(&copy, result.data());
1106 break;
1107 }
1108 case QCryptographicHash::RealSha3_224:
1109 case QCryptographicHash::RealSha3_256:
1110 case QCryptographicHash::RealSha3_384:
1111 case QCryptographicHash::RealSha3_512: {
1112 SHA3Context copy = sha3Context;
1113 sha3Finish(copy, result, Sha3Variant::Sha3);
1114 break;
1115 }
1116 case QCryptographicHash::Keccak_224:
1117 case QCryptographicHash::Keccak_256:
1118 case QCryptographicHash::Keccak_384:
1119 case QCryptographicHash::Keccak_512: {
1120 SHA3Context copy = sha3Context;
1121 sha3Finish(copy, result, Sha3Variant::Keccak);
1122 break;
1123 }
1124 case QCryptographicHash::Blake2b_160:
1125 case QCryptographicHash::Blake2b_256:
1126 case QCryptographicHash::Blake2b_384:
1127 case QCryptographicHash::Blake2b_512: {
1128 const auto length = hashLengthInternal(method);
1129 blake2b_state copy = blake2bContext;
1130 blake2b_final(&copy, result.data(), length);
1131 break;
1132 }
1133 case QCryptographicHash::Blake2s_128:
1134 case QCryptographicHash::Blake2s_160:
1135 case QCryptographicHash::Blake2s_224:
1136 case QCryptographicHash::Blake2s_256: {
1137 const auto length = hashLengthInternal(method);
1138 blake2s_state copy = blake2sContext;
1139 blake2s_final(&copy, result.data(), length);
1140 break;
1141 }
1142 case QCryptographicHash::NumAlgorithms:
1143 Q_UNREACHABLE();
1144 }
1145}
1146#endif // !USING_OPENSSL30
1147
1148/*!
1149 Returns the hash of \a data using \a method.
1150
1151 \note In Qt versions prior to 6.3, this function took QByteArray,
1152 not QByteArrayView.
1153
1154 \sa hashInto()
1155*/
1156QByteArray QCryptographicHash::hash(QByteArrayView data, Algorithm method)
1157{
1158 QByteArray ba(hashLengthInternal(method), Qt::Uninitialized);
1159 [[maybe_unused]] const auto r = hashInto(ba, data, method);
1160 Q_ASSERT(r.size() == ba.size());
1161 return ba;
1162}
1163
1164/*!
1165 \since 6.8
1166 \fn QCryptographicHash::hashInto(QSpan<char> buffer, QSpan<const QByteArrayView> data, Algorithm method);
1167 \fn QCryptographicHash::hashInto(QSpan<uchar> buffer, QSpan<const QByteArrayView> data, Algorithm method);
1168 \fn QCryptographicHash::hashInto(QSpan<std::byte> buffer, QSpan<const QByteArrayView> data, Algorithm method);
1169 \fn QCryptographicHash::hashInto(QSpan<char> buffer, QByteArrayView data, Algorithm method);
1170 \fn QCryptographicHash::hashInto(QSpan<uchar> buffer, QByteArrayView data, Algorithm method);
1171 \fn QCryptographicHash::hashInto(QSpan<std::byte> buffer, QByteArrayView data, Algorithm method);
1172
1173 Returns the hash of \a data using \a method, using \a buffer to store the result.
1174
1175 If \a data is a span, adds all the byte array views to the hash, in the order given.
1176
1177 The return value will be a sub-span of \a buffer, unless \a buffer is of
1178 insufficient size, in which case a null QByteArrayView is returned.
1179
1180 \sa hash()
1181*/
1182QByteArrayView QCryptographicHash::hashInto(QSpan<std::byte> buffer,
1183 QSpan<const QByteArrayView> data,
1184 Algorithm method) noexcept
1185{
1186 if (buffer.size() < hashLengthInternal(method))
1187 return {}; // buffer too small
1188
1189 Q_DECL_UNINITIALIZED
1190 QCryptographicHashPrivate hash(method);
1191 for (QByteArrayView part : data)
1192 hash.addData(part);
1193 auto span = QSpan{reinterpret_cast<uchar *>(buffer.data()), buffer.size()};
1194 return hash.finalizeUnchecked(span); // no mutex needed: no-one but us has access to 'hash'
1195}
1196
1197/*!
1198 Returns the size of the output of the selected hash \a method in bytes.
1199
1200 \since 5.12
1201*/
1202int QCryptographicHash::hashLength(QCryptographicHash::Algorithm method)
1203{
1204 return hashLengthInternal(method);
1205}
1206
1207/*!
1208 Returns whether the selected algorithm \a method is supported and if
1209 result() will return a value when the \a method is used.
1210
1211 \note OpenSSL will be responsible for providing this information when
1212 used as a provider, otherwise \c true will be returned as the non-OpenSSL
1213 implementation doesn't have any restrictions.
1214 We return \c false if we fail to query OpenSSL.
1215
1216 \since 6.5
1217*/
1218
1219
1220bool QCryptographicHash::supportsAlgorithm(QCryptographicHash::Algorithm method)
1221{
1222 return QCryptographicHashPrivate::supportsAlgorithm(method);
1223}
1224
1225#ifdef USING_OPENSSL30
1226bool QCryptographicHashPrivate::supportsAlgorithm(QCryptographicHash::Algorithm method)
1227{
1228 // OpenSSL doesn't support Keccak*, Blake2b{160,256,384} and Blake2s{128,160,224},
1229 // and these would automatically return FALSE in that case, while they are
1230 // actually supported by our non-OpenSSL implementation.
1231 switch (method) {
1232 case QCryptographicHash::Keccak_224:
1233 case QCryptographicHash::Keccak_256:
1234 case QCryptographicHash::Keccak_384:
1235 case QCryptographicHash::Keccak_512:
1236 case QCryptographicHash::Blake2b_160:
1237 case QCryptographicHash::Blake2b_256:
1238 case QCryptographicHash::Blake2b_384:
1239 case QCryptographicHash::Blake2s_128:
1240 case QCryptographicHash::Blake2s_160:
1241 case QCryptographicHash::Blake2s_224:
1242 return true;
1243 case QCryptographicHash::Sha1:
1244 case QCryptographicHash::Md4:
1245 case QCryptographicHash::Md5:
1246 case QCryptographicHash::Sha224:
1247 case QCryptographicHash::Sha256:
1248 case QCryptographicHash::Sha384:
1249 case QCryptographicHash::Sha512:
1250 case QCryptographicHash::RealSha3_224:
1251 case QCryptographicHash::RealSha3_256:
1252 case QCryptographicHash::RealSha3_384:
1253 case QCryptographicHash::RealSha3_512:
1254 case QCryptographicHash::Blake2b_512:
1255 case QCryptographicHash::Blake2s_256: {
1256 // retain_fallbacks=1: don't disable the global default-provider fallback
1257 // auto-load (see QTBUG-136223 and the EVP constructor above).
1258 auto legacyProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_try_load(nullptr, "legacy", /*retain_fallbacks=*/1));
1259 auto defaultProvider = OSSL_PROVIDER_ptr(OSSL_PROVIDER_try_load(nullptr, "default", /*retain_fallbacks=*/1));
1260
1261 const char *restriction = "-fips";
1262 EVP_MD_ptr algorithm = EVP_MD_ptr(EVP_MD_fetch(nullptr, methodToName(method), restriction));
1263
1264 return algorithm != nullptr;
1265
1266 }
1267 case QCryptographicHash::NumAlgorithms:
1268 ;
1269 }
1270 return false;
1271
1272}
1273#else
1274bool QCryptographicHashPrivate::supportsAlgorithm(QCryptographicHash::Algorithm method)
1275{
1276 switch (method) {
1277 case QCryptographicHash::Sha1:
1278 case QCryptographicHash::Md4:
1279 case QCryptographicHash::Md5:
1280 case QCryptographicHash::Sha224:
1281 case QCryptographicHash::Sha256:
1282 case QCryptographicHash::Sha384:
1283 case QCryptographicHash::Sha512:
1284 case QCryptographicHash::RealSha3_224:
1285 case QCryptographicHash::Keccak_224:
1286 case QCryptographicHash::RealSha3_256:
1287 case QCryptographicHash::Keccak_256:
1288 case QCryptographicHash::RealSha3_384:
1289 case QCryptographicHash::Keccak_384:
1290 case QCryptographicHash::RealSha3_512:
1291 case QCryptographicHash::Keccak_512:
1292 case QCryptographicHash::Blake2b_160:
1293 case QCryptographicHash::Blake2b_256:
1294 case QCryptographicHash::Blake2b_384:
1295 case QCryptographicHash::Blake2b_512:
1296 case QCryptographicHash::Blake2s_128:
1297 case QCryptographicHash::Blake2s_160:
1298 case QCryptographicHash::Blake2s_224:
1299 case QCryptographicHash::Blake2s_256:
1300 return true;
1301 case QCryptographicHash::NumAlgorithms: ;
1302 };
1303 return false;
1304}
1305#endif // !USING_OPENSSL3
1306
1307static constexpr int qt_hash_block_size(QCryptographicHash::Algorithm method)
1308{
1309 switch (method) {
1310 case QCryptographicHash::Sha1:
1311 return SHA1_Message_Block_Size;
1312 case QCryptographicHash::Md4:
1313 return 64;
1314 case QCryptographicHash::Md5:
1315 return 64;
1316 case QCryptographicHash::Sha224:
1317 return SHA224_Message_Block_Size;
1318 case QCryptographicHash::Sha256:
1319 return SHA256_Message_Block_Size;
1320 case QCryptographicHash::Sha384:
1321 return SHA384_Message_Block_Size;
1322 case QCryptographicHash::Sha512:
1323 return SHA512_Message_Block_Size;
1324 case QCryptographicHash::RealSha3_224:
1325 case QCryptographicHash::Keccak_224:
1326 return 144;
1327 case QCryptographicHash::RealSha3_256:
1328 case QCryptographicHash::Keccak_256:
1329 return 136;
1330 case QCryptographicHash::RealSha3_384:
1331 case QCryptographicHash::Keccak_384:
1332 return 104;
1333 case QCryptographicHash::RealSha3_512:
1334 case QCryptographicHash::Keccak_512:
1335 return 72;
1336 case QCryptographicHash::Blake2b_160:
1337 case QCryptographicHash::Blake2b_256:
1338 case QCryptographicHash::Blake2b_384:
1339 case QCryptographicHash::Blake2b_512:
1340 return BLAKE2B_BLOCKBYTES;
1341 case QCryptographicHash::Blake2s_128:
1342 case QCryptographicHash::Blake2s_160:
1343 case QCryptographicHash::Blake2s_224:
1344 case QCryptographicHash::Blake2s_256:
1345 return BLAKE2S_BLOCKBYTES;
1346 case QCryptographicHash::NumAlgorithms:
1347#if !defined(Q_CC_GNU_ONLY) || Q_CC_GNU >= 900
1348 // GCC 8 has trouble with Q_UNREACHABLE() in constexpr functions
1349 Q_UNREACHABLE();
1350#endif
1351 break;
1352 }
1353 return 0;
1354}
1355
1356constexpr int maxHashBlockSize()
1357{
1358 int result = 0;
1359 using A = QCryptographicHash::Algorithm;
1360 for (int i = 0; i < A::NumAlgorithms ; ++i)
1361 result = std::max(result, qt_hash_block_size(A(i)));
1362 return result;
1363}
1364
1365[[maybe_unused]]
1366constexpr int minHashBlockSize()
1367{
1368 int result = INT_MAX;
1369 using A = QCryptographicHash::Algorithm;
1370 for (int i = 0; i < A::NumAlgorithms ; ++i)
1371 result = std::min(result, qt_hash_block_size(A(i)));
1372 return result;
1373}
1374
1375[[maybe_unused]]
1376constexpr int gcdHashBlockSize()
1377{
1378 int result = 0;
1379 using A = QCryptographicHash::Algorithm;
1380 for (int i = 0; i < A::NumAlgorithms ; ++i)
1381 result = std::gcd(result, qt_hash_block_size(A(i)));
1382 return result;
1383}
1384
1385using HashBlock = QSmallByteArray<maxHashBlockSize()>;
1386
1387static HashBlock xored(const HashBlock &block, quint8 val) noexcept
1388{
1389 // some hints for the optimizer:
1390 Q_ASSERT(block.size() >= minHashBlockSize());
1391 Q_ASSERT(block.size() <= maxHashBlockSize());
1392 Q_ASSERT(block.size() % gcdHashBlockSize() == 0);
1393
1394 Q_DECL_UNINITIALIZED
1395 HashBlock result;
1396 result.resizeForOverwrite(block.size());
1397 for (qsizetype i = 0; i < block.size(); ++i)
1398 result[i] = block[i] ^ val;
1399 return result;
1400}
1401
1403{
1404public:
1409
1412
1413 void setKey(QByteArrayView k) noexcept;
1414 void initMessageHash() noexcept;
1415 void finalize();
1416
1417 // when not called from the static hash() function, this function needs to be
1418 // called with messageHash.finalizeMutex held:
1419 void finalizeUnchecked() noexcept;
1420 // END functions that need to be called with finalizeMutex held
1421};
1422
1423/*!
1424 \internal
1425
1426 Transforms key \a newKey into a block-sized format and stores it in member
1427 \c key.
1428
1429 This function assumes it can use messageHash (i.e. it's in its initial
1430 state (reset() has been called)).
1431*/
1432void QMessageAuthenticationCodePrivate::setKey(QByteArrayView newKey) noexcept
1433{
1434 const int blockSize = qt_hash_block_size(messageHash.method);
1435
1436 if (newKey.size() > blockSize) {
1437 messageHash.addData(newKey);
1438 messageHash.finalizeUnchecked();
1439 static_assert([] {
1440 using A = QCryptographicHash::Algorithm;
1441 for (int i = 0; i < A::NumAlgorithms; ++i) {
1442 if (hashLengthInternal(A(i)) > qt_hash_block_size(A(i)))
1443 return false;
1444 }
1445 return true;
1446 }(), "this code assumes that a hash's result always fits into that hash's block size");
1447 key = messageHash.result;
1448 messageHash.reset();
1449 } else {
1450 key.assign(newKey);
1451 }
1452
1453 if (key.size() < blockSize)
1454 key.resize(blockSize, '\0');
1455
1457}
1458
1459/*!
1460 \internal
1461
1462 Seeds messageHash from \c key.
1463
1464 This function assumes that messageHash is in its initial state (reset() has
1465 been called).
1466*/
1468{
1469 messageHash.addData(xored(key, 0x36));
1470}
1471
1472/*!
1473 \class QMessageAuthenticationCode
1474 \inmodule QtCore
1475
1476 \brief The QMessageAuthenticationCode class provides a way to generate
1477 hash-based message authentication codes.
1478
1479 \since 5.1
1480
1481 \ingroup tools
1482 \reentrant
1483
1484 Use the QMessageAuthenticationCode class to generate hash-based message
1485 authentication codes (HMACs). The class supports all cryptographic
1486 hash algorithms from \l QCryptographicHash (see also
1487 \l{QCryptographicHash::Algorithm}).
1488
1489 To generate a message authentication code, pass a suitable hash
1490 algorithm and secret key to the constructor. Then process the message
1491 data by calling \l addData() one or more times. After the full
1492 message has been processed, get the final authentication code
1493 via the \l result() function:
1494
1495 \snippet qmessageauthenticationcode/main.cpp 0
1496 \dots
1497 \snippet qmessageauthenticationcode/main.cpp 1
1498
1499 For simple cases like above, you can also use the static
1500 \l hash() function:
1501
1502 \snippet qmessageauthenticationcode/main.cpp 2
1503
1504
1505 \note The cryptographic strength of the HMAC depends upon the
1506 size of the secret key, and the security of the
1507 underlying hash function.
1508
1509 \sa QCryptographicHash, QCryptographicHash::Algorithm
1510*/
1511
1512/*!
1513 Constructs an object that can be used to create a cryptographic hash from data
1514 using method \a method and key \a key.
1515
1516//! [qba-to-qbav-6.6]
1517 \note In Qt versions prior to 6.6, this function took its arguments as
1518 QByteArray, not QByteArrayView. If you experience compile errors, it's
1519 because your code is passing objects that are implicitly convertible to
1520 QByteArray, but not QByteArrayView. Wrap the corresponding argument in
1521 \c{QByteArray{~~~}} to make the cast explicit. This is backwards-compatible
1522 with old Qt versions.
1523//! [qba-to-qbav-6.6]
1524*/
1525QMessageAuthenticationCode::QMessageAuthenticationCode(QCryptographicHash::Algorithm method,
1526 QByteArrayView key)
1527 : d(new QMessageAuthenticationCodePrivate(method))
1528{
1529 d->setKey(key);
1530}
1531
1532/*!
1533 Destroys the object.
1534*/
1535QMessageAuthenticationCode::~QMessageAuthenticationCode()
1536{
1537 delete d;
1538}
1539
1540/*!
1541 \fn QMessageAuthenticationCode::QMessageAuthenticationCode(QMessageAuthenticationCode &&other)
1542
1543 Move-constructs a new QMessageAuthenticationCode from \a other.
1544
1545 \note The moved-from object \a other is placed in a
1546 partially-formed state, in which the only valid operations are
1547 destruction and assignment of a new object.
1548
1549 \since 6.6
1550*/
1551
1552/*!
1553 \fn QMessageAuthenticationCode &QMessageAuthenticationCode::operator=(QMessageAuthenticationCode &&other)
1554
1555 Move-assigns \a other to this QMessageAuthenticationCode instance.
1556
1557 \note The moved-from object \a other is placed in a
1558 partially-formed state, in which the only valid operations are
1559 destruction and assignment of a new object.
1560
1561 \since 6.6
1562*/
1563
1564/*!
1565 \fn void QMessageAuthenticationCode::swap(QMessageAuthenticationCode &other)
1566 \memberswap{message authentication code}
1567 \since 6.6
1568*/
1569
1570/*!
1571 Resets message data. Calling this function doesn't affect the key.
1572*/
1573void QMessageAuthenticationCode::reset() noexcept
1574{
1575 d->messageHash.reset();
1576 d->initMessageHash();
1577}
1578
1579/*!
1580 Sets secret \a key. Calling this function automatically resets the object state.
1581
1582 For optimal performance, call this function only to \e change the active key,
1583 not to set an \e initial key, as in
1584
1585 \code
1586 QMessageAuthenticationCode mac(method);
1587 mac.setKey(key); // does extra work
1588 use(mac);
1589 \endcode
1590
1591 Prefer to pass initial keys as the constructor argument:
1592
1593 \code
1594 QMessageAuthenticationCode mac(method, key); // OK, optimal
1595 use(mac);
1596 \endcode
1597
1598 You can use std::optional to delay construction of a
1599 QMessageAuthenticationCode until you know the key:
1600
1601 \code
1602 std::optional<QMessageAuthenticationCode> mac;
1603 ~~~
1604 key = ~~~;
1605 mac.emplace(method, key);
1606 use(*mac);
1607 \endcode
1608
1609 \include qcryptographichash.cpp {qba-to-qbav-6.6}
1610*/
1611void QMessageAuthenticationCode::setKey(QByteArrayView key) noexcept
1612{
1613 d->messageHash.reset();
1614 d->setKey(key);
1615}
1616
1617/*!
1618 \overload
1619 Adds the first \a length chars of \a data to the message.
1620*/
1621void QMessageAuthenticationCode::addData(const char *data, qsizetype length)
1622{
1623 d->messageHash.addData({data, length});
1624}
1625
1626/*!
1627 Adds \a data to the message.
1628
1629 \include qcryptographichash.cpp {qba-to-qbav-6.6}
1630
1631 \sa resultView(), result()
1632*/
1633void QMessageAuthenticationCode::addData(QByteArrayView data) noexcept
1634{
1635 d->messageHash.addData(data);
1636}
1637
1638/*!
1639 Reads the data from the open QIODevice \a device until it ends
1640 and adds it to message. Returns \c true if reading was successful.
1641
1642 \note \a device must be already opened.
1643 */
1644bool QMessageAuthenticationCode::addData(QIODevice *device)
1645{
1646 return d->messageHash.addData(device);
1647}
1648
1649/*!
1650 \since 6.6
1651
1652 Returns the final hash value.
1653
1654 Note that the returned view remains valid only as long as the
1655 QMessageAuthenticationCode object is not modified by other means.
1656
1657 \sa result()
1658*/
1659QByteArrayView QMessageAuthenticationCode::resultView() const noexcept
1660{
1661 d->finalize();
1662 return d->messageHash.resultView();
1663}
1664
1665/*!
1666 Returns the final authentication code.
1667
1668 \sa resultView(), QByteArray::toHex()
1669*/
1670QByteArray QMessageAuthenticationCode::result() const
1671{
1672 return resultView().toByteArray();
1673}
1674
1676{
1677 const auto lock = qt_scoped_lock(messageHash.finalizeMutex);
1678 if (!messageHash.result.isEmpty())
1679 return;
1681}
1682
1684{
1685 messageHash.finalizeUnchecked();
1686 const HashResult hashedMessage = messageHash.result;
1687
1688 messageHash.reset();
1689 messageHash.addData(xored(key, 0x5c));
1690 messageHash.addData(hashedMessage);
1691 messageHash.finalizeUnchecked();
1692}
1693
1694/*!
1695 Returns the authentication code for the message \a message using
1696 the key \a key and the method \a method.
1697
1698 \include qcryptographichash.cpp {qba-to-qbav-6.6}
1699
1700 \sa hashInto()
1701*/
1702QByteArray QMessageAuthenticationCode::hash(QByteArrayView message, QByteArrayView key,
1703 QCryptographicHash::Algorithm method)
1704{
1705 QByteArray ba(hashLengthInternal(method), Qt::Uninitialized);
1706 [[maybe_unused]] const auto r = hashInto(ba, message, key, method);
1707 Q_ASSERT(r.size() == ba.size());
1708 return ba;
1709}
1710
1711/*!
1712 \since 6.8
1713 \fn QMessageAuthenticationCode::hashInto(QSpan<char> buffer, QSpan<const QByteArrayView> messageParts, QByteArrayView key, QCryptographicHash::Algorithm method);
1714 \fn QMessageAuthenticationCode::hashInto(QSpan<uchar> buffer, QSpan<const QByteArrayView> messageParts, QByteArrayView key, QCryptographicHash::Algorithm method);
1715 \fn QMessageAuthenticationCode::hashInto(QSpan<std::byte> buffer, QSpan<const QByteArrayView> messageParts, QByteArrayView key, QCryptographicHash::Algorithm method);
1716 \fn QMessageAuthenticationCode::hashInto(QSpan<char> buffer, QByteArrayView message, QByteArrayView key, QCryptographicHash::Algorithm method);
1717 \fn QMessageAuthenticationCode::hashInto(QSpan<uchar> buffer, QByteArrayView message, QByteArrayView key, QCryptographicHash::Algorithm method);
1718 \fn QMessageAuthenticationCode::hashInto(QSpan<std::byte> buffer, QByteArrayView message, QByteArrayView key, QCryptographicHash::Algorithm method);
1719
1720 Returns the authentication code for the message (\a message or, for the
1721 QSpan overloads, the concatenation of \a messageParts) using the key \a key
1722 and the method \a method.
1723
1724 The return value will be a sub-span of \a buffer, unless \a buffer is of
1725 insufficient size, in which case a null QByteArrayView is returned.
1726
1727 \sa hash()
1728*/
1729QByteArrayView QMessageAuthenticationCode::hashInto(QSpan<std::byte> buffer,
1730 QSpan<const QByteArrayView> messageParts,
1731 QByteArrayView key,
1732 QCryptographicHash::Algorithm method) noexcept
1733{
1734 Q_DECL_UNINITIALIZED
1735 QMessageAuthenticationCodePrivate mac(method);
1736 mac.setKey(key);
1737 for (QByteArrayView part : messageParts)
1738 mac.messageHash.addData(part);
1739 mac.finalizeUnchecked();
1740 auto result = mac.messageHash.resultView();
1741 if (buffer.size() < result.size())
1742 return {}; // buffer too small
1743 // ### optimize: have the method directly write into `buffer`
1744 memcpy(buffer.data(), result.data(), result.size());
1745 return buffer.first(result.size());
1746}
1747
1748QT_END_NAMESPACE
1749
1750#ifndef QT_NO_QOBJECT
1751#include "moc_qcryptographichash.cpp"
1752#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