00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "qca_tools.h"
00023
00024 #include "qdebug.h"
00025
00026 #ifdef Q_OS_UNIX
00027 # include <stdlib.h>
00028 # include <sys/mman.h>
00029 #endif
00030 #include "botantools/botantools.h"
00031
00032 namespace QCA {
00033
00034 static bool can_lock()
00035 {
00036 #ifdef Q_OS_UNIX
00037 bool ok = false;
00038 #ifdef MLOCK_NOT_VOID_PTR
00039 # define MLOCK_TYPE char *
00040 # define MLOCK_TYPE_CAST (MLOCK_TYPE)
00041 #else
00042 # define MLOCK_TYPE void *
00043 # define MLOCK_TYPE_CAST
00044 #endif
00045
00046 MLOCK_TYPE d = MLOCK_TYPE_CAST malloc(256);
00047 if(mlock(d, 256) == 0)
00048 {
00049 munlock(d, 256);
00050 ok = true;
00051 }
00052 free(d);
00053 return ok;
00054 #else
00055 return true;
00056 #endif
00057 }
00058
00059
00060
00061 static Botan::Allocator *alloc = 0;
00062
00063 void botan_throw_abort()
00064 {
00065 fprintf(stderr, "QCA: Exception from internal Botan\n");
00066 abort();
00067 }
00068
00069 bool botan_init(int prealloc, bool mmap)
00070 {
00071
00072 if(prealloc < 64)
00073 prealloc = 64;
00074
00075 bool secmem = false;
00076
00077 try
00078 {
00079 Botan::Builtin_Modules modules;
00080 Botan::Library_State *libstate = new Botan::Library_State(modules.mutex_factory());
00081 libstate->prealloc_size = prealloc * 1024;
00082 Botan::set_global_state(libstate);
00083 Botan::global_state().load(modules);
00084
00085 if(can_lock())
00086 {
00087 Botan::global_state().set_default_allocator("locking");
00088 secmem = true;
00089 }
00090 else if(mmap)
00091 {
00092 Botan::global_state().set_default_allocator("mmap");
00093 secmem = true;
00094 }
00095 alloc = Botan::Allocator::get(true);
00096 }
00097 catch(std::exception &)
00098 {
00099 fprintf(stderr, "QCA: Error initializing internal Botan\n");
00100 abort();
00101 }
00102
00103 return secmem;
00104 }
00105
00106 void botan_deinit()
00107 {
00108 try
00109 {
00110 alloc = 0;
00111 Botan::set_global_state(0);
00112 }
00113 catch(std::exception &)
00114 {
00115 botan_throw_abort();
00116 }
00117 }
00118
00119 void *botan_secure_alloc(int bytes)
00120 {
00121 try
00122 {
00123 return alloc->allocate((Botan::u32bit)bytes);
00124 }
00125 catch(std::exception &)
00126 {
00127 botan_throw_abort();
00128 }
00129 return 0;
00130 }
00131
00132 void botan_secure_free(void *p, int bytes)
00133 {
00134 try
00135 {
00136 alloc->deallocate(p, (Botan::u32bit)bytes);
00137 }
00138 catch(std::exception &)
00139 {
00140 botan_throw_abort();
00141 }
00142 }
00143
00144 }
00145
00146 void *qca_secure_alloc(int bytes)
00147 {
00148
00149 char *c = (char *)QCA::botan_secure_alloc(bytes + sizeof(int));
00150 ((int *)c)[0] = bytes + sizeof(int);
00151 return c + sizeof(int);
00152 }
00153
00154 void qca_secure_free(void *p)
00155 {
00156
00157 char *c = (char *)p;
00158 c -= sizeof(int);
00159 int bytes = ((int *)c)[0];
00160 QCA::botan_secure_free(c, bytes);
00161 }
00162
00163 void *qca_secure_realloc(void *p, int bytes)
00164 {
00165
00166 if(!p)
00167 return qca_secure_alloc(bytes);
00168
00169
00170 char *c = (char *)p;
00171 c -= sizeof(int);
00172 int oldsize = ((int *)c)[0] - sizeof(int);
00173
00174
00175 char *new_p = (char *)qca_secure_alloc(bytes);
00176 if(!new_p)
00177 return 0;
00178
00179
00180 memmove(new_p, p, qMin(oldsize, bytes));
00181
00182
00183 qca_secure_free(p);
00184
00185
00186 return new_p;
00187 }
00188
00189 namespace QCA {
00190
00191
00192
00193 struct alloc_info
00194 {
00195 bool sec;
00196 char *data;
00197 int size;
00198
00199
00200 Botan::SecureVector<Botan::byte> *sbuf;
00201 QByteArray *qbuf;
00202 };
00203
00204
00205
00206
00207
00208
00209
00210 static bool ai_new(alloc_info *ai, int size, bool sec);
00211
00212
00213
00214 static bool ai_copy(alloc_info *ai, const alloc_info *from);
00215
00216
00217
00218 static bool ai_resize(alloc_info *ai, int new_size);
00219
00220
00221 static void ai_delete(alloc_info *ai);
00222
00223 bool ai_new(alloc_info *ai, int size, bool sec)
00224 {
00225 if(size < 0)
00226 return false;
00227
00228 ai->size = size;
00229 ai->sec = sec;
00230
00231 if(size == 0)
00232 {
00233 ai->sbuf = 0;
00234 ai->qbuf = 0;
00235 ai->data = 0;
00236 return true;
00237 }
00238
00239 if(sec)
00240 {
00241 try
00242 {
00243 ai->sbuf = new Botan::SecureVector<Botan::byte>((Botan::u32bit)size + 1);
00244 }
00245 catch(std::exception &)
00246 {
00247 botan_throw_abort();
00248 return false;
00249 }
00250
00251 (*(ai->sbuf))[size] = 0;
00252 ai->qbuf = 0;
00253 Botan::byte *bp = (Botan::byte *)(*(ai->sbuf));
00254 ai->data = (char *)bp;
00255 }
00256 else
00257 {
00258 ai->sbuf = 0;
00259 ai->qbuf = new QByteArray(size, 0);
00260 ai->data = ai->qbuf->data();
00261 }
00262
00263 return true;
00264 }
00265
00266 bool ai_copy(alloc_info *ai, const alloc_info *from)
00267 {
00268 ai->size = from->size;
00269 ai->sec = from->sec;
00270
00271 if(ai->size == 0)
00272 {
00273 ai->sbuf = 0;
00274 ai->qbuf = 0;
00275 ai->data = 0;
00276 return true;
00277 }
00278
00279 if(ai->sec)
00280 {
00281 try
00282 {
00283 ai->sbuf = new Botan::SecureVector<Botan::byte>(*(from->sbuf));
00284 }
00285 catch(std::exception &)
00286 {
00287 botan_throw_abort();
00288 return false;
00289 }
00290
00291 ai->qbuf = 0;
00292 Botan::byte *bp = (Botan::byte *)(*(ai->sbuf));
00293 ai->data = (char *)bp;
00294 }
00295 else
00296 {
00297 ai->sbuf = 0;
00298 ai->qbuf = new QByteArray(*(from->qbuf));
00299 ai->data = ai->qbuf->data();
00300 }
00301
00302 return true;
00303 }
00304
00305 bool ai_resize(alloc_info *ai, int new_size)
00306 {
00307 if(new_size < 0)
00308 return false;
00309
00310
00311 if(new_size == 0)
00312 {
00313
00314 if(ai->size > 0)
00315 {
00316 if(ai->sec)
00317 {
00318 delete ai->sbuf;
00319 ai->sbuf = 0;
00320 }
00321 else
00322 {
00323 delete ai->qbuf;
00324 ai->qbuf = 0;
00325 }
00326
00327 ai->size = 0;
00328 ai->data = 0;
00329 }
00330
00331 return true;
00332 }
00333
00334 if(ai->sec)
00335 {
00336 Botan::SecureVector<Botan::byte> *new_buf;
00337 try
00338 {
00339 new_buf = new Botan::SecureVector<Botan::byte>((Botan::u32bit)new_size + 1);
00340 }
00341 catch(std::exception &)
00342 {
00343 botan_throw_abort();
00344 return false;
00345 }
00346
00347 Botan::byte *new_p = (Botan::byte *)(*new_buf);
00348 if(ai->size > 0)
00349 {
00350 const Botan::byte *old_p = (const Botan::byte *)(*(ai->sbuf));
00351 memcpy(new_p, old_p, qMin(new_size, ai->size));
00352 delete ai->sbuf;
00353 }
00354 ai->sbuf = new_buf;
00355 ai->size = new_size;
00356 (*(ai->sbuf))[new_size] = 0;
00357 ai->data = (char *)new_p;
00358 }
00359 else
00360 {
00361 if(ai->size > 0)
00362 ai->qbuf->resize(new_size);
00363 else
00364 ai->qbuf = new QByteArray(new_size, 0);
00365
00366 ai->size = new_size;
00367 ai->data = ai->qbuf->data();
00368 }
00369
00370 return true;
00371 }
00372
00373 void ai_delete(alloc_info *ai)
00374 {
00375 if(ai->size > 0)
00376 {
00377 if(ai->sec)
00378 delete ai->sbuf;
00379 else
00380 delete ai->qbuf;
00381 }
00382 }
00383
00384
00385
00386
00387 static char blank[] = "";
00388
00389 class MemoryRegion::Private : public QSharedData
00390 {
00391 public:
00392 alloc_info ai;
00393
00394 Private(int size, bool sec)
00395 {
00396 ai_new(&ai, size, sec);
00397 }
00398
00399 Private(const QByteArray &from, bool sec)
00400 {
00401 ai_new(&ai, from.size(), sec);
00402 memcpy(ai.data, from.data(), ai.size);
00403 }
00404
00405 Private(const Private &from) : QSharedData(from)
00406 {
00407 ai_copy(&ai, &from.ai);
00408 }
00409
00410 ~Private()
00411 {
00412 ai_delete(&ai);
00413 }
00414
00415 bool resize(int new_size)
00416 {
00417 return ai_resize(&ai, new_size);
00418 }
00419
00420 void setSecure(bool sec)
00421 {
00422
00423 if(ai.sec == sec)
00424 return;
00425
00426 alloc_info other;
00427 ai_new(&other, ai.size, sec);
00428 memcpy(other.data, ai.data, ai.size);
00429 ai_delete(&ai);
00430 ai = other;
00431 }
00432 };
00433
00434 MemoryRegion::MemoryRegion()
00435 :_secure(false), d(0)
00436 {
00437 }
00438
00439 MemoryRegion::MemoryRegion(const char *str)
00440 :_secure(false), d(new Private(QByteArray::fromRawData(str, strlen(str)), false))
00441 {
00442 }
00443
00444 MemoryRegion::MemoryRegion(const QByteArray &from)
00445 :_secure(false), d(new Private(from, false))
00446 {
00447 }
00448
00449 MemoryRegion::MemoryRegion(const MemoryRegion &from)
00450 :_secure(from._secure), d(from.d)
00451 {
00452 }
00453
00454 MemoryRegion::~MemoryRegion()
00455 {
00456 }
00457
00458 MemoryRegion & MemoryRegion::operator=(const MemoryRegion &from)
00459 {
00460 _secure = from._secure;
00461 d = from.d;
00462 return *this;
00463 }
00464
00465 MemoryRegion & MemoryRegion::operator=(const QByteArray &from)
00466 {
00467 set(from, false);
00468 return *this;
00469 }
00470
00471 bool MemoryRegion::isNull() const
00472 {
00473 return (d ? false : true);
00474 }
00475
00476 bool MemoryRegion::isSecure() const
00477 {
00478 return _secure;
00479 }
00480
00481 QByteArray MemoryRegion::toByteArray() const
00482 {
00483 if(!d)
00484 return QByteArray();
00485
00486 if(d->ai.sec)
00487 {
00488 QByteArray buf(d->ai.size, 0);
00489 memcpy(buf.data(), d->ai.data, d->ai.size);
00490 return buf;
00491 }
00492 else
00493 {
00494 if(d->ai.size > 0)
00495 return *(d->ai.qbuf);
00496 else
00497 return QByteArray((int)0, (char)0);
00498 }
00499 }
00500
00501 MemoryRegion::MemoryRegion(bool secure)
00502 :_secure(secure), d(0)
00503 {
00504 }
00505
00506 MemoryRegion::MemoryRegion(int size, bool secure)
00507 :_secure(secure), d(new Private(size, secure))
00508 {
00509 }
00510
00511 MemoryRegion::MemoryRegion(const QByteArray &from, bool secure)
00512 :_secure(secure), d(new Private(from, secure))
00513 {
00514 }
00515
00516 char *MemoryRegion::data()
00517 {
00518 if(!d)
00519 return blank;
00520 return d->ai.data;
00521 }
00522
00523 const char *MemoryRegion::data() const
00524 {
00525 if(!d)
00526 return blank;
00527 return d->ai.data;
00528 }
00529
00530 const char *MemoryRegion::constData() const
00531 {
00532 if(!d)
00533 return blank;
00534 return d->ai.data;
00535 }
00536
00537 char & MemoryRegion::at(int index)
00538 {
00539 return *(d->ai.data + index);
00540 }
00541
00542 const char & MemoryRegion::at(int index) const
00543 {
00544 return *(d->ai.data + index);
00545 }
00546
00547 int MemoryRegion::size() const
00548 {
00549 if(!d)
00550 return 0;
00551 return d->ai.size;
00552 }
00553
00554 bool MemoryRegion::isEmpty() const
00555 {
00556 if(!d)
00557 return true;
00558 return (d->ai.size > 0 ? false : true);
00559 }
00560
00561 bool MemoryRegion::resize(int size)
00562 {
00563 if(!d)
00564 {
00565 d = new Private(size, _secure);
00566 return true;
00567 }
00568
00569 if(d->ai.size == size)
00570 return true;
00571
00572 return d->resize(size);
00573 }
00574
00575 void MemoryRegion::set(const QByteArray &from, bool secure)
00576 {
00577 _secure = secure;
00578
00579 if(!from.isEmpty())
00580 d = new Private(from, secure);
00581 else
00582 d = new Private(0, secure);
00583 }
00584
00585 void MemoryRegion::setSecure(bool secure)
00586 {
00587 _secure = secure;
00588
00589 if(!d)
00590 {
00591 d = new Private(0, secure);
00592 return;
00593 }
00594
00595 d->setSecure(secure);
00596 }
00597
00598
00599
00600
00601 SecureArray::SecureArray()
00602 :MemoryRegion(true)
00603 {
00604 }
00605
00606 SecureArray::SecureArray(int size, char ch)
00607 :MemoryRegion(size, true)
00608 {
00609
00610 if(ch != 0)
00611 fill(ch, size);
00612 }
00613
00614 SecureArray::SecureArray(const char *str)
00615 :MemoryRegion(QByteArray::fromRawData(str, strlen(str)), true)
00616 {
00617 }
00618
00619 SecureArray::SecureArray(const QByteArray &a)
00620 :MemoryRegion(a, true)
00621 {
00622 }
00623
00624 SecureArray::SecureArray(const MemoryRegion &a)
00625 :MemoryRegion(a)
00626 {
00627 setSecure(true);
00628 }
00629
00630 SecureArray::SecureArray(const SecureArray &from)
00631 :MemoryRegion(from)
00632 {
00633 }
00634
00635 SecureArray::~SecureArray()
00636 {
00637 }
00638
00639 SecureArray & SecureArray::operator=(const SecureArray &from)
00640 {
00641 MemoryRegion::operator=(from);
00642 return *this;
00643 }
00644
00645 SecureArray & SecureArray::operator=(const QByteArray &from)
00646 {
00647 MemoryRegion::set(from, true);
00648 return *this;
00649 }
00650
00651 void SecureArray::clear()
00652 {
00653 MemoryRegion::resize(0);
00654 }
00655
00656 bool SecureArray::resize(int size)
00657 {
00658 return MemoryRegion::resize(size);
00659 }
00660
00661 char & SecureArray::operator[](int index)
00662 {
00663 return at(index);
00664 }
00665
00666 const char & SecureArray::operator[](int index) const
00667 {
00668 return at(index);
00669 }
00670
00671 char & SecureArray::at(int index)
00672 {
00673 return MemoryRegion::at(index);
00674 }
00675
00676 const char & SecureArray::at(int index) const
00677 {
00678 return MemoryRegion::at(index);
00679 }
00680
00681 char *SecureArray::data()
00682 {
00683 return MemoryRegion::data();
00684 }
00685
00686 const char *SecureArray::data() const
00687 {
00688 return MemoryRegion::data();
00689 }
00690
00691 const char *SecureArray::constData() const
00692 {
00693 return MemoryRegion::constData();
00694 }
00695
00696 int SecureArray::size() const
00697 {
00698 return MemoryRegion::size();
00699 }
00700
00701 bool SecureArray::isEmpty() const
00702 {
00703 return MemoryRegion::isEmpty();
00704 }
00705
00706 QByteArray SecureArray::toByteArray() const
00707 {
00708 return MemoryRegion::toByteArray();
00709 }
00710
00711 SecureArray & SecureArray::append(const SecureArray &a)
00712 {
00713 int oldsize = size();
00714 resize(oldsize + a.size());
00715 memcpy(data() + oldsize, a.data(), a.size());
00716 return *this;
00717 }
00718
00719 bool SecureArray::operator==(const MemoryRegion &other) const
00720 {
00721 if(this == &other)
00722 return true;
00723 if(size() == other.size() && memcmp(data(), other.data(), size()) == 0)
00724 return true;
00725 return false;
00726 }
00727
00728 SecureArray & SecureArray::operator+=(const SecureArray &a)
00729 {
00730 return append(a);
00731 }
00732
00733 void SecureArray::fill(char fillChar, int fillToPosition)
00734 {
00735 int len = (fillToPosition == -1) ? size() : qMin(fillToPosition, size());
00736 if(len > 0)
00737 memset(data(), (int)fillChar, len);
00738 }
00739
00740 void SecureArray::set(const SecureArray &from)
00741 {
00742 *this = from;
00743 }
00744
00745 void SecureArray::set(const QByteArray &from)
00746 {
00747 *this = from;
00748 }
00749
00750 const SecureArray operator+(const SecureArray &a, const SecureArray &b)
00751 {
00752 SecureArray c = a;
00753 return c.append(b);
00754 }
00755
00756
00757
00758
00759 static void negate_binary(char *a, int size)
00760 {
00761
00762 bool done = false;
00763 for(int n = size - 1; n >= 0; --n)
00764 {
00765 a[n] = ~a[n];
00766 if(!done)
00767 {
00768 if((unsigned char)a[n] < 0xff)
00769 {
00770 ++a[n];
00771 done = true;
00772 }
00773 else
00774 a[n] = 0;
00775 }
00776 }
00777 }
00778
00779 class BigInteger::Private : public QSharedData
00780 {
00781 public:
00782 Botan::BigInt n;
00783 };
00784
00785 BigInteger::BigInteger()
00786 {
00787 d = new Private;
00788 }
00789
00790 BigInteger::BigInteger(int i)
00791 {
00792 d = new Private;
00793 if(i < 0)
00794 {
00795 d->n = Botan::BigInt(i * (-1));
00796 d->n.set_sign(Botan::BigInt::Negative);
00797 }
00798 else
00799 {
00800 d->n = Botan::BigInt(i);
00801 d->n.set_sign(Botan::BigInt::Positive);
00802 }
00803 }
00804
00805 BigInteger::BigInteger(const char *c)
00806 {
00807 d = new Private;
00808 fromString(QString(c));
00809 }
00810
00811 BigInteger::BigInteger(const QString &s)
00812 {
00813 d = new Private;
00814 fromString(s);
00815 }
00816
00817 BigInteger::BigInteger(const SecureArray &a)
00818 {
00819 d = new Private;
00820 fromArray(a);
00821 }
00822
00823 BigInteger::BigInteger(const BigInteger &from)
00824 {
00825 *this = from;
00826 }
00827
00828 BigInteger::~BigInteger()
00829 {
00830 }
00831
00832 BigInteger & BigInteger::operator=(const BigInteger &from)
00833 {
00834 d = from.d;
00835 return *this;
00836 }
00837
00838 BigInteger & BigInteger::operator+=(const BigInteger &i)
00839 {
00840 d->n += i.d->n;
00841 return *this;
00842 }
00843
00844 BigInteger & BigInteger::operator-=(const BigInteger &i)
00845 {
00846 d->n -= i.d->n;
00847 return *this;
00848 }
00849
00850 BigInteger & BigInteger::operator*=(const BigInteger &i)
00851 {
00852 d->n *= i.d->n;
00853 return *this;
00854 }
00855
00856 BigInteger & BigInteger::operator/=(const BigInteger &i)
00857 {
00858 try
00859 {
00860 d->n /= i.d->n;
00861 }
00862 catch(std::exception &)
00863 {
00864 fprintf(stderr, "QCA: Botan integer division error\n");
00865 abort();
00866 }
00867 return *this;
00868 }
00869
00870 BigInteger & BigInteger::operator%=(const BigInteger &i)
00871 {
00872 try
00873 {
00874 d->n %= i.d->n;
00875 }
00876 catch(std::exception &)
00877 {
00878 fprintf(stderr, "QCA: Botan integer division error\n");
00879 abort();
00880 }
00881 return *this;
00882 }
00883
00884 BigInteger & BigInteger::operator=(const QString &s)
00885 {
00886 fromString(s);
00887 return *this;
00888 }
00889
00890 int BigInteger::compare(const BigInteger &n) const
00891 {
00892 return ( (d->n).cmp( n.d->n, true) );
00893 }
00894
00895 QTextStream &operator<<(QTextStream &stream, const BigInteger& b)
00896 {
00897 stream << b.toString();
00898 return stream;
00899 }
00900
00901 SecureArray BigInteger::toArray() const
00902 {
00903 int size = d->n.encoded_size(Botan::BigInt::Binary);
00904
00905
00906 if(size == 0)
00907 {
00908 SecureArray a(1);
00909 a[0] = 0;
00910 return a;
00911 }
00912
00913 int offset = 0;
00914 SecureArray a;
00915
00916
00917 if(d->n.get_bit((size * 8) - 1))
00918 {
00919 ++size;
00920 a.resize(size);
00921 a[0] = 0;
00922 ++offset;
00923 }
00924 else
00925 a.resize(size);
00926
00927 Botan::BigInt::encode((Botan::byte *)a.data() + offset, d->n, Botan::BigInt::Binary);
00928
00929 if(d->n.is_negative())
00930 negate_binary(a.data(), a.size());
00931
00932 return a;
00933 }
00934
00935 void BigInteger::fromArray(const SecureArray &_a)
00936 {
00937 if(_a.isEmpty())
00938 {
00939 d->n = Botan::BigInt(0);
00940 return;
00941 }
00942 SecureArray a = _a;
00943
00944 Botan::BigInt::Sign sign = Botan::BigInt::Positive;
00945 if(a[0] & 0x80)
00946 sign = Botan::BigInt::Negative;
00947
00948 if(sign == Botan::BigInt::Negative)
00949 negate_binary(a.data(), a.size());
00950
00951 d->n = Botan::BigInt::decode((const Botan::byte *)a.data(), a.size(), Botan::BigInt::Binary);
00952 d->n.set_sign(sign);
00953 }
00954
00955 QString BigInteger::toString() const
00956 {
00957 QByteArray cs;
00958 try
00959 {
00960 cs.resize(d->n.encoded_size(Botan::BigInt::Decimal));
00961 Botan::BigInt::encode((Botan::byte *)cs.data(), d->n, Botan::BigInt::Decimal);
00962 }
00963 catch(std::exception &)
00964 {
00965 return QString();
00966 }
00967
00968 QString str;
00969 if(d->n.is_negative())
00970 str += '-';
00971 str += QString::fromLatin1(cs);
00972 return str;
00973 }
00974
00975 bool BigInteger::fromString(const QString &s)
00976 {
00977 if(s.isEmpty())
00978 return false;
00979 QByteArray cs = s.toLatin1();
00980
00981 bool neg = false;
00982 if(s[0] == '-')
00983 neg = true;
00984
00985 try
00986 {
00987 d->n = Botan::BigInt::decode((const Botan::byte *)cs.data() + (neg ? 1 : 0), cs.length() - (neg ? 1 : 0), Botan::BigInt::Decimal);
00988 }
00989 catch(std::exception &)
00990 {
00991 return false;
00992 }
00993
00994 if(neg)
00995 d->n.set_sign(Botan::BigInt::Negative);
00996 else
00997 d->n.set_sign(Botan::BigInt::Positive);
00998 return true;
00999 }
01000
01001 }