2
* Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com>
3
* Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net>
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21
#include "qca_tools.h"
27
# include <sys/mman.h>
29
#include "botantools/botantools.h"
33
static bool can_lock()
37
#ifdef MLOCK_NOT_VOID_PTR
38
# define MLOCK_TYPE char *
39
# define MLOCK_TYPE_CAST (MLOCK_TYPE)
41
# define MLOCK_TYPE void *
42
# define MLOCK_TYPE_CAST
45
MLOCK_TYPE d = MLOCK_TYPE_CAST malloc(256);
46
if(mlock(d, 256) == 0)
58
// Botan shouldn't throw any exceptions in our init/deinit.
60
static Botan::Allocator *alloc = 0;
62
void botan_throw_abort()
64
fprintf(stderr, "QCA: Exception from internal Botan\n");
68
bool botan_init(int prealloc, bool mmap)
78
Botan::Builtin_Modules modules;
79
Botan::Library_State *libstate = new Botan::Library_State(modules.mutex_factory());
80
libstate->prealloc_size = prealloc * 1024;
81
Botan::set_global_state(libstate);
82
Botan::global_state().load(modules);
86
Botan::global_state().set_default_allocator("locking");
91
Botan::global_state().set_default_allocator("mmap");
94
alloc = Botan::Allocator::get(true);
96
catch(std::exception &)
98
fprintf(stderr, "QCA: Error initializing internal Botan\n");
110
Botan::set_global_state(0);
112
catch(std::exception &)
118
void *botan_secure_alloc(int bytes)
122
return alloc->allocate((Botan::u32bit)bytes);
124
catch(std::exception &)
128
return 0; // never get here
131
void botan_secure_free(void *p, int bytes)
135
alloc->deallocate(p, (Botan::u32bit)bytes);
137
catch(std::exception &)
143
} // end namespace QCA
145
void *qca_secure_alloc(int bytes)
147
// allocate enough room to store a size value in front, return a pointer after it
148
char *c = (char *)QCA::botan_secure_alloc(bytes + sizeof(int));
149
((int *)c)[0] = bytes + sizeof(int);
150
return c + sizeof(int);
153
void qca_secure_free(void *p)
155
// backtrack to read the size value
158
int bytes = ((int *)c)[0];
159
QCA::botan_secure_free(c, bytes);
162
void *qca_secure_realloc(void *p, int bytes)
164
// if null, do a plain alloc (just like how realloc() works)
166
return qca_secure_alloc(bytes);
168
// backtrack to read the size value
171
int oldsize = ((int *)c)[0] - sizeof(int);
173
// alloc the new chunk
174
char *new_p = (char *)qca_secure_alloc(bytes);
178
// move over the memory from the original block
179
memmove(new_p, p, qMin(oldsize, bytes));
190
// secure or non-secure buffer, with trailing 0-byte.
191
// buffer size of 0 is okay (sbuf/qbuf will be 0).
199
Botan::SecureVector<Botan::byte> *sbuf;
203
// note: these functions don't return error if memory allocation/resizing
204
// fails.. maybe fix this someday?
208
// note: memory will be initially zero'd out
209
static bool ai_new(alloc_info *ai, int size, bool sec);
213
static bool ai_copy(alloc_info *ai, const alloc_info *from);
217
static bool ai_resize(alloc_info *ai, int new_size);
220
static void ai_delete(alloc_info *ai);
222
bool ai_new(alloc_info *ai, int size, bool sec)
242
ai->sbuf = new Botan::SecureVector<Botan::byte>((Botan::u32bit)size + 1);
244
catch(std::exception &)
247
return false; // never get here
250
(*(ai->sbuf))[size] = 0;
252
Botan::byte *bp = (Botan::byte *)(*(ai->sbuf));
253
ai->data = (char *)bp;
258
ai->qbuf = new QByteArray(size, 0);
259
ai->data = ai->qbuf->data();
265
bool ai_copy(alloc_info *ai, const alloc_info *from)
267
ai->size = from->size;
282
ai->sbuf = new Botan::SecureVector<Botan::byte>(*(from->sbuf));
284
catch(std::exception &)
287
return false; // never get here
291
Botan::byte *bp = (Botan::byte *)(*(ai->sbuf));
292
ai->data = (char *)bp;
297
ai->qbuf = new QByteArray(*(from->qbuf));
298
ai->data = ai->qbuf->data();
304
bool ai_resize(alloc_info *ai, int new_size)
312
// we currently aren't empty
335
Botan::SecureVector<Botan::byte> *new_buf;
338
new_buf = new Botan::SecureVector<Botan::byte>((Botan::u32bit)new_size + 1);
340
catch(std::exception &)
343
return false; // never get here
346
Botan::byte *new_p = (Botan::byte *)(*new_buf);
349
const Botan::byte *old_p = (const Botan::byte *)(*(ai->sbuf));
350
memcpy(new_p, old_p, qMin(new_size, ai->size));
355
(*(ai->sbuf))[new_size] = 0;
356
ai->data = (char *)new_p;
361
ai->qbuf->resize(new_size);
363
ai->qbuf = new QByteArray(new_size, 0);
366
ai->data = ai->qbuf->data();
372
void ai_delete(alloc_info *ai)
383
//----------------------------------------------------------------------------
385
//----------------------------------------------------------------------------
386
static char blank[] = "";
388
class MemoryRegion::Private : public QSharedData
393
Private(int size, bool sec)
395
ai_new(&ai, size, sec);
398
Private(const QByteArray &from, bool sec)
400
ai_new(&ai, from.size(), sec);
401
memcpy(ai.data, from.data(), ai.size);
404
Private(const Private &from) : QSharedData(from)
406
ai_copy(&ai, &from.ai);
414
bool resize(int new_size)
416
return ai_resize(&ai, new_size);
419
void setSecure(bool sec)
421
// if same mode, do nothing
426
ai_new(&other, ai.size, sec);
427
memcpy(other.data, ai.data, ai.size);
433
MemoryRegion::MemoryRegion()
434
:_secure(false), d(0)
438
MemoryRegion::MemoryRegion(const char *str)
439
:_secure(false), d(new Private(QByteArray::fromRawData(str, strlen(str)), false))
443
MemoryRegion::MemoryRegion(const QByteArray &from)
444
:_secure(false), d(new Private(from, false))
448
MemoryRegion::MemoryRegion(const MemoryRegion &from)
449
:_secure(from._secure), d(from.d)
453
MemoryRegion::~MemoryRegion()
457
MemoryRegion & MemoryRegion::operator=(const MemoryRegion &from)
459
_secure = from._secure;
464
MemoryRegion & MemoryRegion::operator=(const QByteArray &from)
470
bool MemoryRegion::isNull() const
472
return (d ? false : true);
475
bool MemoryRegion::isSecure() const
480
QByteArray MemoryRegion::toByteArray() const
487
QByteArray buf(d->ai.size, 0);
488
memcpy(buf.data(), d->ai.data, d->ai.size);
494
return *(d->ai.qbuf);
496
return QByteArray((int)0, (char)0);
500
MemoryRegion::MemoryRegion(bool secure)
501
:_secure(secure), d(0)
505
MemoryRegion::MemoryRegion(int size, bool secure)
506
:_secure(secure), d(new Private(size, secure))
510
MemoryRegion::MemoryRegion(const QByteArray &from, bool secure)
511
:_secure(secure), d(new Private(from, secure))
515
char *MemoryRegion::data()
522
const char *MemoryRegion::data() const
529
const char *MemoryRegion::constData() const
536
char & MemoryRegion::at(int index)
538
return *(d->ai.data + index);
541
const char & MemoryRegion::at(int index) const
543
return *(d->ai.data + index);
546
int MemoryRegion::size() const
553
bool MemoryRegion::isEmpty() const
557
return (d->ai.size > 0 ? false : true);
560
bool MemoryRegion::resize(int size)
564
d = new Private(size, _secure);
568
if(d->ai.size == size)
571
return d->resize(size);
574
void MemoryRegion::set(const QByteArray &from, bool secure)
579
d = new Private(from, secure);
581
d = new Private(0, secure);
584
void MemoryRegion::setSecure(bool secure)
590
d = new Private(0, secure);
594
d->setSecure(secure);
597
//----------------------------------------------------------------------------
599
//----------------------------------------------------------------------------
600
SecureArray::SecureArray()
605
SecureArray::SecureArray(int size, char ch)
606
:MemoryRegion(size, true)
608
// ai_new fills with zeros for us
613
SecureArray::SecureArray(const char *str)
614
:MemoryRegion(QByteArray::fromRawData(str, strlen(str)), true)
618
SecureArray::SecureArray(const QByteArray &a)
619
:MemoryRegion(a, true)
623
SecureArray::SecureArray(const MemoryRegion &a)
629
SecureArray::SecureArray(const SecureArray &from)
634
SecureArray::~SecureArray()
638
SecureArray & SecureArray::operator=(const SecureArray &from)
640
MemoryRegion::operator=(from);
644
SecureArray & SecureArray::operator=(const QByteArray &from)
646
MemoryRegion::set(from, true);
650
void SecureArray::clear()
652
MemoryRegion::resize(0);
655
bool SecureArray::resize(int size)
657
return MemoryRegion::resize(size);
660
char & SecureArray::operator[](int index)
665
const char & SecureArray::operator[](int index) const
670
char & SecureArray::at(int index)
672
return MemoryRegion::at(index);
675
const char & SecureArray::at(int index) const
677
return MemoryRegion::at(index);
680
char *SecureArray::data()
682
return MemoryRegion::data();
685
const char *SecureArray::data() const
687
return MemoryRegion::data();
690
const char *SecureArray::constData() const
692
return MemoryRegion::constData();
695
int SecureArray::size() const
697
return MemoryRegion::size();
700
bool SecureArray::isEmpty() const
702
return MemoryRegion::isEmpty();
705
QByteArray SecureArray::toByteArray() const
707
return MemoryRegion::toByteArray();
710
SecureArray & SecureArray::append(const SecureArray &a)
712
int oldsize = size();
713
resize(oldsize + a.size());
714
memcpy(data() + oldsize, a.data(), a.size());
718
bool SecureArray::operator==(const MemoryRegion &other) const
722
if(size() == other.size() && memcmp(data(), other.data(), size()) == 0)
727
SecureArray & SecureArray::operator+=(const SecureArray &a)
732
void SecureArray::fill(char fillChar, int fillToPosition)
734
int len = (fillToPosition == -1) ? size() : qMin(fillToPosition, size());
736
memset(data(), (int)fillChar, len);
739
void SecureArray::set(const SecureArray &from)
744
void SecureArray::set(const QByteArray &from)
749
const SecureArray operator+(const SecureArray &a, const SecureArray &b)
755
//----------------------------------------------------------------------------
757
//----------------------------------------------------------------------------
758
static void negate_binary(char *a, int size)
760
// negate = two's compliment + 1
762
for(int n = size - 1; n >= 0; --n)
767
if((unsigned char)a[n] < 0xff)
778
class BigInteger::Private : public QSharedData
784
BigInteger::BigInteger()
789
BigInteger::BigInteger(int i)
794
d->n = Botan::BigInt(i * (-1));
795
d->n.set_sign(Botan::BigInt::Negative);
799
d->n = Botan::BigInt(i);
800
d->n.set_sign(Botan::BigInt::Positive);
804
BigInteger::BigInteger(const char *c)
807
fromString(QString(c));
810
BigInteger::BigInteger(const QString &s)
816
BigInteger::BigInteger(const SecureArray &a)
822
BigInteger::BigInteger(const BigInteger &from)
827
BigInteger::~BigInteger()
831
BigInteger & BigInteger::operator=(const BigInteger &from)
837
BigInteger & BigInteger::operator+=(const BigInteger &i)
843
BigInteger & BigInteger::operator-=(const BigInteger &i)
849
BigInteger & BigInteger::operator*=(const BigInteger &i)
855
BigInteger & BigInteger::operator/=(const BigInteger &i)
861
catch(std::exception &)
863
fprintf(stderr, "QCA: Botan integer division error\n");
869
BigInteger & BigInteger::operator%=(const BigInteger &i)
875
catch(std::exception &)
877
fprintf(stderr, "QCA: Botan integer division error\n");
883
BigInteger & BigInteger::operator=(const QString &s)
889
int BigInteger::compare(const BigInteger &n) const
891
return ( (d->n).cmp( n.d->n, true) );
894
QTextStream &operator<<(QTextStream &stream, const BigInteger& b)
896
stream << b.toString();
900
SecureArray BigInteger::toArray() const
902
int size = d->n.encoded_size(Botan::BigInt::Binary);
904
// return at least 8 bits
915
// make room for a sign bit if needed
916
if(d->n.get_bit((size * 8) - 1))
926
Botan::BigInt::encode((Botan::byte *)a.data() + offset, d->n, Botan::BigInt::Binary);
928
if(d->n.is_negative())
929
negate_binary(a.data(), a.size());
934
void BigInteger::fromArray(const SecureArray &_a)
938
d->n = Botan::BigInt(0);
943
Botan::BigInt::Sign sign = Botan::BigInt::Positive;
945
sign = Botan::BigInt::Negative;
947
if(sign == Botan::BigInt::Negative)
948
negate_binary(a.data(), a.size());
950
d->n = Botan::BigInt::decode((const Botan::byte *)a.data(), a.size(), Botan::BigInt::Binary);
954
QString BigInteger::toString() const
959
cs.resize(d->n.encoded_size(Botan::BigInt::Decimal));
960
Botan::BigInt::encode((Botan::byte *)cs.data(), d->n, Botan::BigInt::Decimal);
962
catch(std::exception &)
968
if(d->n.is_negative())
970
str += QString::fromLatin1(cs);
974
bool BigInteger::fromString(const QString &s)
978
QByteArray cs = s.toLatin1();
986
d->n = Botan::BigInt::decode((const Botan::byte *)cs.data() + (neg ? 1 : 0), cs.length() - (neg ? 1 : 0), Botan::BigInt::Decimal);
988
catch(std::exception &)
994
d->n.set_sign(Botan::BigInt::Negative);
996
d->n.set_sign(Botan::BigInt::Positive);