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"