From: Chris Duncan Date: Fri, 21 Aug 2026 21:38:41 +0000 (-0700) Subject: Overload conditional move of FieldElements for cleaner memory access. X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=99e74e55196b11874a177ea8b4c517a065d3df99;p=nano25519.git Overload conditional move of FieldElements for cleaner memory access. --- diff --git a/src/assembly/fe.ts b/src/assembly/fe.ts index 06abed1..a0c4e7f 100644 --- a/src/assembly/fe.ts +++ b/src/assembly/fe.ts @@ -76,19 +76,32 @@ export function fe_add (h: FieldElement, f: FieldElement, g: FieldElement): void /** * Conditionally copy values from one FieldElement to another. * - * @param f FieldElement destination - * @param g FieldElement source - * @param b Copy `g` into `f` if 1, copy `f` into `f` if 0 + * @param {usize} f FieldElement destination + * @param {usize} g FieldElement source + * @param {u64} b Copy `g` into `f` if 1, copy `f` into `f` if 0 */ //@ts-expect-error @inline -export function fe_cmov (f: usize, g: usize, b: u64): void { +export function fe_memcmov (f: usize, g: usize, b: u64): void { const c = v128.splat(0 - b) v128.store(f, v128.bitselect(v128.load(g), v128.load(f, 0), c)) v128.store(f, v128.bitselect(v128.load(g, 16), v128.load(f, 16), c), 16) v128.store_lane(f, v128.bitselect(v128.load(g, 32), v128.load(f, 32), c), 0, 32) } +/** + * Conditionally copy values from one FieldElement to another. + * + * @param {FieldElement} f destination + * @param {FieldElement} g source + * @param {u64} b Copy `g` into `f` if 1, copy `f` into `f` if 0 + */ +//@ts-expect-error +@inline +export function fe_cmov (f: FieldElement, g: FieldElement, b: u64): void { + fe_memcmov(changetype(f), changetype(g), b) +} + /** * Copy values from one FieldElement to another. * diff --git a/src/assembly/ge.ts b/src/assembly/ge.ts index 380245b..e7f5fc8 100644 --- a/src/assembly/ge.ts +++ b/src/assembly/ge.ts @@ -19,16 +19,16 @@ import { base } from './base' import { base2 } from './base2' import { ed25519_d, fe_sqrtm1 } from './constants' -import { FieldElement, fe, fe_1, fe_add, fe_cmov, fe_frombytes, fe_isnegative, fe_iszero, fe_memcopy, fe_memneg, fe_mul, fe_neg, fe_pow22523, fe_sq, fe_sub } from './fe' +import { FieldElement, fe, fe_1, fe_add, fe_cmov, fe_frombytes, fe_isnegative, fe_iszero, fe_memcmov, fe_memcopy, fe_memneg, fe_mul, fe_neg, fe_pow22523, fe_sq, fe_sub } from './fe' import { ge_add_cached, ge_add_precomp, ge_cached, ge_p1p1, ge_p1p1_to_p2, ge_p1p1_to_p3, ge_p2, ge_p2_0, ge_p2_dbl, ge_p2_to_p3, ge_p3, ge_p3_0, ge_p3_dbl, ge_p3_to_cached, ge_p3_tobytes, ge_precomp, ge_precomp_0, ge_sub_cached, ge_sub_precomp } from './p' import { equal, negative } from './utils' //@ts-expect-error @inline function ge_cmov (t: ge_precomp, u: usize, b: u8): void { - fe_cmov(changetype(t.yplusx), u, b) - fe_cmov(changetype(t.yminusx), u + 48, b) - fe_cmov(changetype(t.xy2d), u + 96, b) + fe_memcmov(changetype(t.yplusx), u, b) + fe_memcmov(changetype(t.yminusx), u + 48, b) + fe_memcmov(changetype(t.xy2d), u + 96, b) } const minust = changetype(new StaticArray(36)) @@ -130,10 +130,10 @@ export function ge_frombytes (h: ge_p3, s: StaticArray): i32 { has_m_root = fe_iszero(m_root_check) has_p_root = fe_iszero(p_root_check) fe_mul(x_sqrtm1, h.X, fe_sqrtm1) /* x*sqrt(-1) */ - fe_cmov(changetype(h.X), changetype(x_sqrtm1), 1 - has_m_root) + fe_cmov(h.X, x_sqrtm1, 1 - has_m_root) fe_neg(negx, h.X) - fe_cmov(changetype(h.X), changetype(negx), fe_isnegative(h.X) ^ (s[31] >> 7)) + fe_cmov(h.X, negx, fe_isnegative(h.X) ^ (s[31] >> 7)) fe_mul(h.T, h.X, h.Y) return i32(has_m_root | has_p_root) - 1