فهرست منبع

core/crypto: Change hash asserts to panics

Assertions can be disabled, but at the point where cryptographic
anything is involved, a single branch has an infinitesimally small
performance impact.

The correct thing to do is to punch the caller in the face if they do
something that is blatantly incorrect, especially in a security critical
setting.
Yawning Angel 1 سال پیش
والد
کامیت
e86bb3a795

+ 7 - 1
core/crypto/_blake2/blake2.odin

@@ -180,11 +180,17 @@ update :: proc "contextless" (ctx: ^$T, p: []byte) {
 	ctx.nx += copy(ctx.x[ctx.nx:], p)
 }
 
-final :: proc "contextless" (ctx: ^$T, hash: []byte) {
+final :: proc(ctx: ^$T, hash: []byte) {
 	when T == Blake2s_Context {
+		if len(hash) < BLAKE2S_SIZE {
+			panic("crypto/blake2s: invalid destination digest size")
+		}
 		blake2s_final(ctx, hash)
 	}
 	when T == Blake2b_Context {
+		if len(hash) < BLAKE2B_SIZE {
+			panic("crypto/blake2b: invalid destination digest size")
+		}
 		blake2b_final(ctx, hash)
 	}
 }

+ 7 - 1
core/crypto/_sha3/sha3.odin

@@ -121,7 +121,13 @@ update :: proc "contextless" (c: ^Sha3_Context, data: []byte) {
 	c.pt = j
 }
 
-final :: proc "contextless" (c: ^Sha3_Context, hash: []byte) {
+final :: proc(c: ^Sha3_Context, hash: []byte) {
+	if len(hash) < c.mdlen {
+		if c.is_keccak {
+			panic("crypto/keccac: invalid destination digest size")
+		}
+		panic("crypto/sha3: invalid destination digest size")
+	}
 	if c.is_keccak {
 		c.st.b[c.pt] ~= 0x01
 	} else {

+ 1 - 2
core/crypto/blake2b/blake2b.odin

@@ -53,7 +53,6 @@ hash_string_to_buffer :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer :: proc(data, hash: []byte) {
-	assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
 	ctx: _blake2.Blake2b_Context
 	cfg: _blake2.Blake2_Config
 	cfg.size = _blake2.BLAKE2B_SIZE
@@ -122,6 +121,6 @@ update :: proc "contextless" (ctx: ^_blake2.Blake2b_Context, data: []byte) {
 	_blake2.update(ctx, data)
 }
 
-final :: proc "contextless" (ctx: ^_blake2.Blake2b_Context, hash: []byte) {
+final :: proc(ctx: ^_blake2.Blake2b_Context, hash: []byte) {
 	_blake2.final(ctx, hash)
 }

+ 1 - 2
core/crypto/blake2s/blake2s.odin

@@ -54,7 +54,6 @@ hash_string_to_buffer :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer :: proc(data, hash: []byte) {
-	assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
 	ctx: _blake2.Blake2s_Context
 	cfg: _blake2.Blake2_Config
 	cfg.size = _blake2.BLAKE2S_SIZE
@@ -122,6 +121,6 @@ update :: proc "contextless" (ctx: ^_blake2.Blake2s_Context, data: []byte) {
 	_blake2.update(ctx, data)
 }
 
-final :: proc "contextless" (ctx: ^_blake2.Blake2s_Context, hash: []byte) {
+final :: proc(ctx: ^_blake2.Blake2s_Context, hash: []byte) {
 	_blake2.final(ctx, hash)
 }

+ 1 - 17
core/crypto/keccak/keccak.odin

@@ -56,10 +56,6 @@ hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_224 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_224,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_224
 	ctx.is_keccak = true
@@ -141,10 +137,6 @@ hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_256 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_256,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_256
 	ctx.is_keccak = true
@@ -226,10 +218,6 @@ hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_384 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_384,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_384
 	ctx.is_keccak = true
@@ -311,10 +299,6 @@ hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_512 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_512,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_512
 	ctx.is_keccak = true
@@ -381,6 +365,6 @@ update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) {
 	_sha3.update(ctx, data)
 }
 
-final :: proc "contextless" (ctx: ^_sha3.Sha3_Context, hash: []byte) {
+final :: proc(ctx: ^_sha3.Sha3_Context, hash: []byte) {
 	_sha3.final(ctx, hash)
 }

+ 4 - 1
core/crypto/md5/md5.odin

@@ -50,7 +50,6 @@ hash_string_to_buffer :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer :: proc(data, hash: []byte) {
-	assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
 	ctx: Md5_Context
 	init(&ctx)
 	update(&ctx, data)
@@ -125,6 +124,10 @@ update :: proc(ctx: ^Md5_Context, data: []byte) {
 }
 
 final :: proc(ctx: ^Md5_Context, hash: []byte) {
+	if len(hash) < DIGEST_SIZE {
+		panic("crypto/md5: invalid destination digest size")
+	}
+
 	i := ctx.datalen
 
 	if ctx.datalen < 56 {

+ 4 - 1
core/crypto/sha1/sha1.odin

@@ -50,7 +50,6 @@ hash_string_to_buffer :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer :: proc(data, hash: []byte) {
-	assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
 	ctx: Sha1_Context
 	init(&ctx)
 	update(&ctx, data)
@@ -130,6 +129,10 @@ update :: proc(ctx: ^Sha1_Context, data: []byte) {
 }
 
 final :: proc(ctx: ^Sha1_Context, hash: []byte) {
+	if len(hash) < DIGEST_SIZE {
+		panic("crypto/sha1: invalid destination digest size")
+	}
+
 	i := ctx.datalen
 
 	if ctx.datalen < 56 {

+ 4 - 16
core/crypto/sha2/sha2.odin

@@ -55,10 +55,6 @@ hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_224 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_224,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: Sha256_Context
 	ctx.md_bits = 224
 	init(&ctx)
@@ -137,10 +133,6 @@ hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_256 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_256,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: Sha256_Context
 	ctx.md_bits = 256
 	init(&ctx)
@@ -219,10 +211,6 @@ hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_384 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_384,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: Sha512_Context
 	ctx.md_bits = 384
 	init(&ctx)
@@ -301,10 +289,6 @@ hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_512 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_512,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: Sha512_Context
 	ctx.md_bits = 512
 	init(&ctx)
@@ -445,6 +429,10 @@ update :: proc(ctx: ^$T, data: []byte) {
 final :: proc(ctx: ^$T, hash: []byte) {
 	block_nb, pm_len, len_b: u32
 
+	if len(hash) * 8 < ctx.md_bits {
+		panic("crypto/sha2: invalid destination digest size")
+	}
+
 	when T == Sha256_Context {CURR_BLOCK_SIZE :: SHA256_BLOCK_SIZE} else when T == Sha512_Context {CURR_BLOCK_SIZE :: SHA512_BLOCK_SIZE}
 
 	when T == Sha256_Context {block_nb = 1 + ((CURR_BLOCK_SIZE - 9) < (ctx.length % CURR_BLOCK_SIZE) ? 1 : 0)} else when T == Sha512_Context {block_nb = 1 + ((CURR_BLOCK_SIZE - 17) < (ctx.length % CURR_BLOCK_SIZE) ? 1 : 0)}

+ 1 - 17
core/crypto/sha3/sha3.odin

@@ -54,10 +54,6 @@ hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_224 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_224,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_224
 	_sha3.init(&ctx)
@@ -136,10 +132,6 @@ hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_256 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_256,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_256
 	_sha3.init(&ctx)
@@ -218,10 +210,6 @@ hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_384 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_384,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_384
 	_sha3.init(&ctx)
@@ -300,10 +288,6 @@ hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_512 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_512,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_512
 	_sha3.init(&ctx)
@@ -367,6 +351,6 @@ update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) {
 	_sha3.update(ctx, data)
 }
 
-final :: proc "contextless" (ctx: ^_sha3.Sha3_Context, hash: []byte) {
+final :: proc(ctx: ^_sha3.Sha3_Context, hash: []byte) {
 	_sha3.final(ctx, hash)
 }

+ 0 - 8
core/crypto/shake/shake.odin

@@ -53,10 +53,6 @@ hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_128 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_128,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_128
 	_sha3.init(&ctx)
@@ -138,10 +134,6 @@ hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer_256 :: proc(data, hash: []byte) {
-	assert(
-		len(hash) >= DIGEST_SIZE_256,
-		"Size of destination buffer is smaller than the digest size",
-	)
 	ctx: _sha3.Sha3_Context
 	ctx.mdlen = DIGEST_SIZE_256
 	_sha3.init(&ctx)

+ 10 - 18
core/crypto/siphash/siphash.odin

@@ -49,10 +49,6 @@ sum_string_to_buffer_1_3 :: proc(msg, key: string, dst: []byte) {
 // sum_bytes_to_buffer_1_3 will hash the given message with the key and write
 // the computed hash into the provided destination buffer
 sum_bytes_to_buffer_1_3 :: proc(msg, key, dst: []byte) {
-	assert(
-		len(dst) >= DIGEST_SIZE,
-		"crypto/siphash: Destination buffer needs to be at least of size 8",
-	)
 	hash := sum_bytes_1_3(msg, key)
 	_collect_output(dst[:], hash)
 }
@@ -109,10 +105,6 @@ sum_string_to_buffer_2_4 :: proc(msg, key: string, dst: []byte) {
 // sum_bytes_to_buffer_2_4 will hash the given message with the key and write
 // the computed hash into the provided destination buffer
 sum_bytes_to_buffer_2_4 :: proc(msg, key, dst: []byte) {
-	assert(
-		len(dst) >= DIGEST_SIZE,
-		"crypto/siphash: Destination buffer needs to be at least of size 8",
-	)
 	hash := sum_bytes_2_4(msg, key)
 	_collect_output(dst[:], hash)
 }
@@ -187,10 +179,6 @@ sum_string_to_buffer_4_8 :: proc(msg, key: string, dst: []byte) {
 // sum_bytes_to_buffer_4_8 will hash the given message with the key and write
 // the computed hash into the provided destination buffer
 sum_bytes_to_buffer_4_8 :: proc(msg, key, dst: []byte) {
-	assert(
-		len(dst) >= DIGEST_SIZE,
-		"crypto/siphash: Destination buffer needs to be at least of size 8",
-	)
 	hash := sum_bytes_4_8(msg, key)
 	_collect_output(dst[:], hash)
 }
@@ -226,17 +214,18 @@ verify_4_8 :: proc {
 */
 
 init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) {
-	assert(len(key) == KEY_SIZE, "crypto/siphash: Invalid key size, want 16")
+	if len(key) != KEY_SIZE {
+		panic("crypto/siphash; invalid key size")
+	}
 	ctx.c_rounds = c_rounds
 	ctx.d_rounds = d_rounds
 	is_valid_setting :=
 		(ctx.c_rounds == 1 && ctx.d_rounds == 3) ||
 		(ctx.c_rounds == 2 && ctx.d_rounds == 4) ||
 		(ctx.c_rounds == 4 && ctx.d_rounds == 8)
-	assert(
-		is_valid_setting,
-		"crypto/siphash: Incorrect rounds set up. Valid pairs are (1,3), (2,4) and (4,8)",
-	)
+	if !is_valid_setting {
+		panic("crypto/siphash: incorrect rounds set up")
+	}
 	ctx.k0 = endian.unchecked_get_u64le(key[:8])
 	ctx.k1 = endian.unchecked_get_u64le(key[8:])
 	ctx.v0 = 0x736f6d6570736575 ~ ctx.k0
@@ -341,7 +330,10 @@ _get_byte :: #force_inline proc "contextless" (byte_num: byte, into: u64) -> byt
 }
 
 @(private)
-_collect_output :: #force_inline proc "contextless" (dst: []byte, hash: u64) {
+_collect_output :: #force_inline proc(dst: []byte, hash: u64) {
+	if len(dst) < DIGEST_SIZE {
+		panic("crypto/siphash: invalid tag size")
+	}
 	dst[0] = _get_byte(7, hash)
 	dst[1] = _get_byte(6, hash)
 	dst[2] = _get_byte(5, hash)

+ 4 - 1
core/crypto/sm3/sm3.odin

@@ -49,7 +49,6 @@ hash_string_to_buffer :: proc(data: string, hash: []byte) {
 // computed hash into the second parameter.
 // It requires that the destination buffer is at least as big as the digest size
 hash_bytes_to_buffer :: proc(data, hash: []byte) {
-	assert(len(hash) >= DIGEST_SIZE, "Size of destination buffer is smaller than the digest size")
 	ctx: Sm3_Context
 	init(&ctx)
 	update(&ctx, data)
@@ -139,6 +138,10 @@ update :: proc(ctx: ^Sm3_Context, data: []byte) {
 }
 
 final :: proc(ctx: ^Sm3_Context, hash: []byte) {
+	if len(hash) < DIGEST_SIZE {
+		panic("crypto/sm3: invalid destination digest size")
+	}
+
 	length := ctx.length
 
 	pad: [BLOCK_SIZE]byte