core/crypto: Switch to using ensure

This commit is contained in:
Yawning Angel
2025-03-23 19:14:33 +09:00
parent dc94452fb9
commit 2f301e46dc
36 changed files with 188 additions and 363 deletions
+1 -3
View File
@@ -23,9 +23,7 @@
package aes_ct64 package aes_ct64
add_round_key :: proc "contextless" (q: ^[8]u64, sk: []u64) #no_bounds_check { add_round_key :: proc "contextless" (q: ^[8]u64, sk: []u64) #no_bounds_check {
if len(sk) < 8 { ensure_contextless(len(sk) >= 8, "aes/ct64: invalid round key size")
panic_contextless("aes/ct64: invalid round key size")
}
q[0] ~= sk[0] q[0] ~= sk[0]
q[1] ~= sk[1] q[1] ~= sk[1]
+2 -2
View File
@@ -41,7 +41,7 @@ sub_word :: proc "contextless" (x: u32) -> u32 {
} }
@(private, require_results) @(private, require_results)
keysched :: proc(comp_skey: []u64, key: []byte) -> int { keysched :: proc "contextless" (comp_skey: []u64, key: []byte) -> int {
num_rounds, key_len := 0, len(key) num_rounds, key_len := 0, len(key)
switch key_len { switch key_len {
case _aes.KEY_SIZE_128: case _aes.KEY_SIZE_128:
@@ -51,7 +51,7 @@ keysched :: proc(comp_skey: []u64, key: []byte) -> int {
case _aes.KEY_SIZE_256: case _aes.KEY_SIZE_256:
num_rounds = _aes.ROUNDS_256 num_rounds = _aes.ROUNDS_256
case: case:
panic("crypto/aes: invalid AES key size") panic_contextless("crypto/aes: invalid AES key size")
} }
skey: [60]u32 = --- skey: [60]u32 = ---
+2 -3
View File
@@ -63,9 +63,8 @@ rev64 :: proc "contextless" (x: u64) -> u64 {
// Note: `dst` is both an input and an output, to support easy implementation // Note: `dst` is both an input and an output, to support easy implementation
// of GCM. // of GCM.
ghash :: proc "contextless" (dst, key, data: []byte) { ghash :: proc "contextless" (dst, key, data: []byte) {
if len(dst) != _aes.GHASH_BLOCK_SIZE || len(key) != _aes.GHASH_BLOCK_SIZE { ensure_contextless(len(dst) == _aes.GHASH_BLOCK_SIZE)
panic_contextless("aes/ghash: invalid dst or key size") ensure_contextless(len(key) == _aes.GHASH_BLOCK_SIZE)
}
buf := data buf := data
l := len(buf) l := len(buf)
+6 -18
View File
@@ -31,41 +31,31 @@ and_interleaved :: #force_inline proc "contextless" (a0, a1, b0, b1: u64) -> (u6
} }
load_blockx1 :: proc "contextless" (q: ^[8]u64, src: []byte) { load_blockx1 :: proc "contextless" (q: ^[8]u64, src: []byte) {
if len(src) != _aes.BLOCK_SIZE { ensure_contextless(len(src) == _aes.BLOCK_SIZE, "aes/ct64: invalid block size")
panic_contextless("aes/ct64: invalid block size")
}
q[0], q[4] = #force_inline load_interleaved(src) q[0], q[4] = #force_inline load_interleaved(src)
orthogonalize(q) orthogonalize(q)
} }
store_blockx1 :: proc "contextless" (dst: []byte, q: ^[8]u64) { store_blockx1 :: proc "contextless" (dst: []byte, q: ^[8]u64) {
if len(dst) != _aes.BLOCK_SIZE { ensure_contextless(len(dst) == _aes.BLOCK_SIZE, "aes/ct64: invalid block size")
panic_contextless("aes/ct64: invalid block size")
}
orthogonalize(q) orthogonalize(q)
#force_inline store_interleaved(dst, q[0], q[4]) #force_inline store_interleaved(dst, q[0], q[4])
} }
load_blocks :: proc "contextless" (q: ^[8]u64, src: [][]byte) { load_blocks :: proc "contextless" (q: ^[8]u64, src: [][]byte) {
if n := len(src); n > STRIDE || n == 0 { ensure_contextless(len(src) == 0 || len(src) <= STRIDE, "aes/ct64: invalid block(s) size")
panic_contextless("aes/ct64: invalid block(s) size")
}
for s, i in src { for s, i in src {
if len(s) != _aes.BLOCK_SIZE { ensure_contextless(len(s) == _aes.BLOCK_SIZE, "aes/ct64: invalid block size")
panic_contextless("aes/ct64: invalid block size")
}
q[i], q[i + 4] = #force_inline load_interleaved(s) q[i], q[i + 4] = #force_inline load_interleaved(s)
} }
orthogonalize(q) orthogonalize(q)
} }
store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) { store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) {
if n := len(dst); n > STRIDE || n == 0 { ensure_contextless(len(dst) == 0 || len(dst) <= STRIDE, "aes/ct64: invalid block(s) size")
panic_contextless("aes/ct64: invalid block(s) size")
}
orthogonalize(q) orthogonalize(q)
for d, i in dst { for d, i in dst {
@@ -73,9 +63,7 @@ store_blocks :: proc "contextless" (dst: [][]byte, q: ^[8]u64) {
if d == nil { if d == nil {
break break
} }
if len(d) != _aes.BLOCK_SIZE { ensure_contextless(len(d) == _aes.BLOCK_SIZE, "aes/ct64: invalid block size")
panic_contextless("aes/ct64: invalid block size")
}
#force_inline store_interleaved(d, q[i], q[i + 4]) #force_inline store_interleaved(d, q[i], q[i + 4])
} }
} }
+11 -17
View File
@@ -18,6 +18,8 @@ BLAKE2S_SIZE :: 32
BLAKE2B_BLOCK_SIZE :: 128 BLAKE2B_BLOCK_SIZE :: 128
BLAKE2B_SIZE :: 64 BLAKE2B_SIZE :: 64
MAX_SIZE :: 255
Blake2s_Context :: struct { Blake2s_Context :: struct {
h: [8]u32, h: [8]u32,
t: [2]u32, t: [2]u32,
@@ -82,16 +84,13 @@ BLAKE2B_IV := [8]u64 {
0x1f83d9abfb41bd6b, 0x5be0cd19137e2179, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
} }
init :: proc(ctx: ^$T, cfg: ^Blake2_Config) { init :: proc "contextless" (ctx: ^$T, cfg: ^Blake2_Config) {
when T == Blake2s_Context { when T == Blake2s_Context {
max_size :: BLAKE2S_SIZE max_size :: BLAKE2S_SIZE
} else when T == Blake2b_Context { } else when T == Blake2b_Context {
max_size :: BLAKE2B_SIZE max_size :: BLAKE2B_SIZE
} }
ensure_contextless(cfg.size <= max_size, "blake2: requested output size exceeeds algorithm max")
if cfg.size > max_size {
panic("blake2: requested output size exceeeds algorithm max")
}
// To save having to allocate a scratch buffer, use the internal // To save having to allocate a scratch buffer, use the internal
// data buffer (`ctx.x`), as it is exactly the correct size. // data buffer (`ctx.x`), as it is exactly the correct size.
@@ -167,8 +166,8 @@ init :: proc(ctx: ^$T, cfg: ^Blake2_Config) {
ctx.is_initialized = true ctx.is_initialized = true
} }
update :: proc(ctx: ^$T, p: []byte) { update :: proc "contextless" (ctx: ^$T, p: []byte) {
assert(ctx.is_initialized) ensure_contextless(ctx.is_initialized)
p := p p := p
when T == Blake2s_Context { when T == Blake2s_Context {
@@ -195,8 +194,8 @@ update :: proc(ctx: ^$T, p: []byte) {
ctx.nx += copy(ctx.x[ctx.nx:], p) ctx.nx += copy(ctx.x[ctx.nx:], p)
} }
final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) { final :: proc "contextless" (ctx: ^$T, hash: []byte, finalize_clone: bool = false) {
assert(ctx.is_initialized) ensure_contextless(ctx.is_initialized)
ctx := ctx ctx := ctx
if finalize_clone { if finalize_clone {
@@ -206,24 +205,19 @@ final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) {
} }
defer(reset(ctx)) defer(reset(ctx))
ensure_contextless(len(hash) >= int(ctx.size), "crypto/blake2: invalid destination digest size")
when T == Blake2s_Context { when T == Blake2s_Context {
if len(hash) < int(ctx.size) {
panic("crypto/blake2s: invalid destination digest size")
}
blake2s_final(ctx, hash) blake2s_final(ctx, hash)
} else when T == Blake2b_Context { } else when T == Blake2b_Context {
if len(hash) < int(ctx.size) {
panic("crypto/blake2b: invalid destination digest size")
}
blake2b_final(ctx, hash) blake2b_final(ctx, hash)
} }
} }
clone :: proc(ctx, other: ^$T) { clone :: proc "contextless" (ctx, other: ^$T) {
ctx^ = other^ ctx^ = other^
} }
reset :: proc(ctx: ^$T) { reset :: proc "contextless" (ctx: ^$T) {
if !ctx.is_initialized { if !ctx.is_initialized {
return return
} }
+11 -14
View File
@@ -45,9 +45,8 @@ Context :: struct {
// derivation is expected to be handled by the caller, so that the // derivation is expected to be handled by the caller, so that the
// HChaCha call can be suitably accelerated. // HChaCha call can be suitably accelerated.
init :: proc "contextless" (ctx: ^Context, key, iv: []byte, is_xchacha: bool) { init :: proc "contextless" (ctx: ^Context, key, iv: []byte, is_xchacha: bool) {
if len(key) != KEY_SIZE || len(iv) != IV_SIZE { ensure_contextless(len(key) == KEY_SIZE, "chacha20: invalid key size")
panic_contextless("chacha20: invalid key or IV size") ensure_contextless(len(iv) == IV_SIZE, "chacha20: invalid key size")
}
k, n := key, iv k, n := key, iv
@@ -75,12 +74,10 @@ init :: proc "contextless" (ctx: ^Context, key, iv: []byte, is_xchacha: bool) {
// seek seeks the (X)ChaCha20 stream counter to the specified block. // seek seeks the (X)ChaCha20 stream counter to the specified block.
seek :: proc(ctx: ^Context, block_nr: u64) { seek :: proc(ctx: ^Context, block_nr: u64) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
if ctx._is_ietf_flavor { if ctx._is_ietf_flavor {
if block_nr > MAX_CTR_IETF { ensure(block_nr <= MAX_CTR_IETF, "crypto/chacha20: attempted to seek past maximum counter")
panic("crypto/chacha20: attempted to seek past maximum counter")
}
} else { } else {
ctx._s[13] = u32(block_nr >> 32) ctx._s[13] = u32(block_nr >> 32)
} }
@@ -101,7 +98,7 @@ check_counter_limit :: proc(ctx: ^Context, nr_blocks: int) {
// Enforce the maximum consumed keystream per IV. // Enforce the maximum consumed keystream per IV.
// //
// While all modern "standard" definitions of ChaCha20 use // While all modern "standard" definitions of ChaCha20 use
// the IETF 32-bit counter, for XChaCha20 most common // the IETF 32-bit counter, for XChaCha20 historical
// implementations allow for a 64-bit counter. // implementations allow for a 64-bit counter.
// //
// Honestly, the answer here is "use a MRAE primitive", but // Honestly, the answer here is "use a MRAE primitive", but
@@ -109,14 +106,14 @@ check_counter_limit :: proc(ctx: ^Context, nr_blocks: int) {
ERR_CTR_EXHAUSTED :: "crypto/chacha20: maximum (X)ChaCha20 keystream per IV reached" ERR_CTR_EXHAUSTED :: "crypto/chacha20: maximum (X)ChaCha20 keystream per IV reached"
ctr_ok: bool
if ctx._is_ietf_flavor { if ctx._is_ietf_flavor {
if u64(ctx._s[12]) + u64(nr_blocks) > MAX_CTR_IETF { ctr_ok = u64(ctx._s[12]) + u64(nr_blocks) <= MAX_CTR_IETF
panic(ERR_CTR_EXHAUSTED)
}
} else { } else {
ctr := (u64(ctx._s[13]) << 32) | u64(ctx._s[12]) ctr := (u64(ctx._s[13]) << 32) | u64(ctx._s[12])
if _, carry := bits.add_u64(ctr, u64(nr_blocks), 0); carry != 0 { _, carry := bits.add_u64(ctr, u64(nr_blocks), 0)
panic(ERR_CTR_EXHAUSTED) ctr_ok = carry == 0
}
} }
ensure(ctr_ok, "crypto/chacha20: maximum (X)ChaCha20 keystream per IV reached")
} }
+2 -6
View File
@@ -108,9 +108,7 @@ ge_set :: proc "contextless" (ge, a: ^Group_Element) {
@(require_results) @(require_results)
ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool { ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool {
if len(b) != 32 { ensure_contextless(len(b) == 32, "edwards25519: invalid group element size")
panic_contextless("edwards25519: invalid group element size")
}
b_ := (^[32]byte)(raw_data(b)) b_ := (^[32]byte)(raw_data(b))
// Do the work in a scratch element, so that ge is unchanged on // Do the work in a scratch element, so that ge is unchanged on
@@ -167,9 +165,7 @@ ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool {
} }
ge_bytes :: proc "contextless" (ge: ^Group_Element, dst: []byte) { ge_bytes :: proc "contextless" (ge: ^Group_Element, dst: []byte) {
if len(dst) != 32 { ensure_contextless(len(dst) == 32, "edwards25519: invalid group element size")
panic_contextless("edwards25519: invalid group element size")
}
dst_ := (^[32]byte)(raw_data(dst)) dst_ := (^[32]byte)(raw_data(dst))
// Convert the element to affine (x, y) representation. // Convert the element to affine (x, y) representation.
@@ -24,17 +24,13 @@ sc_set_u64 :: proc "contextless" (sc: ^Scalar, i: u64) {
@(require_results) @(require_results)
sc_set_bytes :: proc "contextless" (sc: ^Scalar, b: []byte) -> bool { sc_set_bytes :: proc "contextless" (sc: ^Scalar, b: []byte) -> bool {
if len(b) != 32 { ensure_contextless(len(b) == 32, "edwards25519: invalid scalar size")
panic_contextless("edwards25519: invalid scalar size")
}
b_ := (^[32]byte)(raw_data(b)) b_ := (^[32]byte)(raw_data(b))
return field.fe_from_bytes(sc, b_) return field.fe_from_bytes(sc, b_)
} }
sc_set_bytes_rfc8032 :: proc "contextless" (sc: ^Scalar, b: []byte) { sc_set_bytes_rfc8032 :: proc "contextless" (sc: ^Scalar, b: []byte) {
if len(b) != 32 { ensure_contextless(len(b) == 32, "edwards25519: invalid scalar size")
panic_contextless("edwards25519: invalid scalar size")
}
b_ := (^[32]byte)(raw_data(b)) b_ := (^[32]byte)(raw_data(b))
field.fe_from_bytes_rfc8032(sc, b_) field.fe_from_bytes_rfc8032(sc, b_)
} }
+1 -3
View File
@@ -28,9 +28,7 @@ fe_from_bytes :: #force_inline proc "contextless" (
// makes implementing the actual MAC block processing considerably // makes implementing the actual MAC block processing considerably
// neater. // neater.
if len(arg1) != 16 { ensure_contextless(len(arg1) == 16, "poly1305: invalid field element size")
panic_contextless("poly1305: invalid field element size")
}
// While it may be unwise to do deserialization here on our // While it may be unwise to do deserialization here on our
// own when fiat-crypto provides equivalent functionality, // own when fiat-crypto provides equivalent functionality,
@@ -94,9 +94,8 @@ fe_from_bytes_wide :: proc "contextless" (
@(private) @(private)
_fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) { _fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) {
// INVARIANT: len(arg1) < 32. // INVARIANT: len(arg1) < 32.
if len(arg1) >= 32 { ensure_contextless(len(arg1) < 32, "edwards25519: oversized short scalar")
panic_contextless("edwards25519: oversized short scalar")
}
tmp: [32]byte tmp: [32]byte
copy(tmp[:], arg1) copy(tmp[:], arg1)
@@ -105,9 +104,7 @@ _fe_from_bytes_short :: proc "contextless" (out1: ^Montgomery_Domain_Field_Eleme
} }
fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) {
if len(out1) != 32 { ensure_contextless(len(out1) == 32, "edwards25519: oversized scalar output buffer")
panic_contextless("edwards25519: oversized scalar output buffer")
}
tmp: Non_Montgomery_Domain_Field_Element tmp: Non_Montgomery_Domain_Field_Element
fe_from_montgomery(&tmp, arg1) fe_from_montgomery(&tmp, arg1)
+15 -18
View File
@@ -122,7 +122,7 @@ keccakf :: proc "contextless" (st: ^[25]u64) {
} }
} }
init :: proc(ctx: ^Context) { init :: proc "contextless" (ctx: ^Context) {
for i := 0; i < 25; i += 1 { for i := 0; i < 25; i += 1 {
ctx.st.q[i] = 0 ctx.st.q[i] = 0
} }
@@ -133,9 +133,9 @@ init :: proc(ctx: ^Context) {
ctx.is_finalized = false ctx.is_finalized = false
} }
update :: proc(ctx: ^Context, data: []byte) { update :: proc "contextless" (ctx: ^Context, data: []byte) {
assert(ctx.is_initialized) ensure_contextless(ctx.is_initialized)
assert(!ctx.is_finalized) ensure_contextless(!ctx.is_finalized)
j := ctx.pt j := ctx.pt
for i := 0; i < len(data); i += 1 { for i := 0; i < len(data); i += 1 {
@@ -149,12 +149,9 @@ update :: proc(ctx: ^Context, data: []byte) {
ctx.pt = j ctx.pt = j
} }
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { final :: proc "contextless" (ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
assert(ctx.is_initialized) ensure_contextless(ctx.is_initialized)
ensure_contextless(len(hash) >= ctx.mdlen, "crypto/sha3: invalid destination digest size")
if len(hash) < ctx.mdlen {
panic("crypto/sha3: invalid destination digest size")
}
ctx := ctx ctx := ctx
if finalize_clone { if finalize_clone {
@@ -173,11 +170,11 @@ final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
} }
} }
clone :: proc(ctx, other: ^Context) { clone :: proc "contextless" (ctx, other: ^Context) {
ctx^ = other^ ctx^ = other^
} }
reset :: proc(ctx: ^Context) { reset :: proc "contextless" (ctx: ^Context) {
if !ctx.is_initialized { if !ctx.is_initialized {
return return
} }
@@ -185,9 +182,9 @@ reset :: proc(ctx: ^Context) {
mem.zero_explicit(ctx, size_of(ctx^)) mem.zero_explicit(ctx, size_of(ctx^))
} }
shake_xof :: proc(ctx: ^Context) { shake_xof :: proc "contextless" (ctx: ^Context) {
assert(ctx.is_initialized) ensure_contextless(ctx.is_initialized)
assert(!ctx.is_finalized) ensure_contextless(!ctx.is_finalized)
ctx.st.b[ctx.pt] ~= ctx.dsbyte ctx.st.b[ctx.pt] ~= ctx.dsbyte
ctx.st.b[ctx.rsiz - 1] ~= 0x80 ctx.st.b[ctx.rsiz - 1] ~= 0x80
@@ -197,9 +194,9 @@ shake_xof :: proc(ctx: ^Context) {
ctx.is_finalized = true // No more absorb, unlimited squeeze. ctx.is_finalized = true // No more absorb, unlimited squeeze.
} }
shake_out :: proc(ctx: ^Context, hash: []byte) { shake_out :: proc "contextless" (ctx: ^Context, hash: []byte) {
assert(ctx.is_initialized) ensure_contextless(ctx.is_initialized)
assert(ctx.is_finalized) ensure_contextless(ctx.is_finalized)
j := ctx.pt j := ctx.pt
for i := 0; i < len(hash); i += 1 { for i := 0; i < len(hash); i += 1 {
+9 -11
View File
@@ -3,7 +3,7 @@ package _sha3
import "core:encoding/endian" import "core:encoding/endian"
import "core:math/bits" import "core:math/bits"
init_cshake :: proc(ctx: ^Context, n, s: []byte, sec_strength: int) { init_cshake :: proc "contextless" (ctx: ^Context, n, s: []byte, sec_strength: int) {
ctx.mdlen = sec_strength / 8 ctx.mdlen = sec_strength / 8
// No domain separator is equivalent to vanilla SHAKE. // No domain separator is equivalent to vanilla SHAKE.
@@ -18,7 +18,7 @@ init_cshake :: proc(ctx: ^Context, n, s: []byte, sec_strength: int) {
bytepad(ctx, [][]byte{n, s}, rate_cshake(sec_strength)) bytepad(ctx, [][]byte{n, s}, rate_cshake(sec_strength))
} }
final_cshake :: proc(ctx: ^Context, dst: []byte, finalize_clone: bool = false) { final_cshake :: proc "contextless" (ctx: ^Context, dst: []byte, finalize_clone: bool = false) {
ctx := ctx ctx := ctx
if finalize_clone { if finalize_clone {
tmp_ctx: Context tmp_ctx: Context
@@ -32,7 +32,7 @@ final_cshake :: proc(ctx: ^Context, dst: []byte, finalize_clone: bool = false) {
shake_out(ctx, dst) shake_out(ctx, dst)
} }
rate_cshake :: #force_inline proc(sec_strength: int) -> int { rate_cshake :: #force_inline proc "contextless" (sec_strength: int) -> int {
switch sec_strength { switch sec_strength {
case 128: case 128:
return RATE_128 return RATE_128
@@ -40,7 +40,7 @@ rate_cshake :: #force_inline proc(sec_strength: int) -> int {
return RATE_256 return RATE_256
} }
panic("crypto/sha3: invalid security strength") panic_contextless("crypto/sha3: invalid security strength")
} }
// right_encode and left_encode are defined to support 0 <= x < 2^2040 // right_encode and left_encode are defined to support 0 <= x < 2^2040
@@ -55,7 +55,7 @@ rate_cshake :: #force_inline proc(sec_strength: int) -> int {
@(private, rodata) @(private, rodata)
_PAD: [RATE_128]byte // Biggest possible value of w per spec. _PAD: [RATE_128]byte // Biggest possible value of w per spec.
bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) { bytepad :: proc "contextless" (ctx: ^Context, x_strings: [][]byte, w: int) {
// 1. z = left_encode(w) || X. // 1. z = left_encode(w) || X.
z_hi: u64 z_hi: u64
z_lo := left_right_encode(ctx, 0, u64(w), true) z_lo := left_right_encode(ctx, 0, u64(w), true)
@@ -70,9 +70,7 @@ bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) {
// This isn't actually possible, at least with the currently // This isn't actually possible, at least with the currently
// defined SP 800-185 routines. // defined SP 800-185 routines.
if carry != 0 { ensure_contextless(carry == 0, "crypto/sha3: bytepad input length overflow")
panic("crypto/sha3: bytepad input length overflow")
}
} }
// We skip this step as we are doing a byte-oriented implementation // We skip this step as we are doing a byte-oriented implementation
@@ -95,7 +93,7 @@ bytepad :: proc(ctx: ^Context, x_strings: [][]byte, w: int) {
} }
} }
encode_string :: #force_inline proc(ctx: ^Context, s: []byte) -> (u64, u64) { encode_string :: #force_inline proc "contextless" (ctx: ^Context, s: []byte) -> (u64, u64) {
l := encode_byte_len(ctx, len(s), true) // left_encode l := encode_byte_len(ctx, len(s), true) // left_encode
update(ctx, s) update(ctx, s)
@@ -104,13 +102,13 @@ encode_string :: #force_inline proc(ctx: ^Context, s: []byte) -> (u64, u64) {
return hi, lo return hi, lo
} }
encode_byte_len :: #force_inline proc(ctx: ^Context, l: int, is_left: bool) -> u64 { encode_byte_len :: #force_inline proc "contextless" (ctx: ^Context, l: int, is_left: bool) -> u64 {
hi, lo := bits.mul_u64(u64(l), 8) hi, lo := bits.mul_u64(u64(l), 8)
return left_right_encode(ctx, hi, lo, is_left) return left_right_encode(ctx, hi, lo, is_left)
} }
@(private) @(private)
left_right_encode :: proc(ctx: ^Context, hi, lo: u64, is_left: bool) -> u64 { left_right_encode :: proc "contextless" (ctx: ^Context, hi, lo: u64, is_left: bool) -> u64 {
HI_OFFSET :: 1 HI_OFFSET :: 1
LO_OFFSET :: HI_OFFSET + 8 LO_OFFSET :: HI_OFFSET + 8
RIGHT_OFFSET :: LO_OFFSET + 8 RIGHT_OFFSET :: LO_OFFSET + 8
+3 -9
View File
@@ -128,9 +128,7 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat
reset(ctx) reset(ctx)
} }
if len(key) != KEY_SIZES[algorithm] { ensure(len(key) == KEY_SIZES[algorithm], "crypto/aead: invalid key size")
panic("crypto/aead: invalid key size")
}
// Directly specialize the union by setting the type ID (save a copy). // Directly specialize the union by setting the type ID (save a copy).
reflect.set_union_variant_typeid( reflect.set_union_variant_typeid(
@@ -167,9 +165,7 @@ init :: proc(ctx: ^Context, algorithm: Algorithm, key: []byte, impl: Implementat
// //
// dst and plaintext MUST alias exactly or not at all. // dst and plaintext MUST alias exactly or not at all.
seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
if len(tag) != TAG_SIZES[ctx._algo] { ensure(len(tag) == TAG_SIZES[ctx._algo], "crypto/aead: invalid tag size")
panic("crypto/aead: invalid tag size")
}
switch &impl in ctx._impl { switch &impl in ctx._impl {
case aes.Context_GCM: case aes.Context_GCM:
@@ -193,9 +189,7 @@ seal_ctx :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
// dst and plaintext MUST alias exactly or not at all. // dst and plaintext MUST alias exactly or not at all.
@(require_results) @(require_results)
open_ctx :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { open_ctx :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool {
if len(tag) != TAG_SIZES[ctx._algo] { ensure(len(tag) == TAG_SIZES[ctx._algo], "crypto/aead: invalid tag size")
panic("crypto/aead: invalid tag size")
}
switch &impl in ctx._impl { switch &impl in ctx._impl {
case aes.Context_GCM: case aes.Context_GCM:
+4 -8
View File
@@ -21,9 +21,7 @@ Context_CTR :: struct {
// init_ctr initializes a Context_CTR with the provided key and IV. // init_ctr initializes a Context_CTR with the provided key and IV.
init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) { init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) {
if len(iv) != CTR_IV_SIZE { ensure(len(iv) == CTR_IV_SIZE, "crypto/aes: invalid CTR IV size")
panic("crypto/aes: invalid CTR IV size")
}
init_impl(&ctx._impl, key, impl) init_impl(&ctx._impl, key, impl)
ctx._off = BLOCK_SIZE ctx._off = BLOCK_SIZE
@@ -36,16 +34,14 @@ init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := DEFAULT_IMPLEMENTAT
// keystream, and writes the resulting output to dst. dst and src MUST // keystream, and writes the resulting output to dst. dst and src MUST
// alias exactly or not at all. // alias exactly or not at all.
xor_bytes_ctr :: proc(ctx: ^Context_CTR, dst, src: []byte) { xor_bytes_ctr :: proc(ctx: ^Context_CTR, dst, src: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
src, dst := src, dst src, dst := src, dst
if dst_len := len(dst); dst_len < len(src) { if dst_len := len(dst); dst_len < len(src) {
src = src[:dst_len] src = src[:dst_len]
} }
if bytes.alias_inexactly(dst, src) { ensure(!bytes.alias_inexactly(dst, src), "crypto/aes: dst and src alias inexactly")
panic("crypto/aes: dst and src alias inexactly")
}
#no_bounds_check for remaining := len(src); remaining > 0; { #no_bounds_check for remaining := len(src); remaining > 0; {
// Process multiple blocks at once // Process multiple blocks at once
@@ -82,7 +78,7 @@ xor_bytes_ctr :: proc(ctx: ^Context_CTR, dst, src: []byte) {
// keystream_bytes_ctr fills dst with the raw AES-CTR keystream output. // keystream_bytes_ctr fills dst with the raw AES-CTR keystream output.
keystream_bytes_ctr :: proc(ctx: ^Context_CTR, dst: []byte) { keystream_bytes_ctr :: proc(ctx: ^Context_CTR, dst: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
dst := dst dst := dst
#no_bounds_check for remaining := len(dst); remaining > 0; { #no_bounds_check for remaining := len(dst); remaining > 0; {
+6 -10
View File
@@ -19,11 +19,9 @@ init_ecb :: proc(ctx: ^Context_ECB, key: []byte, impl := DEFAULT_IMPLEMENTATION)
// encrypt_ecb encrypts the BLOCK_SIZE buffer src, and writes the result to dst. // encrypt_ecb encrypts the BLOCK_SIZE buffer src, and writes the result to dst.
encrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) { encrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid dst size")
if len(dst) != BLOCK_SIZE || len(src) != BLOCK_SIZE { ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid src size")
panic("crypto/aes: invalid buffer size(s)")
}
switch &impl in ctx._impl { switch &impl in ctx._impl {
case ct64.Context: case ct64.Context:
@@ -35,11 +33,9 @@ encrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) {
// decrypt_ecb decrypts the BLOCK_SIZE buffer src, and writes the result to dst. // decrypt_ecb decrypts the BLOCK_SIZE buffer src, and writes the result to dst.
decrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) { decrypt_ecb :: proc(ctx: ^Context_ECB, dst, src: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid dst size")
if len(dst) != BLOCK_SIZE || len(src) != BLOCK_SIZE { ensure(len(dst) == BLOCK_SIZE, "crypto/aes: invalid src size")
panic("crypto/aes: invalid buffer size(s)")
}
switch &impl in ctx._impl { switch &impl in ctx._impl {
case ct64.Context: case ct64.Context:
+10 -26
View File
@@ -36,15 +36,11 @@ init_gcm :: proc(ctx: ^Context_GCM, key: []byte, impl := DEFAULT_IMPLEMENTATION)
// //
// dst and plaintext MUST alias exactly or not at all. // dst and plaintext MUST alias exactly or not at all.
seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, iv, aad, plaintext: []byte) { seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, iv, aad, plaintext: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
gcm_validate_common_slice_sizes(tag, iv, aad, plaintext) gcm_validate_common_slice_sizes(tag, iv, aad, plaintext)
if len(dst) != len(plaintext) { ensure(len(dst) == len(plaintext), "crypto/aes: invalid destination ciphertext size")
panic("crypto/aes: invalid destination ciphertext size") ensure(!bytes.alias_inexactly(dst, plaintext), "crypto/aes: dst and plaintext alias inexactly")
}
if bytes.alias_inexactly(dst, plaintext) {
panic("crypto/aes: dst and plaintext alias inexactly")
}
if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw { if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw {
gcm_seal_hw(&impl, dst, tag, iv, aad, plaintext) gcm_seal_hw(&impl, dst, tag, iv, aad, plaintext)
@@ -76,15 +72,11 @@ seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, iv, aad, plaintext: []byte) {
// dst and plaintext MUST alias exactly or not at all. // dst and plaintext MUST alias exactly or not at all.
@(require_results) @(require_results)
open_gcm :: proc(ctx: ^Context_GCM, dst, iv, aad, ciphertext, tag: []byte) -> bool { open_gcm :: proc(ctx: ^Context_GCM, dst, iv, aad, ciphertext, tag: []byte) -> bool {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
gcm_validate_common_slice_sizes(tag, iv, aad, ciphertext) gcm_validate_common_slice_sizes(tag, iv, aad, ciphertext)
if len(dst) != len(ciphertext) { ensure(len(dst) == len(ciphertext), "crypto/aes: invalid destination plaintext size")
panic("crypto/aes: invalid destination plaintext size") ensure(!bytes.alias_inexactly(dst, ciphertext), "crypto/aes: dst and ciphertext alias inexactly")
}
if bytes.alias_inexactly(dst, ciphertext) {
panic("crypto/aes: dst and ciphertext alias inexactly")
}
if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw { if impl, is_hw := ctx._impl.(Context_Impl_Hardware); is_hw {
return gcm_open_hw(&impl, dst, iv, aad, ciphertext, tag) return gcm_open_hw(&impl, dst, iv, aad, ciphertext, tag)
@@ -122,21 +114,13 @@ reset_gcm :: proc "contextless" (ctx: ^Context_GCM) {
@(private = "file") @(private = "file")
gcm_validate_common_slice_sizes :: proc(tag, iv, aad, text: []byte) { gcm_validate_common_slice_sizes :: proc(tag, iv, aad, text: []byte) {
if len(tag) != GCM_TAG_SIZE { ensure(len(tag) == GCM_TAG_SIZE, "crypto/aes: invalid GCM tag size")
panic("crypto/aes: invalid GCM tag size")
}
// The specification supports IVs in the range [1, 2^64) bits. // The specification supports IVs in the range [1, 2^64) bits.
if l := len(iv); l == 0 || u64(l) >= GCM_IV_SIZE_MAX { ensure(len(iv) == 0 || u64(len(iv)) <= GCM_IV_SIZE_MAX, "crypto/aes: invalid GCM IV size")
panic("crypto/aes: invalid GCM IV size")
}
if aad_len := u64(len(aad)); aad_len > GCM_A_MAX { ensure(u64(len(aad)) <= GCM_A_MAX, "crypto/aes: oversized GCM aad")
panic("crypto/aes: oversized GCM aad") ensure(u64(len(text)) <= GCM_P_MAX, "crypto/aes: oversized GCM data")
}
if text_len := u64(len(text)); text_len > GCM_P_MAX {
panic("crypto/aes: oversized GCM src data")
}
} }
@(private = "file") @(private = "file")
+1 -1
View File
@@ -235,7 +235,7 @@ gctr_hw :: proc(
// BUG: Sticking this in gctr_hw (like the other implementations) crashes // BUG: Sticking this in gctr_hw (like the other implementations) crashes
// the compiler. // the compiler.
// //
// src/check_expr.cpp(7892): Assertion Failure: `c->curr_proc_decl->entity` // src/check_expr.cpp(8104): Assertion Failure: `c->curr_proc_decl->entity`
@(private = "file", enable_target_feature = "sse4.1") @(private = "file", enable_target_feature = "sse4.1")
hw_inc_ctr32 :: #force_inline proc "contextless" (src: ^x86.__m128i, ctr: u32) -> (x86.__m128i, u32) { hw_inc_ctr32 :: #force_inline proc "contextless" (src: ^x86.__m128i, ctr: u32) -> (x86.__m128i, u32) {
ret := x86._mm_insert_epi32(src^, i32(intrinsics.byte_swap(ctr)), 3) ret := x86._mm_insert_epi32(src^, i32(intrinsics.byte_swap(ctr)), 3)
+2 -3
View File
@@ -28,9 +28,8 @@ Context :: _blake2.Blake2b_Context
// init initializes a Context with the default BLAKE2b config. // init initializes a Context with the default BLAKE2b config.
init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) { init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) {
if digest_size > 255 { ensure(digest_size <= _blake2.MAX_SIZE, "crypto/blake2b: invalid digest size")
panic("blake2b: invalid digest size")
}
cfg: _blake2.Blake2_Config cfg: _blake2.Blake2_Config
cfg.size = u8(digest_size) cfg.size = u8(digest_size)
_blake2.init(ctx, &cfg) _blake2.init(ctx, &cfg)
+2 -3
View File
@@ -28,9 +28,8 @@ Context :: _blake2.Blake2s_Context
// init initializes a Context with the default BLAKE2s config. // init initializes a Context with the default BLAKE2s config.
init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) { init :: proc(ctx: ^Context, digest_size := DIGEST_SIZE) {
if digest_size > 255 { ensure(digest_size <= _blake2.MAX_SIZE, "crypto/blake2s: invalid digest size")
panic("blake2s: invalid digest size")
}
cfg: _blake2.Blake2_Config cfg: _blake2.Blake2_Config
cfg.size = u8(digest_size) cfg.size = u8(digest_size)
_blake2.init(ctx, &cfg) _blake2.init(ctx, &cfg)
+5 -11
View File
@@ -27,12 +27,8 @@ Context :: struct {
// init inititializes a Context for ChaCha20 or XChaCha20 with the provided // init inititializes a Context for ChaCha20 or XChaCha20 with the provided
// key and iv. // key and iv.
init :: proc(ctx: ^Context, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) { init :: proc(ctx: ^Context, key, iv: []byte, impl := DEFAULT_IMPLEMENTATION) {
if len(key) != KEY_SIZE { ensure(len(key) == KEY_SIZE, "crypto/chacha20: invalid (X)ChaCha20 key size")
panic("crypto/chacha20: invalid (X)ChaCha20 key size") ensure(len(iv) == IV_SIZE || len(iv) == XIV_SIZE, "crypto/chacha20: invalid (X)ChaCha20 IV size")
}
if l := len(iv); l != IV_SIZE && l != XIV_SIZE {
panic("crypto/chacha20: invalid (X)ChaCha20 IV size")
}
k, n := key, iv k, n := key, iv
@@ -67,16 +63,14 @@ seek :: proc(ctx: ^Context, block_nr: u64) {
// keystream, and writes the resulting output to dst. Dst and src MUST // keystream, and writes the resulting output to dst. Dst and src MUST
// alias exactly or not at all. // alias exactly or not at all.
xor_bytes :: proc(ctx: ^Context, dst, src: []byte) { xor_bytes :: proc(ctx: ^Context, dst, src: []byte) {
assert(ctx._state._is_initialized) ensure(ctx._state._is_initialized)
src, dst := src, dst src, dst := src, dst
if dst_len := len(dst); dst_len < len(src) { if dst_len := len(dst); dst_len < len(src) {
src = src[:dst_len] src = src[:dst_len]
} }
if bytes.alias_inexactly(dst, src) { ensure(!bytes.alias_inexactly(dst, src), "crypto/chacha20: dst and src alias inexactly")
panic("crypto/chacha20: dst and src alias inexactly")
}
st := &ctx._state st := &ctx._state
#no_bounds_check for remaining := len(src); remaining > 0; { #no_bounds_check for remaining := len(src); remaining > 0; {
@@ -114,7 +108,7 @@ xor_bytes :: proc(ctx: ^Context, dst, src: []byte) {
// keystream_bytes fills dst with the raw (X)ChaCha20 keystream output. // keystream_bytes fills dst with the raw (X)ChaCha20 keystream output.
keystream_bytes :: proc(ctx: ^Context, dst: []byte) { keystream_bytes :: proc(ctx: ^Context, dst: []byte) {
assert(ctx._state._is_initialized) ensure(ctx._state._is_initialized)
dst, st := dst, &ctx._state dst, st := dst, &ctx._state
#no_bounds_check for remaining := len(dst); remaining > 0; { #no_bounds_check for remaining := len(dst); remaining > 0; {
@@ -29,13 +29,9 @@ _P_MAX :: 64 * 0xffffffff // 64 * (2^32-1)
@(private) @(private)
_validate_common_slice_sizes :: proc (tag, iv, aad, text: []byte, is_xchacha: bool) { _validate_common_slice_sizes :: proc (tag, iv, aad, text: []byte, is_xchacha: bool) {
if len(tag) != TAG_SIZE {
panic("crypto/chacha20poly1305: invalid destination tag size")
}
expected_iv_len := is_xchacha ? XIV_SIZE : IV_SIZE expected_iv_len := is_xchacha ? XIV_SIZE : IV_SIZE
if len(iv) != expected_iv_len { ensure(len(tag) == TAG_SIZE, "crypto/chacha20poly1305: invalid destination tag size")
panic("crypto/chacha20poly1305: invalid IV size") ensure(len(iv) == expected_iv_len, "crypto/chacha20poly1305: invalid IV size")
}
#assert(size_of(int) == 8 || size_of(int) <= 4) #assert(size_of(int) == 8 || size_of(int) <= 4)
when size_of(int) == 8 { when size_of(int) == 8 {
@@ -45,9 +41,7 @@ _validate_common_slice_sizes :: proc (tag, iv, aad, text: []byte, is_xchacha: bo
// A_MAX is limited by size_of(int), so there is no need to // A_MAX is limited by size_of(int), so there is no need to
// enforce it. P_MAX only needs to be checked on 64-bit targets, // enforce it. P_MAX only needs to be checked on 64-bit targets,
// for reasons that should be obvious. // for reasons that should be obvious.
if text_len := len(text); text_len > _P_MAX { ensure(len(text) <= _P_MAX, "crypto/chacha20poly1305: oversized src data")
panic("crypto/chacha20poly1305: oversized src data")
}
} }
} }
@@ -71,9 +65,7 @@ Context :: struct {
// init initializes a Context with the provided key, for AEAD_CHACHA20_POLY1305. // init initializes a Context with the provided key, for AEAD_CHACHA20_POLY1305.
init :: proc(ctx: ^Context, key: []byte, impl := chacha20.DEFAULT_IMPLEMENTATION) { init :: proc(ctx: ^Context, key: []byte, impl := chacha20.DEFAULT_IMPLEMENTATION) {
if len(key) != KEY_SIZE { ensure(len(key) == KEY_SIZE, "crypto/chacha20poly1305: invalid key size")
panic("crypto/chacha20poly1305: invalid key size")
}
copy(ctx._key[:], key) copy(ctx._key[:], key)
ctx._impl = impl ctx._impl = impl
@@ -96,13 +88,11 @@ init_xchacha :: proc(ctx: ^Context, key: []byte, impl := chacha20.DEFAULT_IMPLEM
// //
// dst and plaintext MUST alias exactly or not at all. // dst and plaintext MUST alias exactly or not at all.
seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
ciphertext := dst ciphertext := dst
_validate_common_slice_sizes(tag, iv, aad, plaintext, ctx._is_xchacha) _validate_common_slice_sizes(tag, iv, aad, plaintext, ctx._is_xchacha)
if len(ciphertext) != len(plaintext) { ensure(len(ciphertext) == len(plaintext), "crypto/chacha20poly1305: invalid destination ciphertext size")
panic("crypto/chacha20poly1305: invalid destination ciphertext size")
}
stream_ctx: chacha20.Context = --- stream_ctx: chacha20.Context = ---
chacha20.init(&stream_ctx, ctx._key[:],iv, ctx._impl) chacha20.init(&stream_ctx, ctx._key[:],iv, ctx._impl)
@@ -153,13 +143,11 @@ seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
// dst and plaintext MUST alias exactly or not at all. // dst and plaintext MUST alias exactly or not at all.
@(require_results) @(require_results)
open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
plaintext := dst plaintext := dst
_validate_common_slice_sizes(tag, iv, aad, ciphertext, ctx._is_xchacha) _validate_common_slice_sizes(tag, iv, aad, ciphertext, ctx._is_xchacha)
if len(ciphertext) != len(plaintext) { ensure(len(ciphertext) == len(plaintext), "crypto/chacha20poly1305: invalid destination plaintext size")
panic("crypto/chacha20poly1305: invalid destination plaintext size")
}
// Note: Unlike encrypt, this can fail early, so use defer for // Note: Unlike encrypt, this can fail early, so use defer for
// sanitization rather than assuming control flow reaches certain // sanitization rather than assuming control flow reaches certain
+9 -24
View File
@@ -76,13 +76,8 @@ Context :: struct {
@(private) @(private)
_validate_common_slice_sizes :: proc (ctx: ^Context, tag, iv, aad, text: []byte) { _validate_common_slice_sizes :: proc (ctx: ^Context, tag, iv, aad, text: []byte) {
if len(tag) != TAG_SIZE { ensure(len(tag) == TAG_SIZE, "crypto/deoxysii: invalid tag size")
panic("crypto/deoxysii: invalid tag size") ensure(len(iv) == IV_SIZE, "crypto/deoxysii: invalid IV size")
}
if len(iv) != IV_SIZE {
panic("crypto/deoxysii: invalid IV size")
}
#assert(size_of(int) == 8 || size_of(int) <= 4) #assert(size_of(int) == 8 || size_of(int) <= 4)
// For the nonce-misuse resistant mode, the total size of the // For the nonce-misuse resistant mode, the total size of the
@@ -95,9 +90,7 @@ _validate_common_slice_sizes :: proc (ctx: ^Context, tag, iv, aad, text: []byte)
// init initializes a Context with the provided key. // init initializes a Context with the provided key.
init :: proc(ctx: ^Context, key: []byte, impl := aes.DEFAULT_IMPLEMENTATION) { init :: proc(ctx: ^Context, key: []byte, impl := aes.DEFAULT_IMPLEMENTATION) {
if len(key) != KEY_SIZE { ensure(len(key) == KEY_SIZE, "crypto/deoxysii: invalid key size")
panic("crypto/deoxysii: invalid key size")
}
ctx._impl = impl ctx._impl = impl
if ctx._impl == .Hardware && !is_hardware_accelerated() { if ctx._impl == .Hardware && !is_hardware_accelerated() {
@@ -114,15 +107,11 @@ init :: proc(ctx: ^Context, key: []byte, impl := aes.DEFAULT_IMPLEMENTATION) {
// //
// dst and plaintext MUST alias exactly or not at all. // dst and plaintext MUST alias exactly or not at all.
seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) { seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
_validate_common_slice_sizes(ctx, tag, iv, aad, plaintext) _validate_common_slice_sizes(ctx, tag, iv, aad, plaintext)
if len(dst) != len(plaintext) { ensure(len(dst) == len(plaintext), "crypto/deoxysii: invalid destination ciphertext size")
panic("crypto/deoxysii: invalid destination ciphertext size") ensure(!bytes.alias_inexactly(dst, plaintext), "crypto/deoxysii: dst and plaintext alias inexactly")
}
if bytes.alias_inexactly(dst, plaintext) {
panic("crypto/deoxysii: dst and plaintext alias inexactly")
}
switch ctx._impl { switch ctx._impl {
case .Hardware: case .Hardware:
@@ -140,15 +129,11 @@ seal :: proc(ctx: ^Context, dst, tag, iv, aad, plaintext: []byte) {
// dst and plaintext MUST alias exactly or not at all. // dst and plaintext MUST alias exactly or not at all.
@(require_results) @(require_results)
open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool { open :: proc(ctx: ^Context, dst, iv, aad, ciphertext, tag: []byte) -> bool {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
_validate_common_slice_sizes(ctx, tag, iv, aad, ciphertext) _validate_common_slice_sizes(ctx, tag, iv, aad, ciphertext)
if len(dst) != len(ciphertext) { ensure(len(dst) == len(ciphertext), "crypto/deoxysii: invalid destination plaintext size")
panic("crypto/deoxysii: invalid destination plaintext size") ensure(!bytes.alias_inexactly(dst, ciphertext), "crypto/deoxysii: dst and ciphertext alias inexactly")
}
if bytes.alias_inexactly(dst, ciphertext) {
panic("crypto/deoxysii: dst and ciphertext alias inexactly")
}
ok: bool ok: bool
switch ctx._impl { switch ctx._impl {
+8 -24
View File
@@ -81,12 +81,8 @@ private_key_set_bytes :: proc(priv_key: ^Private_Key, b: []byte) -> bool {
// private_key_bytes sets dst to byte-encoding of priv_key. // private_key_bytes sets dst to byte-encoding of priv_key.
private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) { private_key_bytes :: proc(priv_key: ^Private_Key, dst: []byte) {
if !priv_key._is_initialized { ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized private key")
panic("crypto/ed25519: uninitialized private key") ensure(len(dst) == PRIVATE_KEY_SIZE, "crypto/ed25519: invalid destination size")
}
if len(dst) != PRIVATE_KEY_SIZE {
panic("crypto/ed25519: invalid destination size")
}
copy(dst, priv_key._b[:]) copy(dst, priv_key._b[:])
} }
@@ -98,12 +94,8 @@ private_key_clear :: proc "contextless" (priv_key: ^Private_Key) {
// sign writes the signature by priv_key over msg to sig. // sign writes the signature by priv_key over msg to sig.
sign :: proc(priv_key: ^Private_Key, msg, sig: []byte) { sign :: proc(priv_key: ^Private_Key, msg, sig: []byte) {
if !priv_key._is_initialized { ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized private key")
panic("crypto/ed25519: uninitialized private key") ensure(len(sig) == SIGNATURE_SIZE, "crypto/ed25519: invalid destination size")
}
if len(sig) != SIGNATURE_SIZE {
panic("crypto/ed25519: invalid destination size")
}
// 1. Compute the hash of the private key d, H(d) = (h_0, h_1, ..., h_2b-1) // 1. Compute the hash of the private key d, H(d) = (h_0, h_1, ..., h_2b-1)
// using SHA-512 for Ed25519. H(d) may be precomputed. // using SHA-512 for Ed25519. H(d) may be precomputed.
@@ -178,9 +170,7 @@ public_key_set_bytes :: proc "contextless" (pub_key: ^Public_Key, b: []byte) ->
// public_key_set_priv sets pub_key to the public component of priv_key. // public_key_set_priv sets pub_key to the public component of priv_key.
public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) { public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) {
if !priv_key._is_initialized { ensure(priv_key._is_initialized, "crypto/ed25519: uninitialized public key")
panic("crypto/ed25519: uninitialized public key")
}
src := &priv_key._pub_key src := &priv_key._pub_key
copy(pub_key._b[:], src._b[:]) copy(pub_key._b[:], src._b[:])
@@ -191,21 +181,15 @@ public_key_set_priv :: proc(pub_key: ^Public_Key, priv_key: ^Private_Key) {
// public_key_bytes sets dst to byte-encoding of pub_key. // public_key_bytes sets dst to byte-encoding of pub_key.
public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) { public_key_bytes :: proc(pub_key: ^Public_Key, dst: []byte) {
if !pub_key._is_initialized { ensure(pub_key._is_initialized, "crypto/ed25519: uninitialized public key")
panic("crypto/ed25519: uninitialized public key") ensure(len(dst) == PUBLIC_KEY_SIZE, "crypto/ed25519: invalid destination size")
}
if len(dst) != PUBLIC_KEY_SIZE {
panic("crypto/ed25519: invalid destination size")
}
copy(dst, pub_key._b[:]) copy(dst, pub_key._b[:])
} }
// public_key_equal returns true iff pub_key is equal to other. // public_key_equal returns true iff pub_key is equal to other.
public_key_equal :: proc(pub_key, other: ^Public_Key) -> bool { public_key_equal :: proc(pub_key, other: ^Public_Key) -> bool {
if !pub_key._is_initialized || !other._is_initialized { ensure(pub_key._is_initialized && other._is_initialized, "crypto/ed25519: uninitialized public key")
panic("crypto/ed25519: uninitialized public key")
}
return crypto.compare_constant_time(pub_key._b[:], other._b[:]) == 1 return crypto.compare_constant_time(pub_key._b[:], other._b[:]) == 1
} }
+5 -8
View File
@@ -56,7 +56,7 @@ init :: proc(ctx: ^Context, algorithm: hash.Algorithm, key: []byte) {
// update adds more data to the Context. // update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) { update :: proc(ctx: ^Context, data: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
hash.update(&ctx._i_hash, data) hash.update(&ctx._i_hash, data)
} }
@@ -64,13 +64,10 @@ update :: proc(ctx: ^Context, data: []byte) {
// final finalizes the Context, writes the tag to dst, and calls // final finalizes the Context, writes the tag to dst, and calls
// reset on the Context. // reset on the Context.
final :: proc(ctx: ^Context, dst: []byte) { final :: proc(ctx: ^Context, dst: []byte) {
assert(ctx._is_initialized)
defer (reset(ctx)) defer (reset(ctx))
if len(dst) != ctx._tag_sz { ensure(ctx._is_initialized)
panic("crypto/hmac: invalid destination tag size") ensure(len(dst) == ctx._tag_sz, "crypto/hmac: invalid destination tag size")
}
hash.final(&ctx._i_hash, dst) // H((k ^ ipad) || text) hash.final(&ctx._i_hash, dst) // H((k ^ ipad) || text)
@@ -105,14 +102,14 @@ reset :: proc(ctx: ^Context) {
// algorithm returns the Algorithm used by a Context instance. // algorithm returns the Algorithm used by a Context instance.
algorithm :: proc(ctx: ^Context) -> hash.Algorithm { algorithm :: proc(ctx: ^Context) -> hash.Algorithm {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
return hash.algorithm(&ctx._i_hash) return hash.algorithm(&ctx._i_hash)
} }
// tag_size returns the tag size of a Context instance in bytes. // tag_size returns the tag size of a Context instance in bytes.
tag_size :: proc(ctx: ^Context) -> int { tag_size :: proc(ctx: ^Context) -> int {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
return ctx._tag_sz return ctx._tag_sz
} }
+3 -9
View File
@@ -36,6 +36,7 @@ sum :: proc(sec_strength: int, dst, msg, key, domain_sep: []byte) {
// tag is valid. // tag is valid.
verify :: proc(sec_strength: int, tag, msg, key, domain_sep: []byte, allocator := context.temp_allocator) -> bool { verify :: proc(sec_strength: int, tag, msg, key, domain_sep: []byte, allocator := context.temp_allocator) -> bool {
derived_tag := make([]byte, len(tag), allocator) derived_tag := make([]byte, len(tag), allocator)
defer(delete(derived_tag))
sum(sec_strength, derived_tag, msg, key, domain_sep) sum(sec_strength, derived_tag, msg, key, domain_sep)
@@ -59,8 +60,6 @@ init_256 :: proc(ctx: ^Context, key, domain_sep: []byte) {
// update adds more data to the Context. // update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) { update :: proc(ctx: ^Context, data: []byte) {
assert(ctx.is_initialized)
shake.write((^shake.Context)(ctx), data) shake.write((^shake.Context)(ctx), data)
} }
@@ -68,12 +67,9 @@ update :: proc(ctx: ^Context, data: []byte) {
// on the Context. This routine will panic if the dst length is less than // on the Context. This routine will panic if the dst length is less than
// MIN_TAG_SIZE. // MIN_TAG_SIZE.
final :: proc(ctx: ^Context, dst: []byte) { final :: proc(ctx: ^Context, dst: []byte) {
assert(ctx.is_initialized)
defer reset(ctx) defer reset(ctx)
if len(dst) < MIN_TAG_SIZE { ensure(len(dst) >= MIN_TAG_SIZE, "crypto/kmac: invalid KMAC tag_size, too short")
panic("crypto/kmac: invalid KMAC tag_size, too short")
}
_sha3.final_cshake((^_sha3.Context)(ctx), dst) _sha3.final_cshake((^_sha3.Context)(ctx), dst)
} }
@@ -103,9 +99,7 @@ _init_kmac :: proc(ctx: ^Context, key, s: []byte, sec_strength: int) {
reset(ctx) reset(ctx)
} }
if len(key) < sec_strength / 8 { ensure(len(key) >= sec_strength / 8, "crypto/kmac: invalid KMAC key, too short")
panic("crypto/kmac: invalid KMAC key, too short")
}
ctx_ := (^_sha3.Context)(ctx) ctx_ := (^_sha3.Context)(ctx)
_sha3.init_cshake(ctx_, N_KMAC, s, sec_strength) _sha3.init_cshake(ctx_, N_KMAC, s, sec_strength)
+9 -9
View File
@@ -40,37 +40,37 @@ BLOCK_SIZE_512 :: _sha3.RATE_512
Context :: distinct _sha3.Context Context :: distinct _sha3.Context
// init_224 initializes a Context for Keccak-224. // init_224 initializes a Context for Keccak-224.
init_224 :: proc(ctx: ^Context) { init_224 :: proc "contextless" (ctx: ^Context) {
ctx.mdlen = DIGEST_SIZE_224 ctx.mdlen = DIGEST_SIZE_224
_init(ctx) _init(ctx)
} }
// init_256 initializes a Context for Keccak-256. // init_256 initializes a Context for Keccak-256.
init_256 :: proc(ctx: ^Context) { init_256 :: proc "contextless" (ctx: ^Context) {
ctx.mdlen = DIGEST_SIZE_256 ctx.mdlen = DIGEST_SIZE_256
_init(ctx) _init(ctx)
} }
// init_384 initializes a Context for Keccak-384. // init_384 initializes a Context for Keccak-384.
init_384 :: proc(ctx: ^Context) { init_384 :: proc "contextless" (ctx: ^Context) {
ctx.mdlen = DIGEST_SIZE_384 ctx.mdlen = DIGEST_SIZE_384
_init(ctx) _init(ctx)
} }
// init_512 initializes a Context for Keccak-512. // init_512 initializes a Context for Keccak-512.
init_512 :: proc(ctx: ^Context) { init_512 :: proc "contextless" (ctx: ^Context) {
ctx.mdlen = DIGEST_SIZE_512 ctx.mdlen = DIGEST_SIZE_512
_init(ctx) _init(ctx)
} }
@(private) @(private)
_init :: proc(ctx: ^Context) { _init :: proc "contextless" (ctx: ^Context) {
ctx.dsbyte = _sha3.DS_KECCAK ctx.dsbyte = _sha3.DS_KECCAK
_sha3.init((^_sha3.Context)(ctx)) _sha3.init((^_sha3.Context)(ctx))
} }
// update adds more data to the Context. // update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) { update :: proc "contextless" (ctx: ^Context, data: []byte) {
_sha3.update((^_sha3.Context)(ctx), data) _sha3.update((^_sha3.Context)(ctx), data)
} }
@@ -79,17 +79,17 @@ update :: proc(ctx: ^Context, data: []byte) {
// //
// Iff finalize_clone is set, final will work on a copy of the Context, // Iff finalize_clone is set, final will work on a copy of the Context,
// which is useful for for calculating rolling digests. // which is useful for for calculating rolling digests.
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { final :: proc "contextless" (ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
_sha3.final((^_sha3.Context)(ctx), hash, finalize_clone) _sha3.final((^_sha3.Context)(ctx), hash, finalize_clone)
} }
// clone clones the Context other into ctx. // clone clones the Context other into ctx.
clone :: proc(ctx, other: ^Context) { clone :: proc "contextless" (ctx, other: ^Context) {
_sha3.clone((^_sha3.Context)(ctx), (^_sha3.Context)(other)) _sha3.clone((^_sha3.Context)(ctx), (^_sha3.Context)(other))
} }
// reset sanitizes the Context. The Context must be re-initialized to // reset sanitizes the Context. The Context must be re-initialized to
// be used again. // be used again.
reset :: proc(ctx: ^Context) { reset :: proc "contextless" (ctx: ^Context) {
_sha3.reset((^_sha3.Context)(ctx)) _sha3.reset((^_sha3.Context)(ctx))
} }
+3 -6
View File
@@ -53,7 +53,7 @@ init :: proc(ctx: ^Context) {
// update adds more data to the Context. // update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) { update :: proc(ctx: ^Context, data: []byte) {
assert(ctx.is_initialized) ensure(ctx.is_initialized)
for i := 0; i < len(data); i += 1 { for i := 0; i < len(data); i += 1 {
ctx.data[ctx.datalen] = data[i] ctx.data[ctx.datalen] = data[i]
@@ -72,11 +72,8 @@ update :: proc(ctx: ^Context, data: []byte) {
// Iff finalize_clone is set, final will work on a copy of the Context, // Iff finalize_clone is set, final will work on a copy of the Context,
// which is useful for for calculating rolling digests. // which is useful for for calculating rolling digests.
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
assert(ctx.is_initialized) ensure(ctx.is_initialized)
ensure(len(hash) >= DIGEST_SIZE, "crypto/md5: invalid destination digest size")
if len(hash) < DIGEST_SIZE {
panic("crypto/md5: invalid destination digest size")
}
ctx := ctx ctx := ctx
if finalize_clone { if finalize_clone {
+3 -6
View File
@@ -60,7 +60,7 @@ init :: proc(ctx: ^Context) {
// update adds more data to the Context. // update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) { update :: proc(ctx: ^Context, data: []byte) {
assert(ctx.is_initialized) ensure(ctx.is_initialized)
for i := 0; i < len(data); i += 1 { for i := 0; i < len(data); i += 1 {
ctx.data[ctx.datalen] = data[i] ctx.data[ctx.datalen] = data[i]
@@ -79,11 +79,8 @@ update :: proc(ctx: ^Context, data: []byte) {
// Iff finalize_clone is set, final will work on a copy of the Context, // Iff finalize_clone is set, final will work on a copy of the Context,
// which is useful for for calculating rolling digests. // which is useful for for calculating rolling digests.
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
assert(ctx.is_initialized) ensure(ctx.is_initialized)
ensure(len(hash) >= DIGEST_SIZE, "crypto/sha1: invalid destination digest size")
if len(hash) < DIGEST_SIZE {
panic("crypto/sha1: invalid destination digest size")
}
ctx := ctx ctx := ctx
if finalize_clone { if finalize_clone {
+4 -8
View File
@@ -60,9 +60,7 @@ Context :: struct {
// init initializes a Context with the specified key. The key SHOULD be // init initializes a Context with the specified key. The key SHOULD be
// unique and MUST be unpredictable for each invocation. // unique and MUST be unpredictable for each invocation.
init :: proc(ctx: ^Context, key: []byte) { init :: proc(ctx: ^Context, key: []byte) {
if len(key) != KEY_SIZE { ensure(len(key) == KEY_SIZE, "crypto/poly1305: invalid key size")
panic("crypto/poly1305: invalid key size")
}
// r = le_bytes_to_num(key[0..15]) // r = le_bytes_to_num(key[0..15])
// r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff) // r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff)
@@ -85,7 +83,7 @@ init :: proc(ctx: ^Context, key: []byte) {
// update adds more data to the Context. // update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) { update :: proc(ctx: ^Context, data: []byte) {
assert(ctx._is_initialized) ensure(ctx._is_initialized)
msg := data msg := data
msg_len := len(data) msg_len := len(data)
@@ -124,12 +122,10 @@ update :: proc(ctx: ^Context, data: []byte) {
// final finalizes the Context, writes the tag to dst, and calls // final finalizes the Context, writes the tag to dst, and calls
// reset on the Context. // reset on the Context.
final :: proc(ctx: ^Context, dst: []byte) { final :: proc(ctx: ^Context, dst: []byte) {
assert(ctx._is_initialized)
defer reset(ctx) defer reset(ctx)
if len(dst) != TAG_SIZE { ensure(ctx._is_initialized)
panic("poly1305: invalid destination tag size") ensure(len(dst) == TAG_SIZE, "poly1305: invalid destination tag size")
}
// Process remaining block // Process remaining block
if ctx._leftover > 0 { if ctx._leftover > 0 {
+16 -22
View File
@@ -76,7 +76,7 @@ ge_clear :: proc "contextless" (ge: ^Group_Element) {
// ge_set sets `ge = a`. // ge_set sets `ge = a`.
ge_set :: proc(ge, a: ^Group_Element) { ge_set :: proc(ge, a: ^Group_Element) {
_ge_assert_initialized([]^Group_Element{a}) _ge_ensure_initialized([]^Group_Element{a})
grp.ge_set(&ge._p, &a._p) grp.ge_set(&ge._p, &a._p)
ge._is_initialized = true ge._is_initialized = true
@@ -199,9 +199,7 @@ ge_set_bytes :: proc "contextless" (ge: ^Group_Element, b: []byte) -> bool {
// ge_set_wide_bytes sets ge to the result of deriving a ristretto255 // ge_set_wide_bytes sets ge to the result of deriving a ristretto255
// group element, from a wide (512-bit) byte string. // group element, from a wide (512-bit) byte string.
ge_set_wide_bytes :: proc(ge: ^Group_Element, b: []byte) { ge_set_wide_bytes :: proc(ge: ^Group_Element, b: []byte) {
if len(b) != WIDE_ELEMENT_SIZE { ensure(len(b) == WIDE_ELEMENT_SIZE, "crypto/ristretto255: invalid wide input size")
panic("crypto/ristretto255: invalid wide input size")
}
// The element derivation function on an input string b proceeds as // The element derivation function on an input string b proceeds as
// follows: // follows:
@@ -222,10 +220,8 @@ ge_set_wide_bytes :: proc(ge: ^Group_Element, b: []byte) {
// ge_bytes sets dst to the canonical encoding of ge. // ge_bytes sets dst to the canonical encoding of ge.
ge_bytes :: proc(ge: ^Group_Element, dst: []byte) { ge_bytes :: proc(ge: ^Group_Element, dst: []byte) {
_ge_assert_initialized([]^Group_Element{ge}) _ge_ensure_initialized([]^Group_Element{ge})
if len(dst) != ELEMENT_SIZE { ensure(len(dst) == ELEMENT_SIZE, "crypto/ristretto255: invalid destination size")
panic("crypto/ristretto255: invalid destination size")
}
x0, y0, z0, t0 := &ge._p.x, &ge._p.y, &ge._p.z, &ge._p.t x0, y0, z0, t0 := &ge._p.x, &ge._p.y, &ge._p.z, &ge._p.t
@@ -306,7 +302,7 @@ ge_bytes :: proc(ge: ^Group_Element, dst: []byte) {
// ge_add sets `ge = a + b`. // ge_add sets `ge = a + b`.
ge_add :: proc(ge, a, b: ^Group_Element) { ge_add :: proc(ge, a, b: ^Group_Element) {
_ge_assert_initialized([]^Group_Element{a, b}) _ge_ensure_initialized([]^Group_Element{a, b})
grp.ge_add(&ge._p, &a._p, &b._p) grp.ge_add(&ge._p, &a._p, &b._p)
ge._is_initialized = true ge._is_initialized = true
@@ -314,7 +310,7 @@ ge_add :: proc(ge, a, b: ^Group_Element) {
// ge_double sets `ge = a + a`. // ge_double sets `ge = a + a`.
ge_double :: proc(ge, a: ^Group_Element) { ge_double :: proc(ge, a: ^Group_Element) {
_ge_assert_initialized([]^Group_Element{a}) _ge_ensure_initialized([]^Group_Element{a})
grp.ge_double(&ge._p, &a._p) grp.ge_double(&ge._p, &a._p)
ge._is_initialized = true ge._is_initialized = true
@@ -322,7 +318,7 @@ ge_double :: proc(ge, a: ^Group_Element) {
// ge_negate sets `ge = -a`. // ge_negate sets `ge = -a`.
ge_negate :: proc(ge, a: ^Group_Element) { ge_negate :: proc(ge, a: ^Group_Element) {
_ge_assert_initialized([]^Group_Element{a}) _ge_ensure_initialized([]^Group_Element{a})
grp.ge_negate(&ge._p, &a._p) grp.ge_negate(&ge._p, &a._p)
ge._is_initialized = true ge._is_initialized = true
@@ -330,7 +326,7 @@ ge_negate :: proc(ge, a: ^Group_Element) {
// ge_scalarmult sets `ge = A * sc`. // ge_scalarmult sets `ge = A * sc`.
ge_scalarmult :: proc(ge, A: ^Group_Element, sc: ^Scalar) { ge_scalarmult :: proc(ge, A: ^Group_Element, sc: ^Scalar) {
_ge_assert_initialized([]^Group_Element{A}) _ge_ensure_initialized([]^Group_Element{A})
grp.ge_scalarmult(&ge._p, &A._p, sc) grp.ge_scalarmult(&ge._p, &A._p, sc)
ge._is_initialized = true ge._is_initialized = true
@@ -344,7 +340,7 @@ ge_scalarmult_generator :: proc "contextless" (ge: ^Group_Element, sc: ^Scalar)
// ge_scalarmult_vartime sets `ge = A * sc` in variable time. // ge_scalarmult_vartime sets `ge = A * sc` in variable time.
ge_scalarmult_vartime :: proc(ge, A: ^Group_Element, sc: ^Scalar) { ge_scalarmult_vartime :: proc(ge, A: ^Group_Element, sc: ^Scalar) {
_ge_assert_initialized([]^Group_Element{A}) _ge_ensure_initialized([]^Group_Element{A})
grp.ge_scalarmult_vartime(&ge._p, &A._p, sc) grp.ge_scalarmult_vartime(&ge._p, &A._p, sc)
ge._is_initialized = true ge._is_initialized = true
@@ -358,7 +354,7 @@ ge_double_scalarmult_generator_vartime :: proc(
A: ^Group_Element, A: ^Group_Element,
b: ^Scalar, b: ^Scalar,
) { ) {
_ge_assert_initialized([]^Group_Element{A}) _ge_ensure_initialized([]^Group_Element{A})
grp.ge_double_scalarmult_basepoint_vartime(&ge._p, a, &A._p, b) grp.ge_double_scalarmult_basepoint_vartime(&ge._p, a, &A._p, b)
ge._is_initialized = true ge._is_initialized = true
@@ -367,7 +363,7 @@ ge_double_scalarmult_generator_vartime :: proc(
// ge_cond_negate sets `ge = a` iff `ctrl == 0` and `ge = -a` iff `ctrl == 1`. // ge_cond_negate sets `ge = a` iff `ctrl == 0` and `ge = -a` iff `ctrl == 1`.
// Behavior for all other values of ctrl are undefined, // Behavior for all other values of ctrl are undefined,
ge_cond_negate :: proc(ge, a: ^Group_Element, ctrl: int) { ge_cond_negate :: proc(ge, a: ^Group_Element, ctrl: int) {
_ge_assert_initialized([]^Group_Element{a}) _ge_ensure_initialized([]^Group_Element{a})
grp.ge_cond_negate(&ge._p, &a._p, ctrl) grp.ge_cond_negate(&ge._p, &a._p, ctrl)
ge._is_initialized = true ge._is_initialized = true
@@ -376,7 +372,7 @@ ge_cond_negate :: proc(ge, a: ^Group_Element, ctrl: int) {
// ge_cond_assign sets `ge = ge` iff `ctrl == 0` and `ge = a` iff `ctrl == 1`. // ge_cond_assign sets `ge = ge` iff `ctrl == 0` and `ge = a` iff `ctrl == 1`.
// Behavior for all other values of ctrl are undefined, // Behavior for all other values of ctrl are undefined,
ge_cond_assign :: proc(ge, a: ^Group_Element, ctrl: int) { ge_cond_assign :: proc(ge, a: ^Group_Element, ctrl: int) {
_ge_assert_initialized([]^Group_Element{ge, a}) _ge_ensure_initialized([]^Group_Element{ge, a})
grp.ge_cond_assign(&ge._p, &a._p, ctrl) grp.ge_cond_assign(&ge._p, &a._p, ctrl)
} }
@@ -384,7 +380,7 @@ ge_cond_assign :: proc(ge, a: ^Group_Element, ctrl: int) {
// ge_cond_select sets `ge = a` iff `ctrl == 0` and `ge = b` iff `ctrl == 1`. // ge_cond_select sets `ge = a` iff `ctrl == 0` and `ge = b` iff `ctrl == 1`.
// Behavior for all other values of ctrl are undefined, // Behavior for all other values of ctrl are undefined,
ge_cond_select :: proc(ge, a, b: ^Group_Element, ctrl: int) { ge_cond_select :: proc(ge, a, b: ^Group_Element, ctrl: int) {
_ge_assert_initialized([]^Group_Element{a, b}) _ge_ensure_initialized([]^Group_Element{a, b})
grp.ge_cond_select(&ge._p, &a._p, &b._p, ctrl) grp.ge_cond_select(&ge._p, &a._p, &b._p, ctrl)
ge._is_initialized = true ge._is_initialized = true
@@ -393,7 +389,7 @@ ge_cond_select :: proc(ge, a, b: ^Group_Element, ctrl: int) {
// ge_equal returns 1 iff `a == b`, and 0 otherwise. // ge_equal returns 1 iff `a == b`, and 0 otherwise.
@(require_results) @(require_results)
ge_equal :: proc(a, b: ^Group_Element) -> int { ge_equal :: proc(a, b: ^Group_Element) -> int {
_ge_assert_initialized([]^Group_Element{a, b}) _ge_ensure_initialized([]^Group_Element{a, b})
// CT_EQ(x1 * y2, y1 * x2) | CT_EQ(y1 * y2, x1 * x2) // CT_EQ(x1 * y2, y1 * x2) | CT_EQ(y1 * y2, x1 * x2)
ax_by, ay_bx, ay_by, ax_bx: field.Tight_Field_Element = ---, ---, ---, --- ax_by, ay_bx, ay_by, ax_bx: field.Tight_Field_Element = ---, ---, ---, ---
@@ -501,10 +497,8 @@ ge_map :: proc "contextless" (ge: ^Group_Element, b: []byte) {
} }
@(private) @(private)
_ge_assert_initialized :: proc(ges: []^Group_Element) { _ge_ensure_initialized :: proc(ges: []^Group_Element) {
for ge in ges { for ge in ges {
if !ge._is_initialized { ensure(ge._is_initialized, "crypto/ristretto255: uninitialized group element")
panic("crypto/ristretto255: uninitialized group element")
}
} }
} }
@@ -42,9 +42,7 @@ sc_set_bytes :: proc(sc: ^Scalar, b: []byte) -> bool {
// scalar, from a wide (512-bit) byte string by interpreting b as a // scalar, from a wide (512-bit) byte string by interpreting b as a
// little-endian value, and reducing it mod the group order. // little-endian value, and reducing it mod the group order.
sc_set_bytes_wide :: proc(sc: ^Scalar, b: []byte) { sc_set_bytes_wide :: proc(sc: ^Scalar, b: []byte) {
if len(b) != WIDE_SCALAR_SIZE { ensure(len(b) == WIDE_SCALAR_SIZE, "crypto/ristretto255: invalid wide input size")
panic("crypto/ristretto255: invalid wide input size")
}
b_ := (^[WIDE_SCALAR_SIZE]byte)(raw_data(b)) b_ := (^[WIDE_SCALAR_SIZE]byte)(raw_data(b))
grp.sc_set_bytes_wide(sc, b_) grp.sc_set_bytes_wide(sc, b_)
@@ -52,9 +50,7 @@ sc_set_bytes_wide :: proc(sc: ^Scalar, b: []byte) {
// sc_bytes sets dst to the canonical encoding of sc. // sc_bytes sets dst to the canonical encoding of sc.
sc_bytes :: proc(sc: ^Scalar, dst: []byte) { sc_bytes :: proc(sc: ^Scalar, dst: []byte) {
if len(dst) != SCALAR_SIZE { ensure(len(dst) == SCALAR_SIZE, "crypto/ristretto255: invalid destination size")
panic("crypto/ristretto255: invalid destination size")
}
grp.sc_bytes(dst, sc) grp.sc_bytes(dst, sc)
} }
+4 -7
View File
@@ -158,7 +158,7 @@ _init :: proc(ctx: ^$T) {
// update adds more data to the Context. // update adds more data to the Context.
update :: proc(ctx: ^$T, data: []byte) { update :: proc(ctx: ^$T, data: []byte) {
assert(ctx.is_initialized) ensure(ctx.is_initialized)
when T == Context_256 { when T == Context_256 {
CURR_BLOCK_SIZE :: BLOCK_SIZE_256 CURR_BLOCK_SIZE :: BLOCK_SIZE_256
@@ -194,11 +194,8 @@ update :: proc(ctx: ^$T, data: []byte) {
// Iff finalize_clone is set, final will work on a copy of the Context, // Iff finalize_clone is set, final will work on a copy of the Context,
// which is useful for for calculating rolling digests. // which is useful for for calculating rolling digests.
final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) { final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) {
assert(ctx.is_initialized) ensure(ctx.is_initialized)
ensure(len(hash) * 8 >= ctx.md_bits, "crypto/sha2: invalid destination digest size")
if len(hash) * 8 < ctx.md_bits {
panic("crypto/sha2: invalid destination digest size")
}
ctx := ctx ctx := ctx
if finalize_clone { if finalize_clone {
@@ -238,7 +235,7 @@ final :: proc(ctx: ^$T, hash: []byte, finalize_clone: bool = false) {
endian.unchecked_put_u64be(pad[8:], length_lo) endian.unchecked_put_u64be(pad[8:], length_lo)
update(ctx, pad[0:16]) update(ctx, pad[0:16])
} }
assert(ctx.bitlength == 0) assert(ctx.bitlength == 0) // Check for bugs
when T == Context_256 { when T == Context_256 {
for i := 0; i < ctx.md_bits / 32; i += 1 { for i := 0; i < ctx.md_bits / 32; i += 1 {
+6 -11
View File
@@ -219,18 +219,14 @@ verify_4_8 :: proc {
*/ */
init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) { init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) {
if len(key) != KEY_SIZE { ensure(len(key) == KEY_SIZE,"crypto/siphash; invalid key size")
panic("crypto/siphash; invalid key size")
}
ctx.c_rounds = c_rounds ctx.c_rounds = c_rounds
ctx.d_rounds = d_rounds ctx.d_rounds = d_rounds
is_valid_setting := is_valid_setting :=
(ctx.c_rounds == 1 && ctx.d_rounds == 3) || (ctx.c_rounds == 1 && ctx.d_rounds == 3) ||
(ctx.c_rounds == 2 && ctx.d_rounds == 4) || (ctx.c_rounds == 2 && ctx.d_rounds == 4) ||
(ctx.c_rounds == 4 && ctx.d_rounds == 8) (ctx.c_rounds == 4 && ctx.d_rounds == 8)
if !is_valid_setting { ensure(is_valid_setting, "crypto/siphash: incorrect rounds set up")
panic("crypto/siphash: incorrect rounds set up")
}
ctx.k0 = endian.unchecked_get_u64le(key[:8]) ctx.k0 = endian.unchecked_get_u64le(key[:8])
ctx.k1 = endian.unchecked_get_u64le(key[8:]) ctx.k1 = endian.unchecked_get_u64le(key[8:])
ctx.v0 = 0x736f6d6570736575 ~ ctx.k0 ctx.v0 = 0x736f6d6570736575 ~ ctx.k0
@@ -245,7 +241,7 @@ init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) {
} }
update :: proc(ctx: ^Context, data: []byte) { update :: proc(ctx: ^Context, data: []byte) {
assert(ctx.is_initialized, "crypto/siphash: context is not initialized") ensure(ctx.is_initialized)
data := data data := data
ctx.total_length += len(data) ctx.total_length += len(data)
@@ -269,7 +265,7 @@ update :: proc(ctx: ^Context, data: []byte) {
} }
final :: proc(ctx: ^Context, dst: ^u64) { final :: proc(ctx: ^Context, dst: ^u64) {
assert(ctx.is_initialized, "crypto/siphash: context is not initialized") ensure(ctx.is_initialized)
tmp: [BLOCK_SIZE]byte tmp: [BLOCK_SIZE]byte
copy(tmp[:], ctx.buf[:ctx.last_block]) copy(tmp[:], ctx.buf[:ctx.last_block])
@@ -336,9 +332,8 @@ _get_byte :: #force_inline proc "contextless" (byte_num: byte, into: u64) -> byt
@(private) @(private)
_collect_output :: #force_inline proc(dst: []byte, hash: u64) { _collect_output :: #force_inline proc(dst: []byte, hash: u64) {
if len(dst) < DIGEST_SIZE { ensure(len(dst) >= DIGEST_SIZE, "crypto/siphash: invalid tag size")
panic("crypto/siphash: invalid tag size")
}
dst[0] = _get_byte(7, hash) dst[0] = _get_byte(7, hash)
dst[1] = _get_byte(6, hash) dst[1] = _get_byte(6, hash)
dst[2] = _get_byte(5, hash) dst[2] = _get_byte(5, hash)
+4 -7
View File
@@ -53,7 +53,7 @@ init :: proc(ctx: ^Context) {
// update adds more data to the Context. // update adds more data to the Context.
update :: proc(ctx: ^Context, data: []byte) { update :: proc(ctx: ^Context, data: []byte) {
assert(ctx.is_initialized) ensure(ctx.is_initialized)
data := data data := data
ctx.length += u64(len(data)) ctx.length += u64(len(data))
@@ -83,11 +83,8 @@ update :: proc(ctx: ^Context, data: []byte) {
// Iff finalize_clone is set, final will work on a copy of the Context, // Iff finalize_clone is set, final will work on a copy of the Context,
// which is useful for for calculating rolling digests. // which is useful for for calculating rolling digests.
final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) { final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
assert(ctx.is_initialized) ensure(ctx.is_initialized)
ensure(len(hash) >= DIGEST_SIZE, "crypto/sm3: invalid destination digest size")
if len(hash) < DIGEST_SIZE {
panic("crypto/sm3: invalid destination digest size")
}
ctx := ctx ctx := ctx
if finalize_clone { if finalize_clone {
@@ -110,7 +107,7 @@ final :: proc(ctx: ^Context, hash: []byte, finalize_clone: bool = false) {
length <<= 3 length <<= 3
endian.unchecked_put_u64be(pad[:], length) endian.unchecked_put_u64be(pad[:], length)
update(ctx, pad[0:8]) update(ctx, pad[0:8])
assert(ctx.bitlength == 0) assert(ctx.bitlength == 0) // Check for bugs
for i := 0; i < DIGEST_SIZE / 4; i += 1 { for i := 0; i < DIGEST_SIZE / 4; i += 1 {
endian.unchecked_put_u32be(hash[i * 4:], ctx.state[i]) endian.unchecked_put_u32be(hash[i * 4:], ctx.state[i])
+3 -9
View File
@@ -101,15 +101,9 @@ _scalarmult :: proc "contextless" (out, scalar, point: ^[32]byte) {
// scalarmult "multiplies" the provided scalar and point, and writes the // scalarmult "multiplies" the provided scalar and point, and writes the
// resulting point to dst. // resulting point to dst.
scalarmult :: proc(dst, scalar, point: []byte) { scalarmult :: proc(dst, scalar, point: []byte) {
if len(scalar) != SCALAR_SIZE { ensure(len(scalar) == SCALAR_SIZE, "crypto/x25519: invalid scalar size")
panic("crypto/x25519: invalid scalar size") ensure(len(point) == POINT_SIZE, "crypto/x25519: invalid point size")
} ensure(len(dst) == POINT_SIZE, "crypto/x25519: invalid destination point size")
if len(point) != POINT_SIZE {
panic("crypto/x25519: invalid point size")
}
if len(dst) != POINT_SIZE {
panic("crypto/x25519: invalid destination point size")
}
// "clamp" the scalar // "clamp" the scalar
e: [32]byte = --- e: [32]byte = ---
+3 -9
View File
@@ -127,15 +127,9 @@ _scalarmult :: proc "contextless" (out, scalar, point: ^[56]byte) {
// scalarmult "multiplies" the provided scalar and point, and writes the // scalarmult "multiplies" the provided scalar and point, and writes the
// resulting point to dst. // resulting point to dst.
scalarmult :: proc(dst, scalar, point: []byte) { scalarmult :: proc(dst, scalar, point: []byte) {
if len(scalar) != SCALAR_SIZE { ensure(len(scalar) == SCALAR_SIZE, "crypto/x448: invalid scalar size")
panic("crypto/x448: invalid scalar size") ensure(len(point) == POINT_SIZE, "crypto/x448: invalid point size")
} ensure(len(dst) == POINT_SIZE, "crypto/x448: invalid destination point size")
if len(point) != POINT_SIZE {
panic("crypto/x448: invalid point size")
}
if len(dst) != POINT_SIZE {
panic("crypto/x448: invalid destination point size")
}
// "clamp" the scalar // "clamp" the scalar
e: [56]byte = --- e: [56]byte = ---