1 /***************************************************************************
2  begin       : Sun Oct 27 2019
3  copyright   : (C) 2019 by Martin Preuss
4  email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  * This file is part of the project "AqBanking".                           *
8  * Please see toplevel file COPYING of that project for license details.   *
9  ***************************************************************************/
10 
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14 
15 #include "session/hbci/s_verify_hbci.h"
16 #include "session/s_decode.h"
17 #include "session/cryptparams.h"
18 #include "parser/parser.h"
19 
20 #include <gwenhywfar/misc.h>
21 #include <gwenhywfar/debug.h>
22 #include <gwenhywfar/text.h>
23 #include <gwenhywfar/mdigest.h>
24 #include <gwenhywfar/paddalgo.h>
25 
26 #include <time.h>
27 
28 
29 
30 /* ------------------------------------------------------------------------------------------------
31  * forward declarations
32  * ------------------------------------------------------------------------------------------------
33  */
34 
35 
36 
37 /* ------------------------------------------------------------------------------------------------
38  * implementations
39  * ------------------------------------------------------------------------------------------------
40  */
41 
42 
43 
AQFINTS_Session_VerifySegmentHbci(AQFINTS_SESSION * sess,AQFINTS_MESSAGE * message,const AQFINTS_KEYDESCR * keyDescr,AQFINTS_SEGMENT * segSigHead,AQFINTS_SEGMENT * segSigTail,AQFINTS_SEGMENT * segFirstSigned,AQFINTS_SEGMENT * segLastSigned)44 int AQFINTS_Session_VerifySegmentHbci(AQFINTS_SESSION *sess,
45                                       AQFINTS_MESSAGE *message,
46                                       const AQFINTS_KEYDESCR *keyDescr,
47                                       AQFINTS_SEGMENT *segSigHead,
48                                       AQFINTS_SEGMENT *segSigTail,
49                                       AQFINTS_SEGMENT *segFirstSigned,
50                                       AQFINTS_SEGMENT *segLastSigned)
51 {
52   int rv;
53   GWEN_DB_NODE *dbSigHead;
54   GWEN_DB_NODE *dbSigTail;
55   const uint8_t *ptr;
56   unsigned int len=0;
57   int sigCounter;
58   const char *securityProfileName;
59   int securityProfileVersion;
60   const AQFINTS_CRYPTPARAMS *cryptParams;
61   GWEN_BUFFER *bufHashData;
62 
63   securityProfileName=AQFINTS_KeyDescr_GetSecurityProfileName(keyDescr);
64   securityProfileVersion=AQFINTS_KeyDescr_GetSecurityProfileVersion(keyDescr);
65 
66   /* hack for hibiscus */
67   if (securityProfileVersion==0) {
68     if (securityProfileName && strcasecmp(securityProfileName, "RDH")==0)
69       securityProfileVersion=10;
70   }
71 
72   cryptParams=AQFINTS_CryptParams_GetParamsForSecurityProfile(securityProfileName, securityProfileVersion);
73   if (cryptParams==NULL) {
74     DBG_ERROR(AQFINTS_LOGDOMAIN, "No crypt params for [%s:%d]", securityProfileName?securityProfileName:"<empty>",
75               securityProfileVersion);
76     return GWEN_ERROR_INVALID;
77   }
78 
79   dbSigTail=AQFINTS_Segment_GetDbData(segSigTail);
80   assert(dbSigTail);
81   ptr=(const uint8_t *) GWEN_DB_GetBinValue(dbSigTail, "signature", 0, 0, 0, &len);
82   if (ptr==NULL || len<1) {
83     DBG_ERROR(AQFINTS_LOGDOMAIN, "No signature in segment");
84     return GWEN_ERROR_BAD_DATA;
85   }
86 
87   dbSigHead=AQFINTS_Segment_GetDbData(segSigHead);
88   assert(dbSigHead);
89   sigCounter=GWEN_DB_GetIntValue(dbSigHead, "signseq", 0, 0);
90 
91   bufHashData=GWEN_Buffer_new(0, 256, 0, 1);
92   rv=AQFINTS_Session_SampleDataToHash(segSigHead, segFirstSigned, segLastSigned, bufHashData);
93   if (rv<0) {
94     DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
95     GWEN_Buffer_free(bufHashData);
96     return rv;
97   }
98 
99   rv=AQFINTS_Session_Verify(sess, keyDescr, cryptParams,
100                             (const uint8_t *) GWEN_Buffer_GetStart(bufHashData), GWEN_Buffer_GetUsedBytes(bufHashData),
101                             ptr, len, sigCounter);
102   if (rv<0) {
103     if (rv==GWEN_ERROR_TRY_AGAIN) {
104       DBG_INFO(AQFINTS_LOGDOMAIN, "Not yet ready to verify signature, retry later");
105       GWEN_Buffer_free(bufHashData);
106     }
107     else {
108       DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
109     }
110     return rv;
111   }
112 
113   return 0;
114 }
115 
116 
117 
118 
119