gwenhywfar 5.12.0
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
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;
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
99void 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
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
153int 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 const uint8_t *srcBuf, unsigned int srcLen,
167 uint8_t *dstBuf, unsigned int dstLen)
168{
169 int rv;
170 int digestLen;
171
172 assert(md);
173 assert(srcBuf && srcLen);
174 assert(dstBuf && dstLen);
175
176 if (md && srcBuf && srcLen && dstBuf && dstLen) {
177 rv=GWEN_MDigest_Begin(md);
178 if (rv<0) {
179 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
180 return rv;
181 }
182 rv=GWEN_MDigest_Update(md, srcBuf, srcLen);
183 if (rv<0) {
184 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
185 return rv;
186 }
187 rv=GWEN_MDigest_End(md);
188 if (rv<0) {
189 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
190 return rv;
191 }
192 digestLen=GWEN_MDigest_GetDigestSize(md);
193 if (dstLen<digestLen) {
194 DBG_ERROR(GWEN_LOGDOMAIN, "Provided buffer too small (%d < %d)", dstLen, digestLen);
196 }
197
198 memmove(dstBuf, GWEN_MDigest_GetDigestPtr(md), digestLen);
199 return 0;
200 }
201 else {
202 DBG_ERROR(GWEN_LOGDOMAIN, "Empty function arguments");
203 return GWEN_ERROR_INTERNAL;
204 }
205}
206
207
208
209
210
211
212
214{
216
217 assert(md);
218 assert(md->refCount);
219 of=md->beginFn;
220 md->beginFn=f;
221
222 return of;
223}
224
225
226
228{
230
231 assert(md);
232 assert(md->refCount);
233 of=md->endFn;
234 md->endFn=f;
235
236 return of;
237}
238
239
240
242{
244
245 assert(md);
246 assert(md->refCount);
247 of=md->updateFn;
248 md->updateFn=f;
249
250 return of;
251}
252
253
254
256 const char *password,
257 const uint8_t *pSalt,
258 uint32_t lSalt,
259 uint8_t *pKey,
260 uint32_t lKey,
261 uint32_t iterations)
262{
263 int rv;
264 uint8_t hash[128];
265 uint32_t hsize;
266 uint32_t i;
267
269 if (lKey>hsize || lKey>sizeof(hash)) {
270 DBG_ERROR(GWEN_LOGDOMAIN, "Derived key too long");
271 return GWEN_ERROR_INVALID;
272 }
273
274 rv=GWEN_MDigest_Begin(md);
275 if (rv<0) {
276 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
278 return rv;
279 }
280
281 /* hash password */
282 rv=GWEN_MDigest_Update(md, (const uint8_t *) password, strlen(password));
283 if (rv<0) {
284 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
286 return rv;
287 }
288
289 /* hash salt */
290 rv=GWEN_MDigest_Update(md, pSalt, lSalt);
291 if (rv<0) {
292 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
294 return rv;
295 }
296
297 rv=GWEN_MDigest_End(md);
298 if (rv<0) {
299 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
301 return rv;
302 }
303
304 /* use that hash now for the iterations */
305 memmove(hash, GWEN_MDigest_GetDigestPtr(md), hsize);
306
307 for (i=2; i<iterations; i++) {
308 rv=GWEN_MDigest_Begin(md);
309 if (rv<0) {
310 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
312 return rv;
313 }
314 rv=GWEN_MDigest_Update(md, hash, hsize);
315 if (rv<0) {
316 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
318 return rv;
319 }
320
321 rv=GWEN_MDigest_End(md);
322 if (rv<0) {
323 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
325 return rv;
326 }
327
328 /* use that hash now for the next iteration */
329 memmove(hash, GWEN_MDigest_GetDigestPtr(md), hsize);
330 }
331
332 /* done, copy key */
333 memmove(pKey, hash, lKey);
334 memset(hash, 0, sizeof(hash));
335
336 return 0;
337}
338
339
340
342 const char *fname,
343 GWEN_BUFFER *hbuf)
344{
345 GWEN_SYNCIO *sio;
346 int rv;
347 uint8_t buffer[1024];
348
351 rv=GWEN_SyncIo_Connect(sio);
352 if (rv<0) {
353 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
354 GWEN_SyncIo_free(sio);
355 return rv;
356 }
357
358 rv=GWEN_MDigest_Begin(md);
359 if (rv<0) {
360 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
362 GWEN_SyncIo_free(sio);
363 return rv;
364 }
365
366 while (1) {
367 rv=GWEN_SyncIo_Read(sio, buffer, sizeof(buffer));
368 if (rv<0) {
369 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
371 GWEN_SyncIo_free(sio);
372 return rv;
373 }
374 else if (rv==0)
375 break;
376 else {
377 rv=GWEN_MDigest_Update(md, (const uint8_t *) buffer, rv);
378 if (rv<0) {
379 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
381 GWEN_SyncIo_free(sio);
382 return rv;
383 }
384 }
385 }
386
387 rv=GWEN_MDigest_End(md);
388 if (rv<0) {
389 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
391 GWEN_SyncIo_free(sio);
392 return rv;
393 }
394
396 GWEN_SyncIo_free(sio);
397
400 hbuf, 0, 0, 0);
401 if (rv<0) {
402 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
403 return rv;
404 }
405
406 return 0;
407}
408
409
410
412 const char *baseFolder,
413 const char *relFolder,
414 const char *ignoreFile,
415 GWEN_STRINGLIST *sl)
416{
417 GWEN_STRINGLIST *files;
419 GWEN_BUFFER *pbuf;
420 uint32_t ppos;
421 uint32_t rpos;
422 int rv;
423
424 files=GWEN_StringList_new();
425 pbuf=GWEN_Buffer_new(0, 256, 0, 1);
426 GWEN_Buffer_AppendString(pbuf, baseFolder);
428 rpos=GWEN_Buffer_GetPos(pbuf);
429 if (relFolder) {
430 GWEN_Buffer_AppendString(pbuf, relFolder);
432 }
433 ppos=GWEN_Buffer_GetPos(pbuf);
434
436 if (rv<0) {
437 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
438 GWEN_Buffer_free(pbuf);
440 return rv;
441 }
442
444 while (se) {
445 const char *s;
446
448 if (s && *s) {
449 GWEN_Buffer_AppendString(pbuf, s+1);
450 if (*s=='d') {
451 if (strcasecmp(s+1, ".")!=0 && strcasecmp(s+1, "..")!=0) {
453 baseFolder,
454 GWEN_Buffer_GetStart(pbuf)+rpos,
455 ignoreFile,
456 sl);
457 if (rv<0) {
458 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
459 GWEN_Buffer_free(pbuf);
461 return rv;
462 }
463 }
464 }
465 else if (*s=='f') {
466 if (!(ignoreFile && strcasecmp(ignoreFile, s+1)==0)) {
467 GWEN_BUFFER *tbuf;
468 GWEN_BUFFER *xbuf;
469 char *p;
470
471 xbuf=GWEN_Buffer_new(0, 256, 0, 1);
473 p=GWEN_Buffer_GetStart(xbuf);
474 while (*p) {
475 if (*p=='\\')
476 *p='/';
477 p++;
478 }
479
480 tbuf=GWEN_Buffer_new(0, 256, 0, 1);
481
482 /* add relative path to line buffer */
483 GWEN_Buffer_AppendString(tbuf, "F");
485 GWEN_Buffer_free(xbuf);
486 if (rv<0) {
487 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
488 GWEN_Buffer_free(tbuf);
489 GWEN_Buffer_free(pbuf);
491 return rv;
492 }
493 GWEN_Buffer_AppendString(tbuf, ":");
494
495 /* hash file */
497 if (rv<0) {
498 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
499 GWEN_Buffer_free(tbuf);
500 GWEN_Buffer_free(pbuf);
502 return rv;
503 }
504
505 /* append line to stringlist */
507 GWEN_Buffer_free(tbuf);
508 }
509 }
510 else {
511 DBG_INFO(GWEN_LOGDOMAIN, "Unknown file type in [%s]", s);
512 }
513 GWEN_Buffer_Crop(pbuf, 0, ppos);
514 }
516 }
517
518 GWEN_Buffer_free(pbuf);
520 return 0;
521}
522
523
524
526 const char *folder,
527 const char *ignoreFile,
528 GWEN_STRINGLIST *sl)
529{
530 int rv;
531
532 rv=GWEN_MDigest__HashFileTree(md, folder, NULL, ignoreFile, sl);
533 if (rv<0) {
534 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
535 return rv;
536 }
537
538 return 0;
539}
540
541
542
544 const char *folder,
545 const char *checksumFile,
546 int strictCheck,
547 uint32_t pid)
548{
549 GWEN_STRINGLIST *sl;
550 GWEN_STRINGLIST *savedList;
551 GWEN_BUFFER *tbuf;
553 int rv;
554 int allHashesOk=1;
555 int validLines=0;
556
558
559 /* generate hash list */
560 rv=GWEN_MDigest_HashFileTree(md, folder, checksumFile, sl);
561 if (rv<0) {
563 I18N("Error unpacking program (%d)"), rv);
565 return rv;
566 }
567
568 savedList=GWEN_StringList_new();
569
570 /* read checksums from file */
571 tbuf=GWEN_Buffer_new(0, 256, 0, 1);
572 GWEN_Buffer_AppendString(tbuf, folder);
574 GWEN_Buffer_AppendString(tbuf, checksumFile);
576 -1,
577 savedList);
578 if (rv<0) {
580 I18N("Error loading checksum file (%d)"), rv);
581 GWEN_Buffer_free(tbuf);
582 GWEN_StringList_free(savedList);
584 return rv;
585 }
586 GWEN_Buffer_free(tbuf);
587
588 /* check checksums */
589 se=GWEN_StringList_FirstEntry(savedList);
590 while (se) {
591 const char *s;
592
594 if (s && *s) {
595 validLines++;
596 if (0==GWEN_StringList_RemoveString(sl, s)) {
597 DBG_ERROR(0, "Hash not found: %s", s);
598 allHashesOk=0;
599 }
600 }
602 }
603
604 if (validLines==0) {
606 I18N("Checksum file does not contain valid lines"));
607 GWEN_StringList_free(savedList);
609 return GWEN_ERROR_VERIFY;
610 }
611
612 if (allHashesOk==0) {
614 I18N("Integrity check on folder failed"));
615 GWEN_StringList_free(savedList);
617 return GWEN_ERROR_VERIFY;
618 }
619
620 /* check for additional files */
621 if (GWEN_StringList_Count(sl)) {
622 if (strictCheck) {
624 I18N("Folder contains %d files without checksum"),
626 GWEN_StringList_free(savedList);
628 }
629 else
631 I18N("Folder contains %d files without checksum"),
633 }
634 GWEN_StringList_free(savedList);
636
637 return 0;
638}
639
640
641
642
643
644
#define NULL
Definition binreloc.c:300
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition buffer.c:42
uint32_t GWEN_Buffer_GetPos(const GWEN_BUFFER *bf)
Definition buffer.c:253
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition buffer.c:89
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition buffer.c:992
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition buffer.c:235
int GWEN_Buffer_Crop(GWEN_BUFFER *bf, uint32_t pos, uint32_t l)
Definition buffer.c:950
#define DBG_INFO(dbg_logger, format,...)
Definition debug.h:181
#define DBG_ERROR(dbg_logger, format,...)
Definition debug.h:97
GWENHYWFAR_API int GWEN_Directory_GetFileEntriesWithType(const char *folder, GWEN_STRINGLIST *sl, const char *mask)
#define I18N(m)
Definition error.c:42
#define GWEN_ERROR_NOT_IMPLEMENTED
Definition error.h:108
#define GWEN_ERROR_INTERNAL
Definition error.h:125
#define GWEN_ERROR_VERIFY
Definition error.h:104
#define GWEN_ERROR_INVALID
Definition error.h:67
#define GWEN_ERROR_BUFFER_OVERFLOW
Definition error.h:79
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition buffer.h:38
GWENHYWFAR_API int GWEN_Gui_ProgressLog2(uint32_t id, GWEN_LOGGER_LEVEL level, const char *text,...)
#define GWEN_DIR_SEPARATOR_S
GWEN_CRYPT_HASHALGOID
Definition hashalgo.h:48
#define GWEN_INHERIT_FUNCTIONS(t)
Definition inherit.h:163
#define GWEN_INHERIT_INIT(t, element)
Definition inherit.h:223
#define GWEN_INHERIT_FINI(t, element)
Definition inherit.h:238
#define GWEN_LIST_FINI(t, element)
Definition list1.h:475
#define GWEN_LIST_FUNCTIONS(t, pr)
Definition list1.h:367
#define GWEN_LIST_INIT(t, element)
Definition list1.h:466
#define GWEN_LIST2_FUNCTIONS(t, pr)
Definition list2.h:99
#define GWEN_LOGDOMAIN
Definition logger.h:35
@ GWEN_LoggerLevel_Warning
Definition logger.h:69
@ GWEN_LoggerLevel_Error
Definition logger.h:68
int GWEN_MDigest_Begin(GWEN_MDIGEST *md)
Definition mdigest.c:129
void GWEN_MDigest_SetDigestBuffer(GWEN_MDIGEST *md, uint8_t *buf, unsigned int l)
Definition mdigest.c:99
void GWEN_MDigest_SetDigestLen(GWEN_MDIGEST *md, unsigned int l)
Definition mdigest.c:116
int GWEN_MDigest_CheckFileTree(GWEN_MDIGEST *md, const char *folder, const char *checksumFile, int strictCheck, uint32_t pid)
Definition mdigest.c:543
GWEN_MDIGEST_BEGIN_FN GWEN_MDigest_SetBeginFn(GWEN_MDIGEST *md, GWEN_MDIGEST_BEGIN_FN f)
Definition mdigest.c:213
int GWEN_MDigest_End(GWEN_MDIGEST *md)
Definition mdigest.c:141
unsigned int GWEN_MDigest_GetDigestSize(GWEN_MDIGEST *md)
Definition mdigest.c:90
uint8_t * GWEN_MDigest_GetDigestPtr(GWEN_MDIGEST *md)
Definition mdigest.c:81
static int GWEN_MDigest__HashFileTree(GWEN_MDIGEST *md, const char *baseFolder, const char *relFolder, const char *ignoreFile, GWEN_STRINGLIST *sl)
Definition mdigest.c:411
int GWEN_MDigest_HashFileTree(GWEN_MDIGEST *md, const char *folder, const char *ignoreFile, GWEN_STRINGLIST *sl)
Definition mdigest.c:525
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:241
int GWEN_MDigest_Digest(GWEN_MDIGEST *md, const uint8_t *srcBuf, unsigned int srcLen, uint8_t *dstBuf, unsigned int dstLen)
Definition mdigest.c:165
GWEN_MDIGEST_END_FN GWEN_MDigest_SetEndFn(GWEN_MDIGEST *md, GWEN_MDIGEST_END_FN f)
Definition mdigest.c:227
void GWEN_MDigest_free(GWEN_MDIGEST *md)
Definition mdigest.c:54
static int GWEN_MDigest__HashFile(GWEN_MDIGEST *md, const char *fname, GWEN_BUFFER *hbuf)
Definition mdigest.c:341
GWEN_CRYPT_HASHALGOID GWEN_MDigest_GetHashAlgoId(const GWEN_MDIGEST *md)
Definition mdigest.c:72
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:255
int GWEN_MDigest_Update(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l)
Definition mdigest.c:153
struct GWEN_MDIGEST GWEN_MDIGEST
Definition mdigest.h:25
int(* GWEN_MDIGEST_UPDATE_FN)(GWEN_MDIGEST *md, const uint8_t *buf, unsigned int l)
Definition mdigest_be.h:26
int(* GWEN_MDIGEST_END_FN)(GWEN_MDIGEST *md)
Definition mdigest_be.h:25
int(* GWEN_MDIGEST_BEGIN_FN)(GWEN_MDIGEST *md)
Definition mdigest_be.h:24
#define GWEN_FREE_OBJECT(varname)
Definition memory.h:61
#define GWEN_NEW_OBJECT(typ, varname)
Definition memory.h:55
void GWEN_StringList_free(GWEN_STRINGLIST *sl)
Definition stringlist.c:62
const char * GWEN_StringListEntry_Data(const GWEN_STRINGLISTENTRY *se)
Definition stringlist.c:406
GWEN_STRINGLISTENTRY * GWEN_StringListEntry_Next(const GWEN_STRINGLISTENTRY *se)
Definition stringlist.c:398
unsigned int GWEN_StringList_Count(const GWEN_STRINGLIST *sl)
Definition stringlist.c:427
int GWEN_StringList_AppendString(GWEN_STRINGLIST *sl, const char *s, int take, int checkDouble)
Definition stringlist.c:245
int GWEN_StringList_RemoveString(GWEN_STRINGLIST *sl, const char *s)
Definition stringlist.c:326
GWEN_STRINGLISTENTRY * GWEN_StringList_FirstEntry(const GWEN_STRINGLIST *sl)
Definition stringlist.c:390
GWEN_STRINGLIST * GWEN_StringList_new(void)
Definition stringlist.c:50
struct GWEN_STRINGLISTENTRYSTRUCT GWEN_STRINGLISTENTRY
Definition stringlist.h:53
struct GWEN_STRINGLISTSTRUCT GWEN_STRINGLIST
Definition stringlist.h:56
void GWEN_SyncIo_SetFlags(GWEN_SYNCIO *sio, uint32_t fl)
Definition syncio.c:170
int GWEN_SyncIo_Connect(GWEN_SYNCIO *sio)
Definition syncio.c:97
int GWEN_SyncIo_Helper_ReadFileToStringList(const char *fname, int maxLines, GWEN_STRINGLIST *sl)
Definition syncio.c:438
void GWEN_SyncIo_free(GWEN_SYNCIO *sio)
Definition syncio.c:78
int GWEN_SyncIo_Read(GWEN_SYNCIO *sio, uint8_t *buffer, uint32_t size)
Definition syncio.c:133
int GWEN_SyncIo_Disconnect(GWEN_SYNCIO *sio)
Definition syncio.c:109
struct GWEN_SYNCIO GWEN_SYNCIO
Definition syncio.h:40
@ GWEN_SyncIo_File_CreationMode_OpenExisting
Definition syncio_file.h:38
GWENHYWFAR_API GWEN_SYNCIO * GWEN_SyncIo_File_new(const char *path, GWEN_SYNCIO_FILE_CREATIONMODE cm)
#define GWEN_SYNCIO_FILE_FLAGS_READ
Definition syncio_file.h:53
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_Text_EscapeToBuffer(const char *src, GWEN_BUFFER *buf)
Definition text.c:1376