aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYawning Angel <yawning@schwanenlied.me>2024-02-07 02:29:02 +0900
committerYawning Angel <yawning@schwanenlied.me>2024-02-07 02:33:53 +0900
commit44758f2a6035803e504a06ec1d6b47f6336bb8cb (patch)
treee18ff272c65514ce2c106b8babbb9737478628a4
parent56516ee8b267c1be0ca714db4b6c43bc8be508cb (diff)
core/crypto: Stop using context.temp_allocator
The max digest size for the foreseeable future will be 512 bits, and the max block size is currently 1152 bits (SHA3-224). If people add more exotic hash algorithms without bumping the constants when required, tests will fail. The stream buffer will currently be 576 bytes, which is "fine" to just stick on the stack, and is a sensible multiple of the more common block size of 64 bytes.
-rw-r--r--core/crypto/hash/hash.odin12
-rw-r--r--core/crypto/hash/low_level.odin7
-rw-r--r--core/crypto/hmac/hmac.odin13
-rw-r--r--tests/core/crypto/test_core_crypto_hash.odin25
4 files changed, 42 insertions, 15 deletions
diff --git a/core/crypto/hash/hash.odin b/core/crypto/hash/hash.odin
index 0840910c1..e4b3d4be1 100644
--- a/core/crypto/hash/hash.odin
+++ b/core/crypto/hash/hash.odin
@@ -56,17 +56,13 @@ hash_stream :: proc(
) {
ctx: Context
- init(&ctx, algorithm)
+ buf: [MAX_BLOCK_SIZE * 4]byte
+ defer mem.zero_explicit(&buf, size_of(buf))
- buffer_size := block_size(&ctx) * 4
- buf := make([]byte, buffer_size, context.temp_allocator)
- defer {
- mem.zero_explicit(raw_data(buf), buffer_size)
- delete(buf, context.temp_allocator)
- }
+ init(&ctx, algorithm)
loop: for {
- n, err := io.read(s, buf)
+ n, err := io.read(s, buf[:])
if n > 0 {
// XXX/yawning: Can io.read return n > 0 and EOF?
update(&ctx, buf[:n])
diff --git a/core/crypto/hash/low_level.odin b/core/crypto/hash/low_level.odin
index 2b40a0a7c..242eadd5f 100644
--- a/core/crypto/hash/low_level.odin
+++ b/core/crypto/hash/low_level.odin
@@ -11,6 +11,13 @@ import "core:crypto/legacy/sha1"
import "core:reflect"
+// MAX_DIGEST_SIZE is the maximum size digest that can be returned by any
+// of the Algorithms supported via this package.
+MAX_DIGEST_SIZE :: 64
+// MAX_BLOCK_SIZE is the maximum block size used by any of Algorithms
+// supported by this package.
+MAX_BLOCK_SIZE :: sha3.BLOCK_SIZE_224
+
// Algorithm is the algorithm identifier associated with a given Context.
Algorithm :: enum {
Invalid,
diff --git a/core/crypto/hmac/hmac.odin b/core/crypto/hmac/hmac.odin
index e9bd3b5ae..f720d2181 100644
--- a/core/crypto/hmac/hmac.odin
+++ b/core/crypto/hmac/hmac.odin
@@ -6,7 +6,6 @@ See:
*/
package hmac
-import "base:runtime"
import "core:crypto"
import "core:crypto/hash"
import "core:mem"
@@ -26,10 +25,9 @@ sum :: proc(algorithm: hash.Algorithm, dst, msg, key: []byte) {
// and key over msg and return true iff the tag is valid. It requires
// that the tag is correctly sized.
verify :: proc(algorithm: hash.Algorithm, tag, msg, key: []byte) -> bool {
- runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
- tag_sz := hash.DIGEST_SIZES[algorithm]
+ tag_buf: [hash.MAX_DIGEST_SIZE]byte
- derived_tag := make([]byte, tag_sz, context.temp_allocator)
+ derived_tag := tag_buf[:hash.DIGEST_SIZES[algorithm]]
sum(algorithm, derived_tag, msg, key)
return crypto.compare_constant_time(derived_tag, tag) == 1
@@ -113,11 +111,12 @@ _O_PAD :: 0x5c
@(private)
_init_hashes :: proc(ctx: ^Context, algorithm: hash.Algorithm, key: []byte) {
- runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
+ K0_buf: [hash.MAX_BLOCK_SIZE]byte
+ kPad_buf: [hash.MAX_BLOCK_SIZE]byte
kLen := len(key)
B := hash.BLOCK_SIZES[algorithm]
- K0 := make([]byte, B, context.temp_allocator)
+ K0 := K0_buf[:B]
defer mem.zero_explicit(raw_data(K0), B)
switch {
@@ -148,7 +147,7 @@ _init_hashes :: proc(ctx: ^Context, algorithm: hash.Algorithm, key: []byte) {
hash.init(&ctx._o_hash, algorithm)
hash.init(&ctx._i_hash, algorithm)
- kPad := make([]byte, B, context.temp_allocator)
+ kPad := kPad_buf[:B]
defer mem.zero_explicit(raw_data(kPad), B)
for v, i in K0 {
diff --git a/tests/core/crypto/test_core_crypto_hash.odin b/tests/core/crypto/test_core_crypto_hash.odin
index 1646c1baf..7dc559681 100644
--- a/tests/core/crypto/test_core_crypto_hash.odin
+++ b/tests/core/crypto/test_core_crypto_hash.odin
@@ -514,6 +514,31 @@ test_hash :: proc(t: ^testing.T) {
algo_name := hash.ALGORITHM_NAMES[algo]
+ // Ensure that the MAX_(DIGEST_SIZE, BLOCK_SIZE) constants are
+ // still correct.
+ digest_sz := hash.DIGEST_SIZES[algo]
+ block_sz := hash.BLOCK_SIZES[algo]
+ expect(
+ t,
+ digest_sz <= hash.MAX_DIGEST_SIZE,
+ fmt.tprintf(
+ "%s: Digest size %d exceeds max %d",
+ algo_name,
+ digest_sz,
+ hash.MAX_DIGEST_SIZE,
+ ),
+ )
+ expect(
+ t,
+ block_sz <= hash.MAX_BLOCK_SIZE,
+ fmt.tprintf(
+ "%s: Block size %d exceeds max %d",
+ algo_name,
+ block_sz,
+ hash.MAX_BLOCK_SIZE,
+ ),
+ )
+
// Exercise most of the happy-path for the high level interface.
rd: bytes.Reader
bytes.reader_init(&rd, transmute([]byte)(data_1_000_000_a))