summaryrefslogtreecommitdiffabout
authorulf69 <ulf69>2004-10-16 01:06:16 (UTC)
committer ulf69 <ulf69>2004-10-16 01:06:16 (UTC)
commit1a7713f557e9ac6b15793808ccf665d6de782035 (patch) (unidiff)
tree5e44005fa1fe707f680c7250df0367097d003f8a
parenta6b0eba5c1aac3ba170b99c2b773fcabe10d8a40 (diff)
downloadkdepimpi-1a7713f557e9ac6b15793808ccf665d6de782035.zip
kdepimpi-1a7713f557e9ac6b15793808ccf665d6de782035.tar.gz
kdepimpi-1a7713f557e9ac6b15793808ccf665d6de782035.tar.bz2
*** empty log message ***
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/pwmanager/libgcryptif.cpp430
-rw-r--r--pwmanager/pwmanager/libgcryptif.h13
2 files changed, 21 insertions, 422 deletions
diff --git a/pwmanager/pwmanager/libgcryptif.cpp b/pwmanager/pwmanager/libgcryptif.cpp
index 6f3a994..8175510 100644
--- a/pwmanager/pwmanager/libgcryptif.cpp
+++ b/pwmanager/pwmanager/libgcryptif.cpp
@@ -1,570 +1,164 @@
1/*************************************************************************** 1/***************************************************************************
2 * * 2 * *
3 * copyright (C) 2004 by Michael Buesch * 3 * copyright (C) 2004 by Michael Buesch *
4 * email: mbuesch@freenet.de * 4 * email: mbuesch@freenet.de *
5 * * 5 * *
6 * hashPassphrase() is derived from GnuPG and is * 6 * hashPassphrase() is derived from GnuPG and is *
7 * Copyright (C) 1998, 1999, 2000, 2001, 2003 * 7 * Copyright (C) 1998, 1999, 2000, 2001, 2003 *
8 * Free Software Foundation, Inc. * 8 * Free Software Foundation, Inc. *
9 * * 9 * *
10 * This program is free software; you can redistribute it and/or modify * 10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License version 2 * 11 * it under the terms of the GNU General Public License version 2 *
12 * as published by the Free Software Foundation. * 12 * as published by the Free Software Foundation. *
13 * * 13 * *
14 ***************************************************************************/ 14 ***************************************************************************/
15 15
16/***************************************************************************
17 * copyright (C) 2004 by Ulf Schenk
18 * This file is originaly based on version 2.0 of pwmanager
19 * and was modified to run on embedded devices that run microkde
20 *
21 * $Id$
22 **************************************************************************/
23
16#include "libgcryptif.h" 24#include "libgcryptif.h"
17 25
18#ifdef CONFIG_PWMANAGER_GCRY 26#ifdef CONFIG_PWMANAGER_GCRY
19 27
20#include "pwmdoc.h" 28#include "pwmdoc.h"
21#include "randomizer.h" 29#include "randomizer.h"
22 30
23#include <gcrypt.h> 31#include <gcrypt.h>
24 32
25PwMerror LibGCryptIf::encrypt(unsigned char **outBuf, 33#ifdef PWM_EMBEDDED
26 size_t *outBufLen, 34#include <pwmprefs.h>
27 unsigned char *inBuf, 35#endif
28 size_t inBufLen,
29 const unsigned char *key,
30 size_t keylen,
31 char _algo)
32{
33 PwMerror ret = e_success;
34 gcry_error_t err;
35 gcry_cipher_hd_t handle;
36 size_t blklen;
37 size_t unpaddedLen = inBufLen;
38 size_t cipherKeylen;
39 unsigned char *hashedKey;
40 unsigned char salt[STRING2KEY_SALTLEN];
41 int algo = mapCipherId(_algo);
42
43 if (!inBufLen || !keylen)
44 return e_invalidArg;
45
46 // test if algo is ready for encryption
47 err = gcry_cipher_algo_info(algo,
48 GCRYCTL_TEST_ALGO,
49 0, 0);
50 if (err != GPG_ERR_NO_ERROR) {
51 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_TEST_ALGO failed: ")
52 + gcry_strerror(err));
53 ret = e_cryptNotImpl;
54 goto out;
55 }
56 // get the algo block length
57 err = gcry_cipher_algo_info(algo,
58 GCRYCTL_GET_BLKLEN,
59 0,
60 &blklen);
61 if (err != GPG_ERR_NO_ERROR) {
62 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_BLKLEN failed: ")
63 + gcry_strerror(err));
64 ret = e_cryptNotImpl;
65 goto out;
66 }
67 /* double check if we have enough space.
68 * We have only 1024 extra bytes for padding and salt.
69 */
70 BUG_ON(blklen > 1024 - STRING2KEY_SALTLEN);
71 // get the algo key length
72 err = gcry_cipher_algo_info(algo,
73 GCRYCTL_GET_KEYLEN,
74 0,
75 &cipherKeylen);
76 if (err != GPG_ERR_NO_ERROR) {
77 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_KEYLEN failed: ")
78 + gcry_strerror(err));
79 ret = e_cryptNotImpl;
80 goto out;
81 }
82 // now open the algo and get a handle
83 err = gcry_cipher_open(&handle,
84 algo,
85 GCRY_CIPHER_MODE_CBC,
86 0);
87 if (err != GPG_ERR_NO_ERROR) {
88 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_open() failed: ")
89 + gcry_strerror(err));
90 ret = e_cryptNotImpl;
91 goto out;
92 }
93 // hash the "key" to a fixed size hash matching "cipherKeylen"
94 hashedKey = new unsigned char[cipherKeylen];
95 hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, true);
96 // so now set the hashed key
97 err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
98 if (err != GPG_ERR_NO_ERROR) {
99 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_setkey() failed: ")
100 + gcry_strerror(err));
101 ret = e_cryptNotImpl;
102 delete [] hashedKey;
103 goto out_close;
104 }
105 delete [] hashedKey;
106 /* allocate a buffer for the encrypted data.
107 * The size of the buffer is the inBuf length, but blklen
108 * aligned and plus the length of the salt, that is appended.
109 */
110 *outBufLen = getBufLen(unpaddedLen, blklen) + STRING2KEY_SALTLEN;
111 *outBuf = new unsigned char[*outBufLen];
112 padData(inBuf, unpaddedLen, blklen);
113 // encrypt the padded data
114 err = gcry_cipher_encrypt(handle,
115 *outBuf,
116 *outBufLen - STRING2KEY_SALTLEN,
117 inBuf,
118 *outBufLen - STRING2KEY_SALTLEN);
119 if (err != GPG_ERR_NO_ERROR) {
120 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
121 + gcry_strerror(err));
122 ret = e_cryptNotImpl;
123 goto out_delete;
124 }
125 // append the salt to the encrypted data
126 memcpy(*outBuf + *outBufLen - STRING2KEY_SALTLEN, salt, STRING2KEY_SALTLEN);
127 goto out_close;
128out_delete:
129 delete [] *outBuf;
130out_close:
131 gcry_cipher_close(handle);
132out:
133 return ret;
134}
135
136PwMerror LibGCryptIf::decrypt(unsigned char **outBuf,
137 size_t *outBufLen,
138 const unsigned char *inBuf,
139 size_t inBufLen,
140 const unsigned char *key,
141 size_t keylen,
142 char _algo)
143{
144 PwMerror ret = e_success;
145 gcry_error_t err;
146 gcry_cipher_hd_t handle;
147 size_t cipherKeylen;
148 unsigned char *hashedKey;
149 unsigned char salt[STRING2KEY_SALTLEN];
150 int algo = mapCipherId(_algo);
151
152 if (!inBufLen || !keylen)
153 return e_invalidArg;
154
155 // test if algo is ready for encryption
156 err = gcry_cipher_algo_info(algo,
157 GCRYCTL_TEST_ALGO,
158 0, 0);
159 if (err != GPG_ERR_NO_ERROR) {
160 printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_TEST_ALGO failed: ")
161 + gcry_strerror(err));
162 ret = e_cryptNotImpl;
163 goto out;
164 }
165 // get algo key length
166 err = gcry_cipher_algo_info(algo,
167 GCRYCTL_GET_KEYLEN,
168 0,
169 &cipherKeylen);
170 if (err != GPG_ERR_NO_ERROR) {
171 printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_GET_KEYLEN failed: ")
172 + gcry_strerror(err));
173 ret = e_cryptNotImpl;
174 goto out;
175 }
176 // extract the salt of the encrypted data buffer
177 memcpy(salt, inBuf + inBufLen - STRING2KEY_SALTLEN, STRING2KEY_SALTLEN);
178 // open the algo and get a handle
179 err = gcry_cipher_open(&handle,
180 algo,
181 GCRY_CIPHER_MODE_CBC,
182 0);
183 if (err != GPG_ERR_NO_ERROR) {
184 printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_open() failed: ")
185 + gcry_strerror(err));
186 ret = e_cryptNotImpl;
187 goto out;
188 }
189 // hash the "key" to a fixed size hash matching "cipherKeylen"
190 hashedKey = new unsigned char[cipherKeylen];
191 hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, false);
192 // so now set the hashed key
193 err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
194 if (err != GPG_ERR_NO_ERROR) {
195 printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_setkey() failed: ")
196 + gcry_strerror(err));
197 ret = e_cryptNotImpl;
198 delete [] hashedKey;
199 goto out_close;
200 }
201 delete [] hashedKey;
202 *outBufLen = inBufLen - STRING2KEY_SALTLEN;
203 *outBuf = new unsigned char[*outBufLen];
204 // decrypt the data
205 err = gcry_cipher_decrypt(handle,
206 *outBuf,
207 *outBufLen,
208 inBuf,
209 *outBufLen);
210 if (err != GPG_ERR_NO_ERROR) {
211 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
212 + gcry_strerror(err));
213 ret = e_cryptNotImpl;
214 goto out_delete;
215 }
216 // remove all random padding
217 unpadData(*outBuf, outBufLen);
218 goto out_close;
219out_delete:
220 delete [] *outBuf;
221out_close:
222 gcry_cipher_close(handle);
223out:
224 return ret;
225}
226
227PwMerror LibGCryptIf::hash(unsigned char **outBuf,
228 size_t *outBufLen,
229 const unsigned char *inBuf,
230 size_t inBufLen,
231 char _algo)
232{
233 PwMerror ret = e_success;
234 unsigned int hashLen;
235 int algo = mapHashId(_algo);
236
237 hashLen = gcry_md_get_algo_dlen(algo);
238 *outBufLen = hashLen;
239 *outBuf = new unsigned char[*outBufLen];
240 gcry_md_hash_buffer(algo,
241 *outBuf,
242 inBuf,
243 inBufLen);
244 return ret;
245}
246 36
247unsigned int LibGCryptIf::hashLength(char _algo)
248{
249 unsigned int ret;
250 int algo = mapHashId(_algo);
251 ret = gcry_md_get_algo_dlen(algo);
252 return ret;
253}
254
255int LibGCryptIf::mapCipherId(char algo)
256{
257 switch (algo) {
258 case PWM_CRYPT_AES128:
259 return GCRY_CIPHER_AES;
260 case PWM_CRYPT_AES192:
261 return GCRY_CIPHER_AES192;
262 case PWM_CRYPT_AES256:
263 return GCRY_CIPHER_AES256;
264 case PWM_CRYPT_3DES:
265 return GCRY_CIPHER_3DES;
266 case PWM_CRYPT_TWOFISH:
267 return GCRY_CIPHER_TWOFISH;
268 case PWM_CRYPT_TWOFISH128:
269 return GCRY_CIPHER_TWOFISH128;
270 default:
271 BUG();
272 }
273 return GCRY_CIPHER_NONE;
274}
275
276int LibGCryptIf::mapHashId(char algo)
277{
278 switch (algo) {
279 case PWM_HASH_SHA1:
280 return GCRY_MD_SHA1;
281 case PWM_HASH_SHA256:
282 return GCRY_MD_SHA256;
283 case PWM_HASH_SHA384:
284 return GCRY_MD_SHA384;
285 case PWM_HASH_SHA512:
286 return GCRY_MD_SHA512;
287 case PWM_HASH_MD5:
288 return GCRY_MD_MD5;
289 case PWM_HASH_RMD160:
290 return GCRY_MD_RMD160;
291 case PWM_HASH_TIGER:
292 return GCRY_MD_TIGER;
293 default:
294 BUG();
295 }
296 return GCRY_MD_NONE;
297}
298
299bool LibGCryptIf::hashPassphrase(const unsigned char *pw,
300 size_t pwlen,
301 unsigned char *salt,
302 unsigned char *key,
303 size_t keylen,
304 bool create)
305{
306 DEK dek;
307 STRING2KEY s2k;
308 bool ret;
309
310 dek.keylen = keylen;
311 s2k.mode = 1;
312 s2k.hash_algo = mapHashId(conf()->confGlobHashAlgo());
313 s2k.count = 0;
314 if (!create)
315 memcpy(s2k.salt, salt, STRING2KEY_SALTLEN);
316 ret = doHashPassphrase(&dek,
317 pw,
318 pwlen,
319 &s2k,
320 create);
321 if (!ret)
322 goto out;
323 memcpy(key, dek.key, dek.keylen);
324 if (create)
325 memcpy(salt, s2k.salt, STRING2KEY_SALTLEN);
326out:
327 return ret;
328}
329
330
331bool LibGCryptIf::doHashPassphrase(DEK *dek,
332 const unsigned char *pw,
333 size_t pwlen,
334 STRING2KEY *s2k,
335 bool create)
336{
337 // This function is derived from GnuPG-1.2.5-rc2
338 gcry_md_hd_t md;
339 gcry_error_t err;
340 bool ret = true;
341 size_t pass, i;
342 size_t used = 0;
343
344 PWM_ASSERT(s2k->hash_algo);
345 BUG_ON(!(dek->keylen > 0 && dek->keylen <= array_size(dek->key)));
346
347 err = gcry_md_open(&md, s2k->hash_algo, 0);
348 if (err != GPG_ERR_NO_ERROR) {
349 ret = false;
350 goto out;
351 }
352 for (pass = 0; used < dek->keylen; pass++) {
353 if (pass) {
354 gcry_md_reset(md);
355 for (i = 0; i < pass; i++) // preset the hash context
356 gcry_md_putc(md, 0);
357 }
358 if (s2k->mode == 1 || s2k->mode == 3) {
359 size_t len2 = pwlen + 8;
360 size_t count = len2;
361
362 if (create && !pass) {
363 Randomizer *rnd = Randomizer::obj();
364 const unsigned int salt_len = 8;
365 string rndBuf(rnd->genRndBuf(salt_len));
366 memcpy(s2k->salt, rndBuf.c_str(), salt_len);
367 if (s2k->mode == 3)
368 s2k->count = 96; // 65536 iterations
369 }
370 if (s2k->mode == 3) {
371 count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
372 if (count < len2)
373 count = len2;
374 }
375 // a little bit complicated because we need a ulong for count
376 while (count > len2) { // maybe iterated+salted
377 gcry_md_write(md, s2k->salt, 8);
378 gcry_md_write(md, pw, pwlen);
379 count -= len2;
380 }
381 if (count < 8) {
382 gcry_md_write(md, s2k->salt, count);
383 } else {
384 gcry_md_write(md, s2k->salt, 8);
385 count -= 8;
386 gcry_md_write(md, pw, count);
387 }
388 } else
389 gcry_md_write(md, pw, pwlen);
390 gcry_md_final(md);
391 i = gcry_md_get_algo_dlen(s2k->hash_algo);
392 if (i > dek->keylen - used)
393 i = dek->keylen - used;
394 memcpy(dek->key+used, gcry_md_read(md, s2k->hash_algo), i);
395 used += i;
396 }
397 gcry_md_close(md);
398out:
399 return ret;
400}
401
402void LibGCryptIf::padData(unsigned char *buf,
403 size_t bufLen,
404 size_t boundary)
405{
406 size_t numPadBytes = boundary - ((bufLen + 1) % boundary);
407 buf[bufLen] = static_cast<char>(0x01);
408 size_t i = 0;
409 Randomizer *rnd = Randomizer::obj();
410 char c;
411 unsigned char *b;
412 while (i < numPadBytes) {
413 c = rnd->genRndChar();
414 if (c == static_cast<char>(0x01))
415 continue;
416 b = buf + bufLen + 1 + i;
417 *b = c;
418 ++i;
419 }
420}
421
422void LibGCryptIf::unpadData(const unsigned char *buf,
423 size_t *bufLen)
424{
425 size_t pos;
426 BUG_ON(*bufLen % 8);
427 pos = *bufLen - 1;
428 while (buf[pos] != static_cast<char>(0x01)) {
429 BUG_ON(!pos);
430 --pos;
431 }
432 *bufLen = pos;
433}
434
435#endif // CONFIG_PWMANAGER_GCRY
436
437#ifdef CONFIG_PWMANAGER_CRYPTO
438
439#include "pwmdoc.h"
440#include "randomizer.h"
441
442#include <openssl/crypto.h>
443 37
444PwMerror LibGCryptIf::encrypt(unsigned char **outBuf, 38PwMerror LibGCryptIf::encrypt(unsigned char **outBuf,
445 size_t *outBufLen, 39 size_t *outBufLen,
446 unsigned char *inBuf, 40 unsigned char *inBuf,
447 size_t inBufLen, 41 size_t inBufLen,
448 const unsigned char *key, 42 const unsigned char *key,
449 size_t keylen, 43 size_t keylen,
450 char _algo) 44 char _algo)
451{ 45{
452 PwMerror ret = e_success; 46 PwMerror ret = e_success;
453 gcry_error_t err; 47 gcry_error_t err;
454 gcry_cipher_hd_t handle; 48 gcry_cipher_hd_t handle;
455 size_t blklen; 49 size_t blklen;
456 size_t unpaddedLen = inBufLen; 50 size_t unpaddedLen = inBufLen;
457 size_t cipherKeylen; 51 size_t cipherKeylen;
458 unsigned char *hashedKey; 52 unsigned char *hashedKey;
459 unsigned char salt[STRING2KEY_SALTLEN]; 53 unsigned char salt[STRING2KEY_SALTLEN];
460 int algo = mapCipherId(_algo); 54 int algo = mapCipherId(_algo);
461 55
462 if (!inBufLen || !keylen) 56 if (!inBufLen || !keylen)
463 return e_invalidArg; 57 return e_invalidArg;
464 58
465 // test if algo is ready for encryption 59 // test if algo is ready for encryption
466 err = gcry_cipher_algo_info(algo, 60 err = gcry_cipher_algo_info(algo,
467 GCRYCTL_TEST_ALGO, 61 GCRYCTL_TEST_ALGO,
468 0, 0); 62 0, 0);
469 if (err != GPG_ERR_NO_ERROR) { 63 if (err != GPG_ERR_NO_ERROR) {
470 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_TEST_ALGO failed: ") 64 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_TEST_ALGO failed: ")
471 + gcry_strerror(err)); 65 + gcry_strerror(err));
472 ret = e_cryptNotImpl; 66 ret = e_cryptNotImpl;
473 goto out; 67 goto out;
474 } 68 }
475 // get the algo block length 69 // get the algo block length
476 err = gcry_cipher_algo_info(algo, 70 err = gcry_cipher_algo_info(algo,
477 GCRYCTL_GET_BLKLEN, 71 GCRYCTL_GET_BLKLEN,
478 0, 72 0,
479 &blklen); 73 &blklen);
480 if (err != GPG_ERR_NO_ERROR) { 74 if (err != GPG_ERR_NO_ERROR) {
481 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_BLKLEN failed: ") 75 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_BLKLEN failed: ")
482 + gcry_strerror(err)); 76 + gcry_strerror(err));
483 ret = e_cryptNotImpl; 77 ret = e_cryptNotImpl;
484 goto out; 78 goto out;
485 } 79 }
486 /* double check if we have enough space. 80 /* double check if we have enough space.
487 * We have only 1024 extra bytes for padding and salt. 81 * We have only 1024 extra bytes for padding and salt.
488 */ 82 */
489 BUG_ON(blklen > 1024 - STRING2KEY_SALTLEN); 83 BUG_ON(blklen > 1024 - STRING2KEY_SALTLEN);
490 // get the algo key length 84 // get the algo key length
491 err = gcry_cipher_algo_info(algo, 85 err = gcry_cipher_algo_info(algo,
492 GCRYCTL_GET_KEYLEN, 86 GCRYCTL_GET_KEYLEN,
493 0, 87 0,
494 &cipherKeylen); 88 &cipherKeylen);
495 if (err != GPG_ERR_NO_ERROR) { 89 if (err != GPG_ERR_NO_ERROR) {
496 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_KEYLEN failed: ") 90 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_KEYLEN failed: ")
497 + gcry_strerror(err)); 91 + gcry_strerror(err));
498 ret = e_cryptNotImpl; 92 ret = e_cryptNotImpl;
499 goto out; 93 goto out;
500 } 94 }
501 // now open the algo and get a handle 95 // now open the algo and get a handle
502 err = gcry_cipher_open(&handle, 96 err = gcry_cipher_open(&handle,
503 algo, 97 algo,
504 GCRY_CIPHER_MODE_CBC, 98 GCRY_CIPHER_MODE_CBC,
505 0); 99 0);
506 if (err != GPG_ERR_NO_ERROR) { 100 if (err != GPG_ERR_NO_ERROR) {
507 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_open() failed: ") 101 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_open() failed: ")
508 + gcry_strerror(err)); 102 + gcry_strerror(err));
509 ret = e_cryptNotImpl; 103 ret = e_cryptNotImpl;
510 goto out; 104 goto out;
511 } 105 }
512 // hash the "key" to a fixed size hash matching "cipherKeylen" 106 // hash the "key" to a fixed size hash matching "cipherKeylen"
513 hashedKey = new unsigned char[cipherKeylen]; 107 hashedKey = new unsigned char[cipherKeylen];
514 hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, true); 108 hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, true);
515 // so now set the hashed key 109 // so now set the hashed key
516 err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen); 110 err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
517 if (err != GPG_ERR_NO_ERROR) { 111 if (err != GPG_ERR_NO_ERROR) {
518 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_setkey() failed: ") 112 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_setkey() failed: ")
519 + gcry_strerror(err)); 113 + gcry_strerror(err));
520 ret = e_cryptNotImpl; 114 ret = e_cryptNotImpl;
521 delete [] hashedKey; 115 delete [] hashedKey;
522 goto out_close; 116 goto out_close;
523 } 117 }
524 delete [] hashedKey; 118 delete [] hashedKey;
525 /* allocate a buffer for the encrypted data. 119 /* allocate a buffer for the encrypted data.
526 * The size of the buffer is the inBuf length, but blklen 120 * The size of the buffer is the inBuf length, but blklen
527 * aligned and plus the length of the salt, that is appended. 121 * aligned and plus the length of the salt, that is appended.
528 */ 122 */
529 *outBufLen = getBufLen(unpaddedLen, blklen) + STRING2KEY_SALTLEN; 123 *outBufLen = getBufLen(unpaddedLen, blklen) + STRING2KEY_SALTLEN;
530 *outBuf = new unsigned char[*outBufLen]; 124 *outBuf = new unsigned char[*outBufLen];
531 padData(inBuf, unpaddedLen, blklen); 125 padData(inBuf, unpaddedLen, blklen);
532 // encrypt the padded data 126 // encrypt the padded data
533 err = gcry_cipher_encrypt(handle, 127 err = gcry_cipher_encrypt(handle,
534 *outBuf, 128 *outBuf,
535 *outBufLen - STRING2KEY_SALTLEN, 129 *outBufLen - STRING2KEY_SALTLEN,
536 inBuf, 130 inBuf,
537 *outBufLen - STRING2KEY_SALTLEN); 131 *outBufLen - STRING2KEY_SALTLEN);
538 if (err != GPG_ERR_NO_ERROR) { 132 if (err != GPG_ERR_NO_ERROR) {
539 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ") 133 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
540 + gcry_strerror(err)); 134 + gcry_strerror(err));
541 ret = e_cryptNotImpl; 135 ret = e_cryptNotImpl;
542 goto out_delete; 136 goto out_delete;
543 } 137 }
544 // append the salt to the encrypted data 138 // append the salt to the encrypted data
545 memcpy(*outBuf + *outBufLen - STRING2KEY_SALTLEN, salt, STRING2KEY_SALTLEN); 139 memcpy(*outBuf + *outBufLen - STRING2KEY_SALTLEN, salt, STRING2KEY_SALTLEN);
546 goto out_close; 140 goto out_close;
547out_delete: 141out_delete:
548 delete [] *outBuf; 142 delete [] *outBuf;
549out_close: 143out_close:
550 gcry_cipher_close(handle); 144 gcry_cipher_close(handle);
551out: 145out:
552 return ret; 146 return ret;
553} 147}
554 148
555PwMerror LibGCryptIf::decrypt(unsigned char **outBuf, 149PwMerror LibGCryptIf::decrypt(unsigned char **outBuf,
556 size_t *outBufLen, 150 size_t *outBufLen,
557 const unsigned char *inBuf, 151 const unsigned char *inBuf,
558 size_t inBufLen, 152 size_t inBufLen,
559 const unsigned char *key, 153 const unsigned char *key,
560 size_t keylen, 154 size_t keylen,
561 char _algo) 155 char _algo)
562{ 156{
563 PwMerror ret = e_success; 157 PwMerror ret = e_success;
564 gcry_error_t err; 158 gcry_error_t err;
565 gcry_cipher_hd_t handle; 159 gcry_cipher_hd_t handle;
566 size_t cipherKeylen; 160 size_t cipherKeylen;
567 unsigned char *hashedKey; 161 unsigned char *hashedKey;
568 unsigned char salt[STRING2KEY_SALTLEN]; 162 unsigned char salt[STRING2KEY_SALTLEN];
569 int algo = mapCipherId(_algo); 163 int algo = mapCipherId(_algo);
570 164
@@ -726,130 +320,130 @@ bool LibGCryptIf::hashPassphrase(const unsigned char *pw,
726 STRING2KEY s2k; 320 STRING2KEY s2k;
727 bool ret; 321 bool ret;
728 322
729 dek.keylen = keylen; 323 dek.keylen = keylen;
730 s2k.mode = 1; 324 s2k.mode = 1;
731 s2k.hash_algo = mapHashId(conf()->confGlobHashAlgo()); 325 s2k.hash_algo = mapHashId(conf()->confGlobHashAlgo());
732 s2k.count = 0; 326 s2k.count = 0;
733 if (!create) 327 if (!create)
734 memcpy(s2k.salt, salt, STRING2KEY_SALTLEN); 328 memcpy(s2k.salt, salt, STRING2KEY_SALTLEN);
735 ret = doHashPassphrase(&dek, 329 ret = doHashPassphrase(&dek,
736 pw, 330 pw,
737 pwlen, 331 pwlen,
738 &s2k, 332 &s2k,
739 create); 333 create);
740 if (!ret) 334 if (!ret)
741 goto out; 335 goto out;
742 memcpy(key, dek.key, dek.keylen); 336 memcpy(key, dek.key, dek.keylen);
743 if (create) 337 if (create)
744 memcpy(salt, s2k.salt, STRING2KEY_SALTLEN); 338 memcpy(salt, s2k.salt, STRING2KEY_SALTLEN);
745out: 339out:
746 return ret; 340 return ret;
747} 341}
748 342
749 343
750bool LibGCryptIf::doHashPassphrase(DEK *dek, 344bool LibGCryptIf::doHashPassphrase(DEK *dek,
751 const unsigned char *pw, 345 const unsigned char *pw,
752 size_t pwlen, 346 size_t pwlen,
753 STRING2KEY *s2k, 347 STRING2KEY *s2k,
754 bool create) 348 bool create)
755{ 349{
756 // This function is derived from GnuPG-1.2.5-rc2 350 // This function is derived from GnuPG-1.2.5-rc2
757 gcry_md_hd_t md; 351 gcry_md_hd_t md;
758 gcry_error_t err; 352 gcry_error_t err;
759 bool ret = true; 353 bool ret = true;
760 size_t pass, i; 354 size_t pass, i;
761 size_t used = 0; 355 size_t used = 0;
762 356
763 PWM_ASSERT(s2k->hash_algo); 357 PWM_ASSERT(s2k->hash_algo);
764 BUG_ON(!(dek->keylen > 0 && dek->keylen <= array_size(dek->key))); 358 BUG_ON(!(dek->keylen > 0 && dek->keylen <= array_size(dek->key)));
765 359
766 err = gcry_md_open(&md, s2k->hash_algo, 0); 360 err = gcry_md_open(&md, s2k->hash_algo, 0);
767 if (err != GPG_ERR_NO_ERROR) { 361 if (err != GPG_ERR_NO_ERROR) {
768 ret = false; 362 ret = false;
769 goto out; 363 goto out;
770 } 364 }
771 for (pass = 0; used < dek->keylen; pass++) { 365 for (pass = 0; used < dek->keylen; pass++) {
772 if (pass) { 366 if (pass) {
773 gcry_md_reset(md); 367 gcry_md_reset(md);
774 for (i = 0; i < pass; i++) // preset the hash context 368 for (i = 0; i < pass; i++) // preset the hash context
775 gcry_md_putc(md, 0); 369 gcry_md_putc(md, 0);
776 } 370 }
777 if (s2k->mode == 1 || s2k->mode == 3) { 371 if (s2k->mode == 1 || s2k->mode == 3) {
778 size_t len2 = pwlen + 8; 372 size_t len2 = pwlen + 8;
779 size_t count = len2; 373 size_t count = len2;
780 374
781 if (create && !pass) { 375 if (create && !pass) {
782 Randomizer *rnd = Randomizer::obj(); 376 Randomizer *rnd = Randomizer::obj();
783 const unsigned int salt_len = 8; 377 const unsigned int salt_len = 8;
784 string rndBuf(rnd->genRndBuf(salt_len)); 378 string rndBuf(rnd->genRndBuf(salt_len));
785 memcpy(s2k->salt, rndBuf.c_str(), salt_len); 379 memcpy(s2k->salt, rndBuf.c_str(), salt_len);
786 if (s2k->mode == 3) 380 if (s2k->mode == 3)
787 s2k->count = 96; // 65536 iterations 381 s2k->count = 96; // 65536 iterations
788 } 382 }
789 if (s2k->mode == 3) { 383 if (s2k->mode == 3) {
790 count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6); 384 count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
791 if (count < len2) 385 if (count < len2)
792 count = len2; 386 count = len2;
793 } 387 }
794 // a little bit complicated because we need a ulong for count 388 // a little bit complicated because we need a ulong for count
795 while (count > len2) { // maybe iterated+salted 389 while (count > len2) { // maybe iterated+salted
796 gcry_md_write(md, s2k->salt, 8); 390 gcry_md_write(md, s2k->salt, 8);
797 gcry_md_write(md, pw, pwlen); 391 gcry_md_write(md, pw, pwlen);
798 count -= len2; 392 count -= len2;
799 } 393 }
800 if (count < 8) { 394 if (count < 8) {
801 gcry_md_write(md, s2k->salt, count); 395 gcry_md_write(md, s2k->salt, count);
802 } else { 396 } else {
803 gcry_md_write(md, s2k->salt, 8); 397 gcry_md_write(md, s2k->salt, 8);
804 count -= 8; 398 count -= 8;
805 gcry_md_write(md, pw, count); 399 gcry_md_write(md, pw, count);
806 } 400 }
807 } else 401 } else
808 gcry_md_write(md, pw, pwlen); 402 gcry_md_write(md, pw, pwlen);
809 gcry_md_final(md); 403 gcry_md_final(md);
810 i = gcry_md_get_algo_dlen(s2k->hash_algo); 404 i = gcry_md_get_algo_dlen(s2k->hash_algo);
811 if (i > dek->keylen - used) 405 if (i > dek->keylen - used)
812 i = dek->keylen - used; 406 i = dek->keylen - used;
813 memcpy(dek->key+used, gcry_md_read(md, s2k->hash_algo), i); 407 memcpy(dek->key+used, gcry_md_read(md, s2k->hash_algo), i);
814 used += i; 408 used += i;
815 } 409 }
816 gcry_md_close(md); 410 gcry_md_close(md);
817out: 411out:
818 return ret; 412 return ret;
819} 413}
820 414
821void LibGCryptIf::padData(unsigned char *buf, 415void LibGCryptIf::padData(unsigned char *buf,
822 size_t bufLen, 416 size_t bufLen,
823 size_t boundary) 417 size_t boundary)
824{ 418{
825 size_t numPadBytes = boundary - ((bufLen + 1) % boundary); 419 size_t numPadBytes = boundary - ((bufLen + 1) % boundary);
826 buf[bufLen] = static_cast<char>(0x01); 420 buf[bufLen] = static_cast<char>(0x01);
827 size_t i = 0; 421 size_t i = 0;
828 Randomizer *rnd = Randomizer::obj(); 422 Randomizer *rnd = Randomizer::obj();
829 char c; 423 char c;
830 unsigned char *b; 424 unsigned char *b;
831 while (i < numPadBytes) { 425 while (i < numPadBytes) {
832 c = rnd->genRndChar(); 426 c = rnd->genRndChar();
833 if (c == static_cast<char>(0x01)) 427 if (c == static_cast<char>(0x01))
834 continue; 428 continue;
835 b = buf + bufLen + 1 + i; 429 b = buf + bufLen + 1 + i;
836 *b = c; 430 *b = c;
837 ++i; 431 ++i;
838 } 432 }
839} 433}
840 434
841void LibGCryptIf::unpadData(const unsigned char *buf, 435void LibGCryptIf::unpadData(const unsigned char *buf,
842 size_t *bufLen) 436 size_t *bufLen)
843{ 437{
844 size_t pos; 438 size_t pos;
845 BUG_ON(*bufLen % 8); 439 BUG_ON(*bufLen % 8);
846 pos = *bufLen - 1; 440 pos = *bufLen - 1;
847 while (buf[pos] != static_cast<char>(0x01)) { 441 while (buf[pos] != static_cast<char>(0x01)) {
848 BUG_ON(!pos); 442 BUG_ON(!pos);
849 --pos; 443 --pos;
850 } 444 }
851 *bufLen = pos; 445 *bufLen = pos;
852} 446}
853 447
854#endif // CONFIG_PWMANAGER_CRYPTO 448#endif // CONFIG_PWMANAGER_GCRY
855 449
diff --git a/pwmanager/pwmanager/libgcryptif.h b/pwmanager/pwmanager/libgcryptif.h
index 7390827..ce76675 100644
--- a/pwmanager/pwmanager/libgcryptif.h
+++ b/pwmanager/pwmanager/libgcryptif.h
@@ -1,153 +1,158 @@
1/*************************************************************************** 1/***************************************************************************
2 * * 2 * *
3 * copyright (C) 2004 by Michael Buesch * 3 * copyright (C) 2004 by Michael Buesch *
4 * email: mbuesch@freenet.de * 4 * email: mbuesch@freenet.de *
5 * * 5 * *
6 * hashPassphrase() is derived from GnuPG and is * 6 * hashPassphrase() is derived from GnuPG and is *
7 * Copyright (C) 1998, 1999, 2000, 2001, 2003 * 7 * Copyright (C) 1998, 1999, 2000, 2001, 2003 *
8 * Free Software Foundation, Inc. * 8 * Free Software Foundation, Inc. *
9 * * 9 * *
10 * This program is free software; you can redistribute it and/or modify * 10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License version 2 * 11 * it under the terms of the GNU General Public License version 2 *
12 * as published by the Free Software Foundation. * 12 * as published by the Free Software Foundation. *
13 * * 13 * *
14 ***************************************************************************/ 14 ***************************************************************************/
15 15
16/***************************************************************************
17 * copyright (C) 2004 by Ulf Schenk
18 * This file is originaly based on version 2.0 of pwmanager
19 * and was modified to run on embedded devices that run microkde
20 *
21 * $Id$
22 **************************************************************************/
23
16#ifndef __LIBGCRYPTIF_H 24#ifndef __LIBGCRYPTIF_H
17#define __LIBGCRYPTIF_H 25#define __LIBGCRYPTIF_H
18 26
19#include "pwmexception.h" 27#include "pwmexception.h"
20 28
21//US ENH: should we put this better into globalstuff.h?
22#define CONFIG_PWMANAGER_CRYPTO
23
24//#undef CONFIG_PWMANAGER_GCRY // for debugging only. 29//#undef CONFIG_PWMANAGER_GCRY // for debugging only.
25#if defined CONFIG_PWMANAGER_GCRY || defined CONFIG_PWMANAGER_CRYPTO 30#ifdef CONFIG_PWMANAGER_GCRY
26 31
27#include <stddef.h> 32#include <stddef.h>
28#include <sys/types.h> 33#include <sys/types.h>
29#include <stdint.h> 34#include <stdint.h>
30 35
31 #define STRING2KEY_SALTLEN8 36 #define STRING2KEY_SALTLEN8
32 37
33/** interface class for the libgcrypt cipher and hash algorithms 38/** interface class for the libgcrypt cipher and hash algorithms
34 * NOTE: Always allocate 1024 extra bytes for the inBuf (for padding) 39 * NOTE: Always allocate 1024 extra bytes for the inBuf (for padding)
35 */ 40 */
36class LibGCryptIf 41class LibGCryptIf
37{ 42{
38protected: 43protected:
39 struct STRING2KEY 44 struct STRING2KEY
40 { 45 {
41 int mode; 46 int mode;
42 int hash_algo; 47 int hash_algo;
43 uint8_t salt[STRING2KEY_SALTLEN]; 48 uint8_t salt[STRING2KEY_SALTLEN];
44 uint32_t count; 49 uint32_t count;
45 }; 50 };
46 struct DEK 51 struct DEK
47 { 52 {
48 size_t keylen; 53 size_t keylen;
49 uint8_t key[32]; // this is the largest used keylen (256 bit) 54 uint8_t key[32]; // this is the largest used keylen (256 bit)
50 }; 55 };
51 56
52public: 57public:
53 LibGCryptIf() { } 58 LibGCryptIf() { }
54 /** is libgcrypt available? */ 59 /** is libgcrypt available? */
55 static bool available() 60 static bool available()
56 { return true; } 61 { return true; }
57 /** encrypt data. _algo is the PWM_CRYPT_* ID 62 /** encrypt data. _algo is the PWM_CRYPT_* ID
58 * of the algorithm. 63 * of the algorithm.
59 */ 64 */
60 PwMerror encrypt(unsigned char **outBuf, 65 PwMerror encrypt(unsigned char **outBuf,
61 size_t *outBufLen, 66 size_t *outBufLen,
62 unsigned char *inBuf, 67 unsigned char *inBuf,
63 size_t inBufLen, 68 size_t inBufLen,
64 const unsigned char *key, 69 const unsigned char *key,
65 size_t keylen, 70 size_t keylen,
66 char _algo); 71 char _algo);
67 /** decrypt data. _algo is the PWM_CRYPT_* ID 72 /** decrypt data. _algo is the PWM_CRYPT_* ID
68 * of the algorithm. 73 * of the algorithm.
69 */ 74 */
70 PwMerror decrypt(unsigned char **outBuf, 75 PwMerror decrypt(unsigned char **outBuf,
71 size_t *outBufLen, 76 size_t *outBufLen,
72 const unsigned char *inBuf, 77 const unsigned char *inBuf,
73 size_t inBufLen, 78 size_t inBufLen,
74 const unsigned char *key, 79 const unsigned char *key,
75 size_t keylen, 80 size_t keylen,
76 char _algo); 81 char _algo);
77 /** hash data. _algo is the PWM_HASH_* ID of the hash */ 82 /** hash data. _algo is the PWM_HASH_* ID of the hash */
78 PwMerror hash(unsigned char **outBuf, 83 PwMerror hash(unsigned char **outBuf,
79 size_t *outBufLen, 84 size_t *outBufLen,
80 const unsigned char *inBuf, 85 const unsigned char *inBuf,
81 size_t inBufLen, 86 size_t inBufLen,
82 char _algo); 87 char _algo);
83 /** returns the length of the hash. _algo is the PWM_HASH_* 88 /** returns the length of the hash. _algo is the PWM_HASH_*
84 * id of the hash. returns 0 on error. 89 * id of the hash. returns 0 on error.
85 */ 90 */
86 unsigned int hashLength(char _algo); 91 unsigned int hashLength(char _algo);
87 92
88protected: 93protected:
89 /** returns the total buffer length */ 94 /** returns the total buffer length */
90 size_t getBufLen(size_t inBufLen, size_t boundary) 95 size_t getBufLen(size_t inBufLen, size_t boundary)
91 { 96 {
92 return ((boundary - (inBufLen % boundary)) + inBufLen); 97 return ((boundary - (inBufLen % boundary)) + inBufLen);
93 } 98 }
94 /** pad the data up to the given boundary. 99 /** pad the data up to the given boundary.
95 * "buf" has to be big enough! 100 * "buf" has to be big enough!
96 */ 101 */
97 void padData(unsigned char *buf, 102 void padData(unsigned char *buf,
98 size_t bufLen, 103 size_t bufLen,
99 size_t boundary); 104 size_t boundary);
100 /** unpad the data */ 105 /** unpad the data */
101 void unpadData(const unsigned char *buf, 106 void unpadData(const unsigned char *buf,
102 size_t *bufLen); 107 size_t *bufLen);
103 /** maps the PWM_CRYPT_* ID of an algorithm 108 /** maps the PWM_CRYPT_* ID of an algorithm
104 * to the libgcrypt GCRY_CIPHER_* ID 109 * to the libgcrypt GCRY_CIPHER_* ID
105 */ 110 */
106 int mapCipherId(char algo); 111 int mapCipherId(char algo);
107 /** maps the PWM_HASH_* ID of an algorithm 112 /** maps the PWM_HASH_* ID of an algorithm
108 * to the libgcrypt GCRY_MD_* ID 113 * to the libgcrypt GCRY_MD_* ID
109 */ 114 */
110 int mapHashId(char algo); 115 int mapHashId(char algo);
111 /** hash a passphrase to a cipher key */ 116 /** hash a passphrase to a cipher key */
112 bool hashPassphrase(const unsigned char *pw, 117 bool hashPassphrase(const unsigned char *pw,
113 size_t pwlen, 118 size_t pwlen,
114 unsigned char *salt, 119 unsigned char *salt,
115 unsigned char *key, 120 unsigned char *key,
116 size_t keylen, 121 size_t keylen,
117 bool create); 122 bool create);
118 /** hash a passphrase to a cipher key */ 123 /** hash a passphrase to a cipher key */
119 bool doHashPassphrase(DEK *dek, 124 bool doHashPassphrase(DEK *dek,
120 const unsigned char *pw, 125 const unsigned char *pw,
121 size_t pwlen, 126 size_t pwlen,
122 STRING2KEY *s2k, 127 STRING2KEY *s2k,
123 bool create); 128 bool create);
124}; 129};
125 130
126 131
127#else // CONFIG_PWMANAGER_GCRY 132#else // CONFIG_PWMANAGER_GCRY
128/** libgcrypt is not installed. This is a NOP wrapper. */ 133/** libgcrypt is not installed. This is a NOP wrapper. */
129class LibGCryptIf 134class LibGCryptIf
130{ 135{
131public: 136public:
132 LibGCryptIf() { } 137 LibGCryptIf() { }
133 static bool available() 138 static bool available()
134 { return false; } 139 { return false; }
135 PwMerror encrypt(unsigned char **, 140 PwMerror encrypt(unsigned char **,
136 size_t *, 141 size_t *,
137 unsigned char *, 142 unsigned char *,
138 size_t, 143 size_t,
139 const unsigned char *, 144 const unsigned char *,
140 size_t, 145 size_t,
141 char) 146 char)
142 { return e_cryptNotImpl; } 147 { return e_cryptNotImpl; }
143 PwMerror decrypt(unsigned char **, 148 PwMerror decrypt(unsigned char **,
144 size_t *, 149 size_t *,
145 const unsigned char *, 150 const unsigned char *,
146 size_t, 151 size_t,
147 const unsigned char *, 152 const unsigned char *,
148 size_t, 153 size_t,
149 char) 154 char)
150 { return e_cryptNotImpl; } 155 { return e_cryptNotImpl; }
151 PwMerror hash(unsigned char **, 156 PwMerror hash(unsigned char **,
152 size_t *, 157 size_t *,
153 const unsigned char *, 158 const unsigned char *,