summaryrefslogtreecommitdiffabout
Side-by-side diff
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,855 +1,449 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* hashPassphrase() is derived from GnuPG and is *
* Copyright (C) 1998, 1999, 2000, 2001, 2003 *
* Free Software Foundation, Inc. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
+/***************************************************************************
+ * copyright (C) 2004 by Ulf Schenk
+ * This file is originaly based on version 2.0 of pwmanager
+ * and was modified to run on embedded devices that run microkde
+ *
+ * $Id$
+ **************************************************************************/
+
#include "libgcryptif.h"
#ifdef CONFIG_PWMANAGER_GCRY
#include "pwmdoc.h"
#include "randomizer.h"
#include <gcrypt.h>
-PwMerror LibGCryptIf::encrypt(unsigned char **outBuf,
- size_t *outBufLen,
- unsigned char *inBuf,
- size_t inBufLen,
- const unsigned char *key,
- size_t keylen,
- char _algo)
-{
- PwMerror ret = e_success;
- gcry_error_t err;
- gcry_cipher_hd_t handle;
- size_t blklen;
- size_t unpaddedLen = inBufLen;
- size_t cipherKeylen;
- unsigned char *hashedKey;
- unsigned char salt[STRING2KEY_SALTLEN];
- int algo = mapCipherId(_algo);
-
- if (!inBufLen || !keylen)
- return e_invalidArg;
-
- // test if algo is ready for encryption
- err = gcry_cipher_algo_info(algo,
- GCRYCTL_TEST_ALGO,
- 0, 0);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_TEST_ALGO failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out;
- }
- // get the algo block length
- err = gcry_cipher_algo_info(algo,
- GCRYCTL_GET_BLKLEN,
- 0,
- &blklen);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_BLKLEN failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out;
- }
- /* double check if we have enough space.
- * We have only 1024 extra bytes for padding and salt.
- */
- BUG_ON(blklen > 1024 - STRING2KEY_SALTLEN);
- // get the algo key length
- err = gcry_cipher_algo_info(algo,
- GCRYCTL_GET_KEYLEN,
- 0,
- &cipherKeylen);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_KEYLEN failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out;
- }
- // now open the algo and get a handle
- err = gcry_cipher_open(&handle,
- algo,
- GCRY_CIPHER_MODE_CBC,
- 0);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_open() failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out;
- }
- // hash the "key" to a fixed size hash matching "cipherKeylen"
- hashedKey = new unsigned char[cipherKeylen];
- hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, true);
- // so now set the hashed key
- err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_setkey() failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- delete [] hashedKey;
- goto out_close;
- }
- delete [] hashedKey;
- /* allocate a buffer for the encrypted data.
- * The size of the buffer is the inBuf length, but blklen
- * aligned and plus the length of the salt, that is appended.
- */
- *outBufLen = getBufLen(unpaddedLen, blklen) + STRING2KEY_SALTLEN;
- *outBuf = new unsigned char[*outBufLen];
- padData(inBuf, unpaddedLen, blklen);
- // encrypt the padded data
- err = gcry_cipher_encrypt(handle,
- *outBuf,
- *outBufLen - STRING2KEY_SALTLEN,
- inBuf,
- *outBufLen - STRING2KEY_SALTLEN);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out_delete;
- }
- // append the salt to the encrypted data
- memcpy(*outBuf + *outBufLen - STRING2KEY_SALTLEN, salt, STRING2KEY_SALTLEN);
- goto out_close;
-out_delete:
- delete [] *outBuf;
-out_close:
- gcry_cipher_close(handle);
-out:
- return ret;
-}
-
-PwMerror LibGCryptIf::decrypt(unsigned char **outBuf,
- size_t *outBufLen,
- const unsigned char *inBuf,
- size_t inBufLen,
- const unsigned char *key,
- size_t keylen,
- char _algo)
-{
- PwMerror ret = e_success;
- gcry_error_t err;
- gcry_cipher_hd_t handle;
- size_t cipherKeylen;
- unsigned char *hashedKey;
- unsigned char salt[STRING2KEY_SALTLEN];
- int algo = mapCipherId(_algo);
-
- if (!inBufLen || !keylen)
- return e_invalidArg;
-
- // test if algo is ready for encryption
- err = gcry_cipher_algo_info(algo,
- GCRYCTL_TEST_ALGO,
- 0, 0);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_TEST_ALGO failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out;
- }
- // get algo key length
- err = gcry_cipher_algo_info(algo,
- GCRYCTL_GET_KEYLEN,
- 0,
- &cipherKeylen);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_GET_KEYLEN failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out;
- }
- // extract the salt of the encrypted data buffer
- memcpy(salt, inBuf + inBufLen - STRING2KEY_SALTLEN, STRING2KEY_SALTLEN);
- // open the algo and get a handle
- err = gcry_cipher_open(&handle,
- algo,
- GCRY_CIPHER_MODE_CBC,
- 0);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_open() failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out;
- }
- // hash the "key" to a fixed size hash matching "cipherKeylen"
- hashedKey = new unsigned char[cipherKeylen];
- hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, false);
- // so now set the hashed key
- err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_setkey() failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- delete [] hashedKey;
- goto out_close;
- }
- delete [] hashedKey;
- *outBufLen = inBufLen - STRING2KEY_SALTLEN;
- *outBuf = new unsigned char[*outBufLen];
- // decrypt the data
- err = gcry_cipher_decrypt(handle,
- *outBuf,
- *outBufLen,
- inBuf,
- *outBufLen);
- if (err != GPG_ERR_NO_ERROR) {
- printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
- + gcry_strerror(err));
- ret = e_cryptNotImpl;
- goto out_delete;
- }
- // remove all random padding
- unpadData(*outBuf, outBufLen);
- goto out_close;
-out_delete:
- delete [] *outBuf;
-out_close:
- gcry_cipher_close(handle);
-out:
- return ret;
-}
-
-PwMerror LibGCryptIf::hash(unsigned char **outBuf,
- size_t *outBufLen,
- const unsigned char *inBuf,
- size_t inBufLen,
- char _algo)
-{
- PwMerror ret = e_success;
- unsigned int hashLen;
- int algo = mapHashId(_algo);
-
- hashLen = gcry_md_get_algo_dlen(algo);
- *outBufLen = hashLen;
- *outBuf = new unsigned char[*outBufLen];
- gcry_md_hash_buffer(algo,
- *outBuf,
- inBuf,
- inBufLen);
- return ret;
-}
+#ifdef PWM_EMBEDDED
+#include <pwmprefs.h>
+#endif
-unsigned int LibGCryptIf::hashLength(char _algo)
-{
- unsigned int ret;
- int algo = mapHashId(_algo);
- ret = gcry_md_get_algo_dlen(algo);
- return ret;
-}
-
-int LibGCryptIf::mapCipherId(char algo)
-{
- switch (algo) {
- case PWM_CRYPT_AES128:
- return GCRY_CIPHER_AES;
- case PWM_CRYPT_AES192:
- return GCRY_CIPHER_AES192;
- case PWM_CRYPT_AES256:
- return GCRY_CIPHER_AES256;
- case PWM_CRYPT_3DES:
- return GCRY_CIPHER_3DES;
- case PWM_CRYPT_TWOFISH:
- return GCRY_CIPHER_TWOFISH;
- case PWM_CRYPT_TWOFISH128:
- return GCRY_CIPHER_TWOFISH128;
- default:
- BUG();
- }
- return GCRY_CIPHER_NONE;
-}
-
-int LibGCryptIf::mapHashId(char algo)
-{
- switch (algo) {
- case PWM_HASH_SHA1:
- return GCRY_MD_SHA1;
- case PWM_HASH_SHA256:
- return GCRY_MD_SHA256;
- case PWM_HASH_SHA384:
- return GCRY_MD_SHA384;
- case PWM_HASH_SHA512:
- return GCRY_MD_SHA512;
- case PWM_HASH_MD5:
- return GCRY_MD_MD5;
- case PWM_HASH_RMD160:
- return GCRY_MD_RMD160;
- case PWM_HASH_TIGER:
- return GCRY_MD_TIGER;
- default:
- BUG();
- }
- return GCRY_MD_NONE;
-}
-
-bool LibGCryptIf::hashPassphrase(const unsigned char *pw,
- size_t pwlen,
- unsigned char *salt,
- unsigned char *key,
- size_t keylen,
- bool create)
-{
- DEK dek;
- STRING2KEY s2k;
- bool ret;
-
- dek.keylen = keylen;
- s2k.mode = 1;
- s2k.hash_algo = mapHashId(conf()->confGlobHashAlgo());
- s2k.count = 0;
- if (!create)
- memcpy(s2k.salt, salt, STRING2KEY_SALTLEN);
- ret = doHashPassphrase(&dek,
- pw,
- pwlen,
- &s2k,
- create);
- if (!ret)
- goto out;
- memcpy(key, dek.key, dek.keylen);
- if (create)
- memcpy(salt, s2k.salt, STRING2KEY_SALTLEN);
-out:
- return ret;
-}
-
-
-bool LibGCryptIf::doHashPassphrase(DEK *dek,
- const unsigned char *pw,
- size_t pwlen,
- STRING2KEY *s2k,
- bool create)
-{
- // This function is derived from GnuPG-1.2.5-rc2
- gcry_md_hd_t md;
- gcry_error_t err;
- bool ret = true;
- size_t pass, i;
- size_t used = 0;
-
- PWM_ASSERT(s2k->hash_algo);
- BUG_ON(!(dek->keylen > 0 && dek->keylen <= array_size(dek->key)));
-
- err = gcry_md_open(&md, s2k->hash_algo, 0);
- if (err != GPG_ERR_NO_ERROR) {
- ret = false;
- goto out;
- }
- for (pass = 0; used < dek->keylen; pass++) {
- if (pass) {
- gcry_md_reset(md);
- for (i = 0; i < pass; i++) // preset the hash context
- gcry_md_putc(md, 0);
- }
- if (s2k->mode == 1 || s2k->mode == 3) {
- size_t len2 = pwlen + 8;
- size_t count = len2;
-
- if (create && !pass) {
- Randomizer *rnd = Randomizer::obj();
- const unsigned int salt_len = 8;
- string rndBuf(rnd->genRndBuf(salt_len));
- memcpy(s2k->salt, rndBuf.c_str(), salt_len);
- if (s2k->mode == 3)
- s2k->count = 96; // 65536 iterations
- }
- if (s2k->mode == 3) {
- count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
- if (count < len2)
- count = len2;
- }
- // a little bit complicated because we need a ulong for count
- while (count > len2) { // maybe iterated+salted
- gcry_md_write(md, s2k->salt, 8);
- gcry_md_write(md, pw, pwlen);
- count -= len2;
- }
- if (count < 8) {
- gcry_md_write(md, s2k->salt, count);
- } else {
- gcry_md_write(md, s2k->salt, 8);
- count -= 8;
- gcry_md_write(md, pw, count);
- }
- } else
- gcry_md_write(md, pw, pwlen);
- gcry_md_final(md);
- i = gcry_md_get_algo_dlen(s2k->hash_algo);
- if (i > dek->keylen - used)
- i = dek->keylen - used;
- memcpy(dek->key+used, gcry_md_read(md, s2k->hash_algo), i);
- used += i;
- }
- gcry_md_close(md);
-out:
- return ret;
-}
-
-void LibGCryptIf::padData(unsigned char *buf,
- size_t bufLen,
- size_t boundary)
-{
- size_t numPadBytes = boundary - ((bufLen + 1) % boundary);
- buf[bufLen] = static_cast<char>(0x01);
- size_t i = 0;
- Randomizer *rnd = Randomizer::obj();
- char c;
- unsigned char *b;
- while (i < numPadBytes) {
- c = rnd->genRndChar();
- if (c == static_cast<char>(0x01))
- continue;
- b = buf + bufLen + 1 + i;
- *b = c;
- ++i;
- }
-}
-
-void LibGCryptIf::unpadData(const unsigned char *buf,
- size_t *bufLen)
-{
- size_t pos;
- BUG_ON(*bufLen % 8);
- pos = *bufLen - 1;
- while (buf[pos] != static_cast<char>(0x01)) {
- BUG_ON(!pos);
- --pos;
- }
- *bufLen = pos;
-}
-
-#endif // CONFIG_PWMANAGER_GCRY
-
-#ifdef CONFIG_PWMANAGER_CRYPTO
-
-#include "pwmdoc.h"
-#include "randomizer.h"
-
-#include <openssl/crypto.h>
PwMerror LibGCryptIf::encrypt(unsigned char **outBuf,
size_t *outBufLen,
unsigned char *inBuf,
size_t inBufLen,
const unsigned char *key,
size_t keylen,
char _algo)
{
PwMerror ret = e_success;
gcry_error_t err;
gcry_cipher_hd_t handle;
size_t blklen;
size_t unpaddedLen = inBufLen;
size_t cipherKeylen;
unsigned char *hashedKey;
unsigned char salt[STRING2KEY_SALTLEN];
int algo = mapCipherId(_algo);
if (!inBufLen || !keylen)
return e_invalidArg;
// test if algo is ready for encryption
err = gcry_cipher_algo_info(algo,
GCRYCTL_TEST_ALGO,
0, 0);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_TEST_ALGO failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out;
}
// get the algo block length
err = gcry_cipher_algo_info(algo,
GCRYCTL_GET_BLKLEN,
0,
&blklen);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_BLKLEN failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out;
}
/* double check if we have enough space.
* We have only 1024 extra bytes for padding and salt.
*/
BUG_ON(blklen > 1024 - STRING2KEY_SALTLEN);
// get the algo key length
err = gcry_cipher_algo_info(algo,
GCRYCTL_GET_KEYLEN,
0,
&cipherKeylen);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_KEYLEN failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out;
}
// now open the algo and get a handle
err = gcry_cipher_open(&handle,
algo,
GCRY_CIPHER_MODE_CBC,
0);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_open() failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out;
}
// hash the "key" to a fixed size hash matching "cipherKeylen"
hashedKey = new unsigned char[cipherKeylen];
hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, true);
// so now set the hashed key
err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_setkey() failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
delete [] hashedKey;
goto out_close;
}
delete [] hashedKey;
/* allocate a buffer for the encrypted data.
* The size of the buffer is the inBuf length, but blklen
* aligned and plus the length of the salt, that is appended.
*/
*outBufLen = getBufLen(unpaddedLen, blklen) + STRING2KEY_SALTLEN;
*outBuf = new unsigned char[*outBufLen];
padData(inBuf, unpaddedLen, blklen);
// encrypt the padded data
err = gcry_cipher_encrypt(handle,
*outBuf,
*outBufLen - STRING2KEY_SALTLEN,
inBuf,
*outBufLen - STRING2KEY_SALTLEN);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out_delete;
}
// append the salt to the encrypted data
memcpy(*outBuf + *outBufLen - STRING2KEY_SALTLEN, salt, STRING2KEY_SALTLEN);
goto out_close;
out_delete:
delete [] *outBuf;
out_close:
gcry_cipher_close(handle);
out:
return ret;
}
PwMerror LibGCryptIf::decrypt(unsigned char **outBuf,
size_t *outBufLen,
const unsigned char *inBuf,
size_t inBufLen,
const unsigned char *key,
size_t keylen,
char _algo)
{
PwMerror ret = e_success;
gcry_error_t err;
gcry_cipher_hd_t handle;
size_t cipherKeylen;
unsigned char *hashedKey;
unsigned char salt[STRING2KEY_SALTLEN];
int algo = mapCipherId(_algo);
if (!inBufLen || !keylen)
return e_invalidArg;
// test if algo is ready for encryption
err = gcry_cipher_algo_info(algo,
GCRYCTL_TEST_ALGO,
0, 0);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_TEST_ALGO failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out;
}
// get algo key length
err = gcry_cipher_algo_info(algo,
GCRYCTL_GET_KEYLEN,
0,
&cipherKeylen);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_GET_KEYLEN failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out;
}
// extract the salt of the encrypted data buffer
memcpy(salt, inBuf + inBufLen - STRING2KEY_SALTLEN, STRING2KEY_SALTLEN);
// open the algo and get a handle
err = gcry_cipher_open(&handle,
algo,
GCRY_CIPHER_MODE_CBC,
0);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_open() failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out;
}
// hash the "key" to a fixed size hash matching "cipherKeylen"
hashedKey = new unsigned char[cipherKeylen];
hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, false);
// so now set the hashed key
err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_setkey() failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
delete [] hashedKey;
goto out_close;
}
delete [] hashedKey;
*outBufLen = inBufLen - STRING2KEY_SALTLEN;
*outBuf = new unsigned char[*outBufLen];
// decrypt the data
err = gcry_cipher_decrypt(handle,
*outBuf,
*outBufLen,
inBuf,
*outBufLen);
if (err != GPG_ERR_NO_ERROR) {
printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
+ gcry_strerror(err));
ret = e_cryptNotImpl;
goto out_delete;
}
// remove all random padding
unpadData(*outBuf, outBufLen);
goto out_close;
out_delete:
delete [] *outBuf;
out_close:
gcry_cipher_close(handle);
out:
return ret;
}
PwMerror LibGCryptIf::hash(unsigned char **outBuf,
size_t *outBufLen,
const unsigned char *inBuf,
size_t inBufLen,
char _algo)
{
PwMerror ret = e_success;
unsigned int hashLen;
int algo = mapHashId(_algo);
hashLen = gcry_md_get_algo_dlen(algo);
*outBufLen = hashLen;
*outBuf = new unsigned char[*outBufLen];
gcry_md_hash_buffer(algo,
*outBuf,
inBuf,
inBufLen);
return ret;
}
unsigned int LibGCryptIf::hashLength(char _algo)
{
unsigned int ret;
int algo = mapHashId(_algo);
ret = gcry_md_get_algo_dlen(algo);
return ret;
}
int LibGCryptIf::mapCipherId(char algo)
{
switch (algo) {
case PWM_CRYPT_AES128:
return GCRY_CIPHER_AES;
case PWM_CRYPT_AES192:
return GCRY_CIPHER_AES192;
case PWM_CRYPT_AES256:
return GCRY_CIPHER_AES256;
case PWM_CRYPT_3DES:
return GCRY_CIPHER_3DES;
case PWM_CRYPT_TWOFISH:
return GCRY_CIPHER_TWOFISH;
case PWM_CRYPT_TWOFISH128:
return GCRY_CIPHER_TWOFISH128;
default:
BUG();
}
return GCRY_CIPHER_NONE;
}
int LibGCryptIf::mapHashId(char algo)
{
switch (algo) {
case PWM_HASH_SHA1:
return GCRY_MD_SHA1;
case PWM_HASH_SHA256:
return GCRY_MD_SHA256;
case PWM_HASH_SHA384:
return GCRY_MD_SHA384;
case PWM_HASH_SHA512:
return GCRY_MD_SHA512;
case PWM_HASH_MD5:
return GCRY_MD_MD5;
case PWM_HASH_RMD160:
return GCRY_MD_RMD160;
case PWM_HASH_TIGER:
return GCRY_MD_TIGER;
default:
BUG();
}
return GCRY_MD_NONE;
}
bool LibGCryptIf::hashPassphrase(const unsigned char *pw,
size_t pwlen,
unsigned char *salt,
unsigned char *key,
size_t keylen,
bool create)
{
DEK dek;
STRING2KEY s2k;
bool ret;
dek.keylen = keylen;
s2k.mode = 1;
s2k.hash_algo = mapHashId(conf()->confGlobHashAlgo());
s2k.count = 0;
if (!create)
memcpy(s2k.salt, salt, STRING2KEY_SALTLEN);
ret = doHashPassphrase(&dek,
pw,
pwlen,
&s2k,
create);
if (!ret)
goto out;
memcpy(key, dek.key, dek.keylen);
if (create)
memcpy(salt, s2k.salt, STRING2KEY_SALTLEN);
out:
return ret;
}
bool LibGCryptIf::doHashPassphrase(DEK *dek,
const unsigned char *pw,
size_t pwlen,
STRING2KEY *s2k,
bool create)
{
// This function is derived from GnuPG-1.2.5-rc2
gcry_md_hd_t md;
gcry_error_t err;
bool ret = true;
size_t pass, i;
size_t used = 0;
PWM_ASSERT(s2k->hash_algo);
BUG_ON(!(dek->keylen > 0 && dek->keylen <= array_size(dek->key)));
err = gcry_md_open(&md, s2k->hash_algo, 0);
if (err != GPG_ERR_NO_ERROR) {
ret = false;
goto out;
}
for (pass = 0; used < dek->keylen; pass++) {
if (pass) {
gcry_md_reset(md);
for (i = 0; i < pass; i++) // preset the hash context
gcry_md_putc(md, 0);
}
if (s2k->mode == 1 || s2k->mode == 3) {
size_t len2 = pwlen + 8;
size_t count = len2;
if (create && !pass) {
Randomizer *rnd = Randomizer::obj();
const unsigned int salt_len = 8;
string rndBuf(rnd->genRndBuf(salt_len));
memcpy(s2k->salt, rndBuf.c_str(), salt_len);
if (s2k->mode == 3)
s2k->count = 96; // 65536 iterations
}
if (s2k->mode == 3) {
count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
if (count < len2)
count = len2;
}
// a little bit complicated because we need a ulong for count
while (count > len2) { // maybe iterated+salted
gcry_md_write(md, s2k->salt, 8);
gcry_md_write(md, pw, pwlen);
count -= len2;
}
if (count < 8) {
gcry_md_write(md, s2k->salt, count);
} else {
gcry_md_write(md, s2k->salt, 8);
count -= 8;
gcry_md_write(md, pw, count);
}
} else
gcry_md_write(md, pw, pwlen);
gcry_md_final(md);
i = gcry_md_get_algo_dlen(s2k->hash_algo);
if (i > dek->keylen - used)
i = dek->keylen - used;
memcpy(dek->key+used, gcry_md_read(md, s2k->hash_algo), i);
used += i;
}
gcry_md_close(md);
out:
return ret;
}
void LibGCryptIf::padData(unsigned char *buf,
size_t bufLen,
size_t boundary)
{
size_t numPadBytes = boundary - ((bufLen + 1) % boundary);
buf[bufLen] = static_cast<char>(0x01);
size_t i = 0;
Randomizer *rnd = Randomizer::obj();
char c;
unsigned char *b;
while (i < numPadBytes) {
c = rnd->genRndChar();
if (c == static_cast<char>(0x01))
continue;
b = buf + bufLen + 1 + i;
*b = c;
++i;
}
}
void LibGCryptIf::unpadData(const unsigned char *buf,
size_t *bufLen)
{
size_t pos;
BUG_ON(*bufLen % 8);
pos = *bufLen - 1;
while (buf[pos] != static_cast<char>(0x01)) {
BUG_ON(!pos);
--pos;
}
*bufLen = pos;
}
-#endif // CONFIG_PWMANAGER_CRYPTO
+#endif // CONFIG_PWMANAGER_GCRY
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,161 +1,166 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* hashPassphrase() is derived from GnuPG and is *
* Copyright (C) 1998, 1999, 2000, 2001, 2003 *
* Free Software Foundation, Inc. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
+/***************************************************************************
+ * copyright (C) 2004 by Ulf Schenk
+ * This file is originaly based on version 2.0 of pwmanager
+ * and was modified to run on embedded devices that run microkde
+ *
+ * $Id$
+ **************************************************************************/
+
#ifndef __LIBGCRYPTIF_H
#define __LIBGCRYPTIF_H
#include "pwmexception.h"
-//US ENH: should we put this better into globalstuff.h?
-#define CONFIG_PWMANAGER_CRYPTO
-
//#undef CONFIG_PWMANAGER_GCRY // for debugging only.
-#if defined CONFIG_PWMANAGER_GCRY || defined CONFIG_PWMANAGER_CRYPTO
+#ifdef CONFIG_PWMANAGER_GCRY
#include <stddef.h>
#include <sys/types.h>
#include <stdint.h>
#define STRING2KEY_SALTLEN 8
/** interface class for the libgcrypt cipher and hash algorithms
* NOTE: Always allocate 1024 extra bytes for the inBuf (for padding)
*/
class LibGCryptIf
{
protected:
struct STRING2KEY
{
int mode;
int hash_algo;
uint8_t salt[STRING2KEY_SALTLEN];
uint32_t count;
};
struct DEK
{
size_t keylen;
uint8_t key[32]; // this is the largest used keylen (256 bit)
};
public:
LibGCryptIf() { }
/** is libgcrypt available? */
static bool available()
{ return true; }
/** encrypt data. _algo is the PWM_CRYPT_* ID
* of the algorithm.
*/
PwMerror encrypt(unsigned char **outBuf,
size_t *outBufLen,
unsigned char *inBuf,
size_t inBufLen,
const unsigned char *key,
size_t keylen,
char _algo);
/** decrypt data. _algo is the PWM_CRYPT_* ID
* of the algorithm.
*/
PwMerror decrypt(unsigned char **outBuf,
size_t *outBufLen,
const unsigned char *inBuf,
size_t inBufLen,
const unsigned char *key,
size_t keylen,
char _algo);
/** hash data. _algo is the PWM_HASH_* ID of the hash */
PwMerror hash(unsigned char **outBuf,
size_t *outBufLen,
const unsigned char *inBuf,
size_t inBufLen,
char _algo);
/** returns the length of the hash. _algo is the PWM_HASH_*
* id of the hash. returns 0 on error.
*/
unsigned int hashLength(char _algo);
protected:
/** returns the total buffer length */
size_t getBufLen(size_t inBufLen, size_t boundary)
{
return ((boundary - (inBufLen % boundary)) + inBufLen);
}
/** pad the data up to the given boundary.
* "buf" has to be big enough!
*/
void padData(unsigned char *buf,
size_t bufLen,
size_t boundary);
/** unpad the data */
void unpadData(const unsigned char *buf,
size_t *bufLen);
/** maps the PWM_CRYPT_* ID of an algorithm
* to the libgcrypt GCRY_CIPHER_* ID
*/
int mapCipherId(char algo);
/** maps the PWM_HASH_* ID of an algorithm
* to the libgcrypt GCRY_MD_* ID
*/
int mapHashId(char algo);
/** hash a passphrase to a cipher key */
bool hashPassphrase(const unsigned char *pw,
size_t pwlen,
unsigned char *salt,
unsigned char *key,
size_t keylen,
bool create);
/** hash a passphrase to a cipher key */
bool doHashPassphrase(DEK *dek,
const unsigned char *pw,
size_t pwlen,
STRING2KEY *s2k,
bool create);
};
#else // CONFIG_PWMANAGER_GCRY
/** libgcrypt is not installed. This is a NOP wrapper. */
class LibGCryptIf
{
public:
LibGCryptIf() { }
static bool available()
{ return false; }
PwMerror encrypt(unsigned char **,
size_t *,
unsigned char *,
size_t,
const unsigned char *,
size_t,
char)
{ return e_cryptNotImpl; }
PwMerror decrypt(unsigned char **,
size_t *,
const unsigned char *,
size_t,
const unsigned char *,
size_t,
char)
{ return e_cryptNotImpl; }
PwMerror hash(unsigned char **,
size_t *,
const unsigned char *,
size_t,
char)
{ return e_hashNotImpl; }
unsigned int hashLength(char)
{ return 0; }
};
#endif // CONFIG_PWMANAGER_GCRY
#endif // __LIBGCRYPTIF_H