Augmented checksum tags for superblock and tree by parameter next=

for unambigous linking.
This commit is contained in:
Thomas Schmitt 2009-08-16 16:58:41 +02:00
parent b4e2a60cd9
commit 955471a064
8 changed files with 90 additions and 59 deletions

View File

@ -69,7 +69,7 @@ array. (Then follows eventual padding.)
The tags are a single lines of printable text, padded by 0 bytes. They have The tags are a single lines of printable text, padded by 0 bytes. They have
the following format: the following format:
Tag_id pos=# range_start=# range_size=# md5=# self=#\n Tag_id pos=# range_start=# range_size=# [next=#] md5=# self=#\n
Tag_id distinguishes the three tag types Tag_id distinguishes the three tag types
"libisofs_sb_checksum_tag_v1" Superblock tag "libisofs_sb_checksum_tag_v1" Superblock tag
@ -109,6 +109,14 @@ are strings of 32 hex digits:
The number of blocks beginning at range_start which are covered by the The number of blocks beginning at range_start which are covered by the
checksum of the tag. checksum of the tag.
Only with superblock tag and tree tag:
next=
The block address where the next tag is supposed to be found. This is
to avoid the small possibility that a checksum tag with matching position
is part of a directory entry or data file. The superblock tag is quite
uniquely placed directly after the ECMA-119 Volume Descriptor Set Terminator
where no such cleartext is supposed to reside by accident.
md5= md5=
The checksum payload of the tag as lower case hex digits. The checksum payload of the tag as lower case hex digits.
@ -139,8 +147,9 @@ read before the tag block.
Checking before Image Tree Loading Checking before Image Tree Loading
In order to check for a trustworthy loadable image tree, read the first In order to check for a trustworthy loadable image tree, read the first 32
32 blocks of the session and look for the superblock checksum tag by blocks to the session start and look in block 16 to 32 for the superblock
checksum tag by
iso_util_decode_md5_tag(block, &pos, &range_start, &range_size, md5, 2); iso_util_decode_md5_tag(block, &pos, &range_start, &range_size, md5, 2);
If one appears and has plausible parameters, then check whether its MD5 matches If one appears and has plausible parameters, then check whether its MD5 matches
the MD5 of the data blocks read before. the MD5 of the data blocks read before.

View File

@ -691,7 +691,7 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
if (t->md5_session_checksum) { if (t->md5_session_checksum) {
/* Write tree checksum tag */ /* Write tree checksum tag */
ret = iso_md5_write_tag(t, t->checksum_tree_tag_pos, 3); ret = iso_md5_write_tag(t, 3);
} }
#endif /* Libisofs_with_checksumS */ #endif /* Libisofs_with_checksumS */
@ -874,7 +874,7 @@ void *write_function(void *arg)
/* Write superblock checksum tag */ /* Write superblock checksum tag */
if (target->md5_session_checksum && target->checksum_ctx != NULL) { if (target->md5_session_checksum && target->checksum_ctx != NULL) {
res = iso_md5_write_tag(target, target->checksum_sb_tag_pos, 2); res = iso_md5_write_tag(target, 2);
if (res < 0) if (res < 0)
goto write_error; goto write_error;
} }
@ -1099,6 +1099,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->checksum_counter = 0; target->checksum_counter = 0;
target->checksum_sb_tag_pos = 0; target->checksum_sb_tag_pos = 0;
target->checksum_tree_tag_pos = 0; target->checksum_tree_tag_pos = 0;
target->checksum_tag_pos = 0;
target->checksum_buffer = NULL; target->checksum_buffer = NULL;
target->checksum_array_pos = 0; target->checksum_array_pos = 0;
target->checksum_range_start = 0; target->checksum_range_start = 0;

View File

@ -456,6 +456,7 @@ struct ecma119_image
off_t checksum_counter; off_t checksum_counter;
uint32_t checksum_sb_tag_pos; uint32_t checksum_sb_tag_pos;
uint32_t checksum_tree_tag_pos; uint32_t checksum_tree_tag_pos;
uint32_t checksum_tag_pos;
char image_md5[16]; char image_md5[16];
char *checksum_buffer; char *checksum_buffer;
uint32_t checksum_array_pos; uint32_t checksum_array_pos;

View File

@ -2278,6 +2278,15 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block)
return ISO_SUCCESS; return ISO_SUCCESS;
} }
static
int iso_src_check_sb_tree(IsoDataSource *src, uint32_t start_lba, int flag)
{
/* >>>> */;
return 2;
}
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)
{ {
@ -2342,6 +2351,21 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
/* read Volume Descriptors and ensure it is a valid image */ /* read Volume Descriptors and ensure it is a valid image */
#ifdef Libisofs_with_checksumS
if (data->md5_load) {
/* >>> 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 */;
}
}
#endif /* Libisofs_with_checksumS */
/* 1. first, open the filesystem */ /* 1. first, open the filesystem */
ifs_fs_open(ifs); ifs_fs_open(ifs);

View File

@ -5046,9 +5046,10 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag);
/** /**
* Check a data block whether it is a libisofs session checksum tag and * Check a data block whether it is a libisofs session checksum tag and
* eventually obtain its recorded parameters. These tags get written after * eventually obtain its recorded parameters. These tags get written after
* the checksum arrays and can be detected without loading the image tree. * volume descriptors, directory tree and checksum array and can be detected
* without loading the image tree.
* One may start reading and computing MD5 at the suspected image session * One may start reading and computing MD5 at the suspected image session
* start and look out for a session tag on the fly. * start and look out for a session tag on the fly. See doc/checksum.txt .
* @param data * @param data
* A complete and aligned data block read from an ISO image session. * A complete and aligned data block read from an ISO image session.
* @param pos * @param pos
@ -5063,6 +5064,9 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag);
* @param range_size * @param range_size
* Returns the number of blocks beginning at range_start which are * Returns the number of blocks beginning at range_start which are
* covered by parameter md5. * covered by parameter md5.
* @param next_tag
* Returns the predicted block address of the next tag.
* Valid only with return values 2 and 3 and if not 0.
* @param md5 * @param md5
* Returns 16 byte of MD5 checksum. * Returns 16 byte of MD5 checksum.
* @param flag * @param flag
@ -5074,7 +5078,9 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag);
* 3= tree tag * 3= tree tag
* @return * @return
* 0= not a checksum tag, return parameters are invalid * 0= not a checksum tag, return parameters are invalid
* 1= checksum tag found * 1= session tag found
* 2= superblock tag found
* 3= tree tag found
* <0= error * <0= error
* return parameters are valid with error ISO_MD5_AREA_CORRUPTED * return parameters are valid with error ISO_MD5_AREA_CORRUPTED
* but not trustworthy because the tag seems corrupted. * but not trustworthy because the tag seems corrupted.
@ -5083,7 +5089,7 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag);
*/ */
int iso_util_decode_md5_tag(char data[2048], uint32_t *pos, int iso_util_decode_md5_tag(char data[2048], uint32_t *pos,
uint32_t *range_start, uint32_t *range_size, uint32_t *range_start, uint32_t *range_size,
char md5[16], int flag); uint32_t *next_tag, char md5[16], int flag);
/* The following functions allow to do own MD5 computations. E.g for /* The following functions allow to do own MD5 computations. E.g for

View File

@ -487,11 +487,14 @@ int checksum_writer_compute_data_blocks(IsoImageWriter *writer)
size = (t->checksum_idx_counter + 2) / 128; size = (t->checksum_idx_counter + 2) / 128;
if (size * 128 < t->checksum_idx_counter + 2) if (size * 128 < t->checksum_idx_counter + 2)
size++; size++;
t->curblock += size + 1; t->curblock += size;
/* + 1 = extra block for stream detectable checksum tag */
t->checksum_range_size = t->checksum_array_pos + size t->checksum_range_size = t->checksum_array_pos + size
- t->checksum_range_start; - t->checksum_range_start;
/* Extra block for stream detectable checksum tag */
t->checksum_tag_pos = t->curblock;
t->curblock++;
/* Allocate array of MD5 sums */ /* Allocate array of MD5 sums */
t->checksum_buffer = calloc(size, 2048); t->checksum_buffer = calloc(size, 2048);
if (t->checksum_buffer == NULL) if (t->checksum_buffer == NULL)
@ -592,47 +595,10 @@ int checksum_writer_write_data(IsoImageWriter *writer)
} }
/* Write stream detectable checksum tag to extra block */; /* Write stream detectable checksum tag to extra block */;
res = iso_md5_write_tag(t, 1);
#ifdef NIX
memset(tag_block, 0, 2048);
res = iso_md5_end(&(t->checksum_ctx), md5);
if (res > 0) {
sprintf(tag_block,
"libisofs_checksum_tag_v1 pos=%u range_start=%u range_size=%u md5=",
t->checksum_array_pos + (unsigned int) size,
t->checksum_range_start, t->checksum_range_size);
l = strlen(tag_block);
for (i = 0; i < 16; i++)
sprintf(tag_block + l + 2 * i, "%2.2x",
((unsigned char *) md5)[i]);
res = iso_md5_start(&ctx);
if (res > 0) {
iso_md5_compute(ctx, tag_block, l + 32);
iso_md5_end(&ctx, md5);
strcpy(tag_block + l + 32, " self=");
l += 32 + 6;
for (i = 0; i < 16; i++)
sprintf(tag_block + l + 2 * i, "%2.2x",
((unsigned char *) md5)[i]);
}
tag_block[l + 32] = '\n';
}
wres = iso_write(t, tag_block, 2048);
if (wres < 0) {
res = wres;
goto ex;
}
#else /* NIX */
res = iso_md5_write_tag(t, t->checksum_array_pos + (uint32_t) size, 1);
if (res < 0) if (res < 0)
goto ex; goto ex;
#endif /* ! NIX */
res = ISO_SUCCESS; res = ISO_SUCCESS;
ex:; ex:;
if (ctx != NULL) if (ctx != NULL)
@ -694,7 +660,7 @@ int checksum_writer_create(Ecma119Image *target)
* 2= superblock tag (System Area and Volume Descriptors) * 2= superblock tag (System Area and Volume Descriptors)
* 3= tree tag (ECMA-119 and Rock Ridge tree) * 3= tree tag (ECMA-119 and Rock Ridge tree)
*/ */
int iso_md5_write_tag(Ecma119Image *t, uint32_t pos, int flag) int iso_md5_write_tag(Ecma119Image *t, int flag)
{ {
#ifdef Libisofs_with_checksumS #ifdef Libisofs_with_checksumS
@ -702,7 +668,7 @@ int iso_md5_write_tag(Ecma119Image *t, uint32_t pos, int flag)
int res, mode, l, i, wres; int res, mode, l, i, wres;
void *ctx = NULL; void *ctx = NULL;
char md5[16], tag_block[2048]; char md5[16], tag_block[2048];
uint32_t size; uint32_t size= 0, pos, next_pos = 0;
static char *tag_ids[4]= {"", static char *tag_ids[4]= {"",
"libisofs_checksum_tag_v1", "libisofs_checksum_tag_v1",
"libisofs_sb_checksum_tag_v1", "libisofs_sb_checksum_tag_v1",
@ -713,7 +679,15 @@ int iso_md5_write_tag(Ecma119Image *t, uint32_t pos, int flag)
if (mode == 1) { if (mode == 1) {
res = iso_md5_end(&(t->checksum_ctx), md5); res = iso_md5_end(&(t->checksum_ctx), md5);
size = t->checksum_range_size; size = t->checksum_range_size;
pos = t->checksum_tag_pos;
} else if (mode == 2 || mode == 3) { } else if (mode == 2 || mode == 3) {
if (mode == 2) {
pos = t->checksum_sb_tag_pos;
next_pos = t->checksum_tree_tag_pos;
} else {
pos = t->checksum_tree_tag_pos;
next_pos = t->checksum_tag_pos;
}
size = pos - t->checksum_range_start; size = pos - t->checksum_range_start;
res = iso_md5_clone(t->checksum_ctx, &ctx); res = iso_md5_clone(t->checksum_ctx, &ctx);
if (res < 0) if (res < 0)
@ -724,20 +698,28 @@ int iso_md5_write_tag(Ecma119Image *t, uint32_t pos, int flag)
} }
if (res > 0) { if (res > 0) {
sprintf(tag_block, sprintf(tag_block,
"%s pos=%u range_start=%u range_size=%u md5=", "%s pos=%u range_start=%u range_size=%u",
tag_ids[mode], pos, tag_ids[mode], pos,
t->checksum_range_start, size); t->checksum_range_start, size);
l = strlen(tag_block); l = strlen(tag_block);
if (mode == 2) {
sprintf(tag_block + l, " next=%u", t->checksum_tree_tag_pos);
} else if (mode == 3) {
sprintf(tag_block + l, " next=%u", t->checksum_tag_pos);
}
strcat(tag_block + l, " md5=");
l = strlen(tag_block);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
sprintf(tag_block + l + 2 * i, "%2.2x", sprintf(tag_block + l + 2 * i, "%2.2x",
((unsigned char *) md5)[i]); ((unsigned char *) md5)[i]);
l+= 32;
res = iso_md5_start(&ctx); res = iso_md5_start(&ctx);
if (res > 0) { if (res > 0) {
iso_md5_compute(ctx, tag_block, l + 32); iso_md5_compute(ctx, tag_block, l);
iso_md5_end(&ctx, md5); iso_md5_end(&ctx, md5);
strcpy(tag_block + l + 32, " self="); strcpy(tag_block + l, " self=");
l += 32 + 6; l += 6;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
sprintf(tag_block + l + 2 * i, "%2.2x", sprintf(tag_block + l + 2 * i, "%2.2x",
((unsigned char *) md5)[i]); ((unsigned char *) md5)[i]);

View File

@ -34,13 +34,12 @@ int checksum_xinfo_func(void *data, int flag);
* Type 1 is written at the very end of the session. If it matches, then * Type 1 is written at the very end of the session. If it matches, then
* the whole image is trustworthy. * the whole image is trustworthy.
* @param t The image being written * @param t The image being written
* @param pos The LBA where this tag block is supposed to be written
* @flag bit0-7= tag type * @flag bit0-7= tag type
* 1= session tag (End checksumming.) * 1= session tag (End checksumming.)
* 2= superblock tag (System Area and Volume Descriptors) * 2= superblock tag (System Area and Volume Descriptors)
* 3= tree tag (ECMA-119 and Rock Ridge tree) * 3= tree tag (ECMA-119 and Rock Ridge tree)
*/ */
int iso_md5_write_tag(Ecma119Image *t, uint32_t pos, int flag); int iso_md5_write_tag(Ecma119Image *t, int flag);
#endif /* ! LIBISO_MD5_H_ */ #endif /* ! LIBISO_MD5_H_ */

View File

@ -1565,7 +1565,7 @@ int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count,
int iso_util_decode_md5_tag(char data[2048], uint32_t *pos, int iso_util_decode_md5_tag(char data[2048], uint32_t *pos,
uint32_t *range_start, uint32_t *range_size, uint32_t *range_start, uint32_t *range_size,
char md5[16], int flag) uint32_t *next_tag, char md5[16], int flag)
{ {
static char *tag_magic[4] = {"", static char *tag_magic[4] = {"",
"libisofs_checksum_tag_v1", "libisofs_checksum_tag_v1",
@ -1576,6 +1576,7 @@ int iso_util_decode_md5_tag(char data[2048], uint32_t *pos,
char *cpt, self_md5[16], tag_md5[16]; char *cpt, self_md5[16], tag_md5[16];
void *ctx = NULL; void *ctx = NULL;
*next_tag = 0;
mode = flag & 255; mode = flag & 255;
if (mode > magic_last) if (mode > magic_last)
return ISO_WRONG_ARG_VALUE; return ISO_WRONG_ARG_VALUE;
@ -1606,6 +1607,14 @@ int iso_util_decode_md5_tag(char data[2048], uint32_t *pos,
ret = iso_util_dec_to_uint32(cpt + 11, range_size, 0); ret = iso_util_dec_to_uint32(cpt + 11, range_size, 0);
if (ret <= 0) if (ret <= 0)
return 0; return 0;
if (found == 2 || found == 3) {
cpt = strstr(cpt, "next=");
if (cpt == NULL)
return(0);
ret = iso_util_dec_to_uint32(cpt + 5, next_tag, 0);
if (ret <= 0)
return 0;
}
cpt = strstr(cpt, "md5="); cpt = strstr(cpt, "md5=");
if (cpt == NULL) if (cpt == NULL)
return(0); return(0);