diff options
| author | Yawning Angel <yawning@schwanenlied.me> | 2026-01-02 23:59:38 +0900 |
|---|---|---|
| committer | Yawning Angel <yawning@schwanenlied.me> | 2026-01-28 22:20:03 +0900 |
| commit | 6bbd060352dc0aba41594362c9b82bda636fedde (patch) | |
| tree | df58032e0363da7eec872ab9ed4e7070d642887a /core/crypto/_subtle | |
| parent | 429e8a46dba047833087f22bddd8d03519929258 (diff) | |
core/crypto/_subtle: Refactor out common helpers
Diffstat (limited to 'core/crypto/_subtle')
| -rw-r--r-- | core/crypto/_subtle/subtle.odin | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/core/crypto/_subtle/subtle.odin b/core/crypto/_subtle/subtle.odin new file mode 100644 index 000000000..89328072c --- /dev/null +++ b/core/crypto/_subtle/subtle.odin @@ -0,0 +1,42 @@ +/* +Various useful bit operations in constant time. +*/ +package _subtle + +import "core:math/bits" + +// byte_eq returns 1 iff a == b, 0 otherwise. +@(optimization_mode="none") +byte_eq :: proc "contextless" (a, b: byte) -> int { + v := a ~ b + + // v == 0 iff a == b. The subtraction will underflow, setting the + // sign bit, which will get returned. + return int((u32(v)-1) >> 31) +} + +// u64_eq returns 1 iff a == b, 0 otherwise. +@(optimization_mode="none") +u64_eq :: proc "contextless" (a, b: u64) -> u64 { + _, borrow := bits.sub_u64(0, a ~ b, 0) + return (~borrow) & 1 +} + +eq :: proc { + byte_eq, + u64_eq, +} + +// u64_is_zero returns 1 iff a == 0, 0 otherwise. +@(optimization_mode="none") +u64_is_zero :: proc "contextless" (a: u64) -> u64 { + _, borrow := bits.sub_u64(a, 1, 0) + return borrow +} + +// u64_is_non_zero returns 1 iff a != 0, 0 otherwise. +@(optimization_mode="none") +u64_is_non_zero :: proc "contextless" (a: u64) -> u64 { + is_zero := u64_is_zero(a) + return (~is_zero) & 1 +} |