Changeset View
Changeset View
Standalone View
Standalone View
plugins/qca-botan/qca-botan.cpp
Show All 17 Lines | |||||
18 | * | 18 | * | ||
19 | */ | 19 | */ | ||
20 | #include <QtCrypto> | 20 | #include <QtCrypto> | ||
21 | #include <QTime> | 21 | #include <QTime> | ||
22 | #include <QtPlugin> | 22 | #include <QtPlugin> | ||
23 | 23 | | |||
24 | #include <qstringlist.h> | 24 | #include <qstringlist.h> | ||
25 | 25 | | |||
26 | #include <botan/botan.h> | | |||
27 | #include <botan/hmac.h> | 26 | #include <botan/hmac.h> | ||
28 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0) | 27 | #include <botan/version.h> | ||
29 | #include <botan/s2k.h> | 28 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||
30 | #endif | 29 | #include <botan/botan.h> | ||
31 | #if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,8,0) | | |||
32 | #include <botan/algo_factory.h> | 30 | #include <botan/algo_factory.h> | ||
31 | #else | ||||
32 | #include <botan/auto_rng.h> | ||||
33 | #include <botan/block_cipher.h> | ||||
34 | #include <botan/filters.h> | ||||
35 | #include <botan/hash.h> | ||||
36 | #include <botan/pbkdf.h> | ||||
37 | #include <botan/stream_cipher.h> | ||||
33 | #endif | 38 | #endif | ||
34 | 39 | | |||
35 | #include <stdlib.h> | 40 | #include <stdlib.h> | ||
36 | #include <iostream> | 41 | #include <iostream> | ||
37 | 42 | | |||
38 | //----------------------------------------------------------- | 43 | //----------------------------------------------------------- | ||
39 | class botanRandomContext : public QCA::RandomContext | 44 | class botanRandomContext : public QCA::RandomContext | ||
40 | { | 45 | { | ||
41 | public: | 46 | public: | ||
42 | botanRandomContext(QCA::Provider *p) : RandomContext(p) | 47 | botanRandomContext(QCA::Provider *p) : RandomContext(p) | ||
43 | { | 48 | { | ||
44 | } | 49 | } | ||
45 | 50 | | |||
46 | Context *clone() const | 51 | Context *clone() const | ||
47 | { | 52 | { | ||
48 | return new botanRandomContext( *this ); | 53 | return new botanRandomContext( *this ); | ||
49 | } | 54 | } | ||
50 | 55 | | |||
51 | QCA::SecureArray nextBytes(int size) | 56 | QCA::SecureArray nextBytes(int size) | ||
52 | { | 57 | { | ||
53 | QCA::SecureArray buf(size); | 58 | QCA::SecureArray buf(size); | ||
54 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,5,0) | | |||
55 | Botan::Global_RNG::randomize( (Botan::byte*)buf.data(), buf.size(), Botan::SessionKey ); | | |||
56 | #elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,7,6) | | |||
57 | Botan::Global_RNG::randomize( (Botan::byte*)buf.data(), buf.size() ); | | |||
58 | #else | | |||
59 | Botan::AutoSeeded_RNG rng; | 59 | Botan::AutoSeeded_RNG rng; | ||
60 | rng.randomize(reinterpret_cast<Botan::byte*>(buf.data()), buf.size()); | 60 | rng.randomize(reinterpret_cast<Botan::byte*>(buf.data()), buf.size()); | ||
61 | #endif | | |||
62 | return buf; | 61 | return buf; | ||
63 | } | 62 | } | ||
64 | }; | 63 | }; | ||
65 | 64 | | |||
66 | 65 | | |||
67 | //----------------------------------------------------------- | 66 | //----------------------------------------------------------- | ||
68 | class BotanHashContext : public QCA::HashContext | 67 | class BotanHashContext : public QCA::HashContext | ||
69 | { | 68 | { | ||
70 | public: | 69 | public: | ||
71 | BotanHashContext( const QString &hashName, QCA::Provider *p, const QString &type) : QCA::HashContext(p, type) | 70 | BotanHashContext( const QString &hashName, QCA::Provider *p, const QString &type) : QCA::HashContext(p, type) | ||
72 | { | 71 | { | ||
72 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||||
73 | m_hashObj = Botan::get_hash(hashName.toStdString()); | 73 | m_hashObj = Botan::get_hash(hashName.toStdString()); | ||
74 | #else | ||||
75 | m_hashObj = Botan::HashFunction::create(hashName.toStdString()).release(); | ||||
76 | #endif | ||||
74 | } | 77 | } | ||
75 | 78 | | |||
76 | ~BotanHashContext() | 79 | ~BotanHashContext() | ||
77 | { | 80 | { | ||
78 | delete m_hashObj; | 81 | delete m_hashObj; | ||
79 | } | 82 | } | ||
80 | 83 | | |||
81 | Context *clone() const | 84 | Context *clone() const | ||
82 | { | 85 | { | ||
83 | return new BotanHashContext(*this); | 86 | return new BotanHashContext(*this); | ||
84 | } | 87 | } | ||
85 | 88 | | |||
86 | void clear() | 89 | void clear() | ||
87 | { | 90 | { | ||
88 | m_hashObj->clear(); | 91 | m_hashObj->clear(); | ||
89 | } | 92 | } | ||
90 | 93 | | |||
91 | void update(const QCA::MemoryRegion &a) | 94 | void update(const QCA::MemoryRegion &a) | ||
92 | { | 95 | { | ||
93 | m_hashObj->update( (const Botan::byte*)a.data(), a.size() ); | 96 | m_hashObj->update( (const Botan::byte*)a.data(), a.size() ); | ||
94 | } | 97 | } | ||
95 | 98 | | |||
96 | QCA::MemoryRegion final() | 99 | QCA::MemoryRegion final() | ||
97 | { | 100 | { | ||
98 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0) | | |||
99 | QCA::SecureArray a( m_hashObj->OUTPUT_LENGTH ); | | |||
100 | #else | | |||
101 | QCA::SecureArray a( m_hashObj->output_length() ); | 101 | QCA::SecureArray a( m_hashObj->output_length() ); | ||
102 | #endif | | |||
103 | m_hashObj->final( (Botan::byte *)a.data() ); | 102 | m_hashObj->final( (Botan::byte *)a.data() ); | ||
104 | return a; | 103 | return a; | ||
105 | } | 104 | } | ||
106 | 105 | | |||
107 | private: | 106 | private: | ||
108 | Botan::HashFunction *m_hashObj; | 107 | Botan::HashFunction *m_hashObj; | ||
109 | }; | 108 | }; | ||
110 | 109 | | |||
111 | 110 | | |||
112 | //----------------------------------------------------------- | 111 | //----------------------------------------------------------- | ||
113 | class BotanHMACContext : public QCA::MACContext | 112 | class BotanHMACContext : public QCA::MACContext | ||
114 | { | 113 | { | ||
115 | public: | 114 | public: | ||
116 | BotanHMACContext( const QString &hashName, QCA::Provider *p, const QString &type) : QCA::MACContext(p, type) | 115 | BotanHMACContext( const QString &hashName, QCA::Provider *p, const QString &type) : QCA::MACContext(p, type) | ||
117 | { | 116 | { | ||
118 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,8,0) | 117 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||
119 | m_hashObj = new Botan::HMAC(hashName.toStdString()); | | |||
120 | #else | | |||
121 | m_hashObj = new Botan::HMAC(Botan::global_state().algorithm_factory().make_hash_function(hashName.toStdString())); | 118 | m_hashObj = new Botan::HMAC(Botan::global_state().algorithm_factory().make_hash_function(hashName.toStdString())); | ||
119 | #else | ||||
120 | m_hashObj = new Botan::HMAC(Botan::HashFunction::create_or_throw(hashName.toStdString()).release()); | ||||
122 | #endif | 121 | #endif | ||
123 | if (0 == m_hashObj) { | 122 | if (0 == m_hashObj) { | ||
124 | std::cout << "null context object" << std::endl; | 123 | std::cout << "null context object" << std::endl; | ||
125 | } | 124 | } | ||
126 | } | 125 | } | ||
127 | 126 | | |||
128 | ~BotanHMACContext() | 127 | ~BotanHMACContext() | ||
129 | { | 128 | { | ||
Show All 26 Lines | 148 | m_hashObj->clear(); | |||
156 | 155 | | |||
157 | void update(const QCA::MemoryRegion &a) | 156 | void update(const QCA::MemoryRegion &a) | ||
158 | { | 157 | { | ||
159 | m_hashObj->update( (const Botan::byte*)a.data(), a.size() ); | 158 | m_hashObj->update( (const Botan::byte*)a.data(), a.size() ); | ||
160 | } | 159 | } | ||
161 | 160 | | |||
162 | void final( QCA::MemoryRegion *out) | 161 | void final( QCA::MemoryRegion *out) | ||
163 | { | 162 | { | ||
164 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0) | | |||
165 | QCA::SecureArray sa( m_hashObj->OUTPUT_LENGTH, 0 ); | | |||
166 | #else | | |||
167 | QCA::SecureArray sa( m_hashObj->output_length(), 0 ); | 163 | QCA::SecureArray sa( m_hashObj->output_length(), 0 ); | ||
168 | #endif | | |||
169 | m_hashObj->final( (Botan::byte *)sa.data() ); | 164 | m_hashObj->final( (Botan::byte *)sa.data() ); | ||
170 | *out = sa; | 165 | *out = sa; | ||
171 | } | 166 | } | ||
172 | 167 | | |||
173 | protected: | 168 | protected: | ||
174 | Botan::HMAC *m_hashObj; | 169 | Botan::HMAC *m_hashObj; | ||
175 | }; | 170 | }; | ||
176 | 171 | | |||
Show All 15 Lines | 184 | delete m_s2k; | |||
192 | Context *clone() const | 187 | Context *clone() const | ||
193 | { | 188 | { | ||
194 | return new BotanPBKDFContext( *this ); | 189 | return new BotanPBKDFContext( *this ); | ||
195 | } | 190 | } | ||
196 | 191 | | |||
197 | QCA::SymmetricKey makeKey(const QCA::SecureArray &secret, const QCA::InitializationVector &salt, | 192 | QCA::SymmetricKey makeKey(const QCA::SecureArray &secret, const QCA::InitializationVector &salt, | ||
198 | unsigned int keyLength, unsigned int iterationCount) | 193 | unsigned int keyLength, unsigned int iterationCount) | ||
199 | { | 194 | { | ||
200 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0) | | |||
201 | m_s2k->set_iterations(iterationCount); | | |||
202 | m_s2k->change_salt((const Botan::byte*)salt.data(), salt.size()); | | |||
203 | std::string secretString(secret.data(), secret.size() ); | | |||
204 | Botan::OctetString key = m_s2k->derive_key(keyLength, secretString); | | |||
205 | #else | | |||
206 | std::string secretString(secret.data(), secret.size() ); | 195 | std::string secretString(secret.data(), secret.size() ); | ||
207 | Botan::OctetString key = m_s2k->derive_key(keyLength, secretString, (const Botan::byte*)salt.data(), salt.size(), iterationCount); | 196 | Botan::OctetString key = m_s2k->derive_key(keyLength, secretString, (const Botan::byte*)salt.data(), salt.size(), iterationCount); | ||
208 | #endif | | |||
209 | QCA::SecureArray retval(QByteArray((const char*)key.begin(), key.length())); | 197 | QCA::SecureArray retval(QByteArray((const char*)key.begin(), key.length())); | ||
210 | return QCA::SymmetricKey(retval); | 198 | return QCA::SymmetricKey(retval); | ||
211 | } | 199 | } | ||
212 | 200 | | |||
213 | QCA::SymmetricKey makeKey(const QCA::SecureArray &secret, | 201 | QCA::SymmetricKey makeKey(const QCA::SecureArray &secret, | ||
214 | const QCA::InitializationVector &salt, | 202 | const QCA::InitializationVector &salt, | ||
215 | unsigned int keyLength, | 203 | unsigned int keyLength, | ||
216 | int msecInterval, | 204 | int msecInterval, | ||
217 | unsigned int *iterationCount) | 205 | unsigned int *iterationCount) | ||
218 | { | 206 | { | ||
219 | Q_ASSERT(iterationCount != NULL); | 207 | Q_ASSERT(iterationCount != NULL); | ||
220 | Botan::OctetString key; | 208 | Botan::OctetString key; | ||
221 | QTime timer; | 209 | QTime timer; | ||
222 | std::string secretString(secret.data(), secret.size() ); | 210 | std::string secretString(secret.data(), secret.size() ); | ||
223 | 211 | | |||
224 | *iterationCount = 0; | 212 | *iterationCount = 0; | ||
225 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0) | | |||
226 | m_s2k->set_iterations(1); | | |||
227 | m_s2k->change_salt((const Botan::byte*)salt.data(), salt.size()); | | |||
228 | timer.start(); | | |||
229 | while (timer.elapsed() < msecInterval) { | | |||
230 | key = m_s2k->derive_key(keyLength, secretString); | | |||
231 | ++(*iterationCount); | | |||
232 | } | | |||
233 | #else | | |||
234 | timer.start(); | 213 | timer.start(); | ||
235 | while (timer.elapsed() < msecInterval) { | 214 | while (timer.elapsed() < msecInterval) { | ||
236 | key = m_s2k->derive_key(keyLength, | 215 | key = m_s2k->derive_key(keyLength, | ||
237 | secretString, | 216 | secretString, | ||
238 | (const Botan::byte*)salt.data(), | 217 | (const Botan::byte*)salt.data(), | ||
239 | salt.size(), | 218 | salt.size(), | ||
240 | 1); | 219 | 1); | ||
241 | ++(*iterationCount); | 220 | ++(*iterationCount); | ||
242 | } | 221 | } | ||
243 | #endif | | |||
244 | return makeKey(secret, salt, keyLength, *iterationCount); | 222 | return makeKey(secret, salt, keyLength, *iterationCount); | ||
245 | } | 223 | } | ||
246 | 224 | | |||
247 | protected: | 225 | protected: | ||
248 | Botan::S2K* m_s2k; | 226 | Botan::S2K* m_s2k; | ||
249 | }; | 227 | }; | ||
250 | 228 | | |||
251 | 229 | | |||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Line(s) | 275 | } | |||
299 | 277 | | |||
300 | Context *clone() const | 278 | Context *clone() const | ||
301 | { | 279 | { | ||
302 | return new BotanCipherContext( *this ); | 280 | return new BotanCipherContext( *this ); | ||
303 | } | 281 | } | ||
304 | 282 | | |||
305 | int blockSize() const | 283 | int blockSize() const | ||
306 | { | 284 | { | ||
285 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||||
307 | return Botan::block_size_of(m_algoName); | 286 | return Botan::block_size_of(m_algoName); | ||
287 | #else | ||||
288 | if(const std::unique_ptr<Botan::BlockCipher> bc = Botan::BlockCipher::create(m_algoName)) | ||||
289 | return bc->block_size(); | ||||
290 | | ||||
291 | throw Botan::Algorithm_Not_Found(m_algoName); | ||||
292 | #endif | ||||
308 | } | 293 | } | ||
309 | 294 | | |||
310 | QCA::AuthTag tag() const | 295 | QCA::AuthTag tag() const | ||
311 | { | 296 | { | ||
312 | // For future implementation | 297 | // For future implementation | ||
313 | return QCA::AuthTag(); | 298 | return QCA::AuthTag(); | ||
314 | } | 299 | } | ||
315 | 300 | | |||
Show All 16 Lines | |||||
332 | size_t bytes_read = m_crypter->read((Botan::byte*)result.data(), result.size()); | 317 | size_t bytes_read = m_crypter->read((Botan::byte*)result.data(), result.size()); | ||
333 | result.resize(bytes_read); | 318 | result.resize(bytes_read); | ||
334 | *out = result; | 319 | *out = result; | ||
335 | return true; | 320 | return true; | ||
336 | } | 321 | } | ||
337 | 322 | | |||
338 | QCA::KeyLength keyLength() const | 323 | QCA::KeyLength keyLength() const | ||
339 | { | 324 | { | ||
340 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0) | 325 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||
341 | return QCA::KeyLength( Botan::min_keylength_of(m_algoName), | | |||
342 | Botan::max_keylength_of(m_algoName), | | |||
343 | Botan::keylength_multiple_of(m_algoName) ); | | |||
344 | #else | | |||
345 | Botan::Algorithm_Factory &af = Botan::global_state().algorithm_factory(); | 326 | Botan::Algorithm_Factory &af = Botan::global_state().algorithm_factory(); | ||
327 | #endif | ||||
346 | Botan::Key_Length_Specification kls(0); | 328 | Botan::Key_Length_Specification kls(0); | ||
329 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||||
347 | if(const Botan::BlockCipher *bc = af.prototype_block_cipher(m_algoName)) | 330 | if(const Botan::BlockCipher *bc = af.prototype_block_cipher(m_algoName)) | ||
fvogt: AFAICT this leaks the algorithm object. | |||||
331 | #else | ||||
332 | if(const std::unique_ptr<Botan::BlockCipher> bc = Botan::BlockCipher::create(m_algoName)) | ||||
333 | #endif | ||||
348 | kls = bc->key_spec(); | 334 | kls = bc->key_spec(); | ||
335 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||||
349 | else if(const Botan::StreamCipher *sc = af.prototype_stream_cipher(m_algoName)) | 336 | else if(const Botan::StreamCipher *sc = af.prototype_stream_cipher(m_algoName)) | ||
337 | #else | ||||
338 | else if(const std::unique_ptr<Botan::StreamCipher> sc = Botan::StreamCipher::create(m_algoName)) | ||||
339 | #endif | ||||
350 | kls = sc->key_spec(); | 340 | kls = sc->key_spec(); | ||
341 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||||
351 | else if(const Botan::MessageAuthenticationCode *mac = af.prototype_mac(m_algoName)) | 342 | else if(const Botan::MessageAuthenticationCode *mac = af.prototype_mac(m_algoName)) | ||
343 | #else | ||||
344 | else if(const std::unique_ptr<Botan::MessageAuthenticationCode> mac = Botan::MessageAuthenticationCode::create(m_algoName)) | ||||
345 | #endif | ||||
352 | kls = mac->key_spec(); | 346 | kls = mac->key_spec(); | ||
353 | return QCA::KeyLength( kls.minimum_keylength(), | 347 | return QCA::KeyLength( kls.minimum_keylength(), | ||
354 | kls.maximum_keylength(), | 348 | kls.maximum_keylength(), | ||
355 | kls.keylength_multiple() ); | 349 | kls.keylength_multiple() ); | ||
356 | #endif | | |||
357 | } | 350 | } | ||
358 | 351 | | |||
359 | 352 | | |||
360 | ~BotanCipherContext() | 353 | ~BotanCipherContext() | ||
361 | { | 354 | { | ||
362 | delete m_crypter; | 355 | delete m_crypter; | ||
363 | } | 356 | } | ||
364 | 357 | | |||
Show All 9 Lines | |||||
374 | 367 | | |||
375 | 368 | | |||
376 | //========================================================== | 369 | //========================================================== | ||
377 | class botanProvider : public QCA::Provider | 370 | class botanProvider : public QCA::Provider | ||
378 | { | 371 | { | ||
379 | public: | 372 | public: | ||
380 | void init() | 373 | void init() | ||
381 | { | 374 | { | ||
375 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||||
382 | m_init = new Botan::LibraryInitializer; | 376 | m_init = new Botan::LibraryInitializer; | ||
377 | #endif | ||||
383 | } | 378 | } | ||
384 | 379 | | |||
385 | ~botanProvider() | 380 | ~botanProvider() | ||
386 | { | 381 | { | ||
387 | // We should be cleaning up there, but | 382 | // We should be cleaning up there, but | ||
388 | // this causes the unit tests to segfault | 383 | // this causes the unit tests to segfault | ||
389 | // delete m_init; | 384 | // delete m_init; | ||
390 | } | 385 | } | ||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Line(s) | |||||
533 | else if ( type == "des-ofb" ) | 528 | else if ( type == "des-ofb" ) | ||
534 | return new BotanCipherContext( QString("DES"), QString("OFB"), QString("NoPadding"), this, type ); | 529 | return new BotanCipherContext( QString("DES"), QString("OFB"), QString("NoPadding"), this, type ); | ||
535 | else if ( type == "tripledes-ecb" ) | 530 | else if ( type == "tripledes-ecb" ) | ||
536 | return new BotanCipherContext( QString("TripleDES"), QString("ECB"), QString("NoPadding"), this, type ); | 531 | return new BotanCipherContext( QString("TripleDES"), QString("ECB"), QString("NoPadding"), this, type ); | ||
537 | else | 532 | else | ||
538 | return 0; | 533 | return 0; | ||
539 | } | 534 | } | ||
540 | private: | 535 | private: | ||
536 | #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(2,0,0) | ||||
541 | Botan::LibraryInitializer *m_init; | 537 | Botan::LibraryInitializer *m_init; | ||
538 | #endif | ||||
542 | 539 | | |||
543 | }; | 540 | }; | ||
544 | 541 | | |||
545 | class botanPlugin : public QObject, public QCAPlugin | 542 | class botanPlugin : public QObject, public QCAPlugin | ||
546 | { | 543 | { | ||
547 | Q_OBJECT | 544 | Q_OBJECT | ||
548 | #if QT_VERSION >= 0x050000 | 545 | #if QT_VERSION >= 0x050000 | ||
549 | Q_PLUGIN_METADATA(IID "com.affinix.qca.Plugin/1.0") | 546 | Q_PLUGIN_METADATA(IID "com.affinix.qca.Plugin/1.0") | ||
Show All 11 Lines |
AFAICT this leaks the algorithm object.