1 | /* |
2 | * Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com> |
3 | * Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net> |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2.1 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Lesser General Public |
16 | * License along with this library; if not, write to the Free Software |
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 | * 02110-1301 USA |
19 | * |
20 | */ |
21 | |
22 | #include "qca_core.h" |
23 | |
24 | #include "qca_cert.h" |
25 | #include "qca_textfilter.h" |
26 | #include "qcaprovider.h" |
27 | #include <QMutex> |
28 | |
29 | #ifndef QCA_NO_SYSTEMSTORE |
30 | #include "qca_systemstore.h" |
31 | #endif |
32 | |
33 | #include <cstdlib> |
34 | |
35 | #define FRIENDLY_NAMES |
36 | |
37 | namespace QCA { |
38 | |
39 | class DefaultShared |
40 | { |
41 | private: |
42 | mutable QMutex m; |
43 | bool _use_system; |
44 | QString _roots_file; |
45 | QStringList _skip_plugins; |
46 | QStringList _plugin_priorities; |
47 | |
48 | public: |
49 | DefaultShared() |
50 | : _use_system(true) |
51 | { |
52 | } |
53 | |
54 | bool use_system() const |
55 | { |
56 | QMutexLocker locker(&m); |
57 | return _use_system; |
58 | } |
59 | |
60 | QString roots_file() const |
61 | { |
62 | QMutexLocker locker(&m); |
63 | return _roots_file; |
64 | } |
65 | |
66 | QStringList skip_plugins() const |
67 | { |
68 | QMutexLocker locker(&m); |
69 | return _skip_plugins; |
70 | } |
71 | |
72 | QStringList plugin_priorities() const |
73 | { |
74 | QMutexLocker locker(&m); |
75 | return _plugin_priorities; |
76 | } |
77 | |
78 | void set(bool use_system, |
79 | const QString &roots_file, |
80 | const QStringList &skip_plugins, |
81 | const QStringList &plugin_priorities) |
82 | { |
83 | QMutexLocker locker(&m); |
84 | _use_system = use_system; |
85 | _roots_file = roots_file; |
86 | _skip_plugins = skip_plugins; |
87 | _plugin_priorities = plugin_priorities; |
88 | } |
89 | }; |
90 | |
91 | //---------------------------------------------------------------------------- |
92 | // DefaultRandomContext |
93 | //---------------------------------------------------------------------------- |
94 | class DefaultRandomContext : public RandomContext |
95 | { |
96 | Q_OBJECT |
97 | public: |
98 | DefaultRandomContext(Provider *p) |
99 | : RandomContext(p) |
100 | { |
101 | } |
102 | |
103 | Provider::Context *clone() const override |
104 | { |
105 | return new DefaultRandomContext(provider()); |
106 | } |
107 | |
108 | SecureArray nextBytes(int size) override |
109 | { |
110 | SecureArray buf(size); |
111 | for (int n = 0; n < (int)buf.size(); ++n) |
112 | buf[n] = (char)std::rand(); |
113 | return buf; |
114 | } |
115 | }; |
116 | |
117 | //---------------------------------------------------------------------------- |
118 | // DefaultMD5Context |
119 | //---------------------------------------------------------------------------- |
120 | |
121 | /* NOTE: the following code was modified to not need BYTE_ORDER -- Justin */ |
122 | |
123 | /* |
124 | Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. |
125 | |
126 | This software is provided 'as-is', without any express or implied |
127 | warranty. In no event will the authors be held liable for any damages |
128 | arising from the use of this software. |
129 | |
130 | Permission is granted to anyone to use this software for any purpose, |
131 | including commercial applications, and to alter it and redistribute it |
132 | freely, subject to the following restrictions: |
133 | |
134 | 1. The origin of this software must not be misrepresented; you must not |
135 | claim that you wrote the original software. If you use this software |
136 | in a product, an acknowledgment in the product documentation would be |
137 | appreciated but is not required. |
138 | 2. Altered source versions must be plainly marked as such, and must not be |
139 | misrepresented as being the original software. |
140 | 3. This notice may not be removed or altered from any source distribution. |
141 | |
142 | L. Peter Deutsch |
143 | ghost@aladdin.com |
144 | |
145 | */ |
146 | /* $Id$ */ |
147 | /* |
148 | Independent implementation of MD5 (RFC 1321). |
149 | |
150 | This code implements the MD5 Algorithm defined in RFC 1321, whose |
151 | text is available at |
152 | http://www.ietf.org/rfc/rfc1321.txt |
153 | The code is derived from the text of the RFC, including the test suite |
154 | (section A.5) but excluding the rest of Appendix A. It does not include |
155 | any code or documentation that is identified in the RFC as being |
156 | copyrighted. |
157 | |
158 | The original and principal author of md5.c is L. Peter Deutsch |
159 | <ghost@aladdin.com>. Other authors are noted in the change history |
160 | that follows (in reverse chronological order): |
161 | |
162 | 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order |
163 | either statically or dynamically; added missing #include <string.h> |
164 | in library. |
165 | 2002-03-11 lpd Corrected argument list for main(), and added int return |
166 | type, in test program and T value program. |
167 | 2002-02-21 lpd Added missing #include <stdio.h> in test program. |
168 | 2000-07-03 lpd Patched to eliminate warnings about "constant is |
169 | unsigned in ANSI C, signed in traditional"; made test program |
170 | self-checking. |
171 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. |
172 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). |
173 | 1999-05-03 lpd Original version. |
174 | */ |
175 | |
176 | /* |
177 | * This package supports both compile-time and run-time determination of CPU |
178 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be |
179 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is |
180 | * defined as non-zero, the code will be compiled to run only on big-endian |
181 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to |
182 | * run on either big- or little-endian CPUs, but will run slightly less |
183 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. |
184 | */ |
185 | |
186 | typedef quint8 md5_byte_t; /* 8-bit byte */ |
187 | typedef quint32 md5_word_t; /* 32-bit word */ |
188 | |
189 | /* Define the state of the MD5 Algorithm. */ |
190 | struct md5_state_t |
191 | { |
192 | md5_word_t count[2]; // 2 /* message length in bits, lsw first */ |
193 | md5_word_t abcd[4]; // 4 /* digest buffer */ |
194 | md5_byte_t buf[64]; // 64 /* accumulate block */ |
195 | |
196 | md5_state_t() |
197 | { |
198 | memset(s: count, c: 0, n: sizeof(count)); |
199 | memset(s: abcd, c: 0, n: sizeof(abcd)); |
200 | memset(s: buf, c: 0, n: sizeof(buf)); |
201 | } |
202 | }; |
203 | |
204 | /* Initialize the algorithm. */ |
205 | void md5_init(md5_state_t *pms); |
206 | |
207 | /* Append a string to the message. */ |
208 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); |
209 | |
210 | /* Finish the message and return the digest. */ |
211 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); |
212 | |
213 | #define T_MASK ((md5_word_t)~0) |
214 | #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) |
215 | #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) |
216 | #define T3 0x242070db |
217 | #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) |
218 | #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) |
219 | #define T6 0x4787c62a |
220 | #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) |
221 | #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) |
222 | #define T9 0x698098d8 |
223 | #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) |
224 | #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) |
225 | #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) |
226 | #define T13 0x6b901122 |
227 | #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) |
228 | #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) |
229 | #define T16 0x49b40821 |
230 | #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) |
231 | #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) |
232 | #define T19 0x265e5a51 |
233 | #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) |
234 | #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) |
235 | #define T22 0x02441453 |
236 | #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) |
237 | #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) |
238 | #define T25 0x21e1cde6 |
239 | #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) |
240 | #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) |
241 | #define T28 0x455a14ed |
242 | #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) |
243 | #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) |
244 | #define T31 0x676f02d9 |
245 | #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) |
246 | #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) |
247 | #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) |
248 | #define T35 0x6d9d6122 |
249 | #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) |
250 | #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) |
251 | #define T38 0x4bdecfa9 |
252 | #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) |
253 | #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) |
254 | #define T41 0x289b7ec6 |
255 | #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) |
256 | #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) |
257 | #define T44 0x04881d05 |
258 | #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) |
259 | #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) |
260 | #define T47 0x1fa27cf8 |
261 | #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) |
262 | #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) |
263 | #define T50 0x432aff97 |
264 | #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) |
265 | #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) |
266 | #define T53 0x655b59c3 |
267 | #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) |
268 | #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) |
269 | #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) |
270 | #define T57 0x6fa87e4f |
271 | #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) |
272 | #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) |
273 | #define T60 0x4e0811a1 |
274 | #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) |
275 | #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) |
276 | #define T63 0x2ad7d2bb |
277 | #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) |
278 | |
279 | static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) |
280 | { |
281 | md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; |
282 | md5_word_t t; |
283 | |
284 | /* Define storage for little-endian or both types of CPUs. */ |
285 | md5_word_t xbuf[16]; |
286 | const md5_word_t *X; |
287 | |
288 | { |
289 | if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { |
290 | /* |
291 | * On big-endian machines, we must arrange the bytes in the |
292 | * right order. |
293 | */ |
294 | const md5_byte_t *xp = data; |
295 | int i; |
296 | |
297 | X = xbuf; /* (dynamic only) */ |
298 | |
299 | for (i = 0; i < 16; ++i, xp += 4) |
300 | xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); |
301 | } else /* dynamic big-endian */ |
302 | { |
303 | /* |
304 | * On little-endian machines, we can process properly aligned |
305 | * data without copying it. On arm do copying always |
306 | */ |
307 | #ifndef Q_PROCESSOR_ARM |
308 | if (!(reinterpret_cast<uintptr_t>(data) & 3)) { |
309 | /* data are properly aligned */ |
310 | X = reinterpret_cast<const md5_word_t *>(data); |
311 | } else |
312 | #endif |
313 | { |
314 | /* not aligned */ |
315 | memcpy(dest: xbuf, src: data, n: 64); |
316 | X = xbuf; |
317 | } |
318 | } |
319 | } |
320 | |
321 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) |
322 | |
323 | /* Round 1. */ |
324 | /* Let [abcd k s i] denote the operation |
325 | a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ |
326 | #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) |
327 | #define SET(a, b, c, d, k, s, Ti) \ |
328 | t = a + F(b, c, d) + X[k] + Ti; \ |
329 | a = ROTATE_LEFT(t, s) + b |
330 | /* Do the following 16 operations. */ |
331 | SET(a, b, c, d, 0, 7, T1); |
332 | SET(d, a, b, c, 1, 12, T2); |
333 | SET(c, d, a, b, 2, 17, T3); |
334 | SET(b, c, d, a, 3, 22, T4); |
335 | SET(a, b, c, d, 4, 7, T5); |
336 | SET(d, a, b, c, 5, 12, T6); |
337 | SET(c, d, a, b, 6, 17, T7); |
338 | SET(b, c, d, a, 7, 22, T8); |
339 | SET(a, b, c, d, 8, 7, T9); |
340 | SET(d, a, b, c, 9, 12, T10); |
341 | SET(c, d, a, b, 10, 17, T11); |
342 | SET(b, c, d, a, 11, 22, T12); |
343 | SET(a, b, c, d, 12, 7, T13); |
344 | SET(d, a, b, c, 13, 12, T14); |
345 | SET(c, d, a, b, 14, 17, T15); |
346 | SET(b, c, d, a, 15, 22, T16); |
347 | #undef SET |
348 | |
349 | /* Round 2. */ |
350 | /* Let [abcd k s i] denote the operation |
351 | a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ |
352 | #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) |
353 | #define SET(a, b, c, d, k, s, Ti) \ |
354 | t = a + G(b, c, d) + X[k] + Ti; \ |
355 | a = ROTATE_LEFT(t, s) + b |
356 | /* Do the following 16 operations. */ |
357 | SET(a, b, c, d, 1, 5, T17); |
358 | SET(d, a, b, c, 6, 9, T18); |
359 | SET(c, d, a, b, 11, 14, T19); |
360 | SET(b, c, d, a, 0, 20, T20); |
361 | SET(a, b, c, d, 5, 5, T21); |
362 | SET(d, a, b, c, 10, 9, T22); |
363 | SET(c, d, a, b, 15, 14, T23); |
364 | SET(b, c, d, a, 4, 20, T24); |
365 | SET(a, b, c, d, 9, 5, T25); |
366 | SET(d, a, b, c, 14, 9, T26); |
367 | SET(c, d, a, b, 3, 14, T27); |
368 | SET(b, c, d, a, 8, 20, T28); |
369 | SET(a, b, c, d, 13, 5, T29); |
370 | SET(d, a, b, c, 2, 9, T30); |
371 | SET(c, d, a, b, 7, 14, T31); |
372 | SET(b, c, d, a, 12, 20, T32); |
373 | #undef SET |
374 | |
375 | /* Round 3. */ |
376 | /* Let [abcd k s t] denote the operation |
377 | a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ |
378 | #define H(x, y, z) ((x) ^ (y) ^ (z)) |
379 | #define SET(a, b, c, d, k, s, Ti) \ |
380 | t = a + H(b, c, d) + X[k] + Ti; \ |
381 | a = ROTATE_LEFT(t, s) + b |
382 | /* Do the following 16 operations. */ |
383 | SET(a, b, c, d, 5, 4, T33); |
384 | SET(d, a, b, c, 8, 11, T34); |
385 | SET(c, d, a, b, 11, 16, T35); |
386 | SET(b, c, d, a, 14, 23, T36); |
387 | SET(a, b, c, d, 1, 4, T37); |
388 | SET(d, a, b, c, 4, 11, T38); |
389 | SET(c, d, a, b, 7, 16, T39); |
390 | SET(b, c, d, a, 10, 23, T40); |
391 | SET(a, b, c, d, 13, 4, T41); |
392 | SET(d, a, b, c, 0, 11, T42); |
393 | SET(c, d, a, b, 3, 16, T43); |
394 | SET(b, c, d, a, 6, 23, T44); |
395 | SET(a, b, c, d, 9, 4, T45); |
396 | SET(d, a, b, c, 12, 11, T46); |
397 | SET(c, d, a, b, 15, 16, T47); |
398 | SET(b, c, d, a, 2, 23, T48); |
399 | #undef SET |
400 | |
401 | /* Round 4. */ |
402 | /* Let [abcd k s t] denote the operation |
403 | a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ |
404 | #define I(x, y, z) ((y) ^ ((x) | ~(z))) |
405 | #define SET(a, b, c, d, k, s, Ti) \ |
406 | t = a + I(b, c, d) + X[k] + Ti; \ |
407 | a = ROTATE_LEFT(t, s) + b |
408 | /* Do the following 16 operations. */ |
409 | SET(a, b, c, d, 0, 6, T49); |
410 | SET(d, a, b, c, 7, 10, T50); |
411 | SET(c, d, a, b, 14, 15, T51); |
412 | SET(b, c, d, a, 5, 21, T52); |
413 | SET(a, b, c, d, 12, 6, T53); |
414 | SET(d, a, b, c, 3, 10, T54); |
415 | SET(c, d, a, b, 10, 15, T55); |
416 | SET(b, c, d, a, 1, 21, T56); |
417 | SET(a, b, c, d, 8, 6, T57); |
418 | SET(d, a, b, c, 15, 10, T58); |
419 | SET(c, d, a, b, 6, 15, T59); |
420 | SET(b, c, d, a, 13, 21, T60); |
421 | SET(a, b, c, d, 4, 6, T61); |
422 | SET(d, a, b, c, 11, 10, T62); |
423 | SET(c, d, a, b, 2, 15, T63); |
424 | SET(b, c, d, a, 9, 21, T64); |
425 | #undef SET |
426 | |
427 | /* Then perform the following additions. (That is increment each |
428 | of the four registers by the value it had before this block |
429 | was started.) */ |
430 | pms->abcd[0] += a; |
431 | pms->abcd[1] += b; |
432 | pms->abcd[2] += c; |
433 | pms->abcd[3] += d; |
434 | } |
435 | |
436 | void md5_init(md5_state_t *pms) |
437 | { |
438 | pms->count[0] = pms->count[1] = 0; |
439 | pms->abcd[0] = 0x67452301; |
440 | pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; |
441 | pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; |
442 | pms->abcd[3] = 0x10325476; |
443 | } |
444 | |
445 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) |
446 | { |
447 | const md5_byte_t *p = data; |
448 | int left = nbytes; |
449 | int offset = (pms->count[0] >> 3) & 63; |
450 | md5_word_t nbits = (md5_word_t)(nbytes << 3); |
451 | |
452 | if (nbytes <= 0) |
453 | return; |
454 | |
455 | /* Update the message length. */ |
456 | pms->count[1] += nbytes >> 29; |
457 | pms->count[0] += nbits; |
458 | if (pms->count[0] < nbits) |
459 | pms->count[1]++; |
460 | |
461 | /* Process an initial partial block. */ |
462 | if (offset) { |
463 | int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); |
464 | |
465 | memcpy(dest: pms->buf + offset, src: p, n: copy); |
466 | if (offset + copy < 64) |
467 | return; |
468 | p += copy; |
469 | left -= copy; |
470 | md5_process(pms, data: pms->buf); |
471 | } |
472 | |
473 | /* Process full blocks. */ |
474 | for (; left >= 64; p += 64, left -= 64) |
475 | md5_process(pms, data: p); |
476 | |
477 | /* Process a final partial block. */ |
478 | if (left) |
479 | memcpy(dest: pms->buf, src: p, n: left); |
480 | } |
481 | |
482 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) |
483 | { |
484 | static const md5_byte_t pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
485 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
486 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
487 | md5_byte_t data[8]; |
488 | int i; |
489 | |
490 | /* Save the length before padding. */ |
491 | for (i = 0; i < 8; ++i) |
492 | data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); |
493 | /* Pad to 56 bytes mod 64. */ |
494 | md5_append(pms, data: pad, nbytes: ((55 - (pms->count[0] >> 3)) & 63) + 1); |
495 | /* Append the length. */ |
496 | md5_append(pms, data, nbytes: 8); |
497 | for (i = 0; i < 16; ++i) |
498 | digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); |
499 | } |
500 | |
501 | class DefaultMD5Context : public HashContext |
502 | { |
503 | Q_OBJECT |
504 | public: |
505 | DefaultMD5Context(Provider *p) |
506 | : HashContext(p, QStringLiteral("md5" )) |
507 | { |
508 | clear(); |
509 | } |
510 | |
511 | Provider::Context *clone() const override |
512 | { |
513 | return new DefaultMD5Context(*this); |
514 | } |
515 | |
516 | void clear() override |
517 | { |
518 | secure = true; |
519 | md5_init(pms: &md5); |
520 | } |
521 | |
522 | void update(const MemoryRegion &in) override |
523 | { |
524 | if (!in.isSecure()) |
525 | secure = false; |
526 | md5_append(pms: &md5, data: (const md5_byte_t *)in.data(), nbytes: in.size()); |
527 | } |
528 | |
529 | MemoryRegion final() override |
530 | { |
531 | if (secure) { |
532 | SecureArray b(16, 0); |
533 | md5_finish(pms: &md5, digest: (md5_byte_t *)b.data()); |
534 | return b; |
535 | } else { |
536 | QByteArray b(16, 0); |
537 | md5_finish(pms: &md5, digest: (md5_byte_t *)b.data()); |
538 | return b; |
539 | } |
540 | } |
541 | |
542 | bool secure; |
543 | md5_state_t md5; |
544 | }; |
545 | |
546 | //---------------------------------------------------------------------------- |
547 | // DefaultSHA1Context |
548 | //---------------------------------------------------------------------------- |
549 | |
550 | // SHA1 - from a public domain implementation by Steve Reid (steve@edmweb.com) |
551 | |
552 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) |
553 | |
554 | #ifdef Q_PROCESSOR_ARM |
555 | #define blk(i) \ |
556 | (block.l[i & 15] = rol(block.l[(i + 13) & 15] ^ block.l[(i + 8) & 15] ^ block.l[(i + 2) & 15] ^ block.l[i & 15], 1)) |
557 | #else |
558 | #define blk(i) \ |
559 | (block->l[i & 15] = \ |
560 | rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) |
561 | #endif |
562 | |
563 | /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ |
564 | #define R0(v, w, x, y, z, i) \ |
565 | z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ |
566 | w = rol(w, 30); |
567 | #define R1(v, w, x, y, z, i) \ |
568 | z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ |
569 | w = rol(w, 30); |
570 | #define R2(v, w, x, y, z, i) \ |
571 | z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ |
572 | w = rol(w, 30); |
573 | #define R3(v, w, x, y, z, i) \ |
574 | z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ |
575 | w = rol(w, 30); |
576 | #define R4(v, w, x, y, z, i) \ |
577 | z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ |
578 | w = rol(w, 30); |
579 | |
580 | struct SHA1_CONTEXT |
581 | { |
582 | quint32 state[5]; // 5 |
583 | quint32 count[2]; // 2 |
584 | unsigned char buffer[64]; // 64 |
585 | |
586 | SHA1_CONTEXT() |
587 | { |
588 | memset(s: state, c: 0, n: sizeof(state)); |
589 | memset(s: count, c: 0, n: sizeof(count)); |
590 | memset(s: buffer, c: 0, n: sizeof(buffer)); |
591 | } |
592 | }; |
593 | |
594 | typedef union { |
595 | unsigned char c[64]; |
596 | quint32 l[16]; |
597 | } CHAR64LONG16; |
598 | |
599 | class DefaultSHA1Context : public HashContext |
600 | { |
601 | Q_OBJECT |
602 | public: |
603 | SHA1_CONTEXT _context; |
604 | #ifdef Q_PROCESSOR_ARM |
605 | CHAR64LONG16 block; |
606 | #else |
607 | CHAR64LONG16 *block; |
608 | #endif |
609 | bool secure; |
610 | |
611 | DefaultSHA1Context(Provider *p) |
612 | : HashContext(p, QStringLiteral("sha1" )) |
613 | { |
614 | clear(); |
615 | } |
616 | |
617 | Provider::Context *clone() const override |
618 | { |
619 | return new DefaultSHA1Context(*this); |
620 | } |
621 | |
622 | void clear() override |
623 | { |
624 | secure = true; |
625 | sha1_init(context: &_context); |
626 | } |
627 | |
628 | void update(const MemoryRegion &in) override |
629 | { |
630 | if (!in.isSecure()) |
631 | secure = false; |
632 | sha1_update(context: &_context, data: (unsigned char *)in.data(), len: (unsigned int)in.size()); |
633 | } |
634 | |
635 | MemoryRegion final() override |
636 | { |
637 | if (secure) { |
638 | SecureArray b(20, 0); |
639 | sha1_final(digest: (unsigned char *)b.data(), context: &_context); |
640 | return b; |
641 | } else { |
642 | QByteArray b(20, 0); |
643 | sha1_final(digest: (unsigned char *)b.data(), context: &_context); |
644 | return b; |
645 | } |
646 | } |
647 | |
648 | inline unsigned long blk0(quint32 i) |
649 | { |
650 | if (QSysInfo::ByteOrder == QSysInfo::BigEndian) |
651 | #ifdef Q_PROCESSOR_ARM |
652 | return block.l[i]; |
653 | #else |
654 | return block->l[i]; |
655 | #endif |
656 | else |
657 | #ifdef Q_PROCESSOR_ARM |
658 | return (block.l[i] = (rol(block.l[i], 24) & 0xFF00FF00) | (rol(block.l[i], 8) & 0x00FF00FF)); |
659 | #else |
660 | return (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF)); |
661 | #endif |
662 | } |
663 | |
664 | // Hash a single 512-bit block. This is the core of the algorithm. |
665 | void transform(quint32 state[5], unsigned char buffer[64]) |
666 | { |
667 | quint32 a, b, c, d, e; |
668 | |
669 | #ifdef Q_PROCESSOR_ARM |
670 | memcpy(&block, buffer, sizeof(block)); |
671 | #else |
672 | block = reinterpret_cast<CHAR64LONG16 *>(buffer); |
673 | #endif |
674 | // Copy context->state[] to working vars |
675 | a = state[0]; |
676 | b = state[1]; |
677 | c = state[2]; |
678 | d = state[3]; |
679 | e = state[4]; |
680 | |
681 | // 4 rounds of 20 operations each. Loop unrolled. |
682 | R0(a, b, c, d, e, 0); |
683 | R0(e, a, b, c, d, 1); |
684 | R0(d, e, a, b, c, 2); |
685 | R0(c, d, e, a, b, 3); |
686 | R0(b, c, d, e, a, 4); |
687 | R0(a, b, c, d, e, 5); |
688 | R0(e, a, b, c, d, 6); |
689 | R0(d, e, a, b, c, 7); |
690 | R0(c, d, e, a, b, 8); |
691 | R0(b, c, d, e, a, 9); |
692 | R0(a, b, c, d, e, 10); |
693 | R0(e, a, b, c, d, 11); |
694 | R0(d, e, a, b, c, 12); |
695 | R0(c, d, e, a, b, 13); |
696 | R0(b, c, d, e, a, 14); |
697 | R0(a, b, c, d, e, 15); |
698 | R1(e, a, b, c, d, 16); |
699 | R1(d, e, a, b, c, 17); |
700 | R1(c, d, e, a, b, 18); |
701 | R1(b, c, d, e, a, 19); |
702 | R2(a, b, c, d, e, 20); |
703 | R2(e, a, b, c, d, 21); |
704 | R2(d, e, a, b, c, 22); |
705 | R2(c, d, e, a, b, 23); |
706 | R2(b, c, d, e, a, 24); |
707 | R2(a, b, c, d, e, 25); |
708 | R2(e, a, b, c, d, 26); |
709 | R2(d, e, a, b, c, 27); |
710 | R2(c, d, e, a, b, 28); |
711 | R2(b, c, d, e, a, 29); |
712 | R2(a, b, c, d, e, 30); |
713 | R2(e, a, b, c, d, 31); |
714 | R2(d, e, a, b, c, 32); |
715 | R2(c, d, e, a, b, 33); |
716 | R2(b, c, d, e, a, 34); |
717 | R2(a, b, c, d, e, 35); |
718 | R2(e, a, b, c, d, 36); |
719 | R2(d, e, a, b, c, 37); |
720 | R2(c, d, e, a, b, 38); |
721 | R2(b, c, d, e, a, 39); |
722 | R3(a, b, c, d, e, 40); |
723 | R3(e, a, b, c, d, 41); |
724 | R3(d, e, a, b, c, 42); |
725 | R3(c, d, e, a, b, 43); |
726 | R3(b, c, d, e, a, 44); |
727 | R3(a, b, c, d, e, 45); |
728 | R3(e, a, b, c, d, 46); |
729 | R3(d, e, a, b, c, 47); |
730 | R3(c, d, e, a, b, 48); |
731 | R3(b, c, d, e, a, 49); |
732 | R3(a, b, c, d, e, 50); |
733 | R3(e, a, b, c, d, 51); |
734 | R3(d, e, a, b, c, 52); |
735 | R3(c, d, e, a, b, 53); |
736 | R3(b, c, d, e, a, 54); |
737 | R3(a, b, c, d, e, 55); |
738 | R3(e, a, b, c, d, 56); |
739 | R3(d, e, a, b, c, 57); |
740 | R3(c, d, e, a, b, 58); |
741 | R3(b, c, d, e, a, 59); |
742 | R4(a, b, c, d, e, 60); |
743 | R4(e, a, b, c, d, 61); |
744 | R4(d, e, a, b, c, 62); |
745 | R4(c, d, e, a, b, 63); |
746 | R4(b, c, d, e, a, 64); |
747 | R4(a, b, c, d, e, 65); |
748 | R4(e, a, b, c, d, 66); |
749 | R4(d, e, a, b, c, 67); |
750 | R4(c, d, e, a, b, 68); |
751 | R4(b, c, d, e, a, 69); |
752 | R4(a, b, c, d, e, 70); |
753 | R4(e, a, b, c, d, 71); |
754 | R4(d, e, a, b, c, 72); |
755 | R4(c, d, e, a, b, 73); |
756 | R4(b, c, d, e, a, 74); |
757 | R4(a, b, c, d, e, 75); |
758 | R4(e, a, b, c, d, 76); |
759 | R4(d, e, a, b, c, 77); |
760 | R4(c, d, e, a, b, 78); |
761 | R4(b, c, d, e, a, 79); |
762 | |
763 | // Add the working vars back into context.state[] |
764 | state[0] += a; |
765 | state[1] += b; |
766 | state[2] += c; |
767 | state[3] += d; |
768 | state[4] += e; |
769 | |
770 | // Wipe variables |
771 | a = b = c = d = e = 0; |
772 | } |
773 | |
774 | // SHA1Init - Initialize new context |
775 | void sha1_init(SHA1_CONTEXT *context) |
776 | { |
777 | // SHA1 initialization constants |
778 | context->state[0] = 0x67452301; |
779 | context->state[1] = 0xEFCDAB89; |
780 | context->state[2] = 0x98BADCFE; |
781 | context->state[3] = 0x10325476; |
782 | context->state[4] = 0xC3D2E1F0; |
783 | context->count[0] = context->count[1] = 0; |
784 | } |
785 | |
786 | // Run your data through this |
787 | void sha1_update(SHA1_CONTEXT *context, unsigned char *data, quint32 len) |
788 | { |
789 | quint32 i, j; |
790 | |
791 | j = (context->count[0] >> 3) & 63; |
792 | if ((context->count[0] += len << 3) < (len << 3)) |
793 | context->count[1]++; |
794 | |
795 | context->count[1] += (len >> 29); |
796 | |
797 | if ((j + len) > 63) { |
798 | memcpy(dest: &context->buffer[j], src: data, n: (i = 64 - j)); |
799 | transform(state: context->state, buffer: context->buffer); |
800 | for (; i + 63 < len; i += 64) { |
801 | transform(state: context->state, buffer: &data[i]); |
802 | } |
803 | j = 0; |
804 | } else |
805 | i = 0; |
806 | memcpy(dest: &context->buffer[j], src: &data[i], n: len - i); |
807 | } |
808 | |
809 | // Add padding and return the message digest |
810 | void sha1_final(unsigned char digest[20], SHA1_CONTEXT *context) |
811 | { |
812 | quint32 i; |
813 | unsigned char finalcount[8]; |
814 | |
815 | for (i = 0; i < 8; i++) { |
816 | finalcount[i] = |
817 | (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); // Endian independent |
818 | } |
819 | sha1_update(context, data: (unsigned char *)"\200" , len: 1); |
820 | while ((context->count[0] & 504) != 448) { |
821 | sha1_update(context, data: (unsigned char *)"\0" , len: 1); |
822 | } |
823 | sha1_update(context, data: finalcount, len: 8); // Should cause a transform() |
824 | for (i = 0; i < 20; i++) { |
825 | digest[i] = (unsigned char)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); |
826 | } |
827 | |
828 | // Wipe variables |
829 | i = 0; |
830 | memset(s: context->buffer, c: 0, n: 64); |
831 | memset(s: context->state, c: 0, n: 20); |
832 | memset(s: context->count, c: 0, n: 8); |
833 | memset(s: &finalcount, c: 0, n: 8); |
834 | } |
835 | }; |
836 | |
837 | //---------------------------------------------------------------------------- |
838 | // DefaultKeyStoreEntry |
839 | //---------------------------------------------------------------------------- |
840 | |
841 | // this escapes colons, commas, and newlines. colons and commas so that they |
842 | // are available as delimiters, and newlines so that our output can be a |
843 | // single line of text. |
844 | static QString escape_string(const QString &in) |
845 | { |
846 | QString out; |
847 | for (const QChar &c : in) { |
848 | if (c == QLatin1Char('\\')) |
849 | out += QLatin1String("\\\\" ); |
850 | else if (c == QLatin1Char(':')) |
851 | out += QLatin1String("\\c" ); |
852 | else if (c == QLatin1Char(',')) |
853 | out += QLatin1String("\\o" ); |
854 | else if (c == QLatin1Char('\n')) |
855 | out += QLatin1String("\\n" ); |
856 | else |
857 | out += c; |
858 | } |
859 | return out; |
860 | } |
861 | |
862 | static bool unescape_string(const QString &in, QString *_out) |
863 | { |
864 | QString out; |
865 | for (int n = 0; n < in.length(); ++n) { |
866 | if (in[n] == QLatin1Char('\\')) { |
867 | if (n + 1 >= in.length()) |
868 | return false; |
869 | |
870 | if (in[n + 1] == QLatin1Char('\\')) |
871 | out += QLatin1Char('\\'); |
872 | else if (in[n + 1] == QLatin1Char('c')) |
873 | out += QLatin1Char(':'); |
874 | else if (in[n + 1] == QLatin1Char('o')) |
875 | out += QLatin1Char(','); |
876 | else if (in[n + 1] == QLatin1Char('n')) |
877 | out += QLatin1Char('\n'); |
878 | else |
879 | return false; |
880 | ++n; |
881 | } else |
882 | out += in[n]; |
883 | } |
884 | *_out = out; |
885 | return true; |
886 | } |
887 | |
888 | static QString escape_stringlist(const QStringList &in) |
889 | { |
890 | QStringList list; |
891 | for (int n = 0; n < in.count(); ++n) |
892 | list += escape_string(in: in[n]); |
893 | return list.join(QStringLiteral(":" )); |
894 | } |
895 | |
896 | static bool unescape_stringlist(const QString &in, QStringList *_out) |
897 | { |
898 | QStringList out; |
899 | const QStringList list = in.split(sep: QLatin1Char(':')); |
900 | for (int n = 0; n < list.count(); ++n) { |
901 | QString str; |
902 | if (!unescape_string(in: list[n], out: &str)) |
903 | return false; |
904 | out += str; |
905 | } |
906 | *_out = out; |
907 | return true; |
908 | } |
909 | |
910 | // serialization format is a colon separated list of 7 escaped strings |
911 | // 0 - "qca_def_1" (header) |
912 | // 1 - store id |
913 | // 2 - store name |
914 | // 3 - entry id |
915 | // 4 - entry name |
916 | // 5 - entry type (e.g. "cert") |
917 | // 6 - string encoding of object (e.g. DER encoded in Base64) |
918 | static QString entry_serialize(const QString &storeId, |
919 | const QString &storeName, |
920 | const QString &entryId, |
921 | const QString &entryName, |
922 | const QString &entryType, |
923 | const QString &data) |
924 | { |
925 | QStringList out; |
926 | out += QStringLiteral("qca_def" ); |
927 | out += storeId; |
928 | out += storeName; |
929 | out += entryId; |
930 | out += entryName; |
931 | out += entryType; |
932 | out += data; |
933 | return escape_stringlist(in: out); |
934 | } |
935 | |
936 | static bool entry_deserialize(const QString &in, |
937 | QString *storeId, |
938 | QString *storeName, |
939 | QString *entryId, |
940 | QString *entryName, |
941 | QString *entryType, |
942 | QString *data) |
943 | { |
944 | QStringList list; |
945 | if (!unescape_stringlist(in, out: &list)) |
946 | return false; |
947 | if (list.count() != 7) |
948 | return false; |
949 | if (list[0] != QLatin1String("qca_def" )) |
950 | return false; |
951 | *storeId = list[1]; |
952 | *storeName = list[2]; |
953 | *entryId = list[3]; |
954 | *entryName = list[4]; |
955 | *entryType = list[5]; |
956 | *data = list[6]; |
957 | return true; |
958 | } |
959 | |
960 | class DefaultKeyStoreEntry : public KeyStoreEntryContext |
961 | { |
962 | Q_OBJECT |
963 | public: |
964 | KeyStoreEntry::Type _type; |
965 | QString _id, _name, _storeId, _storeName; |
966 | Certificate _cert; |
967 | CRL _crl; |
968 | mutable QString _serialized; |
969 | |
970 | DefaultKeyStoreEntry(const Certificate &cert, const QString &storeId, const QString &storeName, Provider *p) |
971 | : KeyStoreEntryContext(p) |
972 | { |
973 | _type = KeyStoreEntry::TypeCertificate; |
974 | _storeId = storeId; |
975 | _storeName = storeName; |
976 | _cert = cert; |
977 | } |
978 | |
979 | DefaultKeyStoreEntry(const CRL &crl, const QString &storeId, const QString &storeName, Provider *p) |
980 | : KeyStoreEntryContext(p) |
981 | { |
982 | _type = KeyStoreEntry::TypeCRL; |
983 | _storeId = storeId; |
984 | _storeName = storeName; |
985 | _crl = crl; |
986 | } |
987 | |
988 | Provider::Context *clone() const override |
989 | { |
990 | return new DefaultKeyStoreEntry(*this); |
991 | } |
992 | |
993 | KeyStoreEntry::Type type() const override |
994 | { |
995 | return _type; |
996 | } |
997 | |
998 | QString id() const override |
999 | { |
1000 | return _id; |
1001 | } |
1002 | |
1003 | QString name() const override |
1004 | { |
1005 | return _name; |
1006 | } |
1007 | |
1008 | QString storeId() const override |
1009 | { |
1010 | return _storeId; |
1011 | } |
1012 | |
1013 | QString storeName() const override |
1014 | { |
1015 | return _storeName; |
1016 | } |
1017 | |
1018 | Certificate certificate() const override |
1019 | { |
1020 | return _cert; |
1021 | } |
1022 | |
1023 | CRL crl() const override |
1024 | { |
1025 | return _crl; |
1026 | } |
1027 | |
1028 | QString serialize() const override |
1029 | { |
1030 | if (_serialized.isEmpty()) { |
1031 | QString typestr; |
1032 | QString datastr; |
1033 | |
1034 | if (_type == KeyStoreEntry::TypeCertificate) { |
1035 | typestr = QStringLiteral("cert" ); |
1036 | datastr = Base64().arrayToString(a: _cert.toDER()); |
1037 | } else { |
1038 | typestr = QStringLiteral("crl" ); |
1039 | datastr = Base64().arrayToString(a: _crl.toDER()); |
1040 | } |
1041 | |
1042 | _serialized = entry_serialize(storeId: _storeId, storeName: _storeName, entryId: _id, entryName: _name, entryType: typestr, data: datastr); |
1043 | } |
1044 | |
1045 | return _serialized; |
1046 | } |
1047 | |
1048 | static DefaultKeyStoreEntry *deserialize(const QString &in, Provider *provider) |
1049 | { |
1050 | QString storeId, storeName, id, name, typestr, datastr; |
1051 | |
1052 | if (entry_deserialize(in, storeId: &storeId, storeName: &storeName, entryId: &id, entryName: &name, entryType: &typestr, data: &datastr)) { |
1053 | const QByteArray data = Base64().stringToArray(s: datastr).toByteArray(); |
1054 | DefaultKeyStoreEntry *c; |
1055 | |
1056 | if (typestr == QLatin1String("cert" )) { |
1057 | Certificate cert = Certificate::fromDER(a: data); |
1058 | if (cert.isNull()) |
1059 | return nullptr; |
1060 | c = new DefaultKeyStoreEntry(cert, storeId, storeName, provider); |
1061 | } else if (typestr == QLatin1String("crl" )) { |
1062 | CRL crl = CRL::fromDER(a: data); |
1063 | if (crl.isNull()) |
1064 | return nullptr; |
1065 | c = new DefaultKeyStoreEntry(crl, storeId, storeName, provider); |
1066 | } else |
1067 | return nullptr; |
1068 | |
1069 | c->_id = id; |
1070 | c->_name = name; |
1071 | c->_serialized = in; |
1072 | return c; |
1073 | } |
1074 | return nullptr; |
1075 | } |
1076 | |
1077 | QString simpleId() const |
1078 | { |
1079 | if (_type == KeyStoreEntry::TypeCertificate) |
1080 | return QString::number(qHash(key: _cert.toDER())); |
1081 | else |
1082 | return QString::number(qHash(key: _crl.toDER())); |
1083 | } |
1084 | |
1085 | QString simpleName() const |
1086 | { |
1087 | // use the common name, else orgname |
1088 | if (_type == KeyStoreEntry::TypeCertificate) { |
1089 | QString str = _cert.commonName(); |
1090 | if (str.isEmpty()) |
1091 | str = _cert.subjectInfo().value(key: Organization); |
1092 | return str; |
1093 | } else |
1094 | return _crl.issuerInfo().value(key: CommonName); |
1095 | } |
1096 | }; |
1097 | |
1098 | //---------------------------------------------------------------------------- |
1099 | // DefaultKeyStoreList |
1100 | //---------------------------------------------------------------------------- |
1101 | class DefaultKeyStoreList : public KeyStoreListContext |
1102 | { |
1103 | Q_OBJECT |
1104 | public: |
1105 | bool x509_supported; |
1106 | DefaultShared *shared; |
1107 | |
1108 | DefaultKeyStoreList(Provider *p, DefaultShared *_shared) |
1109 | : KeyStoreListContext(p) |
1110 | , shared(_shared) |
1111 | { |
1112 | } |
1113 | |
1114 | ~DefaultKeyStoreList() override |
1115 | { |
1116 | } |
1117 | |
1118 | Provider::Context *clone() const override |
1119 | { |
1120 | return nullptr; |
1121 | } |
1122 | |
1123 | void start() override |
1124 | { |
1125 | x509_supported = false; |
1126 | |
1127 | QMetaObject::invokeMethod(obj: this, member: "busyEnd" , c: Qt::QueuedConnection); |
1128 | } |
1129 | |
1130 | QList<int> keyStores() override |
1131 | { |
1132 | if (!x509_supported) { |
1133 | if (isSupported(features: "cert" ) && isSupported(features: "crl" )) |
1134 | x509_supported = true; |
1135 | } |
1136 | |
1137 | bool have_systemstore = false; |
1138 | #ifndef QCA_NO_SYSTEMSTORE |
1139 | if (shared->use_system()) |
1140 | have_systemstore = qca_have_systemstore(); |
1141 | #endif |
1142 | |
1143 | QList<int> list; |
1144 | |
1145 | // system store only shows up if the OS store is available or |
1146 | // there is a configured store file |
1147 | if (x509_supported && (have_systemstore || !shared->roots_file().isEmpty())) |
1148 | list += 0; |
1149 | |
1150 | return list; |
1151 | } |
1152 | |
1153 | KeyStore::Type type(int) const override |
1154 | { |
1155 | return KeyStore::System; |
1156 | } |
1157 | |
1158 | QString storeId(int) const override |
1159 | { |
1160 | return QStringLiteral("qca-default-systemstore" ); |
1161 | } |
1162 | |
1163 | QString name(int) const override |
1164 | { |
1165 | return QStringLiteral("System Trusted Certificates" ); |
1166 | } |
1167 | |
1168 | QList<KeyStoreEntry::Type> entryTypes(int) const override |
1169 | { |
1170 | QList<KeyStoreEntry::Type> list; |
1171 | list += KeyStoreEntry::TypeCertificate; |
1172 | list += KeyStoreEntry::TypeCRL; |
1173 | return list; |
1174 | } |
1175 | |
1176 | QList<KeyStoreEntryContext *> entryList(int) override |
1177 | { |
1178 | QList<KeyStoreEntryContext *> out; |
1179 | |
1180 | QList<Certificate> certs; |
1181 | QList<CRL> crls; |
1182 | |
1183 | if (shared->use_system()) { |
1184 | CertificateCollection col; |
1185 | #ifndef QCA_NO_SYSTEMSTORE |
1186 | col = qca_get_systemstore(provider: QString()); |
1187 | #endif |
1188 | certs += col.certificates(); |
1189 | crls += col.crls(); |
1190 | } |
1191 | |
1192 | const QString roots = shared->roots_file(); |
1193 | if (!roots.isEmpty()) { |
1194 | CertificateCollection col = CertificateCollection::fromFlatTextFile(fileName: roots); |
1195 | certs += col.certificates(); |
1196 | crls += col.crls(); |
1197 | } |
1198 | |
1199 | #ifdef FRIENDLY_NAMES |
1200 | const QStringList names = makeFriendlyNames(list: certs); |
1201 | #endif |
1202 | for (int n = 0; n < certs.count(); ++n) { |
1203 | DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(certs[n], storeId(0), name(0), provider()); |
1204 | c->_id = c->simpleId(); |
1205 | #ifdef FRIENDLY_NAMES |
1206 | c->_name = names[n]; |
1207 | #else |
1208 | c->_name = c->simpleName(); |
1209 | #endif |
1210 | out.append(t: c); |
1211 | } |
1212 | |
1213 | for (int n = 0; n < crls.count(); ++n) { |
1214 | DefaultKeyStoreEntry *c = new DefaultKeyStoreEntry(crls[n], storeId(0), name(0), provider()); |
1215 | c->_id = c->simpleId(); |
1216 | c->_name = c->simpleName(); |
1217 | out.append(t: c); |
1218 | } |
1219 | |
1220 | return out; |
1221 | } |
1222 | |
1223 | KeyStoreEntryContext *entryPassive(const QString &serialized) override |
1224 | { |
1225 | return DefaultKeyStoreEntry::deserialize(in: serialized, provider: provider()); |
1226 | } |
1227 | }; |
1228 | |
1229 | //---------------------------------------------------------------------------- |
1230 | // DefaultProvider |
1231 | //---------------------------------------------------------------------------- |
1232 | static bool unescape_config_stringlist(const QString &in, QStringList *_out) |
1233 | { |
1234 | QStringList out; |
1235 | const QStringList list = in.split(sep: QLatin1Char(',')); |
1236 | for (int n = 0; n < list.count(); ++n) { |
1237 | QString str; |
1238 | if (!unescape_string(in: list[n], out: &str)) |
1239 | return false; |
1240 | out += str.trimmed(); |
1241 | } |
1242 | *_out = out; |
1243 | return true; |
1244 | } |
1245 | |
1246 | class DefaultProvider : public Provider |
1247 | { |
1248 | public: |
1249 | DefaultShared shared; |
1250 | |
1251 | void init() override |
1252 | { |
1253 | const QDateTime now = QDateTime::currentDateTime(); |
1254 | |
1255 | uint t = now.toSecsSinceEpoch(); |
1256 | if (now.time().msec() > 0) |
1257 | t /= now.time().msec(); |
1258 | std::srand(seed: t); |
1259 | } |
1260 | |
1261 | int version() const override |
1262 | { |
1263 | return QCA_VERSION; |
1264 | } |
1265 | |
1266 | int qcaVersion() const override |
1267 | { |
1268 | return QCA_VERSION; |
1269 | } |
1270 | |
1271 | QString name() const override |
1272 | { |
1273 | return QStringLiteral("default" ); |
1274 | } |
1275 | |
1276 | QStringList features() const override |
1277 | { |
1278 | QStringList list; |
1279 | list += QStringLiteral("random" ); |
1280 | list += QStringLiteral("md5" ); |
1281 | list += QStringLiteral("sha1" ); |
1282 | list += QStringLiteral("keystorelist" ); |
1283 | return list; |
1284 | } |
1285 | |
1286 | Provider::Context *createContext(const QString &type) override |
1287 | { |
1288 | if (type == QLatin1String("random" )) |
1289 | return new DefaultRandomContext(this); |
1290 | else if (type == QLatin1String("md5" )) |
1291 | return new DefaultMD5Context(this); |
1292 | else if (type == QLatin1String("sha1" )) |
1293 | return new DefaultSHA1Context(this); |
1294 | else if (type == QLatin1String("keystorelist" )) |
1295 | return new DefaultKeyStoreList(this, &shared); |
1296 | else |
1297 | return nullptr; |
1298 | } |
1299 | |
1300 | QVariantMap defaultConfig() const override |
1301 | { |
1302 | QVariantMap config; |
1303 | config[QStringLiteral("formtype" )] = QStringLiteral("http://affinix.com/qca/forms/default#1.0" ); |
1304 | config[QStringLiteral("use_system" )] = true; |
1305 | config[QStringLiteral("roots_file" )] = QString(); |
1306 | config[QStringLiteral("skip_plugins" )] = QString(); |
1307 | config[QStringLiteral("plugin_priorities" )] = QString(); |
1308 | return config; |
1309 | } |
1310 | |
1311 | void configChanged(const QVariantMap &config) override |
1312 | { |
1313 | const bool use_system = config[QStringLiteral("use_system" )].toBool(); |
1314 | const QString roots_file = config[QStringLiteral("roots_file" )].toString(); |
1315 | const QString skip_plugins_str = config[QStringLiteral("skip_plugins" )].toString(); |
1316 | const QString plugin_priorities_str = config[QStringLiteral("plugin_priorities" )].toString(); |
1317 | |
1318 | QStringList tmp; |
1319 | |
1320 | QStringList skip_plugins; |
1321 | if (unescape_config_stringlist(in: skip_plugins_str, out: &tmp)) |
1322 | skip_plugins = tmp; |
1323 | |
1324 | QStringList plugin_priorities; |
1325 | if (unescape_config_stringlist(in: plugin_priorities_str, out: &tmp)) |
1326 | plugin_priorities = tmp; |
1327 | |
1328 | for (int n = 0; n < plugin_priorities.count(); ++n) { |
1329 | QString &s = plugin_priorities[n]; |
1330 | |
1331 | // make sure the entry ends with ":number" |
1332 | int x = s.indexOf(c: QLatin1Char(':')); |
1333 | bool ok = false; |
1334 | if (x != -1) |
1335 | #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2) |
1336 | (void)QStringView(s).mid(pos: x + 1).toInt(ok: &ok); |
1337 | #else |
1338 | s.midRef(x + 1).toInt(&ok); |
1339 | #endif |
1340 | if (!ok) { |
1341 | plugin_priorities.removeAt(i: n); |
1342 | --n; |
1343 | } |
1344 | } |
1345 | |
1346 | shared.set(use_system, roots_file, skip_plugins, plugin_priorities); |
1347 | } |
1348 | }; |
1349 | |
1350 | Provider *create_default_provider() |
1351 | { |
1352 | return new DefaultProvider; |
1353 | } |
1354 | |
1355 | QStringList skip_plugins(Provider *defaultProvider) |
1356 | { |
1357 | DefaultProvider *that = (DefaultProvider *)defaultProvider; |
1358 | return that->shared.skip_plugins(); |
1359 | } |
1360 | |
1361 | QStringList plugin_priorities(Provider *defaultProvider) |
1362 | { |
1363 | DefaultProvider *that = (DefaultProvider *)defaultProvider; |
1364 | return that->shared.plugin_priorities(); |
1365 | } |
1366 | |
1367 | } |
1368 | |
1369 | #include "qca_default.moc" |
1370 | |