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 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
|
static
|
||||||
int iso_src_check_sb_tree(IsoDataSource *src, uint32_t start_lba, int flag)
|
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 iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
||||||
int msgid, IsoImageFilesystem **fs)
|
int msgid, IsoImageFilesystem **fs)
|
||||||
{
|
{
|
||||||
@ -2355,12 +2423,13 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
|
|||||||
|
|
||||||
if (data->md5_load) {
|
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);
|
ret = iso_src_check_sb_tree(src, opts->block, 0);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
|
|
||||||
/* >>> refuse to load, hint towards loading without MD5 check */;
|
/* >>> 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]);
|
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 ********************/
|
/************ 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
|
#define ISO_ZLIB_EARLY_EOF 0xE830FEA1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checksum area appears damaged and not trustworthy for verifications.
|
* Checksum area or checksum tag appear corrupted (WARNING,HIGH, -352)
|
||||||
* (WARNING,HIGH, -352)
|
|
||||||
* @since 0.6.22
|
* @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 ! */
|
/* ! PLACE NEW ERROR CODES HERE ! */
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "ecma119.h"
|
#include "ecma119.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include "md5.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
|
#ifdef Libisofs_with_checksumS
|
||||||
|
|
||||||
int res, mode, l, i, wres;
|
int res, mode, l, i, wres, tag_id_len;
|
||||||
void *ctx = NULL;
|
void *ctx = NULL;
|
||||||
char md5[16], tag_block[2048];
|
char md5[16], tag_block[2048], *tag_id;
|
||||||
uint32_t size = 0, pos = 0, start;
|
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;
|
start = t->checksum_range_start;
|
||||||
memset(tag_block, 0, 2048);
|
memset(tag_block, 0, 2048);
|
||||||
@ -702,9 +710,10 @@ int iso_md5_write_tag(Ecma119Image *t, int flag)
|
|||||||
return ISO_WRONG_ARG_VALUE;
|
return ISO_WRONG_ARG_VALUE;
|
||||||
}
|
}
|
||||||
if (res > 0) {
|
if (res > 0) {
|
||||||
|
iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
|
||||||
sprintf(tag_block,
|
sprintf(tag_block,
|
||||||
"%s pos=%u range_start=%u range_size=%u",
|
"%s pos=%u range_start=%u range_size=%u",
|
||||||
tag_ids[mode], pos, start, size);
|
tag_id, pos, start, size);
|
||||||
|
|
||||||
l = strlen(tag_block);
|
l = strlen(tag_block);
|
||||||
if (mode == 2) {
|
if (mode == 2) {
|
||||||
|
@ -261,7 +261,17 @@ const char *iso_error_to_msg(int errcode)
|
|||||||
case ISO_ZLIB_EARLY_EOF:
|
case ISO_ZLIB_EARLY_EOF:
|
||||||
return "Premature EOF of zlib input stream";
|
return "Premature EOF of zlib input stream";
|
||||||
case ISO_MD5_AREA_CORRUPTED:
|
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:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "libisofs.h"
|
#include "libisofs.h"
|
||||||
|
#include "messages.h"
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
|
||||||
#include <stdlib.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,
|
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 *range_start, uint32_t *range_size,
|
||||||
uint32_t *next_tag, char md5[16], int flag)
|
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;
|
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;
|
void *ctx = NULL;
|
||||||
|
|
||||||
*next_tag = 0;
|
*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;
|
return ISO_WRONG_ARG_VALUE;
|
||||||
if (mode > 0)
|
if (mode > 0)
|
||||||
magic_first = magic_last = mode;
|
magic_first = magic_last = mode;
|
||||||
for (i = magic_first; i <= magic_last; i++)
|
for (i = magic_first; i <= magic_last; i++) {
|
||||||
if (strncmp(data, tag_magic[i], magic_len[i]) == 0)
|
iso_util_tag_magic(i, &tag_magic, &magic_len, 0);
|
||||||
|
if (strncmp(data, tag_magic, magic_len) == 0)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if (i > magic_last )
|
if (i > magic_last )
|
||||||
return 0;
|
return 0;
|
||||||
*tag_type = i;
|
*tag_type = i;
|
||||||
cpt = data + magic_len[*tag_type] + 1;
|
cpt = data + magic_len + 1;
|
||||||
if (strncmp(cpt, "pos=", 4) != 0)
|
if (strncmp(cpt, "pos=", 4) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
cpt+= 4;
|
cpt+= 4;
|
||||||
@ -1650,3 +1668,51 @@ int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos,
|
|||||||
return(1);
|
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 iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len,
|
||||||
int buffer_len, int flag);
|
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_*/
|
#endif /*LIBISO_UTIL_H_*/
|
||||||
|
Loading…
Reference in New Issue
Block a user