gwenhywfar  4.99.8beta
mdigest.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Wed Mar 16 2005
3  copyright : (C) 2005-2010 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * Please see toplevel file COPYING for license details *
8  ***************************************************************************/
9 
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13 
14 #define DISABLE_DEBUGLOG
15 
16 
17 #include "mdigest_p.h"
18 #include "i18n_l.h"
19 
20 #include <gwenhywfar/misc.h>
21 #include <gwenhywfar/debug.h>
22 #include <gwenhywfar/directory.h>
23 #include <gwenhywfar/text.h>
24 #include <gwenhywfar/syncio.h>
25 #include <gwenhywfar/syncio_file.h>
26 #include <gwenhywfar/gui.h>
27 
28 
29 
30 
32 GWEN_LIST_FUNCTIONS(GWEN_MDIGEST, GWEN_MDigest)
33 GWEN_LIST2_FUNCTIONS(GWEN_MDIGEST, GWEN_MDigest)
34 
35 
36 
37 
38 
40  GWEN_MDIGEST *md;
41 
42  GWEN_NEW_OBJECT(GWEN_MDIGEST, md)
43  md->refCount=1;
44  GWEN_INHERIT_INIT(GWEN_MDIGEST, md)
45  GWEN_LIST_INIT(GWEN_MDIGEST, md)
46 
47  md->hashAlgoId=a;
48  return md;
49 }
50 
51 
52 
54  if (md) {
55  assert(md->refCount);
56  if (md->refCount==1) {
58  free(md->pDigest);
59  md->refCount=0;
61  GWEN_FREE_OBJECT(md);
62  }
63  else
64  md->refCount--;
65  }
66 }
67 
68 
69 
71  assert(md);
72  assert(md->refCount);
73  return md->hashAlgoId;
74 }
75 
76 
77 
79  assert(md);
80  assert(md->refCount);
81  return md->pDigest;
82 }
83 
84 
85 
87  assert(md);
88  assert(md->refCount);
89  return md->lDigest;
90 }
91 
92 
93 
94 void GWEN_MDigest_SetDigestBuffer(GWEN_MDIGEST *md, uint8_t *buf, unsigned int l) {
95  assert(md);
96  assert(md->refCount);
97 
98  if (l) {
99  assert(buf);
100  }
101 
102  if (md->pDigest && md->lDigest)
103  free(md->pDigest);
104  md->pDigest=buf;
105  md->lDigest=l;
106 }
107 
108 
109 
110 void GWEN_MDigest_SetDigestLen(GWEN_MDIGEST *md, unsigned int l) {
111  assert(md);
112  assert(md->refCount);
113 
114  if (md->pDigest && md->lDigest)
115  free(md->pDigest);
116  md->pDigest=NULL;
117  md->lDigest=l;
118 }
119 
120 
121 
123  assert(md);
124  assert(md->refCount);
125  if (md->beginFn)
126  return md->beginFn(md);
127  else
129 }
130 
131 
132 
134  assert(md);
135  assert(md->refCount);
136  if (md->endFn)
137  return md->endFn(md);
138  else
140 }
141 
142 
143 
144 int GWEN_MDigest_Update(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l) {
145  assert(md);
146  assert(md->refCount);
147  if (md->updateFn)
148  return md->updateFn(md, buf, l);
149  else
151 }
152 
153 
154 
157 
158  assert(md);
159  assert(md->refCount);
160  of=md->beginFn;
161  md->beginFn=f;
162 
163  return of;
164 }
165 
166 
167 
170 
171  assert(md);
172  assert(md->refCount);
173  of=md->endFn;
174  md->endFn=f;
175 
176  return of;
177 }
178 
179 
180 
183 
184  assert(md);
185  assert(md->refCount);
186  of=md->updateFn;
187  md->updateFn=f;
188 
189  return of;
190 }
191 
192 
193 
195  const char *password,
196  const uint8_t *pSalt,
197  uint32_t lSalt,
198  uint8_t *pKey,
199  uint32_t lKey,
200  uint32_t iterations) {
201  int rv;
202  uint8_t hash[128];
203  uint32_t hsize;
204  uint32_t i;
205 
206  hsize=GWEN_MDigest_GetDigestSize(md);
207  if (lKey>hsize || lKey>sizeof(hash)) {
208  DBG_ERROR(GWEN_LOGDOMAIN, "Derived key too long");
209  return GWEN_ERROR_INVALID;
210  }
211 
212  rv=GWEN_MDigest_Begin(md);
213  if (rv<0) {
214  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
215  GWEN_MDigest_End(md);
216  return rv;
217  }
218 
219  /* hash password */
220  rv=GWEN_MDigest_Update(md, (const uint8_t*) password, strlen(password));
221  if (rv<0) {
222  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
223  GWEN_MDigest_End(md);
224  return rv;
225  }
226 
227  /* hash salt */
228  rv=GWEN_MDigest_Update(md, pSalt, lSalt);
229  if (rv<0) {
230  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
231  GWEN_MDigest_End(md);
232  return rv;
233  }
234 
235  rv=GWEN_MDigest_End(md);
236  if (rv<0) {
237  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
238  GWEN_MDigest_End(md);
239  return rv;
240  }
241 
242  /* use that hash now for the iterations */
243  memmove(hash, GWEN_MDigest_GetDigestPtr(md), hsize);
244 
245  for (i=2; i<iterations; i++) {
246  rv=GWEN_MDigest_Begin(md);
247  if (rv<0) {
248  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
249  GWEN_MDigest_End(md);
250  return rv;
251  }
252  rv=GWEN_MDigest_Update(md, hash, hsize);
253  if (rv<0) {
254  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
255  GWEN_MDigest_End(md);
256  return rv;
257  }
258 
259  rv=GWEN_MDigest_End(md);
260  if (rv<0) {
261  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
262  GWEN_MDigest_End(md);
263  return rv;
264  }
265 
266  /* use that hash now for the next iteration */
267  memmove(hash, GWEN_MDigest_GetDigestPtr(md), hsize);
268  }
269 
270  /* done, copy key */
271  memmove(pKey, hash, lKey);
272  memset(hash, 0, sizeof(hash));
273 
274  return 0;
275 }
276 
277 
278 
280  const char *fname,
281  GWEN_BUFFER *hbuf) {
282  GWEN_SYNCIO *sio;
283  int rv;
284  uint8_t buffer[1024];
285 
288  rv=GWEN_SyncIo_Connect(sio);
289  if (rv<0) {
290  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
291  GWEN_SyncIo_free(sio);
292  return rv;
293  }
294 
295  rv=GWEN_MDigest_Begin(md);
296  if (rv<0) {
297  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
299  GWEN_SyncIo_free(sio);
300  return rv;
301  }
302 
303  while(1) {
304  rv=GWEN_SyncIo_Read(sio, buffer, sizeof(buffer));
305  if (rv<0) {
306  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
308  GWEN_SyncIo_free(sio);
309  return rv;
310  }
311  else if (rv==0)
312  break;
313  else {
314  rv=GWEN_MDigest_Update(md, (const uint8_t*) buffer, rv);
315  if (rv<0) {
316  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
318  GWEN_SyncIo_free(sio);
319  return rv;
320  }
321  }
322  }
323 
324  rv=GWEN_MDigest_End(md);
325  if (rv<0) {
326  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
328  GWEN_SyncIo_free(sio);
329  return rv;
330  }
331 
333  GWEN_SyncIo_free(sio);
334 
337  hbuf, 0, 0, 0);
338  if (rv<0) {
339  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
340  return rv;
341  }
342 
343  return 0;
344 }
345 
346 
347 
349  const char *baseFolder,
350  const char *relFolder,
351  const char *ignoreFile,
352  GWEN_STRINGLIST *sl) {
353  GWEN_STRINGLIST *files;
355  GWEN_BUFFER *pbuf;
356  uint32_t ppos;
357  uint32_t rpos;
358  int rv;
359 
360  files=GWEN_StringList_new();
361  pbuf=GWEN_Buffer_new(0, 256, 0, 1);
362  GWEN_Buffer_AppendString(pbuf, baseFolder);
364  rpos=GWEN_Buffer_GetPos(pbuf);
365  if (relFolder) {
366  GWEN_Buffer_AppendString(pbuf, relFolder);
368  }
369  ppos=GWEN_Buffer_GetPos(pbuf);
370 
372  if (rv<0) {
373  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
374  GWEN_Buffer_free(pbuf);
375  GWEN_StringList_free(files);
376  return rv;
377  }
378 
379  se=GWEN_StringList_FirstEntry(files);
380  while(se) {
381  const char *s;
382 
384  if (s && *s) {
385  GWEN_Buffer_AppendString(pbuf, s+1);
386  if (*s=='d') {
387  if (strcasecmp(s+1, ".")!=0 && strcasecmp(s+1, "..")!=0) {
389  baseFolder,
390  GWEN_Buffer_GetStart(pbuf)+rpos,
391  ignoreFile,
392  sl);
393  if (rv<0) {
394  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
395  GWEN_Buffer_free(pbuf);
396  GWEN_StringList_free(files);
397  return rv;
398  }
399  }
400  }
401  else if (*s=='f') {
402  if (!(ignoreFile && strcasecmp(ignoreFile, s+1)==0)) {
403  GWEN_BUFFER *tbuf;
404  GWEN_BUFFER *xbuf;
405  char *p;
406 
407  xbuf=GWEN_Buffer_new(0, 256, 0, 1);
409  p=GWEN_Buffer_GetStart(xbuf);
410  while(*p) {
411  if (*p=='\\')
412  *p='/';
413  p++;
414  }
415 
416  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
417 
418  /* add relative path to line buffer */
419  GWEN_Buffer_AppendString(tbuf, "F");
421  GWEN_Buffer_free(xbuf);
422  if (rv<0) {
423  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
424  GWEN_Buffer_free(tbuf);
425  GWEN_Buffer_free(pbuf);
426  GWEN_StringList_free(files);
427  return rv;
428  }
429  GWEN_Buffer_AppendString(tbuf, ":");
430 
431  /* hash file */
432  rv=GWEN_MDigest__HashFile(md, GWEN_Buffer_GetStart(pbuf), tbuf);
433  if (rv<0) {
434  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
435  GWEN_Buffer_free(tbuf);
436  GWEN_Buffer_free(pbuf);
437  GWEN_StringList_free(files);
438  return rv;
439  }
440 
441  /* append line to stringlist */
443  GWEN_Buffer_free(tbuf);
444  }
445  }
446  else {
447  DBG_INFO(GWEN_LOGDOMAIN, "Unknown file type in [%s]", s);
448  }
449  GWEN_Buffer_Crop(pbuf, 0, ppos);
450  }
452  }
453 
454  GWEN_Buffer_free(pbuf);
455  GWEN_StringList_free(files);
456  return 0;
457 }
458 
459 
460 
462  const char *folder,
463  const char *ignoreFile,
464  GWEN_STRINGLIST *sl) {
465  int rv;
466 
467  rv=GWEN_MDigest__HashFileTree(md, folder, NULL, ignoreFile, sl);
468  if (rv<0) {
469  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
470  return rv;
471  }
472 
473  return 0;
474 }
475 
476 
477 
479  const char *folder,
480  const char *checksumFile,
481  int strictCheck,
482  uint32_t pid) {
483  GWEN_STRINGLIST *sl;
484  GWEN_STRINGLIST *savedList;
485  GWEN_BUFFER *tbuf;
487  int rv;
488  int allHashesOk=1;
489  int validLines=0;
490 
491  sl=GWEN_StringList_new();
492 
493  /* generate hash list */
494  rv=GWEN_MDigest_HashFileTree(md, folder, checksumFile, sl);
495  if (rv<0) {
497  I18N("Error unpacking program (%d)"), rv);
499  return rv;
500  }
501 
502  savedList=GWEN_StringList_new();
503 
504  /* read checksums from file */
505  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
506  GWEN_Buffer_AppendString(tbuf, folder);
508  GWEN_Buffer_AppendString(tbuf, checksumFile);
510  -1,
511  savedList);
512  if (rv<0) {
514  I18N("Error loading checksum file (%d)"), rv);
515  GWEN_Buffer_free(tbuf);
516  GWEN_StringList_free(savedList);
518  return rv;
519  }
520  GWEN_Buffer_free(tbuf);
521 
522  /* check checksums */
523  se=GWEN_StringList_FirstEntry(savedList);
524  while(se) {
525  const char *s;
526 
528  if (s && *s) {
529  validLines++;
530  if (0==GWEN_StringList_RemoveString(sl, s)) {
531  DBG_ERROR(0, "Hash not found: %s", s);
532  allHashesOk=0;
533  }
534  }
536  }
537 
538  if (validLines==0) {
540  I18N("Checksum file does not contain valid lines"));
541  GWEN_StringList_free(savedList);
543  return GWEN_ERROR_VERIFY;
544  }
545 
546  if (allHashesOk==0) {
548  I18N("Integrity check on folder failed"));
549  GWEN_StringList_free(savedList);
551  return GWEN_ERROR_VERIFY;
552  }
553 
554  /* check for additional files */
555  if (GWEN_StringList_Count(sl)) {
556  if (strictCheck) {
558  I18N("Folder contains %d files without checksum"),
560  GWEN_StringList_free(savedList);
562  }
563  else
565  I18N("Folder contains %d files without checksum"),
567  }
568  GWEN_StringList_free(savedList);
570 
571  return 0;
572 }
573 
574 
575 
576 
577 
578 
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:223
#define I18N(m)
Definition: error.c:42
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition: stringlist.h:51
GWEN_CRYPT_HASHALGOID
Definition: hashalgo.h:48
int GWEN_SyncIo_Connect(GWEN_SYNCIO *sio)
Definition: syncio.c:94
void GWEN_MDigest_free(GWEN_MDIGEST *md)
Definition: mdigest.c:53
#define GWEN_INHERIT_FINI(t, element)
Definition: inherit.h:238
#define GWEN_ERROR_INVALID
Definition: error.h:67
#define GWEN_DIR_SEPARATOR_S
#define GWEN_SYNCIO_FILE_FLAGS_READ
Definition: syncio_file.h:53
int(* GWEN_MDIGEST_UPDATE_FN)(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l)
Definition: mdigest_be.h:26
int GWEN_SyncIo_Read(GWEN_SYNCIO *sio, uint8_t *buffer, uint32_t size)
Definition: syncio.c:127
GWEN_MDIGEST_END_FN GWEN_MDigest_SetEndFn(GWEN_MDIGEST *md, GWEN_MDIGEST_END_FN f)
Definition: mdigest.c:168
void GWEN_MDigest_SetDigestLen(GWEN_MDIGEST *md, unsigned int l)
Definition: mdigest.c:110
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:92
#define NULL
Definition: binreloc.c:290
GWEN_MDIGEST * GWEN_MDigest_new(GWEN_CRYPT_HASHALGOID a)
Definition: mdigest.c:39
GWEN_MDIGEST_UPDATE_FN GWEN_MDigest_SetUpdateFn(GWEN_MDIGEST *md, GWEN_MDIGEST_UPDATE_FN f)
Definition: mdigest.c:181
#define GWEN_LOGDOMAIN
Definition: logger.h:35
uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
Definition: buffer.c:239
int GWEN_MDigest_Update(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l)
Definition: mdigest.c:144
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:38
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:352
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:366
GWENHYWFAR_API int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:309
uint8_t * GWEN_MDigest_GetDigestPtr(GWEN_MDIGEST *md)
Definition: mdigest.c:78
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition: stringlist.c:57
int GWEN_MDigest_Begin(GWEN_MDIGEST *md)
Definition: mdigest.c:122
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:86
struct GWEN_SYNCIO GWEN_SYNCIO
Definition: syncio.h:40
int GWEN_MDigest_HashFileTree(GWEN_MDIGEST *md, const char *folder, const char *ignoreFile, GWEN_STRINGLIST *sl)
Definition: mdigest.c:461
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition: stringlist.c:230
int GWEN_SyncIo_Helper_ReadFileToStringList(const char *fname, int maxLines, GWEN_STRINGLIST *sl)
Definition: syncio.c:411
int GWEN_Gui_ProgressLog2(uint32_t id, GWEN_LOGGER_LEVEL level, const char *fmt,...)
Definition: gui.c:951
int GWEN_MDigest_CheckFileTree(GWEN_MDIGEST *md, const char *folder, const char *checksumFile, int strictCheck, uint32_t pid)
Definition: mdigest.c:478
int GWEN_Text_EscapeToBuffer(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1326
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition: stringlist.h:54
struct GWEN_MDIGEST GWEN_MDIGEST
Definition: mdigest.h:25
int(* GWEN_MDIGEST_BEGIN_FN)(GWEN_MDIGEST *md)
Definition: mdigest_be.h:24
GWEN_CRYPT_HASHALGOID GWEN_MDigest_GetHashAlgoId(const GWEN_MDIGEST *md)
Definition: mdigest.c:70
#define GWEN_INHERIT_INIT(t, element)
Definition: inherit.h:223
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:83
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:41
void GWEN_SyncIo_free(GWEN_SYNCIO *sio)
Definition: syncio.c:76
GWENHYWFAR_API int GWEN_Directory_GetFileEntriesWithType(const char *folder, GWEN_STRINGLIST *sl, const char *mask)
GWEN_LIST2_FUNCTIONS(TYPEMAKER2_TYPE, Typemaker2_Type)
int GWEN_Buffer_Crop(GWEN_BUFFER *bf, uint32_t pos, uint32_t l)
Definition: buffer.c:973
int(* GWEN_MDIGEST_END_FN)(GWEN_MDIGEST *md)
Definition: mdigest_be.h:25
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:382
int GWEN_MDigest_End(GWEN_MDIGEST *md)
Definition: mdigest.c:133
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
unsigned int GWEN_MDigest_GetDigestSize(GWEN_MDIGEST *md)
Definition: mdigest.c:86
int GWEN_SyncIo_Disconnect(GWEN_SYNCIO *sio)
Definition: syncio.c:105
void GWEN_SyncIo_SetFlags(GWEN_SYNCIO *sio, uint32_t fl)
Definition: syncio.c:161
static int GWEN_MDigest__HashFile(GWEN_MDIGEST *md, const char *fname, GWEN_BUFFER *hbuf)
Definition: mdigest.c:279
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:359
GWEN_MDIGEST_BEGIN_FN GWEN_MDigest_SetBeginFn(GWEN_MDIGEST *md, GWEN_MDIGEST_BEGIN_FN f)
Definition: mdigest.c:155
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:164
#define GWEN_LIST_INIT(t, element)
Definition: list1.h:465
#define GWEN_ERROR_VERIFY
Definition: error.h:104
GWENHYWFAR_API GWEN_SYNCIO * GWEN_SyncIo_File_new(const char *path, GWEN_SYNCIO_FILE_CREATIONMODE cm)
#define GWEN_LIST_FUNCTIONS(t, pr)
Definition: list1.h:366
int GWEN_MDigest_PBKDF2(GWEN_MDIGEST *md, const char *password, const uint8_t *pSalt, uint32_t lSalt, uint8_t *pKey, uint32_t lKey, uint32_t iterations)
Definition: mdigest.c:194
void GWEN_MDigest_SetDigestBuffer(GWEN_MDIGEST *md, uint8_t *buf, unsigned int l)
Definition: mdigest.c:94
GWEN_STRINGLIST * GWEN_StringList_new(void)
Definition: stringlist.c:46
#define GWEN_LIST_FINI(t, element)
Definition: list1.h:474
#define GWEN_INHERIT_FUNCTIONS(t)
Definition: inherit.h:163
int GWEN_Text_ToHexBuffer(const char *src, unsigned l, GWEN_BUFFER *buf, unsigned int groupsize, char delimiter, int skipLeadingZeroes)
Definition: text.c:740
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1014
static int GWEN_MDigest__HashFileTree(GWEN_MDIGEST *md, const char *baseFolder, const char *relFolder, const char *ignoreFile, GWEN_STRINGLIST *sl)
Definition: mdigest.c:348
#define GWEN_ERROR_NOT_IMPLEMENTED
Definition: error.h:108