~ubuntu-branches/ubuntu/jaunty/psi/jaunty

« back to all changes in this revision

Viewing changes to third-party/qca/qca/src/qca_tools.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-04-14 18:57:30 UTC
  • mfrom: (2.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080414185730-528re3zp0m2hdlhi
Tags: 0.11-8
* added CONFIG -= link_prl to .pro files and removed dependencies
  which are made unnecessary by this change
* Fix segfault when closing last chat tab with qt4.4
  (This is from upstream svn, rev. 1101) (Closes: Bug#476122)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2003-2007  Justin Karneges <justin@affinix.com>
 
3
 * Copyright (C) 2004,2005  Brad Hards <bradh@frogmouth.net>
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 *
 
19
 */
 
20
 
 
21
#include "qca_tools.h"
 
22
 
 
23
#include "qdebug.h"
 
24
 
 
25
#ifdef Q_OS_UNIX
 
26
# include <stdlib.h>
 
27
# include <sys/mman.h>
 
28
#endif
 
29
#include "botantools/botantools.h"
 
30
 
 
31
namespace QCA {
 
32
 
 
33
static bool can_lock()
 
34
{
 
35
#ifdef Q_OS_UNIX
 
36
        bool ok = false;
 
37
#ifdef MLOCK_NOT_VOID_PTR
 
38
# define MLOCK_TYPE char *
 
39
# define MLOCK_TYPE_CAST (MLOCK_TYPE)
 
40
#else
 
41
# define MLOCK_TYPE void *
 
42
# define MLOCK_TYPE_CAST
 
43
#endif
 
44
 
 
45
        MLOCK_TYPE d = MLOCK_TYPE_CAST malloc(256);
 
46
        if(mlock(d, 256) == 0)
 
47
        {
 
48
                munlock(d, 256);
 
49
                ok = true;
 
50
        }
 
51
        free(d);
 
52
        return ok;
 
53
#else
 
54
        return true;
 
55
#endif
 
56
}
 
57
 
 
58
// Botan shouldn't throw any exceptions in our init/deinit.
 
59
 
 
60
static Botan::Allocator *alloc = 0;
 
61
 
 
62
void botan_throw_abort()
 
63
{
 
64
        fprintf(stderr, "QCA: Exception from internal Botan\n");
 
65
        abort();
 
66
}
 
67
 
 
68
bool botan_init(int prealloc, bool mmap)
 
69
{
 
70
        // 64k minimum
 
71
        if(prealloc < 64)
 
72
                prealloc = 64;
 
73
 
 
74
        bool secmem = false;
 
75
 
 
76
        try
 
77
        {
 
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);
 
83
 
 
84
                if(can_lock())
 
85
                {
 
86
                        Botan::global_state().set_default_allocator("locking");
 
87
                        secmem = true;
 
88
                }
 
89
                else if(mmap)
 
90
                {
 
91
                        Botan::global_state().set_default_allocator("mmap");
 
92
                        secmem = true;
 
93
                }
 
94
                alloc = Botan::Allocator::get(true);
 
95
        }
 
96
        catch(std::exception &)
 
97
        {
 
98
                fprintf(stderr, "QCA: Error initializing internal Botan\n");
 
99
                abort();
 
100
        }
 
101
 
 
102
        return secmem;
 
103
}
 
104
 
 
105
void botan_deinit()
 
106
{
 
107
        try
 
108
        {
 
109
                alloc = 0;
 
110
                Botan::set_global_state(0);
 
111
        }
 
112
        catch(std::exception &)
 
113
        {
 
114
                botan_throw_abort();
 
115
        }
 
116
}
 
117
 
 
118
void *botan_secure_alloc(int bytes)
 
119
{
 
120
        try
 
121
        {
 
122
                return alloc->allocate((Botan::u32bit)bytes);
 
123
        }
 
124
        catch(std::exception &)
 
125
        {
 
126
                botan_throw_abort();
 
127
        }
 
128
        return 0; // never get here
 
129
}
 
130
 
 
131
void botan_secure_free(void *p, int bytes)
 
132
{
 
133
        try
 
134
        {
 
135
                alloc->deallocate(p, (Botan::u32bit)bytes);
 
136
        }
 
137
        catch(std::exception &)
 
138
        {
 
139
                botan_throw_abort();
 
140
        }
 
141
}
 
142
 
 
143
} // end namespace QCA
 
144
 
 
145
void *qca_secure_alloc(int bytes)
 
146
{
 
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);
 
151
}
 
152
 
 
153
void qca_secure_free(void *p)
 
154
{
 
155
        // backtrack to read the size value
 
156
        char *c = (char *)p;
 
157
        c -= sizeof(int);
 
158
        int bytes = ((int *)c)[0];
 
159
        QCA::botan_secure_free(c, bytes);
 
160
}
 
161
 
 
162
void *qca_secure_realloc(void *p, int bytes)
 
163
{
 
164
        // if null, do a plain alloc (just like how realloc() works)
 
165
        if(!p)
 
166
                return qca_secure_alloc(bytes);
 
167
 
 
168
        // backtrack to read the size value
 
169
        char *c = (char *)p;
 
170
        c -= sizeof(int);
 
171
        int oldsize = ((int *)c)[0] - sizeof(int);
 
172
 
 
173
        // alloc the new chunk
 
174
        char *new_p = (char *)qca_secure_alloc(bytes);
 
175
        if(!new_p)
 
176
                return 0;
 
177
 
 
178
        // move over the memory from the original block
 
179
        memmove(new_p, p, qMin(oldsize, bytes));
 
180
 
 
181
        // free the original
 
182
        qca_secure_free(p);
 
183
 
 
184
        // done
 
185
        return new_p;
 
186
}
 
187
 
 
188
namespace QCA {
 
189
 
 
190
// secure or non-secure buffer, with trailing 0-byte.
 
191
// buffer size of 0 is okay (sbuf/qbuf will be 0).
 
192
struct alloc_info
 
193
{
 
194
        bool sec;
 
195
        char *data;
 
196
        int size;
 
197
 
 
198
        // internal
 
199
        Botan::SecureVector<Botan::byte> *sbuf;
 
200
        QByteArray *qbuf;
 
201
};
 
202
 
 
203
// note: these functions don't return error if memory allocation/resizing
 
204
//   fails..  maybe fix this someday?
 
205
 
 
206
// ai: uninitialized
 
207
// size: >= 0
 
208
// note: memory will be initially zero'd out
 
209
static bool ai_new(alloc_info *ai, int size, bool sec);
 
210
 
 
211
// ai: uninitialized
 
212
// from: initialized
 
213
static bool ai_copy(alloc_info *ai, const alloc_info *from);
 
214
 
 
215
// ai: initialized
 
216
// new_size: >= 0
 
217
static bool ai_resize(alloc_info *ai, int new_size);
 
218
 
 
219
// ai: initialized
 
220
static void ai_delete(alloc_info *ai);
 
221
 
 
222
bool ai_new(alloc_info *ai, int size, bool sec)
 
223
{
 
224
        if(size < 0)
 
225
                return false;
 
226
 
 
227
        ai->size = size;
 
228
        ai->sec = sec;
 
229
 
 
230
        if(size == 0)
 
231
        {
 
232
                ai->sbuf = 0;
 
233
                ai->qbuf = 0;
 
234
                ai->data = 0;
 
235
                return true;
 
236
        }
 
237
 
 
238
        if(sec)
 
239
        {
 
240
                try
 
241
                {
 
242
                        ai->sbuf = new Botan::SecureVector<Botan::byte>((Botan::u32bit)size + 1);
 
243
                }
 
244
                catch(std::exception &)
 
245
                {
 
246
                        botan_throw_abort();
 
247
                        return false; // never get here
 
248
                }
 
249
 
 
250
                (*(ai->sbuf))[size] = 0;
 
251
                ai->qbuf = 0;
 
252
                Botan::byte *bp = (Botan::byte *)(*(ai->sbuf));
 
253
                ai->data = (char *)bp;
 
254
        }
 
255
        else
 
256
        {
 
257
                ai->sbuf = 0;
 
258
                ai->qbuf = new QByteArray(size, 0);
 
259
                ai->data = ai->qbuf->data();
 
260
        }
 
261
 
 
262
        return true;
 
263
}
 
264
 
 
265
bool ai_copy(alloc_info *ai, const alloc_info *from)
 
266
{
 
267
        ai->size = from->size;
 
268
        ai->sec = from->sec;
 
269
 
 
270
        if(ai->size == 0)
 
271
        {
 
272
                ai->sbuf = 0;
 
273
                ai->qbuf = 0;
 
274
                ai->data = 0;
 
275
                return true;
 
276
        }
 
277
 
 
278
        if(ai->sec)
 
279
        {
 
280
                try
 
281
                {
 
282
                        ai->sbuf = new Botan::SecureVector<Botan::byte>(*(from->sbuf));
 
283
                }
 
284
                catch(std::exception &)
 
285
                {
 
286
                        botan_throw_abort();
 
287
                        return false; // never get here
 
288
                }
 
289
 
 
290
                ai->qbuf = 0;
 
291
                Botan::byte *bp = (Botan::byte *)(*(ai->sbuf));
 
292
                ai->data = (char *)bp;
 
293
        }
 
294
        else
 
295
        {
 
296
                ai->sbuf = 0;
 
297
                ai->qbuf = new QByteArray(*(from->qbuf));
 
298
                ai->data = ai->qbuf->data();
 
299
        }
 
300
 
 
301
        return true;
 
302
}
 
303
 
 
304
bool ai_resize(alloc_info *ai, int new_size)
 
305
{
 
306
        if(new_size < 0)
 
307
                return false;
 
308
 
 
309
        // new size is empty
 
310
        if(new_size == 0)
 
311
        {
 
312
                // we currently aren't empty
 
313
                if(ai->size > 0)
 
314
                {
 
315
                        if(ai->sec)
 
316
                        {
 
317
                                delete ai->sbuf;
 
318
                                ai->sbuf = 0;
 
319
                        }
 
320
                        else
 
321
                        {
 
322
                                delete ai->qbuf;
 
323
                                ai->qbuf = 0;
 
324
                        }
 
325
 
 
326
                        ai->size = 0;
 
327
                        ai->data = 0;
 
328
                }
 
329
 
 
330
                return true;
 
331
        }
 
332
 
 
333
        if(ai->sec)
 
334
        {
 
335
                Botan::SecureVector<Botan::byte> *new_buf;
 
336
                try
 
337
                {
 
338
                        new_buf = new Botan::SecureVector<Botan::byte>((Botan::u32bit)new_size + 1);
 
339
                }
 
340
                catch(std::exception &)
 
341
                {
 
342
                        botan_throw_abort();
 
343
                        return false; // never get here
 
344
                }
 
345
 
 
346
                Botan::byte *new_p = (Botan::byte *)(*new_buf);
 
347
                if(ai->size > 0)
 
348
                {
 
349
                        const Botan::byte *old_p = (const Botan::byte *)(*(ai->sbuf));
 
350
                        memcpy(new_p, old_p, qMin(new_size, ai->size));
 
351
                        delete ai->sbuf;
 
352
                }
 
353
                ai->sbuf = new_buf;
 
354
                ai->size = new_size;
 
355
                (*(ai->sbuf))[new_size] = 0;
 
356
                ai->data = (char *)new_p;
 
357
        }
 
358
        else
 
359
        {
 
360
                if(ai->size > 0)
 
361
                        ai->qbuf->resize(new_size);
 
362
                else
 
363
                        ai->qbuf = new QByteArray(new_size, 0);
 
364
 
 
365
                ai->size = new_size;
 
366
                ai->data = ai->qbuf->data();
 
367
        }
 
368
 
 
369
        return true;
 
370
}
 
371
 
 
372
void ai_delete(alloc_info *ai)
 
373
{
 
374
        if(ai->size > 0)
 
375
        {
 
376
                if(ai->sec)
 
377
                        delete ai->sbuf;
 
378
                else
 
379
                        delete ai->qbuf;
 
380
        }
 
381
}
 
382
 
 
383
//----------------------------------------------------------------------------
 
384
// MemoryRegion
 
385
//----------------------------------------------------------------------------
 
386
static char blank[] = "";
 
387
 
 
388
class MemoryRegion::Private : public QSharedData
 
389
{
 
390
public:
 
391
        alloc_info ai;
 
392
 
 
393
        Private(int size, bool sec)
 
394
        {
 
395
                ai_new(&ai, size, sec);
 
396
        }
 
397
 
 
398
        Private(const QByteArray &from, bool sec)
 
399
        {
 
400
                ai_new(&ai, from.size(), sec);
 
401
                memcpy(ai.data, from.data(), ai.size);
 
402
        }
 
403
 
 
404
        Private(const Private &from) : QSharedData(from)
 
405
        {
 
406
                ai_copy(&ai, &from.ai);
 
407
        }
 
408
 
 
409
        ~Private()
 
410
        {
 
411
                ai_delete(&ai);
 
412
        }
 
413
 
 
414
        bool resize(int new_size)
 
415
        {
 
416
                return ai_resize(&ai, new_size);
 
417
        }
 
418
 
 
419
        void setSecure(bool sec)
 
420
        {
 
421
                // if same mode, do nothing
 
422
                if(ai.sec == sec)
 
423
                        return;
 
424
 
 
425
                alloc_info other;
 
426
                ai_new(&other, ai.size, sec);
 
427
                memcpy(other.data, ai.data, ai.size);
 
428
                ai_delete(&ai);
 
429
                ai = other;
 
430
        }
 
431
};
 
432
 
 
433
MemoryRegion::MemoryRegion()
 
434
:_secure(false), d(0)
 
435
{
 
436
}
 
437
 
 
438
MemoryRegion::MemoryRegion(const char *str)
 
439
:_secure(false), d(new Private(QByteArray::fromRawData(str, strlen(str)), false))
 
440
{
 
441
}
 
442
 
 
443
MemoryRegion::MemoryRegion(const QByteArray &from)
 
444
:_secure(false), d(new Private(from, false))
 
445
{
 
446
}
 
447
 
 
448
MemoryRegion::MemoryRegion(const MemoryRegion &from)
 
449
:_secure(from._secure), d(from.d)
 
450
{
 
451
}
 
452
 
 
453
MemoryRegion::~MemoryRegion()
 
454
{
 
455
}
 
456
 
 
457
MemoryRegion & MemoryRegion::operator=(const MemoryRegion &from)
 
458
{
 
459
        _secure = from._secure;
 
460
        d = from.d;
 
461
        return *this;
 
462
}
 
463
 
 
464
MemoryRegion & MemoryRegion::operator=(const QByteArray &from)
 
465
{
 
466
        set(from, false);
 
467
        return *this;
 
468
}
 
469
 
 
470
bool MemoryRegion::isNull() const
 
471
{
 
472
        return (d ? false : true);
 
473
}
 
474
 
 
475
bool MemoryRegion::isSecure() const
 
476
{
 
477
        return _secure;
 
478
}
 
479
 
 
480
QByteArray MemoryRegion::toByteArray() const
 
481
{
 
482
        if(!d)
 
483
                return QByteArray();
 
484
 
 
485
        if(d->ai.sec)
 
486
        {
 
487
                QByteArray buf(d->ai.size, 0);
 
488
                memcpy(buf.data(), d->ai.data, d->ai.size);
 
489
                return buf;
 
490
        }
 
491
        else
 
492
        {
 
493
                if(d->ai.size > 0)
 
494
                        return *(d->ai.qbuf);
 
495
                else
 
496
                        return QByteArray((int)0, (char)0);
 
497
        }
 
498
}
 
499
 
 
500
MemoryRegion::MemoryRegion(bool secure)
 
501
:_secure(secure), d(0)
 
502
{
 
503
}
 
504
 
 
505
MemoryRegion::MemoryRegion(int size, bool secure)
 
506
:_secure(secure), d(new Private(size, secure))
 
507
{
 
508
}
 
509
 
 
510
MemoryRegion::MemoryRegion(const QByteArray &from, bool secure)
 
511
:_secure(secure), d(new Private(from, secure))
 
512
{
 
513
}
 
514
 
 
515
char *MemoryRegion::data()
 
516
{
 
517
        if(!d)
 
518
                return blank;
 
519
        return d->ai.data;
 
520
}
 
521
 
 
522
const char *MemoryRegion::data() const
 
523
{
 
524
        if(!d)
 
525
                return blank;
 
526
        return d->ai.data;
 
527
}
 
528
 
 
529
const char *MemoryRegion::constData() const
 
530
{
 
531
        if(!d)
 
532
                return blank;
 
533
        return d->ai.data;
 
534
}
 
535
 
 
536
char & MemoryRegion::at(int index)
 
537
{
 
538
        return *(d->ai.data + index);
 
539
}
 
540
 
 
541
const char & MemoryRegion::at(int index) const
 
542
{
 
543
        return *(d->ai.data + index);
 
544
}
 
545
 
 
546
int MemoryRegion::size() const
 
547
{
 
548
        if(!d)
 
549
                return 0;
 
550
        return d->ai.size;
 
551
}
 
552
 
 
553
bool MemoryRegion::isEmpty() const
 
554
{
 
555
        if(!d)
 
556
                return true;
 
557
        return (d->ai.size > 0 ? false : true);
 
558
}
 
559
 
 
560
bool MemoryRegion::resize(int size)
 
561
{
 
562
        if(!d)
 
563
        {
 
564
                d = new Private(size, _secure);
 
565
                return true;
 
566
        }
 
567
 
 
568
        if(d->ai.size == size)
 
569
                return true;
 
570
 
 
571
        return d->resize(size);
 
572
}
 
573
 
 
574
void MemoryRegion::set(const QByteArray &from, bool secure)
 
575
{
 
576
        _secure = secure;
 
577
 
 
578
        if(!from.isEmpty())
 
579
                d = new Private(from, secure);
 
580
        else
 
581
                d = new Private(0, secure);
 
582
}
 
583
 
 
584
void MemoryRegion::setSecure(bool secure)
 
585
{
 
586
        _secure = secure;
 
587
 
 
588
        if(!d)
 
589
        {
 
590
                d = new Private(0, secure);
 
591
                return;
 
592
        }
 
593
 
 
594
        d->setSecure(secure);
 
595
}
 
596
 
 
597
//----------------------------------------------------------------------------
 
598
// SecureArray
 
599
//----------------------------------------------------------------------------
 
600
SecureArray::SecureArray()
 
601
:MemoryRegion(true)
 
602
{
 
603
}
 
604
 
 
605
SecureArray::SecureArray(int size, char ch)
 
606
:MemoryRegion(size, true)
 
607
{
 
608
        // ai_new fills with zeros for us
 
609
        if(ch != 0)
 
610
                fill(ch, size);
 
611
}
 
612
 
 
613
SecureArray::SecureArray(const char *str)
 
614
:MemoryRegion(QByteArray::fromRawData(str, strlen(str)), true)
 
615
{
 
616
}
 
617
 
 
618
SecureArray::SecureArray(const QByteArray &a)
 
619
:MemoryRegion(a, true)
 
620
{
 
621
}
 
622
 
 
623
SecureArray::SecureArray(const MemoryRegion &a)
 
624
:MemoryRegion(a)
 
625
{
 
626
        setSecure(true);
 
627
}
 
628
 
 
629
SecureArray::SecureArray(const SecureArray &from)
 
630
:MemoryRegion(from)
 
631
{
 
632
}
 
633
 
 
634
SecureArray::~SecureArray()
 
635
{
 
636
}
 
637
 
 
638
SecureArray & SecureArray::operator=(const SecureArray &from)
 
639
{
 
640
        MemoryRegion::operator=(from);
 
641
        return *this;
 
642
}
 
643
 
 
644
SecureArray & SecureArray::operator=(const QByteArray &from)
 
645
{
 
646
        MemoryRegion::set(from, true);
 
647
        return *this;
 
648
}
 
649
 
 
650
void SecureArray::clear()
 
651
{
 
652
        MemoryRegion::resize(0);
 
653
}
 
654
 
 
655
bool SecureArray::resize(int size)
 
656
{
 
657
        return MemoryRegion::resize(size);
 
658
}
 
659
 
 
660
char & SecureArray::operator[](int index)
 
661
{
 
662
        return at(index);
 
663
}
 
664
 
 
665
const char & SecureArray::operator[](int index) const
 
666
{
 
667
        return at(index);
 
668
}
 
669
 
 
670
char & SecureArray::at(int index)
 
671
{
 
672
        return MemoryRegion::at(index);
 
673
}
 
674
 
 
675
const char & SecureArray::at(int index) const
 
676
{
 
677
        return MemoryRegion::at(index);
 
678
}
 
679
 
 
680
char *SecureArray::data()
 
681
{
 
682
        return MemoryRegion::data();
 
683
}
 
684
 
 
685
const char *SecureArray::data() const
 
686
{
 
687
        return MemoryRegion::data();
 
688
}
 
689
 
 
690
const char *SecureArray::constData() const
 
691
{
 
692
        return MemoryRegion::constData();
 
693
}
 
694
 
 
695
int SecureArray::size() const
 
696
{
 
697
        return MemoryRegion::size();
 
698
}
 
699
 
 
700
bool SecureArray::isEmpty() const
 
701
{
 
702
        return MemoryRegion::isEmpty();
 
703
}
 
704
 
 
705
QByteArray SecureArray::toByteArray() const
 
706
{
 
707
        return MemoryRegion::toByteArray();
 
708
}
 
709
 
 
710
SecureArray & SecureArray::append(const SecureArray &a)
 
711
{
 
712
        int oldsize = size();
 
713
        resize(oldsize + a.size());
 
714
        memcpy(data() + oldsize, a.data(), a.size());
 
715
        return *this;
 
716
}
 
717
 
 
718
bool SecureArray::operator==(const MemoryRegion &other) const
 
719
{
 
720
        if(this == &other)
 
721
                return true;
 
722
        if(size() == other.size() && memcmp(data(), other.data(), size()) == 0)
 
723
                return true;
 
724
        return false;
 
725
}
 
726
 
 
727
SecureArray & SecureArray::operator+=(const SecureArray &a)
 
728
{
 
729
        return append(a);
 
730
}
 
731
 
 
732
void SecureArray::fill(char fillChar, int fillToPosition)
 
733
{
 
734
        int len = (fillToPosition == -1) ? size() : qMin(fillToPosition, size());
 
735
        if(len > 0)
 
736
                memset(data(), (int)fillChar, len);
 
737
}
 
738
 
 
739
void SecureArray::set(const SecureArray &from)
 
740
{
 
741
        *this = from;
 
742
}
 
743
 
 
744
void SecureArray::set(const QByteArray &from)
 
745
{
 
746
        *this = from;
 
747
}
 
748
 
 
749
const SecureArray operator+(const SecureArray &a, const SecureArray &b)
 
750
{
 
751
        SecureArray c = a;
 
752
        return c.append(b);
 
753
}
 
754
 
 
755
//----------------------------------------------------------------------------
 
756
// BigInteger
 
757
//----------------------------------------------------------------------------
 
758
static void negate_binary(char *a, int size)
 
759
{
 
760
        // negate = two's compliment + 1
 
761
        bool done = false;
 
762
        for(int n = size - 1; n >= 0; --n)
 
763
        {
 
764
                a[n] = ~a[n];
 
765
                if(!done)
 
766
                {
 
767
                        if((unsigned char)a[n] < 0xff)
 
768
                        {
 
769
                                ++a[n];
 
770
                                done = true;
 
771
                        }
 
772
                        else
 
773
                                a[n] = 0;
 
774
                }
 
775
        }
 
776
}
 
777
 
 
778
class BigInteger::Private : public QSharedData
 
779
{
 
780
public:
 
781
        Botan::BigInt n;
 
782
};
 
783
 
 
784
BigInteger::BigInteger()
 
785
{
 
786
        d = new Private;
 
787
}
 
788
 
 
789
BigInteger::BigInteger(int i)
 
790
{
 
791
        d = new Private;
 
792
        if(i < 0)
 
793
        {
 
794
                d->n = Botan::BigInt(i * (-1));
 
795
                d->n.set_sign(Botan::BigInt::Negative);
 
796
        }
 
797
        else
 
798
        {
 
799
                d->n = Botan::BigInt(i);
 
800
                d->n.set_sign(Botan::BigInt::Positive);
 
801
        }
 
802
}
 
803
 
 
804
BigInteger::BigInteger(const char *c)
 
805
{
 
806
        d = new Private;
 
807
        fromString(QString(c));
 
808
}
 
809
 
 
810
BigInteger::BigInteger(const QString &s)
 
811
{
 
812
        d = new Private;
 
813
        fromString(s);
 
814
}
 
815
 
 
816
BigInteger::BigInteger(const SecureArray &a)
 
817
{
 
818
        d = new Private;
 
819
        fromArray(a);
 
820
}
 
821
 
 
822
BigInteger::BigInteger(const BigInteger &from)
 
823
{
 
824
        *this = from;
 
825
}
 
826
 
 
827
BigInteger::~BigInteger()
 
828
{
 
829
}
 
830
 
 
831
BigInteger & BigInteger::operator=(const BigInteger &from)
 
832
{
 
833
        d = from.d;
 
834
        return *this;
 
835
}
 
836
 
 
837
BigInteger & BigInteger::operator+=(const BigInteger &i)
 
838
{
 
839
        d->n += i.d->n;
 
840
        return *this;
 
841
}
 
842
 
 
843
BigInteger & BigInteger::operator-=(const BigInteger &i)
 
844
{
 
845
        d->n -= i.d->n;
 
846
        return *this;
 
847
}
 
848
 
 
849
BigInteger & BigInteger::operator*=(const BigInteger &i)
 
850
{
 
851
        d->n *= i.d->n;
 
852
        return *this;
 
853
}
 
854
 
 
855
BigInteger & BigInteger::operator/=(const BigInteger &i)
 
856
{
 
857
        try
 
858
        {
 
859
                d->n /= i.d->n;
 
860
        }
 
861
        catch(std::exception &)
 
862
        {
 
863
                fprintf(stderr, "QCA: Botan integer division error\n");
 
864
                abort();
 
865
        }
 
866
        return *this;
 
867
}
 
868
 
 
869
BigInteger & BigInteger::operator%=(const BigInteger &i)
 
870
{
 
871
        try
 
872
        {
 
873
                d->n %= i.d->n;
 
874
        }
 
875
        catch(std::exception &)
 
876
        {
 
877
                fprintf(stderr, "QCA: Botan integer division error\n");
 
878
                abort();
 
879
        }
 
880
        return *this;
 
881
}
 
882
 
 
883
BigInteger & BigInteger::operator=(const QString &s)
 
884
{
 
885
        fromString(s);
 
886
        return *this;
 
887
}
 
888
 
 
889
int BigInteger::compare(const BigInteger &n) const
 
890
{
 
891
        return ( (d->n).cmp( n.d->n, true) );
 
892
}
 
893
 
 
894
QTextStream &operator<<(QTextStream &stream, const BigInteger& b)
 
895
{
 
896
        stream << b.toString();
 
897
        return stream;
 
898
}
 
899
 
 
900
SecureArray BigInteger::toArray() const
 
901
{
 
902
        int size = d->n.encoded_size(Botan::BigInt::Binary);
 
903
 
 
904
        // return at least 8 bits
 
905
        if(size == 0)
 
906
        {
 
907
                SecureArray a(1);
 
908
                a[0] = 0;
 
909
                return a;
 
910
        }
 
911
 
 
912
        int offset = 0;
 
913
        SecureArray a;
 
914
 
 
915
        // make room for a sign bit if needed
 
916
        if(d->n.get_bit((size * 8) - 1))
 
917
        {
 
918
                ++size;
 
919
                a.resize(size);
 
920
                a[0] = 0;
 
921
                ++offset;
 
922
        }
 
923
        else
 
924
                a.resize(size);
 
925
 
 
926
        Botan::BigInt::encode((Botan::byte *)a.data() + offset, d->n, Botan::BigInt::Binary);
 
927
 
 
928
        if(d->n.is_negative())
 
929
                negate_binary(a.data(), a.size());
 
930
 
 
931
        return a;
 
932
}
 
933
 
 
934
void BigInteger::fromArray(const SecureArray &_a)
 
935
{
 
936
        if(_a.isEmpty())
 
937
        {
 
938
                d->n = Botan::BigInt(0);
 
939
                return;
 
940
        }
 
941
        SecureArray a = _a;
 
942
 
 
943
        Botan::BigInt::Sign sign = Botan::BigInt::Positive;
 
944
        if(a[0] & 0x80)
 
945
                sign = Botan::BigInt::Negative;
 
946
 
 
947
        if(sign == Botan::BigInt::Negative)
 
948
                negate_binary(a.data(), a.size());
 
949
 
 
950
        d->n = Botan::BigInt::decode((const Botan::byte *)a.data(), a.size(), Botan::BigInt::Binary);
 
951
        d->n.set_sign(sign);
 
952
}
 
953
 
 
954
QString BigInteger::toString() const
 
955
{
 
956
        QByteArray cs;
 
957
        try
 
958
        {
 
959
                cs.resize(d->n.encoded_size(Botan::BigInt::Decimal));
 
960
                Botan::BigInt::encode((Botan::byte *)cs.data(), d->n, Botan::BigInt::Decimal);
 
961
        }
 
962
        catch(std::exception &)
 
963
        {
 
964
                return QString();
 
965
        }
 
966
 
 
967
        QString str;
 
968
        if(d->n.is_negative())
 
969
                str += '-';
 
970
        str += QString::fromLatin1(cs);
 
971
        return str;
 
972
}
 
973
 
 
974
bool BigInteger::fromString(const QString &s)
 
975
{
 
976
        if(s.isEmpty())
 
977
                return false;
 
978
        QByteArray cs = s.toLatin1();
 
979
 
 
980
        bool neg = false;
 
981
        if(s[0] == '-')
 
982
                neg = true;
 
983
 
 
984
        try
 
985
        {
 
986
                d->n = Botan::BigInt::decode((const Botan::byte *)cs.data() + (neg ? 1 : 0), cs.length() - (neg ? 1 : 0), Botan::BigInt::Decimal);
 
987
        }
 
988
        catch(std::exception &)
 
989
        {
 
990
                return false;
 
991
        }
 
992
 
 
993
        if(neg)
 
994
                d->n.set_sign(Botan::BigInt::Negative);
 
995
        else
 
996
                d->n.set_sign(Botan::BigInt::Positive);
 
997
        return true;
 
998
}
 
999
 
 
1000
}