aboutsummaryrefslogtreecommitdiff
path: root/core/crypto/_subtle
diff options
context:
space:
mode:
authorYawning Angel <yawning@schwanenlied.me>2026-01-02 23:59:38 +0900
committerYawning Angel <yawning@schwanenlied.me>2026-01-28 22:20:03 +0900
commit6bbd060352dc0aba41594362c9b82bda636fedde (patch)
treedf58032e0363da7eec872ab9ed4e7070d642887a /core/crypto/_subtle
parent429e8a46dba047833087f22bddd8d03519929258 (diff)
core/crypto/_subtle: Refactor out common helpers
Diffstat (limited to 'core/crypto/_subtle')
-rw-r--r--core/crypto/_subtle/subtle.odin42
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
+}