:: commit db799dee0327ab0d26840345a2271da4b7813cc7

Kamila Szewczyk <k@iczelia.net> — 2026-04-11 08:50

parents: 42eb5f97f3

crypto: streaming blake2b for validation

exposes the internals of the streaming blake2b checksum and integrates
the cryptography code with the standard fake-vtable mechanism for file
i/o in Limine, allowing for validation of the checksum without reading
the whole file into memory in one shot and caching it until closed.
diff --git a/common/crypt/blake2b.c b/common/crypt/blake2b.c
index b62183f3..40a40ede 100644
--- a/common/crypt/blake2b.c
+++ b/common/crypt/blake2b.c
@@ -5,6 +5,7 @@
 #include <stdint.h>
 #include <stddef.h>
 #include <crypt/blake2b.h>
+#include <fs/file.h>
 #include <lib/libc.h>
 
 #define BLAKE2B_BLOCK_BYTES 128
@@ -218,3 +219,25 @@ void blake2b(void *out, const void *in, size_t in_len) {
     blake2b_update(&state, in, in_len);
     blake2b_final(&state, out);
 }
+
+bool blake2b_verify_file(struct file_handle *fd, const uint8_t expected[BLAKE2B_OUT_BYTES]) {
+    uint8_t out_buf[BLAKE2B_OUT_BYTES];
+
+    if (fd->is_memfile) {
+        blake2b(out_buf, fd->fd, fd->size);
+        return memcmp(out_buf, expected, BLAKE2B_OUT_BYTES) == 0;
+    }
+    
+    struct blake2b_state state;
+    blake2b_init(&state);
+    char chunk_buf[4096];
+    
+    for (uint64_t r = fd->size, off = 0, sz; r > 0; off += sz, r -= sz) {
+        fd->read(fd, chunk_buf, off, sz = r < 4096 ? r : 4096);
+        blake2b_update(&state, chunk_buf, sz);
+    }
+    
+    blake2b_final(&state, out_buf);
+
+    return memcmp(out_buf, expected, BLAKE2B_OUT_BYTES) == 0;
+}
diff --git a/common/crypt/blake2b.h b/common/crypt/blake2b.h
index 313a7c63..7967d57f 100644
--- a/common/crypt/blake2b.h
+++ b/common/crypt/blake2b.h
@@ -7,4 +7,7 @@
 
 void blake2b(void *out, const void *in, size_t in_len);
 
+struct file_handle;
+bool blake2b_verify_file(struct file_handle *fd, const uint8_t expected[BLAKE2B_OUT_BYTES]);
+
 #endif
diff --git a/common/lib/uri.c b/common/lib/uri.c
index 7f868791..d04e3917 100644
--- a/common/lib/uri.c
+++ b/common/lib/uri.c
@@ -257,20 +257,13 @@ struct file_handle *uri_open(char *uri) {
     }
 
     if (hash != NULL && ret != NULL) {
-        uint8_t out_buf[BLAKE2B_OUT_BYTES];
-#if defined (UEFI) && defined (__x86_64__)
-        void *file_buf = freadall_mode(ret, MEMMAP_BOOTLOADER_RECLAIMABLE, true);
-#else
-        void *file_buf = freadall(ret, MEMMAP_BOOTLOADER_RECLAIMABLE);
-#endif
-        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 (!blake2b_verify_file(ret, hash_buf)) {
             if (hash_mismatch_panic) {
                 panic(true, "Blake2b hash for URI `%#` does not match!", uri);
             } else {
tab: 248 wrap: offon