Projekt

Allgemein

Profil

Herunterladen (19,8 KB) Statistiken
| Zweig: | Markierung: | Revision:
/***************************************************************************
begin : Mon Dec 01 2008
copyright : (C) 2008 by Martin Preuss
email : martin@libchipcard.de

***************************************************************************
* Please see toplevel file COPYING for license details *
***************************************************************************/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#define DISABLE_DEBUGLOG


#include "cryptmgr_p.h"
#include "i18n_l.h"
#include <gwenhywfar/misc.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/gwentime.h>

#include <gwenhywfar/crypthead.h>
#include <gwenhywfar/sighead.h>
#include <gwenhywfar/sigtail.h>
#include <gwenhywfar/tag16.h>
#include <gwenhywfar/cryptkeysym.h>
#include <gwenhywfar/padd.h>




GWEN_INHERIT_FUNCTIONS(GWEN_CRYPTMGR)



GWEN_CRYPTMGR *GWEN_CryptMgr_new() {
GWEN_CRYPTMGR *cm;

GWEN_NEW_OBJECT(GWEN_CRYPTMGR, cm);
GWEN_INHERIT_INIT(GWEN_CRYPTMGR, cm);

return cm;
}



void GWEN_CryptMgr_free(GWEN_CRYPTMGR *cm) {
if (cm) {
GWEN_INHERIT_FINI(GWEN_CRYPTMGR, cm);
free(cm->localKeyName);
free(cm->peerKeyName);

GWEN_FREE_OBJECT(cm);
}
}



const char *GWEN_CryptMgr_GetLocalKeyName(const GWEN_CRYPTMGR *cm) {
assert(cm);
return cm->localKeyName;
}



void GWEN_CryptMgr_SetLocalKeyName(GWEN_CRYPTMGR *cm, const char *s) {
assert(cm);
free(cm->localKeyName);
if (s) cm->localKeyName=strdup(s);
else cm->localKeyName=NULL;
}



int GWEN_CryptMgr_GetLocalKeyNumber(const GWEN_CRYPTMGR *cm) {
assert(cm);
return cm->localKeyNumber;
}



void GWEN_CryptMgr_SetLocalKeyNumber(GWEN_CRYPTMGR *cm, int i) {
assert(cm);
cm->localKeyNumber=i;
}



int GWEN_CryptMgr_GetLocalKeyVersion(const GWEN_CRYPTMGR *cm) {
assert(cm);
return cm->localKeyVersion;
}



void GWEN_CryptMgr_SetLocalKeyVersion(GWEN_CRYPTMGR *cm, int i) {
assert(cm);
cm->localKeyVersion=i;
}



const char *GWEN_CryptMgr_GetPeerKeyName(const GWEN_CRYPTMGR *cm) {
assert(cm);
return cm->peerKeyName;
}



void GWEN_CryptMgr_SetPeerKeyName(GWEN_CRYPTMGR *cm, const char *s) {
assert(cm);
free(cm->peerKeyName);
if (s) cm->peerKeyName=strdup(s);
else cm->peerKeyName=NULL;
}



int GWEN_CryptMgr_GetPeerKeyNumber(const GWEN_CRYPTMGR *cm) {
assert(cm);
return cm->peerKeyNumber;
}



void GWEN_CryptMgr_SetPeerKeyNumber(GWEN_CRYPTMGR *cm, int i) {
assert(cm);
cm->peerKeyNumber=i;
}



int GWEN_CryptMgr_GetPeerKeyVersion(const GWEN_CRYPTMGR *cm) {
assert(cm);
return cm->peerKeyVersion;
}



void GWEN_CryptMgr_SetPeerKeyVersion(GWEN_CRYPTMGR *cm, int i) {
assert(cm);
cm->peerKeyVersion=i;
}



int GWEN_CryptMgr_GetCryptProfile(const GWEN_CRYPTMGR *cm) {
assert(cm);
return cm->cryptProfile;
}



void GWEN_CryptMgr_SetCryptProfile(GWEN_CRYPTMGR *cm, int i) {
assert(cm);
cm->cryptProfile=i;
}



int GWEN_CryptMgr_GetSignatureProfile(const GWEN_CRYPTMGR *cm) {
assert(cm);
return cm->signatureProfile;
}



void GWEN_CryptMgr_SetSignatureProfile(GWEN_CRYPTMGR *cm, int i) {
assert(cm);
cm->signatureProfile=i;
}





int GWEN_CryptMgr_SignData(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
assert(cm);
if (cm->signDataFn)
return cm->signDataFn(cm, pData, lData, dbuf);
else
return GWEN_ERROR_NOT_IMPLEMENTED;
}



int GWEN_CryptMgr_EncryptKey(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
assert(cm);
if (cm->encryptKeyFn)
return cm->encryptKeyFn(cm, pData, lData, dbuf);
else
return GWEN_ERROR_NOT_IMPLEMENTED;
}



int GWEN_CryptMgr_VerifyData(GWEN_CRYPTMGR *cm,
const uint8_t *pData, uint32_t lData,
const uint8_t *pSignature, uint32_t lSignature) {
assert(cm);
if (cm->verifyDataFn)
return cm->verifyDataFn(cm, pData, lData, pSignature, lSignature);
else
return GWEN_ERROR_NOT_IMPLEMENTED;
}



int GWEN_CryptMgr_DecryptKey(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
assert(cm);
if (cm->decryptKeyFn)
return cm->decryptKeyFn(cm, pData, lData, dbuf);
else
return GWEN_ERROR_NOT_IMPLEMENTED;
}



GWEN_CRYPTMGR_SIGNDATA_FN GWEN_CryptMgr_SetSignDataFn(GWEN_CRYPTMGR *cm,
GWEN_CRYPTMGR_SIGNDATA_FN f) {
GWEN_CRYPTMGR_SIGNDATA_FN of;

assert(cm);
of=cm->signDataFn;
cm->signDataFn=f;
return of;
}



GWEN_CRYPTMGR_VERIFYDATA_FN GWEN_CryptMgr_SetVerifyDataFn(GWEN_CRYPTMGR *cm,
GWEN_CRYPTMGR_VERIFYDATA_FN f) {
GWEN_CRYPTMGR_VERIFYDATA_FN of;

assert(cm);
of=cm->verifyDataFn;
cm->verifyDataFn=f;
return of;
}



GWEN_CRYPTMGR_ENCRYPTKEY_FN GWEN_CryptMgr_SetEncryptKeyFn(GWEN_CRYPTMGR *cm,
GWEN_CRYPTMGR_ENCRYPTKEY_FN f) {
GWEN_CRYPTMGR_ENCRYPTKEY_FN of;

assert(cm);
of=cm->encryptKeyFn;
cm->encryptKeyFn=f;
return of;
}



GWEN_CRYPTMGR_DECRYPTKEY_FN GWEN_CryptMgr_SetDecryptKeyFn(GWEN_CRYPTMGR *cm,
GWEN_CRYPTMGR_DECRYPTKEY_FN f) {
GWEN_CRYPTMGR_DECRYPTKEY_FN of;

assert(cm);
of=cm->decryptKeyFn;
cm->decryptKeyFn=f;
return of;
}



int GWEN_CryptMgr_Sign(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
GWEN_SIGHEAD *sh;
GWEN_SIGTAIL *st;
GWEN_TIME *ti;
uint32_t pos;
uint32_t shPos;
uint8_t *p;
uint32_t l;
int rv;
GWEN_BUFFER *sigbuf;

assert(cm);
GWEN_Buffer_AppendByte(dbuf, GWEN_CRYPTMGR_TLV_SIGNEDOBJECT);
pos=GWEN_Buffer_GetPos(dbuf);
GWEN_Buffer_AppendByte(dbuf, 0);
GWEN_Buffer_AppendByte(dbuf, 0);

/* prepare signature head */
sh=GWEN_SigHead_new();
GWEN_SigHead_SetKeyName(sh, cm->localKeyName);
GWEN_SigHead_SetKeyNumber(sh, cm->localKeyNumber);
GWEN_SigHead_SetKeyVersion(sh, cm->localKeyVersion);
ti=GWEN_CurrentTime();
GWEN_SigHead_SetDateTime(sh, ti);
GWEN_Time_free(ti);
GWEN_SigHead_SetSignatureProfile(sh, cm->signatureProfile);
GWEN_SigHead_SetSignatureNumber(sh, 1);

/* write signature head to buffer */
shPos=GWEN_Buffer_GetPos(dbuf);
rv=GWEN_SigHead_toBuffer(sh, dbuf, GWEN_CRYPTMGR_TLV_SIGHEAD);
GWEN_SigHead_free(sh);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}

/* write data to buffer */
if (pData && lData)
GWEN_Tag16_DirectlyToBuffer(GWEN_CRYPTMGR_TLV_SIGDATA,
(const char*)pData,
lData,
dbuf);

/* sign data: signature head TLV + data TLV */
sigbuf=GWEN_Buffer_new(0, 300, 0, 1);
p=((uint8_t*)GWEN_Buffer_GetStart(dbuf))+shPos;
l=GWEN_Buffer_GetPos(dbuf)-shPos;
rv=GWEN_CryptMgr_SignData(cm, p, l, sigbuf);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Buffer_free(sigbuf);
return rv;
}

/* create signature tail */
st=GWEN_SigTail_new();
GWEN_SigTail_SetSignature(st,
(const uint8_t*)GWEN_Buffer_GetStart(sigbuf),
GWEN_Buffer_GetUsedBytes(sigbuf));
GWEN_Buffer_free(sigbuf);
GWEN_SigTail_SetSignatureNumber(st, 1);

/* write signature tail */
rv=GWEN_SigTail_toBuffer(st, dbuf, GWEN_CRYPTMGR_TLV_SIGTAIL);
GWEN_SigTail_free(st);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}

/* write complete size */
l=GWEN_Buffer_GetPos(dbuf)-pos-2;
p=(uint8_t*)GWEN_Buffer_GetStart(dbuf)+pos;
*(p++)=l & 0xff;
*p=(l>>8) & 0xff;

return 0;
}



int GWEN_CryptMgr_Encrypt(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
GWEN_CRYPTHEAD *ch;
uint32_t pos;
uint8_t *p;
uint32_t l;
int rv;
GWEN_BUFFER *cryptbuf;
GWEN_BUFFER *tbuf;
GWEN_CRYPT_KEY *mkey;

assert(cm);

/* generate a message key */
mkey=GWEN_Crypt_KeyBlowFish_Generate(GWEN_Crypt_CryptMode_Cbc, 256/8, 2);
if (mkey==NULL) {
DBG_ERROR(GWEN_LOGDOMAIN, "Unable to generate BLOWFISH key");
return GWEN_ERROR_GENERIC;
}

GWEN_Buffer_AppendByte(dbuf, GWEN_CRYPTMGR_TLV_ENCRYPTEDOBJECT);
pos=GWEN_Buffer_GetPos(dbuf);
GWEN_Buffer_AppendByte(dbuf, 0);
GWEN_Buffer_AppendByte(dbuf, 0);

/* prepare signature head */
ch=GWEN_CryptHead_new();
GWEN_CryptHead_SetKeyName(ch, cm->peerKeyName);
GWEN_CryptHead_SetKeyNumber(ch, cm->peerKeyNumber);
GWEN_CryptHead_SetKeyVersion(ch, cm->peerKeyVersion);
GWEN_CryptHead_SetCryptProfile(ch, cm->signatureProfile);

/* encrypt key */
cryptbuf=GWEN_Buffer_new(0, lData+256, 0, 1);
rv=GWEN_CryptMgr_EncryptKey(cm,
GWEN_Crypt_KeyBlowFish_GetKeyDataPtr(mkey),
GWEN_Crypt_KeyBlowFish_GetKeyDataLen(mkey),
cryptbuf);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Buffer_free(cryptbuf);
GWEN_CryptHead_free(ch);
GWEN_Crypt_Key_free(mkey);
return rv;
}
GWEN_CryptHead_SetKey(ch,
(const uint8_t*)GWEN_Buffer_GetStart(cryptbuf),
GWEN_Buffer_GetUsedBytes(cryptbuf));
GWEN_Buffer_free(cryptbuf);

/* write crypt head to buffer */
rv=GWEN_CryptHead_toBuffer(ch, dbuf, GWEN_CRYPTMGR_TLV_CRYPTHEAD);
GWEN_CryptHead_free(ch);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Crypt_Key_free(mkey);
return rv;
}

/* padd plain text data */
tbuf=GWEN_Buffer_new(0, lData+256, 0, 1);
GWEN_Buffer_AppendBytes(tbuf, (const char*)pData, lData);
GWEN_Padd_PaddWithAnsiX9_23(tbuf);

/* encrypt with message key */
cryptbuf=GWEN_Buffer_new(0, lData+256, 0, 1);
l=GWEN_Buffer_GetMaxUnsegmentedWrite(cryptbuf);
rv=GWEN_Crypt_Key_Encipher(mkey,
(const uint8_t*)GWEN_Buffer_GetStart(tbuf),
GWEN_Buffer_GetUsedBytes(tbuf),
(uint8_t*)GWEN_Buffer_GetStart(cryptbuf),
&l);
GWEN_Buffer_free(tbuf);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Buffer_free(cryptbuf);
GWEN_Crypt_Key_free(mkey);
return rv;
}
GWEN_Buffer_IncrementPos(cryptbuf, l);
GWEN_Buffer_AdjustUsedBytes(cryptbuf);

/* write encrypted data */
GWEN_Tag16_DirectlyToBuffer(GWEN_CRYPTMGR_TLV_CRYPTDATA,
GWEN_Buffer_GetStart(cryptbuf),
GWEN_Buffer_GetUsedBytes(cryptbuf),
dbuf);
GWEN_Buffer_free(cryptbuf);
GWEN_Crypt_Key_free(mkey);

/* write complete size */
l=GWEN_Buffer_GetPos(dbuf)-pos-2;
p=(uint8_t*)GWEN_Buffer_GetStart(dbuf)+pos;
*(p++)=l & 0xff;
*p=(l>>8) & 0xff;

return 0;
}



int GWEN_CryptMgr_Verify(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
GWEN_TAG16 *tag;
const uint8_t *p;
uint32_t l;
GWEN_SIGHEAD *sh=NULL;
GWEN_SIGTAIL *st=NULL;
const uint8_t *pSignedData=NULL;
uint32_t lSignedData=0;
int rv;

assert(cm);
if (lData<3) {
DBG_ERROR(GWEN_LOGDOMAIN, "Too few bytes");
return GWEN_ERROR_BAD_DATA;
}

tag=GWEN_Tag16_fromBuffer2(pData, lData, 0);
if (tag==NULL) {
DBG_ERROR(GWEN_LOGDOMAIN, "Data doesn't contain a valid TLV");
return GWEN_ERROR_BAD_DATA;
}

if (GWEN_Tag16_GetTagType(tag)!=GWEN_CRYPTMGR_TLV_SIGNEDOBJECT) {
DBG_ERROR(GWEN_LOGDOMAIN, "Data does not contain asigned object");
GWEN_Tag16_free(tag);
return GWEN_ERROR_BAD_DATA;
}

p=GWEN_Tag16_GetTagData(tag);
l=GWEN_Tag16_GetTagLength(tag);

/* read sighead */
if (l) {
GWEN_TAG16 *subtag;

subtag=GWEN_Tag16_fromBuffer2(p, l, 0);
if (subtag) {
if (GWEN_Tag16_GetTagType(subtag)==GWEN_CRYPTMGR_TLV_SIGHEAD) {
sh=GWEN_SigHead_fromBuffer(GWEN_Tag16_GetTagData(subtag),
GWEN_Tag16_GetTagLength(subtag));
if (sh) {
pSignedData=p;
lSignedData=GWEN_Tag16_GetTagSize(subtag);
}
}
p+=GWEN_Tag16_GetTagSize(subtag);
l-=GWEN_Tag16_GetTagSize(subtag);
GWEN_Tag16_free(subtag);
}
}

/* read and store signed data */
if (l) {
GWEN_TAG16 *subtag;

subtag=GWEN_Tag16_fromBuffer2(p, l, 0);
if (subtag) {
if (GWEN_Tag16_GetTagType(subtag)==GWEN_CRYPTMGR_TLV_SIGDATA) {
GWEN_Buffer_AppendBytes(dbuf,
GWEN_Tag16_GetTagData(subtag),
GWEN_Tag16_GetTagLength(subtag));
if ((pSignedData+lSignedData)==p) {
lSignedData+=GWEN_Tag16_GetTagSize(subtag);
}
else {
DBG_ERROR(GWEN_LOGDOMAIN, "data TLV must follow sighead TLV");
GWEN_Tag16_free(subtag);
GWEN_SigHead_free(sh);
GWEN_Tag16_free(tag);
return GWEN_ERROR_BAD_DATA;
}
}
p+=GWEN_Tag16_GetTagSize(subtag);
l-=GWEN_Tag16_GetTagSize(subtag);
GWEN_Tag16_free(subtag);
}
}

/* read sigtail (contains the signature) */
if (l) {
GWEN_TAG16 *subtag;

subtag=GWEN_Tag16_fromBuffer2(p, l, 0);
if (subtag) {
if (GWEN_Tag16_GetTagType(subtag)==GWEN_CRYPTMGR_TLV_SIGTAIL) {
st=GWEN_SigTail_fromBuffer(GWEN_Tag16_GetTagData(subtag),
GWEN_Tag16_GetTagLength(subtag));
}
p+=GWEN_Tag16_GetTagSize(subtag);
l-=GWEN_Tag16_GetTagSize(subtag);
GWEN_Tag16_free(subtag);
}
}

/* check for all needed components */
if (!(sh && st && pSignedData && lSignedData)) {
DBG_ERROR(GWEN_LOGDOMAIN, "Signed object is not complete");
GWEN_SigTail_free(st);
GWEN_SigHead_free(sh);
GWEN_Tag16_free(tag);
return GWEN_ERROR_BAD_DATA;
}

if (GWEN_SigHead_GetSignatureNumber(sh)!=GWEN_SigTail_GetSignatureNumber(st)) {
DBG_ERROR(GWEN_LOGDOMAIN, "Sighead doesn't match sigtail");
GWEN_SigTail_free(st);
GWEN_SigHead_free(sh);
GWEN_Tag16_free(tag);
return GWEN_ERROR_BAD_DATA;
}

/* store or check peer key info */
if (cm->peerKeyName==NULL) {
/* store peer info */
GWEN_CryptMgr_SetPeerKeyName(cm, GWEN_SigHead_GetKeyName(sh));
GWEN_CryptMgr_SetPeerKeyNumber(cm, GWEN_SigHead_GetKeyNumber(sh));
GWEN_CryptMgr_SetPeerKeyVersion(cm, GWEN_SigHead_GetKeyVersion(sh));
}
else {
const char *s;

/* compare peer info with expected info */
s=GWEN_SigHead_GetKeyName(sh);
if (!(cm->peerKeyName && s && (strcasecmp(cm->peerKeyName, s)==0) &&
(cm->peerKeyNumber==GWEN_SigHead_GetKeyNumber(sh)) &&
(cm->peerKeyVersion==GWEN_SigHead_GetKeyVersion(sh)))) {
DBG_ERROR(GWEN_LOGDOMAIN, "Unexpected peer key information in signature");
GWEN_SigTail_free(st);
GWEN_SigHead_free(sh);
GWEN_Tag16_free(tag);

return GWEN_ERROR_BAD_DATA;
}
}

/* verify signature */
rv=GWEN_CryptMgr_VerifyData(cm,
pSignedData, lSignedData,
GWEN_SigTail_GetSignaturePtr(st),
GWEN_SigTail_GetSignatureLen(st));
GWEN_SigTail_free(st);
GWEN_SigHead_free(sh);
GWEN_Tag16_free(tag);

if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}

return 0;
}



int GWEN_CryptMgr_Decrypt(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
GWEN_TAG16 *tag;
const uint8_t *p;
uint32_t l;
GWEN_CRYPTHEAD *ch=NULL;
const uint8_t *pEncryptedData=NULL;
uint32_t lEncryptedData=0;
int rv;
GWEN_BUFFER *tbuf;
GWEN_CRYPT_KEY *mkey;

assert(cm);
if (lData<3) {
DBG_ERROR(GWEN_LOGDOMAIN, "Too few bytes");
return GWEN_ERROR_BAD_DATA;
}

tag=GWEN_Tag16_fromBuffer2(pData, lData, 0);
if (tag==NULL) {
DBG_ERROR(GWEN_LOGDOMAIN, "Data doesn't contain a valid TLV");
return GWEN_ERROR_BAD_DATA;
}

if (GWEN_Tag16_GetTagType(tag)!=GWEN_CRYPTMGR_TLV_ENCRYPTEDOBJECT) {
DBG_ERROR(GWEN_LOGDOMAIN, "Data does not contain an encrypted object");
GWEN_Tag16_free(tag);
return GWEN_ERROR_BAD_DATA;
}

p=GWEN_Tag16_GetTagData(tag);
l=GWEN_Tag16_GetTagLength(tag);

/* read crypthead */
if (l) {
GWEN_TAG16 *subtag;

subtag=GWEN_Tag16_fromBuffer2(p, l, 0);
if (subtag) {
if (GWEN_Tag16_GetTagType(subtag)==GWEN_CRYPTMGR_TLV_CRYPTHEAD) {
ch=GWEN_CryptHead_fromBuffer(GWEN_Tag16_GetTagData(subtag),
GWEN_Tag16_GetTagLength(subtag));
}
p+=GWEN_Tag16_GetTagSize(subtag);
l-=GWEN_Tag16_GetTagSize(subtag);
GWEN_Tag16_free(subtag);
}
}

/* read encrypted data */
if (l) {
GWEN_TAG16 *subtag;

subtag=GWEN_Tag16_fromBuffer2(p, l, 0);
if (subtag) {
if (GWEN_Tag16_GetTagType(subtag)==GWEN_CRYPTMGR_TLV_CRYPTDATA) {
pEncryptedData=GWEN_Tag16_GetTagData(subtag);
lEncryptedData=GWEN_Tag16_GetTagLength(subtag);
}
p+=GWEN_Tag16_GetTagSize(subtag);
l-=GWEN_Tag16_GetTagSize(subtag);
GWEN_Tag16_free(subtag);
}
}

/* check for all needed components */
if (!(ch && pEncryptedData && lEncryptedData)) {
DBG_ERROR(GWEN_LOGDOMAIN, "Encrypted object is not complete");
GWEN_CryptHead_free(ch);
GWEN_Tag16_free(tag);
return GWEN_ERROR_BAD_DATA;
}

/* store or check peer key info */
if (cm->localKeyName) {
const char *s;

/* compare peer info with expected info */
s=GWEN_CryptHead_GetKeyName(ch);
if (!(cm->localKeyName && s && (strcasecmp(cm->localKeyName, s)==0) &&
(cm->localKeyNumber==GWEN_CryptHead_GetKeyNumber(ch)) &&
(cm->localKeyVersion==GWEN_CryptHead_GetKeyVersion(ch)))) {
DBG_ERROR(GWEN_LOGDOMAIN, "Unexpected local key information in signature");
GWEN_CryptHead_free(ch);
GWEN_Tag16_free(tag);

return GWEN_ERROR_BAD_DATA;
}
}

/* decrypt message key */
tbuf=GWEN_Buffer_new(0, GWEN_CryptHead_GetKeyLen(ch), 0, 1);
rv=GWEN_CryptMgr_DecryptKey(cm,
GWEN_CryptHead_GetKeyPtr(ch),
GWEN_CryptHead_GetKeyLen(ch),
tbuf);
GWEN_CryptHead_free(ch);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Buffer_free(tbuf);
GWEN_Tag16_free(tag);
return rv;
}

/* create message key */
mkey=GWEN_Crypt_KeyBlowFish_fromData(GWEN_Crypt_CryptMode_Cbc,
256/8,
(const uint8_t*) GWEN_Buffer_GetStart(tbuf),
GWEN_Buffer_GetUsedBytes(tbuf));
GWEN_Buffer_free(tbuf);
if (mkey==NULL) {
DBG_ERROR(GWEN_LOGDOMAIN, "Unable to create BLOWFISH key from received data");
GWEN_Tag16_free(tag);
return GWEN_ERROR_BAD_DATA;
}


/* decrypt data with message key */
tbuf=GWEN_Buffer_new(0, lEncryptedData+256, 0, 1);
l=GWEN_Buffer_GetMaxUnsegmentedWrite(tbuf);
rv=GWEN_Crypt_Key_Decipher(mkey,
pEncryptedData, lEncryptedData,
(uint8_t*)GWEN_Buffer_GetStart(tbuf),
&l);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Buffer_free(tbuf);
GWEN_Crypt_Key_free(mkey);
GWEN_Tag16_free(tag);
return rv;
}
GWEN_Buffer_IncrementPos(tbuf, l);
GWEN_Buffer_AdjustUsedBytes(tbuf);

/* unpadd data */
rv=GWEN_Padd_UnpaddWithAnsiX9_23(tbuf);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Buffer_free(tbuf);
GWEN_Crypt_Key_free(mkey);
GWEN_Tag16_free(tag);
return rv;
}

/* store data */
GWEN_Buffer_AppendBuffer(dbuf, tbuf);

GWEN_Buffer_free(tbuf);
GWEN_Crypt_Key_free(mkey);
GWEN_Tag16_free(tag);

return 0;
}



int GWEN_CryptMgr_Encode(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
GWEN_BUFFER *tbuf;
int rv;

tbuf=GWEN_Buffer_new(0, lData, 0, 1);

/* create signed object */
DBG_INFO(GWEN_LOGDOMAIN, "Signing data");
rv=GWEN_CryptMgr_Sign(cm, pData, lData, tbuf);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Buffer_free(tbuf);
return rv;
}

/* create encrypted object (containing a signed object in this case) */
DBG_INFO(GWEN_LOGDOMAIN, "Encrypting data");
rv=GWEN_CryptMgr_Encrypt(cm,
(const uint8_t*)GWEN_Buffer_GetStart(tbuf),
GWEN_Buffer_GetUsedBytes(tbuf),
dbuf);
GWEN_Buffer_free(tbuf);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}

return 0;
}



int GWEN_CryptMgr_Decode(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) {
GWEN_BUFFER *tbuf;
int rv;

tbuf=GWEN_Buffer_new(0, lData, 0, 1);

/* decrypt encrypted object */
DBG_INFO(GWEN_LOGDOMAIN, "Decrypting data");
rv=GWEN_CryptMgr_Decrypt(cm, pData, lData, tbuf);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
GWEN_Buffer_free(tbuf);
return rv;
}

/* verify signature, copy signed data to dbuf in the process */
DBG_INFO(GWEN_LOGDOMAIN, "Verifying data");
rv=GWEN_CryptMgr_Verify(cm,
(const uint8_t*)GWEN_Buffer_GetStart(tbuf),
GWEN_Buffer_GetUsedBytes(tbuf),
dbuf);
GWEN_Buffer_free(tbuf);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}

return 0;
}





(5-5/17)