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

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

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