From ff13ee3281ef36632ea3d5f5e1bb7de835783b1a Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Fri, 12 Jul 2024 17:31:02 +0900 Subject: [PATCH] core/crypto: Enforce aliasing restrictions --- core/crypto/aes/aes_ctr.odin | 8 +++++--- core/crypto/aes/aes_gcm.odin | 7 +++++++ core/crypto/chacha20/chacha20.odin | 8 +++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/core/crypto/aes/aes_ctr.odin b/core/crypto/aes/aes_ctr.odin index 1821a7bdf..de88a0c12 100644 --- a/core/crypto/aes/aes_ctr.odin +++ b/core/crypto/aes/aes_ctr.odin @@ -1,5 +1,6 @@ package aes +import "core:bytes" import "core:crypto/_aes/ct64" import "core:encoding/endian" import "core:math/bits" @@ -37,14 +38,15 @@ init_ctr :: proc(ctx: ^Context_CTR, key, iv: []byte, impl := Implementation.Hard xor_bytes_ctr :: proc(ctx: ^Context_CTR, dst, src: []byte) { assert(ctx._is_initialized) - // TODO: Enforcing that dst and src alias exactly or not at all - // is a good idea, though odd aliasing should be extremely uncommon. - src, dst := src, dst if dst_len := len(dst); dst_len < len(src) { src = src[:dst_len] } + if bytes.alias_inexactly(dst, src) { + panic("crypto/aes: dst and src alias inexactly") + } + for remaining := len(src); remaining > 0; { // Process multiple blocks at once if ctx._off == BLOCK_SIZE { diff --git a/core/crypto/aes/aes_gcm.odin b/core/crypto/aes/aes_gcm.odin index 66ef48db2..e097e0011 100644 --- a/core/crypto/aes/aes_gcm.odin +++ b/core/crypto/aes/aes_gcm.odin @@ -1,5 +1,6 @@ package aes +import "core:bytes" import "core:crypto" import "core:crypto/_aes" import "core:crypto/_aes/ct64" @@ -39,6 +40,9 @@ seal_gcm :: proc(ctx: ^Context_GCM, dst, tag, nonce, aad, plaintext: []byte) { if len(dst) != len(plaintext) { panic("crypto/aes: invalid destination ciphertext size") } + 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 { gcm_seal_hw(&impl, dst, tag, nonce, aad, plaintext) @@ -73,6 +77,9 @@ open_gcm :: proc(ctx: ^Context_GCM, dst, nonce, aad, ciphertext, tag: []byte) -> if len(dst) != len(ciphertext) { panic("crypto/aes: invalid destination plaintext size") } + 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 { return gcm_open_hw(&impl, dst, nonce, aad, ciphertext, tag) diff --git a/core/crypto/chacha20/chacha20.odin b/core/crypto/chacha20/chacha20.odin index 7f0950d03..73d3e1ea2 100644 --- a/core/crypto/chacha20/chacha20.odin +++ b/core/crypto/chacha20/chacha20.odin @@ -7,6 +7,7 @@ See: */ package chacha20 +import "core:bytes" import "core:encoding/endian" import "core:math/bits" import "core:mem" @@ -121,14 +122,15 @@ seek :: proc(ctx: ^Context, block_nr: u64) { xor_bytes :: proc(ctx: ^Context, dst, src: []byte) { assert(ctx._is_initialized) - // TODO: Enforcing that dst and src alias exactly or not at all - // is a good idea, though odd aliasing should be extremely uncommon. - src, dst := src, dst if dst_len := len(dst); dst_len < len(src) { src = src[:dst_len] } + if bytes.alias_inexactly(dst, src) { + panic("crypto/chacha20: dst and src alias inexactly") + } + for remaining := len(src); remaining > 0; { // Process multiple blocks at once if ctx._off == _BLOCK_SIZE {