gwenhywfar  4.8.0beta
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) {
57  free(md->pDigest);
58  md->refCount=0;
59  GWEN_FREE_OBJECT(md);
60  }
61  else
62  md->refCount--;
63  }
64 }
65 
66 
67 
69  assert(md);
70  assert(md->refCount);
71  return md->hashAlgoId;
72 }
73 
74 
75 
77  assert(md);
78  assert(md->refCount);
79  return md->pDigest;
80 }
81 
82 
83 
85  assert(md);
86  assert(md->refCount);
87  return md->lDigest;
88 }
89 
90 
91 
92 void GWEN_MDigest_SetDigestBuffer(GWEN_MDIGEST *md, uint8_t *buf, unsigned int l) {
93  assert(md);
94  assert(md->refCount);
95 
96  if (l) {
97  assert(buf);
98  }
99 
100  if (md->pDigest && md->lDigest)
101  free(md->pDigest);
102  md->pDigest=buf;
103  md->lDigest=l;
104 }
105 
106 
107 
108 void GWEN_MDigest_SetDigestLen(GWEN_MDIGEST *md, unsigned int l) {
109  assert(md);
110  assert(md->refCount);
111 
112  if (md->pDigest && md->lDigest)
113  free(md->pDigest);
114  md->pDigest=NULL;
115  md->lDigest=l;
116 }
117 
118 
119 
121  assert(md);
122  assert(md->refCount);
123  if (md->beginFn)
124  return md->beginFn(md);
125  else
127 }
128 
129 
130 
132  assert(md);
133  assert(md->refCount);
134  if (md->endFn)
135  return md->endFn(md);
136  else
138 }
139 
140 
141 
142 int GWEN_MDigest_Update(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l) {
143  assert(md);
144  assert(md->refCount);
145  if (md->updateFn)
146  return md->updateFn(md, buf, l);
147  else
149 }
150 
151 
152 
155 
156  assert(md);
157  assert(md->refCount);
158  of=md->beginFn;
159  md->beginFn=f;
160 
161  return of;
162 }
163 
164 
165 
168 
169  assert(md);
170  assert(md->refCount);
171  of=md->endFn;
172  md->endFn=f;
173 
174  return of;
175 }
176 
177 
178 
181 
182  assert(md);
183  assert(md->refCount);
184  of=md->updateFn;
185  md->updateFn=f;
186 
187  return of;
188 }
189 
190 
191 
193  const char *password,
194  const uint8_t *pSalt,
195  uint32_t lSalt,
196  uint8_t *pKey,
197  uint32_t lKey,
198  uint32_t iterations) {
199  int rv;
200  uint8_t hash[128];
201  uint32_t hsize;
202  uint32_t i;
203 
204  hsize=GWEN_MDigest_GetDigestSize(md);
205  if (lKey>hsize || lKey>sizeof(hash)) {
206  DBG_ERROR(GWEN_LOGDOMAIN, "Derived key too long");
207  return GWEN_ERROR_INVALID;
208  }
209 
210  rv=GWEN_MDigest_Begin(md);
211  if (rv<0) {
212  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
213  GWEN_MDigest_End(md);
214  return rv;
215  }
216 
217  /* hash password */
218  rv=GWEN_MDigest_Update(md, (const uint8_t*) password, strlen(password));
219  if (rv<0) {
220  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
221  GWEN_MDigest_End(md);
222  return rv;
223  }
224 
225  /* hash salt */
226  rv=GWEN_MDigest_Update(md, pSalt, lSalt);
227  if (rv<0) {
228  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
229  GWEN_MDigest_End(md);
230  return rv;
231  }
232 
233  rv=GWEN_MDigest_End(md);
234  if (rv<0) {
235  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
236  GWEN_MDigest_End(md);
237  return rv;
238  }
239 
240  /* use that hash now for the iterations */
241  memmove(hash, GWEN_MDigest_GetDigestPtr(md), hsize);
242 
243  for (i=2; i<iterations; i++) {
244  rv=GWEN_MDigest_Begin(md);
245  if (rv<0) {
246  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
247  GWEN_MDigest_End(md);
248  return rv;
249  }
250  rv=GWEN_MDigest_Update(md, hash, hsize);
251  if (rv<0) {
252  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
253  GWEN_MDigest_End(md);
254  return rv;
255  }
256 
257  rv=GWEN_MDigest_End(md);
258  if (rv<0) {
259  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
260  GWEN_MDigest_End(md);
261  return rv;
262  }
263 
264  /* use that hash now for the next iteration */
265  memmove(hash, GWEN_MDigest_GetDigestPtr(md), hsize);
266  }
267 
268  /* done, copy key */
269  memmove(pKey, hash, lKey);
270  memset(hash, 0, sizeof(hash));
271 
272  return 0;
273 }
274 
275 
276 
278  const char *fname,
279  GWEN_BUFFER *hbuf) {
280  GWEN_SYNCIO *sio;
281  int rv;
282  uint8_t buffer[1024];
283 
286  rv=GWEN_SyncIo_Connect(sio);
287  if (rv<0) {
288  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
289  GWEN_SyncIo_free(sio);
290  return rv;
291  }
292 
293  rv=GWEN_MDigest_Begin(md);
294  if (rv<0) {
295  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
297  GWEN_SyncIo_free(sio);
298  return rv;
299  }
300 
301  while(1) {
302  rv=GWEN_SyncIo_Read(sio, buffer, sizeof(buffer));
303  if (rv<0) {
304  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
306  GWEN_SyncIo_free(sio);
307  return rv;
308  }
309  else if (rv==0)
310  break;
311  else {
312  rv=GWEN_MDigest_Update(md, (const uint8_t*) buffer, rv);
313  if (rv<0) {
314  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
316  GWEN_SyncIo_free(sio);
317  return rv;
318  }
319  }
320  }
321 
322  rv=GWEN_MDigest_End(md);
323  if (rv<0) {
324  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
326  GWEN_SyncIo_free(sio);
327  return rv;
328  }
329 
331  GWEN_SyncIo_free(sio);
332 
335  hbuf, 0, 0, 0);
336  if (rv<0) {
337  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
338  return rv;
339  }
340 
341  return 0;
342 }
343 
344 
345 
347  const char *baseFolder,
348  const char *relFolder,
349  const char *ignoreFile,
350  GWEN_STRINGLIST *sl) {
351  GWEN_STRINGLIST *files;
353  GWEN_BUFFER *pbuf;
354  uint32_t ppos;
355  uint32_t rpos;
356  int rv;
357 
358  files=GWEN_StringList_new();
359  pbuf=GWEN_Buffer_new(0, 256, 0, 1);
360  GWEN_Buffer_AppendString(pbuf, baseFolder);
362  rpos=GWEN_Buffer_GetPos(pbuf);
363  if (relFolder) {
364  GWEN_Buffer_AppendString(pbuf, relFolder);
366  }
367  ppos=GWEN_Buffer_GetPos(pbuf);
368 
370  if (rv<0) {
371  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
372  GWEN_Buffer_free(pbuf);
373  GWEN_StringList_free(files);
374  return rv;
375  }
376 
377  se=GWEN_StringList_FirstEntry(files);
378  while(se) {
379  const char *s;
380 
382  if (s && *s) {
383  GWEN_Buffer_AppendString(pbuf, s+1);
384  if (*s=='d') {
385  if (strcasecmp(s+1, ".")!=0 && strcasecmp(s+1, "..")!=0) {
387  baseFolder,
388  GWEN_Buffer_GetStart(pbuf)+rpos,
389  ignoreFile,
390  sl);
391  if (rv<0) {
392  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
393  GWEN_Buffer_free(pbuf);
394  GWEN_StringList_free(files);
395  return rv;
396  }
397  }
398  }
399  else if (*s=='f') {
400  if (!(ignoreFile && strcasecmp(ignoreFile, s+1)==0)) {
401  GWEN_BUFFER *tbuf;
402  GWEN_BUFFER *xbuf;
403  char *p;
404 
405  xbuf=GWEN_Buffer_new(0, 256, 0, 1);
407  p=GWEN_Buffer_GetStart(xbuf);
408  while(*p) {
409  if (*p=='\\')
410  *p='/';
411  p++;
412  }
413 
414  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
415 
416  /* add relative path to line buffer */
417  GWEN_Buffer_AppendString(tbuf, "F");
419  GWEN_Buffer_free(xbuf);
420  if (rv<0) {
421  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
422  GWEN_Buffer_free(tbuf);
423  GWEN_Buffer_free(pbuf);
424  GWEN_StringList_free(files);
425  return rv;
426  }
427  GWEN_Buffer_AppendString(tbuf, ":");
428 
429  /* hash file */
430  rv=GWEN_MDigest__HashFile(md, GWEN_Buffer_GetStart(pbuf), tbuf);
431  if (rv<0) {
432  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
433  GWEN_Buffer_free(tbuf);
434  GWEN_Buffer_free(pbuf);
435  GWEN_StringList_free(files);
436  return rv;
437  }
438 
439  /* append line to stringlist */
441  GWEN_Buffer_free(tbuf);
442  }
443  }
444  else {
445  DBG_INFO(GWEN_LOGDOMAIN, "Unknown file type in [%s]", s);
446  }
447  GWEN_Buffer_Crop(pbuf, 0, ppos);
448  }
450  }
451 
452  GWEN_Buffer_free(pbuf);
453  GWEN_StringList_free(files);
454  return 0;
455 }
456 
457 
458 
460  const char *folder,
461  const char *ignoreFile,
462  GWEN_STRINGLIST *sl) {
463  int rv;
464 
465  rv=GWEN_MDigest__HashFileTree(md, folder, NULL, ignoreFile, sl);
466  if (rv<0) {
467  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
468  return rv;
469  }
470 
471  return 0;
472 }
473 
474 
475 
477  const char *folder,
478  const char *checksumFile,
479  int strictCheck,
480  uint32_t pid) {
481  GWEN_STRINGLIST *sl;
482  GWEN_STRINGLIST *savedList;
483  GWEN_BUFFER *tbuf;
485  int rv;
486  int allHashesOk=1;
487  int validLines=0;
488 
489  sl=GWEN_StringList_new();
490 
491  /* generate hash list */
492  rv=GWEN_MDigest_HashFileTree(md, folder, checksumFile, sl);
493  if (rv<0) {
495  I18N("Error unpacking program (%d)"), rv);
497  return rv;
498  }
499 
500  savedList=GWEN_StringList_new();
501 
502  /* read checksums from file */
503  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
504  GWEN_Buffer_AppendString(tbuf, folder);
506  GWEN_Buffer_AppendString(tbuf, checksumFile);
508  -1,
509  savedList);
510  if (rv<0) {
512  I18N("Error loading checksum file (%d)"), rv);
513  GWEN_Buffer_free(tbuf);
514  GWEN_StringList_free(savedList);
516  return rv;
517  }
518  GWEN_Buffer_free(tbuf);
519 
520  /* check checksums */
521  se=GWEN_StringList_FirstEntry(savedList);
522  while(se) {
523  const char *s;
524 
526  if (s && *s) {
527  validLines++;
528  if (0==GWEN_StringList_RemoveString(sl, s)) {
529  DBG_ERROR(0, "Hash not found: %s", s);
530  allHashesOk=0;
531  }
532  }
534  }
535 
536  if (validLines==0) {
538  I18N("Checksum file does not contain valid lines"));
539  GWEN_StringList_free(savedList);
541  return GWEN_ERROR_VERIFY;
542  }
543 
544  if (allHashesOk==0) {
546  I18N("Integrity check on folder failed"));
547  GWEN_StringList_free(savedList);
549  return GWEN_ERROR_VERIFY;
550  }
551 
552  /* check for additional files */
553  if (GWEN_StringList_Count(sl)) {
554  if (strictCheck) {
556  I18N("Folder contains %d files without checksum"),
558  GWEN_StringList_free(savedList);
560  }
561  else
563  I18N("Folder contains %d files without checksum"),
565  }
566  GWEN_StringList_free(savedList);
568 
569  return 0;
570 }
571 
572 
573 
574 
575 
576