Beispiel #1
0
LC_CLIENT_RESULT LC_DDVCard_CryptCharBlock(LC_CARD *card,
                                           const char *data,
                                           unsigned int dlen,
                                           GWEN_BUFFER *obuf){
  LC_DDVCARD *ddv;
  GWEN_DB_NODE *dbReq;
  GWEN_DB_NODE *dbResp;
  LC_CLIENT_RESULT res;
  const void *p;
  unsigned int bs;

  assert(card);
  ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card);
  assert(ddv);

  if (dlen!=8) {
    DBG_ERROR(LC_LOGDOMAIN,
              "In-block must exactly be 8 bytes in length (is %d)",
              dlen);
    return LC_Client_ResultDataError;
  }

  dbReq=GWEN_DB_Group_new("CryptBlock");
  dbResp=GWEN_DB_Group_new("response");
  GWEN_DB_SetBinValue(dbReq, GWEN_DB_FLAGS_DEFAULT,
                      "in",
                      data, dlen);

  res=LC_Card_ExecCommand(card, "CryptBlock", dbReq, dbResp);
  if (res!=LC_Client_ResultOk) {
    GWEN_DB_Group_free(dbReq);
    GWEN_DB_Group_free(dbResp);
    return res;
  }

  p=GWEN_DB_GetBinValue(dbResp,
                        "response/out",
                        0,
                        0, 0,
                        &bs);
  if ( p && bs==8)
    GWEN_Buffer_AppendBytes(obuf, p, bs);
  else {
    DBG_ERROR(LC_LOGDOMAIN, "Expected 8 bytes response, got %d bytes", bs);
    GWEN_DB_Group_free(dbReq);
    GWEN_DB_Group_free(dbResp);
    return LC_Client_ResultDataError;
  }

  GWEN_DB_Group_free(dbReq);
  GWEN_DB_Group_free(dbResp);
  return LC_Client_ResultOk;
}
int AH_Msg_EncryptPinTan(AH_MSG *hmsg) {
  AH_HBCI *h;
  GWEN_XMLNODE *node;
  GWEN_DB_NODE *cfg;
  GWEN_BUFFER *hbuf;
  int rv;
  const char *p;
  GWEN_MSGENGINE *e;
  AB_USER *u;
  const char *peerId;
//  uint32_t uFlags;

  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);

  /* create crypt head */
  node=GWEN_MsgEngine_FindNodeByPropertyStrictProto(e,
						    "SEG",
						    "id",
						    0,
						    "CryptHead");
  if (!node) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "Segment \"CryptHead\" not found");
    return GWEN_ERROR_INTERNAL;
  }

  /* create CryptHead */
  cfg=GWEN_DB_Group_new("crypthead");
  GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT,
		      "head/seq", 998);

  rv=AH_MsgPinTan_PrepareCryptoSeg(hmsg, u, cfg, 1, 0);
  if (rv) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv);
    GWEN_DB_Group_free(cfg);
    return rv;
  }

  /* store system id */
  p=NULL;
  if (!hmsg->noSysId)
    p=AH_User_GetSystemId(u);
  if (!p)
    p="0";
  GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecDetails/SecId", p);

  /* store encrypted message key */
  GWEN_DB_SetBinValue(cfg, GWEN_DB_FLAGS_DEFAULT,
		      "CryptAlgo/MsgKey",
                      "NOKEY", 5);

  hbuf=GWEN_Buffer_new(0, 256+GWEN_Buffer_GetUsedBytes(hmsg->buffer), 0, 1);
  rv=GWEN_MsgEngine_CreateMessageFromNode(e,
					  node,
					  hbuf,
					  cfg);
  if (rv) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "Could not create CryptHead (%d)", rv);
    GWEN_Buffer_free(hbuf);
    GWEN_DB_Group_free(cfg);
    return rv;
  }
  GWEN_DB_Group_free(cfg);

  /* create cryptdata */
  cfg=GWEN_DB_Group_new("cryptdata");
  GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT,
                      "head/seq", 999);
  GWEN_DB_SetBinValue(cfg, GWEN_DB_FLAGS_DEFAULT,
		      "cryptdata",
		      GWEN_Buffer_GetStart(hmsg->buffer),
                      GWEN_Buffer_GetUsedBytes(hmsg->buffer));

  node=GWEN_MsgEngine_FindNodeByPropertyStrictProto(e,
						    "SEG",
						    "id",
						    0,
						    "CryptData");
  if (!node) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "Segment \"CryptData\"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 CryptData (%d)", rv);
    GWEN_Buffer_free(hbuf);
    GWEN_DB_Group_free(cfg);
    return rv;
  }

  /* replace existing buffer by encrypted one */
  GWEN_Buffer_free(hmsg->buffer);
  hmsg->buffer=hbuf;
  GWEN_DB_Group_free(cfg);

  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;
}
Beispiel #4
0
int GWEN_DBIO__XmlDb_ImportVar(GWEN_DBIO *dbio,
			       uint32_t flags,
			       GWEN_DB_NODE *data,
			       GWEN_DB_NODE *cfg,
			       GWEN_XMLNODE *node) {
  GWEN_XMLNODE *n;
  const char *vname;
  GWEN_BUFFER *tbuf;

  assert(node);
  vname=GWEN_XMLNode_GetData(node);
  assert(vname && *vname);
  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
  n=GWEN_XMLNode_FindFirstTag(node, "value", 0, 0);
  while(n) {
    const char *s;
    const char *d;
    int rv;

    GWEN_DBIO__XmlDb_ReadDataTags(n, tbuf);
    d=GWEN_Buffer_GetStart(tbuf);
    if (*d) {
      s=GWEN_XMLNode_GetData(n);
      assert(s && *s);
      s=GWEN_XMLNode_GetProperty(n, "type", 0);
      if (s) {
	if (strcasecmp(s, "char")==0) {
	  rv=GWEN_DB_SetCharValue(data, flags, vname, d);
	  if (rv) {
	    DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
	    GWEN_Buffer_free(tbuf);
            return rv;
	  }
	}
	else if (strcasecmp(s, "int")==0) {
	  int val;

	  if (1!=sscanf(d, "%i", &val)) {
	    DBG_INFO(GWEN_LOGDOMAIN, "Non-integer value [%s]", d);
	    GWEN_Buffer_free(tbuf);
	    return GWEN_ERROR_INVALID;
	  }
	  rv=GWEN_DB_SetIntValue(data, flags, vname, val);
	  if (rv) {
	    DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
	    GWEN_Buffer_free(tbuf);
	    return rv;
	  }
	}
	else if (strcasecmp(s, "bin")==0) {
	  GWEN_BUFFER *xbuf;

	  xbuf=GWEN_Buffer_new(0, 256, 0, 1);
	  rv=GWEN_Text_FromHexBuffer(d, xbuf);
	  if (rv) {
	    DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
	    GWEN_Buffer_free(xbuf);
	    GWEN_Buffer_free(tbuf);
	    return rv;
	  }

	  rv=GWEN_DB_SetBinValue(data, flags, vname,
				 GWEN_Buffer_GetStart(xbuf),
				 GWEN_Buffer_GetUsedBytes(xbuf));
	  GWEN_Buffer_free(xbuf);
	  if (rv) {
	    DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
	    GWEN_Buffer_free(tbuf);
	    return rv;
	  }
	}
	else {
	  DBG_ERROR(GWEN_LOGDOMAIN,
		    "Unhandled value type \"%s\"", s);
	  GWEN_Buffer_free(tbuf);
	  return GWEN_ERROR_INVALID;
	}
      }
    }
    else {
      DBG_DEBUG(GWEN_LOGDOMAIN, "Empty value");
    }
    GWEN_Buffer_Reset(tbuf);

    n=GWEN_XMLNode_FindNextTag(n, "value", 0, 0);
  }
  GWEN_Buffer_free(tbuf);

  return 0;
}
Beispiel #5
0
static int _readLogFile(const char *fname, GWEN_DB_NODE *db) {
  GWEN_SYNCIO *sio;
  GWEN_FAST_BUFFER *fb;
  int rv;
  GWEN_BUFFER *tbuf = NULL;

  sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
  GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
  rv=GWEN_SyncIo_Connect(sio);
  if (rv<0) {
    DBG_ERROR(0, "Error opening file [%s] (%d)", fname, rv);
    return rv;
  }

  /* create fast buffer around io layer */
  fb=GWEN_FastBuffer_new(1024, sio);

  for (;;) {
    GWEN_DB_NODE *dbMsg;
    GWEN_DB_NODE *dbHeader;
    unsigned int size;

    /* read header */
    dbMsg=GWEN_DB_Group_new("Message");
    dbHeader=GWEN_DB_GetGroup(dbMsg, GWEN_DB_FLAGS_DEFAULT, "header");

    rv=GWEN_DB_ReadFromFastBuffer(dbHeader, fb,
				  GWEN_DB_FLAGS_HTTP |
				  GWEN_DB_FLAGS_UNTIL_EMPTY_LINE);
    if (rv<0) {
      if (rv==GWEN_ERROR_EOF)
	break;
      else {
	GWEN_DB_Group_free(dbMsg);
	GWEN_FastBuffer_free(fb);
	GWEN_SyncIo_Disconnect(sio);
	GWEN_SyncIo_free(sio);
	DBG_ERROR(0, "Error reading header from file [%s] (%d)", fname, rv);
	GWEN_DB_Dump(db, 2);
	return rv;
      }
    }

    /* read body */
    size=GWEN_DB_GetIntValue(dbHeader, "size", 0, 0);
    tbuf=GWEN_Buffer_new(0, 2048, 0, 1);
    while(size) {
      unsigned int lsize;
      uint8_t buffer[1024];

      lsize=size;
      if (lsize>sizeof(buffer))
	lsize=sizeof(buffer);

      GWEN_FASTBUFFER_READFORCED(fb, rv, buffer, lsize);
      if (rv<0) {
	GWEN_DB_Group_free(dbMsg);
	GWEN_FastBuffer_free(fb);
	GWEN_SyncIo_Disconnect(sio);
	GWEN_SyncIo_free(sio);
	DBG_ERROR(0, "Error reading body from file [%s] (%d)", fname, rv);
	return rv;
      }
      GWEN_Buffer_AppendBytes(tbuf, (const char*)buffer, lsize);
      size-=lsize;
    } // while

    GWEN_DB_SetBinValue(dbMsg, GWEN_DB_FLAGS_OVERWRITE_VARS, "body",
			GWEN_Buffer_GetStart(tbuf),
			GWEN_Buffer_GetUsedBytes(tbuf));
    GWEN_Buffer_Reset(tbuf);

    GWEN_DB_AddGroup(db, dbMsg);
  }
  GWEN_Buffer_free(tbuf);

  GWEN_FastBuffer_free(fb);
  GWEN_SyncIo_Disconnect(sio);
  GWEN_SyncIo_free(sio);

  return 0;
}
Beispiel #6
0
int AH_Msg_EncryptRdh2(AH_MSG *hmsg) {
  AH_HBCI *h;
  GWEN_XMLNODE *node;
  GWEN_DB_NODE *cfg;
  GWEN_BUFFER *mbuf;
  GWEN_BUFFER *hbuf;
  uint32_t l;
  int rv;
  const char *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;
  uint8_t encKey[300];
  int encKeyLen;
  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_GetEncipherKeyId(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;
  }

  rv=GWEN_Padd_PaddWithAnsiX9_23(hmsg->buffer);
  if (rv) {
    DBG_INFO(AQHBCI_LOGDOMAIN,
	     "Error padding message with ANSI X9.23 (%d)", rv);
    return rv;
  }

  /* create session key */
  sk=GWEN_Crypt_KeyDes3K_Generate(GWEN_Crypt_CryptMode_Cbc, 24, 2);
  if (sk==NULL) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "Could not generate DES key");
    return GWEN_ERROR_INTERNAL;
  }

  /* encrypt message with that session key */
  mbuf=GWEN_Buffer_new(0, GWEN_Buffer_GetUsedBytes(hmsg->buffer), 0, 1);
  l=GWEN_Buffer_GetUsedBytes(hmsg->buffer);
  rv=GWEN_Crypt_Key_Encipher(sk,
			     (uint8_t*)GWEN_Buffer_GetStart(hmsg->buffer),
			     GWEN_Buffer_GetUsedBytes(hmsg->buffer),
			     (uint8_t*)GWEN_Buffer_GetPosPointer(mbuf),
			     &l);
  if (rv<0) {
    DBG_INFO(AQHBCI_LOGDOMAIN,
	     "Could not encipher with DES session key (%d)",
	     rv);
    GWEN_Buffer_free(mbuf);
    GWEN_Crypt_Key_free(sk);
    return rv;
  }
  GWEN_Buffer_IncrementPos(mbuf, l);
  GWEN_Buffer_AdjustUsedBytes(mbuf);

  /* encrypt session key */
  if (1) {
    uint32_t elen;
    GWEN_CRYPT_PADDALGO *algo;

    algo=GWEN_Crypt_PaddAlgo_new(GWEN_Crypt_PaddAlgoId_LeftZero);
    GWEN_Crypt_PaddAlgo_SetPaddSize(algo, GWEN_Crypt_Token_KeyInfo_GetKeySize(ki));

    elen=sizeof(encKey);
    rv=GWEN_Crypt_Token_Encipher(ct,
				 keyId,
				 algo,
				 GWEN_Crypt_KeyDes3K_GetKeyDataPtr(sk),
				 16,
				 encKey,
				 &elen,
				 gid);

    GWEN_Crypt_PaddAlgo_free(algo);
    if (rv<0) {
      DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv);
      GWEN_Buffer_free(mbuf);
      GWEN_Crypt_Key_free(sk);
      return rv;
    }
    encKeyLen=elen;
  }
  GWEN_Crypt_Key_free(sk);

  /* create crypt head */
  node=GWEN_MsgEngine_FindNodeByPropertyStrictProto(e,
						    "SEG",
						    "id",
						    0,
						    "CryptHead");
  if (!node) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "Segment \"CryptHead\" not found");
    GWEN_Buffer_free(mbuf);
    GWEN_Crypt_Key_free(sk);
    return GWEN_ERROR_INTERNAL;
  }

  /* create CryptHead */
  cfg=GWEN_DB_Group_new("crypthead");
  GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT,
		      "head/seq", 998);

  rv=AH_MsgRdh_PrepareCryptoSeg2(hmsg, u, ki, cfg, 1, 0);
  if (rv) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv);
    GWEN_DB_Group_free(cfg);
    GWEN_Buffer_free(mbuf);
    return rv;
  }

  /* store system id */
  if (hmsg->noSysId) {
    GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT,
			 "SecDetails/SecId", "0");
  }
  else {
    p=AH_User_GetSystemId(u);
    if (p==NULL)
      p=GWEN_Crypt_Token_Context_GetSystemId(ctx);
    if (p)
      GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT,
			   "SecDetails/SecId", p);
    else {
      DBG_INFO(AQHBCI_LOGDOMAIN,
	       "No System id on RDH medium, using default");
      GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT,
			   "SecDetails/SecId", "0");
    }
  }

  /* store encrypted message key */
  GWEN_DB_SetBinValue(cfg, GWEN_DB_FLAGS_DEFAULT,
		      "CryptAlgo/MsgKey",
                      encKey,
		      encKeyLen);

  hbuf=GWEN_Buffer_new(0, 256+GWEN_Buffer_GetUsedBytes(mbuf), 0, 1);
  rv=GWEN_MsgEngine_CreateMessageFromNode(e,
                                          node,
                                          hbuf,
                                          cfg);
  if (rv) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "Could not create CryptHead (%d)", rv);
    GWEN_Buffer_free(hbuf);
    GWEN_DB_Group_free(cfg);
    GWEN_Buffer_free(mbuf);
    return rv;
  }
  GWEN_DB_Group_free(cfg);

  /* create cryptdata */
  cfg=GWEN_DB_Group_new("cryptdata");
  GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT,
                      "head/seq", 999);
  GWEN_DB_SetBinValue(cfg, GWEN_DB_FLAGS_DEFAULT,
                      "cryptdata",
		      GWEN_Buffer_GetStart(mbuf),
                      GWEN_Buffer_GetUsedBytes(mbuf));
  GWEN_Buffer_free(mbuf);

  node=GWEN_MsgEngine_FindNodeByPropertyStrictProto(e,
						    "SEG",
						    "id",
						    0,
						    "CryptData");
  if (!node) {
    DBG_INFO(AQHBCI_LOGDOMAIN, "Segment \"CryptData\"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 CryptData (%d)", rv);
    GWEN_Buffer_free(hbuf);
    GWEN_DB_Group_free(cfg);
    return rv;
  }

  /* replace existing buffer by encrypted one */
  GWEN_Buffer_free(hmsg->buffer);
  hmsg->buffer=hbuf;
  GWEN_DB_Group_free(cfg);

  return 0;
}
Beispiel #7
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;
}
Beispiel #8
0
LC_CLIENT_RESULT LC_DDVCard_SignHash1(LC_CARD *card,
                                      GWEN_BUFFER *hbuf,
                                      GWEN_BUFFER *obuf){
  LC_DDVCARD *ddv;
  GWEN_DB_NODE *dbReq;
  GWEN_DB_NODE *dbResp;
  LC_CLIENT_RESULT res;
  const void *p;
  unsigned int bs;

  assert(card);
  ddv=GWEN_INHERIT_GETDATA(LC_CARD, LC_DDVCARD, card);
  assert(ddv);

  if (GWEN_Buffer_GetUsedBytes(hbuf)!=20) {
    DBG_ERROR(LC_LOGDOMAIN, "Hash must exactly be 20 bytes in length (is %d)",
              GWEN_Buffer_GetUsedBytes(hbuf));
    return LC_Client_ResultDataError;
  }

  /* write right part of the hash */
  dbReq=GWEN_DB_Group_new("WriteHashR");
  dbResp=GWEN_DB_Group_new("response");
  GWEN_DB_SetBinValue(dbReq, GWEN_DB_FLAGS_DEFAULT,
                      "hashR",
                      GWEN_Buffer_GetStart(hbuf)+8, 12);

  res=LC_Card_ExecCommand(card, "WriteHashR", dbReq, dbResp);
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "Error while executing WriteHashR");
    GWEN_DB_Group_free(dbReq);
    GWEN_DB_Group_free(dbResp);
    return res;
  }
  GWEN_DB_Group_free(dbReq);
  GWEN_DB_Group_free(dbResp);


  /* write left part of hash and retrieve signed hash */
  dbReq=GWEN_DB_Group_new("SignHash");
  dbResp=GWEN_DB_Group_new("response");
  GWEN_DB_SetBinValue(dbReq, GWEN_DB_FLAGS_DEFAULT,
                      "hashL",
                      GWEN_Buffer_GetStart(hbuf), 8);
  res=LC_Card_ExecCommand(card, "SignHash", dbReq, dbResp);
  if (res!=LC_Client_ResultOk) {
    DBG_INFO(LC_LOGDOMAIN, "Error while executing SignHash");
    GWEN_DB_Group_free(dbReq);
    GWEN_DB_Group_free(dbResp);
    return res;
  }


  p=GWEN_DB_GetBinValue(dbResp,
                        "response/signedHash",
                        0,
                        0, 0,
                        &bs);
  if ( p && bs==8)
    GWEN_Buffer_AppendBytes(obuf, p, bs);
  else {
    DBG_ERROR(LC_LOGDOMAIN, "Expected 8 bytes response, got %d bytes", bs);
    GWEN_DB_Group_free(dbReq);
    GWEN_DB_Group_free(dbResp);
    return LC_Client_ResultDataError;
  }

  GWEN_DB_Group_free(dbReq);
  GWEN_DB_Group_free(dbResp);
  return LC_Client_ResultOk;
}