summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2021-05-02 14:24:51 +0200
committerPali Rohár <pali.rohar@gmail.com>2021-05-02 14:24:51 +0200
commit4f45b045c305efdb216a24912aedceba0cd23670 (patch)
tree1dc2978c61cc2d49f3821e495955a107763b53d3
parent3c4943340b72ab468070105d10064391ca636271 (diff)
download0xFFFF-4f45b045c305efdb216a24912aedceba0cd23670.tar.bz2
fiasco: Implement subsection checksum verification during parsing fiasco image
When checksum is set to 0x00 then skip verification due to backward compatibility with 0xFFFF version 0.9 and earlier.
-rw-r--r--src/fiasco.c38
1 files changed, 23 insertions, 15 deletions
diff --git a/src/fiasco.c b/src/fiasco.c
index 881d172..890e1c0 100644
--- a/src/fiasco.c
+++ b/src/fiasco.c
@@ -38,7 +38,7 @@
#define FIASCO_READ_ERROR(fiasco, ...) do { ERROR_INFO(__VA_ARGS__); fiasco_free(fiasco); return NULL; } while (0)
#define FIASCO_WRITE_ERROR(file, fd, ...) do { ERROR_INFO_STR(file, __VA_ARGS__); if ( fd >= 0 ) close(fd); return -1; } while (0)
#define READ_OR_FAIL(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) { FIASCO_READ_ERROR(fiasco, "Cannot read %d bytes", size); } } while (0)
-#define READ_OR_RETURN(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; } while (0)
+#define READ_OR_RETURN(fiasco, checksum, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; CHECKSUM(checksum, buf, size); } while (0)
#define WRITE_OR_FAIL_FREE(file, fd, buf, size, var) do { if ( ! simulate ) { if ( write(fd, buf, size) != (ssize_t)size ) { free(var); FIASCO_WRITE_ERROR(file, fd, "Cannot write %d bytes", size); } } } while (0)
#define WRITE_OR_FAIL(file, fd, buf, size) WRITE_OR_FAIL_FREE(file, fd, buf, size, NULL)
@@ -69,6 +69,7 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
uint8_t asicidx;
uint8_t devicetype;
uint8_t deviceidx;
+ uint8_t checksum;
uint32_t address;
uint16_t hash;
off_t offset;
@@ -125,7 +126,7 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
while ( 1 ) {
/* If end of file, return fiasco image */
- READ_OR_RETURN(fiasco, buf, 1);
+ READ_OR_RETURN(fiasco, checksum, buf, 1);
/* Header of next image (0x54) */
if ( buf[0] != 0x54 ) {
@@ -133,14 +134,16 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
return fiasco;
}
- READ_OR_RETURN(fiasco, &count8, 1);
+ checksum = 0x00;
+
+ READ_OR_RETURN(fiasco, checksum, &count8, 1);
if ( count8 == 0 ) {
ERROR("No section in image header");
return fiasco;
}
- READ_OR_RETURN(fiasco, buf, 2);
+ READ_OR_RETURN(fiasco, checksum, buf, 2);
/* File data section (0x2E) with length of 25 bytes */
if ( buf[0] != 0x2E || buf[1] != 25 ) {
@@ -148,15 +151,15 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
return fiasco;
}
- READ_OR_RETURN(fiasco, &asicidx, 1);
- READ_OR_RETURN(fiasco, &devicetype, 1);
- READ_OR_RETURN(fiasco, &deviceidx, 1);
+ READ_OR_RETURN(fiasco, checksum, &asicidx, 1);
+ READ_OR_RETURN(fiasco, checksum, &devicetype, 1);
+ READ_OR_RETURN(fiasco, checksum, &deviceidx, 1);
- READ_OR_RETURN(fiasco, &hash, 2);
+ READ_OR_RETURN(fiasco, checksum, &hash, 2);
hash = ntohs(hash);
memset(type, 0, sizeof(type));
- READ_OR_RETURN(fiasco, type, 12);
+ READ_OR_RETURN(fiasco, checksum, type, 12);
byte = type[0];
if ( byte == 0xFF )
@@ -164,11 +167,11 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
VERBOSE(" %s\n", type);
- READ_OR_RETURN(fiasco, &length, 4);
+ READ_OR_RETURN(fiasco, checksum, &length, 4);
length = ntohl(length);
/* load address (unused) */
- READ_OR_RETURN(fiasco, &address, 4);
+ READ_OR_RETURN(fiasco, checksum, &address, 4);
/* end of file data section */
--count8;
@@ -188,9 +191,9 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
while ( count8 > 0 ) {
- READ_OR_RETURN(fiasco, &byte, 1);
- READ_OR_RETURN(fiasco, &length8, 1);
- READ_OR_RETURN(fiasco, buf, length8);
+ READ_OR_RETURN(fiasco, checksum, &byte, 1);
+ READ_OR_RETURN(fiasco, checksum, &length8, 1);
+ READ_OR_RETURN(fiasco, checksum, buf, length8);
VERBOSE(" subinfo\n");
VERBOSE(" length: %d\n", length8);
@@ -242,9 +245,14 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
}
/* checksum */
- READ_OR_RETURN(fiasco, buf, 1);
+ READ_OR_RETURN(fiasco, checksum, buf, 1);
VERBOSE(" subinfo checksum: 0x%02x\n", buf[0]);
+ if ( ! noverify && buf[0] != 0x00 && checksum != 0xFF ) {
+ ERROR("Image header subinfo checksum mishmash (counted 0x%02x, got 0x%02x)", (0xFF - checksum + buf[0]) & 0xFF, buf[0]);
+ return fiasco;
+ }
+
offset = lseek(fiasco->fd, 0, SEEK_CUR);
if ( offset == (off_t)-1 )
FIASCO_READ_ERROR(fiasco, "Cannot get offset of file");