File indexing completed on 2024-04-14 04:38:58
0001 /* 0002 * Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com> 0003 * Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net> 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Lesser General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2.1 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Lesser General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Lesser General Public 0016 * License along with this library; if not, write to the Free Software 0017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 0018 * 02110-1301 USA 0019 * 0020 */ 0021 0022 #include "qca_core.h" 0023 0024 #include "qca_cert.h" 0025 #include "qca_textfilter.h" 0026 #include "qcaprovider.h" 0027 #include <QMutex> 0028 0029 #ifndef QCA_NO_SYSTEMSTORE 0030 #include "qca_systemstore.h" 0031 #endif 0032 0033 #include <cstdlib> 0034 0035 #define FRIENDLY_NAMES 0036 0037 namespace QCA { 0038 0039 class DefaultShared 0040 { 0041 private: 0042 mutable QMutex m; 0043 bool _use_system; 0044 QString _roots_file; 0045 QStringList _skip_plugins; 0046 QStringList _plugin_priorities; 0047 0048 public: 0049 DefaultShared() 0050 : _use_system(true) 0051 { 0052 } 0053 0054 bool use_system() const 0055 { 0056 QMutexLocker locker(&m); 0057 return _use_system; 0058 } 0059 0060 QString roots_file() const 0061 { 0062 QMutexLocker locker(&m); 0063 return _roots_file; 0064 } 0065 0066 QStringList skip_plugins() const 0067 { 0068 QMutexLocker locker(&m); 0069 return _skip_plugins; 0070 } 0071 0072 QStringList plugin_priorities() const 0073 { 0074 QMutexLocker locker(&m); 0075 return _plugin_priorities; 0076 } 0077 0078 void set(bool use_system, 0079 const QString &roots_file, 0080 const QStringList &skip_plugins, 0081 const QStringList &plugin_priorities) 0082 { 0083 QMutexLocker locker(&m); 0084 _use_system = use_system; 0085 _roots_file = roots_file; 0086 _skip_plugins = skip_plugins; 0087 _plugin_priorities = plugin_priorities; 0088 } 0089 }; 0090 0091 //---------------------------------------------------------------------------- 0092 // DefaultRandomContext 0093 //---------------------------------------------------------------------------- 0094 class DefaultRandomContext : public RandomContext 0095 { 0096 Q_OBJECT 0097 public: 0098 DefaultRandomContext(Provider *p) 0099 : RandomContext(p) 0100 { 0101 } 0102 0103 Provider::Context *clone() const override 0104 { 0105 return new DefaultRandomContext(provider()); 0106 } 0107 0108 SecureArray nextBytes(int size) override 0109 { 0110 SecureArray buf(size); 0111 for (int n = 0; n < (int)buf.size(); ++n) 0112 buf[n] = (char)std::rand(); 0113 return buf; 0114 } 0115 }; 0116 0117 //---------------------------------------------------------------------------- 0118 // DefaultMD5Context 0119 //---------------------------------------------------------------------------- 0120 0121 /* NOTE: the following code was modified to not need BYTE_ORDER -- Justin */ 0122 0123 /* 0124 Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. 0125 0126 This software is provided 'as-is', without any express or implied 0127 warranty. In no event will the authors be held liable for any damages 0128 arising from the use of this software. 0129 0130 Permission is granted to anyone to use this software for any purpose, 0131 including commercial applications, and to alter it and redistribute it 0132 freely, subject to the following restrictions: 0133 0134 1. The origin of this software must not be misrepresented; you must not 0135 claim that you wrote the original software. If you use this software 0136 in a product, an acknowledgment in the product documentation would be 0137 appreciated but is not required. 0138 2. Altered source versions must be plainly marked as such, and must not be 0139 misrepresented as being the original software. 0140 3. This notice may not be removed or altered from any source distribution. 0141 0142 L. Peter Deutsch 0143 ghost@aladdin.com 0144 0145 */ 0146 /* $Id$ */ 0147 /* 0148 Independent implementation of MD5 (RFC 1321). 0149 0150 This code implements the MD5 Algorithm defined in RFC 1321, whose 0151 text is available at 0152 http://www.ietf.org/rfc/rfc1321.txt 0153 The code is derived from the text of the RFC, including the test suite 0154 (section A.5) but excluding the rest of Appendix A. It does not include 0155 any code or documentation that is identified in the RFC as being 0156 copyrighted. 0157 0158 The original and principal author of md5.c is L. Peter Deutsch 0159 <ghost@aladdin.com>. Other authors are noted in the change history 0160 that follows (in reverse chronological order): 0161 0162 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order 0163 either statically or dynamically; added missing #include <string.h> 0164 in library. 0165 2002-03-11 lpd Corrected argument list for main(), and added int return 0166 type, in test program and T value program. 0167 2002-02-21 lpd Added missing #include <stdio.h> in test program. 0168 2000-07-03 lpd Patched to eliminate warnings about "constant is 0169 unsigned in ANSI C, signed in traditional"; made test program 0170 self-checking. 0171 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 0172 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 0173 1999-05-03 lpd Original version. 0174 */ 0175 0176 /* 0177 * This package supports both compile-time and run-time determination of CPU 0178 * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 0179 * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 0180 * defined as non-zero, the code will be compiled to run only on big-endian 0181 * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 0182 * run on either big- or little-endian CPUs, but will run slightly less 0183 * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 0184 */ 0185 0186 typedef quint8 md5_byte_t; /* 8-bit byte */ 0187 typedef quint32 md5_word_t; /* 32-bit word */ 0188 0189 /* Define the state of the MD5 Algorithm. */ 0190 struct md5_state_t 0191 { 0192 md5_word_t count[2]; // 2 /* message length in bits, lsw first */ 0193 md5_word_t abcd[4]; // 4 /* digest buffer */ 0194 md5_byte_t buf[64]; // 64 /* accumulate block */ 0195 0196 md5_state_t() 0197 { 0198 memset(count, 0, sizeof(count)); 0199 memset(abcd, 0, sizeof(abcd)); 0200 memset(buf, 0, sizeof(buf)); 0201 } 0202 }; 0203 0204 /* Initialize the algorithm. */ 0205 void md5_init(md5_state_t *pms); 0206 0207 /* Append a string to the message. */ 0208 void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 0209 0210 /* Finish the message and return the digest. */ 0211 void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 0212 0213 #define T_MASK ((md5_word_t)~0) 0214 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) 0215 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) 0216 #define T3 0x242070db 0217 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) 0218 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) 0219 #define T6 0x4787c62a 0220 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) 0221 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) 0222 #define T9 0x698098d8 0223 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) 0224 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) 0225 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) 0226 #define T13 0x6b901122 0227 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) 0228 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) 0229 #define T16 0x49b40821 0230 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) 0231 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) 0232 #define T19 0x265e5a51 0233 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) 0234 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) 0235 #define T22 0x02441453 0236 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) 0237 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) 0238 #define T25 0x21e1cde6 0239 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) 0240 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) 0241 #define T28 0x455a14ed 0242 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) 0243 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) 0244 #define T31 0x676f02d9 0245 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) 0246 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) 0247 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) 0248 #define T35 0x6d9d6122 0249 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) 0250 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) 0251 #define T38 0x4bdecfa9 0252 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) 0253 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) 0254 #define T41 0x289b7ec6 0255 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) 0256 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) 0257 #define T44 0x04881d05 0258 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) 0259 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) 0260 #define T47 0x1fa27cf8 0261 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) 0262 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) 0263 #define T50 0x432aff97 0264 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) 0265 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) 0266 #define T53 0x655b59c3 0267 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) 0268 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) 0269 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) 0270 #define T57 0x6fa87e4f 0271 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) 0272 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) 0273 #define T60 0x4e0811a1 0274 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) 0275 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) 0276 #define T63 0x2ad7d2bb 0277 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) 0278 0279 static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) 0280 { 0281 md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; 0282 md5_word_t t; 0283 0284 /* Define storage for little-endian or both types of CPUs. */ 0285 md5_word_t xbuf[16]; 0286 const md5_word_t *X; 0287 0288 { 0289 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { 0290 /* 0291 * On big-endian machines, we must arrange the bytes in the 0292 * right order. 0293 */ 0294 const md5_byte_t *xp = data; 0295 int i; 0296 0297 X = xbuf; /* (dynamic only) */ 0298 0299 for (i = 0; i < 16; ++i, xp += 4) 0300 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); 0301 } else /* dynamic big-endian */ 0302 { 0303 /* 0304 * On little-endian machines, we can process properly aligned 0305 * data without copying it. On arm do copying always 0306 */ 0307 #ifndef Q_PROCESSOR_ARM 0308 if (!(reinterpret_cast<uintptr_t>(data) & 3)) { 0309 /* data are properly aligned */ 0310 X = reinterpret_cast<const md5_word_t *>(data); 0311 } else 0312 #endif 0313 { 0314 /* not aligned */ 0315 memcpy(xbuf, data, 64); 0316 X = xbuf; 0317 } 0318 } 0319 } 0320 0321 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 0322 0323 /* Round 1. */ 0324 /* Let [abcd k s i] denote the operation 0325 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ 0326 #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 0327 #define SET(a, b, c, d, k, s, Ti) \ 0328 t = a + F(b, c, d) + X[k] + Ti; \ 0329 a = ROTATE_LEFT(t, s) + b 0330 /* Do the following 16 operations. */ 0331 SET(a, b, c, d, 0, 7, T1); 0332 SET(d, a, b, c, 1, 12, T2); 0333 SET(c, d, a, b, 2, 17, T3); 0334 SET(b, c, d, a, 3, 22, T4); 0335 SET(a, b, c, d, 4, 7, T5); 0336 SET(d, a, b, c, 5, 12, T6); 0337 SET(c, d, a, b, 6, 17, T7); 0338 SET(b, c, d, a, 7, 22, T8); 0339 SET(a, b, c, d, 8, 7, T9); 0340 SET(d, a, b, c, 9, 12, T10); 0341 SET(c, d, a, b, 10, 17, T11); 0342 SET(b, c, d, a, 11, 22, T12); 0343 SET(a, b, c, d, 12, 7, T13); 0344 SET(d, a, b, c, 13, 12, T14); 0345 SET(c, d, a, b, 14, 17, T15); 0346 SET(b, c, d, a, 15, 22, T16); 0347 #undef SET 0348 0349 /* Round 2. */ 0350 /* Let [abcd k s i] denote the operation 0351 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ 0352 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) 0353 #define SET(a, b, c, d, k, s, Ti) \ 0354 t = a + G(b, c, d) + X[k] + Ti; \ 0355 a = ROTATE_LEFT(t, s) + b 0356 /* Do the following 16 operations. */ 0357 SET(a, b, c, d, 1, 5, T17); 0358 SET(d, a, b, c, 6, 9, T18); 0359 SET(c, d, a, b, 11, 14, T19); 0360 SET(b, c, d, a, 0, 20, T20); 0361 SET(a, b, c, d, 5, 5, T21); 0362 SET(d, a, b, c, 10, 9, T22); 0363 SET(c, d, a, b, 15, 14, T23); 0364 SET(b, c, d, a, 4, 20, T24); 0365 SET(a, b, c, d, 9, 5, T25); 0366 SET(d, a, b, c, 14, 9, T26); 0367 SET(c, d, a, b, 3, 14, T27); 0368 SET(b, c, d, a, 8, 20, T28); 0369 SET(a, b, c, d, 13, 5, T29); 0370 SET(d, a, b, c, 2, 9, T30); 0371 SET(c, d, a, b, 7, 14, T31); 0372 SET(b, c, d, a, 12, 20, T32); 0373 #undef SET 0374 0375 /* Round 3. */ 0376 /* Let [abcd k s t] denote the operation 0377 a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ 0378 #define H(x, y, z) ((x) ^ (y) ^ (z)) 0379 #define SET(a, b, c, d, k, s, Ti) \ 0380 t = a + H(b, c, d) + X[k] + Ti; \ 0381 a = ROTATE_LEFT(t, s) + b 0382 /* Do the following 16 operations. */ 0383 SET(a, b, c, d, 5, 4, T33); 0384 SET(d, a, b, c, 8, 11, T34); 0385 SET(c, d, a, b, 11, 16, T35); 0386 SET(b, c, d, a, 14, 23, T36); 0387 SET(a, b, c, d, 1, 4, T37); 0388 SET(d, a, b, c, 4, 11, T38); 0389 SET(c, d, a, b, 7, 16, T39); 0390 SET(b, c, d, a, 10, 23, T40); 0391 SET(a, b, c, d, 13, 4, T41); 0392 SET(d, a, b, c, 0, 11, T42); 0393 SET(c, d, a, b, 3, 16, T43); 0394 SET(b, c, d, a, 6, 23, T44); 0395 SET(a, b, c, d, 9, 4, T45); 0396 SET(d, a, b, c, 12, 11, T46); 0397 SET(c, d, a, b, 15, 16, T47); 0398 SET(b, c, d, a, 2, 23, T48); 0399 #undef SET 0400 0401 /* Round 4. */ 0402 /* Let [abcd k s t] denote the operation 0403 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ 0404 #define I(x, y, z) ((y) ^ ((x) | ~(z))) 0405 #define SET(a, b, c, d, k, s, Ti) \ 0406 t = a + I(b, c, d) + X[k] + Ti; \ 0407 a = ROTATE_LEFT(t, s) + b 0408 /* Do the following 16 operations. */ 0409 SET(a, b, c, d, 0, 6, T49); 0410 SET(d, a, b, c, 7, 10, T50); 0411 SET(c, d, a, b, 14, 15, T51); 0412 SET(b, c, d, a, 5, 21, T52); 0413 SET(a, b, c, d, 12, 6, T53); 0414 SET(d, a, b, c, 3, 10, T54); 0415 SET(c, d, a, b, 10, 15, T55); 0416 SET(b, c, d, a, 1, 21, T56); 0417 SET(a, b, c, d, 8, 6, T57); 0418 SET(d, a, b, c, 15, 10, T58); 0419 SET(c, d, a, b, 6, 15, T59); 0420 SET(b, c, d, a, 13, 21, T60); 0421 SET(a, b, c, d, 4, 6, T61); 0422 SET(d, a, b, c, 11, 10, T62); 0423 SET(c, d, a, b, 2, 15, T63); 0424 SET(b, c, d, a, 9, 21, T64); 0425 #undef SET 0426 0427 /* Then perform the following additions. (That is increment each 0428 of the four registers by the value it had before this block 0429 was started.) */ 0430 pms->abcd[0] += a; 0431 pms->abcd[1] += b; 0432 pms->abcd[2] += c; 0433 pms->abcd[3] += d; 0434 } 0435 0436 void md5_init(md5_state_t *pms) 0437 { 0438 pms->count[0] = pms->count[1] = 0; 0439 pms->abcd[0] = 0x67452301; 0440 pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; 0441 pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; 0442 pms->abcd[3] = 0x10325476; 0443 } 0444 0445 void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) 0446 { 0447 const md5_byte_t *p = data; 0448 int left = nbytes; 0449 int offset = (pms->count[0] >> 3) & 63; 0450 md5_word_t nbits = (md5_word_t)(nbytes << 3); 0451 0452 if (nbytes <= 0) 0453 return; 0454 0455 /* Update the message length. */ 0456 pms->count[1] += nbytes >> 29; 0457 pms->count[0] += nbits; 0458 if (pms->count[0] < nbits) 0459 pms->count[1]++; 0460 0461 /* Process an initial partial block. */ 0462 if (offset) { 0463 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); 0464 0465 memcpy(pms->buf + offset, p, copy); 0466 if (offset + copy < 64) 0467 return; 0468 p += copy; 0469 left -= copy; 0470 md5_process(pms, pms->buf); 0471 } 0472 0473 /* Process full blocks. */ 0474 for (; left >= 64; p += 64, left -= 64) 0475 md5_process(pms, p); 0476 0477 /* Process a final partial block. */ 0478 if (left) 0479 memcpy(pms->buf, p, left); 0480 } 0481 0482 void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) 0483 { 0484 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, 0485 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0486 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 0487 md5_byte_t data[8]; 0488 int i; 0489 0490 /* Save the length before padding. */ 0491 for (i = 0; i < 8; ++i) 0492 data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); 0493 /* Pad to 56 bytes mod 64. */ 0494 md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); 0495 /* Append the length. */ 0496 md5_append(pms, data, 8); 0497 for (i = 0; i < 16; ++i) 0498 digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); 0499 } 0500 0501 class DefaultMD5Context : public HashContext 0502 { 0503 Q_OBJECT 0504 public: 0505 DefaultMD5Context(Provider *p) 0506 : HashContext(p, QStringLiteral("md5")) 0507 { 0508 clear(); 0509 } 0510 0511 Provider::Context *clone() const override 0512 { 0513 return new DefaultMD5Context(*this); 0514 } 0515 0516 void clear() override 0517 { 0518 secure = true; 0519 md5_init(&md5); 0520 } 0521 0522 void update(const MemoryRegion &in) override 0523 { 0524 if (!in.isSecure()) 0525 secure = false; 0526 md5_append(&md5, (const md5_byte_t *)in.data(), in.size()); 0527 } 0528 0529 MemoryRegion final() override 0530 { 0531 if (secure) { 0532 SecureArray b(16, 0); 0533 md5_finish(&md5, (md5_byte_t *)b.data()); 0534 return b; 0535 } else { 0536 QByteArray b(16, 0); 0537 md5_finish(&md5, (md5_byte_t *)b.data()); 0538 return b; 0539 } 0540 } 0541 0542 bool secure; 0543 md5_state_t md5; 0544 }; 0545 0546 //---------------------------------------------------------------------------- 0547 // DefaultSHA1Context 0548 //---------------------------------------------------------------------------- 0549 0550 // SHA1 - from a public domain implementation by Steve Reid (steve@edmweb.com) 0551 0552 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 0553 0554 #ifdef Q_PROCESSOR_ARM 0555 #define blk(i) \ 0556 (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)) 0557 #else 0558 #define blk(i) \ 0559 (block->l[i & 15] = \ 0560 rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) 0561 #endif 0562 0563 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 0564 #define R0(v, w, x, y, z, i) \ 0565 z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ 0566 w = rol(w, 30); 0567 #define R1(v, w, x, y, z, i) \ 0568 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ 0569 w = rol(w, 30); 0570 #define R2(v, w, x, y, z, i) \ 0571 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ 0572 w = rol(w, 30); 0573 #define R3(v, w, x, y, z, i) \ 0574 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ 0575 w = rol(w, 30); 0576 #define R4(v, w, x, y, z, i) \ 0577 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ 0578 w = rol(w, 30); 0579 0580 struct SHA1_CONTEXT 0581 { 0582 quint32 state[5]; // 5 0583 quint32 count[2]; // 2 0584 unsigned char buffer[64]; // 64 0585 0586 SHA1_CONTEXT() 0587 { 0588 memset(state, 0, sizeof(state)); 0589 memset(count, 0, sizeof(count)); 0590 memset(buffer, 0, sizeof(buffer)); 0591 } 0592 }; 0593 0594 typedef union { 0595 unsigned char c[64]; 0596 quint32 l[16]; 0597 } CHAR64LONG16; 0598 0599 class DefaultSHA1Context : public HashContext 0600 { 0601 Q_OBJECT 0602 public: 0603 SHA1_CONTEXT _context; 0604 #ifdef Q_PROCESSOR_ARM 0605 CHAR64LONG16 block; 0606 #else 0607 CHAR64LONG16 *block; 0608 #endif 0609 bool secure; 0610 0611 DefaultSHA1Context(Provider *p) 0612 : HashContext(p, QStringLiteral("sha1")) 0613 { 0614 clear(); 0615 } 0616 0617 Provider::Context *clone() const override 0618 { 0619 return new DefaultSHA1Context(*this); 0620 } 0621 0622 void clear() override 0623 { 0624 secure = true; 0625 sha1_init(&_context); 0626 } 0627 0628 void update(const MemoryRegion &in) override 0629 { 0630 if (!in.isSecure()) 0631 secure = false; 0632 sha1_update(&_context, (unsigned char *)in.data(), (unsigned int)in.size()); 0633 } 0634 0635 MemoryRegion final() override 0636 { 0637 if (secure) { 0638 SecureArray b(20, 0); 0639 sha1_final((unsigned char *)b.data(), &_context); 0640 return b; 0641 } else { 0642 QByteArray b(20, 0); 0643 sha1_final((unsigned char *)b.data(), &_context); 0644 return b; 0645 } 0646 } 0647 0648 inline unsigned long blk0(quint32 i) 0649 { 0650 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) 0651 #ifdef Q_PROCESSOR_ARM 0652 return block.l[i]; 0653 #else 0654 return block->l[i]; 0655 #endif 0656 else 0657 #ifdef Q_PROCESSOR_ARM 0658 return (block.l[i] = (rol(block.l[i], 24) & 0xFF00FF00) | (rol(block.l[i], 8) & 0x00FF00FF)); 0659 #else 0660 return (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF)); 0661 #endif 0662 } 0663 0664 // Hash a single 512-bit block. This is the core of the algorithm. 0665 void transform(quint32 state[5], unsigned char buffer[64]) 0666 { 0667 quint32 a, b, c, d, e; 0668 0669 #ifdef Q_PROCESSOR_ARM 0670 memcpy(&block, buffer, sizeof(block)); 0671 #else 0672 block = reinterpret_cast<CHAR64LONG16 *>(buffer); 0673 #endif 0674 // Copy context->state[] to working vars 0675 a = state[0]; 0676 b = state[1]; 0677 c = state[2]; 0678 d = state[3]; 0679 e = state[4]; 0680 0681 // 4 rounds of 20 operations each. Loop unrolled. 0682 R0(a, b, c, d, e, 0); 0683 R0(e, a, b, c, d, 1); 0684 R0(d, e, a, b, c, 2); 0685 R0(c, d, e, a, b, 3); 0686 R0(b, c, d, e, a, 4); 0687 R0(a, b, c, d, e, 5); 0688 R0(e, a, b, c, d, 6); 0689 R0(d, e, a, b, c, 7); 0690 R0(c, d, e, a, b, 8); 0691 R0(b, c, d, e, a, 9); 0692 R0(a, b, c, d, e, 10); 0693 R0(e, a, b, c, d, 11); 0694 R0(d, e, a, b, c, 12); 0695 R0(c, d, e, a, b, 13); 0696 R0(b, c, d, e, a, 14); 0697 R0(a, b, c, d, e, 15); 0698 R1(e, a, b, c, d, 16); 0699 R1(d, e, a, b, c, 17); 0700 R1(c, d, e, a, b, 18); 0701 R1(b, c, d, e, a, 19); 0702 R2(a, b, c, d, e, 20); 0703 R2(e, a, b, c, d, 21); 0704 R2(d, e, a, b, c, 22); 0705 R2(c, d, e, a, b, 23); 0706 R2(b, c, d, e, a, 24); 0707 R2(a, b, c, d, e, 25); 0708 R2(e, a, b, c, d, 26); 0709 R2(d, e, a, b, c, 27); 0710 R2(c, d, e, a, b, 28); 0711 R2(b, c, d, e, a, 29); 0712 R2(a, b, c, d, e, 30); 0713 R2(e, a, b, c, d, 31); 0714 R2(d, e, a, b, c, 32); 0715 R2(c, d, e, a, b, 33); 0716 R2(b, c, d, e, a, 34); 0717 R2(a, b, c, d, e, 35); 0718 R2(e, a, b, c, d, 36); 0719 R2(d, e, a, b, c, 37); 0720 R2(c, d, e, a, b, 38); 0721 R2(b, c, d, e, a, 39); 0722 R3(a, b, c, d, e, 40); 0723 R3(e, a, b, c, d, 41); 0724 R3(d, e, a, b, c, 42); 0725 R3(c, d, e, a, b, 43); 0726 R3(b, c, d, e, a, 44); 0727 R3(a, b, c, d, e, 45); 0728 R3(e, a, b, c, d, 46); 0729 R3(d, e, a, b, c, 47); 0730 R3(c, d, e, a, b, 48); 0731 R3(b, c, d, e, a, 49); 0732 R3(a, b, c, d, e, 50); 0733 R3(e, a, b, c, d, 51); 0734 R3(d, e, a, b, c, 52); 0735 R3(c, d, e, a, b, 53); 0736 R3(b, c, d, e, a, 54); 0737 R3(a, b, c, d, e, 55); 0738 R3(e, a, b, c, d, 56); 0739 R3(d, e, a, b, c, 57); 0740 R3(c, d, e, a, b, 58); 0741 R3(b, c, d, e, a, 59); 0742 R4(a, b, c, d, e, 60); 0743 R4(e, a, b, c, d, 61); 0744 R4(d, e, a, b, c, 62); 0745 R4(c, d, e, a, b, 63); 0746 R4(b, c, d, e, a, 64); 0747 R4(a, b, c, d, e, 65); 0748 R4(e, a, b, c, d, 66); 0749 R4(d, e, a, b, c, 67); 0750 R4(c, d, e, a, b, 68); 0751 R4(b, c, d, e, a, 69); 0752 R4(a, b, c, d, e, 70); 0753 R4(e, a, b, c, d, 71); 0754 R4(d, e, a, b, c, 72); 0755 R4(c, d, e, a, b, 73); 0756 R4(b, c, d, e, a, 74); 0757 R4(a, b, c, d, e, 75); 0758 R4(e, a, b, c, d, 76); 0759 R4(d, e, a, b, c, 77); 0760 R4(c, d, e, a, b, 78); 0761 R4(b, c, d, e, a, 79); 0762 0763 // Add the working vars back into context.state[] 0764 state[0] += a; 0765 state[1] += b; 0766 state[2] += c; 0767 state[3] += d; 0768 state[4] += e; 0769 0770 // Wipe variables 0771 a = b = c = d = e = 0; 0772 } 0773 0774 // SHA1Init - Initialize new context 0775 void sha1_init(SHA1_CONTEXT *context) 0776 { 0777 // SHA1 initialization constants 0778 context->state[0] = 0x67452301; 0779 context->state[1] = 0xEFCDAB89; 0780 context->state[2] = 0x98BADCFE; 0781 context->state[3] = 0x10325476; 0782 context->state[4] = 0xC3D2E1F0; 0783 context->count[0] = context->count[1] = 0; 0784 } 0785 0786 // Run your data through this 0787 void sha1_update(SHA1_CONTEXT *context, unsigned char *data, quint32 len) 0788 { 0789 quint32 i, j; 0790 0791 j = (context->count[0] >> 3) & 63; 0792 if ((context->count[0] += len << 3) < (len << 3)) 0793 context->count[1]++; 0794 0795 context->count[1] += (len >> 29); 0796 0797 if ((j + len) > 63) { 0798 memcpy(&context->buffer[j], data, (i = 64 - j)); 0799 transform(context->state, context->buffer); 0800 for (; i + 63 < len; i += 64) { 0801 transform(context->state, &data[i]); 0802 } 0803 j = 0; 0804 } else 0805 i = 0; 0806 memcpy(&context->buffer[j], &data[i], len - i); 0807 } 0808 0809 // Add padding and return the message digest 0810 void sha1_final(unsigned char digest[20], SHA1_CONTEXT *context) 0811 { 0812 quint32 i; 0813 unsigned char finalcount[8]; 0814 0815 for (i = 0; i < 8; i++) { 0816 finalcount[i] = 0817 (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); // Endian independent 0818 } 0819 sha1_update(context, (unsigned char *)"\200", 1); 0820 while ((context->count[0] & 504) != 448) { 0821 sha1_update(context, (unsigned char *)"\0", 1); 0822 } 0823 sha1_update(context, finalcount, 8); // Should cause a transform() 0824 for (i = 0; i < 20; i++) { 0825 digest[i] = (unsigned char)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); 0826 } 0827 0828 // Wipe variables 0829 i = 0; 0830 memset(context->buffer, 0, 64); 0831 memset(context->state, 0, 20); 0832 memset(context->count, 0, 8); 0833 memset(&finalcount, 0, 8); 0834 } 0835 }; 0836 0837 //---------------------------------------------------------------------------- 0838 // DefaultKeyStoreEntry 0839 //---------------------------------------------------------------------------- 0840 0841 // this escapes colons, commas, and newlines. colons and commas so that they 0842 // are available as delimiters, and newlines so that our output can be a 0843 // single line of text. 0844 static QString escape_string(const QString &in) 0845 { 0846 QString out; 0847 for (const QChar &c : in) { 0848 if (c == QLatin1Char('\\')) 0849 out += QLatin1String("\\\\"); 0850 else if (c == QLatin1Char(':')) 0851 out += QLatin1String("\\c"); 0852 else if (c == QLatin1Char(',')) 0853 out += QLatin1String("\\o"); 0854 else if (c == QLatin1Char('\n')) 0855 out += QLatin1String("\\n"); 0856 else 0857 out += c; 0858 } 0859 return out; 0860 } 0861 0862 static bool unescape_string(const QString &in, QString *_out) 0863 { 0864 QString out; 0865 for (int n = 0; n < in.length(); ++n) { 0866 if (in[n] == QLatin1Char('\\')) { 0867 if (n + 1 >= in.length()) 0868 return false; 0869 0870 if (in[n + 1] == QLatin1Char('\\')) 0871 out += QLatin1Char('\\'); 0872 else if (in[n + 1] == QLatin1Char('c')) 0873 out += QLatin1Char(':'); 0874 else if (in[n + 1] == QLatin1Char('o')) 0875 out += QLatin1Char(','); 0876 else if (in[n + 1] == QLatin1Char('n')) 0877 out += QLatin1Char('\n'); 0878 else 0879 return false; 0880 ++n; 0881 } else 0882 out += in[n]; 0883 } 0884 *_out = out; 0885 return true; 0886 } 0887 0888 static QString escape_stringlist(const QStringList &in) 0889 { 0890 QStringList list; 0891 for (int n = 0; n < in.count(); ++n) 0892 list += escape_string(in[n]); 0893 return list.join(QStringLiteral(":")); 0894 } 0895 0896 static bool unescape_stringlist(const QString &in, QStringList *_out) 0897 { 0898 QStringList out; 0899 const QStringList list = in.split(QLatin1Char(':')); 0900 for (int n = 0; n < list.count(); ++n) { 0901 QString str; 0902 if (!unescape_string(list[n], &str)) 0903 return false; 0904 out += str; 0905 } 0906 *_out = out; 0907 return true; 0908 } 0909 0910 // serialization format is a colon separated list of 7 escaped strings 0911 // 0 - "qca_def_1" (header) 0912 // 1 - store id 0913 // 2 - store name 0914 // 3 - entry id 0915 // 4 - entry name 0916 // 5 - entry type (e.g. "cert") 0917 // 6 - string encoding of object (e.g. DER encoded in Base64) 0918 static QString entry_serialize(const QString &storeId, 0919 const QString &storeName, 0920 const QString &entryId, 0921 const QString &entryName, 0922 const QString &entryType, 0923 const QString &data) 0924 { 0925 QStringList out; 0926 out += QStringLiteral("qca_def"); 0927 out += storeId; 0928 out += storeName; 0929 out += entryId; 0930 out += entryName; 0931 out += entryType; 0932 out += data; 0933 return escape_stringlist(out); 0934 } 0935 0936 static bool entry_deserialize(const QString &in, 0937 QString *storeId, 0938 QString *storeName, 0939 QString *entryId, 0940 QString *entryName, 0941 QString *entryType, 0942 QString *data) 0943 { 0944 QStringList list; 0945 if (!unescape_stringlist(in, &list)) 0946 return false; 0947 if (list.count() != 7) 0948 return false; 0949 if (list[0] != QLatin1String("qca_def")) 0950 return false; 0951 *storeId = list[1]; 0952 *storeName = list[2]; 0953 *entryId = list[3]; 0954 *entryName = list[4]; 0955 *entryType = list[5]; 0956 *data = list[6]; 0957 return true; 0958 } 0959 0960 class DefaultKeyStoreEntry : public KeyStoreEntryContext 0961 { 0962 Q_OBJECT 0963 public: 0964 KeyStoreEntry::Type _type; 0965 QString _id, _name, _storeId, _storeName; 0966 Certificate _cert; 0967 CRL _crl; 0968 mutable QString _serialized; 0969 0970 DefaultKeyStoreEntry(const Certificate &cert, const QString &storeId, const QString &storeName, Provider *p) 0971 : KeyStoreEntryContext(p) 0972 { 0973 _type = KeyStoreEntry::TypeCertificate; 0974 _storeId = storeId; 0975 _storeName = storeName; 0976 _cert = cert; 0977 } 0978 0979 DefaultKeyStoreEntry(const CRL &crl, const QString &storeId, const QString &storeName, Provider *p) 0980 : KeyStoreEntryContext(p) 0981 { 0982 _type = KeyStoreEntry::TypeCRL; 0983 _storeId = storeId; 0984 _storeName = storeName; 0985 _crl = crl; 0986 } 0987 0988 Provider::Context *clone() const override 0989 { 0990 return new DefaultKeyStoreEntry(*this); 0991 } 0992 0993 KeyStoreEntry::Type type() const override 0994 { 0995 return _type; 0996 } 0997 0998 QString id() const override 0999 { 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(_cert.toDER()); 1037 } else { 1038 typestr = QStringLiteral("crl"); 1039 datastr = Base64().arrayToString(_crl.toDER()); 1040 } 1041 1042 _serialized = entry_serialize(_storeId, _storeName, _id, _name, typestr, 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, &storeName, &id, &name, &typestr, &datastr)) { 1053 const QByteArray data = Base64().stringToArray(datastr).toByteArray(); 1054 DefaultKeyStoreEntry *c; 1055 1056 if (typestr == QLatin1String("cert")) { 1057 Certificate cert = Certificate::fromDER(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(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(_cert.toDER())); 1081 else 1082 return QString::number(qHash(_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(Organization); 1092 return str; 1093 } else 1094 return _crl.issuerInfo().value(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(this, "busyEnd", Qt::QueuedConnection); 1128 } 1129 1130 QList<int> keyStores() override 1131 { 1132 if (!x509_supported) { 1133 if (isSupported("cert") && isSupported("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(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(roots); 1195 certs += col.certificates(); 1196 crls += col.crls(); 1197 } 1198 1199 #ifdef FRIENDLY_NAMES 1200 const QStringList names = makeFriendlyNames(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(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(c); 1218 } 1219 1220 return out; 1221 } 1222 1223 KeyStoreEntryContext *entryPassive(const QString &serialized) override 1224 { 1225 return DefaultKeyStoreEntry::deserialize(serialized, 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(QLatin1Char(',')); 1236 for (int n = 0; n < list.count(); ++n) { 1237 QString str; 1238 if (!unescape_string(list[n], &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(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(skip_plugins_str, &tmp)) 1322 skip_plugins = tmp; 1323 1324 QStringList plugin_priorities; 1325 if (unescape_config_stringlist(plugin_priorities_str, &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(QLatin1Char(':')); 1333 bool ok = false; 1334 if (x != -1) 1335 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2) 1336 (void)QStringView(s).mid(x + 1).toInt(&ok); 1337 #else 1338 s.midRef(x + 1).toInt(&ok); 1339 #endif 1340 if (!ok) { 1341 plugin_priorities.removeAt(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"