-rw-r--r-- | pwmanager/pwmanager/libgcryptif.cpp | 430 | ||||
-rw-r--r-- | pwmanager/pwmanager/libgcryptif.h | 13 |
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 @@ -12,8 +12,16 @@ * 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 @@ -21,426 +29,12 @@ #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, @@ -850,6 +444,6 @@ void LibGCryptIf::unpadData(const unsigned char *buf, } *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 @@ -12,18 +12,23 @@ * 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> |