Verifying checksum tags of superblock and tree if available and enabled.
New API call iso_md5_match().
This commit is contained in:
parent
868005ed0e
commit
8b800094af
@ -2278,15 +2278,83 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block)
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@return 1= ok, checked, go on with loading
|
||||
2= no checksum tags found, go on with loading
|
||||
<0= libisofs error
|
||||
especially ISO_SB_TREE_CORRUPTED
|
||||
*/
|
||||
static
|
||||
int iso_src_check_sb_tree(IsoDataSource *src, uint32_t start_lba, int flag)
|
||||
{
|
||||
int tag_type, ret;
|
||||
char block[2048], md5[16];
|
||||
int desired = (1 << 2);
|
||||
void *ctx = NULL;
|
||||
uint32_t next_tag = 0, i;
|
||||
|
||||
ret = iso_md5_start(&ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (start_lba == 0)
|
||||
desired |= (1 << 4);
|
||||
for (i = 0; i < 32; i++) {
|
||||
ret = src->read_block(src, start_lba + i, (uint8_t *) block);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
ret = 0;
|
||||
if (i >= 16)
|
||||
ret = iso_util_eval_md5_tag(block, desired, start_lba + i,
|
||||
ctx, start_lba, &tag_type, &next_tag, 0);
|
||||
iso_md5_compute(ctx, block, 2048);
|
||||
if (ret == ISO_MD5_AREA_CORRUPTED || ret == ISO_MD5_TAG_MISMATCH)
|
||||
ret = ISO_SB_TREE_CORRUPTED;
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (ret == 1)
|
||||
break;
|
||||
}
|
||||
if (i >= 32) {
|
||||
ret = 2;
|
||||
goto ex;
|
||||
}
|
||||
if (tag_type == 4) {
|
||||
/* Relocated Superblock: restart checking at real session start */
|
||||
if (next_tag < 32) {
|
||||
/* Non plausible session_start address */
|
||||
iso_msg_submit(-1, ret, 0, NULL);
|
||||
ret = ISO_SB_TREE_CORRUPTED;
|
||||
goto ex;
|
||||
}
|
||||
/* Check real session */
|
||||
ret = iso_src_check_sb_tree(src, next_tag, 0);
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* >>>> */;
|
||||
/* Go on with tree */
|
||||
for (i++; start_lba + i <= next_tag; i++) {
|
||||
ret = src->read_block(src, start_lba + i, (uint8_t *) block);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
if (start_lba + i < next_tag)
|
||||
iso_md5_compute(ctx, block, 2048);
|
||||
}
|
||||
ret = iso_util_eval_md5_tag(block, (1 << 3), start_lba + i - 1,
|
||||
ctx, start_lba, &tag_type, &next_tag, 0);
|
||||
if (ret == ISO_MD5_AREA_CORRUPTED || ret == ISO_MD5_TAG_MISMATCH)
|
||||
ret = ISO_SB_TREE_CORRUPTED;
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
|
||||
return 2;
|
||||
ret = 1;
|
||||
ex:
|
||||
if (ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
||||
int msgid, IsoImageFilesystem **fs)
|
||||
{
|
||||
@ -2355,12 +2423,13 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
||||
|
||||
if (data->md5_load) {
|
||||
|
||||
/* >>> From opts->block on : check for superblock and tree tags */;
|
||||
/* From opts->block on : check for superblock and tree tags */;
|
||||
ret = iso_src_check_sb_tree(src, opts->block, 0);
|
||||
if (ret <= 0) {
|
||||
|
||||
/* >>> refuse to load, hint towards loading without MD5 check */;
|
||||
|
||||
goto fs_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5169,6 +5169,20 @@ int iso_md5_clone(void *old_md5_context, void **new_md5_context);
|
||||
*/
|
||||
int iso_md5_end(void **md5_context, char result[16]);
|
||||
|
||||
/**
|
||||
* Inquire whether two MD5 checksums match. (This is trivial but such a call
|
||||
* is convenient and completes the interface.)
|
||||
* @param first_md5
|
||||
* A MD5 byte string as returned by iso_md5_end()
|
||||
* @param second_md5
|
||||
* A MD5 byte string as returned by iso_md5_end()
|
||||
* @return
|
||||
* 1= match , 0= mismatch
|
||||
*
|
||||
* @since 0.6.22
|
||||
*/
|
||||
int iso_md5_match(char first_md5[16], char second_md5[16]);
|
||||
|
||||
|
||||
/************ Error codes and return values for libisofs ********************/
|
||||
|
||||
@ -5426,11 +5440,43 @@ int iso_md5_end(void **md5_context, char result[16]);
|
||||
#define ISO_ZLIB_EARLY_EOF 0xE830FEA1
|
||||
|
||||
/**
|
||||
* Checksum area appears damaged and not trustworthy for verifications.
|
||||
* (WARNING,HIGH, -352)
|
||||
* Checksum area or checksum tag appear corrupted (WARNING,HIGH, -352)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_AREA_CORRUPTED 0xD030FEA0
|
||||
#define ISO_MD5_AREA_CORRUPTED 0xD030FEA0
|
||||
|
||||
/**
|
||||
* Checksum mismatch between checksum tag and data blocks
|
||||
* (FAILURE, HIGH, -353)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_TAG_MISMATCH 0xE830FE9F
|
||||
|
||||
/**
|
||||
* Checksum mismatch in System Area, Volume Descriptors, or directory tree.
|
||||
* (FAILURE, HIGH, -354)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_SB_TREE_CORRUPTED 0xE830FE9E
|
||||
|
||||
/**
|
||||
* Unexpected checksum tag type encountered. (WARNING, HIGH, -355)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_TAG_UNEXPECTED 0xD030FE9D
|
||||
|
||||
/**
|
||||
* Misplaced checksum tag encountered. (WARNING, HIGH, -356)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_TAG_MISPLACED 0xD030FE9C
|
||||
|
||||
/**
|
||||
* Checksum tag with unexpected address range encountered.
|
||||
* (WARNING, HIGH, -357)
|
||||
* @since 0.6.22
|
||||
*/
|
||||
#define ISO_MD5_TAG_OTHER_RANGE 0xD030FE9B
|
||||
|
||||
|
||||
/* ! PLACE NEW ERROR CODES HERE ! */
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "messages.h"
|
||||
#include "ecma119.h"
|
||||
#include "image.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
@ -386,6 +387,18 @@ int iso_md5_end(void **md5_context, char result[16])
|
||||
}
|
||||
|
||||
|
||||
/* API */
|
||||
int iso_md5_match(char first_md5[16], char second_md5[16])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i= 0; i < 16; i++)
|
||||
if (first_md5[i] != second_md5[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
@ -667,15 +680,10 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
||||
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
int res, mode, l, i, wres;
|
||||
int res, mode, l, i, wres, tag_id_len;
|
||||
void *ctx = NULL;
|
||||
char md5[16], tag_block[2048];
|
||||
char md5[16], tag_block[2048], *tag_id;
|
||||
uint32_t size = 0, pos = 0, start;
|
||||
static char *tag_ids[] = {"",
|
||||
"libisofs_checksum_tag_v1",
|
||||
"libisofs_sb_checksum_tag_v1",
|
||||
"libisofs_tree_checksum_tag_v1",
|
||||
"libisofs_rlsb32_checksum_tag_v1"};
|
||||
|
||||
start = t->checksum_range_start;
|
||||
memset(tag_block, 0, 2048);
|
||||
@ -702,9 +710,10 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
}
|
||||
if (res > 0) {
|
||||
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
|
||||
sprintf(tag_block,
|
||||
"%s pos=%u range_start=%u range_size=%u",
|
||||
tag_ids[mode], pos, start, size);
|
||||
tag_id, pos, start, size);
|
||||
|
||||
l = strlen(tag_block);
|
||||
if (mode == 2) {
|
||||
|
@ -261,7 +261,17 @@ const char *iso_error_to_msg(int errcode)
|
||||
case ISO_ZLIB_EARLY_EOF:
|
||||
return "Premature EOF of zlib input stream";
|
||||
case ISO_MD5_AREA_CORRUPTED:
|
||||
return "Checksum area appears damaged and not trustworthy for verifications";
|
||||
return "Checksum area or checksum tag appear corrupted";
|
||||
case ISO_MD5_TAG_MISMATCH:
|
||||
return "Checksum mismatch between checksum tag and data blocks";
|
||||
case ISO_SB_TREE_CORRUPTED:
|
||||
return "Checksum mismatch in System Area, Volume Descriptors, or directory tree";
|
||||
case ISO_MD5_TAG_UNEXPECTED:
|
||||
return "Unexpected checksum tag type encountered";
|
||||
case ISO_MD5_TAG_MISPLACED:
|
||||
return "Misplaced checksum tag type encountered";
|
||||
case ISO_MD5_TAG_OTHER_RANGE:
|
||||
return "Checksum tag with unexpected address range encountered";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "util.h"
|
||||
#include "libisofs.h"
|
||||
#include "messages.h"
|
||||
#include "../version.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -1563,18 +1564,33 @@ int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count,
|
||||
}
|
||||
|
||||
|
||||
int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag)
|
||||
{
|
||||
static char *magic[] = {"",
|
||||
"libisofs_checksum_tag_v1",
|
||||
"libisofs_sb_checksum_tag_v1",
|
||||
"libisofs_tree_checksum_tag_v1",
|
||||
"libisofs_rlsb32_checksum_tag_v1"};
|
||||
static int magic_len[]= {0, 24, 27, 29, 31};
|
||||
static int magic_max = 4;
|
||||
|
||||
*tag_magic = NULL;
|
||||
*len = 0;
|
||||
if (tag_type < 0 || tag_type > magic_max)
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
*tag_magic = magic[tag_type];
|
||||
*len = magic_len[tag_type];
|
||||
return magic_max;
|
||||
}
|
||||
|
||||
|
||||
int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos,
|
||||
uint32_t *range_start, uint32_t *range_size,
|
||||
uint32_t *next_tag, char md5[16], int flag)
|
||||
{
|
||||
static char *tag_magic[] = {"",
|
||||
"libisofs_checksum_tag_v1",
|
||||
"libisofs_sb_checksum_tag_v1",
|
||||
"libisofs_tree_checksum_tag_v1",
|
||||
"libisofs_rlsb32_checksum_tag_v1"};
|
||||
static int magic_len[]= {0, 24, 27, 29, 31};
|
||||
int ret, bin_count, i, mode, magic_first = 1, magic_last = 4;
|
||||
char *cpt, self_md5[16], tag_md5[16];
|
||||
int magic_len = 0;
|
||||
char *cpt, self_md5[16], tag_md5[16], *tag_magic;
|
||||
void *ctx = NULL;
|
||||
|
||||
*next_tag = 0;
|
||||
@ -1583,13 +1599,15 @@ int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos,
|
||||
return ISO_WRONG_ARG_VALUE;
|
||||
if (mode > 0)
|
||||
magic_first = magic_last = mode;
|
||||
for (i = magic_first; i <= magic_last; i++)
|
||||
if (strncmp(data, tag_magic[i], magic_len[i]) == 0)
|
||||
for (i = magic_first; i <= magic_last; i++) {
|
||||
iso_util_tag_magic(i, &tag_magic, &magic_len, 0);
|
||||
if (strncmp(data, tag_magic, magic_len) == 0)
|
||||
break;
|
||||
}
|
||||
if (i > magic_last )
|
||||
return 0;
|
||||
*tag_type = i;
|
||||
cpt = data + magic_len[*tag_type] + 1;
|
||||
cpt = data + magic_len + 1;
|
||||
if (strncmp(cpt, "pos=", 4) != 0)
|
||||
return 0;
|
||||
cpt+= 4;
|
||||
@ -1650,3 +1668,51 @@ int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos,
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
|
||||
void *ctx, uint32_t ctx_start_lba,
|
||||
int *tag_type, uint32_t *next_tag, int flag)
|
||||
{
|
||||
int decode_ret, ret;
|
||||
char md5[16], cloned_md5[16];
|
||||
uint32_t pos, range_start, range_size;
|
||||
void *cloned_ctx = NULL;
|
||||
|
||||
*tag_type = 0;
|
||||
decode_ret = iso_util_decode_md5_tag(block, tag_type, &pos,
|
||||
&range_start, &range_size, next_tag, md5, 0);
|
||||
if (decode_ret != 1 && decode_ret != ISO_MD5_AREA_CORRUPTED)
|
||||
return 0;
|
||||
if (*tag_type > 30)
|
||||
goto unexpected_type;
|
||||
|
||||
if (decode_ret == ISO_MD5_AREA_CORRUPTED) {
|
||||
ret = decode_ret;
|
||||
goto ex;
|
||||
} else if (!((1 << *tag_type) & desired)) {
|
||||
unexpected_type:;
|
||||
iso_msg_submit(-1, ISO_MD5_TAG_UNEXPECTED, 0, NULL);
|
||||
ret = 0;
|
||||
goto ex;
|
||||
} else if(pos != lba) {
|
||||
ret = ISO_MD5_TAG_MISPLACED;
|
||||
goto ex;
|
||||
} else if(range_start != ctx_start_lba) {
|
||||
ret = ISO_MD5_TAG_MISPLACED;
|
||||
}
|
||||
ret = iso_md5_clone(ctx, &cloned_ctx);
|
||||
if (ret < 0)
|
||||
goto ex;
|
||||
iso_md5_end(&cloned_ctx, cloned_md5);
|
||||
if (! iso_md5_match(cloned_md5, md5)) {
|
||||
ret = ISO_MD5_TAG_MISMATCH;
|
||||
goto ex;
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (ret < 0)
|
||||
iso_msg_submit(-1, ret, 0, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -458,4 +458,28 @@ int iso_util_encode_len_bytes(uint32_t data, char *buffer, int data_len,
|
||||
int iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len,
|
||||
int buffer_len, int flag);
|
||||
|
||||
|
||||
/* Evaluate a data block whether it is a libisofs session checksum tag of
|
||||
desired type and eventually use it to verify the MD5 checksum computed
|
||||
so far.
|
||||
@param block The data block to be evaluated
|
||||
@param desired Bit map which tells what tag types are expected
|
||||
(0 to 30)
|
||||
@param lba The address from where block was read
|
||||
@param ctx The checksum context computed so far
|
||||
@param ctx_start_lba The block address where checksum computing started
|
||||
@param tag_type Returns the tag type (0 means invalid tag type)
|
||||
@param flag Bitfield for control purposes, unused yet, submit 0
|
||||
@return 1= tag is desired and matches
|
||||
0= not a recognizable tag or a undesired tag
|
||||
<0 is error or mismatch
|
||||
*/
|
||||
int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
|
||||
void *ctx, uint32_t ctx_start_lba,
|
||||
int *tag_type, uint32_t *next_tag, int flag);
|
||||
|
||||
|
||||
int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag);
|
||||
|
||||
|
||||
#endif /*LIBISO_UTIL_H_*/
|
||||
|
Loading…
Reference in New Issue
Block a user