Browse Source

Improved API. hash_file procs now just take a file handle instead of a path

zhibog 3 years ago
parent
commit
f48ee00c2f

+ 1 - 2
core/crypto/README.md

@@ -5,7 +5,6 @@ A crypto library for the Odin language
 This library offers various algorithms available in either native Odin or via bindings to the [Botan](https://botan.randombit.net/) crypto library.
 Please see the chart below for the options.  
 **Note:** All crypto hash algorithms, offered by [Botan\'s FFI](https://botan.randombit.net/handbook/api_ref/hash.html), have been added.
-If you wish to use Botan, make sure you have installed it and the dll is available in either the global path or next to your binary.
 
 ## Hashing algorithms
 | Algorithm                                                                                                    | Odin             | Botan                |
@@ -42,7 +41,7 @@ Included in these groups are four procedures.
 * `hash_string` - Hash a given string and return the computed hash. Just calls `hash_bytes` internally
 * `hash_bytes` - Hash a given byte slice and return the computed hash
 * `hash_stream` - Takes a stream from io.Stream and returns the computed hash from it
-* `hash_file` - Hashes a file. A second boolean parameter controls if the file is streamed (set to false) or read at once (set to true)
+* `hash_file` - Takes a file handle and returns the computed hash from it. A second optional boolean parameter controls if the file is streamed (this is the default) or read at once (set to true)
 
 \*\*\* On some algorithms there is another part to the name, since they might offer control about additional parameters.  
 For instance, `HAVAL` offers different sizes as well as three different round amounts.  

+ 11 - 10
core/crypto/_ctx/_ctx.odin

@@ -11,6 +11,7 @@ package _ctx
 */
 
 import "core:io"
+import "core:os"
 
 Hash_Size :: enum {
     _16,
@@ -44,15 +45,15 @@ Hash_Context_Vtable :: struct {
     hash_bytes_48     : proc (ctx: ^Hash_Context, input: []byte) -> [48]byte,
     hash_bytes_64     : proc (ctx: ^Hash_Context, input: []byte) -> [64]byte,
     hash_bytes_128    : proc (ctx: ^Hash_Context, input: []byte) -> [128]byte,
-    hash_file_16      : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([16]byte,  bool),
-    hash_file_20      : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([20]byte,  bool),
-    hash_file_24      : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([24]byte,  bool),
-    hash_file_28      : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([28]byte,  bool),
-    hash_file_32      : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([32]byte,  bool),
-    hash_file_40      : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([40]byte,  bool),
-    hash_file_48      : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([48]byte,  bool),
-    hash_file_64      : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([64]byte,  bool),
-    hash_file_128     : proc (ctx: ^Hash_Context, path: string, load_at_once: bool)  -> ([128]byte, bool),
+    hash_file_16      : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte,  bool),
+    hash_file_20      : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([20]byte,  bool),
+    hash_file_24      : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([24]byte,  bool),
+    hash_file_28      : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte,  bool),
+    hash_file_32      : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte,  bool),
+    hash_file_40      : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([40]byte,  bool),
+    hash_file_48      : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte,  bool),
+    hash_file_64      : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte,  bool),
+    hash_file_128     : proc (ctx: ^Hash_Context, hd: os.Handle, load_at_once := false) -> ([128]byte, bool),
     hash_stream_16    : proc (ctx: ^Hash_Context, s: io.Stream)  -> ([16]byte,  bool),
     hash_stream_20    : proc (ctx: ^Hash_Context, s: io.Stream)  -> ([20]byte,  bool),
     hash_stream_24    : proc (ctx: ^Hash_Context, s: io.Stream)  -> ([24]byte,  bool),
@@ -63,7 +64,7 @@ Hash_Context_Vtable :: struct {
     hash_stream_64    : proc (ctx: ^Hash_Context, s: io.Stream)  -> ([64]byte,  bool),
     hash_stream_128   : proc (ctx: ^Hash_Context, s: io.Stream)  -> ([128]byte, bool),
     hash_bytes_slice  : proc (ctx: ^Hash_Context, input: []byte, out_size: int, allocator := context.allocator) -> []byte,
-    hash_file_slice   : proc (ctx: ^Hash_Context, path: string,  out_size: int, load_at_once: bool, allocator := context.allocator) -> ([]byte, bool),
+    hash_file_slice   : proc (ctx: ^Hash_Context, hd: os.Handle, out_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool),
     hash_stream_slice : proc (ctx: ^Hash_Context, s: io.Stream,  out_size: int, allocator := context.allocator) -> ([]byte, bool),
     init              : proc (ctx: ^Hash_Context),
     update            : proc (ctx: ^Hash_Context, data: []byte),

+ 41 - 52
core/crypto/blake/blake.odin

@@ -15,6 +15,7 @@ import "core:os"
 import "core:io"
 
 import "../_ctx"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -105,11 +106,11 @@ hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224 will read the file provided by the given handle
+// and compute a hash
+hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
     _create_blake256_ctx(true, ._28)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224 :: proc {
@@ -139,11 +140,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_blake256_ctx(false, ._32)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -173,11 +174,11 @@ hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
     return _hash_impl->hash_stream_48(s)
 }
 
-// hash_file_384 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_384 :: proc(path: string, load_at_once: bool) -> ([48]byte, bool) {
+// hash_file_384 will read the file provided by the given handle
+// and compute a hash
+hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
     _create_blake512_ctx(true, ._48)
-    return _hash_impl->hash_file_48(path, load_at_once)
+    return _hash_impl->hash_file_48(hd, load_at_once)
 }
 
 hash_384 :: proc {
@@ -207,11 +208,11 @@ hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file_512 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_512 :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file_512 will read the file provided by the given handle
+// and compute a hash
+hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
     _create_blake512_ctx(false, ._64)
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash_512 :: proc {
@@ -267,15 +268,12 @@ hash_stream_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([28]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_28(ctx, buf[:]), read_ok
-            }
+hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_28(ctx, buf[:]), ok
         }
     }
     return [28]byte{}, false
@@ -311,15 +309,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false
@@ -355,15 +350,12 @@ hash_stream_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([48]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_48(ctx, buf[:]), read_ok
-            }
+hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_48(ctx, buf[:]), ok
         }
     }
     return [48]byte{}, false
@@ -399,15 +391,12 @@ hash_stream_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_64(ctx, buf[:]), read_ok
-            }
+hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_64(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false

+ 11 - 13
core/crypto/blake2b/blake2b.odin

@@ -18,6 +18,7 @@ import "core:io"
 import "../botan"
 import "../_ctx"
 import "../_blake2"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -82,11 +83,11 @@ hash_stream :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
     _create_blake2_ctx()
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash :: proc {
@@ -142,15 +143,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false

+ 11 - 13
core/crypto/blake2s/blake2s.odin

@@ -17,6 +17,7 @@ import "core:io"
 
 import "../_ctx"
 import "../_blake2"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -82,11 +83,11 @@ hash_stream :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_blake2_ctx()
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash :: proc {
@@ -142,15 +143,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false

+ 55 - 27
core/crypto/botan/hash.odin

@@ -16,6 +16,7 @@ import "core:fmt"
 import "core:strings"
 
 import "../_ctx"
+import "../util"
 
 hash_bytes_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, data: []byte) -> [16]byte {
     hash: [16]byte
@@ -107,76 +108,103 @@ hash_bytes_slice :: #force_inline proc(ctx: ^_ctx.Hash_Context, data: []byte, bi
     return hash[:]
 }
 
-hash_file_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
         return hash_stream_16(ctx, os.stream_from_handle(hd))
     } else {
-        return [16]byte{}, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_16(ctx, buf[:]), ok
+        }
     }
+    return [16]byte{}, false
 }
 
-hash_file_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([20]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
+    if !load_at_once {
         return hash_stream_20(ctx, os.stream_from_handle(hd))
     } else {
-        return [20]byte{}, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_20(ctx, buf[:]), ok
+        }
     }
+    return [20]byte{}, false
 }
 
-hash_file_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([24]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
+    if !load_at_once {
         return hash_stream_24(ctx, os.stream_from_handle(hd))
     } else {
-        return [24]byte{}, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_24(ctx, buf[:]), ok
+        }
     }
+    return [24]byte{}, false
 }
 
-hash_file_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([28]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
+    if !load_at_once {
         return hash_stream_28(ctx, os.stream_from_handle(hd))
     } else {
-        return [28]byte{}, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_28(ctx, buf[:]), ok
+        }
     }
+    return [28]byte{}, false
 }
 
-hash_file_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
         return hash_stream_32(ctx, os.stream_from_handle(hd))
     } else {
-        return [32]byte{}, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_32(ctx, buf[:]), ok
+        }
     }
+    return [32]byte{}, false
 }
 
-hash_file_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([48]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
+    if !load_at_once {
         return hash_stream_48(ctx, os.stream_from_handle(hd))
     } else {
-        return [48]byte{}, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_48(ctx, buf[:]), ok
+        }
     }
+    return [48]byte{}, false
 }
 
-hash_file_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
         return hash_stream_64(ctx, os.stream_from_handle(hd))
     } else {
-        return [64]byte{}, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_64(ctx, buf[:]), ok
+        }
     }
+    return [64]byte{}, false
 }
 
-hash_file_128 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([128]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_128 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([128]byte, bool) {
+    if !load_at_once {
         return hash_stream_128(ctx, os.stream_from_handle(hd))
     } else {
-        return [128]byte{}, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_128(ctx, buf[:]), ok
+        }
     }
+    return [128]byte{}, false
 }
 
-hash_file_slice :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, bit_size: int, load_at_once: bool, allocator := context.allocator) -> ([]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
+hash_file_slice :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, bit_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool) {
+    if !load_at_once {
         return hash_stream_slice(ctx, os.stream_from_handle(hd), bit_size, allocator)
     } else {
-        return nil, false
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_slice(ctx, buf[:], bit_size, allocator), ok
+        }
     }
+    return nil, false
 }
 
 hash_stream_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, s: io.Stream) -> ([16]byte, bool) {

+ 11 - 13
core/crypto/gost/gost.odin

@@ -17,6 +17,7 @@ import "core:io"
 
 import "../botan"
 import "../_ctx"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -75,11 +76,11 @@ hash_stream :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_gost_ctx()
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash :: proc {
@@ -135,15 +136,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false

+ 41 - 52
core/crypto/groestl/groestl.odin

@@ -15,6 +15,7 @@ import "core:os"
 import "core:io"
 
 import "../_ctx"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -102,11 +103,11 @@ hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224 will read the file provided by the given handle
+// and compute a hash
+hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
     _create_groestl_ctx(._28)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224 :: proc {
@@ -136,11 +137,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_groestl_ctx(._32)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -170,11 +171,11 @@ hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
     return _hash_impl->hash_stream_48(s)
 }
 
-// hash_file_384 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_384 :: proc(path: string, load_at_once: bool) -> ([48]byte, bool) {
+// hash_file_384 will read the file provided by the given handle
+// and compute a hash
+hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
     _create_groestl_ctx(._48)
-    return _hash_impl->hash_file_48(path, load_at_once)
+    return _hash_impl->hash_file_48(hd, load_at_once)
 }
 
 hash_384 :: proc {
@@ -204,11 +205,11 @@ hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file_512 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_512 :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file_512 will read the file provided by the given handle
+// and compute a hash
+hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
     _create_groestl_ctx(._64)
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash_512 :: proc {
@@ -264,15 +265,12 @@ hash_stream_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([28]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_28(ctx, buf[:]), read_ok
-            }
+hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_28(ctx, buf[:]), ok
         }
     }
     return [28]byte{}, false
@@ -308,15 +306,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false
@@ -352,15 +347,12 @@ hash_stream_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([48]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_48(ctx, buf[:]), read_ok
-            }
+hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_48(ctx, buf[:]), ok
         }
     }
     return [48]byte{}, false
@@ -396,15 +388,12 @@ hash_stream_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_64(ctx, buf[:]), read_ok
-            }
+hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_64(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false

+ 90 - 105
core/crypto/haval/haval.odin

@@ -109,11 +109,11 @@ hash_stream_128_3 :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file_128_3 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_128_3 :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file_128_3 will read the file provided by the given handle
+// and compute a hash
+hash_file_128_3 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_haval_ctx(._16, 3)
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash_128_3 :: proc {
@@ -143,11 +143,11 @@ hash_stream_128_4 :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file_128_4 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_128_4 :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file_128_4 will read the file provided by the given handle
+// and compute a hash
+hash_file_128_4 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_haval_ctx(._16, 4)
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash_128_4 :: proc {
@@ -177,11 +177,11 @@ hash_stream_128_5 :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file_128_5 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_128_5 :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file_128_5 will read the file provided by the given handle
+// and compute a hash
+hash_file_128_5 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_haval_ctx(._16, 5)
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash_128_5 :: proc {
@@ -211,11 +211,11 @@ hash_stream_160_3 :: proc(s: io.Stream) -> ([20]byte, bool) {
     return _hash_impl->hash_stream_20(s)
 }
 
-// hash_file_160_3 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_160_3 :: proc(path: string, load_at_once: bool) -> ([20]byte, bool) {
+// hash_file_160_3 will read the file provided by the given handle
+// and compute a hash
+hash_file_160_3 :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
     _create_haval_ctx(._20, 3)
-    return _hash_impl->hash_file_20(path, load_at_once)
+    return _hash_impl->hash_file_20(hd, load_at_once)
 }
 
 hash_160_3 :: proc {
@@ -245,11 +245,11 @@ hash_stream_160_4 :: proc(s: io.Stream) -> ([20]byte, bool) {
     return _hash_impl->hash_stream_20(s)
 }
 
-// hash_file_160_4 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_160_4 :: proc(path: string, load_at_once: bool) -> ([20]byte, bool) {
+// hash_file_160_4 will read the file provided by the given handle
+// and compute a hash
+hash_file_160_4 :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
     _create_haval_ctx(._20, 4)
-    return _hash_impl->hash_file_20(path, load_at_once)
+    return _hash_impl->hash_file_20(hd, load_at_once)
 }
 
 hash_160_4 :: proc {
@@ -279,11 +279,11 @@ hash_stream_160_5 :: proc(s: io.Stream) -> ([20]byte, bool) {
     return _hash_impl->hash_stream_20(s)
 }
 
-// hash_file_160_5 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_160_5 :: proc(path: string, load_at_once: bool) -> ([20]byte, bool) {
+// hash_file_160_5 will read the file provided by the given handle
+// and compute a hash
+hash_file_160_5 :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
     _create_haval_ctx(._20, 5)
-    return _hash_impl->hash_file_20(path, load_at_once)
+    return _hash_impl->hash_file_20(hd, load_at_once)
 }
 
 hash_160_5 :: proc {
@@ -313,11 +313,11 @@ hash_stream_192_3 :: proc(s: io.Stream) -> ([24]byte, bool) {
     return _hash_impl->hash_stream_24(s)
 }
 
-// hash_file_192_3 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_192_3 :: proc(path: string, load_at_once: bool) -> ([24]byte, bool) {
+// hash_file_192_3 will read the file provided by the given handle
+// and compute a hash
+hash_file_192_3 :: proc(hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
     _create_haval_ctx(._24, 3)
-    return _hash_impl->hash_file_24(path, load_at_once)
+    return _hash_impl->hash_file_24(hd, load_at_once)
 }
 
 hash_192_3 :: proc {
@@ -347,11 +347,11 @@ hash_stream_192_4 :: proc(s: io.Stream) -> ([24]byte, bool) {
     return _hash_impl->hash_stream_24(s)
 }
 
-// hash_file_192_4 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_192_4 :: proc(path: string, load_at_once: bool) -> ([24]byte, bool) {
+// hash_file_192_4 will read the file provided by the given handle
+// and compute a hash
+hash_file_192_4 :: proc(hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
     _create_haval_ctx(._24, 4)
-    return _hash_impl->hash_file_24(path, load_at_once)
+    return _hash_impl->hash_file_24(hd, load_at_once)
 }
 
 hash_192_4 :: proc {
@@ -381,11 +381,11 @@ hash_stream_192_5 :: proc(s: io.Stream) -> ([24]byte, bool) {
     return _hash_impl->hash_stream_24(s)
 }
 
-// hash_file_192_5 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_192_5 :: proc(path: string, load_at_once: bool) -> ([24]byte, bool) {
+// hash_file_192_5 will read the file provided by the given handle
+// and compute a hash
+hash_file_192_5 :: proc(hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
     _create_haval_ctx(._24, 5)
-    return _hash_impl->hash_file_24(path, load_at_once)
+    return _hash_impl->hash_file_24(hd, load_at_once)
 }
 
 hash_192_5 :: proc {
@@ -415,11 +415,11 @@ hash_stream_224_3 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224_3 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224_3 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224_3 will read the file provided by the given handle
+// and compute a hash
+hash_file_224_3 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
     _create_haval_ctx(._28, 3)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224_3 :: proc {
@@ -449,11 +449,11 @@ hash_stream_224_4 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224_4 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224_4 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224_4 will read the file provided by the given handle
+// and compute a hash
+hash_file_224_4 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
     _create_haval_ctx(._28, 4)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224_4 :: proc {
@@ -483,11 +483,11 @@ hash_stream_224_5 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224_5 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224_5 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224_5 will read the file provided by the given handle
+// and compute a hash
+hash_file_224_5 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
     _create_haval_ctx(._28, 5)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224_5 :: proc {
@@ -517,11 +517,11 @@ hash_stream_256_3 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256_3 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256_3 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256_3 will read the file provided by the given handle
+// and compute a hash
+hash_file_256_3 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_haval_ctx(._32, 3)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256_3 :: proc {
@@ -551,11 +551,11 @@ hash_stream_256_4 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256_4 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256_4 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256_4 will read the file provided by the given handle
+// and compute a hash
+hash_file_256_4 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_haval_ctx(._32, 4)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256_4 :: proc {
@@ -585,11 +585,11 @@ hash_stream_256_5 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256_5 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256_5 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256_5 will read the file provided by the given handle
+// and compute a hash
+hash_file_256_5 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_haval_ctx(._32, 5)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256_5 :: proc {
@@ -647,15 +647,12 @@ hash_stream_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_16(ctx, buf[:]), read_ok
-            }
+hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_16(ctx, buf[:]), ok
         }
     }
     return [16]byte{}, false
@@ -693,15 +690,12 @@ hash_stream_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([20]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_20(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_20(ctx, buf[:]), read_ok
-            }
+hash_file_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_20(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_20(ctx, buf[:]), ok
         }
     }
     return [20]byte{}, false
@@ -739,15 +733,12 @@ hash_stream_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([24]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_24(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_24(ctx, buf[:]), read_ok
-            }
+hash_file_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_24(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_24(ctx, buf[:]), ok
         }
     }
     return [24]byte{}, false
@@ -785,15 +776,12 @@ hash_stream_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([28]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_28(ctx, buf[:]), read_ok
-            }
+hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_28(ctx, buf[:]), ok
         }
     }
     return [28]byte{}, false
@@ -831,15 +819,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false

+ 41 - 52
core/crypto/jh/jh.odin

@@ -15,6 +15,7 @@ import "core:os"
 import "core:io"
 
 import "../_ctx"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -102,11 +103,11 @@ hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224 will read the file provided by the given handle
+// and compute a hash
+hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
     _create_jh_ctx(._28)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224 :: proc {
@@ -136,11 +137,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_jh_ctx(._32)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -170,11 +171,11 @@ hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
     return _hash_impl->hash_stream_48(s)
 }
 
-// hash_file_384 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_384 :: proc(path: string, load_at_once: bool) -> ([48]byte, bool) {
+// hash_file_384 will read the file provided by the given handle
+// and compute a hash
+hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
     _create_jh_ctx(._48)
-    return _hash_impl->hash_file_48(path, load_at_once)
+    return _hash_impl->hash_file_48(hd, load_at_once)
 }
 
 hash_384 :: proc {
@@ -204,11 +205,11 @@ hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file_512 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_512 :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file_512 will read the file provided by the given handle
+// and compute a hash
+hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
     _create_jh_ctx(._64)
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash_512 :: proc {
@@ -264,15 +265,12 @@ hash_stream_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([28]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_28(ctx, buf[:]), read_ok
-            }
+hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_28(ctx, buf[:]), ok
         }
     }
     return [28]byte{}, false
@@ -308,15 +306,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false
@@ -352,15 +347,12 @@ hash_stream_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([48]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_48(ctx, buf[:]), read_ok
-            }
+hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_48(ctx, buf[:]), ok
         }
     }
     return [48]byte{}, false
@@ -396,15 +388,12 @@ hash_stream_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_64(ctx, buf[:]), read_ok
-            }
+hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_64(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false

+ 41 - 52
core/crypto/keccak/keccak.odin

@@ -18,6 +18,7 @@ import "core:io"
 import "../botan"
 import "../_ctx"
 import "../_sha3"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -91,11 +92,11 @@ hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224 will read the file provided by the given handle
+// and compute a hash
+hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
     _create_sha3_ctx(28)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224 :: proc {
@@ -125,11 +126,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_sha3_ctx(32)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -159,11 +160,11 @@ hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
     return _hash_impl->hash_stream_48(s)
 }
 
-// hash_file_384 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_384 :: proc(path: string, load_at_once: bool) -> ([48]byte, bool) {
+// hash_file_384 will read the file provided by the given handle
+// and compute a hash
+hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
     _create_sha3_ctx(48)
-    return _hash_impl->hash_file_48(path, load_at_once)
+    return _hash_impl->hash_file_48(hd, load_at_once)
 }
 
 hash_384 :: proc {
@@ -193,11 +194,11 @@ hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file_512 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_512 :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file_512 will read the file provided by the given handle
+// and compute a hash
+hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
     _create_sha3_ctx(64)
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash_512 :: proc {
@@ -253,15 +254,12 @@ hash_stream_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([28]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_28(ctx, buf[:]), read_ok
-            }
+hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_28(ctx, buf[:]), ok
         }
     }
     return [28]byte{}, false
@@ -297,15 +295,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false
@@ -341,15 +336,12 @@ hash_stream_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([48]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_48(ctx, buf[:]), read_ok
-            }
+hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_48(ctx, buf[:]), ok
         }
     }
     return [48]byte{}, false
@@ -385,15 +377,12 @@ hash_stream_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_64(ctx, buf[:]), read_ok
-            }
+hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_64(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false

+ 11 - 13
core/crypto/md2/md2.odin

@@ -15,6 +15,7 @@ import "core:os"
 import "core:io"
 
 import "../_ctx"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -80,11 +81,11 @@ hash_stream :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
 	_create_md2_ctx()
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash :: proc {
@@ -140,15 +141,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [16]byte{}, false

+ 10 - 13
core/crypto/md4/md4.odin

@@ -82,11 +82,11 @@ hash_stream :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_md4_ctx()
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash :: proc {
@@ -142,15 +142,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [16]byte{}, false

+ 10 - 13
core/crypto/md5/md5.odin

@@ -82,11 +82,11 @@ hash_stream :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_md5_ctx()
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash :: proc {
@@ -142,15 +142,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [16]byte{}, false

+ 40 - 52
core/crypto/ripemd/ripemd.odin

@@ -90,11 +90,11 @@ hash_stream_128 :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file_128 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_128 :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file_128 will read the file provided by the given handle
+// and compute a hash
+hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_ripemd_ctx(16)
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash_128 :: proc {
@@ -124,11 +124,11 @@ hash_stream_160 :: proc(s: io.Stream) -> ([20]byte, bool) {
     return _hash_impl->hash_stream_20(s)
 }
 
-// hash_file_160 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_160 :: proc(path: string, load_at_once: bool) -> ([20]byte, bool) {
+// hash_file_160 will read the file provided by the given handle
+// and compute a hash
+hash_file_160 :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
     _create_ripemd_ctx(20)
-    return _hash_impl->hash_file_20(path, load_at_once)
+    return _hash_impl->hash_file_20(hd, load_at_once)
 }
 
 hash_160 :: proc {
@@ -158,11 +158,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_ripemd_ctx(32)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -192,11 +192,11 @@ hash_stream_320 :: proc(s: io.Stream) -> ([40]byte, bool) {
     return _hash_impl->hash_stream_40(s)
 }
 
-// hash_file_320 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_320 :: proc(path: string, load_at_once: bool) -> ([40]byte, bool) {
+// hash_file_320 will read the file provided by the given handle
+// and compute a hash
+hash_file_320 :: proc(hd: os.Handle, load_at_once := false) -> ([40]byte, bool) {
     _create_ripemd_ctx(40)
-    return _hash_impl->hash_file_40(path, load_at_once)
+    return _hash_impl->hash_file_40(hd, load_at_once)
 }
 
 hash_320 :: proc {
@@ -236,15 +236,12 @@ hash_stream_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_16(ctx, buf[:]), read_ok
-            }
+hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_16(ctx, buf[:]), ok
         }
     }
     return [16]byte{}, false
@@ -280,15 +277,12 @@ hash_stream_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([20]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_20(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_20(ctx, buf[:]), read_ok
-            }
+hash_file_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_20(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_20(ctx, buf[:]), ok
         }
     }
     return [20]byte{}, false
@@ -324,15 +318,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false
@@ -368,15 +359,12 @@ hash_stream_odin_40 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_40 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([40]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_40(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_40(ctx, buf[:]), read_ok
-            }
+hash_file_odin_40 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([40]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_40(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_40(ctx, buf[:]), ok
         }
     }
     return [40]byte{}, false

+ 10 - 13
core/crypto/sha1/sha1.odin

@@ -82,11 +82,11 @@ hash_stream :: proc(s: io.Stream) -> ([20]byte, bool) {
     return _hash_impl->hash_stream_20(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([20]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
 	_create_sha1_ctx()
-    return _hash_impl->hash_file_20(path, load_at_once)
+    return _hash_impl->hash_file_20(hd, load_at_once)
 }
 
 hash :: proc {
@@ -142,15 +142,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([20]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [20]byte{}, false

+ 40 - 52
core/crypto/sha2/sha2.odin

@@ -108,11 +108,11 @@ hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224 will read the file provided by the given handle
+// and compute a hash
+hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
 	_create_sha256_ctx(true)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224 :: proc {
@@ -142,11 +142,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
 	_create_sha256_ctx(false)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -176,11 +176,11 @@ hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
     return _hash_impl->hash_stream_48(s)
 }
 
-// hash_file_384 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_384 :: proc(path: string, load_at_once: bool) -> ([48]byte, bool) {
+// hash_file_384 will read the file provided by the given handle
+// and compute a hash
+hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
 	_create_sha512_ctx(true)
-    return _hash_impl->hash_file_48(path, load_at_once)
+    return _hash_impl->hash_file_48(hd, load_at_once)
 }
 
 hash_384 :: proc {
@@ -210,11 +210,11 @@ hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file_512 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_512 :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file_512 will read the file provided by the given handle
+// and compute a hash
+hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
 	_create_sha512_ctx(false)
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash_512 :: proc {
@@ -270,15 +270,12 @@ hash_stream_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([28]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_28(ctx, buf[:]), read_ok
-            }
+hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_28(ctx, buf[:]), ok
         }
     }
     return [28]byte{}, false
@@ -314,15 +311,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false
@@ -358,15 +352,12 @@ hash_stream_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([48]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_48(ctx, buf[:]), read_ok
-            }
+hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_48(ctx, buf[:]), ok
         }
     }
     return [48]byte{}, false
@@ -402,15 +393,12 @@ hash_stream_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_64(ctx, buf[:]), read_ok
-            }
+hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_64(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false

+ 41 - 52
core/crypto/sha3/sha3.odin

@@ -18,6 +18,7 @@ import "core:io"
 import "../botan"
 import "../_ctx"
 import "../_sha3"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -91,11 +92,11 @@ hash_stream_224 :: proc(s: io.Stream) -> ([28]byte, bool) {
     return _hash_impl->hash_stream_28(s)
 }
 
-// hash_file_224 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_224 :: proc(path: string, load_at_once: bool) -> ([28]byte, bool) {
+// hash_file_224 will read the file provided by the given handle
+// and compute a hash
+hash_file_224 :: proc(hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
     _create_sha3_ctx(28)
-    return _hash_impl->hash_file_28(path, load_at_once)
+    return _hash_impl->hash_file_28(hd, load_at_once)
 }
 
 hash_224 :: proc {
@@ -125,11 +126,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_sha3_ctx(32)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -159,11 +160,11 @@ hash_stream_384 :: proc(s: io.Stream) -> ([48]byte, bool) {
     return _hash_impl->hash_stream_48(s)
 }
 
-// hash_file_384 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_384 :: proc(path: string, load_at_once: bool) -> ([48]byte, bool) {
+// hash_file_384 will read the file provided by the given handle
+// and compute a hash
+hash_file_384 :: proc(hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
     _create_sha3_ctx(48)
-    return _hash_impl->hash_file_48(path, load_at_once)
+    return _hash_impl->hash_file_48(hd, load_at_once)
 }
 
 hash_384 :: proc {
@@ -193,11 +194,11 @@ hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file_512 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_512 :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file_512 will read the file provided by the given handle
+// and compute a hash
+hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
     _create_sha3_ctx(64)
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash_512 :: proc {
@@ -253,15 +254,12 @@ hash_stream_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([28]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_28(ctx, buf[:]), read_ok
-            }
+hash_file_odin_28 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([28]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_28(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_28(ctx, buf[:]), ok
         }
     }
     return [28]byte{}, false
@@ -297,15 +295,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false
@@ -341,15 +336,12 @@ hash_stream_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([48]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_48(ctx, buf[:]), read_ok
-            }
+hash_file_odin_48 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([48]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_48(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_48(ctx, buf[:]), ok
         }
     }
     return [48]byte{}, false
@@ -385,15 +377,12 @@ hash_stream_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_64(ctx, buf[:]), read_ok
-            }
+hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_64(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false

+ 21 - 26
core/crypto/shake/shake.odin

@@ -18,6 +18,7 @@ import "core:io"
 import "../botan"
 import "../_ctx"
 import "../_sha3"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -85,11 +86,11 @@ hash_stream_128 :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file_128 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_128 :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file_128 will read the file provided by the given handle
+// and compute a hash
+hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_sha3_ctx(16)
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash_128 :: proc {
@@ -119,11 +120,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_sha3_ctx(32)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -181,15 +182,12 @@ hash_stream_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_16(ctx, buf[:]), read_ok
-            }
+hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_16(ctx, buf[:]), ok
         }
     }
     return [16]byte{}, false
@@ -227,15 +225,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false

+ 31 - 39
core/crypto/skein/skein.odin

@@ -18,6 +18,7 @@ import "core:io"
 
 import "../botan"
 import "../_ctx"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -138,11 +139,11 @@ hash_skein256_stream :: proc(s: io.Stream, bit_size: int, allocator := context.a
     return _hash_impl->hash_stream_slice(s, bit_size, allocator)
 }
 
-// hash_skein256_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_skein256_file :: proc(path: string, bit_size: int, load_at_once: bool, allocator := context.allocator) -> ([]byte, bool) {
+// hash_skein256_file will read the file provided by the given handle
+// and compute a hash
+hash_skein256_file :: proc(hd: os.Handle, bit_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool) {
     _create_skein256_ctx(bit_size)
-    return _hash_impl->hash_file_slice(path, bit_size, load_at_once, allocator)
+    return _hash_impl->hash_file_slice(hd, bit_size, load_at_once, allocator)
 }
 
 hash_skein256 :: proc {
@@ -172,11 +173,11 @@ hash_skein512_stream :: proc(s: io.Stream, bit_size: int, allocator := context.a
     return _hash_impl->hash_stream_slice(s, bit_size, allocator)
 }
 
-// hash_skein512_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_skein512_file :: proc(path: string, bit_size: int, load_at_once: bool, allocator := context.allocator) -> ([]byte, bool) {
+// hash_skein512_file will read the file provided by the given handle
+// and compute a hash
+hash_skein512_file :: proc(hd: os.Handle, bit_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool) {
     _create_skein512_ctx(bit_size)
-    return _hash_impl->hash_file_slice(path, bit_size, load_at_once, allocator)
+    return _hash_impl->hash_file_slice(hd, bit_size, load_at_once, allocator)
 }
 
 hash_skein512 :: proc {
@@ -206,11 +207,11 @@ hash_skein1024_stream :: proc(s: io.Stream, bit_size: int, allocator := context.
     return _hash_impl->hash_stream_slice(s, bit_size, allocator)
 }
 
-// hash_skein1024_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_skein1024_file :: proc(path: string, bit_size: int, load_at_once: bool, allocator := context.allocator) -> ([]byte, bool) {
+// hash_skein1024_file will read the file provided by the given handle
+// and compute a hash
+hash_skein1024_file :: proc(hd: os.Handle, bit_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool) {
     _create_skein1024_ctx(bit_size)
-    return _hash_impl->hash_file_slice(path, bit_size, load_at_once, allocator)
+    return _hash_impl->hash_file_slice(hd, bit_size, load_at_once, allocator)
 }
 
 hash_skein1024 :: proc {
@@ -270,15 +271,12 @@ hash_stream_skein256_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.
     }
 }
 
-hash_file_skein256_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, bit_size: int, load_at_once: bool, allocator := context.allocator) -> ([]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_skein256_odin(ctx, os.stream_from_handle(hd), bit_size, allocator)
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_skein256_odin(ctx, buf[:], bit_size), read_ok
-            }
+hash_file_skein256_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, bit_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool) {
+    if !load_at_once {
+        return hash_stream_skein256_odin(ctx, os.stream_from_handle(hd), bit_size, allocator)
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_skein256_odin(ctx, buf[:], bit_size, allocator), ok
         }
     }
     return nil, false
@@ -318,15 +316,12 @@ hash_stream_skein512_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.
     }
 }
 
-hash_file_skein512_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, bit_size: int, load_at_once: bool, allocator := context.allocator) -> ([]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_skein512_odin(ctx, os.stream_from_handle(hd), bit_size, allocator)
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_skein512_odin(ctx, buf[:], bit_size), read_ok
-            }
+hash_file_skein512_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, bit_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool) {
+    if !load_at_once {
+        return hash_stream_skein512_odin(ctx, os.stream_from_handle(hd), bit_size, allocator)
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_skein512_odin(ctx, buf[:], bit_size, allocator), ok
         }
     }
     return nil, false
@@ -366,15 +361,12 @@ hash_stream_skein1024_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io
     }
 }
 
-hash_file_skein1024_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, bit_size: int, load_at_once: bool, allocator := context.allocator) -> ([]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_skein1024_odin(ctx, os.stream_from_handle(hd), bit_size, allocator)
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_skein1024_odin(ctx, buf[:], bit_size), read_ok
-            }
+hash_file_skein1024_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, bit_size: int, load_at_once := false, allocator := context.allocator) -> ([]byte, bool) {
+    if !load_at_once {
+        return hash_stream_skein512_odin(ctx, os.stream_from_handle(hd), bit_size, allocator)
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_skein512_odin(ctx, buf[:], bit_size, allocator), ok
         }
     }
     return nil, false

+ 10 - 13
core/crypto/sm3/sm3.odin

@@ -81,11 +81,11 @@ hash_stream :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
     _create_sm3_ctx()
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash :: proc {
@@ -141,15 +141,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false

+ 20 - 26
core/crypto/streebog/streebog.odin

@@ -92,11 +92,11 @@ hash_stream_256 :: proc(s: io.Stream) -> ([32]byte, bool) {
     return _hash_impl->hash_stream_32(s)
 }
 
-// hash_file_256 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_256 :: proc(path: string, load_at_once: bool) -> ([32]byte, bool) {
+// hash_file_256 will read the file provided by the given handle
+// and compute a hash
+hash_file_256 :: proc(hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
 	_create_streebog_ctx(true)
-    return _hash_impl->hash_file_32(path, load_at_once)
+    return _hash_impl->hash_file_32(hd, load_at_once)
 }
 
 hash_256 :: proc {
@@ -126,11 +126,11 @@ hash_stream_512 :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file_512 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_512 :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file_512 will read the file provided by the given handle
+// and compute a hash
+hash_file_512 :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
 	_create_streebog_ctx(false)
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash_512 :: proc {
@@ -186,15 +186,12 @@ hash_stream_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([32]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_32(ctx, buf[:]), read_ok
-            }
+hash_file_odin_32 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([32]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_32(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_32(ctx, buf[:]), ok
         }
     }
     return [32]byte{}, false
@@ -230,15 +227,12 @@ hash_stream_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_64(ctx, buf[:]), read_ok
-            }
+hash_file_odin_64 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_64(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_64(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false

+ 31 - 39
core/crypto/tiger/tiger.odin

@@ -17,6 +17,7 @@ import "core:io"
 import "../botan"
 import "../_ctx"
 import "../_tiger"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -87,11 +88,11 @@ hash_stream_128 :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file_128 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_128 :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file_128 will read the file provided by the given handle
+// and compute a hash
+hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_ripemd_ctx(16)
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash_128 :: proc {
@@ -121,11 +122,11 @@ hash_stream_160 :: proc(s: io.Stream) -> ([20]byte, bool) {
     return _hash_impl->hash_stream_20(s)
 }
 
-// hash_file_160 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_160 :: proc(path: string, load_at_once: bool) -> ([20]byte, bool) {
+// hash_file_160 will read the file provided by the given handle
+// and compute a hash
+hash_file_160 :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
     _create_ripemd_ctx(20)
-    return _hash_impl->hash_file_20(path, load_at_once)
+    return _hash_impl->hash_file_20(hd, load_at_once)
 }
 
 hash_160 :: proc {
@@ -155,11 +156,11 @@ hash_stream_192 :: proc(s: io.Stream) -> ([24]byte, bool) {
     return _hash_impl->hash_stream_24(s)
 }
 
-// hash_file_192 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_192 :: proc(path: string, load_at_once: bool) -> ([24]byte, bool) {
+// hash_file_192 will read the file provided by the given handle
+// and compute a hash
+hash_file_192 :: proc(hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
     _create_ripemd_ctx(24)
-    return _hash_impl->hash_file_24(path, load_at_once)
+    return _hash_impl->hash_file_24(hd, load_at_once)
 }
 
 hash_192 :: proc {
@@ -199,15 +200,12 @@ hash_stream_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_16(ctx, buf[:]), read_ok
-            }
+hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_16(ctx, buf[:]), ok
         }
     }
     return [16]byte{}, false
@@ -243,15 +241,12 @@ hash_stream_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([20]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_20(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_20(ctx, buf[:]), read_ok
-            }
+hash_file_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_20(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_20(ctx, buf[:]), ok
         }
     }
     return [20]byte{}, false
@@ -287,15 +282,12 @@ hash_stream_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([24]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_24(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_24(ctx, buf[:]), read_ok
-            }
+hash_file_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_24(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_24(ctx, buf[:]), ok
         }
     }
     return [24]byte{}, false

+ 31 - 39
core/crypto/tiger2/tiger2.odin

@@ -16,6 +16,7 @@ import "core:io"
 
 import "../_ctx"
 import "../_tiger"
+import "../util"
 
 /*
     Context initialization and switching between the Odin implementation and the bindings
@@ -87,11 +88,11 @@ hash_stream_128 :: proc(s: io.Stream) -> ([16]byte, bool) {
     return _hash_impl->hash_stream_16(s)
 }
 
-// hash_file_128 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_128 :: proc(path: string, load_at_once: bool) -> ([16]byte, bool) {
+// hash_file_128 will read the file provided by the given handle
+// and compute a hash
+hash_file_128 :: proc(hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
     _create_ripemd_ctx(16)
-    return _hash_impl->hash_file_16(path, load_at_once)
+    return _hash_impl->hash_file_16(hd, load_at_once)
 }
 
 hash_128 :: proc {
@@ -121,11 +122,11 @@ hash_stream_160 :: proc(s: io.Stream) -> ([20]byte, bool) {
     return _hash_impl->hash_stream_20(s)
 }
 
-// hash_file_160 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_160 :: proc(path: string, load_at_once: bool) -> ([20]byte, bool) {
+// hash_file_160 will read the file provided by the given handle
+// and compute a hash
+hash_file_160 :: proc(hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
     _create_ripemd_ctx(20)
-    return _hash_impl->hash_file_20(path, load_at_once)
+    return _hash_impl->hash_file_20(hd, load_at_once)
 }
 
 hash_160 :: proc {
@@ -155,11 +156,11 @@ hash_stream_192 :: proc(s: io.Stream) -> ([24]byte, bool) {
     return _hash_impl->hash_stream_24(s)
 }
 
-// hash_file_192 will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file_192 :: proc(path: string, load_at_once: bool) -> ([24]byte, bool) {
+// hash_file_192 will read the file provided by the given handle
+// and compute a hash
+hash_file_192 :: proc(hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
     _create_ripemd_ctx(24)
-    return _hash_impl->hash_file_24(path, load_at_once)
+    return _hash_impl->hash_file_24(hd, load_at_once)
 }
 
 hash_192 :: proc {
@@ -199,15 +200,12 @@ hash_stream_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([16]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_16(ctx, buf[:]), read_ok
-            }
+hash_file_odin_16 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([16]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_16(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_16(ctx, buf[:]), ok
         }
     }
     return [16]byte{}, false
@@ -243,15 +241,12 @@ hash_stream_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([20]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_20(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_20(ctx, buf[:]), read_ok
-            }
+hash_file_odin_20 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([20]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_20(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_20(ctx, buf[:]), ok
         }
     }
     return [20]byte{}, false
@@ -287,15 +282,12 @@ hash_stream_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream
     }
 }
 
-hash_file_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([24]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin_24(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin_24(ctx, buf[:]), read_ok
-            }
+hash_file_odin_24 :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([24]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin_24(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin_24(ctx, buf[:]), ok
         }
     }
     return [24]byte{}, false

+ 26 - 0
core/crypto/util/util.odin

@@ -11,6 +11,7 @@ package util
 */
 
 import "core:mem"
+import "core:os"
 
 // @note(bp): this can replace the other two
 cast_slice :: #force_inline proc "contextless" ($D: typeid/[]$DE, src: $S/[]$SE) -> D {
@@ -141,4 +142,29 @@ XOR_BUF :: #force_inline proc "contextless" (input, output: []byte) {
     for i := 0; i < len(input); i += 1 {
         output[i] ~= input[i]
     }
+}
+
+// Taken from core:os and changed to just take a file handle
+read_entire_file :: proc(fd: os.Handle, allocator := context.allocator) -> (data: []byte, success: bool) {
+    length: i64
+    err: os.Errno
+    if length, err = os.file_size(fd); err != 0 {
+        return nil, false
+    }
+
+    if length <= 0 {
+        return nil, true
+    }
+
+    data = make([]byte, int(length), allocator)
+    if data == nil {
+        return nil, false
+    }
+
+    bytes_read, read_err := os.read(fd, data)
+    if read_err != os.ERROR_NONE {
+        delete(data)
+        return nil, false
+    }
+    return data[:bytes_read], true
 }

+ 10 - 13
core/crypto/whirlpool/whirlpool.odin

@@ -80,11 +80,11 @@ hash_stream :: proc(s: io.Stream) -> ([64]byte, bool) {
     return _hash_impl->hash_stream_64(s)
 }
 
-// hash_file will try to open the file provided by the given
-// path and pass it to hash_stream to compute a hash
-hash_file :: proc(path: string, load_at_once: bool) -> ([64]byte, bool) {
+// hash_file will read the file provided by the given handle
+// and compute a hash
+hash_file :: proc(hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
     _create_whirlpool_ctx()
-    return _hash_impl->hash_file_64(path, load_at_once)
+    return _hash_impl->hash_file_64(hd, load_at_once)
 }
 
 hash :: proc {
@@ -138,15 +138,12 @@ hash_stream_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, fs: io.Stream) -
     }
 }
 
-hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, path: string, load_at_once: bool) -> ([64]byte, bool) {
-    if hd, err := os.open(path); err == os.ERROR_NONE {
-        defer os.close(hd)
-        if !load_at_once {
-            return hash_stream_odin(ctx, os.stream_from_handle(hd))
-        } else {
-            if buf, read_ok := os.read_entire_file(path); read_ok {
-                return hash_bytes_odin(ctx, buf[:]), read_ok
-            }
+hash_file_odin :: #force_inline proc(ctx: ^_ctx.Hash_Context, hd: os.Handle, load_at_once := false) -> ([64]byte, bool) {
+    if !load_at_once {
+        return hash_stream_odin(ctx, os.stream_from_handle(hd))
+    } else {
+        if buf, ok := util.read_entire_file(hd); ok {
+            return hash_bytes_odin(ctx, buf[:]), ok
         }
     }
     return [64]byte{}, false