1 /*
2  * Copyright 2018 Jonathan Dieter <jdieter@gmail.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  1. Redistributions of source code must retain the above copyright notice,
8  *     this list of conditions and the following disclaimer.
9  *
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <stdint.h>
30 #include <stdbool.h>
31 #include <string.h>
32 #include <zck.h>
33 
34 #include "zck_private.h"
35 
36 /***** If we're not using OpenSSL, use bundled sha libraries *****/
37 #ifndef ZCHUNK_OPENSSL
38 #include "sha1/sha1.h"
39 #include "sha2/sha2.h"
40 #define SHA256_CTX sha256_ctx
41 #define SHA256_Init sha256_init
42 #define SHA256_Update sha256_update
SHA256_Final(unsigned char * md,SHA256_CTX * c)43 static void SHA256_Final(unsigned char *md, SHA256_CTX *c) {
44     sha256_final(c, md);
45 }
46 #define SHA512_CTX sha512_ctx
47 #define SHA512_Init sha512_init
48 #define SHA512_Update sha512_update
SHA512_Final(unsigned char * md,SHA512_CTX * c)49 static void SHA512_Final(unsigned char *md, SHA512_CTX *c) {
50     sha512_final(c, md);
51 }
52 /***** If we are using OpenSSL, set the defines accordingly *****/
53 #else
54 #include <openssl/sha.h>
55 #define SHA512_DIGEST_SIZE SHA512_DIGEST_LENGTH
56 #define SHA256_DIGEST_SIZE SHA256_DIGEST_LENGTH
57 #define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
58 #define sha1_byte void
59 #endif
60 
61 /* This needs to be updated to the largest hash size every time a new hash type
62  * is added */
get_max_hash_size()63 int get_max_hash_size() {
64     return SHA512_DIGEST_SIZE;
65 }
66 
67 static char unknown[] = "Unknown(\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
68 
69 const static char *HASH_NAME[] = {
70     "SHA-1",
71     "SHA-256",
72     "SHA-512",
73     "SHA-512/128"
74 };
75 
validate_checksums(zckCtx * zck,zck_log_type bad_checksums)76 static int validate_checksums(zckCtx *zck, zck_log_type bad_checksums) {
77     VALIDATE_READ_BOOL(zck);
78     char buf[BUF_SIZE] = {0};
79 
80     if(zck->data_offset == 0) {
81         set_error(zck, "Header hasn't been read yet");
82         return 0;
83     }
84 
85     if(!hash_init(zck, &(zck->check_full_hash), &(zck->hash_type)))
86         return 0;
87 
88     if(!seek_data(zck, zck->data_offset, SEEK_SET))
89         return 0;
90 
91     /* Check each chunk checksum */
92     bool all_good = true;
93     for(zckChunk *idx = zck->index.first; idx; idx = idx->next) {
94         if(idx == zck->index.first && idx->length == 0) {
95             idx->valid = 1;
96             continue;
97         }
98 
99         if(!hash_init(zck, &(zck->check_chunk_hash), &(zck->chunk_hash_type)))
100             return 0;
101 
102         size_t rlen = 0;
103         while(rlen < idx->comp_length) {
104             size_t rsize = BUF_SIZE;
105             if(BUF_SIZE > idx->comp_length - rlen)
106                 rsize = idx->comp_length - rlen;
107             if(read_data(zck, buf, rsize) != rsize)
108                 zck_log(ZCK_LOG_DEBUG, "No more data");
109             if(!hash_update(zck, &(zck->check_chunk_hash), buf, rsize))
110                 return 0;
111             if(!hash_update(zck, &(zck->check_full_hash), buf, rsize))
112                 return 0;
113             rlen += rsize;
114         }
115         int valid_chunk = validate_chunk(idx, bad_checksums);
116         if(!valid_chunk)
117             return 0;
118         idx->valid = valid_chunk;
119         if(all_good && valid_chunk != 1)
120             all_good = false;
121     }
122     int valid_file = -1;
123     if(all_good) {
124         /* Check data checksum */
125         valid_file = validate_file(zck, bad_checksums);
126         if(!valid_file)
127             return 0;
128 
129         /* If data checksum failed, invalidate *all* chunks */
130         if(valid_file == -1)
131             for(zckChunk *idx = zck->index.first; idx; idx = idx->next)
132                 idx->valid = -1;
133     }
134 
135     /* Go back to beginning of data section */
136     if(!seek_data(zck, zck->data_offset, SEEK_SET))
137         return 0;
138 
139     /* Reinitialize data checksum */
140     if(!hash_init(zck, &(zck->check_full_hash), &(zck->hash_type)))
141         return 0;
142 
143     return valid_file;
144 }
145 
get_digest_string(const char * digest,int size)146 char *get_digest_string(const char *digest, int size) {
147     char *str = zmalloc(size*2+1);
148 
149     for(int i=0; i<size; i++)
150         snprintf(str + i*2, 3, "%02x", (unsigned char)digest[i]);
151     return str;
152 }
153 
hash_setup(zckCtx * zck,zckHashType * ht,int h)154 bool hash_setup(zckCtx *zck, zckHashType *ht, int h) {
155     if(!ht) {
156         set_error(zck, "zckHashType is null");
157         return false;
158     }
159     if(h == ZCK_HASH_SHA1) {
160         memset(ht, 0, sizeof(zckHashType));
161         ht->type = ZCK_HASH_SHA1;
162         ht->digest_size = SHA1_DIGEST_LENGTH;
163         zck_log(ZCK_LOG_DEBUG, "Setting up hash type %s",
164                 zck_hash_name_from_type(ht->type));
165         return true;
166     } else if(h == ZCK_HASH_SHA256) {
167         memset(ht, 0, sizeof(zckHashType));
168         ht->type = ZCK_HASH_SHA256;
169         ht->digest_size = SHA256_DIGEST_SIZE;
170         zck_log(ZCK_LOG_DEBUG, "Setting up hash type %s",
171                 zck_hash_name_from_type(ht->type));
172         return true;
173     } else if(h >= ZCK_HASH_SHA512 &&
174               h <= ZCK_HASH_SHA512_128) {
175         memset(ht, 0, sizeof(zckHashType));
176         ht->type = h;
177         if(h == ZCK_HASH_SHA512)
178             ht->digest_size = SHA512_DIGEST_SIZE;
179         else if(h == ZCK_HASH_SHA512_128)
180             ht->digest_size = 16;
181         zck_log(ZCK_LOG_DEBUG, "Setting up hash type %s",
182                 zck_hash_name_from_type(ht->type));
183         return true;
184     }
185     set_error(zck, "Unsupported hash type: %s", zck_hash_name_from_type(h));
186     return false;
187 }
188 
hash_close(zckHash * hash)189 void hash_close(zckHash *hash) {
190     if(!hash)
191         return;
192 
193     if(hash->ctx) {
194         free(hash->ctx);
195         hash->ctx = NULL;
196     }
197     hash->type = NULL;
198     return;
199 }
200 
hash_reset(zckHashType * ht)201 void hash_reset(zckHashType *ht) {
202     memset(ht, 0, sizeof(zckHashType));
203     return;
204 }
205 
hash_init(zckCtx * zck,zckHash * hash,zckHashType * hash_type)206 bool hash_init(zckCtx *zck, zckHash *hash, zckHashType *hash_type) {
207     hash_close(hash);
208     if(hash == NULL || hash_type == NULL) {
209         set_error(zck, "Either zckHash or zckHashType struct is null");
210         return false;
211     }
212     if(hash_type->type == ZCK_HASH_SHA1) {
213         zck_log(ZCK_LOG_DDEBUG, "Initializing SHA-1 hash");
214         hash->ctx = zmalloc(sizeof(SHA_CTX));
215         hash->type = hash_type;
216         SHA1_Init((SHA_CTX *) hash->ctx);
217         return true;
218     } else if(hash_type->type == ZCK_HASH_SHA256) {
219         zck_log(ZCK_LOG_DDEBUG, "Initializing SHA-256 hash");
220         hash->ctx = zmalloc(sizeof(SHA256_CTX));
221         hash->type = hash_type;
222         SHA256_Init((SHA256_CTX *) hash->ctx);
223         return true;
224     } else if(hash_type->type >= ZCK_HASH_SHA512 &&
225               hash_type->type <= ZCK_HASH_SHA512_128) {
226         zck_log(ZCK_LOG_DDEBUG, "Initializing SHA-512 hash");
227         hash->ctx = zmalloc(sizeof(SHA512_CTX));
228         hash->type = hash_type;
229         SHA512_Init((SHA512_CTX *) hash->ctx);
230         return true;
231     }
232     set_error(zck, "Unsupported hash type: %s",
233               zck_hash_name_from_type(hash_type->type));
234     return false;
235 }
236 
hash_update(zckCtx * zck,zckHash * hash,const char * message,const size_t size)237 bool hash_update(zckCtx *zck, zckHash *hash, const char *message,
238                 const size_t size) {
239     if(message == NULL && size == 0)
240         return true;
241     if(message == NULL) {
242         set_error(zck,
243                   "Hash data is supposed to have %lu bytes, but is NULL", size);
244         return false;
245     }
246     if(size == 0) {
247         set_error(zck,
248                   "Hash data is supposed to be 0-length, but is not NULL");
249         return false;
250     }
251     if(hash && hash->ctx && hash->type) {
252         if(hash->type->type == ZCK_HASH_SHA1) {
253             SHA1_Update((SHA_CTX *)hash->ctx, (const sha1_byte *)message, size);
254             return true;
255         } else if(hash->type->type == ZCK_HASH_SHA256) {
256             SHA256_Update((SHA256_CTX *)hash->ctx,
257                           (const unsigned char *)message, size);
258             return true;
259         } else if(hash->type->type >= ZCK_HASH_SHA512 &&
260                   hash->type->type <= ZCK_HASH_SHA512_128) {
261             SHA512_Update((SHA512_CTX *)hash->ctx,
262                           (const unsigned char *)message, size);
263             return true;
264         }
265         set_error(zck, "Unsupported hash type: %s",
266                   zck_hash_name_from_type(hash->type->type));
267 
268         return false;
269     }
270     set_error(zck, "Hash hasn't been initialized");
271     return false;
272 }
273 
hash_finalize(zckCtx * zck,zckHash * hash)274 char *hash_finalize(zckCtx *zck, zckHash *hash) {
275     if(!hash || !hash->ctx || !hash->type) {
276         set_error(zck, "Hash hasn't been initialized");
277         hash_close(hash);
278         return NULL;
279     }
280     if(hash->type->type == ZCK_HASH_SHA1) {
281         unsigned char *digest = zmalloc(SHA1_DIGEST_LENGTH);
282         SHA1_Final((sha1_byte*)digest, (SHA_CTX *)hash->ctx);
283         hash_close(hash);
284         return (char *)digest;
285     } else if(hash->type->type == ZCK_HASH_SHA256) {
286         unsigned char *digest = zmalloc(SHA256_DIGEST_SIZE);
287         SHA256_Final(digest, (SHA256_CTX *)hash->ctx);
288         hash_close(hash);
289         return (char *)digest;
290     } else if(hash->type->type >= ZCK_HASH_SHA512 &&
291               hash->type->type <= ZCK_HASH_SHA512_128) {
292         unsigned char *digest = zmalloc(SHA512_DIGEST_SIZE);
293         SHA512_Final(digest, (SHA512_CTX *)hash->ctx);
294         hash_close(hash);
295         return (char *)digest;
296     }
297     set_error(zck, "Unsupported hash type: %s",
298               zck_hash_name_from_type(hash->type->type));
299     hash_close(hash);
300     return NULL;
301 }
302 
set_full_hash_type(zckCtx * zck,int hash_type)303 bool set_full_hash_type(zckCtx *zck, int hash_type) {
304     VALIDATE_BOOL(zck);
305 
306     zck_log(ZCK_LOG_INFO, "Setting full hash to %s",
307             zck_hash_name_from_type(hash_type));
308     if(!hash_setup(zck, &(zck->hash_type), hash_type)) {
309         set_error(zck, "Unable to set full hash");
310         return false;
311     }
312     if(!hash_init(zck, &(zck->full_hash), &(zck->hash_type))) {
313         set_error(zck, "Unable initialize full hash");
314         return false;
315     }
316     return true;
317 }
318 
set_chunk_hash_type(zckCtx * zck,int hash_type)319 bool set_chunk_hash_type(zckCtx *zck, int hash_type) {
320     VALIDATE_BOOL(zck);
321 
322     memset(&(zck->chunk_hash_type), 0, sizeof(zckHashType));
323     zck_log(ZCK_LOG_DEBUG, "Setting chunk hash to %s",
324             zck_hash_name_from_type(hash_type));
325     if(!hash_setup(zck, &(zck->chunk_hash_type), hash_type)) {
326         set_error(zck, "Unable to set chunk hash");
327         return false;
328     }
329     zck->index.hash_type = zck->chunk_hash_type.type;
330     zck->index.digest_size = zck->chunk_hash_type.digest_size;
331     return true;
332 }
333 
334 /* Validate chunk, returning -1 if checksum fails, 1 if good, 0 if error */
validate_chunk(zckChunk * idx,zck_log_type bad_checksum)335 int validate_chunk(zckChunk *idx, zck_log_type bad_checksum) {
336     zckCtx *zck = NULL;
337     if(idx && idx->zck) {
338         VALIDATE_INT(idx->zck);
339         zck = idx->zck;
340     }
341     ALLOCD_INT(zck, idx);
342 
343     char *digest = hash_finalize(zck, &(zck->check_chunk_hash));
344     if(digest == NULL) {
345         set_error(zck, "Unable to calculate chunk checksum");
346         idx->valid = 0;
347         return 0;
348     }
349     if(idx->comp_length == 0)
350         memset(digest, 0, idx->digest_size);
351     char *pdigest = zck_get_chunk_digest(idx);
352     zck_log(ZCK_LOG_DDEBUG, "Expected chunk checksum:   %s", pdigest);
353     free(pdigest);
354     pdigest = get_digest_string(digest, idx->digest_size);
355     zck_log(ZCK_LOG_DDEBUG, "Calculated chunk checksum: %s", pdigest);
356     free(pdigest);
357     if(memcmp(digest, idx->digest, idx->digest_size) != 0) {
358         free(digest);
359         if(idx->number == -1)
360             zck_log(bad_checksum, "Chunk checksum: FAILED!");
361         else
362             zck_log(bad_checksum, "Chunk %i's checksum: FAILED",
363                     idx->number);
364         idx->valid = -1;
365         return -1;
366     }
367     if(idx->number == -1)
368         zck_log(ZCK_LOG_DEBUG, "Chunk checksum: valid");
369     else
370         zck_log(ZCK_LOG_DEBUG, "Chunk %i's checksum: valid", idx->number);
371     free(digest);
372     idx->valid = 1;
373     return 1;
374 }
375 
validate_current_chunk(zckCtx * zck)376 int validate_current_chunk(zckCtx *zck) {
377     VALIDATE_BOOL(zck);
378 
379     return validate_chunk(zck->comp.data_idx, ZCK_LOG_ERROR);
380 }
381 
validate_file(zckCtx * zck,zck_log_type bad_checksums)382 int validate_file(zckCtx *zck, zck_log_type bad_checksums) {
383     VALIDATE_BOOL(zck);
384     char *digest = hash_finalize(zck, &(zck->check_full_hash));
385     if(digest == NULL) {
386         set_error(zck, "Unable to calculate full file checksum");
387         return 0;
388     }
389     zck_log(ZCK_LOG_DEBUG, "Checking data checksum");
390     char *cks = get_digest_string(zck->full_hash_digest,
391                                   zck->hash_type.digest_size);
392     zck_log(ZCK_LOG_DEBUG, "Expected data checksum:   %s", cks);
393     free(cks);
394     cks = get_digest_string(digest, zck->hash_type.digest_size);
395     zck_log(ZCK_LOG_DEBUG, "Calculated data checksum: %s", cks);
396     free(cks);
397     if(memcmp(digest, zck->full_hash_digest, zck->hash_type.digest_size) != 0) {
398         free(digest);
399         zck_log(bad_checksums, "Data checksum failed!");
400         return -1;
401     }
402     zck_log(ZCK_LOG_DEBUG, "Data checksum valid");
403     free(digest);
404     return 1;
405 }
406 
validate_header(zckCtx * zck)407 int validate_header(zckCtx *zck) {
408     VALIDATE_BOOL(zck);
409 
410     char *digest = hash_finalize(zck, &(zck->check_full_hash));
411     if(digest == NULL) {
412         set_error(zck, "Unable to calculate header checksum");
413         return 0;
414     }
415     zck_log(ZCK_LOG_DEBUG, "Checking header checksum");
416     char *cks = get_digest_string(zck->header_digest,
417                                   zck->hash_type.digest_size);
418     zck_log(ZCK_LOG_DEBUG, "Expected header checksum:   %s", cks);
419     free(cks);
420     cks = get_digest_string(digest, zck->hash_type.digest_size);
421     zck_log(ZCK_LOG_DEBUG, "Calculated header checksum: %s", cks);
422     free(cks);
423     if(memcmp(digest, zck->header_digest, zck->hash_type.digest_size) != 0) {
424         free(digest);
425         zck_log(ZCK_LOG_INFO, "Header checksum failed!");
426         return -1;
427     }
428     zck_log(ZCK_LOG_DEBUG, "Header checksum valid");
429     free(digest);
430 
431     if(!hash_init(zck, &(zck->check_full_hash), &(zck->hash_type)))
432         return 0;
433 
434     return 1;
435 }
436 
437 /* Returns 1 if data hash matches, -1 if it doesn't and 0 if error */
zck_validate_data_checksum(zckCtx * zck)438 int PUBLIC zck_validate_data_checksum(zckCtx *zck) {
439     VALIDATE_READ_BOOL(zck);
440 
441     if(!seek_data(zck, zck->data_offset, SEEK_SET))
442         return 0;
443     if(!hash_init(zck, &(zck->check_full_hash), &(zck->hash_type)))
444         return 0;
445     char buf[BUF_SIZE] = {0};
446     zckChunk *idx = zck->index.first;
447     zck_log(ZCK_LOG_DEBUG, "Checking full hash");
448     while(idx) {
449         size_t to_read = idx->comp_length;
450         while(to_read > 0) {
451             size_t rb = BUF_SIZE;
452             if(rb > to_read)
453                 rb = to_read;
454             if(!read_data(zck, buf, rb))
455                 return 0;
456             if(!hash_update(zck, &(zck->check_full_hash), buf, rb))
457                 return 0;
458             to_read -= rb;
459         }
460         idx = idx->next;
461     }
462     int ret = validate_file(zck, ZCK_LOG_WARNING);
463     if(!seek_data(zck, zck->data_offset, SEEK_SET))
464         return 0;
465     if(!hash_init(zck, &(zck->check_full_hash), &(zck->hash_type)))
466         return 0;
467     return ret;
468 }
469 
zck_hash_name_from_type(int hash_type)470 const char PUBLIC *zck_hash_name_from_type(int hash_type) {
471     if(hash_type >= ZCK_HASH_UNKNOWN || hash_type < 0) {
472         snprintf(unknown+8, 21, "%i)", hash_type);
473         return unknown;
474     }
475     return HASH_NAME[hash_type];
476 }
477 
zck_get_full_hash_type(zckCtx * zck)478 int PUBLIC zck_get_full_hash_type(zckCtx *zck) {
479     VALIDATE_INT(zck);
480 
481     return zck->hash_type.type;
482 }
483 
zck_get_full_digest_size(zckCtx * zck)484 ssize_t PUBLIC zck_get_full_digest_size(zckCtx *zck) {
485     VALIDATE_INT(zck);
486 
487     return zck->hash_type.digest_size;
488 }
489 
zck_get_chunk_hash_type(zckCtx * zck)490 int PUBLIC zck_get_chunk_hash_type(zckCtx *zck) {
491     VALIDATE_INT(zck);
492 
493     return zck->index.hash_type;
494 }
495 
zck_get_chunk_digest_size(zckCtx * zck)496 ssize_t PUBLIC zck_get_chunk_digest_size(zckCtx *zck) {
497     VALIDATE_INT(zck);
498 
499     return zck->index.digest_size;
500 }
501 
zck_get_header_digest(zckCtx * zck)502 char PUBLIC *zck_get_header_digest(zckCtx *zck) {
503     VALIDATE_PTR(zck);
504 
505     return get_digest_string(zck->header_digest, zck->hash_type.digest_size);
506 }
507 
zck_get_data_digest(zckCtx * zck)508 char PUBLIC *zck_get_data_digest(zckCtx *zck) {
509     VALIDATE_PTR(zck);
510 
511     return get_digest_string(zck->full_hash_digest, zck->hash_type.digest_size);
512 }
513 
zck_get_chunk_digest(zckChunk * item)514 char PUBLIC *zck_get_chunk_digest(zckChunk *item) {
515     if(item == NULL)
516         return NULL;
517     return get_digest_string(item->digest, item->digest_size);
518 }
519 
520 /* Returns 1 if all chunks are valid, -1 if even one isn't and 0 if error */
zck_find_valid_chunks(zckCtx * zck)521 int PUBLIC zck_find_valid_chunks(zckCtx *zck) {
522     VALIDATE_READ_BOOL(zck);
523 
524     return validate_checksums(zck, ZCK_LOG_DEBUG);
525 }
526 
527 /* Returns 1 if all checksums matched, -1 if even one doesn't and 0 if error */
zck_validate_checksums(zckCtx * zck)528 int PUBLIC zck_validate_checksums(zckCtx *zck) {
529     VALIDATE_READ_BOOL(zck);
530 
531     return validate_checksums(zck, ZCK_LOG_WARNING);
532 }
533