nx_h2c_p256.nx
buildroot/runtime/hub/nx_h2c_p256.nx
about
nx_h2c_p256.nx -- RFC 9380 hash-to-curve for P-256.
Ciphersuite: P256_XMD:SHA-256_SSWU_RO_ (RFC 9380 §8.2)
Provides deterministic random-oracle mapping from arbitrary bytes
to a point on the NIST P-256 curve. Used by V-MODAUTH-1b OPRF
(RFC 9497) which is the registration primitive of OPAQUE PAKE.
CARDINAL TRACEABILITY: composes existing substrate primitives per
"avoid duplicate primitives" cardinal:
nx_u256 (8-limb LE u256 big-int)
nx_p256_field (F_p add/sub/neg)
nx_p256_field_mul (F_p mul + sq)
nx_p256_field_inv (F_p Fermat inverse)
nx_p256_point (P-256 affine + projective)
nx_p256_point_add (point add for final summation)
sha256 (SHA-256 one-shot digest)
COMPOSED BY:
hub/nx_voprf.nx (V-MODAUTH-1b OPRF protocol)
hub/nx_opaque_pake.nx (V-MODAUTH-2; indirectly via voprf)
SPEC REFERENCES (every implementation choice cites a section):
RFC 9380 §3 hash_to_curve composition
RFC 9380 §5.3 hash_to_field
RFC 9380 §5.4.1 expand_message_xmd
RFC 9380 §8.2 P256_XMD:SHA-256_SSWU_RO_ ciphersuite params
RFC 9380 §F.2 Simplified SWU for AB == 0 (NOT applicable here)
RFC 9380 §F.2.1.2 Simplified SWU for AB != 0 (THIS one for P-256)
RFC 9380 §I.1 P-256 SSWU constants Z, A, B, c1, c2
RFC 9380 §J.1.1 P-256 hash-to-curve TEST VECTORS
WINNER-TIER: BASELINE-A provisional pending RFC 9380 §J.1.1 test
vector verification by bench/nx_h2c_p256_smoke.sh.
INCUMBENTS: voprf-rs (Rust; rustcrypto), filippo.io/edwards25519
(Go; primarily Ed25519 but their P-256 is similar),
hash_to_curve.py (RFC reference impl in Python)
NUMBERS: measured client-side cost per hash_to_curve call:
pending bench post-smoke
GAP: no clear_cofactor (P-256 cofactor = 1; identity);
dependencies 8 imports · 3 importers
imports: nx_syscalls.nxnx_u256.nxnx_p256_field.nxnx_p256_field_mul.nxnx_p256_field_inv.nxnx_p256_point.nxnx_p256_point_add.nxsha256.nx
imported by: nx_opaque_core.nxnx_opaque_pake.nxnx_voprf.nx
structs
| none |
consts
| 65 | const NX_H2C_OK: i64 = 0 |
| 66 | const NX_H2C_BAD_INPUT: i64 = 1300 |
| 67 | const NX_H2C_BUF_OVERFLOW: i64 = 1301 |
| 68 | const NX_H2C_DST_TOO_LONG: i64 = 1302 |
| 69 | const NX_H2C_LEN_TOO_LONG: i64 = 1303 |
| 70 | const NX_H2C_SQRT_NOT_QR: i64 = 1304 // unreachable for RO mode; defensive |
| 71 | const NX_H2C_POINT_NOT_ON_CURVE: i64 = 1305 // post-condition violation |
| 85 | const NX_H2C_B_IN_BYTES: i64 = 32 |
| 86 | const NX_H2C_S_IN_BYTES: i64 = 64 |
| 87 | const NX_H2C_L: i64 = 48 |
| 88 | const NX_H2C_FIELD_BYTES: i64 = 32 // P-256 field element = 32 bytes |
| 89 | const NX_H2C_MAX_DST_LEN: i64 = 255 // RFC 9380 §5.4.3 hard limit |
| 90 | const NX_H2C_MAX_MSG_LEN: i64 = 8192 // sanity cap; OPRF inputs are short |
| 91 | const NX_H2C_MAX_OUT_BYTES: i64 = 8160 // 255 * 32 (XMD upper bound) |
functions
| 101 | func _h2c_i2osp_1(x: i64, out: *u8) -> i64 called by 1: nx_h2c_expand_message_xmd_sha256 |
| 108 | func _h2c_i2osp_2(x: i64, out: *u8) -> i64 called by 1: nx_h2c_expand_message_xmd_sha256 |
| 140 | func nx_h2c_expand_message_xmd_sha256( called by 2: nx_h2c_hash_to_field_p256nx_opq_hash_to_scalar calls 3: sys_mmap_h2c_i2osp_1_h2c_i2osp_2 |
| 296 | func _h2c_load_r_constant(out: *i64) -> i64 called by 1: _h2c_reduce_48be_mod_p |
| 325 | func _h2c_reduce_48be_mod_p(bytes_48: *u8, out_field: *i64) -> i64 called by 1: nx_h2c_hash_to_field_p256 calls 9: sys_mmapu256_load_bep256_field_load_pu256_cmpu256_sub_with_borrowu256_copy+3 |
| 364 | func nx_h2c_hash_to_field_p256( called by 1: nx_h2c_hash_to_curve_p256 calls 3: sys_mmapnx_h2c_expand_message_xmd_sha256_h2c_reduce_48be_mod_p |
| 407 | func _h2c_load_A_neg3(out: *i64) -> i64 |
| 422 | func _h2c_load_B(out: *i64) -> i64 |
| 436 | func _h2c_load_Z_neg10(out: *i64) -> i64 called by 1: _h2c_map_to_curve_sswu_p256 |
| 456 | func _h2c_pow_p(out: *i64, base: *i64, exp: *i64) -> i64 |
| 485 | func _h2c_load_p_plus_1_div_4(out: *i64) -> i64 called by 1: _h2c_sqrt_3mod4 |
| 501 | func _h2c_sqrt_3mod4(out: *i64, a: *i64) -> i64 called by 2: _h2c_load_c2nx_voprf_deserialize_element calls 3: u256_alloc_h2c_load_p_plus_1_div_4_h2c_pow_p |
| 535 | func _h2c_load_p_minus_3_div_4(out: *i64) -> i64 called by 1: _h2c_sqrt_ratio_3mod4 |
| 557 | func _h2c_load_c2(out: *i64) -> i64 |
| 564 | func _h2c_sqrt_ratio_3mod4(out_y: *i64, u: *i64, v: *i64) -> i64 |
| 598 | func _h2c_sgn0(x: *i64) -> i64 called by 1: _h2c_map_to_curve_sswu_p256 |
| 635 | func _h2c_map_to_curve_sswu_p256(u: *i64, out_x: *i64, out_y: *i64) -> i64 |
| 710 | func nx_h2c_hash_to_curve_p256( |