int GWEN_Directory_FindFileInPaths(const GWEN_STRINGLIST *paths, const char *filePath, GWEN_BUFFER *fbuf) { GWEN_STRINGLISTENTRY *se; se=GWEN_StringList_FirstEntry(paths); while(se) { GWEN_BUFFER *tbuf; FILE *f; tbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(tbuf, GWEN_StringListEntry_Data(se)); GWEN_Buffer_AppendString(tbuf, DIRSEP); GWEN_Buffer_AppendString(tbuf, filePath); DBG_VERBOUS(GWEN_LOGDOMAIN, "Trying \"%s\"", GWEN_Buffer_GetStart(tbuf)); f=fopen(GWEN_Buffer_GetStart(tbuf), "r"); if (f) { fclose(f); DBG_DEBUG(GWEN_LOGDOMAIN, "File \"%s\" found in folder \"%s\"", filePath, GWEN_StringListEntry_Data(se)); GWEN_Buffer_AppendBuffer(fbuf, tbuf); GWEN_Buffer_free(tbuf); return 0; } GWEN_Buffer_free(tbuf); se=GWEN_StringListEntry_Next(se); } DBG_INFO(GWEN_LOGDOMAIN, "File \"%s\" not found", filePath); return GWEN_ERROR_NOT_FOUND; }
int GWEN_PathManager_FindFile(const char *destLib, const char *pathName, const char *fileName, GWEN_BUFFER *fbuf) { GWEN_DB_NODE *dbT; assert(gwen__paths); dbT=GWEN_DB_GetGroup(gwen__paths, GWEN_PATH_FLAGS_NAMEMUSTEXIST, destLib); if (dbT) { dbT=GWEN_DB_GetGroup(dbT, GWEN_PATH_FLAGS_NAMEMUSTEXIST, pathName); if (dbT) { int i; const char *s; GWEN_DB_NODE *dbN; GWEN_BUFFER *tbuf; tbuf=GWEN_Buffer_new(0, 256, 0, 1); /* check all paths */ dbN=GWEN_DB_FindFirstGroup(dbT, "pair"); while(dbN) { for (i=0; ; i++) { s=GWEN_DB_GetCharValue(dbN, "path", i, 0); if (!s) break; else { FILE *f; GWEN_Buffer_AppendString(tbuf, s); GWEN_Buffer_AppendString(tbuf, GWEN_DIR_SEPARATOR_S); GWEN_Buffer_AppendString(tbuf, fileName); DBG_DEBUG(GWEN_LOGDOMAIN, "Trying \"%s\"", GWEN_Buffer_GetStart(tbuf)); f=fopen(GWEN_Buffer_GetStart(tbuf), "r"); if (f) { fclose(f); DBG_DEBUG(GWEN_LOGDOMAIN, "File \"%s\" found in folder \"%s\"", fileName, s); GWEN_Buffer_AppendBuffer(fbuf, tbuf); GWEN_Buffer_free(tbuf); return 0; } GWEN_Buffer_Reset(tbuf); } } dbN=GWEN_DB_FindNextGroup(dbN, "pair"); } GWEN_Buffer_free(tbuf); } } DBG_INFO(GWEN_LOGDOMAIN, "File \"%s\" not found", fileName); return GWEN_ERROR_NOT_FOUND; }
GWENHYWFAR_CB int GWEN_CryptMgrKeys_DecryptKey(GWEN_CRYPTMGR *cm, const uint8_t *pData, uint32_t lData, GWEN_BUFFER *dbuf) { GWEN_CRYPTMGR_KEYS *xcm; int rv; GWEN_BUFFER *tbuf; int ksize; uint32_t l; assert(cm); xcm=GWEN_INHERIT_GETDATA(GWEN_CRYPTMGR, GWEN_CRYPTMGR_KEYS, cm); assert(xcm); if (xcm->localKey==NULL) { DBG_ERROR(GWEN_LOGDOMAIN, "No local key"); return GWEN_ERROR_GENERIC; } ksize=GWEN_Crypt_Key_GetKeySize(xcm->localKey); tbuf=GWEN_Buffer_new(0, ksize, 0, 1); l=GWEN_Buffer_GetMaxUnsegmentedWrite(tbuf); rv=GWEN_Crypt_Key_Decipher(xcm->localKey, pData, lData, (uint8_t*)GWEN_Buffer_GetPosPointer(tbuf), &l); if (rv<0) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(tbuf); return rv; } GWEN_Buffer_IncrementPos(tbuf, l); GWEN_Buffer_AdjustUsedBytes(tbuf); /* unpadd data */ rv=GWEN_Padd_UnpaddWithIso9796_2(tbuf); if (rv<0) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(tbuf); return rv; } GWEN_Buffer_AppendBuffer(dbuf, tbuf); GWEN_Buffer_free(tbuf); return 0; }
int AH_Msg_SignPinTan(AH_MSG *hmsg, GWEN_BUFFER *rawBuf, const char *signer) { AH_HBCI *h; GWEN_XMLNODE *node; GWEN_DB_NODE *cfg; GWEN_BUFFER *hbuf; int rv; char ctrlref[15]; const char *p; GWEN_MSGENGINE *e; AB_USER *su; uint32_t uFlags; char pin[64]; uint32_t tm; assert(hmsg); h=AH_Dialog_GetHbci(hmsg->dialog); assert(h); e=AH_Dialog_GetMsgEngine(hmsg->dialog); assert(e); GWEN_MsgEngine_SetMode(e, "pintan"); su=AB_Banking_FindUser(AH_HBCI_GetBankingApi(h), AH_PROVIDER_NAME, "de", "*", signer, "*"); if (!su) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Unknown user \"%s\"", signer); return GWEN_ERROR_NOT_FOUND; } uFlags=AH_User_GetFlags(su); node=GWEN_MsgEngine_FindNodeByPropertyStrictProto(e, "SEG", "id", 0, "SigHead"); if (!node) { DBG_INFO(AQHBCI_LOGDOMAIN, "Segment \"SigHead\" not found"); return GWEN_ERROR_INTERNAL; } /* for iTAN mode: set selected mode (Sicherheitsfunktion, kodiert) */ tm=AH_Msg_GetItanMethod(hmsg); if (tm==0) { tm=AH_Dialog_GetItanMethod(hmsg->dialog); if (tm) /* this is needed by AH_MsgPinTan_PrepareCryptoSeg */ AH_Msg_SetItanMethod(hmsg, tm); } /* prepare config for segment */ cfg=GWEN_DB_Group_new("sighead"); rv=AH_MsgPinTan_PrepareCryptoSeg(hmsg, su, cfg, 0, 1); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv); GWEN_DB_Group_free(cfg); return rv; } /* set expected signer */ if (!(uFlags & AH_USER_FLAGS_BANK_DOESNT_SIGN)) { const char *remoteId; remoteId=AH_User_GetPeerId(su); if (!remoteId || *remoteId==0) remoteId=AB_User_GetUserId(su); assert(remoteId); assert(*remoteId); DBG_DEBUG(AQHBCI_LOGDOMAIN, "Expecting \"%s\" to sign the response", remoteId); AH_Msg_SetExpectedSigner(hmsg, remoteId); } /* store system id */ p=NULL; if (!hmsg->noSysId) p=AH_User_GetSystemId(su); if (!p) p="0"; GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecDetails/SecId", p); if (tm) { GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "function", tm); } /* retrieve control reference for sigtail (to be used later) */ p=GWEN_DB_GetCharValue(cfg, "ctrlref", 0, ""); if (strlen(p)>=sizeof(ctrlref)) { DBG_INFO(AQHBCI_LOGDOMAIN, "Control reference too long (14 bytes maximum)"); GWEN_DB_Group_free(cfg); return -1; } strcpy(ctrlref, p); /* create SigHead */ hbuf=GWEN_Buffer_new(0, 128+GWEN_Buffer_GetUsedBytes(rawBuf), 0, 1); GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "head/seq", hmsg->firstSegment-1); GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "signseq", 1); /* create signature head segment */ rv=GWEN_MsgEngine_CreateMessageFromNode(e, node, hbuf, cfg); GWEN_DB_Group_free(cfg); cfg=0; if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not create SigHead"); GWEN_Buffer_free(hbuf); return rv; } /* insert new SigHead at beginning of message buffer */ DBG_DEBUG(AQHBCI_LOGDOMAIN, "Inserting signature head"); GWEN_Buffer_Rewind(hmsg->buffer); GWEN_Buffer_InsertBytes(hmsg->buffer, GWEN_Buffer_GetStart(hbuf), GWEN_Buffer_GetUsedBytes(hbuf)); /* create sigtail */ DBG_DEBUG(AQHBCI_LOGDOMAIN, "Completing signature tail"); cfg=GWEN_DB_Group_new("sigtail"); GWEN_Buffer_Reset(hbuf); GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "head/seq", hmsg->lastSegment+1); /* store to DB */ GWEN_DB_SetBinValue(cfg, GWEN_DB_FLAGS_DEFAULT, "signature", "NOSIGNATURE", 11); GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "ctrlref", ctrlref); /* handle pin */ memset(pin, 0, sizeof(pin)); rv=AH_User_InputPin(su, pin, 4, sizeof(pin), 0); if (rv<0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Error getting pin from medium (%d)", rv); GWEN_DB_Group_free(cfg); GWEN_Buffer_free(hbuf); memset(pin, 0, sizeof(pin)); return rv; } GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "pin", pin); AH_Msg_SetPin(hmsg, pin); memset(pin, 0, sizeof(pin)); /* handle tan */ if (hmsg->needTan) { DBG_NOTICE(AQHBCI_LOGDOMAIN, "This queue needs a TAN"); if (hmsg->usedTan) { DBG_NOTICE(AQHBCI_LOGDOMAIN, "Using existing TAN"); GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "tan", hmsg->usedTan); } else { char tan[16]; memset(tan, 0, sizeof(tan)); DBG_NOTICE(AQHBCI_LOGDOMAIN, "Asking for TAN"); rv=AH_User_InputTan(su, tan, 4, sizeof(tan)); if (rv<0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Error getting TAN from medium"); GWEN_DB_Group_free(cfg); GWEN_Buffer_free(hbuf); return rv; } GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "tan", tan); AH_Msg_SetTan(hmsg, tan); } } else { DBG_NOTICE(AQHBCI_LOGDOMAIN, "This queue doesn't need a TAN"); } /* get node */ node=GWEN_MsgEngine_FindNodeByPropertyStrictProto(e, "SEG", "id", 0, "SigTail"); if (!node) { DBG_INFO(AQHBCI_LOGDOMAIN, "Segment \"SigTail\"not found"); GWEN_Buffer_free(hbuf); GWEN_DB_Group_free(cfg); return GWEN_ERROR_INTERNAL; } rv=GWEN_MsgEngine_CreateMessageFromNode(e, node, hbuf, cfg); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not create SigTail (%d)", rv); GWEN_Buffer_free(hbuf); GWEN_DB_Group_free(cfg); return rv; } /* append sigtail */ DBG_DEBUG(AQHBCI_LOGDOMAIN, "Appending signature tail"); if (GWEN_Buffer_AppendBuffer(hmsg->buffer, hbuf)) { DBG_INFO(AQHBCI_LOGDOMAIN, "here"); GWEN_Buffer_free(hbuf); GWEN_DB_Group_free(cfg); return GWEN_ERROR_MEMORY_FULL; } DBG_DEBUG(AQHBCI_LOGDOMAIN, "Appending signature tail: done"); GWEN_Buffer_free(hbuf); GWEN_DB_Group_free(cfg); /* adjust segment numbers (for next signature and message tail */ hmsg->firstSegment--; hmsg->lastSegment++; return 0; }
void EBC_Provider_LogRequestResults(AB_PROVIDER *pro, EB_MSG *mRsp, GWEN_BUFFER *logbuf) { const char *tcode; const char *bcode; const char *s; GWEN_BUFFER *tbuf; tcode=EB_Msg_GetCharValue(mRsp, "header/mutable/ReturnCode", NULL); bcode=EB_Msg_GetCharValue(mRsp, "body/ReturnCode", NULL); tbuf=GWEN_Buffer_new(0, 256, 0, 1); if (tcode) { GWEN_Buffer_AppendString(tbuf, I18N("EBICS (Technical Code):")); GWEN_Buffer_AppendString(tbuf, " "); GWEN_Buffer_AppendString(tbuf, tcode); s=EBC_Provider_TechnicalCodeToString(tcode); if (s) { GWEN_Buffer_AppendString(tbuf, " ["); GWEN_Buffer_AppendString(tbuf, s); GWEN_Buffer_AppendString(tbuf, "]"); } if (logbuf) { GWEN_Buffer_AppendString(logbuf, "\t"); GWEN_Buffer_AppendBuffer(logbuf, tbuf); } GWEN_Gui_ProgressLog(0, EBC_Provider_ResultCodeToLogLevel(pro, tcode), GWEN_Buffer_GetStart(tbuf)); DBG_INFO(AQEBICS_LOGDOMAIN, "%s", GWEN_Buffer_GetStart(tbuf)); GWEN_Buffer_Reset(tbuf); } s=EB_Msg_GetCharValue(mRsp, "header/mutable/ReportText", NULL); if (s) { GWEN_Buffer_AppendString(tbuf, I18N("EBICS (Technical Report):")); GWEN_Buffer_AppendString(tbuf, " "); GWEN_Buffer_AppendString(tbuf, s); if (logbuf) { GWEN_Buffer_AppendString(logbuf, "\t"); GWEN_Buffer_AppendBuffer(logbuf, tbuf); } GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Notice, GWEN_Buffer_GetStart(tbuf)); DBG_INFO(AQEBICS_LOGDOMAIN, "%s", GWEN_Buffer_GetStart(tbuf)); GWEN_Buffer_Reset(tbuf); } s=EB_Msg_GetCharValue(mRsp, "body/ReturnCode", NULL); if (bcode) { GWEN_Buffer_AppendString(tbuf, I18N("EBICS (Bank Code):")); GWEN_Buffer_AppendString(tbuf, " "); GWEN_Buffer_AppendString(tbuf, bcode); s=EBC_Provider_BankCodeToString(bcode); if (s) { GWEN_Buffer_AppendString(tbuf, " ["); GWEN_Buffer_AppendString(tbuf, s); GWEN_Buffer_AppendString(tbuf, "]"); } if (logbuf) { GWEN_Buffer_AppendString(logbuf, "\t"); GWEN_Buffer_AppendBuffer(logbuf, tbuf); } GWEN_Gui_ProgressLog(0, EBC_Provider_ResultCodeToLogLevel(pro, bcode), GWEN_Buffer_GetStart(tbuf)); DBG_INFO(AQEBICS_LOGDOMAIN, "%s", GWEN_Buffer_GetStart(tbuf)); GWEN_Buffer_Reset(tbuf); } GWEN_Buffer_free(tbuf); }
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; }
static int EBC_Provider_SignMessage_X001(AB_PROVIDER *pro, EB_MSG *msg, AB_USER *u, xmlNodePtr node) { EBC_PROVIDER *dp; int rv; GWEN_CRYPT_TOKEN *ct; const GWEN_CRYPT_TOKEN_CONTEXT *ctx; const GWEN_CRYPT_TOKEN_KEYINFO *ki; uint32_t keyId; GWEN_BUFFER *hbuf; GWEN_BUFFER *bbuf; xmlNodePtr nodeX = NULL; xmlNodePtr nodeXX = NULL; xmlNodePtr nodeXXX = NULL; xmlNodePtr nodeXXXX = NULL; xmlNsPtr ns; assert(pro); dp=GWEN_INHERIT_GETDATA(AB_PROVIDER, EBC_PROVIDER, pro); assert(dp); /* get crypt token and context */ rv=EBC_Provider_MountToken(pro, u, &ct, &ctx); if (rv<0) { DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv); return rv; } /* get key id */ keyId=GWEN_Crypt_Token_Context_GetAuthSignKeyId(ctx); ki=GWEN_Crypt_Token_GetKeyInfo(ct, keyId, 0xffffffff, 0); if (ki==NULL) { DBG_INFO(AQEBICS_LOGDOMAIN, "Keyinfo %04x not found on crypt token [%s:%s]", keyId, GWEN_Crypt_Token_GetTypeName(ct), GWEN_Crypt_Token_GetTokenName(ct)); GWEN_Crypt_Token_Close(ct, 0, 0); return GWEN_ERROR_NOT_FOUND; } /* prepare signature nodes */ ns=xmlSearchNs(EB_Msg_GetDoc(msg), node, BAD_CAST "ds"); assert(ns); /* build hash */ bbuf=GWEN_Buffer_new(0, 256, 0, 1); rv=EB_Msg_BuildHashSha1(msg, bbuf); if (rv) { DBG_ERROR(AQEBICS_LOGDOMAIN, "Could not build hash"); GWEN_Buffer_free(bbuf); return rv; } /* base64 encode */ hbuf=GWEN_Buffer_new(0, 256, 0, 1); rv=GWEN_Base64_Encode((const uint8_t*)GWEN_Buffer_GetStart(bbuf), GWEN_Buffer_GetUsedBytes(bbuf), hbuf, 0); if (rv<0) { DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(hbuf); GWEN_Buffer_free(bbuf); return rv; } GWEN_Buffer_free(bbuf); /* create signature node */ nodeX=xmlNewChild(node, ns, BAD_CAST "SignedInfo", NULL); nodeXX=xmlNewChild(nodeX, ns, BAD_CAST "CanonicalizationMethod", NULL); xmlNewProp(nodeXX, BAD_CAST "Algorithm", BAD_CAST "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); nodeXX=xmlNewChild(nodeX, ns, BAD_CAST "SignatureMethod", NULL); xmlNewProp(nodeXX, BAD_CAST "Algorithm", BAD_CAST "http://www.w3.org/2000/09/xmldsig#rsa-sha1"); nodeXX=xmlNewChild(nodeX, ns, BAD_CAST "Reference", NULL); xmlNewProp(nodeXX, BAD_CAST "URI", BAD_CAST "#xpointer(//*[@authenticate='true'])"); nodeXXX=xmlNewChild(nodeXX, ns, BAD_CAST "Transforms", NULL); nodeXXXX=xmlNewChild(nodeXXX, ns, BAD_CAST "Transform", NULL); xmlNewProp(nodeXXXX, BAD_CAST "Algorithm", BAD_CAST "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"); nodeXXX=xmlNewChild(nodeXX, ns, BAD_CAST "DigestMethod", NULL); xmlNewProp(nodeXXX, BAD_CAST "Algorithm", BAD_CAST "http://www.w3.org/2000/09/xmldsig#sha1"); /* store hash value */ xmlNewTextChild(nodeXX, ns, BAD_CAST "DigestValue", BAD_CAST GWEN_Buffer_GetStart(hbuf)); GWEN_Buffer_free(hbuf); /* build hash over SignedInfo */ bbuf=GWEN_Buffer_new(0, 256, 0, 1); rv=EB_Xml_BuildNodeHashSha1(nodeX, "#xpointer(//*)", bbuf); if (rv<0) { DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(bbuf); return rv; } /* sign hash */ if (1) { GWEN_CRYPT_PADDALGO *algo; int ksize; uint32_t l; const uint8_t prefix[]={ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; /* add prefix to hash of SignedInfo */ hbuf=GWEN_Buffer_new(0, 256, 0, 1); ksize=GWEN_Crypt_Token_KeyInfo_GetKeySize(ki); GWEN_Buffer_AppendBytes(hbuf, (const char*)prefix, sizeof(prefix)); GWEN_Buffer_AppendBuffer(hbuf, bbuf); GWEN_Buffer_Reset(bbuf); /* select padd algo */ algo=GWEN_Crypt_PaddAlgo_new(GWEN_Crypt_PaddAlgoId_Pkcs1_1); GWEN_Crypt_PaddAlgo_SetPaddSize(algo, ksize); /* actually sign */ GWEN_Buffer_AllocRoom(bbuf, ksize+16); l=GWEN_Buffer_GetMaxUnsegmentedWrite(bbuf); rv=GWEN_Crypt_Token_Sign(ct, keyId, algo, (const uint8_t*)GWEN_Buffer_GetStart(hbuf), GWEN_Buffer_GetUsedBytes(hbuf), (uint8_t*)GWEN_Buffer_GetPosPointer(bbuf), &l, NULL, /* ignore seq counter */ 0); GWEN_Crypt_PaddAlgo_free(algo); if (rv<0) { DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(bbuf); GWEN_Buffer_free(hbuf); return rv; } GWEN_Buffer_IncrementPos(bbuf, l); GWEN_Buffer_AdjustUsedBytes(bbuf); /* base 64 encode signature */ GWEN_Buffer_Reset(hbuf); rv=GWEN_Base64_Encode((const uint8_t*)GWEN_Buffer_GetStart(bbuf), GWEN_Buffer_GetUsedBytes(bbuf), hbuf, 0); if (rv<0) { DBG_INFO(AQEBICS_LOGDOMAIN, "here (%d)", rv); GWEN_Buffer_free(hbuf); GWEN_Buffer_free(bbuf); return rv; } GWEN_Buffer_free(bbuf); /* store signature */ xmlNewTextChild(node, ns, BAD_CAST "SignatureValue", BAD_CAST GWEN_Buffer_GetStart(hbuf)); GWEN_Buffer_free(hbuf); } return 0; }
int AH_Msg_SignRdh2(AH_MSG *hmsg, AB_USER *su, GWEN_BUFFER *rawBuf, const char *signer) { AH_HBCI *h; GWEN_XMLNODE *node; GWEN_DB_NODE *cfg; GWEN_BUFFER *sigbuf; GWEN_BUFFER *hbuf; unsigned int l; int rv; char ctrlref[15]; const char *p; GWEN_MSGENGINE *e; uint32_t uFlags; GWEN_CRYPT_TOKEN *ct; const GWEN_CRYPT_TOKEN_CONTEXT *ctx; const GWEN_CRYPT_TOKEN_KEYINFO *ki; uint32_t keyId; uint32_t gid; assert(hmsg); h=AH_Dialog_GetHbci(hmsg->dialog); assert(h); e=AH_Dialog_GetMsgEngine(hmsg->dialog); assert(e); GWEN_MsgEngine_SetMode(e, "rdh"); gid=0; uFlags=AH_User_GetFlags(su); /* get crypt token of signer */ rv=AB_Banking_GetCryptToken(AH_HBCI_GetBankingApi(h), AH_User_GetTokenType(su), AH_User_GetTokenName(su), &ct); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not get crypt token for user \"%s\" (%d)", AB_User_GetUserId(su), rv); return rv; } /* open CryptToken if necessary */ if (!GWEN_Crypt_Token_IsOpen(ct)) { GWEN_Crypt_Token_AddModes(ct, GWEN_CRYPT_TOKEN_MODE_DIRECT_SIGN); rv=GWEN_Crypt_Token_Open(ct, 0, gid); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not open crypt token for user \"%s\" (%d)", AB_User_GetUserId(su), rv); return rv; } } /* get context and key info */ ctx=GWEN_Crypt_Token_GetContext(ct, AH_User_GetTokenContextId(su), gid); if (ctx==NULL) { DBG_INFO(AQHBCI_LOGDOMAIN, "Context %d not found on crypt token [%s:%s]", AH_User_GetTokenContextId(su), GWEN_Crypt_Token_GetTypeName(ct), GWEN_Crypt_Token_GetTokenName(ct)); return GWEN_ERROR_NOT_FOUND; } keyId=GWEN_Crypt_Token_Context_GetSignKeyId(ctx); ki=GWEN_Crypt_Token_GetKeyInfo(ct, keyId, 0xffffffff, gid); if (ki==NULL) { DBG_INFO(AQHBCI_LOGDOMAIN, "Keyinfo %04x not found on crypt token [%s:%s]", keyId, GWEN_Crypt_Token_GetTypeName(ct), GWEN_Crypt_Token_GetTokenName(ct)); return GWEN_ERROR_NOT_FOUND; } node=GWEN_MsgEngine_FindNodeByPropertyStrictProto(e, "SEG", "id", 0, "SigHead"); if (!node) { DBG_INFO(AQHBCI_LOGDOMAIN, "Segment \"SigHead\" not found"); return GWEN_ERROR_INTERNAL; } /* prepare config for segment */ cfg=GWEN_DB_Group_new("sighead"); rv=AH_MsgRdh_PrepareCryptoSeg2(hmsg, su, ki, cfg, 0, 1); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv); GWEN_DB_Group_free(cfg); return rv; } /* set expected signer */ if (!(uFlags & AH_USER_FLAGS_BANK_DOESNT_SIGN)) { const char *remoteId; remoteId=AH_User_GetPeerId(su); if (!remoteId || *remoteId==0) remoteId=AB_User_GetUserId(su); assert(remoteId); assert(*remoteId); DBG_DEBUG(AQHBCI_LOGDOMAIN, "Expecting \"%s\" to sign the response", remoteId); AH_Msg_SetExpectedSigner(hmsg, remoteId); } /* store system id */ if (hmsg->noSysId) { GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecDetails/SecId", "0"); } else { p=AH_User_GetSystemId(su); if (p==NULL) p=GWEN_Crypt_Token_Context_GetSystemId(ctx); if (p) GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecDetails/SecId", p); else { GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecDetails/SecId", "0"); } } /* retrieve control reference for sigtail (to be used later) */ p=GWEN_DB_GetCharValue(cfg, "ctrlref", 0, ""); if (strlen(p)>=sizeof(ctrlref)) { DBG_INFO(AQHBCI_LOGDOMAIN, "Control reference too long (14 bytes maximum)"); GWEN_DB_Group_free(cfg); return -1; } strcpy(ctrlref, p); /* create SigHead */ hbuf=GWEN_Buffer_new(0, 128+GWEN_Buffer_GetUsedBytes(rawBuf), 0, 1); GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "head/seq", hmsg->firstSegment-1); GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "signseq", GWEN_Crypt_Token_KeyInfo_GetSignCounter(ki)); /* create signature head segment */ rv=GWEN_MsgEngine_CreateMessageFromNode(e, node, hbuf, cfg); GWEN_DB_Group_free(cfg); cfg=0; if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not create SigHead"); GWEN_Buffer_free(hbuf); return rv; } /* remember size of sighead for now */ l=GWEN_Buffer_GetUsedBytes(hbuf); /* add raw data to to-sign data buffer */ GWEN_Buffer_AppendBuffer(hbuf, rawBuf); /* sign message */ sigbuf=GWEN_Buffer_new(0, 512, 0, 1); if (1) { uint32_t signLen; GWEN_CRYPT_PADDALGO *algo; GWEN_MDIGEST *md; uint32_t seq; /* hash sighead + data */ md=GWEN_MDigest_Rmd160_new(); rv=GWEN_MDigest_Begin(md); if (rv==0) rv=GWEN_MDigest_Update(md, (uint8_t*)GWEN_Buffer_GetStart(hbuf), GWEN_Buffer_GetUsedBytes(hbuf)); if (rv==0) rv=GWEN_MDigest_End(md); if (rv<0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Hash error (%d)", rv); GWEN_MDigest_free(md); GWEN_Buffer_free(sigbuf); GWEN_Buffer_free(hbuf); return rv; } /* sign hash */ algo=GWEN_Crypt_PaddAlgo_new(GWEN_Crypt_PaddAlgoId_Iso9796_2); GWEN_Crypt_PaddAlgo_SetPaddSize(algo, GWEN_Crypt_Token_KeyInfo_GetKeySize(ki)); signLen=GWEN_Buffer_GetMaxUnsegmentedWrite(sigbuf); rv=GWEN_Crypt_Token_Sign(ct, keyId, algo, GWEN_MDigest_GetDigestPtr(md), GWEN_MDigest_GetDigestSize(md), (uint8_t*)GWEN_Buffer_GetPosPointer(sigbuf), &signLen, &seq, gid); GWEN_Crypt_PaddAlgo_free(algo); GWEN_MDigest_free(md); if (rv) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Could not sign data with medium of user \"%s\" (%d)", AB_User_GetUserId(su), rv); GWEN_Buffer_free(sigbuf); GWEN_Buffer_free(hbuf); return rv; } GWEN_Buffer_IncrementPos(sigbuf, signLen); GWEN_Buffer_AdjustUsedBytes(sigbuf); } DBG_DEBUG(AQHBCI_LOGDOMAIN, "Signing done"); /* insert new SigHead at beginning of message buffer */ DBG_DEBUG(AQHBCI_LOGDOMAIN, "Inserting signature head"); GWEN_Buffer_Rewind(hmsg->buffer); GWEN_Buffer_InsertBytes(hmsg->buffer, GWEN_Buffer_GetStart(hbuf), l); /* create sigtail */ DBG_DEBUG(AQHBCI_LOGDOMAIN, "Completing signature tail"); cfg=GWEN_DB_Group_new("sigtail"); GWEN_Buffer_Reset(hbuf); GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "head/seq", hmsg->lastSegment+1); /* store to DB */ GWEN_DB_SetBinValue(cfg, GWEN_DB_FLAGS_DEFAULT, "signature", GWEN_Buffer_GetStart(sigbuf), GWEN_Buffer_GetUsedBytes(sigbuf)); GWEN_Buffer_free(sigbuf); GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "ctrlref", ctrlref); /* get node */ node=GWEN_MsgEngine_FindNodeByPropertyStrictProto(e, "SEG", "id", 0, "SigTail"); if (!node) { DBG_INFO(AQHBCI_LOGDOMAIN, "Segment \"SigTail\"not found"); GWEN_Buffer_free(hbuf); GWEN_DB_Group_free(cfg); return -1; } rv=GWEN_MsgEngine_CreateMessageFromNode(e, node, hbuf, cfg); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not create SigTail"); GWEN_Buffer_free(hbuf); GWEN_DB_Group_free(cfg); return -1; } /* append sigtail */ DBG_DEBUG(AQHBCI_LOGDOMAIN, "Appending signature tail"); if (GWEN_Buffer_AppendBuffer(hmsg->buffer, hbuf)) { DBG_INFO(AQHBCI_LOGDOMAIN, "here"); GWEN_Buffer_free(hbuf); GWEN_DB_Group_free(cfg); return -1; } DBG_DEBUG(AQHBCI_LOGDOMAIN, "Appending signature tail: done"); GWEN_Buffer_free(hbuf); GWEN_DB_Group_free(cfg); /* adjust segment numbers (for next signature and message tail */ hmsg->firstSegment--; hmsg->lastSegment++; return 0; }
int GWEN_Crypt_Token_PluginManager_CheckToken(GWEN_PLUGIN_MANAGER *pm, GWEN_CRYPT_TOKEN_DEVICE devt, GWEN_BUFFER *typeName, GWEN_BUFFER *tokenName, uint32_t guiid) { GWEN_PLUGIN_DESCRIPTION_LIST2 *pdl; assert(pm); pdl=GWEN_Crypt_Token_PluginManager_GetPluginDescrs(pm, devt); if (pdl==NULL) { DBG_ERROR(GWEN_LOGDOMAIN, "No plugin descriptions found for this device type"); GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Error, I18N("No plugin found for this device type")); GWEN_Gui_ProgressLog(guiid, GWEN_LoggerLevel_Error, I18N("If you're using a Debian/Ubuntu based system " "please consider to install package " LIBCHIPCARD_GWENHYWFAR_PLUGIN_PACKAGE)); return GWEN_ERROR_NOT_FOUND; } else { GWEN_PLUGIN_DESCRIPTION_LIST2_ITERATOR *pit; pit=GWEN_PluginDescription_List2_First(pdl); if (pit) { GWEN_PLUGIN_DESCRIPTION *pd; uint32_t progressId; unsigned int pdcount; unsigned int cnt=0; pdcount=GWEN_PluginDescription_List2_GetSize(pdl); progressId=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY | GWEN_GUI_PROGRESS_ALLOW_EMBED | GWEN_GUI_PROGRESS_SHOW_PROGRESS | GWEN_GUI_PROGRESS_SHOW_LOG | GWEN_GUI_PROGRESS_ALWAYS_SHOW_LOG | GWEN_GUI_PROGRESS_SHOW_ABORT, I18N("Determining plugin module..."), NULL, pdcount, guiid); pd=GWEN_PluginDescription_List2Iterator_Data(pit); assert(pd); while (pd) { GWEN_XMLNODE *n; int err; GWEN_PLUGIN *pl; char logbuffer[256]; n=GWEN_PluginDescription_GetXmlNode(pd); assert(n); snprintf(logbuffer, sizeof(logbuffer)-1, I18N("Loading plugin \"%s\""), GWEN_PluginDescription_GetName(pd)); logbuffer[sizeof(logbuffer)-1]=0; GWEN_Gui_ProgressLog(progressId, GWEN_LoggerLevel_Notice, logbuffer); /* device type matches, check this plugin */ pl=GWEN_PluginManager_GetPlugin(pm, GWEN_PluginDescription_GetName(pd)); if (pl) { GWEN_BUFFER *lTokenName; int rv; lTokenName=GWEN_Buffer_dup(tokenName); snprintf(logbuffer, sizeof(logbuffer)-1, I18N("Checking plugin \"%s\""), GWEN_Plugin_GetName(pl)); logbuffer[sizeof(logbuffer)-1]=0; GWEN_Gui_ProgressLog(progressId, GWEN_LoggerLevel_Notice, logbuffer); DBG_INFO(GWEN_LOGDOMAIN, "Checking plugin \"%s\" for [%s]", GWEN_Plugin_GetName(pl), GWEN_Buffer_GetStart(lTokenName)); rv=GWEN_Crypt_Token_Plugin_CheckToken(pl, lTokenName); switch (rv) { case 0: /* responsive plugin found */ snprintf(logbuffer, sizeof(logbuffer)-1, I18N("Plugin \"%s\" supports this token"), GWEN_Plugin_GetName(pl)); logbuffer[sizeof(logbuffer)-1]=0; err=GWEN_Gui_ProgressLog(progressId, GWEN_LoggerLevel_Notice, logbuffer); if (err==GWEN_ERROR_USER_ABORTED) { GWEN_Gui_ProgressEnd(progressId); GWEN_Buffer_free(lTokenName); GWEN_PluginDescription_List2Iterator_free(pit); GWEN_PluginDescription_List2_freeAll(pdl); return err; } GWEN_Buffer_Reset(typeName); GWEN_Buffer_AppendString(typeName, GWEN_Plugin_GetName(pl)); GWEN_Buffer_Reset(tokenName); GWEN_Buffer_AppendBuffer(tokenName, lTokenName); GWEN_Buffer_free(lTokenName); GWEN_PluginDescription_List2Iterator_free(pit); GWEN_PluginDescription_List2_freeAll(pdl); GWEN_Gui_ProgressEnd(progressId); return 0; case GWEN_ERROR_NOT_IMPLEMENTED: snprintf(logbuffer, sizeof(logbuffer)-1, I18N("Plugin \"%s\": Function not implemented"), GWEN_Plugin_GetName(pl)); logbuffer[sizeof(logbuffer)-1]=0; GWEN_Gui_ProgressLog(progressId, GWEN_LoggerLevel_Notice, logbuffer); break; case GWEN_ERROR_NOT_SUPPORTED: snprintf(logbuffer, sizeof(logbuffer)-1, I18N("Plugin \"%s\" does not support this token"), GWEN_Plugin_GetName(pl)); logbuffer[sizeof(logbuffer)-1]=0; GWEN_Gui_ProgressLog(progressId, GWEN_LoggerLevel_Info, logbuffer); break; case GWEN_ERROR_BAD_NAME: snprintf(logbuffer, sizeof(logbuffer)-1, I18N("Plugin \"%s\" supports this token, but the name " "did not match"), GWEN_Plugin_GetName(pl)); logbuffer[sizeof(logbuffer)-1]=0; GWEN_Gui_ProgressLog(progressId, GWEN_LoggerLevel_Info, logbuffer); break; default: snprintf(logbuffer, sizeof(logbuffer)-1, I18N("Plugin \"%s\": Unexpected error (%d)"), GWEN_Plugin_GetName(pl), rv); logbuffer[sizeof(logbuffer)-1]=0; GWEN_Gui_ProgressLog(progressId, GWEN_LoggerLevel_Info, logbuffer); break; } /* switch */ } /* if plugin loaded */ else { snprintf(logbuffer, sizeof(logbuffer)-1, I18N("Could not load plugin \"%s\""), GWEN_PluginDescription_GetName(pd)); logbuffer[sizeof(logbuffer)-1]=0; GWEN_Gui_ProgressLog(progressId, GWEN_LoggerLevel_Warning, logbuffer); } cnt++; err=GWEN_Gui_ProgressAdvance(progressId, cnt); if (err) { DBG_INFO(GWEN_LOGDOMAIN, "User aborted"); GWEN_Gui_ProgressEnd(progressId); GWEN_PluginDescription_List2Iterator_free(pit); GWEN_PluginDescription_List2_freeAll(pdl); GWEN_Gui_ProgressEnd(progressId); return err; } pd=GWEN_PluginDescription_List2Iterator_Next(pit); } GWEN_Gui_ProgressEnd(progressId); GWEN_PluginDescription_List2Iterator_free(pit); } GWEN_PluginDescription_List2_freeAll(pdl); } return GWEN_ERROR_NOT_SUPPORTED; }
int GWEN_XMLNode_GetXPath(const GWEN_XMLNODE *n1, const GWEN_XMLNODE *n2, GWEN_BUFFER *nbuf) { GWEN_BUFFER *lbuf; const GWEN_XMLNODE *ln1; const GWEN_XMLNODE *ln2; if (!n1 && !n2) { DBG_ERROR(GWEN_LOGDOMAIN, "Both nodes are NULL"); return -1; } if (!n1) { n1=n2; while(n1->parent) n1=n1->parent; } if (!n2) { n2=n1; while(n2->parent) n2=n2->parent; } if (n2==n1) { GWEN_Buffer_AppendString(nbuf, "here()"); return 0; } lbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_ReserveBytes(lbuf, 128); ln1=n1->parent; if (ln1) { GWEN_Buffer_AppendString(lbuf, "../"); while(ln1) { if (ln1==n2) { /* found n2 */ GWEN_Buffer_AppendBuffer(nbuf, lbuf); GWEN_Buffer_free(lbuf); return 0; } if (GWEN_XMLNode_IsChildOf(ln1, n2)) break; ln1=ln1->parent; GWEN_Buffer_AppendString(lbuf, "../"); } if (!ln1) { DBG_ERROR(GWEN_LOGDOMAIN, "Nodes do not share root node"); GWEN_Buffer_free(lbuf); return -1; } /* append path to n1 */ GWEN_Buffer_AppendBuffer(nbuf, lbuf); } DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf)); /* get path to n2 */ GWEN_Buffer_Reset(lbuf); ln2=n2; while(ln2) { GWEN_XMLNODE *tn; int idx; char idxbuf[32]; if (ln2->parent==ln1) break; /* count occurences of this tag in this level */ idx=1; tn=ln2->parent; if (tn) { tn=GWEN_XMLNode_FindFirstTag(tn, ln2->data, 0, 0); while(tn) { if (tn==ln2) break; idx++; tn=GWEN_XMLNode_FindNextTag(tn, ln2->data, 0, 0); } } snprintf(idxbuf, sizeof(idxbuf), "[%d]", idx); idxbuf[sizeof(idxbuf)-1]=0; GWEN_Buffer_InsertString(lbuf, idxbuf); GWEN_Buffer_InsertString(lbuf, GWEN_XMLNode_GetData(ln2)); GWEN_Buffer_InsertByte(lbuf, '/'); ln2=ln2->parent; } DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf)); assert(ln2); /* append path to n2 */ GWEN_Buffer_AppendBuffer(nbuf, lbuf); GWEN_Buffer_free(lbuf); return 0; }