tools.c: refactored verify_ramdisk_digest()

This consists of several changes at once:
- purged unneccessary variables;
- fixed variable and function types;
- more readable return values;
- improved error logging;
- optimized hash printout just in case.

The original version of this patch fixed an off-by-one
issue too (it's been committed separately now).
This commit is contained in:
Дмитрий Левин 2014-04-23 01:38:54 +04:00 committed by Michael Shigorin
parent f9326392c4
commit 3d63eecb8d
3 changed files with 50 additions and 39 deletions

View File

@ -67,7 +67,9 @@ static int mount_that_cd_device(char * dev_name)
/* test_that_cd() returns 0 on success */
static int test_that_cd(int no_digest)
{
if (IS_VERIFICATION && !no_digest) return !verify_ramdisk_digest(get_ramdisk_path(NULL), get_param_valued("hash"));
if (IS_VERIFICATION && !no_digest)
return verify_ramdisk_digest(get_ramdisk_path(NULL),
get_param_valued("hash")) == RETURN_ERROR;
log_message("test file on cd: %s\n", get_ramdisk_path(NULL));
return access(get_ramdisk_path(NULL), R_OK);
}

83
tools.c
View File

@ -355,51 +355,60 @@ char * get_ramdisk_path(const char *mount_path)
}
/* This function is used to protect against stage2 (aka ramdisk) spoofing */
int verify_ramdisk_digest(const char *filename, const char *sha256_hash)
enum return_type verify_ramdisk_digest(const char *filename, const char *sha256_hash)
{
FILE *fp;
char buffer[8192];
size_t len;
sha256_context ctx;
uint8 digest[32];
char computed_hash[64+1];
char * wait_msg = "Verifying stage2 authenticity...";
if (!sha256_hash)
return RETURN_ERROR;
int fd;
struct stat st;
int bytes_read = 0;
int ramdisk_size;
if(sha256_hash == NULL) return 0;
if(stat(filename, &st)) return 0;
ramdisk_size = st.st_size;
fp = fopen(filename, "rb");
if(fp == NULL) return 0;
init_progression(wait_msg, ramdisk_size);
sha256_starts(&ctx);
while((len = fread(buffer, 1, sizeof(buffer), fp)) > 0)
{
if(ferror(fp))
{
fclose(fp);
log_message("error reading ramdisk");
remove_wait_message();
return 0;
}
sha256_update(&ctx, buffer, len);
update_progression((int)(bytes_read += len));
if ((fd = open(filename, O_RDONLY)) < 0 || fstat(fd, &st)) {
log_message("verify_ramdisk_digest: %s: %m", filename);
close(fd);
return RETURN_ERROR;
}
sha256_finish(&ctx, digest);
init_progression("Verifying stage2 authenticity...", st.st_size);
sha256_context ctx;
sha256_starts(&ctx);
ssize_t bytes_read = 0, total_bytes_read = 0;
unsigned char buffer[8192];
while ((bytes_read = read(fd, buffer, sizeof(buffer)))) {
if (bytes_read < 0) {
if (EINTR == errno)
continue;
log_message("verify_ramdisk_digest: %s: %m", filename);
close(fd);
remove_wait_message();
return RETURN_ERROR;
}
sha256_update(&ctx, buffer, bytes_read);
total_bytes_read += bytes_read;
update_progression(total_bytes_read);
}
close(fd);
end_progression();
fclose(fp);
uint8 digest[256/8];
sha256_finish(&ctx, digest);
len = 0;
int i = 0;
for (i; i < 32; i++) len += sprintf(computed_hash + len, "%02x", digest[i]);
const char *hex = "0123456789abcdef";
unsigned i;
char computed_hash[sizeof(digest)*2 + 1];
char *dest = computed_hash;
return (strcmp(computed_hash, sha256_hash) == 0);
for (i = 0; i < sizeof(digest); ++i) {
*(dest++) = hex[(digest[i] >> 4) & 0xf];
*(dest++) = hex[digest[i] & 0xf];
}
*dest = '\0';
return strcmp(computed_hash, sha256_hash) ? RETURN_ERROR : RETURN_OK;
}
enum return_type load_ramdisk(char *mount_path)

View File

@ -43,7 +43,7 @@ char ** list_directory(char * direct);
int string_array_length(char ** a);
int do_losetup(char * device, char * target);
char * get_ramdisk_path(const char *);
int verify_ramdisk_digest(const char *filename, const char *sha256_hash);
enum return_type verify_ramdisk_digest(const char *filename, const char *sha256_hash);
int splash_verbose();
int update_splash(char * state);
int prepare_progress(void);