File indexing completed on 2024-12-01 10:31:54
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 }