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