File indexing completed on 2024-12-08 04:20:08

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_tools.h"
0023 
0024 #include "qdebug.h"
0025 
0026 #ifdef Q_OS_UNIX
0027 #include <cstdlib>
0028 #include <sys/mman.h>
0029 #endif
0030 #include "botantools/botantools.h"
0031 
0032 namespace QCA {
0033 
0034 static bool can_lock()
0035 {
0036 #ifdef Q_OS_UNIX
0037     bool ok = false;
0038 #ifdef MLOCK_NOT_VOID_PTR
0039 #define MLOCK_TYPE char *
0040 #define MLOCK_TYPE_CAST (MLOCK_TYPE)
0041 #else
0042 #define MLOCK_TYPE void *
0043 #define MLOCK_TYPE_CAST
0044 #endif
0045 
0046     MLOCK_TYPE d = MLOCK_TYPE_CAST malloc(256);
0047     if (mlock(d, 256) == 0) {
0048         munlock(d, 256);
0049         ok = true;
0050     }
0051     free(d);
0052     return ok;
0053 #else
0054     return true;
0055 #endif
0056 }
0057 
0058 // Botan shouldn't throw any exceptions in our init/deinit.
0059 
0060 static Botan::Allocator *alloc = nullptr;
0061 
0062 void botan_throw_abort()
0063 {
0064     fprintf(stderr, "QCA: Exception from internal Botan\n");
0065     abort();
0066 }
0067 
0068 bool botan_init(int prealloc, bool mmap)
0069 {
0070     // 64k minimum
0071     if (prealloc < 64)
0072         prealloc = 64;
0073 
0074     bool secmem = false;
0075 
0076     try {
0077         Botan::Builtin_Modules modules;
0078         Botan::Library_State  *libstate = new Botan::Library_State(modules.mutex_factory());
0079         libstate->prealloc_size         = prealloc * 1024;
0080         Botan::set_global_state(libstate);
0081         Botan::global_state().load(modules);
0082 
0083         if (can_lock()) {
0084             Botan::global_state().set_default_allocator("locking");
0085             secmem = true;
0086         } else if (mmap) {
0087             Botan::global_state().set_default_allocator("mmap");
0088             secmem = true;
0089         }
0090         alloc = Botan::Allocator::get(true);
0091     } catch (std::exception &) {
0092         fprintf(stderr, "QCA: Error initializing internal Botan\n");
0093         abort();
0094     }
0095 
0096     return secmem;
0097 }
0098 
0099 void botan_deinit()
0100 {
0101     try {
0102         alloc = nullptr;
0103         Botan::set_global_state(nullptr);
0104     } catch (std::exception &) {
0105         botan_throw_abort();
0106     }
0107 }
0108 
0109 void *botan_secure_alloc(int bytes)
0110 {
0111     try {
0112         return alloc->allocate((Botan::u32bit)bytes);
0113     } catch (std::exception &) {
0114         botan_throw_abort();
0115     }
0116     return nullptr; // never get here
0117 }
0118 
0119 void botan_secure_free(void *p, int bytes)
0120 {
0121     try {
0122         alloc->deallocate(p, (Botan::u32bit)bytes);
0123     } catch (std::exception &) {
0124         botan_throw_abort();
0125     }
0126 }
0127 
0128 } // end namespace QCA
0129 
0130 void *qca_secure_alloc(int bytes)
0131 {
0132     // allocate enough room to store a size value in front, return a pointer after it
0133     char *c                       = (char *)QCA::botan_secure_alloc(bytes + sizeof(int));
0134     reinterpret_cast<int *>(c)[0] = bytes + sizeof(int);
0135     return c + sizeof(int);
0136 }
0137 
0138 void qca_secure_free(void *p)
0139 {
0140     // backtrack to read the size value
0141     char *c = (char *)p;
0142     c -= sizeof(int);
0143     const int bytes = reinterpret_cast<int *>(c)[0];
0144     QCA::botan_secure_free(c, bytes);
0145 }
0146 
0147 void *qca_secure_realloc(void *p, int bytes)
0148 {
0149     // if null, do a plain alloc (just like how realloc() works)
0150     if (!p)
0151         return qca_secure_alloc(bytes);
0152 
0153     // backtrack to read the size value
0154     char *c = (char *)p;
0155     c -= sizeof(int);
0156     const int oldsize = reinterpret_cast<int *>(c)[0] - sizeof(int);
0157 
0158     // alloc the new chunk
0159     char *new_p = (char *)qca_secure_alloc(bytes);
0160     if (!new_p)
0161         return nullptr;
0162 
0163     // move over the memory from the original block
0164     memmove(new_p, p, qMin(oldsize, bytes));
0165 
0166     // free the original
0167     qca_secure_free(p);
0168 
0169     // done
0170     return new_p;
0171 }
0172 
0173 namespace QCA {
0174 
0175 // secure or non-secure buffer, with trailing 0-byte.
0176 // buffer size of 0 is okay (sbuf/qbuf will be 0).
0177 struct alloc_info
0178 {
0179     bool  sec;
0180     char *data;
0181     int   size;
0182 
0183     // internal
0184     Botan::SecureVector<Botan::byte> *sbuf;
0185     QByteArray                       *qbuf;
0186 };
0187 
0188 // note: these functions don't return error if memory allocation/resizing
0189 //   fails..  maybe fix this someday?
0190 
0191 // ai: uninitialized
0192 // size: >= 0
0193 // note: memory will be initially zero'd out
0194 static bool ai_new(alloc_info *ai, int size, bool sec);
0195 
0196 // ai: uninitialized
0197 // from: initialized
0198 static bool ai_copy(alloc_info *ai, const alloc_info *from);
0199 
0200 // ai: initialized
0201 // new_size: >= 0
0202 static bool ai_resize(alloc_info *ai, int new_size);
0203 
0204 // ai: initialized
0205 static void ai_delete(alloc_info *ai);
0206 
0207 bool ai_new(alloc_info *ai, int size, bool sec)
0208 {
0209     if (size < 0)
0210         return false;
0211 
0212     ai->size = size;
0213     ai->sec  = sec;
0214 
0215     if (size == 0) {
0216         ai->sbuf = nullptr;
0217         ai->qbuf = nullptr;
0218         ai->data = nullptr;
0219         return true;
0220     }
0221 
0222     if (sec) {
0223         try {
0224             ai->sbuf = new Botan::SecureVector<Botan::byte>((Botan::u32bit)size + 1);
0225         } catch (std::exception &) {
0226             botan_throw_abort();
0227             return false; // never get here
0228         }
0229 
0230         (*(ai->sbuf))[size] = 0;
0231         ai->qbuf            = nullptr;
0232         Botan::byte *bp     = (Botan::byte *)(*(ai->sbuf));
0233         ai->data            = (char *)bp;
0234     } else {
0235         ai->sbuf = nullptr;
0236         ai->qbuf = new QByteArray(size, 0);
0237         ai->data = ai->qbuf->data();
0238     }
0239 
0240     return true;
0241 }
0242 
0243 bool ai_copy(alloc_info *ai, const alloc_info *from)
0244 {
0245     ai->size = from->size;
0246     ai->sec  = from->sec;
0247 
0248     if (ai->size == 0) {
0249         ai->sbuf = nullptr;
0250         ai->qbuf = nullptr;
0251         ai->data = nullptr;
0252         return true;
0253     }
0254 
0255     if (ai->sec) {
0256         try {
0257             ai->sbuf = new Botan::SecureVector<Botan::byte>(*(from->sbuf));
0258         } catch (std::exception &) {
0259             botan_throw_abort();
0260             return false; // never get here
0261         }
0262 
0263         ai->qbuf        = nullptr;
0264         Botan::byte *bp = (Botan::byte *)(*(ai->sbuf));
0265         ai->data        = (char *)bp;
0266     } else {
0267         ai->sbuf = nullptr;
0268         ai->qbuf = new QByteArray(*(from->qbuf));
0269         ai->data = ai->qbuf->data();
0270     }
0271 
0272     return true;
0273 }
0274 
0275 bool ai_resize(alloc_info *ai, int new_size)
0276 {
0277     if (new_size < 0)
0278         return false;
0279 
0280     // new size is empty
0281     if (new_size == 0) {
0282         // we currently aren't empty
0283         if (ai->size > 0) {
0284             if (ai->sec) {
0285                 delete ai->sbuf;
0286                 ai->sbuf = nullptr;
0287             } else {
0288                 delete ai->qbuf;
0289                 ai->qbuf = nullptr;
0290             }
0291 
0292             ai->size = 0;
0293             ai->data = nullptr;
0294         }
0295 
0296         return true;
0297     }
0298 
0299     if (ai->sec) {
0300         Botan::SecureVector<Botan::byte> *new_buf;
0301         try {
0302             new_buf = new Botan::SecureVector<Botan::byte>((Botan::u32bit)new_size + 1);
0303         } catch (std::exception &) {
0304             botan_throw_abort();
0305             return false; // never get here
0306         }
0307 
0308         Botan::byte *new_p = (Botan::byte *)(*new_buf);
0309         if (ai->size > 0) {
0310             const Botan::byte *old_p = (const Botan::byte *)(*(ai->sbuf));
0311             memcpy(new_p, old_p, qMin(new_size, ai->size));
0312             delete ai->sbuf;
0313         }
0314         ai->sbuf                = new_buf;
0315         ai->size                = new_size;
0316         (*(ai->sbuf))[new_size] = 0;
0317         ai->data                = (char *)new_p;
0318     } else {
0319         if (ai->size > 0)
0320             ai->qbuf->resize(new_size);
0321         else
0322             ai->qbuf = new QByteArray(new_size, 0);
0323 
0324         ai->size = new_size;
0325         ai->data = ai->qbuf->data();
0326     }
0327 
0328     return true;
0329 }
0330 
0331 void ai_delete(alloc_info *ai)
0332 {
0333     if (ai->size > 0) {
0334         if (ai->sec)
0335             delete ai->sbuf;
0336         else
0337             delete ai->qbuf;
0338     }
0339 }
0340 
0341 //----------------------------------------------------------------------------
0342 // MemoryRegion
0343 //----------------------------------------------------------------------------
0344 static char blank[] = "";
0345 
0346 class MemoryRegion::Private : public QSharedData
0347 {
0348 public:
0349     alloc_info ai;
0350 
0351     Private(int size, bool sec)
0352     {
0353         ai_new(&ai, size, sec);
0354     }
0355 
0356     Private(const QByteArray &from, bool sec)
0357     {
0358         ai_new(&ai, from.size(), sec);
0359         memcpy(ai.data, from.data(), ai.size);
0360     }
0361 
0362     Private(const Private &from)
0363         : QSharedData(from)
0364     {
0365         ai_copy(&ai, &from.ai);
0366     }
0367 
0368     ~Private()
0369     {
0370         ai_delete(&ai);
0371     }
0372 
0373     bool resize(int new_size)
0374     {
0375         return ai_resize(&ai, new_size);
0376     }
0377 
0378     void setSecure(bool sec)
0379     {
0380         // if same mode, do nothing
0381         if (ai.sec == sec)
0382             return;
0383 
0384         alloc_info other;
0385         ai_new(&other, ai.size, sec);
0386         memcpy(other.data, ai.data, ai.size);
0387         ai_delete(&ai);
0388         ai = other;
0389     }
0390 };
0391 
0392 MemoryRegion::MemoryRegion()
0393     : _secure(false)
0394     , d(nullptr)
0395 {
0396 }
0397 
0398 MemoryRegion::MemoryRegion(const char *str)
0399     : _secure(false)
0400     , d(new Private(QByteArray::fromRawData(str, strlen(str)), false))
0401 {
0402 }
0403 
0404 MemoryRegion::MemoryRegion(const QByteArray &from)
0405     : _secure(false)
0406     , d(new Private(from, false))
0407 {
0408 }
0409 
0410 MemoryRegion::MemoryRegion(const MemoryRegion &from)
0411     : _secure(from._secure)
0412     , d(from.d)
0413 {
0414 }
0415 
0416 MemoryRegion::~MemoryRegion()
0417 {
0418 }
0419 
0420 MemoryRegion &MemoryRegion::operator=(const MemoryRegion &from)
0421 {
0422     _secure = from._secure;
0423     d       = from.d;
0424     return *this;
0425 }
0426 
0427 MemoryRegion &MemoryRegion::operator=(const QByteArray &from)
0428 {
0429     set(from, false);
0430     return *this;
0431 }
0432 
0433 bool MemoryRegion::isNull() const
0434 {
0435     return (d ? false : true);
0436 }
0437 
0438 bool MemoryRegion::isSecure() const
0439 {
0440     return _secure;
0441 }
0442 
0443 QByteArray MemoryRegion::toByteArray() const
0444 {
0445     if (!d)
0446         return QByteArray();
0447 
0448     if (d->ai.sec) {
0449         QByteArray buf(d->ai.size, 0);
0450         memcpy(buf.data(), d->ai.data, d->ai.size);
0451         return buf;
0452     } else {
0453         if (d->ai.size > 0)
0454             return *(d->ai.qbuf);
0455         else
0456             return QByteArray((int)0, (char)0);
0457     }
0458 }
0459 
0460 MemoryRegion::MemoryRegion(bool secure)
0461     : _secure(secure)
0462     , d(nullptr)
0463 {
0464 }
0465 
0466 MemoryRegion::MemoryRegion(int size, bool secure)
0467     : _secure(secure)
0468     , d(new Private(size, secure))
0469 {
0470 }
0471 
0472 MemoryRegion::MemoryRegion(const QByteArray &from, bool secure)
0473     : _secure(secure)
0474     , d(new Private(from, secure))
0475 {
0476 }
0477 
0478 char *MemoryRegion::data()
0479 {
0480     if (!d)
0481         return blank;
0482     return d->ai.data;
0483 }
0484 
0485 const char *MemoryRegion::data() const
0486 {
0487     if (!d)
0488         return blank;
0489     return d->ai.data;
0490 }
0491 
0492 const char *MemoryRegion::constData() const
0493 {
0494     if (!d)
0495         return blank;
0496     return d->ai.data;
0497 }
0498 
0499 char &MemoryRegion::at(int index)
0500 {
0501     return *(d->ai.data + index);
0502 }
0503 
0504 const char &MemoryRegion::at(int index) const
0505 {
0506     return *(d->ai.data + index);
0507 }
0508 
0509 int MemoryRegion::size() const
0510 {
0511     if (!d)
0512         return 0;
0513     return d->ai.size;
0514 }
0515 
0516 bool MemoryRegion::isEmpty() const
0517 {
0518     if (!d)
0519         return true;
0520     return (d->ai.size > 0 ? false : true);
0521 }
0522 
0523 bool MemoryRegion::resize(int size)
0524 {
0525     if (!d) {
0526         d = new Private(size, _secure);
0527         return true;
0528     }
0529 
0530     if (d->ai.size == size)
0531         return true;
0532 
0533     return d->resize(size);
0534 }
0535 
0536 void MemoryRegion::set(const QByteArray &from, bool secure)
0537 {
0538     _secure = secure;
0539 
0540     if (!from.isEmpty())
0541         d = new Private(from, secure);
0542     else
0543         d = new Private(0, secure);
0544 }
0545 
0546 void MemoryRegion::setSecure(bool secure)
0547 {
0548     _secure = secure;
0549 
0550     if (!d) {
0551         d = new Private(0, secure);
0552         return;
0553     }
0554 
0555     d->setSecure(secure);
0556 }
0557 
0558 //----------------------------------------------------------------------------
0559 // SecureArray
0560 //----------------------------------------------------------------------------
0561 SecureArray::SecureArray()
0562     : MemoryRegion(true)
0563 {
0564 }
0565 
0566 SecureArray::SecureArray(int size, char ch)
0567     : MemoryRegion(size, true)
0568 {
0569     // ai_new fills with zeros for us
0570     if (ch != 0)
0571         fill(ch, size);
0572 }
0573 
0574 SecureArray::SecureArray(const char *str)
0575     : MemoryRegion(QByteArray::fromRawData(str, strlen(str)), true)
0576 {
0577 }
0578 
0579 SecureArray::SecureArray(const QByteArray &a)
0580     : MemoryRegion(a, true)
0581 {
0582 }
0583 
0584 SecureArray::SecureArray(const MemoryRegion &a)
0585     : MemoryRegion(a)
0586 {
0587     setSecure(true);
0588 }
0589 
0590 SecureArray::SecureArray(const SecureArray &from)
0591     : MemoryRegion(from)
0592 {
0593 }
0594 
0595 SecureArray::~SecureArray()
0596 {
0597 }
0598 
0599 SecureArray &SecureArray::operator=(const SecureArray &from)
0600 {
0601     MemoryRegion::operator=(from);
0602     return *this;
0603 }
0604 
0605 SecureArray &SecureArray::operator=(const QByteArray &from)
0606 {
0607     MemoryRegion::set(from, true);
0608     return *this;
0609 }
0610 
0611 void SecureArray::clear()
0612 {
0613     MemoryRegion::resize(0);
0614 }
0615 
0616 bool SecureArray::resize(int size)
0617 {
0618     return MemoryRegion::resize(size);
0619 }
0620 
0621 char &SecureArray::operator[](int index)
0622 {
0623     return at(index);
0624 }
0625 
0626 const char &SecureArray::operator[](int index) const
0627 {
0628     return at(index);
0629 }
0630 
0631 char &SecureArray::at(int index)
0632 {
0633     return MemoryRegion::at(index);
0634 }
0635 
0636 const char &SecureArray::at(int index) const
0637 {
0638     return MemoryRegion::at(index);
0639 }
0640 
0641 char *SecureArray::data()
0642 {
0643     return MemoryRegion::data();
0644 }
0645 
0646 const char *SecureArray::data() const
0647 {
0648     return MemoryRegion::data();
0649 }
0650 
0651 const char *SecureArray::constData() const
0652 {
0653     return MemoryRegion::constData();
0654 }
0655 
0656 int SecureArray::size() const
0657 {
0658     return MemoryRegion::size();
0659 }
0660 
0661 bool SecureArray::isEmpty() const
0662 {
0663     return MemoryRegion::isEmpty();
0664 }
0665 
0666 QByteArray SecureArray::toByteArray() const
0667 {
0668     return MemoryRegion::toByteArray();
0669 }
0670 
0671 SecureArray &SecureArray::append(const SecureArray &a)
0672 {
0673     const int oldsize = size();
0674     resize(oldsize + a.size());
0675     memcpy(data() + oldsize, a.data(), a.size());
0676     return *this;
0677 }
0678 
0679 bool SecureArray::operator==(const MemoryRegion &other) const
0680 {
0681     if (this == &other)
0682         return true;
0683     if (size() == other.size() && memcmp(data(), other.data(), size()) == 0)
0684         return true;
0685     return false;
0686 }
0687 
0688 SecureArray &SecureArray::operator+=(const SecureArray &a)
0689 {
0690     return append(a);
0691 }
0692 
0693 void SecureArray::fill(char fillChar, int fillToPosition)
0694 {
0695     const int len = (fillToPosition == -1) ? size() : qMin(fillToPosition, size());
0696     if (len > 0)
0697         memset(data(), (int)fillChar, len);
0698 }
0699 
0700 void SecureArray::set(const SecureArray &from)
0701 {
0702     *this = from;
0703 }
0704 
0705 void SecureArray::set(const QByteArray &from)
0706 {
0707     *this = from;
0708 }
0709 
0710 const SecureArray operator+(const SecureArray &a, const SecureArray &b)
0711 {
0712     SecureArray c = a;
0713     return c.append(b);
0714 }
0715 
0716 //----------------------------------------------------------------------------
0717 // BigInteger
0718 //----------------------------------------------------------------------------
0719 static void negate_binary(char *a, int size)
0720 {
0721     // negate = two's compliment + 1
0722     bool done = false;
0723     for (int n = size - 1; n >= 0; --n) {
0724         a[n] = ~a[n];
0725         if (!done) {
0726             if ((unsigned char)a[n] < 0xff) {
0727                 ++a[n];
0728                 done = true;
0729             } else
0730                 a[n] = 0;
0731         }
0732     }
0733 }
0734 
0735 class BigInteger::Private : public QSharedData
0736 {
0737 public:
0738     Botan::BigInt n;
0739 };
0740 
0741 BigInteger::BigInteger()
0742 {
0743     d = new Private;
0744 }
0745 
0746 BigInteger::BigInteger(int i)
0747 {
0748     d = new Private;
0749     if (i < 0) {
0750         d->n = Botan::BigInt(i * (-1));
0751         d->n.set_sign(Botan::BigInt::Negative);
0752     } else {
0753         d->n = Botan::BigInt(i);
0754         d->n.set_sign(Botan::BigInt::Positive);
0755     }
0756 }
0757 
0758 BigInteger::BigInteger(const char *c)
0759 {
0760     d = new Private;
0761     fromString(QString::fromLatin1(c));
0762 }
0763 
0764 BigInteger::BigInteger(const QString &s)
0765 {
0766     d = new Private;
0767     fromString(s);
0768 }
0769 
0770 BigInteger::BigInteger(const SecureArray &a)
0771 {
0772     d = new Private;
0773     fromArray(a);
0774 }
0775 
0776 BigInteger::BigInteger(const BigInteger &from)
0777 {
0778     *this = from;
0779 }
0780 
0781 BigInteger::~BigInteger()
0782 {
0783 }
0784 
0785 BigInteger &BigInteger::operator=(const BigInteger &from)
0786 {
0787     d = from.d;
0788     return *this;
0789 }
0790 
0791 BigInteger &BigInteger::operator+=(const BigInteger &i)
0792 {
0793     d->n += i.d->n;
0794     return *this;
0795 }
0796 
0797 BigInteger &BigInteger::operator-=(const BigInteger &i)
0798 {
0799     d->n -= i.d->n;
0800     return *this;
0801 }
0802 
0803 BigInteger &BigInteger::operator*=(const BigInteger &i)
0804 {
0805     d->n *= i.d->n;
0806     return *this;
0807 }
0808 
0809 BigInteger &BigInteger::operator/=(const BigInteger &i)
0810 {
0811     try {
0812         d->n /= i.d->n;
0813     } catch (std::exception &) {
0814         fprintf(stderr, "QCA: Botan integer division error\n");
0815         abort();
0816     }
0817     return *this;
0818 }
0819 
0820 BigInteger &BigInteger::operator%=(const BigInteger &i)
0821 {
0822     try {
0823         d->n %= i.d->n;
0824     } catch (std::exception &) {
0825         fprintf(stderr, "QCA: Botan integer division error\n");
0826         abort();
0827     }
0828     return *this;
0829 }
0830 
0831 BigInteger &BigInteger::operator=(const QString &s)
0832 {
0833     fromString(s);
0834     return *this;
0835 }
0836 
0837 int BigInteger::compare(const BigInteger &n) const
0838 {
0839     return ((d->n).cmp(n.d->n, true));
0840 }
0841 
0842 QTextStream &operator<<(QTextStream &stream, const BigInteger &b)
0843 {
0844     stream << b.toString();
0845     return stream;
0846 }
0847 
0848 SecureArray BigInteger::toArray() const
0849 {
0850     int size = d->n.encoded_size(Botan::BigInt::Binary);
0851 
0852     // return at least 8 bits
0853     if (size == 0) {
0854         SecureArray a(1);
0855         a[0] = 0;
0856         return a;
0857     }
0858 
0859     int         offset = 0;
0860     SecureArray a;
0861 
0862     // make room for a sign bit if needed
0863     if (d->n.get_bit((size * 8) - 1)) {
0864         ++size;
0865         a.resize(size);
0866         a[0] = 0;
0867         ++offset;
0868     } else
0869         a.resize(size);
0870 
0871     Botan::BigInt::encode((Botan::byte *)a.data() + offset, d->n, Botan::BigInt::Binary);
0872 
0873     if (d->n.is_negative())
0874         negate_binary(a.data(), a.size());
0875 
0876     return a;
0877 }
0878 
0879 void BigInteger::fromArray(const SecureArray &_a)
0880 {
0881     if (_a.isEmpty()) {
0882         d->n = Botan::BigInt(0);
0883         return;
0884     }
0885     SecureArray a = _a;
0886 
0887     Botan::BigInt::Sign sign = Botan::BigInt::Positive;
0888     if (a[0] & 0x80)
0889         sign = Botan::BigInt::Negative;
0890 
0891     if (sign == Botan::BigInt::Negative)
0892         negate_binary(a.data(), a.size());
0893 
0894     d->n = Botan::BigInt::decode((const Botan::byte *)a.data(), a.size(), Botan::BigInt::Binary);
0895     d->n.set_sign(sign);
0896 }
0897 
0898 QString BigInteger::toString() const
0899 {
0900     QByteArray cs;
0901     try {
0902         cs.resize(d->n.encoded_size(Botan::BigInt::Decimal));
0903         Botan::BigInt::encode((Botan::byte *)cs.data(), d->n, Botan::BigInt::Decimal);
0904     } catch (std::exception &) {
0905         return QString();
0906     }
0907 
0908     QString str;
0909     if (d->n.is_negative())
0910         str += QLatin1Char('-');
0911     str += QString::fromLatin1(cs);
0912     str.remove(QChar::Null);
0913     return str;
0914 }
0915 
0916 bool BigInteger::fromString(const QString &s)
0917 {
0918     if (s.isEmpty())
0919         return false;
0920     const QByteArray cs = s.toLatin1();
0921 
0922     bool neg = false;
0923     if (s[0] == QLatin1Char('-'))
0924         neg = true;
0925 
0926     try {
0927         d->n = Botan::BigInt::decode(
0928             (const Botan::byte *)cs.data() + (neg ? 1 : 0), cs.length() - (neg ? 1 : 0), Botan::BigInt::Decimal);
0929     } catch (std::exception &) {
0930         return false;
0931     }
0932 
0933     if (neg)
0934         d->n.set_sign(Botan::BigInt::Negative);
0935     else
0936         d->n.set_sign(Botan::BigInt::Positive);
0937     return true;
0938 }
0939 
0940 }