uri: Add checksum validation

This commit is contained in:
czapek1337 2022-09-11 20:47:57 +02:00 committed by mintsuki
parent 5a6cc57773
commit 2a4cbcecc0
5 changed files with 66 additions and 6 deletions

View File

@ -33,7 +33,7 @@ extern struct volume *boot_volume;
extern bool stage3_loaded;
#endif
extern bool quiet, serial, editor_enabled;
extern bool quiet, serial, editor_enabled, hash_mismatch_panic;
bool parse_resolution(size_t *width, size_t *height, size_t *bpp, const char *buf);

View File

@ -6,6 +6,7 @@
bool verbose = false;
bool quiet = false;
bool serial = false;
bool hash_mismatch_panic = false;
uint8_t bcd_to_int(uint8_t val) {
return (val & 0x0f) + ((val & 0xf0) >> 4) * 10;

View File

@ -9,10 +9,13 @@
#include <lib/print.h>
#include <pxe/tftp.h>
#include <tinf.h>
#include <menu.h>
#include <lib/readline.h>
#include <crypt/blake2b.h>
// A URI takes the form of: resource://root/path
// A URI takes the form of: resource://root/path#hash
// The following function splits up a URI into its componenets
bool uri_resolve(char *uri, char **resource, char **root, char **path) {
bool uri_resolve(char *uri, char **resource, char **root, char **path, char **hash) {
size_t length = strlen(uri) + 1;
char *buf = ext_mem_alloc(length);
memcpy(buf, uri, length);
@ -51,6 +54,31 @@ bool uri_resolve(char *uri, char **resource, char **root, char **path) {
return false;
*path = uri;
// Get hash
for (int i = (int)strlen(uri) - 1; i >= 0; i--) {
if (uri[i] != '#') {
continue;
}
uri[i++] = 0;
if (hash != NULL) {
*hash = uri + i;
}
if (strlen(uri + i) != 128) {
panic(true, "Blake2b hash must be 128 characters long");
return false;
}
break;
}
for (size_t i = 0; ; i++) {
if (uri[i] == 0)
break;
}
return true;
}
@ -190,8 +218,10 @@ static struct file_handle *uri_boot_dispatch(char *s_part, char *path) {
struct file_handle *uri_open(char *uri) {
struct file_handle *ret;
char *resource, *root, *path;
uri_resolve(uri, &resource, &root, &path);
char *resource = NULL, *root = NULL, *path = NULL, *hash = NULL;
if (!uri_resolve(uri, &resource, &root, &path, &hash)) {
return NULL;
}
if (resource == NULL) {
panic(true, "No resource specified for URI `%#`.", uri);
@ -225,6 +255,32 @@ struct file_handle *uri_open(char *uri) {
panic(true, "Resource `%s` not valid.", resource);
}
if (hash != NULL && ret != NULL) {
uint8_t out_buf[BLAKE2B_OUT_BYTES];
void *file_buf = freadall(ret, MEMMAP_BOOTLOADER_RECLAIMABLE);
blake2b(out_buf, file_buf, ret->size);
uint8_t hash_buf[BLAKE2B_OUT_BYTES];
for (size_t i = 0; i < sizeof(hash_buf); i++) {
hash_buf[i] = digit_to_int(hash[i * 2]) << 4 | digit_to_int(hash[i * 2 + 1]);
}
if (memcmp(hash_buf, out_buf, sizeof(out_buf)) != 0) {
if (hash_mismatch_panic) {
panic(true, "Blake2b hash for URI `%#` does not match!", uri);
} else {
print("WARNING: Blake2b hash for URI `%#` does not match!\n"
" Press Y to continue, press any other key otherwise...", uri);
char ch = getchar();
if (ch != 'Y' && ch != 'y') {
menu(false);
}
print("\n");
}
}
}
if (compressed && ret != NULL) {
struct file_handle *compressed_fd = ext_mem_alloc(sizeof(struct file_handle));
fread(ret, &compressed_fd->size, ret->size - 4, sizeof(uint32_t));

View File

@ -4,7 +4,7 @@
#include <stdbool.h>
#include <fs/file.h>
bool uri_resolve(char *uri, char **resource, char **root, char **path);
bool uri_resolve(char *uri, char **resource, char **root, char **path, char **hash);
struct file_handle *uri_open(char *uri);
#endif

View File

@ -653,6 +653,9 @@ noreturn void _menu(bool first_run) {
char *serial_str = config_get_value(NULL, 0, "SERIAL");
serial = serial_str != NULL && strcmp(serial_str, "yes") == 0;
char *hash_mismatch_panic_str = config_get_value(NULL, 0, "HASH_MISMATCH_PANIC");
hash_mismatch_panic = hash_mismatch_panic_str == NULL || strcmp(hash_mismatch_panic_str, "yes") == 0;
char *randomise_mem_str = config_get_value(NULL, 0, "RANDOMISE_MEMORY");
if (randomise_mem_str == NULL)
randomise_mem_str = config_get_value(NULL, 0, "RANDOMIZE_MEMORY");