1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | |
30 | #include <QtTest/QtTest> |
31 | #include "private/qasn1element_p.h" |
32 | |
33 | class tst_QAsn1Element : public QObject |
34 | { |
35 | Q_OBJECT |
36 | |
37 | private slots: |
38 | void emptyConstructor(); |
39 | void equals_data(); |
40 | void equals(); |
41 | void toBool_data(); |
42 | void toBool(); |
43 | void dateTime_data(); |
44 | void dateTime(); |
45 | void integer_data(); |
46 | void integer(); |
47 | void invalid_data(); |
48 | void invalid(); |
49 | void octetString_data(); |
50 | void octetString(); |
51 | void objectIdentifier_data(); |
52 | void objectIdentifier(); |
53 | void string_data(); |
54 | void string(); |
55 | }; |
56 | |
57 | void tst_QAsn1Element::emptyConstructor() |
58 | { |
59 | QAsn1Element elem; |
60 | QCOMPARE(elem.type(), quint8(0)); |
61 | QCOMPARE(elem.value(), QByteArray()); |
62 | } |
63 | |
64 | Q_DECLARE_METATYPE(QAsn1Element) |
65 | |
66 | void tst_QAsn1Element::equals_data() |
67 | { |
68 | QTest::addColumn<QAsn1Element>(name: "a" ); |
69 | QTest::addColumn<QAsn1Element>(name: "b" ); |
70 | QTest::addColumn<bool>(name: "equals" ); |
71 | |
72 | QTest::newRow(dataTag: "equal" ) |
73 | << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\0" , 1)) |
74 | << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\0" , 1)) |
75 | << true; |
76 | QTest::newRow(dataTag: "different type" ) |
77 | << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\0" , 1)) |
78 | << QAsn1Element(QAsn1Element::IntegerType, QByteArray("\0" , 1)) |
79 | << false; |
80 | QTest::newRow(dataTag: "different value" ) |
81 | << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\0" , 1)) |
82 | << QAsn1Element(QAsn1Element::BooleanType, QByteArray("\xff" , 1)) |
83 | << false; |
84 | } |
85 | |
86 | void tst_QAsn1Element::equals() |
87 | { |
88 | QFETCH(QAsn1Element, a); |
89 | QFETCH(QAsn1Element, b); |
90 | QFETCH(bool, equals); |
91 | QCOMPARE(a == b, equals); |
92 | QCOMPARE(a != b, !equals); |
93 | } |
94 | |
95 | void tst_QAsn1Element::toBool_data() |
96 | { |
97 | QTest::addColumn<QByteArray>(name: "encoded" ); |
98 | QTest::addColumn<bool>(name: "value" ); |
99 | QTest::addColumn<bool>(name: "valid" ); |
100 | |
101 | QTest::newRow(dataTag: "bad type" ) << QByteArray::fromHex(hexEncoded: "0201ff" ) << false << false; |
102 | QTest::newRow(dataTag: "bad value" ) << QByteArray::fromHex(hexEncoded: "010102" ) << false << false; |
103 | QTest::newRow(dataTag: "false" ) << QByteArray::fromHex(hexEncoded: "010100" ) << false << true; |
104 | QTest::newRow(dataTag: "true" ) << QByteArray::fromHex(hexEncoded: "0101ff" ) << true << true; |
105 | } |
106 | |
107 | void tst_QAsn1Element::toBool() |
108 | { |
109 | QFETCH(QByteArray, encoded); |
110 | QFETCH(bool, value); |
111 | QFETCH(bool, valid); |
112 | |
113 | bool ok; |
114 | QAsn1Element elem; |
115 | QVERIFY(elem.read(encoded)); |
116 | QCOMPARE(elem.toBool(&ok), value); |
117 | QCOMPARE(ok, valid); |
118 | } |
119 | |
120 | void tst_QAsn1Element::dateTime_data() |
121 | { |
122 | QTest::addColumn<QByteArray>(name: "encoded" ); |
123 | QTest::addColumn<QDateTime>(name: "value" ); |
124 | |
125 | QTest::newRow(dataTag: "bad type" ) |
126 | << QByteArray::fromHex(hexEncoded: "020100" ) |
127 | << QDateTime(); |
128 | QTest::newRow(dataTag: "UTCTime - 070417074026Z" ) |
129 | << QByteArray::fromHex(hexEncoded: "170d3037303431373037343032365a" ) |
130 | << QDateTime(QDate(2007, 4, 17), QTime(7, 40, 26), Qt::UTC); |
131 | QTest::newRow(dataTag: "UTCTime - bad length" ) |
132 | << QByteArray::fromHex(hexEncoded: "170c30373034313730373430325a" ) |
133 | << QDateTime(); |
134 | QTest::newRow(dataTag: "UTCTime - no trailing Z" ) |
135 | << QByteArray::fromHex(hexEncoded: "170d30373034313730373430323659" ) |
136 | << QDateTime(); |
137 | QTest::newRow(dataTag: "UTCTime - year 1950" ) |
138 | << QByteArray::fromHex(hexEncoded: "170d3530313232343035353530305a" ) |
139 | << QDateTime(QDate(1950, 12, 24), QTime(5, 55), Qt::UTC); |
140 | QTest::newRow(dataTag: "UTCTime - year 1999" ) |
141 | << QByteArray::fromHex(hexEncoded: "170d3939313232343035353530305a" ) |
142 | << QDateTime(QDate(1999, 12, 24), QTime(5, 55), Qt::UTC); |
143 | QTest::newRow(dataTag: "UTCTime - year 2000" ) |
144 | << QByteArray::fromHex(hexEncoded: "170d3030313232343035353530305a" ) |
145 | << QDateTime(QDate(2000, 12, 24), QTime(5, 55), Qt::UTC); |
146 | QTest::newRow(dataTag: "UTCTime - year 2049" ) |
147 | << QByteArray::fromHex(hexEncoded: "170d3439313232343035353530305a" ) |
148 | << QDateTime(QDate(2049, 12, 24), QTime(5, 55), Qt::UTC); |
149 | QTest::newRow(dataTag: "UTCTime - invalid year ('-9')" ) |
150 | << QByteArray::fromHex(hexEncoded: "170d2d39313232343035353530305a" ) |
151 | << QDateTime(); |
152 | QTest::newRow(dataTag: "UTCTime - invalid year ('*9')" ) |
153 | << QByteArray::fromHex(hexEncoded: "170d2a39313232343035353530305a" ) |
154 | << QDateTime(); |
155 | QTest::newRow(dataTag: "UTCTime - invalid year ('5*')" ) |
156 | << QByteArray::fromHex(hexEncoded: "170d352a313232343035353530305a" ) |
157 | << QDateTime(); |
158 | QTest::newRow(dataTag: "UTCTime - invalid year ('AB')" ) |
159 | << QByteArray::fromHex(hexEncoded: "170d4142313232343035353530305a" ) |
160 | << QDateTime(); |
161 | QTest::newRow(dataTag: "UTCTime - invalid year ('+1')" ) |
162 | << QByteArray::fromHex(hexEncoded: "170d2b31313232343035353530305a" ) |
163 | << QDateTime(); |
164 | QTest::newRow(dataTag: "GeneralizedTime - 20510829095341Z" ) |
165 | << QByteArray::fromHex(hexEncoded: "180f32303531303832393039353334315a" ) |
166 | << QDateTime(QDate(2051, 8, 29), QTime(9, 53, 41), Qt::UTC); |
167 | QTest::newRow(dataTag: "GeneralizedTime - bad length" ) |
168 | << QByteArray::fromHex(hexEncoded: "180e323035313038323930393533345a" ) |
169 | << QDateTime(); |
170 | QTest::newRow(dataTag: "GeneralizedTime - no trailing Z" ) |
171 | << QByteArray::fromHex(hexEncoded: "180f323035313038323930393533343159" ) |
172 | << QDateTime(); |
173 | } |
174 | |
175 | void tst_QAsn1Element::dateTime() |
176 | { |
177 | QFETCH(QByteArray, encoded); |
178 | QFETCH(QDateTime, value); |
179 | |
180 | QAsn1Element elem; |
181 | QVERIFY(elem.read(encoded)); |
182 | QCOMPARE(elem.toDateTime(), value); |
183 | } |
184 | |
185 | void tst_QAsn1Element::integer_data() |
186 | { |
187 | QTest::addColumn<QByteArray>(name: "encoded" ); |
188 | QTest::addColumn<int>(name: "value" ); |
189 | |
190 | QTest::newRow(dataTag: "0" ) << QByteArray::fromHex(hexEncoded: "020100" ) << 0; |
191 | QTest::newRow(dataTag: "127" ) << QByteArray::fromHex(hexEncoded: "02017F" ) << 127; |
192 | QTest::newRow(dataTag: "128" ) << QByteArray::fromHex(hexEncoded: "02020080" ) << 128; |
193 | QTest::newRow(dataTag: "256" ) << QByteArray::fromHex(hexEncoded: "02020100" ) << 256; |
194 | } |
195 | |
196 | void tst_QAsn1Element::integer() |
197 | { |
198 | QFETCH(QByteArray, encoded); |
199 | QFETCH(int, value); |
200 | |
201 | // read |
202 | bool ok; |
203 | QAsn1Element elem; |
204 | QVERIFY(elem.read(encoded)); |
205 | QCOMPARE(elem.type(), quint8(QAsn1Element::IntegerType)); |
206 | QCOMPARE(elem.toInteger(&ok), value); |
207 | QVERIFY(ok); |
208 | |
209 | // write |
210 | QByteArray buffer; |
211 | QDataStream stream(&buffer, QIODevice::WriteOnly); |
212 | QAsn1Element::fromInteger(val: value).write(data&: stream); |
213 | QCOMPARE(buffer, encoded); |
214 | } |
215 | |
216 | void tst_QAsn1Element::invalid_data() |
217 | { |
218 | QTest::addColumn<QByteArray>(name: "encoded" ); |
219 | |
220 | QTest::newRow(dataTag: "empty" ) << QByteArray(); |
221 | QTest::newRow(dataTag: "bad type" ) << QByteArray::fromHex(hexEncoded: "000100" ); |
222 | QTest::newRow(dataTag: "truncated value" ) << QByteArray::fromHex(hexEncoded: "0401" ); |
223 | } |
224 | |
225 | void tst_QAsn1Element::invalid() |
226 | { |
227 | QFETCH(QByteArray, encoded); |
228 | |
229 | QAsn1Element elem; |
230 | QVERIFY(!elem.read(encoded)); |
231 | } |
232 | |
233 | void tst_QAsn1Element::octetString_data() |
234 | { |
235 | QTest::addColumn<QByteArray>(name: "encoded" ); |
236 | QTest::addColumn<QByteArray>(name: "value" ); |
237 | |
238 | QTest::newRow(dataTag: "0 byte" ) << QByteArray::fromHex(hexEncoded: "0400" ) << QByteArray(); |
239 | QTest::newRow(dataTag: "1 byte" ) << QByteArray::fromHex(hexEncoded: "040100" ) << QByteArray(1, '\0'); |
240 | QTest::newRow(dataTag: "127 bytes" ) << QByteArray::fromHex(hexEncoded: "047f" ) + QByteArray(127, '\0') << QByteArray(127, '\0'); |
241 | QTest::newRow(dataTag: "128 bytes" ) << QByteArray::fromHex(hexEncoded: "048180" ) + QByteArray(128, '\0') << QByteArray(128, '\0'); |
242 | } |
243 | |
244 | void tst_QAsn1Element::octetString() |
245 | { |
246 | QFETCH(QByteArray, encoded); |
247 | QFETCH(QByteArray, value); |
248 | |
249 | // read |
250 | QAsn1Element elem; |
251 | QVERIFY(elem.read(encoded)); |
252 | QCOMPARE(elem.type(), quint8(QAsn1Element::OctetStringType)); |
253 | QCOMPARE(elem.value(), value); |
254 | |
255 | // write |
256 | QByteArray buffer; |
257 | QDataStream stream(&buffer, QIODevice::WriteOnly); |
258 | elem.write(data&: stream); |
259 | QCOMPARE(buffer, encoded); |
260 | } |
261 | |
262 | void tst_QAsn1Element::objectIdentifier_data() |
263 | { |
264 | QTest::addColumn<QByteArray>(name: "encoded" ); |
265 | QTest::addColumn<QByteArray>(name: "oid" ); |
266 | QTest::addColumn<QByteArray>(name: "name" ); |
267 | |
268 | QTest::newRow(dataTag: "1.2.3.4" ) |
269 | << QByteArray::fromHex(hexEncoded: "06032a0304" ) |
270 | << QByteArray("1.2.3.4" ) |
271 | << QByteArray("1.2.3.4" ); |
272 | QTest::newRow(dataTag: "favouriteDrink" ) |
273 | << QByteArray::fromHex(hexEncoded: "060a0992268993f22c640105" ) |
274 | << QByteArray("0.9.2342.19200300.100.1.5" ) |
275 | << QByteArray("favouriteDrink" ); |
276 | } |
277 | |
278 | void tst_QAsn1Element::objectIdentifier() |
279 | { |
280 | QFETCH(QByteArray, encoded); |
281 | QFETCH(QByteArray, oid); |
282 | QFETCH(QByteArray, name); |
283 | |
284 | QAsn1Element elem; |
285 | QVERIFY(elem.read(encoded)); |
286 | QCOMPARE(elem.type(), quint8(QAsn1Element::ObjectIdentifierType)); |
287 | QCOMPARE(elem.toObjectId(), oid); |
288 | QCOMPARE(QAsn1Element::fromObjectId(oid).toObjectId(), oid); |
289 | QCOMPARE(elem.toObjectName(), name); |
290 | } |
291 | |
292 | void tst_QAsn1Element::string_data() |
293 | { |
294 | QTest::addColumn<QAsn1Element>(name: "element" ); |
295 | QTest::addColumn<QString>(name: "value" ); |
296 | |
297 | QTest::newRow(dataTag: "printablestring" ) |
298 | << QAsn1Element(QAsn1Element::PrintableStringType, QByteArray("Hello World" )) |
299 | << QStringLiteral("Hello World" ); |
300 | QTest::newRow(dataTag: "teletextstring" ) |
301 | << QAsn1Element(QAsn1Element::TeletexStringType, QByteArray("Hello World" )) |
302 | << QStringLiteral("Hello World" ); |
303 | QTest::newRow(dataTag: "utf8string" ) |
304 | << QAsn1Element(QAsn1Element::Utf8StringType, QByteArray("Hello World" )) |
305 | << QStringLiteral("Hello World" ); |
306 | QTest::newRow(dataTag: "rfc822name" ) |
307 | << QAsn1Element(QAsn1Element::Rfc822NameType, QByteArray("Hello World" )) |
308 | << QStringLiteral("Hello World" ); |
309 | QTest::newRow(dataTag: "dnsname" ) |
310 | << QAsn1Element(QAsn1Element::DnsNameType, QByteArray("Hello World" )) |
311 | << QStringLiteral("Hello World" ); |
312 | QTest::newRow(dataTag: "uri" ) |
313 | << QAsn1Element(QAsn1Element::UniformResourceIdentifierType, QByteArray("Hello World" )) |
314 | << QStringLiteral("Hello World" ); |
315 | |
316 | // Embedded NULs are not allowed and should be rejected |
317 | QTest::newRow(dataTag: "evil_printablestring" ) |
318 | << QAsn1Element(QAsn1Element::PrintableStringType, QByteArray("Hello\0World" , 11)) |
319 | << QString(); |
320 | QTest::newRow(dataTag: "evil_teletextstring" ) |
321 | << QAsn1Element(QAsn1Element::TeletexStringType, QByteArray("Hello\0World" , 11)) |
322 | << QString(); |
323 | QTest::newRow(dataTag: "evil_utf8string" ) |
324 | << QAsn1Element(QAsn1Element::Utf8StringType, QByteArray("Hello\0World" , 11)) |
325 | << QString(); |
326 | QTest::newRow(dataTag: "evil_rfc822name" ) |
327 | << QAsn1Element(QAsn1Element::Rfc822NameType, QByteArray("Hello\0World" , 11)) |
328 | << QString(); |
329 | QTest::newRow(dataTag: "evil_dnsname" ) |
330 | << QAsn1Element(QAsn1Element::DnsNameType, QByteArray("Hello\0World" , 11)) |
331 | << QString(); |
332 | QTest::newRow(dataTag: "evil_uri" ) |
333 | << QAsn1Element(QAsn1Element::UniformResourceIdentifierType, QByteArray("Hello\0World" , 11)) |
334 | << QString(); |
335 | } |
336 | |
337 | void tst_QAsn1Element::string() |
338 | { |
339 | QFETCH(QAsn1Element, element); |
340 | QFETCH(QString, value); |
341 | |
342 | QCOMPARE(element.toString(), value); |
343 | } |
344 | |
345 | QTEST_MAIN(tst_QAsn1Element) |
346 | #include "tst_qasn1element.moc" |
347 | |