Branch data Line data Source code
1 : : // Copyright (C) 2021 The Qt Company Ltd.
2 : : // Copyright (C) 2019 Luxoft Sweden AB
3 : : // Copyright (C) 2018 Pelagicore AG
4 : : // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
5 : :
6 : : #include <QMutex>
7 : :
8 : : #include "global.h"
9 : : #include "cryptography.h"
10 : :
11 : : #if defined(Q_OS_UNIX)
12 : : # include <QFile>
13 : : #elif defined(Q_OS_WIN)
14 : : // all this mess is needed to get RtlGenRandom()
15 : : # include "windows.h"
16 : : # define SystemFunction036 NTAPI SystemFunction036
17 : : # include "ntsecapi.h"
18 : : # undef SystemFunction036
19 : : #endif
20 : :
21 : : #if defined(Q_OS_MACOS)
22 : : # include <QtCore/private/qcore_mac_p.h>
23 : : # include <Security/SecBase.h>
24 : : # include <Availability.h>
25 : : #endif
26 : :
27 : : #if defined(QT_AM_USE_LIBCRYPTO)
28 : : # include "libcryptofunction.h"
29 : :
30 : : QT_BEGIN_NAMESPACE_AM
31 : :
32 : 4 : Q_GLOBAL_STATIC(QMutex, initMutex)
33 : : static bool openSslInitialized = false;
34 : : static bool loadOpenSsl3LegacyProvider = false;
35 : :
36 : : // clazy:excludeall=non-pod-global-static
37 : : // AXIVION DISABLE Qt-NonPodGlobalStatic
38 : :
39 : : static QT_AM_LIBCRYPTO_FUNCTION(ERR_error_string_n, void(*)(unsigned long, char *, size_t));
40 : :
41 : : // AXIVION ENABLE Qt-NonPodGlobalStatic
42 : :
43 : : QT_END_NAMESPACE_AM
44 : :
45 : : #endif
46 : :
47 : : using namespace Qt::StringLiterals;
48 : :
49 : :
50 : : QT_BEGIN_NAMESPACE_AM
51 : :
52 : :
53 : 4 : QByteArray Cryptography::generateRandomBytes(int size)
54 : : {
55 : 4 : QByteArray result;
56 : :
57 [ + + ]: 4 : if (size > 0) {
58 : : #if defined(Q_OS_UNIX)
59 [ + - ]: 2 : QFile f(u"/dev/urandom"_s);
60 [ + - + - ]: 2 : if (f.open(QIODevice::ReadOnly)) {
61 [ + - ]: 2 : result = f.read(size);
62 [ - + ]: 2 : if (result.size() != size)
63 [ # # ]: 0 : result.clear();
64 : : }
65 : : #elif defined(Q_OS_WIN)
66 : : result.resize(size);
67 : : if (!RtlGenRandom(result.data(), size))
68 : : result.clear();
69 : : #endif
70 : 2 : }
71 : 4 : return result;
72 : 0 : }
73 : :
74 : :
75 : 24 : void Cryptography::initialize()
76 : : {
77 : : #if defined(QT_AM_USE_LIBCRYPTO)
78 [ + - ]: 24 : QMutexLocker locker(initMutex());
79 [ + + ]: 24 : if (!openSslInitialized) {
80 [ + - - + ]: 3 : if (!LibCryptoFunctionBase::initialize(loadOpenSsl3LegacyProvider))
81 : 0 : qFatal("Could not load libcrypto");
82 : 3 : openSslInitialized = true;
83 : : }
84 : : #endif
85 : 24 : }
86 : :
87 : 2 : void Cryptography::enableOpenSsl3LegacyProvider()
88 : : {
89 : : #if defined(QT_AM_USE_LIBCRYPTO)
90 [ + - ]: 2 : QMutexLocker locker(initMutex());
91 [ - + ]: 2 : if (openSslInitialized)
92 [ # # # # ]: 0 : qCritical("Cryptography::enableOpenSsl3LegacyProvider() needs to be called before using any other crypto functions.");
93 : : else
94 : 2 : loadOpenSsl3LegacyProvider = true;
95 : : #endif
96 : 2 : }
97 : :
98 : 12 : QString Cryptography::errorString(qint64 osCryptoError, const char *errorDescription)
99 : : {
100 : 12 : QString result;
101 [ + - + - ]: 12 : if (errorDescription && *errorDescription) {
102 [ + - ]: 12 : result = QString::fromLatin1(errorDescription);
103 [ + - ]: 24 : result.append(u": "_s);
104 : : }
105 : :
106 : : #if defined(QT_AM_USE_LIBCRYPTO)
107 [ + + ]: 12 : if (osCryptoError) {
108 : 8 : char msg[512];
109 : 8 : msg[sizeof(msg) - 1] = 0;
110 : :
111 : : //void ERR_error_string_n(unsigned long e, char *buf, size_t len);
112 [ + - ]: 8 : am_ERR_error_string_n(static_cast<unsigned long>(osCryptoError), msg, sizeof(msg) - 1);
113 [ + - + - ]: 16 : result.append(QString::fromLocal8Bit(msg));
114 : : }
115 : : #elif defined(Q_OS_WIN)
116 : : if (osCryptoError) {
117 : : LPWSTR msg = nullptr;
118 : : FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
119 : : nullptr, osCryptoError, 0, (LPWSTR) &msg, 0, nullptr);
120 : : // remove potential \r\n at the end
121 : : result.append(QString::fromWCharArray(msg).trimmed());
122 : : HeapFree(GetProcessHeap(), 0, msg);
123 : : }
124 : : #elif defined(Q_OS_MACOS)
125 : : if (osCryptoError) {
126 : : # if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(100300, 110300)
127 : : if (__builtin_available(macOS 10.3, iOS 12.3, *)) {
128 : : QCFType<CFStringRef> msg = SecCopyErrorMessageString(qint32(osCryptoError), nullptr);
129 : : result.append(QString::fromCFString(msg));
130 : : }
131 : : # else
132 : : result.append(QString::number(osCryptoError));
133 : : # endif
134 : : }
135 : : #else
136 : : Q_UNUSED(osCryptoError)
137 : : #endif
138 : :
139 : 12 : return result;
140 : 0 : }
141 : :
142 : : QT_END_NAMESPACE_AM
|