From 955471a064dca24edd2d7193b7dc3b695f8755ad Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sun, 16 Aug 2009 16:58:41 +0200 Subject: [PATCH] Augmented checksum tags for superblock and tree by parameter next= for unambigous linking. --- doc/checksums.txt | 15 +++++++-- libisofs/ecma119.c | 5 +-- libisofs/ecma119.h | 1 + libisofs/fs_image.c | 24 ++++++++++++++ libisofs/libisofs.h | 14 ++++++--- libisofs/md5.c | 76 +++++++++++++++++---------------------------- libisofs/md5.h | 3 +- libisofs/util.c | 11 ++++++- 8 files changed, 90 insertions(+), 59 deletions(-) diff --git a/doc/checksums.txt b/doc/checksums.txt index 0c26667..4d95e6e 100644 --- a/doc/checksums.txt +++ b/doc/checksums.txt @@ -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 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 "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 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= 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 -In order to check for a trustworthy loadable image tree, read the first -32 blocks of the session and look for the superblock checksum tag by +In order to check for a trustworthy loadable image tree, read the first 32 +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); If one appears and has plausible parameters, then check whether its MD5 matches the MD5 of the data blocks read before. diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 5be9a94..92d65ad 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -691,7 +691,7 @@ int ecma119_writer_write_data(IsoImageWriter *writer) if (t->md5_session_checksum) { /* 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 */ @@ -874,7 +874,7 @@ void *write_function(void *arg) /* Write superblock checksum tag */ 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) goto write_error; } @@ -1099,6 +1099,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img) target->checksum_counter = 0; target->checksum_sb_tag_pos = 0; target->checksum_tree_tag_pos = 0; + target->checksum_tag_pos = 0; target->checksum_buffer = NULL; target->checksum_array_pos = 0; target->checksum_range_start = 0; diff --git a/libisofs/ecma119.h b/libisofs/ecma119.h index 7a981be..61704bc 100644 --- a/libisofs/ecma119.h +++ b/libisofs/ecma119.h @@ -456,6 +456,7 @@ struct ecma119_image off_t checksum_counter; uint32_t checksum_sb_tag_pos; uint32_t checksum_tree_tag_pos; + uint32_t checksum_tag_pos; char image_md5[16]; char *checksum_buffer; uint32_t checksum_array_pos; diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index e22e681..535975d 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -2278,6 +2278,15 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) 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 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 */ +#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 */ ifs_fs_open(ifs); diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index ae7812e..ead093f 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -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 * 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 - * 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 * A complete and aligned data block read from an ISO image session. * @param pos @@ -5063,6 +5064,9 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag); * @param range_size * Returns the number of blocks beginning at range_start which are * 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 * Returns 16 byte of MD5 checksum. * @param flag @@ -5074,7 +5078,9 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag); * 3= tree tag * @return * 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 * return parameters are valid with error ISO_MD5_AREA_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, 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 diff --git a/libisofs/md5.c b/libisofs/md5.c index 6f02ea7..94f60eb 100644 --- a/libisofs/md5.c +++ b/libisofs/md5.c @@ -487,11 +487,14 @@ int checksum_writer_compute_data_blocks(IsoImageWriter *writer) size = (t->checksum_idx_counter + 2) / 128; if (size * 128 < t->checksum_idx_counter + 2) size++; - t->curblock += size + 1; - /* + 1 = extra block for stream detectable checksum tag */ + t->curblock += size; t->checksum_range_size = t->checksum_array_pos + size - t->checksum_range_start; + /* Extra block for stream detectable checksum tag */ + t->checksum_tag_pos = t->curblock; + t->curblock++; + /* Allocate array of MD5 sums */ t->checksum_buffer = calloc(size, 2048); if (t->checksum_buffer == NULL) @@ -592,47 +595,10 @@ int checksum_writer_write_data(IsoImageWriter *writer) } /* Write stream detectable checksum tag to extra block */; - -#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); + res = iso_md5_write_tag(t, 1); if (res < 0) goto ex; -#endif /* ! NIX */ - res = ISO_SUCCESS; ex:; if (ctx != NULL) @@ -694,7 +660,7 @@ int checksum_writer_create(Ecma119Image *target) * 2= superblock tag (System Area and Volume Descriptors) * 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 @@ -702,7 +668,7 @@ int iso_md5_write_tag(Ecma119Image *t, uint32_t pos, int flag) int res, mode, l, i, wres; void *ctx = NULL; char md5[16], tag_block[2048]; - uint32_t size; + uint32_t size= 0, pos, next_pos = 0; static char *tag_ids[4]= {"", "libisofs_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) { res = iso_md5_end(&(t->checksum_ctx), md5); size = t->checksum_range_size; + pos = t->checksum_tag_pos; } 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; res = iso_md5_clone(t->checksum_ctx, &ctx); if (res < 0) @@ -724,20 +698,28 @@ int iso_md5_write_tag(Ecma119Image *t, uint32_t pos, int flag) } if (res > 0) { 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, t->checksum_range_start, size); 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++) sprintf(tag_block + l + 2 * i, "%2.2x", ((unsigned char *) md5)[i]); - + l+= 32; + res = iso_md5_start(&ctx); if (res > 0) { - iso_md5_compute(ctx, tag_block, l + 32); + iso_md5_compute(ctx, tag_block, l); iso_md5_end(&ctx, md5); - strcpy(tag_block + l + 32, " self="); - l += 32 + 6; + strcpy(tag_block + l, " self="); + l += 6; for (i = 0; i < 16; i++) sprintf(tag_block + l + 2 * i, "%2.2x", ((unsigned char *) md5)[i]); diff --git a/libisofs/md5.h b/libisofs/md5.h index 18ce149..522d7fb 100644 --- a/libisofs/md5.h +++ b/libisofs/md5.h @@ -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 * the whole image is trustworthy. * @param t The image being written - * @param pos The LBA where this tag block is supposed to be written * @flag bit0-7= tag type * 1= session tag (End checksumming.) * 2= superblock tag (System Area and Volume Descriptors) * 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_ */ diff --git a/libisofs/util.c b/libisofs/util.c index 9b1cae8..86077e3 100644 --- a/libisofs/util.c +++ b/libisofs/util.c @@ -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, 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] = {"", "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]; void *ctx = NULL; + *next_tag = 0; mode = flag & 255; if (mode > magic_last) 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); if (ret <= 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="); if (cpt == NULL) return(0);