gwenhywfar  4.99.25rc9
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)
34 
35 
36 
37 
38 
40 {
41  GWEN_MDIGEST *md;
42 
44  md->refCount=1;
47 
48  md->hashAlgoId=a;
49  return md;
50 }
51 
52 
53 
55 {
56  if (md) {
57  assert(md->refCount);
58  if (md->refCount==1) {
60  free(md->pDigest);
61  md->refCount=0;
63  GWEN_FREE_OBJECT(md);
64  }
65  else
66  md->refCount--;
67  }
68 }
69 
70 
71 
73 {
74  assert(md);
75  assert(md->refCount);
76  return md->hashAlgoId;
77 }
78 
79 
80 
82 {
83  assert(md);
84  assert(md->refCount);
85  return md->pDigest;
86 }
87 
88 
89 
91 {
92  assert(md);
93  assert(md->refCount);
94  return md->lDigest;
95 }
96 
97 
98 
99 void GWEN_MDigest_SetDigestBuffer(GWEN_MDIGEST *md, uint8_t *buf, unsigned int l)
100 {
101  assert(md);
102  assert(md->refCount);
103 
104  if (l) {
105  assert(buf);
106  }
107 
108  if (md->pDigest && md->lDigest)
109  free(md->pDigest);
110  md->pDigest=buf;
111  md->lDigest=l;
112 }
113 
114 
115 
116 void GWEN_MDigest_SetDigestLen(GWEN_MDIGEST *md, unsigned int l)
117 {
118  assert(md);
119  assert(md->refCount);
120 
121  if (md->pDigest && md->lDigest)
122  free(md->pDigest);
123  md->pDigest=NULL;
124  md->lDigest=l;
125 }
126 
127 
128 
130 {
131  assert(md);
132  assert(md->refCount);
133  if (md->beginFn)
134  return md->beginFn(md);
135  else
137 }
138 
139 
140 
142 {
143  assert(md);
144  assert(md->refCount);
145  if (md->endFn)
146  return md->endFn(md);
147  else
149 }
150 
151 
152 
153 int GWEN_MDigest_Update(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l)
154 {
155  assert(md);
156  assert(md->refCount);
157  if (md->updateFn)
158  return md->updateFn(md, buf, l);
159  else
161 }
162 
163 
164 
166 {
168 
169  assert(md);
170  assert(md->refCount);
171  of=md->beginFn;
172  md->beginFn=f;
173 
174  return of;
175 }
176 
177 
178 
180 {
182 
183  assert(md);
184  assert(md->refCount);
185  of=md->endFn;
186  md->endFn=f;
187 
188  return of;
189 }
190 
191 
192 
194 {
196 
197  assert(md);
198  assert(md->refCount);
199  of=md->updateFn;
200  md->updateFn=f;
201 
202  return of;
203 }
204 
205 
206 
208  const char *password,
209  const uint8_t *pSalt,
210  uint32_t lSalt,
211  uint8_t *pKey,
212  uint32_t lKey,
213  uint32_t iterations)
214 {
215  int rv;
216  uint8_t hash[128];
217  uint32_t hsize;
218  uint32_t i;
219 
220  hsize=GWEN_MDigest_GetDigestSize(md);
221  if (lKey>hsize || lKey>sizeof(hash)) {
222  DBG_ERROR(GWEN_LOGDOMAIN, "Derived key too long");
223  return GWEN_ERROR_INVALID;
224  }
225 
226  rv=GWEN_MDigest_Begin(md);
227  if (rv<0) {
228  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
229  GWEN_MDigest_End(md);
230  return rv;
231  }
232 
233  /* hash password */
234  rv=GWEN_MDigest_Update(md, (const uint8_t *) password, strlen(password));
235  if (rv<0) {
236  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
237  GWEN_MDigest_End(md);
238  return rv;
239  }
240 
241  /* hash salt */
242  rv=GWEN_MDigest_Update(md, pSalt, lSalt);
243  if (rv<0) {
244  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
245  GWEN_MDigest_End(md);
246  return rv;
247  }
248 
249  rv=GWEN_MDigest_End(md);
250  if (rv<0) {
251  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
252  GWEN_MDigest_End(md);
253  return rv;
254  }
255 
256  /* use that hash now for the iterations */
257  memmove(hash, GWEN_MDigest_GetDigestPtr(md), hsize);
258 
259  for (i=2; i<iterations; i++) {
260  rv=GWEN_MDigest_Begin(md);
261  if (rv<0) {
262  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
263  GWEN_MDigest_End(md);
264  return rv;
265  }
266  rv=GWEN_MDigest_Update(md, hash, hsize);
267  if (rv<0) {
268  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
269  GWEN_MDigest_End(md);
270  return rv;
271  }
272 
273  rv=GWEN_MDigest_End(md);
274  if (rv<0) {
275  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
276  GWEN_MDigest_End(md);
277  return rv;
278  }
279 
280  /* use that hash now for the next iteration */
281  memmove(hash, GWEN_MDigest_GetDigestPtr(md), hsize);
282  }
283 
284  /* done, copy key */
285  memmove(pKey, hash, lKey);
286  memset(hash, 0, sizeof(hash));
287 
288  return 0;
289 }
290 
291 
292 
294  const char *fname,
295  GWEN_BUFFER *hbuf)
296 {
297  GWEN_SYNCIO *sio;
298  int rv;
299  uint8_t buffer[1024];
300 
303  rv=GWEN_SyncIo_Connect(sio);
304  if (rv<0) {
305  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
306  GWEN_SyncIo_free(sio);
307  return rv;
308  }
309 
310  rv=GWEN_MDigest_Begin(md);
311  if (rv<0) {
312  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
314  GWEN_SyncIo_free(sio);
315  return rv;
316  }
317 
318  while (1) {
319  rv=GWEN_SyncIo_Read(sio, buffer, sizeof(buffer));
320  if (rv<0) {
321  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
323  GWEN_SyncIo_free(sio);
324  return rv;
325  }
326  else if (rv==0)
327  break;
328  else {
329  rv=GWEN_MDigest_Update(md, (const uint8_t *) buffer, rv);
330  if (rv<0) {
331  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
333  GWEN_SyncIo_free(sio);
334  return rv;
335  }
336  }
337  }
338 
339  rv=GWEN_MDigest_End(md);
340  if (rv<0) {
341  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
343  GWEN_SyncIo_free(sio);
344  return rv;
345  }
346 
348  GWEN_SyncIo_free(sio);
349 
350  rv=GWEN_Text_ToHexBuffer((const char *) GWEN_MDigest_GetDigestPtr(md),
352  hbuf, 0, 0, 0);
353  if (rv<0) {
354  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
355  return rv;
356  }
357 
358  return 0;
359 }
360 
361 
362 
364  const char *baseFolder,
365  const char *relFolder,
366  const char *ignoreFile,
367  GWEN_STRINGLIST *sl)
368 {
369  GWEN_STRINGLIST *files;
371  GWEN_BUFFER *pbuf;
372  uint32_t ppos;
373  uint32_t rpos;
374  int rv;
375 
376  files=GWEN_StringList_new();
377  pbuf=GWEN_Buffer_new(0, 256, 0, 1);
378  GWEN_Buffer_AppendString(pbuf, baseFolder);
380  rpos=GWEN_Buffer_GetPos(pbuf);
381  if (relFolder) {
382  GWEN_Buffer_AppendString(pbuf, relFolder);
384  }
385  ppos=GWEN_Buffer_GetPos(pbuf);
386 
388  if (rv<0) {
389  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
390  GWEN_Buffer_free(pbuf);
391  GWEN_StringList_free(files);
392  return rv;
393  }
394 
395  se=GWEN_StringList_FirstEntry(files);
396  while (se) {
397  const char *s;
398 
400  if (s && *s) {
401  GWEN_Buffer_AppendString(pbuf, s+1);
402  if (*s=='d') {
403  if (strcasecmp(s+1, ".")!=0 && strcasecmp(s+1, "..")!=0) {
405  baseFolder,
406  GWEN_Buffer_GetStart(pbuf)+rpos,
407  ignoreFile,
408  sl);
409  if (rv<0) {
410  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
411  GWEN_Buffer_free(pbuf);
412  GWEN_StringList_free(files);
413  return rv;
414  }
415  }
416  }
417  else if (*s=='f') {
418  if (!(ignoreFile && strcasecmp(ignoreFile, s+1)==0)) {
419  GWEN_BUFFER *tbuf;
420  GWEN_BUFFER *xbuf;
421  char *p;
422 
423  xbuf=GWEN_Buffer_new(0, 256, 0, 1);
425  p=GWEN_Buffer_GetStart(xbuf);
426  while (*p) {
427  if (*p=='\\')
428  *p='/';
429  p++;
430  }
431 
432  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
433 
434  /* add relative path to line buffer */
435  GWEN_Buffer_AppendString(tbuf, "F");
437  GWEN_Buffer_free(xbuf);
438  if (rv<0) {
439  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
440  GWEN_Buffer_free(tbuf);
441  GWEN_Buffer_free(pbuf);
442  GWEN_StringList_free(files);
443  return rv;
444  }
445  GWEN_Buffer_AppendString(tbuf, ":");
446 
447  /* hash file */
448  rv=GWEN_MDigest__HashFile(md, GWEN_Buffer_GetStart(pbuf), tbuf);
449  if (rv<0) {
450  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
451  GWEN_Buffer_free(tbuf);
452  GWEN_Buffer_free(pbuf);
453  GWEN_StringList_free(files);
454  return rv;
455  }
456 
457  /* append line to stringlist */
459  GWEN_Buffer_free(tbuf);
460  }
461  }
462  else {
463  DBG_INFO(GWEN_LOGDOMAIN, "Unknown file type in [%s]", s);
464  }
465  GWEN_Buffer_Crop(pbuf, 0, ppos);
466  }
468  }
469 
470  GWEN_Buffer_free(pbuf);
471  GWEN_StringList_free(files);
472  return 0;
473 }
474 
475 
476 
478  const char *folder,
479  const char *ignoreFile,
480  GWEN_STRINGLIST *sl)
481 {
482  int rv;
483 
484  rv=GWEN_MDigest__HashFileTree(md, folder, NULL, ignoreFile, sl);
485  if (rv<0) {
486  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
487  return rv;
488  }
489 
490  return 0;
491 }
492 
493 
494 
496  const char *folder,
497  const char *checksumFile,
498  int strictCheck,
499  uint32_t pid)
500 {
501  GWEN_STRINGLIST *sl;
502  GWEN_STRINGLIST *savedList;
503  GWEN_BUFFER *tbuf;
505  int rv;
506  int allHashesOk=1;
507  int validLines=0;
508 
509  sl=GWEN_StringList_new();
510 
511  /* generate hash list */
512  rv=GWEN_MDigest_HashFileTree(md, folder, checksumFile, sl);
513  if (rv<0) {
515  I18N("Error unpacking program (%d)"), rv);
517  return rv;
518  }
519 
520  savedList=GWEN_StringList_new();
521 
522  /* read checksums from file */
523  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
524  GWEN_Buffer_AppendString(tbuf, folder);
526  GWEN_Buffer_AppendString(tbuf, checksumFile);
528  -1,
529  savedList);
530  if (rv<0) {
532  I18N("Error loading checksum file (%d)"), rv);
533  GWEN_Buffer_free(tbuf);
534  GWEN_StringList_free(savedList);
536  return rv;
537  }
538  GWEN_Buffer_free(tbuf);
539 
540  /* check checksums */
541  se=GWEN_StringList_FirstEntry(savedList);
542  while (se) {
543  const char *s;
544 
546  if (s && *s) {
547  validLines++;
548  if (0==GWEN_StringList_RemoveString(sl, s)) {
549  DBG_ERROR(0, "Hash not found: %s", s);
550  allHashesOk=0;
551  }
552  }
554  }
555 
556  if (validLines==0) {
558  I18N("Checksum file does not contain valid lines"));
559  GWEN_StringList_free(savedList);
561  return GWEN_ERROR_VERIFY;
562  }
563 
564  if (allHashesOk==0) {
566  I18N("Integrity check on folder failed"));
567  GWEN_StringList_free(savedList);
569  return GWEN_ERROR_VERIFY;
570  }
571 
572  /* check for additional files */
573  if (GWEN_StringList_Count(sl)) {
574  if (strictCheck) {
576  I18N("Folder contains %d files without checksum"),
578  GWEN_StringList_free(savedList);
580  }
581  else
583  I18N("Folder contains %d files without checksum"),
585  }
586  GWEN_StringList_free(savedList);
588 
589  return 0;
590 }
591 
592 
593 
594 
595 
596 
int(* GWEN_MDIGEST_UPDATE_FN)(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l)
Definition: mdigest_be.h:26
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
#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:97
void GWEN_MDigest_free(GWEN_MDIGEST *md)
Definition: mdigest.c:54
#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_SyncIo_Read(GWEN_SYNCIO *sio, uint8_t *buffer, uint32_t size)
Definition: syncio.c:133
GWEN_MDIGEST_END_FN GWEN_MDigest_SetEndFn(GWEN_MDIGEST *md, GWEN_MDIGEST_END_FN f)
Definition: mdigest.c:179
void GWEN_MDigest_SetDigestLen(GWEN_MDIGEST *md, unsigned int l)
Definition: mdigest.c:116
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:297
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:193
#define GWEN_LOGDOMAIN
Definition: logger.h:35
uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
Definition: buffer.c:253
int GWEN_MDigest_Update(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l)
Definition: mdigest.c:153
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:366
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:382
GWENHYWFAR_API int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl, const char *s)
Definition: stringlist.c:322
uint8_t * GWEN_MDigest_GetDigestPtr(GWEN_MDIGEST *md)
Definition: mdigest.c:81
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition: stringlist.c:58
int GWEN_MDigest_Begin(GWEN_MDIGEST *md)
Definition: mdigest.c:129
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
struct GWEN_SYNCIO GWEN_SYNCIO
Definition: syncio.h:40
int(* GWEN_MDIGEST_END_FN)(GWEN_MDIGEST *md)
Definition: mdigest_be.h:25
int GWEN_MDigest_HashFileTree(GWEN_MDIGEST *md, const char *folder, const char *ignoreFile, GWEN_STRINGLIST *sl)
Definition: mdigest.c:477
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition: stringlist.c:241
int GWEN_SyncIo_Helper_ReadFileToStringList(const char *fname, int maxLines, GWEN_STRINGLIST *sl)
Definition: syncio.c:438
int GWEN_Gui_ProgressLog2(uint32_t id, GWEN_LOGGER_LEVEL level, const char *fmt,...)
Definition: gui.c:1015
int GWEN_MDigest_CheckFileTree(GWEN_MDIGEST *md, const char *folder, const char *checksumFile, int strictCheck, uint32_t pid)
Definition: mdigest.c:495
int GWEN_Text_EscapeToBuffer(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1376
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition: stringlist.h:54
struct GWEN_MDIGEST GWEN_MDIGEST
Definition: mdigest.h:25
GWEN_CRYPT_HASHALGOID GWEN_MDigest_GetHashAlgoId(const GWEN_MDIGEST *md)
Definition: mdigest.c:72
#define GWEN_INHERIT_INIT(t, element)
Definition: inherit.h:223
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:85
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:41
void GWEN_SyncIo_free(GWEN_SYNCIO *sio)
Definition: syncio.c:78
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:1020
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
Definition: stringlist.c:403
int GWEN_MDigest_End(GWEN_MDIGEST *md)
Definition: mdigest.c:141
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
int(* GWEN_MDIGEST_BEGIN_FN)(GWEN_MDIGEST *md)
Definition: mdigest_be.h:24
unsigned int GWEN_MDigest_GetDigestSize(GWEN_MDIGEST *md)
Definition: mdigest.c:90
int GWEN_SyncIo_Disconnect(GWEN_SYNCIO *sio)
Definition: syncio.c:109
void GWEN_SyncIo_SetFlags(GWEN_SYNCIO *sio, uint32_t fl)
Definition: syncio.c:170
static int GWEN_MDigest__HashFile(GWEN_MDIGEST *md, const char *fname, GWEN_BUFFER *hbuf)
Definition: mdigest.c:293
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition: stringlist.c:374
GWEN_MDIGEST_BEGIN_FN GWEN_MDigest_SetBeginFn(GWEN_MDIGEST *md, GWEN_MDIGEST_BEGIN_FN f)
Definition: mdigest.c:165
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:178
#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:207
void GWEN_MDigest_SetDigestBuffer(GWEN_MDIGEST *md, uint8_t *buf, unsigned int l)
Definition: mdigest.c:99
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:777
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1062
static int GWEN_MDigest__HashFileTree(GWEN_MDIGEST *md, const char *baseFolder, const char *relFolder, const char *ignoreFile, GWEN_STRINGLIST *sl)
Definition: mdigest.c:363
#define GWEN_ERROR_NOT_IMPLEMENTED
Definition: error.h:108