code wiki / (root) / nx_p256_ecdh.nx

nx_p256_ecdh.nx

buildroot/runtime/nx_p256_ecdh.nx

5560 B144 linesdepth 9pulls 14 transitivereach 587 importersview sourcekind librarytopic p256
docsdependenciesstructsconstsfunctions

about

nx_p256_ecdh.nx -- ECDH key exchange on P-256 (secp256r1) for the TLS 1.3 key_share path (browser arc rung B4-P256-KEYSHARE). The P-256 stack (field, point, scalar_mul) shipped for ECDSA cert VERIFICATION; this module composes the same primitives into the ECDHE role so the ClientHello can carry a secp256r1 KeyShareEntry next to the X25519 one. Servers that insist on P-256 (the AWS- fronted class behind the B2-HTTPBIN-CH alert) then never need a HelloRetryRequest: they just pick our P-256 share. Public API: p256_ecdh_derive_priv(seed32, out_priv32) -> verdict Domain-separated ephemeral: SHA-256("NISHI-TLS13-P256-ECDH-V1" || seed32), reduced mod n, forced nonzero. Lets the session grow a P-256 keypair from the caller's existing 32 random bytes without changing the session-new entropy contract. p256_ecdh_pub(priv32, out_pub65) -> verdict out = 0x04 || X || Y (RFC 8446 wire form for secp256r1). p256_ecdh_shared(priv32, peer_pub65, peer_len, out_shared32) -> verdict Validates peer point (format, on-curve, not-infinity) then writes the x-coordinate of priv * peer as the 32-byte shared secret (RFC 8446 section 7.4.2). Variable-time scalar_mul note: the scalar here is an EPHEMERAL per-session secret, unlike ECDSA verify's public scalars. The shipped double-and-add is variable-time; constant-time ladder is a named follow-up rung (same lane as the x25519 ladder), accepted for B4 because the scalar lives for one handshake. KAT: RFC 5903 section 8.1 vectors in nx_p256_keyshare_test.nx (vectors re-read from rfc-editor.org 2026-06-10, not from memory). license_tier: INDEPENDENT_REDERIVE genealogy_id: international-research-sources/ietf/rfc_5903 + ietf/rfc_8446 lineage_id: nishi_p256_ecdh_q10

dependencies 8 imports · 11 importers

nx_syscalls.nx nx_sha256.nx nx_u256.nx nx_p256_field.nx nx_p256_point.nx nx_p256_point_add.nx nx_p256_scalar_mul.nx nx_p256_modn.nx nx_p256_ecdh.nx nx_mtls_ecdsa.nx nx_p256_keyshare_test.nx nx_tls12_client.nx nx_tls12_client_session.nx nx_tls12_mutant.nx nx_tls12_req.nx nx_tls13_client_session.nx nx_tls13_client_session_recv_sh.nx nx_tls13_clientauth_ecdsa.nx nx_tls13_server_session.nx

diagram shows first 10 each side; +0 more imports, +1 more importers in the complete lists below.

imports: nx_syscalls.nxnx_sha256.nxnx_u256.nxnx_p256_field.nxnx_p256_point.nxnx_p256_point_add.nxnx_p256_scalar_mul.nxnx_p256_modn.nx

imported by: nx_mtls_ecdsa.nxnx_p256_keyshare_test.nxnx_tls12_client.nxnx_tls12_client_session.nxnx_tls12_mutant.nxnx_tls12_req.nxnx_tls13_client_session.nxnx_tls13_client_session_recv_sh.nxnx_tls13_clientauth_ecdsa.nxnx_tls13_server_session.nxnx_tls13_server_session_derive_hs.nx

structs

none

consts

46const NX_P256_ECDH_OK: i64 = 1
47const NX_P256_ECDH_BAD_PRIV: i64 = 2 // scalar zero or >= n
48const NX_P256_ECDH_BAD_POINT: i64 = 3 // format/on-curve/infinity reject
49const NX_P256_ECDH_VERDICT_N: i64 = 4

functions

51func nx_p256_ecdh_verdict_is_valid(v: i64) -> i64
59func _p256_ecdh_load_scalar(priv32: *u8, out_k: *i64) -> i64
72func p256_ecdh_derive_priv(seed32: *u8, out_priv32: *u8) -> i64
93func p256_ecdh_pub(priv32: *u8, out_pub65: *u8) -> i64
115func p256_ecdh_shared(