~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to cutestuff/util/cipher.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
 
 * cipher.cpp - Simple wrapper to 3DES,AES128/256 CBC ciphers
3
 
 * Copyright (C) 2003  Justin Karneges
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
 *
19
 
 */
20
 
 
21
 
#include"cipher.h"
22
 
 
23
 
#include<openssl/evp.h>
24
 
#include<openssl/rsa.h>
25
 
#include"bytestream.h"
26
 
#include"qrandom.h"
27
 
 
28
 
static bool lib_encryptArray(const EVP_CIPHER *type, const QByteArray &buf, const QByteArray &key, const QByteArray &iv, bool pad, QByteArray *out)
29
 
{
30
 
        QByteArray result(buf.size()+type->block_size);
31
 
        int len;
32
 
        EVP_CIPHER_CTX c;
33
 
 
34
 
        unsigned char *ivp = NULL;
35
 
        if(!iv.isEmpty())
36
 
                ivp = (unsigned char *)iv.data();
37
 
        EVP_CIPHER_CTX_init(&c);
38
 
        //EVP_CIPHER_CTX_set_padding(&c, pad ? 1: 0);
39
 
        if(!EVP_EncryptInit_ex(&c, type, NULL, (unsigned char *)key.data(), ivp))
40
 
                return false;
41
 
        if(!EVP_EncryptUpdate(&c, (unsigned char *)result.data(), &len, (unsigned char *)buf.data(), buf.size()))
42
 
                return false;
43
 
        result.resize(len);
44
 
        if(pad) {
45
 
                QByteArray last(type->block_size);
46
 
                if(!EVP_EncryptFinal_ex(&c, (unsigned char *)last.data(), &len))
47
 
                        return false;
48
 
                last.resize(len);
49
 
                ByteStream::appendArray(&result, last);
50
 
        }
51
 
 
52
 
        memset(&c, 0, sizeof(EVP_CIPHER_CTX));
53
 
        *out = result;
54
 
        return true;
55
 
}
56
 
 
57
 
static bool lib_decryptArray(const EVP_CIPHER *type, const QByteArray &buf, const QByteArray &key, const QByteArray &iv, bool pad, QByteArray *out)
58
 
{
59
 
        QByteArray result(buf.size()+type->block_size);
60
 
        int len;
61
 
        EVP_CIPHER_CTX c;
62
 
 
63
 
        unsigned char *ivp = NULL;
64
 
        if(!iv.isEmpty())
65
 
                ivp = (unsigned char *)iv.data();
66
 
        EVP_CIPHER_CTX_init(&c);
67
 
        //EVP_CIPHER_CTX_set_padding(&c, pad ? 1: 0);
68
 
        if(!EVP_DecryptInit_ex(&c, type, NULL, (unsigned char *)key.data(), ivp))
69
 
                return false;
70
 
        if(!pad) {
71
 
                if(!EVP_EncryptUpdate(&c, (unsigned char *)result.data(), &len, (unsigned char *)buf.data(), buf.size()))
72
 
                        return false;
73
 
        }
74
 
        else {
75
 
                if(!EVP_DecryptUpdate(&c, (unsigned char *)result.data(), &len, (unsigned char *)buf.data(), buf.size()))
76
 
                        return false;
77
 
        }
78
 
        result.resize(len);
79
 
        if(pad) {
80
 
                QByteArray last(type->block_size);
81
 
                if(!EVP_DecryptFinal_ex(&c, (unsigned char *)last.data(), &len))
82
 
                        return false;
83
 
                last.resize(len);
84
 
                ByteStream::appendArray(&result, last);
85
 
        }
86
 
 
87
 
        memset(&c, 0, sizeof(EVP_CIPHER_CTX));
88
 
        *out = result;
89
 
        return true;
90
 
}
91
 
 
92
 
static bool lib_generateKeyIV(const EVP_CIPHER *type, const QByteArray &data, const QByteArray &salt, QByteArray *key, QByteArray *iv)
93
 
{
94
 
        QByteArray k, i;
95
 
        unsigned char *kp = 0;
96
 
        unsigned char *ip = 0;
97
 
        if(key) {
98
 
                k.resize(type->key_len);
99
 
                kp = (unsigned char *)k.data();
100
 
        }
101
 
        if(iv) {
102
 
                i.resize(type->iv_len);
103
 
                ip = (unsigned char *)i.data();
104
 
        }
105
 
        if(!EVP_BytesToKey(type, EVP_sha1(), (unsigned char *)salt.data(), (unsigned char *)data.data(), data.size(), 1, kp, ip))
106
 
                return false;
107
 
        if(key)
108
 
                *key = k;
109
 
        if(iv)
110
 
                *iv = i;
111
 
        return true;
112
 
}
113
 
 
114
 
static const EVP_CIPHER * typeToCIPHER(Cipher::Type t)
115
 
{
116
 
        if(t == Cipher::TripleDES)
117
 
                return EVP_des_ede3_cbc();
118
 
        else if(t == Cipher::AES_128)
119
 
                return EVP_aes_128_cbc();
120
 
        else if(t == Cipher::AES_256)
121
 
                return EVP_aes_256_cbc();
122
 
        else
123
 
                return 0;
124
 
}
125
 
 
126
 
Cipher::Key Cipher::generateKey(Type t)
127
 
{
128
 
        Key k;
129
 
        const EVP_CIPHER *type = typeToCIPHER(t);
130
 
        if(!type)
131
 
                return k;
132
 
        QByteArray out;
133
 
        if(!lib_generateKeyIV(type, QRandom::randomArray(128), QRandom::randomArray(2), &out, 0))
134
 
                return k;
135
 
        k.setType(t);
136
 
        k.setData(out);
137
 
        return k;
138
 
}
139
 
 
140
 
QByteArray Cipher::generateIV(Type t)
141
 
{
142
 
        const EVP_CIPHER *type = typeToCIPHER(t);
143
 
        if(!type)
144
 
                return QByteArray();
145
 
        QByteArray out;
146
 
        if(!lib_generateKeyIV(type, QCString("Get this man an iv!"), QByteArray(), 0, &out))
147
 
                return QByteArray();
148
 
        return out;
149
 
}
150
 
 
151
 
int Cipher::ivSize(Type t)
152
 
{
153
 
        const EVP_CIPHER *type = typeToCIPHER(t);
154
 
        if(!type)
155
 
                return -1;
156
 
        return type->iv_len;
157
 
}
158
 
 
159
 
QByteArray Cipher::encrypt(const QByteArray &buf, const Key &key, const QByteArray &iv, bool pad, bool *ok)
160
 
{
161
 
        if(ok)
162
 
                *ok = false;
163
 
        const EVP_CIPHER *type = typeToCIPHER(key.type());
164
 
        if(!type)
165
 
                return QByteArray();
166
 
        QByteArray out;
167
 
        if(!lib_encryptArray(type, buf, key.data(), iv, pad, &out))
168
 
                return QByteArray();
169
 
 
170
 
        if(ok)
171
 
                *ok = true;
172
 
        return out;
173
 
}
174
 
 
175
 
QByteArray Cipher::decrypt(const QByteArray &buf, const Key &key, const QByteArray &iv, bool pad, bool *ok)
176
 
{
177
 
        if(ok)
178
 
                *ok = false;
179
 
        const EVP_CIPHER *type = typeToCIPHER(key.type());
180
 
        if(!type)
181
 
                return QByteArray();
182
 
        QByteArray out;
183
 
        if(!lib_decryptArray(type, buf, key.data(), iv, pad, &out))
184
 
                return QByteArray();
185
 
 
186
 
        if(ok)
187
 
                *ok = true;
188
 
        return out;
189
 
}
190
 
 
191
 
 
192
 
class RSAKey::Private
193
 
{
194
 
public:
195
 
        Private() {}
196
 
 
197
 
        RSA *rsa;
198
 
        int ref;
199
 
};
200
 
 
201
 
RSAKey::RSAKey()
202
 
{
203
 
        d = 0;
204
 
}
205
 
 
206
 
RSAKey::RSAKey(const RSAKey &from)
207
 
{
208
 
        d = 0;
209
 
        *this = from;
210
 
}
211
 
 
212
 
RSAKey & RSAKey::operator=(const RSAKey &from)
213
 
{
214
 
        free();
215
 
 
216
 
        if(from.d) {
217
 
                d = from.d;
218
 
                ++d->ref;
219
 
        }
220
 
 
221
 
        return *this;
222
 
}
223
 
 
224
 
RSAKey::~RSAKey()
225
 
{
226
 
        free();
227
 
}
228
 
 
229
 
bool RSAKey::isNull() const
230
 
{
231
 
        return d ? false: true;
232
 
}
233
 
 
234
 
void * RSAKey::data() const
235
 
{
236
 
        if(d)
237
 
                return (void *)d->rsa;
238
 
        else
239
 
                return 0;
240
 
}
241
 
 
242
 
void RSAKey::setData(void *p)
243
 
{
244
 
        free();
245
 
 
246
 
        if(p) {
247
 
                d = new Private;
248
 
                d->ref = 1;
249
 
                d->rsa = (RSA *)p;
250
 
        }
251
 
}
252
 
 
253
 
void RSAKey::free()
254
 
{
255
 
        if(!d)
256
 
                return;
257
 
 
258
 
        --d->ref;
259
 
        if(d->ref <= 0) {
260
 
                RSA_free(d->rsa);
261
 
                delete d;
262
 
        }
263
 
        d = 0;
264
 
}
265
 
 
266
 
RSAKey generateRSAKey()
267
 
{
268
 
        RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
269
 
        RSAKey key;
270
 
        if(rsa)
271
 
                key.setData(rsa);
272
 
        return key;
273
 
}
274
 
 
275
 
QByteArray encryptRSA(const QByteArray &buf, const RSAKey &key, bool *ok)
276
 
{
277
 
        if(ok)
278
 
                *ok = false;
279
 
 
280
 
        int size = RSA_size((RSA *)key.data());
281
 
        int flen = buf.size();
282
 
        if(flen >= size - 11)
283
 
                flen = size - 11;
284
 
        QByteArray result(size);
285
 
        unsigned char *from = (unsigned char *)buf.data();
286
 
        unsigned char *to = (unsigned char *)result.data();
287
 
        int r = RSA_public_encrypt(flen, from, to, (RSA *)key.data(), RSA_PKCS1_PADDING);
288
 
        if(r == -1)
289
 
                return QByteArray();
290
 
        result.resize(r);
291
 
 
292
 
        if(ok)
293
 
                *ok = true;
294
 
        return result;
295
 
}
296
 
 
297
 
QByteArray decryptRSA(const QByteArray &buf, const RSAKey &key, bool *ok)
298
 
{
299
 
        if(ok)
300
 
                *ok = false;
301
 
 
302
 
        int size = RSA_size((RSA *)key.data());
303
 
        int flen = buf.size();
304
 
        QByteArray result(size);
305
 
        unsigned char *from = (unsigned char *)buf.data();
306
 
        unsigned char *to = (unsigned char *)result.data();
307
 
        int r = RSA_private_decrypt(flen, from, to, (RSA *)key.data(), RSA_PKCS1_PADDING);
308
 
        if(r == -1)
309
 
                return QByteArray();
310
 
        result.resize(r);
311
 
 
312
 
        if(ok)
313
 
                *ok = true;
314
 
        return result;
315
 
}
316
 
 
317
 
QByteArray encryptRSA2(const QByteArray &buf, const RSAKey &key, bool *ok)
318
 
{
319
 
        if(ok)
320
 
                *ok = false;
321
 
 
322
 
        int size = RSA_size((RSA *)key.data());
323
 
        int flen = buf.size();
324
 
        if(flen >= size - 41)
325
 
                flen = size - 41;
326
 
        QByteArray result(size);
327
 
        unsigned char *from = (unsigned char *)buf.data();
328
 
        unsigned char *to = (unsigned char *)result.data();
329
 
        int r = RSA_public_encrypt(flen, from, to, (RSA *)key.data(), RSA_PKCS1_OAEP_PADDING);
330
 
        if(r == -1)
331
 
                return QByteArray();
332
 
        result.resize(r);
333
 
 
334
 
        if(ok)
335
 
                *ok = true;
336
 
        return result;
337
 
}
338
 
 
339
 
QByteArray decryptRSA2(const QByteArray &buf, const RSAKey &key, bool *ok)
340
 
{
341
 
        if(ok)
342
 
                *ok = false;
343
 
 
344
 
        int size = RSA_size((RSA *)key.data());
345
 
        int flen = buf.size();
346
 
        QByteArray result(size);
347
 
        unsigned char *from = (unsigned char *)buf.data();
348
 
        unsigned char *to = (unsigned char *)result.data();
349
 
        int r = RSA_private_decrypt(flen, from, to, (RSA *)key.data(), RSA_PKCS1_OAEP_PADDING);
350
 
        if(r == -1)
351
 
                return QByteArray();
352
 
        result.resize(r);
353
 
 
354
 
        if(ok)
355
 
                *ok = true;
356
 
        return result;
357
 
}