mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-12 06:18:39 +00:00
core/crypto/_subtle: Refactor out common helpers
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package _edwards25519
|
||||
|
||||
import field "core:crypto/_fiat/field_scalar25519"
|
||||
import "core:math/bits"
|
||||
import subtle "core:crypto/_subtle"
|
||||
import "core:mem"
|
||||
|
||||
// GE_BASEPOINT_TABLE is 1 * G, ... 15 * G, in precomputed format.
|
||||
@@ -281,8 +281,8 @@ mul_tbl_add :: proc "contextless" (
|
||||
{2, 0, 0, 0, 0}, // z * 2
|
||||
}
|
||||
for i := u64(1); i < 16; i = i + 1 {
|
||||
_, ctrl := bits.sub_u64(0, (i ~ idx), 0)
|
||||
ge_addend_conditional_assign(tmp_addend, &tbl[i - 1], int(~ctrl) & 1)
|
||||
ctrl := subtle.eq(i, idx)
|
||||
ge_addend_conditional_assign(tmp_addend, &tbl[i - 1], int(ctrl))
|
||||
}
|
||||
ge_add_addend(ge, ge, tmp_addend, tmp_add)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package field_scalar25519
|
||||
|
||||
import subtle "core:crypto/_subtle"
|
||||
import "core:encoding/endian"
|
||||
import "core:math/bits"
|
||||
import "core:mem"
|
||||
@@ -121,13 +122,11 @@ fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) ->
|
||||
tmp: Montgomery_Domain_Field_Element
|
||||
fe_sub(&tmp, arg1, arg2)
|
||||
|
||||
// This will only underflow iff arg1 == arg2, and we return the borrow,
|
||||
// which will be 1.
|
||||
_, borrow := bits.sub_u64(fe_non_zero(&tmp), 1, 0)
|
||||
is_eq := subtle.eq(fe_non_zero(&tmp), 0)
|
||||
|
||||
fe_clear(&tmp)
|
||||
|
||||
return int(borrow)
|
||||
return int(is_eq)
|
||||
}
|
||||
|
||||
fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) {
|
||||
|
||||
42
core/crypto/_subtle/subtle.odin
Normal file
42
core/crypto/_subtle/subtle.odin
Normal file
@@ -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
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
package crypto
|
||||
|
||||
import "base:runtime"
|
||||
import subtle "core:crypto/_subtle"
|
||||
import "core:mem"
|
||||
|
||||
// HAS_RAND_BYTES is true iff the runtime provides a cryptographic
|
||||
@@ -44,7 +45,17 @@ compare_byte_ptrs_constant_time :: proc "contextless" (a, b: ^byte, n: int) -> i
|
||||
|
||||
// After the loop, v == 0 iff a == b. The subtraction will underflow
|
||||
// iff v == 0, setting the sign-bit, which gets returned.
|
||||
return int((u32(v)-1) >> 31)
|
||||
return subtle.eq(0, v)
|
||||
}
|
||||
|
||||
// is_zero_constant_time returns 1 iff b is all 0s, 0 otherwise.
|
||||
is_zero_constant_time :: proc "contextless" (b: []byte) -> int {
|
||||
v: byte
|
||||
for b_ in b {
|
||||
v |= b_
|
||||
}
|
||||
|
||||
return subtle.byte_eq(0, v)
|
||||
}
|
||||
|
||||
// rand_bytes fills the dst buffer with cryptographic entropy taken from
|
||||
|
||||
Reference in New Issue
Block a user