int GWEN_Padd_PaddWithPkcs1Bt1(GWEN_BUFFER *buf, int dstSize) { unsigned int diff; char *p; if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data"); return GWEN_ERROR_INVALID; } diff=dstSize-GWEN_Buffer_GetUsedBytes(buf); if (diff<11) { /* honour minimum padding length for BT 1 of 8 bytes, plus the * leading and the trailing zero and the block type identifier */ DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too many bytes (diff is <11)"); return GWEN_ERROR_INVALID; } /* reset position to 0 */ GWEN_Buffer_Rewind(buf); if (GWEN_Buffer_InsertRoom(buf, diff)) { DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff); return GWEN_ERROR_GENERIC; } p=GWEN_Buffer_GetStart(buf); *(p++)=0x00; *(p++)=0x01; /* block type 01 */ if (diff>3) { memset(p, 0xff, diff-3); p+=diff-3; } *(p++)=0x00; return 0; }
int LC_DDVCard_GetSignKeyVersion0(LC_CARD *card){ LC_DDVCARD *ddv; LC_CLIENT_RESULT res; GWEN_DB_NODE *dbRecord; GWEN_BUFFER *mbuf; int keyVer; assert(card); ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card); assert(ddv); res=LC_Card_SelectEf(card, "EF_KEYD"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return -1; } mbuf=GWEN_Buffer_new(0, 4, 0, 1); res=LC_Card_IsoReadRecord(card, LC_CARD_ISO_FLAGS_RECSEL_GIVEN, 1 /* should be 2 */, mbuf); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); GWEN_Buffer_free(mbuf); return -1; } GWEN_Buffer_Rewind(mbuf); dbRecord=GWEN_DB_Group_new("autd"); if (LC_Card_ParseRecord(card, 1 /* should be 2, but that doesn't work */, mbuf, dbRecord)) { DBG_ERROR(LC_LOGDOMAIN, "Error parsing record"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return -1; } GWEN_Buffer_free(mbuf); keyVer=GWEN_DB_GetIntValue(dbRecord, "keyVersion", 0, -1); GWEN_DB_Group_free(dbRecord); if (keyVer==-1) { DBG_ERROR(LC_LOGDOMAIN, "No keyVersion in record 2 of EF_KEYD"); } return keyVer; }
int GWEN_Padd_PaddWithIso9796_2(GWEN_BUFFER *buf, int dstSize) { unsigned int diff; char *p; int i; if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)+12) { /*DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");*/ return GWEN_ERROR_INVALID; } /* add trailer */ GWEN_Buffer_AppendByte(buf, 0xbc); /* reset position to 0 */ GWEN_Buffer_Rewind(buf); /* insert room for header */ diff=dstSize-GWEN_Buffer_GetUsedBytes(buf)-11+1; if (GWEN_Buffer_InsertRoom(buf, 1+diff+1+8)) { DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", 1+diff+1+8); return GWEN_ERROR_GENERIC; } /* insert header and more-data-bit */ p=GWEN_Buffer_GetStart(buf); *(p++)=0x60; /* insert padding field */ for (i=0; i<diff; i++) *(p++)=0x0; *(p++)=0x01; /* insert 8 random bytes */ GWEN_Crypt_Random(2, (uint8_t*)p, 8); for (i=0; i<8; i++) { if (*p==0) /* TODO: Need to find a better but yet fast way */ *p=0xff; p++; } return 0; }
LC_CLIENT_RESULT LC_DDVCard_WriteInstituteData(LC_CARD *card, int idx, GWEN_DB_NODE *dbData){ LC_DDVCARD *ddv; LC_CLIENT_RESULT res; GWEN_BUFFER *buf; assert(card); ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card); assert(ddv); if (idx==0) { DBG_ERROR(LC_LOGDOMAIN, "Invalid index 0"); return LC_Client_ResultInvalid; } /* select EF_BNK */ res=LC_Card_SelectEf(card, "EF_BNK"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } /* create record data */ buf=GWEN_Buffer_new(0, 256, 0, 1); if (LC_Card_CreateRecord(card, idx, buf, dbData)) { DBG_ERROR(LC_LOGDOMAIN, "Error creating record %d", idx); GWEN_Buffer_free(buf); return LC_Client_ResultDataError; } GWEN_Buffer_Rewind(buf); /* write record */ res=LC_Card_IsoUpdateRecord(card, LC_CARD_ISO_FLAGS_RECSEL_GIVEN, idx, GWEN_Buffer_GetStart(buf), GWEN_Buffer_GetUsedBytes(buf)); GWEN_Buffer_free(buf); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } return LC_Client_ResultOk; }
int GWEN_Padd_PaddWithPkcs1Bt2(GWEN_BUFFER *buf, int dstSize) { unsigned int diff; char *p; int i; if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data"); return GWEN_ERROR_INVALID; } diff=dstSize-GWEN_Buffer_GetUsedBytes(buf); if (diff<11) { /* honour minimum padding length for BT 1 of 8 bytes, plus the * leading and the trailing zero and the block type identifier */ DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too many bytes (diff is <11)"); return GWEN_ERROR_INVALID; } /* reset position to 0 */ GWEN_Buffer_Rewind(buf); if (GWEN_Buffer_InsertRoom(buf, diff)) { DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff); return GWEN_ERROR_GENERIC; } p=GWEN_Buffer_GetStart(buf); *(p++)=0x00; *(p++)=0x02; /* block type 02 */ GWEN_Crypt_Random(2, (uint8_t*)p, diff-3); for (i=0; i<diff-3; i++) { if (*p==0) /* TODO: Need to find a better but yet fast way */ *p=0xff; p++; } *(p++)=0x00; return 0; }
int AH_Msg_DecryptPinTan(AH_MSG *hmsg, GWEN_DB_NODE *gr){ AH_HBCI *h; GWEN_BUFFER *mbuf; uint32_t l; const uint8_t *p; GWEN_MSGENGINE *e; AB_USER *u; const char *peerId; // uint32_t uFlags; GWEN_DB_NODE *nhead=NULL; GWEN_DB_NODE *ndata=NULL; const char *crypterId; assert(hmsg); h=AH_Dialog_GetHbci(hmsg->dialog); assert(h); e=AH_Dialog_GetMsgEngine(hmsg->dialog); assert(e); GWEN_MsgEngine_SetMode(e, "pintan"); u=AH_Dialog_GetDialogOwner(hmsg->dialog); // uFlags=AH_User_GetFlags(u); peerId=AH_User_GetPeerId(u); if (!peerId || *peerId==0) peerId=AB_User_GetUserId(u); /* get encrypted session key */ nhead=GWEN_DB_GetGroup(gr, GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_NAMEMUSTEXIST, "CryptHead"); if (!nhead) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No crypt head"); return GWEN_ERROR_BAD_DATA; } ndata=GWEN_DB_GetGroup(gr, GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_NAMEMUSTEXIST, "CryptData"); if (!ndata) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No crypt data"); return GWEN_ERROR_BAD_DATA; } crypterId=GWEN_DB_GetCharValue(nhead, "key/userId", 0, I18N("unknown")); /* get encrypted data */ p=GWEN_DB_GetBinValue(ndata, "CryptData", 0, 0,0, &l); if (!p || !l) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No crypt data"); return GWEN_ERROR_BAD_DATA; } /* decipher message with session key */ mbuf=GWEN_Buffer_new(0, l, 0, 1); GWEN_Buffer_AppendBytes(mbuf, (const char*)p, l); /* store crypter id */ AH_Msg_SetCrypterId(hmsg, crypterId); /* store new buffer inside message */ GWEN_Buffer_free(hmsg->origbuffer); hmsg->origbuffer=hmsg->buffer; GWEN_Buffer_Rewind(mbuf); hmsg->buffer=mbuf; 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; }
int logFile(AB_BANKING *ab, GWEN_DB_NODE *dbArgs, int argc, char **argv) { int rv; GWEN_DB_NODE *db; GWEN_DB_NODE *dbMessages; const char *s; GWEN_MSGENGINE *e; GWEN_SYNCIO *sioOut=NULL; GWEN_SYNCIO *sioDb=NULL; const char *inFile; const char *outFile; const char *dbOutFile; int i; GWEN_DB_NODE *dbT; int trustLevel; const GWEN_ARGS args[]={ { GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ GWEN_ArgsType_Char, /* type */ "xmlfile", /* name */ 0, /* minnum */ 99, /* maxnum */ "x", /* short option */ "xmlfile", /* long option */ "Specify XML files to load", /* short description */ "Specify XML files to load" /* long description */ }, { GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ GWEN_ArgsType_Char, /* type */ "infile", /* name */ 1, /* minnum */ 1, /* maxnum */ "i", /* short option */ "infile", /* long option */ "Specify input file", /* short description */ "Specify input file" /* long description */ }, { GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ GWEN_ArgsType_Char, /* type */ "outfile", /* name */ 0, /* minnum */ 1, /* maxnum */ "o", /* short option */ "outfile", /* long option */ "Specify output file", /* short description */ "Specify output file" /* long description */ }, { GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ GWEN_ArgsType_Char, /* type */ "dboutfile", /* name */ 0, /* minnum */ 1, /* maxnum */ "d", /* short option */ "dbfile", /* long option */ "Specify DB output file", /* short description */ "Specify DB output file" /* long description */ }, { GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ GWEN_ArgsType_Int, /* type */ "trustLevel", /* name */ 0, /* minnum */ 1, /* maxnum */ "L", /* short option */ "trustlevel", /* long option */ "Specify the trust level", /* short description */ "Specify the trust level" /* long description */ }, { GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST, /* flags */ GWEN_ArgsType_Int, /* type */ "help", /* name */ 0, /* minnum */ 0, /* maxnum */ "h", /* short option */ "help", /* long option */ "Show this help screen", /* short description */ "Show this help screen" /* long description */ } }; db=GWEN_DB_GetGroup(dbArgs, GWEN_DB_FLAGS_DEFAULT, "local"); rv=GWEN_Args_Check(argc, argv, 1, 0 /*GWEN_ARGS_MODE_ALLOW_FREEPARAM*/, args, db); if (rv==GWEN_ARGS_RESULT_ERROR) { fprintf(stderr, "ERROR: Could not parse arguments\n"); return 1; } else if (rv==GWEN_ARGS_RESULT_HELP) { GWEN_BUFFER *ubuf; ubuf=GWEN_Buffer_new(0, 1024, 0, 1); if (GWEN_Args_Usage(args, ubuf, GWEN_ArgsOutType_Txt)) { fprintf(stderr, "ERROR: Could not create help string\n"); return 1; } fprintf(stderr, "%s\n", GWEN_Buffer_GetStart(ubuf)); GWEN_Buffer_free(ubuf); return 0; } trustLevel=GWEN_DB_GetIntValue(db, "trustLevel", 0, 0); outFile=GWEN_DB_GetCharValue(db, "outFile", 0, NULL); dbOutFile=GWEN_DB_GetCharValue(db, "dbOutFile", 0, NULL); inFile=GWEN_DB_GetCharValue(db, "inFile", 0, NULL); assert(inFile); /* do it */ dbMessages=GWEN_DB_Group_new("Messages"); rv=_readLogFile(inFile, dbMessages); if (rv<0) { DBG_ERROR(0, "Error reading message (%d)", rv); return 2; } /* create message engine, read XML definitions */ e=AH_MsgEngine_new(); for (i=0; i<99; i++) { s=GWEN_DB_GetCharValue(dbArgs, "xmlfile", i, NULL); if (s && *s) { GWEN_XMLNODE *defs; defs=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "defs"); if (GWEN_XML_ReadFile(defs, s, GWEN_XML_FLAGS_DEFAULT)){ fprintf(stderr, "Error parsing.\n"); GWEN_MsgEngine_free(e); return 2; } GWEN_MsgEngine_AddDefinitions(e, defs); GWEN_XMLNode_free(defs); } else { if (i==0) { GWEN_XMLNODE *defs; defs=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "defs"); if (GWEN_XML_ReadFile(defs, XMLDATA_DIR "/hbci.xml", GWEN_XML_FLAGS_DEFAULT)){ fprintf(stderr, "Error parsing.\n"); GWEN_MsgEngine_free(e); return 2; } GWEN_MsgEngine_AddDefinitions(e, defs); GWEN_XMLNode_free(defs); } break; } } if (outFile) { sioOut=GWEN_SyncIo_File_new(outFile, GWEN_SyncIo_File_CreationMode_CreateAlways); GWEN_SyncIo_AddFlags(sioOut, GWEN_SYNCIO_FILE_FLAGS_READ | GWEN_SYNCIO_FILE_FLAGS_WRITE | GWEN_SYNCIO_FILE_FLAGS_UREAD | GWEN_SYNCIO_FILE_FLAGS_UWRITE | GWEN_SYNCIO_FILE_FLAGS_APPEND); rv=GWEN_SyncIo_Connect(sioOut); if (rv<0) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); GWEN_SyncIo_free(sioOut); return 2; } } if (dbOutFile) { sioDb=GWEN_SyncIo_File_new(dbOutFile, GWEN_SyncIo_File_CreationMode_CreateAlways); GWEN_SyncIo_AddFlags(sioDb, GWEN_SYNCIO_FILE_FLAGS_READ | GWEN_SYNCIO_FILE_FLAGS_WRITE | GWEN_SYNCIO_FILE_FLAGS_UREAD | GWEN_SYNCIO_FILE_FLAGS_UWRITE | GWEN_SYNCIO_FILE_FLAGS_APPEND); rv=GWEN_SyncIo_Connect(sioDb); if (rv<0) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); GWEN_SyncIo_free(sioDb); return 2; } } dbT=GWEN_DB_GetFirstGroup(dbMessages); while(dbT) { const uint8_t *p; uint32_t len; GWEN_DB_NODE *dbHeader; dbHeader=GWEN_DB_GetGroup(dbT, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "header"); assert(dbHeader); s=GWEN_DB_GetCharValue(dbHeader, "mode", 0, "PINTAN"); GWEN_MsgEngine_SetMode(e, s); i=GWEN_DB_GetIntValue(dbHeader, "hbciVersion", 0, 220); GWEN_MsgEngine_SetProtocolVersion(e, i); p=GWEN_DB_GetBinValue(dbT, "body", 0, NULL, 0, &len); if (p && len) { GWEN_BUFFER *tbuf; GWEN_DB_NODE *gr; GWEN_MSGENGINE_TRUSTEDDATA *trustedData; GWEN_MSGENGINE_TRUSTEDDATA *ntd; GWEN_DB_NODE *repl; gr=GWEN_DB_Group_new("message"); tbuf=GWEN_Buffer_new((char*) p, len, len, 0); rv=GWEN_MsgEngine_ReadMessage(e, "SEG", tbuf, gr, GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO); if (rv) { fprintf(stderr, "ERROR.\n"); GWEN_Buffer_Dump(tbuf, 2); return 2; } /* work on trust data */ trustedData=GWEN_MsgEngine_TakeTrustInfo(e); if (trustedData) { if (GWEN_MsgEngine_TrustedData_CreateReplacements(trustedData)) { fprintf(stderr, "Could not anonymize log (createReplacements)\n"); GWEN_MsgEngine_TrustedData_free(trustedData); GWEN_MsgEngine_free(e); return 2; } } /* anonymize file */ ntd=trustedData; repl=GWEN_DB_GetGroup(dbHeader, GWEN_DB_FLAGS_OVERWRITE_GROUPS, "replacements"); assert(repl); while(ntd) { if (GWEN_MsgEngine_TrustedData_GetTrustLevel(ntd)>trustLevel) { int pos; unsigned int size; char rbuffer[3]; const char *rpstr; rpstr=GWEN_MsgEngine_TrustedData_GetReplacement(ntd); assert(rpstr); assert(*rpstr); size=strlen(rpstr); if (size==1) { rbuffer[0]=rpstr[0]; rbuffer[1]=0; } else { rbuffer[0]=rpstr[0]; rbuffer[1]=rpstr[1]; rbuffer[2]=0; } GWEN_DB_SetCharValue(repl, GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_CREATE_VAR, rbuffer, GWEN_MsgEngine_TrustedData_GetDescription(ntd)); size=GWEN_MsgEngine_TrustedData_GetSize(ntd); pos=GWEN_MsgEngine_TrustedData_GetFirstPos(ntd); while(pos>=0) { DBG_INFO(0, "Replacing %d bytes at %d", size, pos); GWEN_Buffer_SetPos(tbuf, pos); GWEN_Buffer_ReplaceBytes(tbuf, size, GWEN_MsgEngine_TrustedData_GetReplacement(ntd), size); pos=GWEN_MsgEngine_TrustedData_GetNextPos(ntd); } // while pos } ntd=GWEN_MsgEngine_TrustedData_GetNext(ntd); } // while ntd GWEN_DB_SetIntValue(dbHeader, GWEN_DB_FLAGS_OVERWRITE_VARS, "size", GWEN_Buffer_GetUsedBytes(tbuf)); if (outFile) { rv=dumpMsg(sioOut, dbHeader, (const uint8_t*)GWEN_Buffer_GetStart(tbuf), GWEN_Buffer_GetUsedBytes(tbuf)); if (rv<0) { fprintf(stderr, "Could not anonymize log (dumpMsg)\n"); GWEN_MsgEngine_TrustedData_free(trustedData); GWEN_MsgEngine_free(e); return 2; } } if (dbOutFile) { GWEN_BUFFER *xbuf; GWEN_DB_NODE *dbOut; xbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(xbuf, "# ========== Message ( "); s=GWEN_DB_GetCharValue(dbHeader, "sender", 0, "UNK"); if (s && *s) { GWEN_Buffer_AppendString(xbuf, "sender="); GWEN_Buffer_AppendString(xbuf, s); GWEN_Buffer_AppendString(xbuf, " "); } s=GWEN_DB_GetCharValue(dbHeader, "crypt", 0, "UNK"); if (s && *s) { GWEN_Buffer_AppendString(xbuf, "crypt="); GWEN_Buffer_AppendString(xbuf, s); GWEN_Buffer_AppendString(xbuf, " "); } GWEN_Buffer_AppendString(xbuf, ") ==========\n"); dbOut=GWEN_DB_Group_new("Message"); GWEN_Buffer_Rewind(tbuf); rv=GWEN_MsgEngine_ReadMessage(e, "SEG", tbuf, dbOut, 0); if (rv) { fprintf(stderr, "ERROR.\n"); GWEN_Buffer_Dump(tbuf, 2); return 2; } rv=GWEN_SyncIo_WriteForced(sioDb, (const uint8_t*) GWEN_Buffer_GetStart(xbuf), GWEN_Buffer_GetUsedBytes(xbuf)); GWEN_Buffer_free(xbuf); if (rv<0) { DBG_INFO(0, "here (%d)", rv); return rv; } rv=GWEN_DB_WriteToIo(dbOut, sioDb, GWEN_DB_FLAGS_DEFAULT); if (rv<0) { DBG_INFO(0, "here (%d)", rv); return 2; } /* append empty line to separate header from data */ rv=GWEN_SyncIo_WriteForced(sioDb, (const uint8_t*) "\n", 1); if (rv<0) { DBG_INFO(0, "here (%d)", rv); return rv; } } GWEN_Buffer_free(tbuf); } dbT=GWEN_DB_GetNextGroup(dbT); } /* close output layer */ if (outFile) { rv=GWEN_SyncIo_Disconnect(sioOut); if (rv<0) { DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv); GWEN_SyncIo_free(sioOut); return 2; } GWEN_SyncIo_free(sioOut); } if (dbOutFile) { rv=GWEN_SyncIo_Disconnect(sioDb); if (rv<0) { DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv); GWEN_SyncIo_free(sioDb); return 2; } GWEN_SyncIo_free(sioDb); } return 0; }
/* --------------------------------------------------------------- FUNCTION */ int AH_Job_GetTransactions_Process(AH_JOB *j, AB_IMEXPORTER_CONTEXT *ctx) { AH_JOB_GETTRANSACTIONS *aj; AB_ACCOUNT *a; AB_IMEXPORTER_ACCOUNTINFO *ai; GWEN_DB_NODE *dbResponses; GWEN_DB_NODE *dbCurr; GWEN_BUFFER *tbooked; GWEN_BUFFER *tnoted; int rv; DBG_INFO(AQHBCI_LOGDOMAIN, "Processing JobGetTransactions"); assert(j); aj=GWEN_INHERIT_GETDATA(AH_JOB, AH_JOB_GETTRANSACTIONS, j); assert(aj); tbooked=GWEN_Buffer_new(0, 1024, 0, 1); tnoted=GWEN_Buffer_new(0, 1024, 0, 1); dbResponses=AH_Job_GetResponses(j); assert(dbResponses); /* search for "Transactions" */ dbCurr=GWEN_DB_GetFirstGroup(dbResponses); while (dbCurr) { GWEN_DB_NODE *dbXA; rv=AH_Job_CheckEncryption(j, dbCurr); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Compromised security (encryption)"); GWEN_Buffer_free(tbooked); GWEN_Buffer_free(tnoted); AH_Job_SetStatus(j, AH_JobStatusError); return rv; } rv=AH_Job_CheckSignature(j, dbCurr); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Compromised security (signature)"); GWEN_Buffer_free(tbooked); GWEN_Buffer_free(tnoted); AH_Job_SetStatus(j, AH_JobStatusError); return rv; } dbXA=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "data/transactions"); if (dbXA) { const void *p; unsigned int bs; if (GWEN_Logger_GetLevel(0)>=GWEN_LoggerLevel_Debug) GWEN_DB_Dump(dbXA, 2); p=GWEN_DB_GetBinValue(dbXA, "booked", 0, 0, 0, &bs); if (p && bs) GWEN_Buffer_AppendBytes(tbooked, p, bs); p=GWEN_DB_GetBinValue(dbXA, "noted", 0, 0, 0, &bs); if (p && bs) GWEN_Buffer_AppendBytes(tnoted, p, bs); } /* if "Transactions" */ dbCurr=GWEN_DB_GetNextGroup(dbCurr); } GWEN_Buffer_Rewind(tbooked); GWEN_Buffer_Rewind(tnoted); /* now the buffers contain data to be parsed by DBIOs */ a=AH_AccountJob_GetAccount(j); assert(a); ai=AB_ImExporterContext_GetOrAddAccountInfo(ctx, AB_Account_GetUniqueId(a), AB_Account_GetIban(a), AB_Account_GetBankCode(a), AB_Account_GetAccountNumber(a), AB_Account_GetAccountType(a)); assert(ai); /* read booked transactions */ if (GWEN_Buffer_GetUsedBytes(tbooked)) { if (getenv("AQHBCI_LOGBOOKED")) { FILE *f; f=fopen("/tmp/booked.mt", "w+"); if (f) { if (fwrite(GWEN_Buffer_GetStart(tbooked), GWEN_Buffer_GetUsedBytes(tbooked), 1, f)!=1) { DBG_ERROR(AQHBCI_LOGDOMAIN, "fwrite: %s", strerror(errno)); } if (fclose(f)) { DBG_ERROR(AQHBCI_LOGDOMAIN, "fclose: %s", strerror(errno)); } } } if (AH_Job_GetTransactions__ReadTransactions(j, ai, "SWIFT-MT940", AB_Transaction_TypeStatement, (const uint8_t *) GWEN_Buffer_GetStart(tbooked), GWEN_Buffer_GetUsedBytes(tbooked))) { GWEN_Buffer_free(tbooked); GWEN_Buffer_free(tnoted); DBG_INFO(AQHBCI_LOGDOMAIN, "Error parsing booked transactions"); AH_Job_SetStatus(j, AH_JobStatusError); return -1; } } /* read noted transactions */ if (GWEN_Buffer_GetUsedBytes(tnoted)) { if (getenv("AQHBCI_LOGNOTED")) { FILE *f; f=fopen("/tmp/noted.mt", "w+"); if (f) { if (fwrite(GWEN_Buffer_GetStart(tnoted), GWEN_Buffer_GetUsedBytes(tnoted), 1, f)!=1) { DBG_ERROR(AQHBCI_LOGDOMAIN, "fwrite: %s", strerror(errno)); } if (fclose(f)) { DBG_ERROR(AQHBCI_LOGDOMAIN, "fclose: %s", strerror(errno)); } } } if (AH_Job_GetTransactions__ReadTransactions(j, ai, "SWIFT-MT942", AB_Transaction_TypeNotedStatement, (const uint8_t *) GWEN_Buffer_GetStart(tnoted), GWEN_Buffer_GetUsedBytes(tnoted))) { GWEN_Buffer_free(tbooked); GWEN_Buffer_free(tnoted); DBG_INFO(AQHBCI_LOGDOMAIN, "Error parsing noted transactions"); AH_Job_SetStatus(j, AH_JobStatusError); return -1; } } if (GWEN_Logger_GetLevel(AQHBCI_LOGDOMAIN)>=GWEN_LoggerLevel_Debug) { GWEN_DB_NODE *gn; AB_TRANSACTION *ttmp; DBG_INFO(AQHBCI_LOGDOMAIN, "*** Dumping transactions *******************"); ttmp=AB_ImExporterAccountInfo_GetFirstTransaction(ai, 0, 0); while (ttmp) { DBG_INFO(AQHBCI_LOGDOMAIN, "*** --------------------------------------"); gn=GWEN_DB_Group_new("transaction"); AB_Transaction_toDb(ttmp, gn); GWEN_DB_Dump(gn, 2); GWEN_DB_Group_free(gn); ttmp=AB_Transaction_List_Next(ttmp); } DBG_INFO(AQHBCI_LOGDOMAIN, "*** End dumping transactions ***************"); } GWEN_Buffer_free(tbooked); GWEN_Buffer_free(tnoted); return 0; }
int AH_Msg_DecryptRdh2(AH_MSG *hmsg, GWEN_DB_NODE *gr){ AH_HBCI *h; GWEN_BUFFER *mbuf; uint32_t l; int rv; const uint8_t *p; GWEN_MSGENGINE *e; AB_USER *u; const char *peerId; // uint32_t uFlags; GWEN_CRYPT_TOKEN *ct; const GWEN_CRYPT_TOKEN_CONTEXT *ctx; const GWEN_CRYPT_TOKEN_KEYINFO *ki; uint32_t keyId; GWEN_CRYPT_KEY *sk=NULL; uint8_t decKey[300]; GWEN_DB_NODE *nhead=NULL; GWEN_DB_NODE *ndata=NULL; const char *crypterId; 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; u=AH_Dialog_GetDialogOwner(hmsg->dialog); // uFlags=AH_User_GetFlags(u); peerId=AH_User_GetPeerId(u); if (!peerId || *peerId==0) peerId=AB_User_GetUserId(u); /* get crypt token of signer */ rv=AB_Banking_GetCryptToken(AH_HBCI_GetBankingApi(h), AH_User_GetTokenType(u), AH_User_GetTokenName(u), &ct); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not get crypt token for user \"%s\" (%d)", AB_User_GetUserId(u), 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(u), rv); return rv; } } /* get context and key info */ ctx=GWEN_Crypt_Token_GetContext(ct, AH_User_GetTokenContextId(u), gid); if (ctx==NULL) { DBG_INFO(AQHBCI_LOGDOMAIN, "Context %d not found on crypt token [%s:%s]", AH_User_GetTokenContextId(u), GWEN_Crypt_Token_GetTypeName(ct), GWEN_Crypt_Token_GetTokenName(ct)); return GWEN_ERROR_NOT_FOUND; } keyId=GWEN_Crypt_Token_Context_GetDecipherKeyId(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; } /* get encrypted session key */ nhead=GWEN_DB_GetGroup(gr, GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_NAMEMUSTEXIST, "CryptHead"); if (!nhead) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No crypt head"); return GWEN_ERROR_BAD_DATA; } ndata=GWEN_DB_GetGroup(gr, GWEN_DB_FLAGS_DEFAULT | GWEN_PATH_FLAGS_NAMEMUSTEXIST, "CryptData"); if (!ndata) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No crypt data"); return GWEN_ERROR_BAD_DATA; } crypterId=GWEN_DB_GetCharValue(nhead, "key/userId", 0, I18N("unknown")); p=GWEN_DB_GetBinValue(nhead, "CryptAlgo/MsgKey", 0, 0,0, &l); if (p && l) { uint32_t elen; GWEN_CRYPT_PADDALGO *algo; uint8_t encKey[300]; int ksize; ksize=GWEN_Crypt_Token_KeyInfo_GetKeySize(ki); if (ksize<l) { DBG_WARN(AQHBCI_LOGDOMAIN, "Keyinfo keysize is smaller than size of transmitted key, adjusting"); ksize=l; } assert(ksize<=256); /* fill encoded key with 0 */ memset(encKey, 0, sizeof(encKey)); memmove(encKey+(ksize-l), p, l); algo=GWEN_Crypt_PaddAlgo_new(GWEN_Crypt_PaddAlgoId_None); elen=sizeof(decKey); rv=GWEN_Crypt_Token_Decipher(ct, keyId, algo, encKey, ksize, decKey, &elen, gid); GWEN_Crypt_PaddAlgo_free(algo); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv); return rv; } /* unpadd key (take right-handed 16 bytes) */ p=decKey+(elen-16); sk=GWEN_Crypt_KeyDes3K_fromData(GWEN_Crypt_CryptMode_Cbc, 24, p, 16); if (sk==NULL) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Could not create DES key from data"); return GWEN_ERROR_BAD_DATA; } } else { DBG_ERROR(AQHBCI_LOGDOMAIN, "Missing message key"); return GWEN_ERROR_BAD_DATA; } /* get encrypted data */ p=GWEN_DB_GetBinValue(ndata, "CryptData", 0, 0,0, &l); if (!p || !l) { DBG_ERROR(AQHBCI_LOGDOMAIN, "No crypt data"); GWEN_Crypt_Key_free(sk); return GWEN_ERROR_BAD_DATA; } /* decipher message with session key */ mbuf=GWEN_Buffer_new(0, l, 0, 1); rv=GWEN_Crypt_Key_Decipher(sk, (const uint8_t*)p, l, (uint8_t*)GWEN_Buffer_GetPosPointer(mbuf), &l); GWEN_Crypt_Key_free(sk); if (rv<0) { DBG_INFO(AQHBCI_LOGDOMAIN, "Could not decipher with DES session key (%d)", rv); GWEN_Buffer_free(mbuf); return rv; } GWEN_Buffer_IncrementPos(mbuf, l); GWEN_Buffer_AdjustUsedBytes(mbuf); /* unpadd message */ rv=GWEN_Padd_UnpaddWithAnsiX9_23(mbuf); if (rv) { DBG_INFO(AQHBCI_LOGDOMAIN, "Error unpadding message with ANSI X9.23 (%d)", rv); GWEN_Buffer_free(mbuf); return rv; } /* store crypter id */ AH_Msg_SetCrypterId(hmsg, crypterId); /* store new buffer inside message */ GWEN_Buffer_free(hmsg->origbuffer); hmsg->origbuffer=hmsg->buffer; GWEN_Buffer_Rewind(mbuf); hmsg->buffer=mbuf; 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 testPcsc9(int argc, char **argv) { LC_CLIENT *cl; LC_CLIENT_RESULT res; LC_CARD *card; GWEN_BUFFER *mbuf; LC_PININFO *pi; int triesLeft=-1; fprintf(stderr, "\n"); fprintf(stderr, "====================================================\n"); fprintf(stderr, "I This test will verify the PIN of the card and I\n"); fprintf(stderr, "I dump the first bank information I\n"); fprintf(stderr, "====================================================\n"); fprintf(stderr, "\n"); cl=LC_Client_new("test", "0.1"); if (!cl) { fprintf(stderr, "ERROR: Could not create client.\n"); return 1; } res=LC_Client_Init(cl); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Could not init client (%d).\n", res); return 2; } res=LC_Client_Start(cl); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Could not start using cards (%d).\n", res); return 2; } res=LC_Client_GetNextCard(cl, &card, 20); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: No card found (%d).\n", res); return 2; } fprintf(stderr, "Got this card:\n"); LC_Card_Dump(card, 2); if (LC_ZkaCard_ExtendCard(card)) { fprintf(stderr, "ERROR: Could not extend card as ZKA card\n"); return 2; } fprintf(stderr, "INFO: Opening card\n"); res=LC_Card_Open(card); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Unable to open card (%d).\n", res); return 2; } fprintf(stderr, "Response was %d\n", res); fprintf(stderr, "Selecting MF...\n"); res=LC_Card_SelectMf(card); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Wait timed out.\n"); return 2; } fprintf(stderr, "Response was %d\n", res); fprintf(stderr, "Selecting DF_NOTEPAD...\n"); res=LC_Card_SelectDf(card, "DF_NOTEPAD"); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Wait timed out.\n"); return 2; } fprintf(stderr, "Response was %d\n", res); pi=LC_Card_GetPinInfoByName(card, "ch_pin"); if (pi==NULL) { fprintf(stderr, "ERROR: Pin Info not found.\n"); return 2; } #if 0 if (pi) { GWEN_DB_NODE *dbDEBUG; dbDEBUG=GWEN_DB_Group_new("PinInfo"); LC_PinInfo_toDb(pi, dbDEBUG); GWEN_DB_Dump(dbDEBUG, 2); GWEN_DB_Group_free(dbDEBUG); } #endif fprintf(stderr, "Verifying pin...\n"); res=LC_Card_IsoPerformVerification(card, 0, pi, &triesLeft); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Wait timed out.\n"); return 2; } fprintf(stderr, "Response was %d\n", res); fprintf(stderr, "Selecting EF_NOTEPAD...\n"); res=LC_Card_SelectEf(card, "EF_NOTEPAD"); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Wait timed out.\n"); return 2; } fprintf(stderr, "Response was %d\n", res); fprintf(stderr, "Reading record...\n"); mbuf=GWEN_Buffer_new(0, 256, 0, 1); res=LC_Card_IsoReadRecord(card, LC_CARD_ISO_FLAGS_RECSEL_GIVEN, 1, mbuf); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Wait timed out.\n"); return 2; } fprintf(stderr, "Response was %d\n", res); GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf), 2); GWEN_Buffer_Rewind(mbuf); #if 0 dbRecord=GWEN_DB_Group_new("record"); if (LC_Card_ParseRecord(card, 1, mbuf, dbRecord)) { fprintf(stderr, "Error parsing record.\n"); } else { fprintf(stderr, "Parsed record is:\n"); GWEN_DB_Dump(dbRecord, 2); } GWEN_Buffer_Reset(mbuf); if (LC_Card_CreateRecord(card, 1, mbuf, dbRecord)) { fprintf(stderr, "Error creating record.\n"); } else { fprintf(stderr, "Created record is:\n"); GWEN_Buffer_Dump(mbuf, 2); } #endif res=LC_Client_ReleaseCard(cl, card); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Unable to release card (%d).\n", res); return 2; } LC_Card_free(card); res=LC_Client_Stop(cl); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Could not stop using cards (%d).\n", res); return 2; } res=LC_Client_Fini(cl); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Could not fini client (%d).\n", res); return 2; } return 0; }
int testPcsc6(int argc, char **argv) { LC_CLIENT *cl; LC_CLIENT_RESULT res; LC_CARD *card; GWEN_BUFFER *mbuf; GWEN_DB_NODE *dbRecord; cl=LC_Client_new("test", "0.1"); if (!cl) { fprintf(stderr, "ERROR: Could not create client.\n"); return 1; } res=LC_Client_Init(cl); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Could not init client (%d).\n", res); return 2; } res=LC_Client_Start(cl); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Could not start using cards (%d).\n", res); return 2; } res=LC_Client_GetNextCard(cl, &card, 20); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: No card found (%d).\n", res); return 2; } fprintf(stderr, "Got this card:\n"); LC_Card_Dump(card, 2); if (LC_DDVCard_ExtendCard(card)) { fprintf(stderr, "ERROR: Could not extend card as DDV card\n"); return 2; } fprintf(stderr, "INFO: Opening card\n"); res=LC_Card_Open(card); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Unable to open card (%d).\n", res); return 2; } fprintf(stderr, "Response was %d\n", res); fprintf(stderr, "Selecting EF...\n"); res=LC_Card_SelectEf(card, "EF_BNK"); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Wait timed out.\n"); return 2; } fprintf(stderr, "Response was %d\n", res); fprintf(stderr, "Reading record...\n"); mbuf=GWEN_Buffer_new(0, 256, 0, 1); res=LC_Card_IsoReadRecord(card, LC_CARD_ISO_FLAGS_RECSEL_GIVEN, 1, mbuf); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Wait timed out.\n"); return 2; } fprintf(stderr, "Response was %d\n", res); GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf), 2); GWEN_Buffer_Rewind(mbuf); dbRecord=GWEN_DB_Group_new("record"); if (LC_Card_ParseRecord(card, 1, mbuf, dbRecord)) { fprintf(stderr, "Error parsing record.\n"); } else { fprintf(stderr, "Parsed record is:\n"); GWEN_DB_Dump(dbRecord, 2); } GWEN_Buffer_Reset(mbuf); if (LC_Card_CreateRecord(card, 1, mbuf, dbRecord)) { fprintf(stderr, "Error creating record.\n"); } else { fprintf(stderr, "Created record is:\n"); GWEN_Buffer_Dump(mbuf, 2); } res=LC_Client_ReleaseCard(cl, card); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Unable to release card (%d).\n", res); return 2; } LC_Card_free(card); res=LC_Client_Stop(cl); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Could not stop using cards (%d).\n", res); return 2; } res=LC_Client_Fini(cl); if (res!=LC_Client_ResultOk) { fprintf(stderr, "ERROR: Could not fini client (%d).\n", res); return 2; } return 0; }
/* --------------------------------------------------------------- FUNCTION */ int AH_Job_GetTransactions__ReadTransactions(AH_JOB *j, AB_IMEXPORTER_ACCOUNTINFO *ai, const char *docType, int noted, GWEN_BUFFER *buf){ GWEN_DBIO *dbio; GWEN_SYNCIO *sio; int rv; GWEN_DB_NODE *db; GWEN_DB_NODE *dbDay; GWEN_DB_NODE *dbParams; AB_ACCOUNT *a; AB_USER *u; uint32_t progressId; uint64_t cnt=0; a=AH_AccountJob_GetAccount(j); assert(a); u=AH_Job_GetUser(j); assert(u); dbio=GWEN_DBIO_GetPlugin("swift"); if (!dbio) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Plugin SWIFT is not found"); GWEN_Gui_ProgressLog(0, GWEN_LoggerLevel_Error, I18N("Plugin \"SWIFT\" not found.")); return AB_ERROR_PLUGIN_MISSING; } GWEN_Buffer_Rewind(buf); sio=GWEN_SyncIo_Memory_new(buf, 0); db=GWEN_DB_Group_new("transactions"); dbParams=GWEN_DB_Group_new("params"); GWEN_DB_SetCharValue(dbParams, GWEN_DB_FLAGS_OVERWRITE_VARS, "type", docType); if (AH_User_GetFlags(u) & AH_USER_FLAGS_KEEP_MULTIPLE_BLANKS) GWEN_DB_SetIntValue(dbParams, GWEN_DB_FLAGS_OVERWRITE_VARS, "keepMultipleBlanks", 1); else GWEN_DB_SetIntValue(dbParams, GWEN_DB_FLAGS_OVERWRITE_VARS, "keepMultipleBlanks", 0); rv=GWEN_DBIO_Import(dbio, sio, db, dbParams, GWEN_PATH_FLAGS_CREATE_GROUP); if (rv<0) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Error parsing SWIFT %s (%d)", docType, rv); GWEN_DB_Group_free(dbParams); GWEN_DB_Group_free(db); GWEN_SyncIo_free(sio); GWEN_DBIO_free(dbio); return rv; } GWEN_DB_Group_free(dbParams); GWEN_SyncIo_free(sio); GWEN_DBIO_free(dbio); /* first count the groups */ dbDay=GWEN_DB_FindFirstGroup(db, "day"); while(dbDay) { GWEN_DB_NODE *dbT; dbT=GWEN_DB_FindFirstGroup(dbDay, "transaction"); while(dbT) { cnt++; dbT=GWEN_DB_FindNextGroup(dbT, "transaction"); } /* while */ dbDay=GWEN_DB_FindNextGroup(dbDay, "day"); } /* while */ progressId=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY | GWEN_GUI_PROGRESS_ALLOW_EMBED | GWEN_GUI_PROGRESS_SHOW_PROGRESS | GWEN_GUI_PROGRESS_SHOW_ABORT, I18N("Importing transactions..."), NULL, cnt, 0); /* add transactions to list */ dbDay=GWEN_DB_FindFirstGroup(db, "day"); while(dbDay) { GWEN_DB_NODE *dbT; dbT=GWEN_DB_FindFirstGroup(dbDay, "transaction"); while(dbT) { AB_TRANSACTION *t; t=AB_Transaction_fromDb(dbT); if (!t) { DBG_ERROR(AQHBCI_LOGDOMAIN, "Bad transaction data:"); GWEN_DB_Dump(dbT, 2); } else { const char *s; AB_Transaction_SetLocalBankCode(t, AB_User_GetBankCode(u)); AB_Transaction_SetLocalAccountNumber(t, AB_Account_GetAccountNumber(a)); /* some translations */ s=AB_Transaction_GetRemoteIban(t); if (!(s && *s)) { const char *sAid; /* no remote IBAN set, check whether the bank sends this info in the * fields for national account specifications (instead of the SWIFT * field "?38" which was specified for this case) */ sAid=AB_Transaction_GetRemoteAccountNumber(t); if (sAid && *sAid && AB_Banking_CheckIban(sAid)==0) { /* there is a remote account number specification, and that is an IBAN, * so we set that accordingly */ DBG_INFO(AQBANKING_LOGDOMAIN, "Setting remote IBAN from account number"); AB_Transaction_SetRemoteIban(t, sAid); /* set remote BIC if it not already is */ s=AB_Transaction_GetRemoteBic(t); if (!(s && *s)) { const char *sBid; sBid=AB_Transaction_GetRemoteBankCode(t); if (sBid && *sBid) { DBG_INFO(AQBANKING_LOGDOMAIN, "Setting remote BIC from bank code"); AB_Transaction_SetRemoteBic(t, sBid); } } } } DBG_INFO(AQHBCI_LOGDOMAIN, "Adding transaction"); if (noted) AB_ImExporterAccountInfo_AddNotedTransaction(ai, t); else AB_ImExporterAccountInfo_AddTransaction(ai, t); } if (GWEN_ERROR_USER_ABORTED== GWEN_Gui_ProgressAdvance(progressId, GWEN_GUI_PROGRESS_ONE)) { GWEN_Gui_ProgressEnd(progressId); return GWEN_ERROR_USER_ABORTED; } dbT=GWEN_DB_FindNextGroup(dbT, "transaction"); } /* while */ /* read all endsaldos */ if (!noted) { dbT=GWEN_DB_FindFirstGroup(dbDay, "endSaldo"); while (dbT) { GWEN_DB_NODE *dbX; GWEN_TIME *ti=0; dbX=GWEN_DB_GetGroup(dbT, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "date"); if (dbX) ti=GWEN_Time_fromDb(dbX); dbX=GWEN_DB_GetGroup(dbT, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "value"); if (dbX) { AB_VALUE *v; v=AB_Value_fromDb(dbX); if (v) { AB_BALANCE *bal; AB_ACCOUNT_STATUS *as; bal=AB_Balance_new(v, ti); AB_Value_free(v); as=AB_AccountStatus_new(); if (ti) AB_AccountStatus_SetTime(as, ti); AB_AccountStatus_SetNotedBalance(as, bal); AB_Balance_free(bal); AB_ImExporterAccountInfo_AddAccountStatus(ai, as); } } GWEN_Time_free(ti); dbT=GWEN_DB_FindNextGroup(dbT, "endSaldo"); } /* while */ } dbDay=GWEN_DB_FindNextGroup(dbDay, "day"); } /* while */ GWEN_Gui_ProgressEnd(progressId); GWEN_DB_Group_free(db); return 0; }
LC_CLIENT_RESULT LC_DDVCard_ReadInstituteData(LC_CARD *card, int idx, GWEN_DB_NODE *dbData){ LC_DDVCARD *ddv; LC_CLIENT_RESULT res; GWEN_DB_NODE *dbCurr; int i; unsigned int ctxCount; GWEN_BUFFER *buf; assert(card); ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card); assert(ddv); res=LC_Card_SelectEf(card, "EF_BNK"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } ctxCount=0; buf=GWEN_Buffer_new(0, 256, 0, 1); for (i=1; i<6; i++) { GWEN_Buffer_Reset(buf); res=LC_Card_IsoReadRecord(card, LC_CARD_ISO_FLAGS_RECSEL_GIVEN, idx?idx:i, buf); if (res!=LC_Client_ResultOk) break; dbCurr=GWEN_DB_Group_new("context"); GWEN_Buffer_Rewind(buf); if (LC_Card_ParseRecord(card, idx?idx:i, buf, dbCurr)) { DBG_ERROR(LC_LOGDOMAIN, "Error parsing record %d", idx?idx:i); GWEN_DB_Group_free(dbCurr); } else { const char *p1; p1=GWEN_DB_GetCharValue(dbCurr, "bankCode", 0, ""); if (p1) { char *p2; char *p3; p2=strdup(p1); while ( (p3=strchr(p2, '=')) ) { *p3='2'; } GWEN_DB_SetCharValue(dbCurr, GWEN_DB_FLAGS_OVERWRITE_VARS, "bankCode", p2); free(p2); } GWEN_DB_AddGroup(dbData, dbCurr); ctxCount++; } if (idx) break; } /* for */ GWEN_Buffer_free(buf); if (!ctxCount) { return LC_Client_ResultDataError; } return LC_Client_ResultOk; }
LC_CLIENT_RESULT LC_DDVCard_Reopen(LC_CARD *card){ LC_CLIENT_RESULT res; LC_DDVCARD *ddv; GWEN_BUFFER *mbuf; GWEN_DB_NODE *dbRecord; DBG_INFO(LC_LOGDOMAIN, "Opening DDV card"); assert(card); ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card); assert(ddv); ddv->ddvType=-1; GWEN_DB_Group_free(ddv->db_ef_id_1); ddv->db_ef_id_1=0; GWEN_Buffer_free(ddv->bin_ef_id_1); ddv->bin_ef_id_1=0; res=LC_Card_SelectCard(card, "ProcessorCard"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } res=LC_Card_SelectApp(card, "ddv"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } DBG_INFO(LC_LOGDOMAIN, "Selecting MF..."); res=LC_Card_SelectMf(card); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } DBG_INFO(LC_LOGDOMAIN, "Selecting EF..."); res=LC_Card_SelectEf(card, "EF_ID"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } DBG_INFO(LC_LOGDOMAIN, "Reading record..."); mbuf=GWEN_Buffer_new(0, 256, 0, 1); res=LC_Card_IsoReadRecord(card, LC_CARD_ISO_FLAGS_RECSEL_GIVEN, 1, mbuf); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); GWEN_Buffer_free(mbuf); return res; } DBG_INFO(LC_LOGDOMAIN, "Parsing record..."); GWEN_Buffer_Rewind(mbuf); dbRecord=GWEN_DB_Group_new("record"); if (LC_Card_ParseRecord(card, 1, mbuf, dbRecord)) { DBG_ERROR(LC_LOGDOMAIN, "Error in EF_ID"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return LC_Client_ResultDataError; } if (GWEN_Buffer_GetUsedBytes(mbuf)>22) { /* assume DDV1, perform some checks */ /* check for currency (DDV1 allows EUR only) */ if (strcasecmp(GWEN_DB_GetCharValue(dbRecord, "currency", 0, ""), "EUR")!=0) { DBG_ERROR(LC_LOGDOMAIN, "Bad currency, this does not seem to be DDV1 card"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return LC_Client_ResultDataError; } /* check for OS version on the chip card (DDV1 needs 1 or higher) */ if (GWEN_DB_GetIntValue(dbRecord, "OSVersion",0, 0)<1) { DBG_ERROR(LC_LOGDOMAIN, "Bad CardOS version, this does not seem to be DDV1 card"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return LC_Client_ResultDataError; } /* check for filler (DDV1 needs 0) */ if (GWEN_DB_GetIntValue(dbRecord, "filler",0, 0)!=0) { DBG_ERROR(LC_LOGDOMAIN, "Bad byte at pos 23, this does not seem to be DDV1 card"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return LC_Client_ResultDataError; } /* check for factor (DDV1 needs 1) */ if (GWEN_DB_GetIntValue(dbRecord, "factor", 0, 1)!=1) { DBG_ERROR(LC_LOGDOMAIN, "Bad byte at pos 24, this does not seem to be DDV1 card"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return LC_Client_ResultDataError; } /* select DDV1 card and app */ res=LC_Card_SelectCard(card, "ddv1"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } res=LC_Card_SelectApp(card, "ddv1"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } /* select correct banking DF */ res=LC_Card_SelectDf(card, "DF_BANKING_20"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return res; } DBG_INFO(LC_LOGDOMAIN, "Card type is DDV 1"); ddv->ddvType=1; } else { /* assume DDV0, perform some checks */ /* check for currency (DDV0 allows DEM only) */ if (strcasecmp(GWEN_DB_GetCharValue(dbRecord, "currency", 0, ""), "DEM")!=0) { DBG_ERROR(LC_LOGDOMAIN, "Bad currency, this does not seem to be DDV0 card"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return LC_Client_ResultDataError; } /* select DDV0 card and app */ res=LC_Card_SelectCard(card, "ddv0"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } res=LC_Card_SelectApp(card, "ddv0"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); return res; } /* select correct banking DF */ res=LC_Card_SelectDf(card, "DF_BANKING"); if (res!=LC_Client_ResultOk) { DBG_INFO(LC_LOGDOMAIN, "here"); GWEN_DB_Group_free(dbRecord); GWEN_Buffer_free(mbuf); return res; } DBG_INFO(LC_LOGDOMAIN, "Card type is DDV 0"); ddv->ddvType=0; } ddv->db_ef_id_1=dbRecord; ddv->bin_ef_id_1=mbuf; return LC_Client_ResultOk; }