Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qsslsocket_qt.cpp
Go to the documentation of this file.
1// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qasn1element_p.h"
5
6#include <QtCore/qbytearray.h>
7#include <QtCore/qdatastream.h>
8#include <QtCore/qmessageauthenticationcode.h>
9#include <QtCore/qrandom.h>
10
11#include <QtNetwork/private/qsslsocket_p.h>
12#include <QtNetwork/private/qsslkey_p.h>
13
15
16/*
17 PKCS12 helpers.
18*/
19
21{
24 child.write(stream);
25 return QAsn1Element(type, value);
26}
27
29{
31 items << QAsn1Element::fromObjectId("1.2.840.113549.1.7.1");
35}
36
44static QByteArray _q_PKCS12_keygen(char id, const QByteArray &salt, const QString &passPhrase, int n, int r)
45{
46 const int u = 20;
47 const int v = 64;
48
49 // password formatting
50 QByteArray passUnicode(passPhrase.size() * 2 + 2, '\0');
51 char *p = passUnicode.data();
52 for (int i = 0; i < passPhrase.size(); ++i) {
53 quint16 ch = passPhrase[i].unicode();
54 *(p++) = (ch & 0xff00) >> 8;
55 *(p++) = (ch & 0xff);
56 }
57
58 // prepare I
59 QByteArray D(64, id);
60 QByteArray S, P;
61 const int sSize = v * ((salt.size() + v - 1) / v);
62 S.resize(sSize);
63 for (int i = 0; i < sSize; ++i)
64 S[i] = salt[i % salt.size()];
65 const int pSize = v * ((passUnicode.size() + v - 1) / v);
66 P.resize(pSize);
67 for (int i = 0; i < pSize; ++i)
68 P[i] = passUnicode[i % passUnicode.size()];
69 QByteArray I = S + P;
70
71 // apply hashing
72 const int c = (n + u - 1) / u;
75 B.resize(v);
76 for (int i = 0; i < c; ++i) {
77 // hash r iterations
78 QByteArray Ai = D + I;
79 for (int j = 0; j < r; ++j)
81
82 for (int j = 0; j < v; ++j)
83 B[j] = Ai[j % u];
84
85 // modify I as Ij = (Ij + B + 1) modulo 2^v
86 for (int p = 0; p < I.size(); p += v) {
87 quint8 carry = 1;
88 for (int j = v - 1; j >= 0; --j) {
89 quint16 v = quint8(I[p + j]) + quint8(B[j]) + carry;
90 I[p + j] = v & 0xff;
91 carry = (v & 0xff00) >> 8;
92 }
93 }
94 A += Ai;
95 }
96 return A.left(n);
97}
98
100{
101 QByteArray salt;
102 salt.resize(8);
103 for (int i = 0; i < salt.size(); ++i)
104 salt[i] = (QRandomGenerator::global()->generate() & 0xff);
105 return salt;
106}
107
109{
111 items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.3");
112
113 // certificate
114 QList<QAsn1Element> certItems;
115 certItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.22.1");
116 certItems << wrap(QAsn1Element::Context0Type,
119 QAsn1Element::fromVector(certItems));
120
121 // local key id
122 const QByteArray localKeyId = cert.digest(QCryptographicHash::Sha1);
123 QList<QAsn1Element> idItems;
124 idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21");
125 idItems << wrap(QAsn1Element::SetType,
128
129 // dump
133 root.write(stream);
134 return ba;
135}
136
138{
139 Q_ASSERT(key.algorithm() == QSsl::Rsa || key.algorithm() == QSsl::Dsa);
140
141 QList<QAsn1Element> keyItems;
142 keyItems << QAsn1Element::fromInteger(0);
143 QList<QAsn1Element> algoItems;
144 if (key.algorithm() == QSsl::Rsa)
146 else if (key.algorithm() == QSsl::Dsa)
149 keyItems << QAsn1Element::fromVector(algoItems);
150 keyItems << QAsn1Element(QAsn1Element::OctetStringType, key.toDer());
151 return QAsn1Element::fromVector(keyItems);
152}
153
154static QByteArray _q_PKCS12_shroudedKeyBag(const QSslKey &key, const QString &passPhrase, const QByteArray &localKeyId)
155{
156 const int iterations = 2048;
157 QByteArray salt = _q_PKCS12_salt();
158 QByteArray cKey = _q_PKCS12_keygen(1, salt, passPhrase, 24, iterations);
159 QByteArray cIv = _q_PKCS12_keygen(2, salt, passPhrase, 8, iterations);
160
161 // prepare and encrypt data
162 QByteArray plain;
163 QDataStream plainStream(&plain, QIODevice::WriteOnly);
164 _q_PKCS12_key(key).write(plainStream);
166 plain, cKey, cIv);
167
169 items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.2");
170
171 // key
172 QList<QAsn1Element> keyItems;
173 QList<QAsn1Element> algoItems;
174 algoItems << QAsn1Element::fromObjectId("1.2.840.113549.1.12.1.3");
175 QList<QAsn1Element> paramItems;
176 paramItems << QAsn1Element(QAsn1Element::OctetStringType, salt);
177 paramItems << QAsn1Element::fromInteger(iterations);
178 algoItems << QAsn1Element::fromVector(paramItems);
179 keyItems << QAsn1Element::fromVector(algoItems);
180 keyItems << QAsn1Element(QAsn1Element::OctetStringType, crypted);
182 QAsn1Element::fromVector(keyItems));
183
184 // local key id
185 QList<QAsn1Element> idItems;
186 idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21");
187 idItems << wrap(QAsn1Element::SetType,
190 QAsn1Element::fromVector(idItems));
191
192 // dump
196 root.write(stream);
197 return ba;
198}
199
200static QByteArray _q_PKCS12_bag(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase)
201{
203
204 // certs
205 for (int i = 0; i < certs.size(); ++i)
207
208 // key
209 if (!key.isNull()) {
210 const QByteArray localKeyId = certs.first().digest(QCryptographicHash::Sha1);
211 items << _q_PKCS7_data(_q_PKCS12_shroudedKeyBag(key, passPhrase, localKeyId));
212 }
213
214 // dump
218 root.write(stream);
219 return ba;
220}
221
222static QAsn1Element _q_PKCS12_mac(const QByteArray &data, const QString &passPhrase)
223{
224 const int iterations = 2048;
225
226 // salt generation
227 QByteArray macSalt = _q_PKCS12_salt();
228 QByteArray key = _q_PKCS12_keygen(3, macSalt, passPhrase, 20, iterations);
229
230 // HMAC calculation
232 hmac.addData(data);
233
234 QList<QAsn1Element> algoItems;
235 algoItems << QAsn1Element::fromObjectId("1.3.14.3.2.26");
237
238 QList<QAsn1Element> digestItems;
239 digestItems << QAsn1Element::fromVector(algoItems);
240 digestItems << QAsn1Element(QAsn1Element::OctetStringType, hmac.result());
241
242 QList<QAsn1Element> macItems;
243 macItems << QAsn1Element::fromVector(digestItems);
244 macItems << QAsn1Element(QAsn1Element::OctetStringType, macSalt);
245 macItems << QAsn1Element::fromInteger(iterations);
246 return QAsn1Element::fromVector(macItems);
247}
248
250{
252
253 // version
255
256 // auth safe
257 const QByteArray data = _q_PKCS12_bag(certs, key, passPhrase);
259
260 // HMAC
261 items << _q_PKCS12_mac(data, passPhrase);
262
263 // dump
267 root.write(stream);
268 return ba;
269}
270
static QAsn1Element fromVector(const QList< QAsn1Element > &items)
static QAsn1Element fromObjectId(const QByteArray &id)
void write(QDataStream &data) const
static QAsn1Element fromInteger(unsigned int val)
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
static QByteArray hash(QByteArrayView data, Algorithm method)
Returns the hash of data using method.
\inmodule QtCore\reentrant
Definition qdatastream.h:30
Definition qlist.h:74
void addData(const char *data, qsizetype length)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray result() const
Returns the final authentication code.
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
\threadsafe
Definition qrandom.h:275
The QSslCertificate class provides a convenient API for an X509 certificate.
static Q_NETWORK_EXPORT QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv)
Definition qsslkey_p.cpp:87
The QSslKey class provides an interface for private and public keys.
Definition qsslkey.h:23
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
const QChar * unicode() const
Returns a Unicode representation of the string.
Definition qstring.h:1085
@ Rsa
Definition qssl.h:31
@ Dsa
Definition qssl.h:32
Combined button and popup list for selecting options.
#define DSA_ENCRYPTION_OID
#define RSA_ENCRYPTION_OID
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
n varying highp vec2 A
GLsizei const GLfloat * v
[13]
GLuint64 key
GLboolean r
[2]
GLenum type
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat n
const GLubyte * c
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QByteArray _q_PKCS12_salt()
static QAsn1Element _q_PKCS7_data(const QByteArray &data)
QByteArray _q_makePkcs12(const QList< QSslCertificate > &certs, const QSslKey &key, const QString &passPhrase)
static QByteArray _q_PKCS12_bag(const QList< QSslCertificate > &certs, const QSslKey &key, const QString &passPhrase)
static QByteArray _q_PKCS12_certBag(const QSslCertificate &cert)
static QByteArray _q_PKCS12_shroudedKeyBag(const QSslKey &key, const QString &passPhrase, const QByteArray &localKeyId)
static QAsn1Element _q_PKCS12_mac(const QByteArray &data, const QString &passPhrase)
static QByteArray _q_PKCS12_keygen(char id, const QByteArray &salt, const QString &passPhrase, int n, int r)
PKCS #12 key derivation.
static QAsn1Element _q_PKCS12_key(const QSslKey &key)
static QT_BEGIN_NAMESPACE QAsn1Element wrap(quint8 type, const QAsn1Element &child)
unsigned short quint16
Definition qtypes.h:43
unsigned char quint8
Definition qtypes.h:41
QByteArray ba
[0]
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
QList< QSslCertificate > cert
[0]
const auto certs
[1]