00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "qca_basic.h"
00023
00024 #include "qcaprovider.h"
00025
00026 #include <QMutexLocker>
00027 #include <QtGlobal>
00028
00029 namespace QCA {
00030
00031
00032 QMutex *global_random_mutex();
00033 Random *global_random();
00034 Provider::Context *getContext(const QString &type, Provider *p);
00035
00036
00037 ProviderList allProviders();
00038 Provider *providerForName(const QString &name);
00039
00040 static void mergeList(QStringList *a, const QStringList &b)
00041 {
00042 foreach(const QString &s, b)
00043 {
00044 if(!a->contains(s))
00045 a->append(s);
00046 }
00047 }
00048
00049 static QStringList get_hash_types(Provider *p)
00050 {
00051 QStringList out;
00052 InfoContext *c = static_cast<InfoContext *>(getContext("info", p));
00053 if(!c)
00054 return out;
00055 out = c->supportedHashTypes();
00056 delete c;
00057 return out;
00058 }
00059
00060 static QStringList get_cipher_types(Provider *p)
00061 {
00062 QStringList out;
00063 InfoContext *c = static_cast<InfoContext *>(getContext("info", p));
00064 if(!c)
00065 return out;
00066 out = c->supportedCipherTypes();
00067 delete c;
00068 return out;
00069 }
00070
00071 static QStringList get_mac_types(Provider *p)
00072 {
00073 QStringList out;
00074 InfoContext *c = static_cast<InfoContext *>(getContext("info", p));
00075 if(!c)
00076 return out;
00077 out = c->supportedMACTypes();
00078 delete c;
00079 return out;
00080 }
00081
00082 static QStringList get_types(QStringList (*get_func)(Provider *p), const QString &provider)
00083 {
00084 QStringList out;
00085 if(!provider.isEmpty())
00086 {
00087 Provider *p = providerForName(provider);
00088 if(p)
00089 out = get_func(p);
00090 }
00091 else
00092 {
00093 ProviderList pl = allProviders();
00094 foreach(Provider *p, pl)
00095 mergeList(&out, get_func(p));
00096 }
00097 return out;
00098 }
00099
00100 static QStringList supportedHashTypes(const QString &provider)
00101 {
00102 return get_types(get_hash_types, provider);
00103 }
00104
00105 static QStringList supportedCipherTypes(const QString &provider)
00106 {
00107 return get_types(get_cipher_types, provider);
00108 }
00109
00110 static QStringList supportedMACTypes(const QString &provider)
00111 {
00112 return get_types(get_mac_types, provider);
00113 }
00114
00115
00116
00117
00118 Random::Random(const QString &provider)
00119 :Algorithm("random", provider)
00120 {
00121 }
00122
00123 Random::Random(const Random &from)
00124 :Algorithm(from)
00125 {
00126 }
00127
00128 Random::~Random()
00129 {
00130 }
00131
00132 Random & Random::operator=(const Random &from)
00133 {
00134 Algorithm::operator=(from);
00135 return *this;
00136 }
00137
00138 uchar Random::nextByte()
00139 {
00140 return (uchar)(nextBytes(1)[0]);
00141 }
00142
00143 SecureArray Random::nextBytes(int size)
00144 {
00145 return static_cast<RandomContext *>(context())->nextBytes(size);
00146 }
00147
00148 uchar Random::randomChar()
00149 {
00150 QMutexLocker locker(global_random_mutex());
00151 return global_random()->nextByte();
00152 }
00153
00154 int Random::randomInt()
00155 {
00156 QMutexLocker locker(global_random_mutex());
00157 SecureArray a = global_random()->nextBytes(sizeof(int));
00158 int x;
00159 memcpy(&x, a.data(), a.size());
00160 return x;
00161 }
00162
00163 SecureArray Random::randomArray(int size)
00164 {
00165 QMutexLocker locker(global_random_mutex());
00166 return global_random()->nextBytes(size);
00167 }
00168
00169
00170
00171
00172 Hash::Hash(const QString &type, const QString &provider)
00173 :Algorithm(type, provider)
00174 {
00175 }
00176
00177 Hash::Hash(const Hash &from)
00178 :Algorithm(from), BufferedComputation(from)
00179 {
00180 }
00181
00182 Hash::~Hash()
00183 {
00184 }
00185
00186 Hash & Hash::operator=(const Hash &from)
00187 {
00188 Algorithm::operator=(from);
00189 return *this;
00190 }
00191
00192 QStringList Hash::supportedTypes(const QString &provider)
00193 {
00194 return supportedHashTypes(provider);
00195 }
00196
00197 QString Hash::type() const
00198 {
00199
00200 return Algorithm::type();
00201 }
00202
00203 void Hash::clear()
00204 {
00205 static_cast<HashContext *>(context())->clear();
00206 }
00207
00208 void Hash::update(const MemoryRegion &a)
00209 {
00210 static_cast<HashContext *>(context())->update(a);
00211 }
00212
00213 void Hash::update(const QByteArray &a)
00214 {
00215 update(MemoryRegion(a));
00216 }
00217
00218 void Hash::update(const char *data, int len)
00219 {
00220 if(len < 0)
00221 len = qstrlen(data);
00222 if(len == 0)
00223 return;
00224
00225 update(MemoryRegion(QByteArray::fromRawData(data, len)));
00226 }
00227
00228
00229 void Hash::update(QIODevice *file)
00230 {
00231 char buffer[1024];
00232 int len;
00233
00234 while ((len=file->read(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
00235 update(buffer, len);
00236 }
00237
00238 MemoryRegion Hash::final()
00239 {
00240 return static_cast<HashContext *>(context())->final();
00241 }
00242
00243 MemoryRegion Hash::hash(const MemoryRegion &a)
00244 {
00245 return process(a);
00246 }
00247
00248 QString Hash::hashToString(const MemoryRegion &a)
00249 {
00250 return arrayToHex(hash(a).toByteArray());
00251 }
00252
00253
00254
00255
00256 class Cipher::Private
00257 {
00258 public:
00259 QString type;
00260 Cipher::Mode mode;
00261 Cipher::Padding pad;
00262 Direction dir;
00263 SymmetricKey key;
00264 InitializationVector iv;
00265
00266 bool ok, done;
00267 };
00268
00269 Cipher::Cipher(const QString &type, Mode mode, Padding pad,
00270 Direction dir, const SymmetricKey &key,
00271 const InitializationVector &iv,
00272 const QString &provider)
00273 :Algorithm(withAlgorithms(type, mode, pad), provider)
00274 {
00275 d = new Private;
00276 d->type = type;
00277 d->mode = mode;
00278 d->pad = pad;
00279 if(!key.isEmpty())
00280 setup(dir, key, iv);
00281 }
00282
00283 Cipher::Cipher(const Cipher &from)
00284 :Algorithm(from), Filter(from)
00285 {
00286 d = new Private(*from.d);
00287 }
00288
00289 Cipher::~Cipher()
00290 {
00291 delete d;
00292 }
00293
00294 Cipher & Cipher::operator=(const Cipher &from)
00295 {
00296 Algorithm::operator=(from);
00297 *d = *from.d;
00298 return *this;
00299 }
00300
00301 QStringList Cipher::supportedTypes(const QString &provider)
00302 {
00303 return supportedCipherTypes(provider);
00304 }
00305
00306 QString Cipher::type() const
00307 {
00308 return d->type;
00309 }
00310
00311 Cipher::Mode Cipher::mode() const
00312 {
00313 return d->mode;
00314 }
00315
00316 Cipher::Padding Cipher::padding() const
00317 {
00318 return d->pad;
00319 }
00320
00321 Direction Cipher::direction() const
00322 {
00323 return d->dir;
00324 }
00325
00326 KeyLength Cipher::keyLength() const
00327 {
00328 return static_cast<const CipherContext *>(context())->keyLength();
00329 }
00330
00331 bool Cipher::validKeyLength(int n) const
00332 {
00333 KeyLength len = keyLength();
00334 return ((n >= len.minimum()) && (n <= len.maximum()) && (n % len.multiple() == 0));
00335 }
00336
00337 int Cipher::blockSize() const
00338 {
00339 return static_cast<const CipherContext *>(context())->blockSize();
00340 }
00341
00342 void Cipher::clear()
00343 {
00344 d->done = false;
00345 static_cast<CipherContext *>(context())->setup(d->dir, d->key, d->iv);
00346 }
00347
00348 MemoryRegion Cipher::update(const MemoryRegion &a)
00349 {
00350 SecureArray out;
00351 if(d->done)
00352 return out;
00353 d->ok = static_cast<CipherContext *>(context())->update(a, &out);
00354 return out;
00355 }
00356
00357 MemoryRegion Cipher::final()
00358 {
00359 SecureArray out;
00360 if(d->done)
00361 return out;
00362 d->done = true;
00363 d->ok = static_cast<CipherContext *>(context())->final(&out);
00364 return out;
00365 }
00366
00367 bool Cipher::ok() const
00368 {
00369 return d->ok;
00370 }
00371
00372 void Cipher::setup(Direction dir, const SymmetricKey &key, const InitializationVector &iv)
00373 {
00374 d->dir = dir;
00375 d->key = key;
00376 d->iv = iv;
00377 clear();
00378 }
00379
00380 QString Cipher::withAlgorithms(const QString &cipherType, Mode modeType, Padding paddingType)
00381 {
00382 QString mode;
00383 switch(modeType) {
00384 case CBC:
00385 mode = "cbc";
00386 break;
00387 case CFB:
00388 mode = "cfb";
00389 break;
00390 case OFB:
00391 mode = "ofb";
00392 break;
00393 case ECB:
00394 mode = "ecb";
00395 break;
00396 default:
00397 Q_ASSERT(0);
00398 }
00399
00400
00401 if(paddingType == DefaultPadding)
00402 {
00403
00404 if(modeType == CBC)
00405 paddingType = PKCS7;
00406 else
00407 paddingType = NoPadding;
00408 }
00409
00410 QString pad;
00411 if(paddingType == NoPadding)
00412 pad = "";
00413 else
00414 pad = "pkcs7";
00415
00416 QString result = cipherType + '-' + mode;
00417 if(!pad.isEmpty())
00418 result += QString("-") + pad;
00419
00420 return result;
00421 }
00422
00423
00424
00425
00426 class MessageAuthenticationCode::Private
00427 {
00428 public:
00429 SymmetricKey key;
00430
00431 bool done;
00432 MemoryRegion buf;
00433 };
00434
00435
00436 MessageAuthenticationCode::MessageAuthenticationCode(const QString &type,
00437 const SymmetricKey &key,
00438 const QString &provider)
00439 :Algorithm(type, provider)
00440 {
00441 d = new Private;
00442 setup(key);
00443 }
00444
00445 MessageAuthenticationCode::MessageAuthenticationCode(const MessageAuthenticationCode &from)
00446 :Algorithm(from), BufferedComputation(from)
00447 {
00448 d = new Private(*from.d);
00449 }
00450
00451 MessageAuthenticationCode::~MessageAuthenticationCode()
00452 {
00453 delete d;
00454 }
00455
00456 MessageAuthenticationCode & MessageAuthenticationCode::operator=(const MessageAuthenticationCode &from)
00457 {
00458 Algorithm::operator=(from);
00459 *d = *from.d;
00460 return *this;
00461 }
00462
00463 QStringList MessageAuthenticationCode::supportedTypes(const QString &provider)
00464 {
00465 return supportedMACTypes(provider);
00466 }
00467
00468 QString MessageAuthenticationCode::type() const
00469 {
00470
00471 return Algorithm::type();
00472 }
00473
00474 KeyLength MessageAuthenticationCode::keyLength() const
00475 {
00476 return static_cast<const MACContext *>(context())->keyLength();
00477 }
00478
00479 bool MessageAuthenticationCode::validKeyLength(int n) const
00480 {
00481 KeyLength len = keyLength();
00482 return ((n >= len.minimum()) && (n <= len.maximum()) && (n % len.multiple() == 0));
00483 }
00484
00485 void MessageAuthenticationCode::clear()
00486 {
00487 d->done = false;
00488 static_cast<MACContext *>(context())->setup(d->key);
00489 }
00490
00491 void MessageAuthenticationCode::update(const MemoryRegion &a)
00492 {
00493 if(d->done)
00494 return;
00495 static_cast<MACContext *>(context())->update(a);
00496 }
00497
00498 MemoryRegion MessageAuthenticationCode::final()
00499 {
00500 if(!d->done)
00501 {
00502 d->done = true;
00503 static_cast<MACContext *>(context())->final(&d->buf);
00504 }
00505 return d->buf;
00506 }
00507
00508 void MessageAuthenticationCode::setup(const SymmetricKey &key)
00509 {
00510 d->key = key;
00511 clear();
00512 }
00513
00514
00515
00516
00517 KeyDerivationFunction::KeyDerivationFunction(const QString &type, const QString &provider)
00518 :Algorithm(type, provider)
00519 {
00520 }
00521
00522 KeyDerivationFunction::KeyDerivationFunction(const KeyDerivationFunction &from)
00523 :Algorithm(from)
00524 {
00525 }
00526
00527 KeyDerivationFunction::~KeyDerivationFunction()
00528 {
00529 }
00530
00531 KeyDerivationFunction & KeyDerivationFunction::operator=(const KeyDerivationFunction &from)
00532 {
00533 Algorithm::operator=(from);
00534 return *this;
00535 }
00536
00537 SymmetricKey KeyDerivationFunction::makeKey(const SecureArray &secret, const InitializationVector &salt, unsigned int keyLength, unsigned int iterationCount)
00538 {
00539 return static_cast<KDFContext *>(context())->makeKey(secret, salt, keyLength, iterationCount);
00540 }
00541
00542 QString KeyDerivationFunction::withAlgorithm(const QString &kdfType, const QString &algType)
00543 {
00544 return (kdfType + '(' + algType + ')');
00545 }
00546
00547 }