Verifying checksum tags of superblock and tree if available and enabled.

New API call iso_md5_match().
This commit is contained in:
Thomas Schmitt 2009-08-18 17:03:33 +02:00
parent 868005ed0e
commit 8b800094af
6 changed files with 249 additions and 25 deletions

View File

@ -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;
} }
} }

View File

@ -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 ! */

View File

@ -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) {

View File

@ -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";
} }

View File

@ -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;
}

View File

@ -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_*/