Răsfoiți Sursa

core/crypto: Add more assertions to the low level API

Assertions here are "fine" and it matches what the code that has the
checks in init/update/final already does.
Yawning Angel 1 an în urmă
părinte
comite
70ba4b5321

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

@@ -29,6 +29,8 @@ Blake2s_Context :: struct {
 	size:         byte,
 	is_last_node: bool,
 	cfg:          Blake2_Config,
+
+	is_initialized: bool,
 }
 
 Blake2b_Context :: struct {
@@ -43,6 +45,8 @@ Blake2b_Context :: struct {
 	size:         byte,
 	is_last_node: bool,
 	cfg:          Blake2_Config,
+
+	is_initialized: bool,
 }
 
 Blake2_Config :: struct {
@@ -152,9 +156,13 @@ init :: proc(ctx: ^$T) {
 	}
 
 	ctx.nx = 0
+
+	ctx.is_initialized = true
 }
 
-update :: proc "contextless" (ctx: ^$T, p: []byte) {
+update :: proc(ctx: ^$T, p: []byte) {
+	assert(ctx.is_initialized)
+
 	p := p
 	when T == Blake2s_Context {
 		block_size :: BLAKE2S_BLOCK_SIZE
@@ -181,6 +189,8 @@ update :: proc "contextless" (ctx: ^$T, p: []byte) {
 }
 
 final :: proc(ctx: ^$T, hash: []byte) {
+	assert(ctx.is_initialized)
+
 	when T == Blake2s_Context {
 		if len(hash) < BLAKE2S_SIZE {
 			panic("crypto/blake2s: invalid destination digest size")
@@ -193,6 +203,8 @@ final :: proc(ctx: ^$T, hash: []byte) {
 		}
 		blake2b_final(ctx, hash)
 	}
+
+	ctx.is_initialized = false
 }
 
 @(private)

+ 25 - 4
core/crypto/_sha3/sha3.odin

@@ -24,6 +24,9 @@ Sha3_Context :: struct {
 	rsiz:      int,
 	mdlen:     int,
 	is_keccak: bool,
+
+	is_initialized: bool,
+	is_finalized:   bool, // For SHAKE (unlimited squeeze is allowed)
 }
 
 keccakf :: proc "contextless" (st: ^[25]u64) {
@@ -100,15 +103,21 @@ keccakf :: proc "contextless" (st: ^[25]u64) {
 	}
 }
 
-init :: proc "contextless" (c: ^Sha3_Context) {
+init :: proc(c: ^Sha3_Context) {
 	for i := 0; i < 25; i += 1 {
 		c.st.q[i] = 0
 	}
 	c.rsiz = 200 - 2 * c.mdlen
 	c.pt = 0
+
+	c.is_initialized = true
+	c.is_finalized = false
 }
 
-update :: proc "contextless" (c: ^Sha3_Context, data: []byte) {
+update :: proc(c: ^Sha3_Context, data: []byte) {
+	assert(c.is_initialized)
+	assert(!c.is_finalized)
+
 	j := c.pt
 	for i := 0; i < len(data); i += 1 {
 		c.st.b[j] ~= data[i]
@@ -122,6 +131,8 @@ update :: proc "contextless" (c: ^Sha3_Context, data: []byte) {
 }
 
 final :: proc(c: ^Sha3_Context, hash: []byte) {
+	assert(c.is_initialized)
+
 	if len(hash) < c.mdlen {
 		if c.is_keccak {
 			panic("crypto/keccac: invalid destination digest size")
@@ -139,16 +150,26 @@ final :: proc(c: ^Sha3_Context, hash: []byte) {
 	for i := 0; i < c.mdlen; i += 1 {
 		hash[i] = c.st.b[i]
 	}
+
+	c.is_initialized = false // No more absorb, no more squeeze.
 }
 
-shake_xof :: proc "contextless" (c: ^Sha3_Context) {
+shake_xof :: proc(c: ^Sha3_Context) {
+	assert(c.is_initialized)
+	assert(!c.is_finalized)
+
 	c.st.b[c.pt] ~= 0x1F
 	c.st.b[c.rsiz - 1] ~= 0x80
 	keccakf(&c.st.q)
 	c.pt = 0
+
+	c.is_finalized = true // No more absorb, unlimited squeeze.
 }
 
-shake_out :: proc "contextless" (c: ^Sha3_Context, hash: []byte) {
+shake_out :: proc(c: ^Sha3_Context, hash: []byte) {
+	assert(c.is_initialized)
+	assert(c.is_finalized)
+
 	j := c.pt
 	for i := 0; i < len(hash); i += 1 {
 		if j >= c.rsiz {

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

@@ -117,7 +117,7 @@ init :: proc(ctx: ^_blake2.Blake2b_Context) {
 	_blake2.init(ctx)
 }
 
-update :: proc "contextless" (ctx: ^_blake2.Blake2b_Context, data: []byte) {
+update :: proc(ctx: ^_blake2.Blake2b_Context, data: []byte) {
 	_blake2.update(ctx, data)
 }
 

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

@@ -117,7 +117,7 @@ init :: proc(ctx: ^_blake2.Blake2s_Context) {
 	_blake2.init(ctx)
 }
 
-update :: proc "contextless" (ctx: ^_blake2.Blake2s_Context, data: []byte) {
+update :: proc(ctx: ^_blake2.Blake2s_Context, data: []byte) {
 	_blake2.update(ctx, data)
 }
 

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

@@ -361,7 +361,7 @@ init :: proc(ctx: ^_sha3.Sha3_Context) {
 	_sha3.init(ctx)
 }
 
-update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) {
+update :: proc(ctx: ^_sha3.Sha3_Context, data: []byte) {
 	_sha3.update(ctx, data)
 }
 

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

@@ -109,9 +109,13 @@ init :: proc(ctx: ^Md5_Context) {
 
 	ctx.bitlen = 0
 	ctx.datalen = 0
+
+	ctx.is_initialized = true
 }
 
 update :: proc(ctx: ^Md5_Context, data: []byte) {
+	assert(ctx.is_initialized)
+
 	for i := 0; i < len(data); i += 1 {
 		ctx.data[ctx.datalen] = data[i]
 		ctx.datalen += 1
@@ -124,6 +128,8 @@ update :: proc(ctx: ^Md5_Context, data: []byte) {
 }
 
 final :: proc(ctx: ^Md5_Context, hash: []byte) {
+	assert(ctx.is_initialized)
+
 	if len(hash) < DIGEST_SIZE {
 		panic("crypto/md5: invalid destination digest size")
 	}
@@ -155,6 +161,8 @@ final :: proc(ctx: ^Md5_Context, hash: []byte) {
 	for i = 0; i < DIGEST_SIZE / 4; i += 1 {
 		endian.unchecked_put_u32le(hash[i * 4:], ctx.state[i])
 	}
+
+	ctx.is_initialized = false
 }
 
 /*
@@ -168,6 +176,8 @@ Md5_Context :: struct {
 	state:   [4]u32,
 	bitlen:  u64,
 	datalen: u32,
+
+	is_initialized: bool,
 }
 
 /*

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

@@ -114,9 +114,13 @@ init :: proc(ctx: ^Sha1_Context) {
 
 	ctx.datalen = 0
 	ctx.bitlen = 0
+
+	ctx.is_initialized = true
 }
 
 update :: proc(ctx: ^Sha1_Context, data: []byte) {
+	assert(ctx.is_initialized)
+
 	for i := 0; i < len(data); i += 1 {
 		ctx.data[ctx.datalen] = data[i]
 		ctx.datalen += 1
@@ -129,6 +133,8 @@ update :: proc(ctx: ^Sha1_Context, data: []byte) {
 }
 
 final :: proc(ctx: ^Sha1_Context, hash: []byte) {
+	assert(ctx.is_initialized)
+
 	if len(hash) < DIGEST_SIZE {
 		panic("crypto/sha1: invalid destination digest size")
 	}
@@ -160,6 +166,8 @@ final :: proc(ctx: ^Sha1_Context, hash: []byte) {
 	for i = 0; i < DIGEST_SIZE / 4; i += 1 {
 		endian.unchecked_put_u32be(hash[i * 4:], ctx.state[i])
 	}
+
+	ctx.is_initialized = false
 }
 
 /*
@@ -174,6 +182,8 @@ Sha1_Context :: struct {
 	bitlen:  u64,
 	state:   [5]u32,
 	k:       [4]u32,
+
+	is_initialized: bool,
 }
 
 @(private)

+ 12 - 0
core/crypto/sha2/sha2.odin

@@ -387,9 +387,13 @@ init :: proc(ctx: ^$T) {
 
 	ctx.tot_len = 0
 	ctx.length = 0
+
+	ctx.is_initialized = true
 }
 
 update :: proc(ctx: ^$T, data: []byte) {
+	assert(ctx.is_initialized)
+
 	length := uint(len(data))
 	block_nb: uint
 	new_len, rem_len, tmp_len: uint
@@ -427,6 +431,8 @@ update :: proc(ctx: ^$T, data: []byte) {
 }
 
 final :: proc(ctx: ^$T, hash: []byte) {
+	assert(ctx.is_initialized)
+
 	block_nb, pm_len: uint
 	len_b: u64
 
@@ -457,6 +463,8 @@ final :: proc(ctx: ^$T, hash: []byte) {
 			endian.unchecked_put_u64be(hash[i * 8:], ctx.h[i])
 		}
 	}
+
+	ctx.is_initialized = false
 }
 
 /*
@@ -472,6 +480,8 @@ Sha256_Context :: struct {
 	block:   [128]byte,
 	h:       [8]u32,
 	md_bits: int,
+
+	is_initialized: bool,
 }
 
 Sha512_Context :: struct {
@@ -480,6 +490,8 @@ Sha512_Context :: struct {
 	block:   [256]byte,
 	h:       [8]u64,
 	md_bits: int,
+
+	is_initialized: bool,
 }
 
 @(private)

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

@@ -347,7 +347,7 @@ init :: proc(ctx: ^_sha3.Sha3_Context) {
 	_sha3.init(ctx)
 }
 
-update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) {
+update :: proc(ctx: ^_sha3.Sha3_Context, data: []byte) {
 	_sha3.update(ctx, data)
 }
 

+ 2 - 2
core/crypto/shake/shake.odin

@@ -198,11 +198,11 @@ init :: proc(ctx: ^_sha3.Sha3_Context) {
 	_sha3.init(ctx)
 }
 
-update :: proc "contextless" (ctx: ^_sha3.Sha3_Context, data: []byte) {
+update :: proc(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.shake_xof(ctx)
 	_sha3.shake_out(ctx, hash[:])
 }

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

@@ -112,9 +112,13 @@ init :: proc(ctx: ^Sm3_Context) {
 
 	ctx.length = 0
 	ctx.bitlength = 0
+
+	ctx.is_initialized = true
 }
 
 update :: proc(ctx: ^Sm3_Context, data: []byte) {
+	assert(ctx.is_initialized)
+
 	data := data
 	ctx.length += u64(len(data))
 
@@ -138,6 +142,8 @@ update :: proc(ctx: ^Sm3_Context, data: []byte) {
 }
 
 final :: proc(ctx: ^Sm3_Context, hash: []byte) {
+	assert(ctx.is_initialized)
+
 	if len(hash) < DIGEST_SIZE {
 		panic("crypto/sm3: invalid destination digest size")
 	}
@@ -160,6 +166,8 @@ final :: proc(ctx: ^Sm3_Context, hash: []byte) {
 	for i := 0; i < DIGEST_SIZE / 4; i += 1 {
 		endian.unchecked_put_u32be(hash[i * 4:], ctx.state[i])
 	}
+
+	ctx.is_initialized = false
 }
 
 /*
@@ -173,6 +181,8 @@ Sm3_Context :: struct {
 	x:         [BLOCK_SIZE]byte,
 	bitlength: u64,
 	length:    u64,
+
+	is_initialized: bool,
 }
 
 @(private)