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_sign_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 static AQFINTS_SEGMENT *_createSigHead(AQFINTS_SESSION *sess, const AQFINTS_CRYPTPARAMS *cryptParams,
36                                        int segNum, const AQFINTS_KEYDESCR *keyDescr, const char *ctrlRef);
37 static AQFINTS_SEGMENT *_createSigTail(AQFINTS_SESSION *sess,
38                                        const AQFINTS_CRYPTPARAMS *cryptParams,
39                                        int segNum,
40                                        const AQFINTS_KEYDESCR *keyDescr,
41                                        const char *ctrlRef,
42                                        const uint8_t *ptrSignature, uint32_t lenSignature);
43 
44 
45 static int _createCtrlRef(char *ptrBuf, size_t lenBuf);
46 static int _prepareSignSeg(AQFINTS_SESSION *sess,
47                            const AQFINTS_CRYPTPARAMS *cryptParams,
48                            const AQFINTS_KEYDESCR *keyDescr,
49                            const char *ctrlRef,
50                            GWEN_DB_NODE *cfg);
51 
52 static int _signSegments(AQFINTS_SESSION *sess,
53                          const AQFINTS_CRYPTPARAMS *cryptParams,
54                          const AQFINTS_KEYDESCR *keyDescr,
55                          AQFINTS_SEGMENT *segSigHead,
56                          AQFINTS_SEGMENT *segFirstToSign,
57                          AQFINTS_SEGMENT *segLastToSign,
58                          GWEN_BUFFER *sigBuf);
59 
60 
61 
62 /* ------------------------------------------------------------------------------------------------
63  * implementations
64  * ------------------------------------------------------------------------------------------------
65  */
66 
67 
68 
AQFINTS_Session_SignSegmentHbci(AQFINTS_SESSION * sess,AQFINTS_MESSAGE * message,AQFINTS_KEYDESCR * keyDescr,AQFINTS_SEGMENT * segFirstToSign,AQFINTS_SEGMENT * segLastToSign,int sigHeadNum,int sigTailNum)69 int AQFINTS_Session_SignSegmentHbci(AQFINTS_SESSION *sess,
70                                     AQFINTS_MESSAGE *message,
71                                     AQFINTS_KEYDESCR *keyDescr,
72                                     AQFINTS_SEGMENT *segFirstToSign,
73                                     AQFINTS_SEGMENT *segLastToSign,
74                                     int sigHeadNum,
75                                     int sigTailNum)
76 {
77   int rv;
78   AQFINTS_SEGMENT_LIST *segmentList;
79   char ctrlref[15];
80   AQFINTS_SEGMENT *segment;
81   const char *securityProfileName;
82   int securityProfileVersion;
83   const AQFINTS_CRYPTPARAMS *cryptParams;
84   GWEN_BUFFER *sigBuf;
85 
86   securityProfileName=AQFINTS_KeyDescr_GetSecurityProfileName(keyDescr);
87   securityProfileVersion=AQFINTS_KeyDescr_GetSecurityProfileVersion(keyDescr);
88 
89   /* hack for hibiscus */
90   if (securityProfileVersion==0) {
91     if (securityProfileName && strcasecmp(securityProfileName, "RDH")==0)
92       securityProfileVersion=10;
93   }
94 
95   cryptParams=AQFINTS_CryptParams_GetParamsForSecurityProfile(securityProfileName, securityProfileVersion);
96   if (cryptParams==NULL) {
97     DBG_ERROR(AQFINTS_LOGDOMAIN, "No crypt params for [%s:%d]", securityProfileName?securityProfileName:"<empty>",
98               securityProfileVersion);
99     return GWEN_ERROR_INVALID;
100   }
101 
102   segmentList=AQFINTS_Message_GetSegmentList(message);
103 
104   rv=_createCtrlRef(ctrlref, sizeof(ctrlref));
105   if (rv<0) {
106     DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
107     return rv;
108   }
109 
110   rv=AQFINTS_Session_FilloutKeyname(sess, keyDescr, AQFINTS_SESSION_CRYPTOP_SIGN);
111   if (rv<0) {
112     DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
113     return rv;
114   }
115 
116   segment=_createSigHead(sess, cryptParams, sigHeadNum, keyDescr, ctrlref);
117   if (segment==NULL) {
118     DBG_INFO(AQFINTS_LOGDOMAIN, "here");
119     return GWEN_ERROR_GENERIC;
120   }
121   AQFINTS_Segment_List_Insert(segment, segmentList);
122 
123   sigBuf=GWEN_Buffer_new(0, 256, 0, 1);
124   rv=_signSegments(sess, cryptParams, keyDescr, segment, segFirstToSign, segLastToSign, sigBuf);
125   if (rv<0) {
126     DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
127     GWEN_Buffer_free(sigBuf);
128     return rv;
129   }
130 
131   segment=_createSigTail(sess, cryptParams, sigTailNum, keyDescr, ctrlref,
132                          (const uint8_t *) GWEN_Buffer_GetStart(sigBuf),
133                          GWEN_Buffer_GetUsedBytes(sigBuf));
134   if (segment==NULL) {
135     DBG_INFO(AQFINTS_LOGDOMAIN, "here");
136     GWEN_Buffer_free(sigBuf);
137     return GWEN_ERROR_GENERIC;
138   }
139   GWEN_Buffer_free(sigBuf);
140   AQFINTS_Segment_List_Add(segment, segmentList);
141 
142   return 0;
143 }
144 
145 
146 
_signSegments(AQFINTS_SESSION * sess,const AQFINTS_CRYPTPARAMS * cryptParams,const AQFINTS_KEYDESCR * keyDescr,AQFINTS_SEGMENT * segSigHead,AQFINTS_SEGMENT * segFirstToSign,AQFINTS_SEGMENT * segLastToSign,GWEN_BUFFER * sigBuf)147 int _signSegments(AQFINTS_SESSION *sess,
148                   const AQFINTS_CRYPTPARAMS *cryptParams,
149                   const AQFINTS_KEYDESCR *keyDescr,
150                   AQFINTS_SEGMENT *segSigHead,
151                   AQFINTS_SEGMENT *segFirstToSign,
152                   AQFINTS_SEGMENT *segLastToSign,
153                   GWEN_BUFFER *sigBuf)
154 {
155   uint32_t signLen;
156   int rv;
157   GWEN_BUFFER *hashSrcBuffer;
158 
159   hashSrcBuffer=GWEN_Buffer_new(0, 1024, 0, 1);
160   rv=AQFINTS_Session_SampleDataToHash(segSigHead, segFirstToSign, segLastToSign, hashSrcBuffer);
161   if (rv<0) {
162     DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
163     return rv;
164   }
165 
166   signLen=GWEN_Buffer_GetMaxUnsegmentedWrite(sigBuf);
167   GWEN_Buffer_AllocRoom(sigBuf, 256);
168   rv=AQFINTS_Session_Sign(sess, keyDescr, cryptParams,
169                           (const uint8_t *) GWEN_Buffer_GetStart(hashSrcBuffer),
170                           GWEN_Buffer_GetUsedBytes(hashSrcBuffer),
171                           (uint8_t *)GWEN_Buffer_GetStart(sigBuf),
172                           &signLen);
173   if (rv<0) {
174     DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
175     GWEN_Buffer_free(hashSrcBuffer);
176     return rv;
177   }
178   GWEN_Buffer_free(hashSrcBuffer);
179   GWEN_Buffer_IncrementPos(sigBuf, signLen);
180   GWEN_Buffer_AdjustUsedBytes(sigBuf);
181 
182   return 0;
183 }
184 
185 
186 
187 
188 
_createSigHead(AQFINTS_SESSION * sess,const AQFINTS_CRYPTPARAMS * cryptParams,int segNum,const AQFINTS_KEYDESCR * keyDescr,const char * ctrlRef)189 AQFINTS_SEGMENT *_createSigHead(AQFINTS_SESSION *sess,
190                                 const AQFINTS_CRYPTPARAMS *cryptParams,
191                                 int segNum, const AQFINTS_KEYDESCR *keyDescr, const char *ctrlRef)
192 {
193   GWEN_DB_NODE *dbSegment;
194   AQFINTS_PARSER *parser;
195   int hbciVersion;
196   AQFINTS_SEGMENT *defSegment;
197   AQFINTS_SEGMENT *segment;
198   int rv;
199 
200   parser=AQFINTS_Session_GetParser(sess);
201   hbciVersion=AQFINTS_Session_GetHbciVersion(sess);
202 
203   /* HNSHA */
204   defSegment=AQFINTS_Parser_FindSegmentHighestVersionForProto(parser, "HNSHK", hbciVersion);
205   if (defSegment==NULL) {
206     DBG_ERROR(AQFINTS_LOGDOMAIN, "No matching definition segment found for HNSHK (proto=%d)", hbciVersion);
207     return NULL;
208   }
209 
210   segment=AQFINTS_Segment_new();
211   AQFINTS_Segment_copy(segment, defSegment);
212   AQFINTS_Segment_SetSegmentNumber(segment, segNum);
213   dbSegment=GWEN_DB_Group_new("sigHead");
214   AQFINTS_Segment_SetDbData(segment, dbSegment);
215 
216   rv=_prepareSignSeg(sess, cryptParams, keyDescr, ctrlRef, dbSegment);
217   if (rv<0) {
218     DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
219     AQFINTS_Segment_free(segment);
220     return NULL;
221   }
222 
223   rv=AQFINTS_Session_WriteSegment(sess, segment);
224   if (rv<0) {
225     DBG_INFO(0, "here (%d)", rv);
226     AQFINTS_Segment_free(segment);
227   }
228 
229   return segment;
230 }
231 
232 
233 
_createSigTail(AQFINTS_SESSION * sess,const AQFINTS_CRYPTPARAMS * cryptParams,int segNum,const AQFINTS_KEYDESCR * keyDescr,const char * ctrlRef,const uint8_t * ptrSignature,uint32_t lenSignature)234 AQFINTS_SEGMENT *_createSigTail(AQFINTS_SESSION *sess,
235                                 const AQFINTS_CRYPTPARAMS *cryptParams,
236                                 int segNum,
237                                 const AQFINTS_KEYDESCR *keyDescr,
238                                 const char *ctrlRef,
239                                 const uint8_t *ptrSignature, uint32_t lenSignature)
240 {
241   GWEN_DB_NODE *dbSegment;
242   AQFINTS_PARSER *parser;
243   int hbciVersion;
244   AQFINTS_SEGMENT *defSegment;
245   AQFINTS_SEGMENT *segment;
246   int rv;
247   const char *s;
248 
249   parser=AQFINTS_Session_GetParser(sess);
250   hbciVersion=AQFINTS_Session_GetHbciVersion(sess);
251 
252   /* HNSHA */
253   defSegment=AQFINTS_Parser_FindSegmentHighestVersionForProto(parser, "HNSHA", hbciVersion);
254   if (defSegment==NULL) {
255     DBG_ERROR(AQFINTS_LOGDOMAIN, "No matching definition segment found for HNSHA (proto=%d)", hbciVersion);
256     return NULL;
257   }
258 
259   segment=AQFINTS_Segment_new();
260   AQFINTS_Segment_copy(segment, defSegment);
261   AQFINTS_Segment_SetSegmentNumber(segment, segNum);
262 
263   dbSegment=GWEN_DB_Group_new("sigTail");
264   AQFINTS_Segment_SetDbData(segment, dbSegment);
265 
266   GWEN_DB_SetCharValue(dbSegment, GWEN_DB_FLAGS_DEFAULT, "ctrlref", ctrlRef);
267 
268   if (ptrSignature && lenSignature)
269     GWEN_DB_SetBinValue(dbSegment, GWEN_DB_FLAGS_DEFAULT, "signature", ptrSignature, lenSignature);
270 
271   s=AQFINTS_KeyDescr_GetPin(keyDescr);
272   if (s && *s)
273     GWEN_DB_SetCharValue(dbSegment, GWEN_DB_FLAGS_DEFAULT, "pin", s);
274 
275   s=AQFINTS_KeyDescr_GetTan(keyDescr);
276   if (s && *s)
277     GWEN_DB_SetCharValue(dbSegment, GWEN_DB_FLAGS_DEFAULT, "tan", s);
278 
279   rv=AQFINTS_Session_WriteSegment(sess, segment);
280   if (rv<0) {
281     DBG_INFO(AQFINTS_LOGDOMAIN, "here (%d)", rv);
282     AQFINTS_Segment_free(segment);
283   }
284 
285   return segment;
286 }
287 
288 
289 
290 
291 
_createCtrlRef(char * ptrBuf,size_t lenBuf)292 int _createCtrlRef(char *ptrBuf, size_t lenBuf)
293 {
294 
295   struct tm *lt;
296   time_t tt;
297 
298   tt=time(0);
299   lt=localtime(&tt);
300 
301   if (!strftime(ptrBuf, lenBuf, "%Y%m%d%H%M%S", lt)) {
302     DBG_INFO(AQFINTS_LOGDOMAIN, "CtrlRef string too long");
303     return GWEN_ERROR_INTERNAL;
304   }
305 
306   return 0;
307 }
308 
309 
310 
_prepareSignSeg(AQFINTS_SESSION * sess,const AQFINTS_CRYPTPARAMS * cryptParams,const AQFINTS_KEYDESCR * keyDescr,const char * ctrlRef,GWEN_DB_NODE * cfg)311 int _prepareSignSeg(AQFINTS_SESSION *sess,
312                     const AQFINTS_CRYPTPARAMS *cryptParams,
313                     const AQFINTS_KEYDESCR *keyDescr,
314                     const char *ctrlRef,
315                     GWEN_DB_NODE *cfg)
316 {
317   char sdate[9];
318   char stime[7];
319   struct tm *lt;
320   time_t tt;
321   const char *s;
322   const char *securityProfileName;
323   int securityProfileVersion;
324 
325   /* some preparations */
326   tt=time(0);
327   lt=localtime(&tt);
328 
329   /* create date */
330   if (!strftime(sdate, sizeof(sdate), "%Y%m%d", lt)) {
331     DBG_INFO(AQFINTS_LOGDOMAIN, "Date string too long");
332     return GWEN_ERROR_INTERNAL;
333   }
334   /* create time */
335   if (!strftime(stime, sizeof(stime), "%H%M%S", lt)) {
336     DBG_INFO(AQFINTS_LOGDOMAIN, "Date string too long");
337     return GWEN_ERROR_INTERNAL;
338   }
339 
340   /* store info */
341 
342   /* security profile */
343   securityProfileName=AQFINTS_KeyDescr_GetSecurityProfileName(keyDescr);
344   securityProfileVersion=AQFINTS_KeyDescr_GetSecurityProfileVersion(keyDescr);
345 
346   /* hack for hibiscus */
347   if (securityProfileVersion==0) {
348     if (securityProfileName && strcasecmp(securityProfileName, "RDH")==0)
349       securityProfileVersion=10;
350   }
351 
352   GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "secProfile/code", securityProfileName);
353   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "secProfile/version", securityProfileVersion);
354 
355   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "function", 2); /* sign with digital signature key */
356   GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "ctrlref", ctrlRef);
357   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "area", 1);
358   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "role", 1);
359 
360   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecDetails/id",
361                       AQFINTS_Session_GetIsServer(sess)?2:1); /* 1 client, 2=server */
362 
363   s=AQFINTS_KeyDescr_GetSystemId(keyDescr);
364   if (s && *s)
365     GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecDetails/secId", s);
366   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "signseq", AQFINTS_KeyDescr_GetSignatureCounter(keyDescr));
367 
368   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecStamp/stampCode", 1);
369   GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecStamp/date", sdate);
370   GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "SecStamp/time", stime);
371 
372   /* hashAlgo */
373   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "hashAlgo/purpose", 1);
374   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "hashAlgo/algo", AQFINTS_CryptParams_GetHashAlgoSign(cryptParams));
375   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "hashAlgo/pname", 1);
376 
377   /* signAlgo */
378   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "signAlgo/purpose", 6);
379   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "signAlgo/algo", AQFINTS_CryptParams_GetSignAlgo(cryptParams));
380   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "signAlgo/mode", AQFINTS_CryptParams_GetOpModeSign(cryptParams));
381 
382   /* keyname */
383   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "key/country", AQFINTS_KeyDescr_GetCountry(keyDescr));
384   GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "key/bankcode", AQFINTS_KeyDescr_GetBankCode(keyDescr));
385   GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "key/userid", AQFINTS_KeyDescr_GetUserId(keyDescr));
386   GWEN_DB_SetCharValue(cfg, GWEN_DB_FLAGS_DEFAULT, "key/keytype", AQFINTS_KeyDescr_GetKeyType(keyDescr));
387   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "key/keynum", AQFINTS_KeyDescr_GetKeyNumber(keyDescr));
388   GWEN_DB_SetIntValue(cfg, GWEN_DB_FLAGS_DEFAULT, "key/keyversion", AQFINTS_KeyDescr_GetKeyVersion(keyDescr));
389 
390   /* TODO: add certificate data */
391 
392   return 0;
393 }
394 
395 
396 
397