Introduced checksum tags for superblock and directory tree.

This commit is contained in:
2009-08-16 13:57:42 +02:00
parent 9467f2e644
commit b4e2a60cd9
7 changed files with 319 additions and 57 deletions

View File

@ -241,6 +241,16 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
target->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
target->path_table_size = path_table_size;
#ifdef Libisofs_with_checksumS
if (target->md5_session_checksum) {
/* Account for tree checksum tag */
target->checksum_tree_tag_pos = target->curblock;
target->curblock++;
}
#endif /* Libisofs_with_checksumS */
return ISO_SUCCESS;
}
@ -674,6 +684,17 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
/* and write the path tables */
ret = write_path_tables(t);
if (ret < 0)
return ret;
#ifdef Libisofs_with_checksumS
if (t->md5_session_checksum) {
/* Write tree checksum tag */
ret = iso_md5_write_tag(t, t->checksum_tree_tag_pos, 3);
}
#endif /* Libisofs_with_checksumS */
return ret;
}
@ -849,6 +870,18 @@ void *write_function(void *arg)
}
}
#ifdef Libisofs_with_checksumS
/* 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);
if (res < 0)
goto write_error;
}
#endif /* Libisofs_with_checksumS */
/* write data for each writer */
for (i = 0; i < target->nwriters; ++i) {
writer = target->writers[i];
@ -1064,6 +1097,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->checksum_idx_counter = 0;
target->checksum_ctx = NULL;
target->checksum_counter = 0;
target->checksum_sb_tag_pos = 0;
target->checksum_tree_tag_pos = 0;
target->checksum_buffer = NULL;
target->checksum_array_pos = 0;
target->checksum_range_start = 0;
@ -1175,8 +1210,6 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
#ifdef Libisofs_with_checksumS
/* ??? Is it safe to add a writer after the content writer ? */
if (target->md5_file_checksums || target->md5_session_checksum) {
ret = checksum_writer_create(target);
if (ret < 0)

View File

@ -454,6 +454,8 @@ struct ecma119_image
unsigned int checksum_idx_counter;
void *checksum_ctx;
off_t checksum_counter;
uint32_t checksum_sb_tag_pos;
uint32_t checksum_tree_tag_pos;
char image_md5[16];
char *checksum_buffer;
uint32_t checksum_array_pos;

View File

@ -5065,6 +5065,13 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag);
* covered by parameter md5.
* @param md5
* Returns 16 byte of MD5 checksum.
* @param flag
* Bitfield for control purposes:
* bit0-bit7= tag type being looked for
* 0= any checksum tag
* 1= session tag
* 2= superblock tag
* 3= tree tag
* @return
* 0= not a checksum tag, return parameters are invalid
* 1= checksum tag found

View File

@ -519,7 +519,12 @@ int checksum_writer_compute_data_blocks(IsoImageWriter *writer)
static
int checksum_writer_write_vol_desc(IsoImageWriter *writer)
{
/* nothing needed */
/* The superblock checksum tag has to be written after
the Volume Descriptor Set Terminator and thus may not be
written by this function. (It would have been neat, though).
*/
return ISO_SUCCESS;
}
@ -530,11 +535,16 @@ int checksum_writer_write_data(IsoImageWriter *writer)
#ifdef Libisofs_with_checksumS
int wres, res, l;
int wres, res;
size_t i, size;
Ecma119Image *t;
void *ctx = NULL;
char md5[16], tag_block[2048];
char md5[16];
#ifdef NIX
char tag_block[2048];
int l;
#endif
if (writer == NULL) {
return ISO_ASSERT_FAILURE;
@ -582,6 +592,9 @@ 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) {
@ -612,13 +625,25 @@ int checksum_writer_write_data(IsoImageWriter *writer)
goto ex;
}
#endif /* Libisofs_with_checksumS */
#else /* NIX */
res = iso_md5_write_tag(t, t->checksum_array_pos + (uint32_t) size, 1);
if (res < 0)
goto ex;
#endif /* ! NIX */
res = ISO_SUCCESS;
ex:;
if (ctx != NULL)
iso_md5_end(&ctx, md5);
return(res);
#else /* Libisofs_with_checksumS */
return ISO_SUCCESS;
#endif /* ! Libisofs_with_checksumS */
}
@ -649,6 +674,93 @@ int checksum_writer_create(Ecma119Image *target)
/* add this writer to image */
target->writers[target->nwriters++] = writer;
#ifdef Libisofs_with_checksumS
/* Account for superblock checksum tag */
if (target->md5_session_checksum) {
target->checksum_sb_tag_pos = target->curblock;
target->curblock++;
}
#endif /* Libisofs_with_checksumS */
return ISO_SUCCESS;
}
/* Write stream detectable checksum tag to extra block.
* @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)
{
#ifdef Libisofs_with_checksumS
int res, mode, l, i, wres;
void *ctx = NULL;
char md5[16], tag_block[2048];
uint32_t size;
static char *tag_ids[4]= {"",
"libisofs_checksum_tag_v1",
"libisofs_sb_checksum_tag_v1",
"libisofs_tree_checksum_tag_v1"};
memset(tag_block, 0, 2048);
mode = flag & 255;
if (mode == 1) {
res = iso_md5_end(&(t->checksum_ctx), md5);
size = t->checksum_range_size;
} else if (mode == 2 || mode == 3) {
size = pos - t->checksum_range_start;
res = iso_md5_clone(t->checksum_ctx, &ctx);
if (res < 0)
return res;
res = iso_md5_end(&ctx, md5);
} else {
return ISO_WRONG_ARG_VALUE;
}
if (res > 0) {
sprintf(tag_block,
"%s pos=%u range_start=%u range_size=%u md5=",
tag_ids[mode], pos,
t->checksum_range_start, 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;
}
res = ISO_SUCCESS;
ex:;
if (ctx != NULL)
iso_md5_end(&ctx, md5);
return res;
#else /* Libisofs_with_checksumS */
return ISO_SUCCESS;
#endif /* ! Libisofs_with_checksumS */
}

View File

@ -26,6 +26,23 @@ int checksum_writer_create(Ecma119Image *target);
int checksum_xinfo_func(void *data, int flag);
/* Write stream detectable checksum tag to extra block.
* All tag ranges start at the beginning of the System Area (i.e. t->ms_block)
* and stem from the same MD5 computation context. Tag types 2 and 3 are
* intermediate checksums. Type 2 announces the existence of type 3.
* If both match, then at least the directory tree is trustworthy.
* 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);
#endif /* ! LIBISO_MD5_H_ */

View File

@ -1567,15 +1567,30 @@ 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)
{
static char *tag_magic= "libisofs_checksum_tag_v1 pos=";
static int magic_len= 29;
int ret, bin_count, i;
static char *tag_magic[4] = {"",
"libisofs_checksum_tag_v1",
"libisofs_sb_checksum_tag_v1",
"libisofs_tree_checksum_tag_v1"};
static int magic_len[4]= {0, 24, 27, 29};
int ret, bin_count, i, mode, magic_first = 1, magic_last = 3, found = 0;
char *cpt, self_md5[16], tag_md5[16];
void *ctx = NULL;
if (strncmp(data, tag_magic, magic_len) != 0)
return(0);
cpt = data + magic_len;
mode = flag & 255;
if (mode > magic_last)
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)
break;
if (i > magic_last )
return 0;
found = i;
cpt = data + magic_len[found] + 1;
if (strncmp(cpt, "pos=", 4) != 0)
return 0;
cpt+= 4;
ret = iso_util_dec_to_uint32(cpt, pos, 0);
if (ret <= 0)
return 0;
@ -1615,6 +1630,6 @@ int iso_util_decode_md5_tag(char data[2048], uint32_t *pos,
return ISO_MD5_AREA_CORRUPTED;
if (*(cpt + 5 + 32) != '\n')
return 0;
return(1);
return(found);
}