summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/pwmanager/libgcryptif.cpp2
-rw-r--r--pwmanager/pwmanager/libgcryptif.h2
2 files changed, 2 insertions, 2 deletions
diff --git a/pwmanager/pwmanager/libgcryptif.cpp b/pwmanager/pwmanager/libgcryptif.cpp
index 8175510..eafd318 100644
--- a/pwmanager/pwmanager/libgcryptif.cpp
+++ b/pwmanager/pwmanager/libgcryptif.cpp
@@ -1,449 +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
+ * This file is originaly based on version 1.1 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>
#ifdef PWM_EMBEDDED
#include <pwmprefs.h>
#endif
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_GCRY
diff --git a/pwmanager/pwmanager/libgcryptif.h b/pwmanager/pwmanager/libgcryptif.h
index ce76675..dffd55b 100644
--- a/pwmanager/pwmanager/libgcryptif.h
+++ b/pwmanager/pwmanager/libgcryptif.h
@@ -1,166 +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
+ * This file is originaly based on version 1.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#ifndef __LIBGCRYPTIF_H
#define __LIBGCRYPTIF_H
#include "pwmexception.h"
//#undef CONFIG_PWMANAGER_GCRY // for debugging only.
#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