Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
27
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{
110 QList<QAsn1Element> items;
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
168 QList<QAsn1Element> items;
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{
202 QList<QAsn1Element> items;
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
249QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase)
250{
251 QList<QAsn1Element> items;
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
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:46
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:129
@ Rsa
Definition qssl.h:36
@ Dsa
Definition qssl.h:37
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]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
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:48
unsigned char quint8
Definition qtypes.h:46
QByteArray ba
[0]
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
QList< QSslCertificate > cert
[0]
const auto certs
[1]