New API call iso_util_decode_md5_tag(). Augmented checksum tag by self-MD5.

This commit is contained in:
Thomas Schmitt 2009-08-14 16:32:10 +02:00
parent ba66a7896a
commit 9467f2e644
6 changed files with 158 additions and 13 deletions

View File

@ -70,12 +70,13 @@ The next block after the array begins with the checksum tag and is padded
by 0-bytes. The tag is a single line of printable text and has the following
format:
libisofs_checksum_tag_v1 pos=... range_start=... range_size=... md5=... \n
libisofs_checksum_tag_v1 pos=# range_start=# range_size=# md5=# self=#\n
Example:
libisofs_checksum_tag_v1 pos=81552 range_start=32 range_size=81520 md5=f172b994e8eb565a011d220b2a8b7a19
libisofs_checksum_tag_v1 pos=81552 range_start=32 range_size=81520 md5=f172b994e8eb565a011d220b2a8b7a19 self=020975b2aa1189d455db2c09560b8732
There are four parameters:
There are five parameters. The first three are decimal numbers, the others
are strings of 32 hex digits.
pos=
gives the block address where the tag supposes itself to be stored.
@ -85,16 +86,23 @@ There are four parameters:
range_start=
The block address where the session is supposed to start. If this does not
match the session start on media then the image volume descriptors of the
image have been been relocated. (The latter can happen with overwriteable
media.)
match the session start on media then the volume descriptors of the
image have been relocated. (This can happen with overwriteable media. If
checksumming started at LBA 0 and finds range_start=32, then one has to
restart checksumming at LBA 32. See libburn/doc/cookbook.txt
"ISO 9660 multi-session emulation on overwriteable media" for background
information.)
range_size=
The number of blocks beginning at range_start which are covered by the
checksum of the tag.
md5=
The checksum of the tag. Encoded as 32 hex digits.
The checksum payload of the tag as lower case hex digits.
self=
The MD5 checksum of the tag itself up to and including the last hex digit of
parameter "md5=".
The newline character at the end is mandatory. For now all bytes of the
block after that newline shall be zero. There may arise future extensions.

View File

@ -3201,7 +3201,7 @@ int iso_image_import(IsoImage *image, IsoDataSource *src,
)
break;
if (i < 16) {
iso_msg_submit(image->id, ISO_MD5_ARRAY_CORRUPTED, 0,
iso_msg_submit(image->id, ISO_MD5_AREA_CORRUPTED, 0,
"MD5 checksum array appears damaged and not trustworthy for verifications.");
free(image->checksum_array);
image->checksum_array = NULL;

View File

@ -4992,7 +4992,8 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
/* ---------------------------- MD5 Checksums --------------------------- */
/* Production and loading of MD5 checksums is controlled by calls
iso_write_opts_set_record_md5() and iso_read_opts_set_no_md5()
iso_write_opts_set_record_md5() and iso_read_opts_set_no_md5().
For data representation details see doc/checksums.txt .
*/
/**
@ -5042,6 +5043,41 @@ int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba,
*/
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.
* One may start reading and computing MD5 at the suspected image session
* start and look out for a session tag on the fly.
* @param data
* A complete and aligned data block read from an ISO image session.
* @param pos
* Returns the LBA where the tag supposes itself to be stored.
* If this does not match the data block LBA then the tag might be
* image data payload and should be ignored for image checksumming.
* @param range_start
* Returns the block address where the session is supposed to start.
* If this does not match the session start on media then the image
* volume descriptors have been been relocated.
* A proper checksum will only emerge if computing started at range_start.
* @param range_size
* Returns the number of blocks beginning at range_start which are
* covered by parameter md5.
* @param md5
* Returns 16 byte of MD5 checksum.
* @return
* 0= not a checksum tag, return parameters are invalid
* 1= checksum tag found
* <0= error
* return parameters are valid with error ISO_MD5_AREA_CORRUPTED
* but not trustworthy because the tag seems corrupted.
*
* @since 0.6.22
*/
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);
/* The following functions allow to do own MD5 computations. E.g for
comparing the result with a recorded checksum.
@ -5366,11 +5402,11 @@ int iso_md5_end(void **md5_context, char result[16]);
#define ISO_ZLIB_EARLY_EOF 0xE830FEA1
/**
* Checksum array appears damaged and not trustworthy for verifications.
* Checksum area appears damaged and not trustworthy for verifications.
* (WARNING,HIGH, -352)
* @since 0.6.22
*/
#define ISO_MD5_ARRAY_CORRUPTED 0xD030FEA0
#define ISO_MD5_AREA_CORRUPTED 0xD030FEA0
/* ! PLACE NEW ERROR CODES HERE ! */

View File

@ -593,6 +593,17 @@ int checksum_writer_write_data(IsoImageWriter *writer)
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);

View File

@ -260,8 +260,8 @@ const char *iso_error_to_msg(int errcode)
return "Cannot set global zisofs parameters while filters exist";
case ISO_ZLIB_EARLY_EOF:
return "Premature EOF of zlib input stream";
case ISO_MD5_ARRAY_CORRUPTED:
return "Checksum array appears damaged and not trustworthy for verifications";
case ISO_MD5_AREA_CORRUPTED:
return "Checksum area appears damaged and not trustworthy for verifications";
default:
return "Unknown error";
}

View File

@ -1528,3 +1528,93 @@ int iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len,
}
int iso_util_dec_to_uint32(char *dec, uint32_t *value, int flag)
{
double num;
sscanf(dec, "%lf", &num);
if (num < 0 || num > 4294967295.0)
return 0;
*value = num;
return 1;
}
int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count,
int flag)
{
static char *allowed = {"0123456789ABCDEFabcdef"};
char b[3];
int i;
unsigned int u;
b[2] = 0;
*bin_count = 0;
for (i = 0; i < bin_size; i++) {
b[0] = hex[2 * i];
b[1] = hex[2 * i + 1];
if (strchr(allowed, b[0]) == NULL || strchr(allowed, b[1]) == NULL)
break;
sscanf(b, "%x", &u);
((unsigned char *) bin)[i] = u;
(*bin_count)++;
}
return (*bin_count > 0);
}
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;
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;
ret = iso_util_dec_to_uint32(cpt, pos, 0);
if (ret <= 0)
return 0;
cpt = strstr(cpt, "range_start=");
if (cpt == NULL)
return(0);
ret = iso_util_dec_to_uint32(cpt + 12, range_start, 0);
if (ret <= 0)
return 0;
cpt = strstr(cpt, "range_size=");
if (cpt == NULL)
return(0);
ret = iso_util_dec_to_uint32(cpt + 11, range_size, 0);
if (ret <= 0)
return 0;
cpt = strstr(cpt, "md5=");
if (cpt == NULL)
return(0);
ret = iso_util_hex_to_bin(cpt + 4, md5, 16, &bin_count, 0);
if (ret <= 0 || bin_count != 16)
return 0;
cpt += 4 + 32;
ret = iso_md5_start(&ctx);
if (ret < 0)
return ret;
iso_md5_compute(ctx, data , cpt - data);
iso_md5_end(&ctx, tag_md5);
cpt = strstr(cpt, "self=");
if (cpt == NULL)
return(0);
ret = iso_util_hex_to_bin(cpt + 5, self_md5, 16, &bin_count, 0);
if (ret <= 0 || bin_count != 16)
return 0;
for(i= 0; i < 16; i++)
if(self_md5[i] != tag_md5[i])
return ISO_MD5_AREA_CORRUPTED;
if (*(cpt + 5 + 32) != '\n')
return 0;
return(1);
}