xref: /openbsd/lib/libcrypto/bn/s2n_bignum.h (revision 78843f4e)
13afee70eSjsing // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2*78843f4eSjsing //
3*78843f4eSjsing // Permission to use, copy, modify, and/or distribute this software for any
4*78843f4eSjsing // purpose with or without fee is hereby granted, provided that the above
5*78843f4eSjsing // copyright notice and this permission notice appear in all copies.
6*78843f4eSjsing //
7*78843f4eSjsing // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*78843f4eSjsing // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*78843f4eSjsing // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10*78843f4eSjsing // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*78843f4eSjsing // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12*78843f4eSjsing // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13*78843f4eSjsing // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
143afee70eSjsing 
153afee70eSjsing // ----------------------------------------------------------------------------
163afee70eSjsing // C prototypes for s2n-bignum functions, so you can use them in C programs via
173afee70eSjsing //
183afee70eSjsing //  #include "s2n-bignum.h"
193afee70eSjsing //
203afee70eSjsing // The functions are listed in alphabetical order with a brief description
213afee70eSjsing // in comments for each one. For more detailed documentation see the comment
223afee70eSjsing // banner at the top of the corresponding assembly (.S) file, and
233afee70eSjsing // for the last word in what properties it satisfies see the spec in the
243afee70eSjsing // formal proof (the .ml file in the architecture-specific directory).
253afee70eSjsing //
263afee70eSjsing // For some functions there are additional variants with names ending in
273afee70eSjsing // "_alt". These have the same core mathematical functionality as their
283afee70eSjsing // non-"alt" versions, but can be better suited to some microarchitectures:
293afee70eSjsing //
303afee70eSjsing //      - On x86, the "_alt" forms avoid BMI and ADX instruction set
313afee70eSjsing //        extensions, so will run on any x86_64 machine, even older ones
323afee70eSjsing //
333afee70eSjsing //      - On ARM, the "_alt" forms target machines with higher multiplier
343afee70eSjsing //        throughput, generally offering higher performance there.
353afee70eSjsing // ----------------------------------------------------------------------------
363afee70eSjsing 
373afee70eSjsing // Add, z := x + y
383afee70eSjsing // Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
393afee70eSjsing extern uint64_t bignum_add (uint64_t p, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
403afee70eSjsing 
413afee70eSjsing // Add modulo p_25519, z := (x + y) mod p_25519, assuming x and y reduced
423afee70eSjsing // Inputs x[4], y[4]; output z[4]
433afee70eSjsing extern void bignum_add_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
443afee70eSjsing 
453afee70eSjsing // Add modulo p_256, z := (x + y) mod p_256, assuming x and y reduced
463afee70eSjsing // Inputs x[4], y[4]; output z[4]
473afee70eSjsing extern void bignum_add_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
483afee70eSjsing 
493afee70eSjsing // Add modulo p_256k1, z := (x + y) mod p_256k1, assuming x and y reduced
503afee70eSjsing // Inputs x[4], y[4]; output z[4]
513afee70eSjsing extern void bignum_add_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
523afee70eSjsing 
533afee70eSjsing // Add modulo p_384, z := (x + y) mod p_384, assuming x and y reduced
543afee70eSjsing // Inputs x[6], y[6]; output z[6]
553afee70eSjsing extern void bignum_add_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
563afee70eSjsing 
573afee70eSjsing // Add modulo p_521, z := (x + y) mod p_521, assuming x and y reduced
583afee70eSjsing // Inputs x[9], y[9]; output z[9]
593afee70eSjsing extern void bignum_add_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
603afee70eSjsing 
613afee70eSjsing // Compute "amontification" constant z :== 2^{128k} (congruent mod m)
623afee70eSjsing // Input m[k]; output z[k]; temporary buffer t[>=k]
633afee70eSjsing extern void bignum_amontifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
643afee70eSjsing 
653afee70eSjsing // Almost-Montgomery multiply, z :== (x * y / 2^{64k}) (congruent mod m)
663afee70eSjsing // Inputs x[k], y[k], m[k]; output z[k]
673afee70eSjsing extern void bignum_amontmul (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
683afee70eSjsing 
693afee70eSjsing // Almost-Montgomery reduce, z :== (x' / 2^{64p}) (congruent mod m)
703afee70eSjsing // Inputs x[n], m[k], p; output z[k]
713afee70eSjsing extern void bignum_amontredc (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t *m, uint64_t p);
723afee70eSjsing 
733afee70eSjsing // Almost-Montgomery square, z :== (x^2 / 2^{64k}) (congruent mod m)
743afee70eSjsing // Inputs x[k], m[k]; output z[k]
753afee70eSjsing extern void bignum_amontsqr (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
763afee70eSjsing 
773afee70eSjsing // Convert 4-digit (256-bit) bignum to/from big-endian form
783afee70eSjsing // Input x[4]; output z[4]
793afee70eSjsing extern void bignum_bigendian_4 (uint64_t z[static 4], uint64_t x[static 4]);
803afee70eSjsing 
813afee70eSjsing // Convert 6-digit (384-bit) bignum to/from big-endian form
823afee70eSjsing // Input x[6]; output z[6]
833afee70eSjsing extern void bignum_bigendian_6 (uint64_t z[static 6], uint64_t x[static 6]);
843afee70eSjsing 
853afee70eSjsing // Select bitfield starting at bit n with length l <= 64
863afee70eSjsing // Inputs x[k], n, l; output function return
873afee70eSjsing extern uint64_t bignum_bitfield (uint64_t k, uint64_t *x, uint64_t n, uint64_t l);
883afee70eSjsing 
893afee70eSjsing // Return size of bignum in bits
903afee70eSjsing // Input x[k]; output function return
913afee70eSjsing extern uint64_t bignum_bitsize (uint64_t k, uint64_t *x);
923afee70eSjsing 
933afee70eSjsing // Divide by a single (nonzero) word, z := x / m and return x mod m
943afee70eSjsing // Inputs x[n], m; outputs function return (remainder) and z[k]
953afee70eSjsing extern uint64_t bignum_cdiv (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t m);
963afee70eSjsing 
973afee70eSjsing // Divide by a single word, z := x / m when known to be exact
983afee70eSjsing // Inputs x[n], m; output z[k]
993afee70eSjsing extern void bignum_cdiv_exact (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t m);
1003afee70eSjsing 
1013afee70eSjsing // Count leading zero digits (64-bit words)
1023afee70eSjsing // Input x[k]; output function return
1033afee70eSjsing extern uint64_t bignum_cld (uint64_t k, uint64_t *x);
1043afee70eSjsing 
1053afee70eSjsing // Count leading zero bits
1063afee70eSjsing // Input x[k]; output function return
1073afee70eSjsing extern uint64_t bignum_clz (uint64_t k, uint64_t *x);
1083afee70eSjsing 
1093afee70eSjsing // Multiply-add with single-word multiplier, z := z + c * y
1103afee70eSjsing // Inputs c, y[n]; outputs function return (carry-out) and z[k]
1113afee70eSjsing extern uint64_t bignum_cmadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
1123afee70eSjsing 
1133afee70eSjsing // Negated multiply-add with single-word multiplier, z := z - c * y
1143afee70eSjsing // Inputs c, y[n]; outputs function return (negative carry-out) and z[k]
1153afee70eSjsing extern uint64_t bignum_cmnegadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
1163afee70eSjsing 
1173afee70eSjsing // Find modulus of bignum w.r.t. single nonzero word m, returning x mod m
1183afee70eSjsing // Input x[k], m; output function return
1193afee70eSjsing extern uint64_t bignum_cmod (uint64_t k, uint64_t *x, uint64_t m);
1203afee70eSjsing 
1213afee70eSjsing // Multiply by a single word, z := c * y
1223afee70eSjsing // Inputs c, y[n]; outputs function return (carry-out) and z[k]
1233afee70eSjsing extern uint64_t bignum_cmul (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
1243afee70eSjsing 
1253afee70eSjsing // Multiply by a single word modulo p_25519, z := (c * x) mod p_25519, assuming x reduced
1263afee70eSjsing // Inputs c, x[4]; output z[4]
1273afee70eSjsing extern void bignum_cmul_p25519 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
1283afee70eSjsing extern void bignum_cmul_p25519_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
1293afee70eSjsing 
1303afee70eSjsing // Multiply by a single word modulo p_256, z := (c * x) mod p_256, assuming x reduced
1313afee70eSjsing // Inputs c, x[4]; output z[4]
1323afee70eSjsing extern void bignum_cmul_p256 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
1333afee70eSjsing extern void bignum_cmul_p256_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
1343afee70eSjsing 
1353afee70eSjsing // Multiply by a single word modulo p_256k1, z := (c * x) mod p_256k1, assuming x reduced
1363afee70eSjsing // Inputs c, x[4]; output z[4]
1373afee70eSjsing extern void bignum_cmul_p256k1 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
1383afee70eSjsing extern void bignum_cmul_p256k1_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
1393afee70eSjsing 
1403afee70eSjsing // Multiply by a single word modulo p_384, z := (c * x) mod p_384, assuming x reduced
1413afee70eSjsing // Inputs c, x[6]; output z[6]
1423afee70eSjsing extern void bignum_cmul_p384 (uint64_t z[static 6], uint64_t c, uint64_t x[static 6]);
1433afee70eSjsing extern void bignum_cmul_p384_alt (uint64_t z[static 6], uint64_t c, uint64_t x[static 6]);
1443afee70eSjsing 
1453afee70eSjsing // Multiply by a single word modulo p_521, z := (c * x) mod p_521, assuming x reduced
1463afee70eSjsing // Inputs c, x[9]; output z[9]
1473afee70eSjsing extern void bignum_cmul_p521 (uint64_t z[static 9], uint64_t c, uint64_t x[static 9]);
1483afee70eSjsing extern void bignum_cmul_p521_alt (uint64_t z[static 9], uint64_t c, uint64_t x[static 9]);
1493afee70eSjsing 
1503afee70eSjsing // Test bignums for coprimality, gcd(x,y) = 1
1513afee70eSjsing // Inputs x[m], y[n]; output function return; temporary buffer t[>=2*max(m,n)]
1523afee70eSjsing extern uint64_t bignum_coprime (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y, uint64_t *t);
1533afee70eSjsing 
1543afee70eSjsing // Copy bignum with zero-extension or truncation, z := x
1553afee70eSjsing // Input x[n]; output z[k]
1563afee70eSjsing extern void bignum_copy (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
1573afee70eSjsing 
1583afee70eSjsing // Count trailing zero digits (64-bit words)
1593afee70eSjsing // Input x[k]; output function return
1603afee70eSjsing extern uint64_t bignum_ctd (uint64_t k, uint64_t *x);
1613afee70eSjsing 
1623afee70eSjsing // Count trailing zero bits
1633afee70eSjsing // Input x[k]; output function return
1643afee70eSjsing extern uint64_t bignum_ctz (uint64_t k, uint64_t *x);
1653afee70eSjsing 
1663afee70eSjsing // Convert from almost-Montgomery form, z := (x / 2^256) mod p_256
1673afee70eSjsing // Input x[4]; output z[4]
1683afee70eSjsing extern void bignum_deamont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
1693afee70eSjsing extern void bignum_deamont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
1703afee70eSjsing 
1713afee70eSjsing // Convert from almost-Montgomery form, z := (x / 2^256) mod p_256k1
1723afee70eSjsing // Input x[4]; output z[4]
1733afee70eSjsing extern void bignum_deamont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
1743afee70eSjsing 
1753afee70eSjsing // Convert from almost-Montgomery form, z := (x / 2^384) mod p_384
1763afee70eSjsing // Input x[6]; output z[6]
1773afee70eSjsing extern void bignum_deamont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
1783afee70eSjsing extern void bignum_deamont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
1793afee70eSjsing 
1803afee70eSjsing // Convert from almost-Montgomery form z := (x / 2^576) mod p_521
1813afee70eSjsing // Input x[9]; output z[9]
1823afee70eSjsing extern void bignum_deamont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
1833afee70eSjsing 
1843afee70eSjsing // Convert from (almost-)Montgomery form z := (x / 2^{64k}) mod m
1853afee70eSjsing // Inputs x[k], m[k]; output z[k]
1863afee70eSjsing extern void bignum_demont (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
1873afee70eSjsing 
1883afee70eSjsing // Convert from Montgomery form z := (x / 2^256) mod p_256, assuming x reduced
1893afee70eSjsing // Input x[4]; output z[4]
1903afee70eSjsing extern void bignum_demont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
1913afee70eSjsing extern void bignum_demont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
1923afee70eSjsing 
1933afee70eSjsing // Convert from Montgomery form z := (x / 2^256) mod p_256k1, assuming x reduced
1943afee70eSjsing // Input x[4]; output z[4]
1953afee70eSjsing extern void bignum_demont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
1963afee70eSjsing 
1973afee70eSjsing // Convert from Montgomery form z := (x / 2^384) mod p_384, assuming x reduced
1983afee70eSjsing // Input x[6]; output z[6]
1993afee70eSjsing extern void bignum_demont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
2003afee70eSjsing extern void bignum_demont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
2013afee70eSjsing 
2023afee70eSjsing // Convert from Montgomery form z := (x / 2^576) mod p_521, assuming x reduced
2033afee70eSjsing // Input x[9]; output z[9]
2043afee70eSjsing extern void bignum_demont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
2053afee70eSjsing 
2063afee70eSjsing // Select digit x[n]
2073afee70eSjsing // Inputs x[k], n; output function return
2083afee70eSjsing extern uint64_t bignum_digit (uint64_t k, uint64_t *x, uint64_t n);
2093afee70eSjsing 
2103afee70eSjsing // Return size of bignum in digits (64-bit word)
2113afee70eSjsing // Input x[k]; output function return
2123afee70eSjsing extern uint64_t bignum_digitsize (uint64_t k, uint64_t *x);
2133afee70eSjsing 
2143afee70eSjsing // Divide bignum by 10: z' := z div 10, returning remainder z mod 10
2153afee70eSjsing // Inputs z[k]; outputs function return (remainder) and z[k]
2163afee70eSjsing extern uint64_t bignum_divmod10 (uint64_t k, uint64_t *z);
2173afee70eSjsing 
2183afee70eSjsing // Double modulo p_25519, z := (2 * x) mod p_25519, assuming x reduced
2193afee70eSjsing // Input x[4]; output z[4]
2203afee70eSjsing extern void bignum_double_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
2213afee70eSjsing 
2223afee70eSjsing // Double modulo p_256, z := (2 * x) mod p_256, assuming x reduced
2233afee70eSjsing // Input x[4]; output z[4]
2243afee70eSjsing extern void bignum_double_p256 (uint64_t z[static 4], uint64_t x[static 4]);
2253afee70eSjsing 
2263afee70eSjsing // Double modulo p_256k1, z := (2 * x) mod p_256k1, assuming x reduced
2273afee70eSjsing // Input x[4]; output z[4]
2283afee70eSjsing extern void bignum_double_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
2293afee70eSjsing 
2303afee70eSjsing // Double modulo p_384, z := (2 * x) mod p_384, assuming x reduced
2313afee70eSjsing // Input x[6]; output z[6]
2323afee70eSjsing extern void bignum_double_p384 (uint64_t z[static 6], uint64_t x[static 6]);
2333afee70eSjsing 
2343afee70eSjsing // Double modulo p_521, z := (2 * x) mod p_521, assuming x reduced
2353afee70eSjsing // Input x[9]; output z[9]
2363afee70eSjsing extern void bignum_double_p521 (uint64_t z[static 9], uint64_t x[static 9]);
2373afee70eSjsing 
2383afee70eSjsing // Extended Montgomery reduce, returning results in input-output buffer
2393afee70eSjsing // Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
2403afee70eSjsing extern uint64_t bignum_emontredc (uint64_t k, uint64_t *z, uint64_t *m, uint64_t w);
2413afee70eSjsing 
2423afee70eSjsing // Extended Montgomery reduce in 8-digit blocks, results in input-output buffer
2433afee70eSjsing // Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
2443afee70eSjsing extern uint64_t bignum_emontredc_8n (uint64_t k, uint64_t *z, uint64_t *m, uint64_t w);
2453afee70eSjsing 
2463afee70eSjsing // Test bignums for equality, x = y
2473afee70eSjsing // Inputs x[m], y[n]; output function return
2483afee70eSjsing extern uint64_t bignum_eq (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
2493afee70eSjsing 
2503afee70eSjsing // Test bignum for even-ness
2513afee70eSjsing // Input x[k]; output function return
2523afee70eSjsing extern uint64_t bignum_even (uint64_t k, uint64_t *x);
2533afee70eSjsing 
2543afee70eSjsing // Convert 4-digit (256-bit) bignum from big-endian bytes
2553afee70eSjsing // Input x[32] (bytes); output z[4]
2563afee70eSjsing extern void bignum_frombebytes_4 (uint64_t z[static 4], uint8_t x[static 32]);
2573afee70eSjsing 
2583afee70eSjsing // Convert 6-digit (384-bit) bignum from big-endian bytes
2593afee70eSjsing // Input x[48] (bytes); output z[6]
2603afee70eSjsing extern void bignum_frombebytes_6 (uint64_t z[static 6], uint8_t x[static 48]);
2613afee70eSjsing 
2623afee70eSjsing // Convert 4-digit (256-bit) bignum from little-endian bytes
2633afee70eSjsing // Input x[32] (bytes); output z[4]
2643afee70eSjsing extern void bignum_fromlebytes_4 (uint64_t z[static 4], uint8_t x[static 32]);
2653afee70eSjsing 
2663afee70eSjsing // Convert 6-digit (384-bit) bignum from little-endian bytes
2673afee70eSjsing // Input x[48] (bytes); output z[6]
2683afee70eSjsing extern void bignum_fromlebytes_6 (uint64_t z[static 6], uint8_t x[static 48]);
2693afee70eSjsing 
2703afee70eSjsing // Convert little-endian bytes to 9-digit 528-bit bignum
2713afee70eSjsing // Input x[66] (bytes); output z[9]
2723afee70eSjsing extern void bignum_fromlebytes_p521 (uint64_t z[static 9],uint8_t x[static 66]);
2733afee70eSjsing 
2743afee70eSjsing // Compare bignums, x >= y
2753afee70eSjsing // Inputs x[m], y[n]; output function return
2763afee70eSjsing extern uint64_t bignum_ge (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
2773afee70eSjsing 
2783afee70eSjsing // Compare bignums, x > y
2793afee70eSjsing // Inputs x[m], y[n]; output function return
2803afee70eSjsing extern uint64_t bignum_gt (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
2813afee70eSjsing 
2823afee70eSjsing // Halve modulo p_256, z := (x / 2) mod p_256, assuming x reduced
2833afee70eSjsing // Input x[4]; output z[4]
2843afee70eSjsing extern void bignum_half_p256 (uint64_t z[static 4], uint64_t x[static 4]);
2853afee70eSjsing 
2863afee70eSjsing // Halve modulo p_256k1, z := (x / 2) mod p_256k1, assuming x reduced
2873afee70eSjsing // Input x[4]; output z[4]
2883afee70eSjsing extern void bignum_half_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
2893afee70eSjsing 
2903afee70eSjsing // Halve modulo p_384, z := (x / 2) mod p_384, assuming x reduced
2913afee70eSjsing // Input x[6]; output z[6]
2923afee70eSjsing extern void bignum_half_p384 (uint64_t z[static 6], uint64_t x[static 6]);
2933afee70eSjsing 
2943afee70eSjsing // Halve modulo p_521, z := (x / 2) mod p_521, assuming x reduced
2953afee70eSjsing // Input x[9]; output z[9]
2963afee70eSjsing extern void bignum_half_p521 (uint64_t z[static 9], uint64_t x[static 9]);
2973afee70eSjsing 
2983afee70eSjsing // Test bignum for zero-ness, x = 0
2993afee70eSjsing // Input x[k]; output function return
3003afee70eSjsing extern uint64_t bignum_iszero (uint64_t k, uint64_t *x);
3013afee70eSjsing 
3023afee70eSjsing // Multiply z := x * y
3033afee70eSjsing // Inputs x[16], y[16]; output z[32]; temporary buffer t[>=32]
3043afee70eSjsing extern void bignum_kmul_16_32 (uint64_t z[static 32], uint64_t x[static 16], uint64_t y[static 16], uint64_t t[static 32]);
3053afee70eSjsing 
3063afee70eSjsing // Multiply z := x * y
3073afee70eSjsing // Inputs x[32], y[32]; output z[64]; temporary buffer t[>=96]
3083afee70eSjsing extern void bignum_kmul_32_64 (uint64_t z[static 64], uint64_t x[static 32], uint64_t y[static 32], uint64_t t[static 96]);
3093afee70eSjsing 
3103afee70eSjsing // Square, z := x^2
3113afee70eSjsing // Input x[16]; output z[32]; temporary buffer t[>=24]
3123afee70eSjsing extern void bignum_ksqr_16_32 (uint64_t z[static 32], uint64_t x[static 16], uint64_t t[static 24]);
3133afee70eSjsing 
3143afee70eSjsing // Square, z := x^2
3153afee70eSjsing // Input x[32]; output z[64]; temporary buffer t[>=72]
3163afee70eSjsing extern void bignum_ksqr_32_64 (uint64_t z[static 64], uint64_t x[static 32], uint64_t t[static 72]);
3173afee70eSjsing 
3183afee70eSjsing // Compare bignums, x <= y
3193afee70eSjsing // Inputs x[m], y[n]; output function return
3203afee70eSjsing extern uint64_t bignum_le (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
3213afee70eSjsing 
3223afee70eSjsing // Convert 4-digit (256-bit) bignum to/from little-endian form
3233afee70eSjsing // Input x[4]; output z[4]
3243afee70eSjsing extern void bignum_littleendian_4 (uint64_t z[static 4], uint64_t x[static 4]);
3253afee70eSjsing 
3263afee70eSjsing // Convert 6-digit (384-bit) bignum to/from little-endian form
3273afee70eSjsing // Input x[6]; output z[6]
3283afee70eSjsing extern void bignum_littleendian_6 (uint64_t z[static 6], uint64_t x[static 6]);
3293afee70eSjsing 
3303afee70eSjsing // Compare bignums, x < y
3313afee70eSjsing // Inputs x[m], y[n]; output function return
3323afee70eSjsing extern uint64_t bignum_lt (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
3333afee70eSjsing 
3343afee70eSjsing // Multiply-add, z := z + x * y
3353afee70eSjsing // Inputs x[m], y[n]; outputs function return (carry-out) and z[k]
3363afee70eSjsing extern uint64_t bignum_madd (uint64_t k, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
3373afee70eSjsing 
3383afee70eSjsing // Reduce modulo group order, z := x mod n_256
3393afee70eSjsing // Input x[k]; output z[4]
3403afee70eSjsing extern void bignum_mod_n256 (uint64_t z[static 4], uint64_t k, uint64_t *x);
3413afee70eSjsing extern void bignum_mod_n256_alt (uint64_t z[static 4], uint64_t k, uint64_t *x);
3423afee70eSjsing 
3433afee70eSjsing // Reduce modulo group order, z := x mod n_256
3443afee70eSjsing // Input x[4]; output z[4]
3453afee70eSjsing extern void bignum_mod_n256_4 (uint64_t z[static 4], uint64_t x[static 4]);
3463afee70eSjsing 
3473afee70eSjsing // Reduce modulo group order, z := x mod n_256k1
3483afee70eSjsing // Input x[4]; output z[4]
3493afee70eSjsing extern void bignum_mod_n256k1_4 (uint64_t z[static 4], uint64_t x[static 4]);
3503afee70eSjsing 
3513afee70eSjsing // Reduce modulo group order, z := x mod n_384
3523afee70eSjsing // Input x[k]; output z[6]
3533afee70eSjsing extern void bignum_mod_n384 (uint64_t z[static 6], uint64_t k, uint64_t *x);
3543afee70eSjsing extern void bignum_mod_n384_alt (uint64_t z[static 6], uint64_t k, uint64_t *x);
3553afee70eSjsing 
3563afee70eSjsing // Reduce modulo group order, z := x mod n_384
3573afee70eSjsing // Input x[6]; output z[6]
3583afee70eSjsing extern void bignum_mod_n384_6 (uint64_t z[static 6], uint64_t x[static 6]);
3593afee70eSjsing 
3603afee70eSjsing // Reduce modulo group order, z := x mod n_521
3613afee70eSjsing // Input x[9]; output z[9]
3623afee70eSjsing extern void bignum_mod_n521_9 (uint64_t z[static 9], uint64_t x[static 9]);
3633afee70eSjsing extern void bignum_mod_n521_9_alt (uint64_t z[static 9], uint64_t x[static 9]);
3643afee70eSjsing 
3653afee70eSjsing // Reduce modulo field characteristic, z := x mod p_25519
3663afee70eSjsing // Input x[4]; output z[4]
3673afee70eSjsing extern void bignum_mod_p25519_4 (uint64_t z[static 4], uint64_t x[static 4]);
3683afee70eSjsing 
3693afee70eSjsing // Reduce modulo field characteristic, z := x mod p_256
3703afee70eSjsing // Input x[k]; output z[4]
3713afee70eSjsing extern void bignum_mod_p256 (uint64_t z[static 4], uint64_t k, uint64_t *x);
3723afee70eSjsing extern void bignum_mod_p256_alt (uint64_t z[static 4], uint64_t k, uint64_t *x);
3733afee70eSjsing 
3743afee70eSjsing // Reduce modulo field characteristic, z := x mod p_256
3753afee70eSjsing // Input x[4]; output z[4]
3763afee70eSjsing extern void bignum_mod_p256_4 (uint64_t z[static 4], uint64_t x[static 4]);
3773afee70eSjsing 
3783afee70eSjsing // Reduce modulo field characteristic, z := x mod p_256k1
3793afee70eSjsing // Input x[4]; output z[4]
3803afee70eSjsing extern void bignum_mod_p256k1_4 (uint64_t z[static 4], uint64_t x[static 4]);
3813afee70eSjsing 
3823afee70eSjsing // Reduce modulo field characteristic, z := x mod p_384
3833afee70eSjsing // Input x[k]; output z[6]
3843afee70eSjsing extern void bignum_mod_p384 (uint64_t z[static 6], uint64_t k, uint64_t *x);
3853afee70eSjsing extern void bignum_mod_p384_alt (uint64_t z[static 6], uint64_t k, uint64_t *x);
3863afee70eSjsing 
3873afee70eSjsing // Reduce modulo field characteristic, z := x mod p_384
3883afee70eSjsing // Input x[6]; output z[6]
3893afee70eSjsing extern void bignum_mod_p384_6 (uint64_t z[static 6], uint64_t x[static 6]);
3903afee70eSjsing 
3913afee70eSjsing // Reduce modulo field characteristic, z := x mod p_521
3923afee70eSjsing // Input x[9]; output z[9]
3933afee70eSjsing extern void bignum_mod_p521_9 (uint64_t z[static 9], uint64_t x[static 9]);
3943afee70eSjsing 
3953afee70eSjsing // Add modulo m, z := (x + y) mod m, assuming x and y reduced
3963afee70eSjsing // Inputs x[k], y[k], m[k]; output z[k]
3973afee70eSjsing extern void bignum_modadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
3983afee70eSjsing 
3993afee70eSjsing // Double modulo m, z := (2 * x) mod m, assuming x reduced
4003afee70eSjsing // Inputs x[k], m[k]; output z[k]
4013afee70eSjsing extern void bignum_moddouble (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
4023afee70eSjsing 
4033afee70eSjsing // Compute "modification" constant z := 2^{64k} mod m
4043afee70eSjsing // Input m[k]; output z[k]; temporary buffer t[>=k]
4053afee70eSjsing extern void bignum_modifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
4063afee70eSjsing 
4073afee70eSjsing // Invert modulo m, z = (1/a) mod b, assuming b is an odd number > 1, a coprime to b
4083afee70eSjsing // Inputs a[k], b[k]; output z[k]; temporary buffer t[>=3*k]
4093afee70eSjsing extern void bignum_modinv (uint64_t k, uint64_t *z, uint64_t *a, uint64_t *b, uint64_t *t);
4103afee70eSjsing 
4113afee70eSjsing // Optionally negate modulo m, z := (-x) mod m (if p nonzero) or z := x (if p zero), assuming x reduced
4123afee70eSjsing // Inputs p, x[k], m[k]; output z[k]
4133afee70eSjsing extern void bignum_modoptneg (uint64_t k, uint64_t *z, uint64_t p, uint64_t *x, uint64_t *m);
4143afee70eSjsing 
4153afee70eSjsing // Subtract modulo m, z := (x - y) mod m, assuming x and y reduced
4163afee70eSjsing // Inputs x[k], y[k], m[k]; output z[k]
4173afee70eSjsing extern void bignum_modsub (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
4183afee70eSjsing 
4193afee70eSjsing // Compute "montification" constant z := 2^{128k} mod m
4203afee70eSjsing // Input m[k]; output z[k]; temporary buffer t[>=k]
4213afee70eSjsing extern void bignum_montifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
4223afee70eSjsing 
4233afee70eSjsing // Montgomery multiply, z := (x * y / 2^{64k}) mod m
4243afee70eSjsing // Inputs x[k], y[k], m[k]; output z[k]
4253afee70eSjsing extern void bignum_montmul (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
4263afee70eSjsing 
4273afee70eSjsing // Montgomery multiply, z := (x * y / 2^256) mod p_256
4283afee70eSjsing // Inputs x[4], y[4]; output z[4]
4293afee70eSjsing extern void bignum_montmul_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
4303afee70eSjsing extern void bignum_montmul_p256_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
4313afee70eSjsing 
4323afee70eSjsing // Montgomery multiply, z := (x * y / 2^256) mod p_256k1
4333afee70eSjsing // Inputs x[4], y[4]; output z[4]
4343afee70eSjsing extern void bignum_montmul_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
4353afee70eSjsing extern void bignum_montmul_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
4363afee70eSjsing 
4373afee70eSjsing // Montgomery multiply, z := (x * y / 2^384) mod p_384
4383afee70eSjsing // Inputs x[6], y[6]; output z[6]
4393afee70eSjsing extern void bignum_montmul_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
4403afee70eSjsing extern void bignum_montmul_p384_alt (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
4413afee70eSjsing 
4423afee70eSjsing // Montgomery multiply, z := (x * y / 2^576) mod p_521
4433afee70eSjsing // Inputs x[9], y[9]; output z[9]
4443afee70eSjsing extern void bignum_montmul_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
4453afee70eSjsing extern void bignum_montmul_p521_alt (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
4463afee70eSjsing 
4473afee70eSjsing // Montgomery reduce, z := (x' / 2^{64p}) MOD m
4483afee70eSjsing // Inputs x[n], m[k], p; output z[k]
4493afee70eSjsing extern void bignum_montredc (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t *m, uint64_t p);
4503afee70eSjsing 
4513afee70eSjsing // Montgomery square, z := (x^2 / 2^{64k}) mod m
4523afee70eSjsing // Inputs x[k], m[k]; output z[k]
4533afee70eSjsing extern void bignum_montsqr (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
4543afee70eSjsing 
4553afee70eSjsing // Montgomery square, z := (x^2 / 2^256) mod p_256
4563afee70eSjsing // Input x[4]; output z[4]
4573afee70eSjsing extern void bignum_montsqr_p256 (uint64_t z[static 4], uint64_t x[static 4]);
4583afee70eSjsing extern void bignum_montsqr_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
4593afee70eSjsing 
4603afee70eSjsing // Montgomery square, z := (x^2 / 2^256) mod p_256k1
4613afee70eSjsing // Input x[4]; output z[4]
4623afee70eSjsing extern void bignum_montsqr_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
4633afee70eSjsing extern void bignum_montsqr_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
4643afee70eSjsing 
4653afee70eSjsing // Montgomery square, z := (x^2 / 2^384) mod p_384
4663afee70eSjsing // Input x[6]; output z[6]
4673afee70eSjsing extern void bignum_montsqr_p384 (uint64_t z[static 6], uint64_t x[static 6]);
4683afee70eSjsing extern void bignum_montsqr_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
4693afee70eSjsing 
4703afee70eSjsing // Montgomery square, z := (x^2 / 2^576) mod p_521
4713afee70eSjsing // Input x[9]; output z[9]
4723afee70eSjsing extern void bignum_montsqr_p521 (uint64_t z[static 9], uint64_t x[static 9]);
4733afee70eSjsing extern void bignum_montsqr_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
4743afee70eSjsing 
4753afee70eSjsing // Multiply z := x * y
4763afee70eSjsing // Inputs x[m], y[n]; output z[k]
4773afee70eSjsing extern void bignum_mul (uint64_t k, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
4783afee70eSjsing 
4793afee70eSjsing // Multiply z := x * y
4803afee70eSjsing // Inputs x[4], y[4]; output z[8]
4813afee70eSjsing extern void bignum_mul_4_8 (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
4823afee70eSjsing extern void bignum_mul_4_8_alt (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
4833afee70eSjsing 
4843afee70eSjsing // Multiply z := x * y
4853afee70eSjsing // Inputs x[6], y[6]; output z[12]
4863afee70eSjsing extern void bignum_mul_6_12 (uint64_t z[static 12], uint64_t x[static 6], uint64_t y[static 6]);
4873afee70eSjsing extern void bignum_mul_6_12_alt (uint64_t z[static 12], uint64_t x[static 6], uint64_t y[static 6]);
4883afee70eSjsing 
4893afee70eSjsing // Multiply z := x * y
4903afee70eSjsing // Inputs x[8], y[8]; output z[16]
4913afee70eSjsing extern void bignum_mul_8_16 (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
4923afee70eSjsing extern void bignum_mul_8_16_alt (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
4933afee70eSjsing 
4943afee70eSjsing // Multiply modulo p_25519, z := (x * y) mod p_25519
4953afee70eSjsing // Inputs x[4], y[4]; output z[4]
4963afee70eSjsing extern void bignum_mul_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
4973afee70eSjsing extern void bignum_mul_p25519_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
4983afee70eSjsing 
4993afee70eSjsing // Multiply modulo p_256k1, z := (x * y) mod p_256k1
5003afee70eSjsing // Inputs x[4], y[4]; output z[4]
5013afee70eSjsing extern void bignum_mul_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
5023afee70eSjsing extern void bignum_mul_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
5033afee70eSjsing 
5043afee70eSjsing // Multiply modulo p_521, z := (x * y) mod p_521, assuming x and y reduced
5053afee70eSjsing // Inputs x[9], y[9]; output z[9]
5063afee70eSjsing extern void bignum_mul_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
5073afee70eSjsing extern void bignum_mul_p521_alt (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
5083afee70eSjsing 
5093afee70eSjsing // Multiply bignum by 10 and add word: z := 10 * z + d
5103afee70eSjsing // Inputs z[k], d; outputs function return (carry) and z[k]
5113afee70eSjsing extern uint64_t bignum_muladd10 (uint64_t k, uint64_t *z, uint64_t d);
5123afee70eSjsing 
5133afee70eSjsing // Multiplex/select z := x (if p nonzero) or z := y (if p zero)
5143afee70eSjsing // Inputs p, x[k], y[k]; output z[k]
5153afee70eSjsing extern void bignum_mux (uint64_t p, uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y);
5163afee70eSjsing 
5173afee70eSjsing // 256-bit multiplex/select z := x (if p nonzero) or z := y (if p zero)
5183afee70eSjsing // Inputs p, x[4], y[4]; output z[4]
5193afee70eSjsing extern void bignum_mux_4 (uint64_t p, uint64_t z[static 4],uint64_t x[static 4], uint64_t y[static 4]);
5203afee70eSjsing 
5213afee70eSjsing // 384-bit multiplex/select z := x (if p nonzero) or z := y (if p zero)
5223afee70eSjsing // Inputs p, x[6], y[6]; output z[6]
5233afee70eSjsing extern void bignum_mux_6 (uint64_t p, uint64_t z[static 6],uint64_t x[static 6], uint64_t y[static 6]);
5243afee70eSjsing 
5253afee70eSjsing // Select element from 16-element table, z := xs[k*i]
5263afee70eSjsing // Inputs xs[16*k], i; output z[k]
5273afee70eSjsing extern void bignum_mux16 (uint64_t k, uint64_t *z, uint64_t *xs, uint64_t i);
5283afee70eSjsing 
5293afee70eSjsing // Negate modulo p_25519, z := (-x) mod p_25519, assuming x reduced
5303afee70eSjsing // Input x[4]; output z[4]
5313afee70eSjsing extern void bignum_neg_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
5323afee70eSjsing 
5333afee70eSjsing // Negate modulo p_256, z := (-x) mod p_256, assuming x reduced
5343afee70eSjsing // Input x[4]; output z[4]
5353afee70eSjsing extern void bignum_neg_p256 (uint64_t z[static 4], uint64_t x[static 4]);
5363afee70eSjsing 
5373afee70eSjsing // Negate modulo p_256k1, z := (-x) mod p_256k1, assuming x reduced
5383afee70eSjsing // Input x[4]; output z[4]
5393afee70eSjsing extern void bignum_neg_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
5403afee70eSjsing 
5413afee70eSjsing // Negate modulo p_384, z := (-x) mod p_384, assuming x reduced
5423afee70eSjsing // Input x[6]; output z[6]
5433afee70eSjsing extern void bignum_neg_p384 (uint64_t z[static 6], uint64_t x[static 6]);
5443afee70eSjsing 
5453afee70eSjsing // Negate modulo p_521, z := (-x) mod p_521, assuming x reduced
5463afee70eSjsing // Input x[9]; output z[9]
5473afee70eSjsing extern void bignum_neg_p521 (uint64_t z[static 9], uint64_t x[static 9]);
5483afee70eSjsing 
5493afee70eSjsing // Negated modular inverse, z := (-1/x) mod 2^{64k}
5503afee70eSjsing // Input x[k]; output z[k]
5513afee70eSjsing extern void bignum_negmodinv (uint64_t k, uint64_t *z, uint64_t *x);
5523afee70eSjsing 
5533afee70eSjsing // Test bignum for nonzero-ness x =/= 0
5543afee70eSjsing // Input x[k]; output function return
5553afee70eSjsing extern uint64_t bignum_nonzero (uint64_t k, uint64_t *x);
5563afee70eSjsing 
5573afee70eSjsing // Test 256-bit bignum for nonzero-ness x =/= 0
5583afee70eSjsing // Input x[4]; output function return
5593afee70eSjsing extern uint64_t bignum_nonzero_4(uint64_t x[static 4]);
5603afee70eSjsing 
5613afee70eSjsing // Test 384-bit bignum for nonzero-ness x =/= 0
5623afee70eSjsing // Input x[6]; output function return
5633afee70eSjsing extern uint64_t bignum_nonzero_6(uint64_t x[static 6]);
5643afee70eSjsing 
5653afee70eSjsing // Normalize bignum in-place by shifting left till top bit is 1
5663afee70eSjsing // Input z[k]; outputs function return (bits shifted left) and z[k]
5673afee70eSjsing extern uint64_t bignum_normalize (uint64_t k, uint64_t *z);
5683afee70eSjsing 
5693afee70eSjsing // Test bignum for odd-ness
5703afee70eSjsing // Input x[k]; output function return
5713afee70eSjsing extern uint64_t bignum_odd (uint64_t k, uint64_t *x);
5723afee70eSjsing 
5733afee70eSjsing // Convert single digit to bignum, z := n
5743afee70eSjsing // Input n; output z[k]
5753afee70eSjsing extern void bignum_of_word (uint64_t k, uint64_t *z, uint64_t n);
5763afee70eSjsing 
5773afee70eSjsing // Optionally add, z := x + y (if p nonzero) or z := x (if p zero)
5783afee70eSjsing // Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
5793afee70eSjsing extern uint64_t bignum_optadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
5803afee70eSjsing 
5813afee70eSjsing // Optionally negate, z := -x (if p nonzero) or z := x (if p zero)
5823afee70eSjsing // Inputs p, x[k]; outputs function return (nonzero input) and z[k]
5833afee70eSjsing extern uint64_t bignum_optneg (uint64_t k, uint64_t *z, uint64_t p, uint64_t *x);
5843afee70eSjsing 
5853afee70eSjsing // Optionally negate modulo p_25519, z := (-x) mod p_25519 (if p nonzero) or z := x (if p zero), assuming x reduced
5863afee70eSjsing // Inputs p, x[4]; output z[4]
5873afee70eSjsing extern void bignum_optneg_p25519 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
5883afee70eSjsing 
5893afee70eSjsing // Optionally negate modulo p_256, z := (-x) mod p_256 (if p nonzero) or z := x (if p zero), assuming x reduced
5903afee70eSjsing // Inputs p, x[4]; output z[4]
5913afee70eSjsing extern void bignum_optneg_p256 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
5923afee70eSjsing 
5933afee70eSjsing // Optionally negate modulo p_256k1, z := (-x) mod p_256k1 (if p nonzero) or z := x (if p zero), assuming x reduced
5943afee70eSjsing // Inputs p, x[4]; output z[4]
5953afee70eSjsing extern void bignum_optneg_p256k1 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
5963afee70eSjsing 
5973afee70eSjsing // Optionally negate modulo p_384, z := (-x) mod p_384 (if p nonzero) or z := x (if p zero), assuming x reduced
5983afee70eSjsing // Inputs p, x[6]; output z[6]
5993afee70eSjsing extern void bignum_optneg_p384 (uint64_t z[static 6], uint64_t p, uint64_t x[static 6]);
6003afee70eSjsing 
6013afee70eSjsing // Optionally negate modulo p_521, z := (-x) mod p_521 (if p nonzero) or z := x (if p zero), assuming x reduced
6023afee70eSjsing // Inputs p, x[9]; output z[9]
6033afee70eSjsing extern void bignum_optneg_p521 (uint64_t z[static 9], uint64_t p, uint64_t x[static 9]);
6043afee70eSjsing 
6053afee70eSjsing // Optionally subtract, z := x - y (if p nonzero) or z := x (if p zero)
6063afee70eSjsing // Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
6073afee70eSjsing extern uint64_t bignum_optsub (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
6083afee70eSjsing 
6093afee70eSjsing // Optionally subtract or add, z := x + sgn(p) * y interpreting p as signed
6103afee70eSjsing // Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
6113afee70eSjsing extern uint64_t bignum_optsubadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
6123afee70eSjsing 
6133afee70eSjsing // Return bignum of power of 2, z := 2^n
6143afee70eSjsing // Input n; output z[k]
6153afee70eSjsing extern void bignum_pow2 (uint64_t k, uint64_t *z, uint64_t n);
6163afee70eSjsing 
6173afee70eSjsing // Shift bignum left by c < 64 bits z := x * 2^c
6183afee70eSjsing // Inputs x[n], c; outputs function return (carry-out) and z[k]
6193afee70eSjsing extern uint64_t bignum_shl_small (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t c);
6203afee70eSjsing 
6213afee70eSjsing // Shift bignum right by c < 64 bits z := floor(x / 2^c)
6223afee70eSjsing // Inputs x[n], c; outputs function return (bits shifted out) and z[k]
6233afee70eSjsing extern uint64_t bignum_shr_small (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t c);
6243afee70eSjsing 
6253afee70eSjsing // Square, z := x^2
6263afee70eSjsing // Input x[n]; output z[k]
6273afee70eSjsing extern void bignum_sqr (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
6283afee70eSjsing 
6293afee70eSjsing // Square, z := x^2
6303afee70eSjsing // Input x[4]; output z[8]
6313afee70eSjsing extern void bignum_sqr_4_8 (uint64_t z[static 8], uint64_t x[static 4]);
6323afee70eSjsing extern void bignum_sqr_4_8_alt (uint64_t z[static 8], uint64_t x[static 4]);
6333afee70eSjsing 
6343afee70eSjsing // Square, z := x^2
6353afee70eSjsing // Input x[6]; output z[12]
6363afee70eSjsing extern void bignum_sqr_6_12 (uint64_t z[static 12], uint64_t x[static 6]);
6373afee70eSjsing extern void bignum_sqr_6_12_alt (uint64_t z[static 12], uint64_t x[static 6]);
6383afee70eSjsing 
6393afee70eSjsing // Square, z := x^2
6403afee70eSjsing // Input x[8]; output z[16]
6413afee70eSjsing extern void bignum_sqr_8_16 (uint64_t z[static 16], uint64_t x[static 8]);
6423afee70eSjsing extern void bignum_sqr_8_16_alt (uint64_t z[static 16], uint64_t x[static 8]);
6433afee70eSjsing 
6443afee70eSjsing // Square modulo p_25519, z := (x^2) mod p_25519
6453afee70eSjsing // Input x[4]; output z[4]
6463afee70eSjsing extern void bignum_sqr_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
6473afee70eSjsing extern void bignum_sqr_p25519_alt (uint64_t z[static 4], uint64_t x[static 4]);
6483afee70eSjsing 
6493afee70eSjsing // Square modulo p_256k1, z := (x^2) mod p_256k1
6503afee70eSjsing // Input x[4]; output z[4]
6513afee70eSjsing extern void bignum_sqr_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
6523afee70eSjsing extern void bignum_sqr_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
6533afee70eSjsing 
6543afee70eSjsing // Square modulo p_521, z := (x^2) mod p_521, assuming x reduced
6553afee70eSjsing // Input x[9]; output z[9]
6563afee70eSjsing extern void bignum_sqr_p521 (uint64_t z[static 9], uint64_t x[static 9]);
6573afee70eSjsing extern void bignum_sqr_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
6583afee70eSjsing 
6593afee70eSjsing // Subtract, z := x - y
6603afee70eSjsing // Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
6613afee70eSjsing extern uint64_t bignum_sub (uint64_t p, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
6623afee70eSjsing 
6633afee70eSjsing // Subtract modulo p_25519, z := (x - y) mod p_25519, assuming x and y reduced
6643afee70eSjsing // Inputs x[4], y[4]; output z[4]
6653afee70eSjsing extern void bignum_sub_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
6663afee70eSjsing 
6673afee70eSjsing // Subtract modulo p_256, z := (x - y) mod p_256, assuming x and y reduced
6683afee70eSjsing // Inputs x[4], y[4]; output z[4]
6693afee70eSjsing extern void bignum_sub_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
6703afee70eSjsing 
6713afee70eSjsing // Subtract modulo p_256k1, z := (x - y) mod p_256k1, assuming x and y reduced
6723afee70eSjsing // Inputs x[4], y[4]; output z[4]
6733afee70eSjsing extern void bignum_sub_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
6743afee70eSjsing 
6753afee70eSjsing // Subtract modulo p_384, z := (x - y) mod p_384, assuming x and y reduced
6763afee70eSjsing // Inputs x[6], y[6]; output z[6]
6773afee70eSjsing extern void bignum_sub_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
6783afee70eSjsing 
6793afee70eSjsing // Subtract modulo p_521, z := (x - y) mod p_521, assuming x and y reduced
6803afee70eSjsing // Inputs x[9], y[9]; output z[9]
6813afee70eSjsing extern void bignum_sub_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
6823afee70eSjsing 
6833afee70eSjsing // Convert 4-digit (256-bit) bignum to big-endian bytes
6843afee70eSjsing // Input x[4]; output z[32] (bytes)
6853afee70eSjsing extern void bignum_tobebytes_4 (uint8_t z[static 32], uint64_t x[static 4]);
6863afee70eSjsing 
6873afee70eSjsing // Convert 6-digit (384-bit) bignum to big-endian bytes
6883afee70eSjsing // Input x[6]; output z[48] (bytes)
6893afee70eSjsing extern void bignum_tobebytes_6 (uint8_t z[static 48], uint64_t x[static 6]);
6903afee70eSjsing 
6913afee70eSjsing // Convert 4-digit (256-bit) bignum to little-endian bytes
6923afee70eSjsing // Input x[4]; output z[32] (bytes)
6933afee70eSjsing extern void bignum_tolebytes_4 (uint8_t z[static 32], uint64_t x[static 4]);
6943afee70eSjsing 
6953afee70eSjsing // Convert 6-digit (384-bit) bignum to little-endian bytes
6963afee70eSjsing // Input x[6]; output z[48] (bytes)
6973afee70eSjsing extern void bignum_tolebytes_6 (uint8_t z[static 48], uint64_t x[static 6]);
6983afee70eSjsing 
6993afee70eSjsing // Convert 9-digit 528-bit bignum to little-endian bytes
7003afee70eSjsing // Input x[6]; output z[66] (bytes)
7013afee70eSjsing extern void bignum_tolebytes_p521 (uint8_t z[static 66], uint64_t x[static 9]);
7023afee70eSjsing 
7033afee70eSjsing // Convert to Montgomery form z := (2^256 * x) mod p_256
7043afee70eSjsing // Input x[4]; output z[4]
7053afee70eSjsing extern void bignum_tomont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
7063afee70eSjsing extern void bignum_tomont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
7073afee70eSjsing 
7083afee70eSjsing // Convert to Montgomery form z := (2^256 * x) mod p_256k1
7093afee70eSjsing // Input x[4]; output z[4]
7103afee70eSjsing extern void bignum_tomont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
7113afee70eSjsing extern void bignum_tomont_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
7123afee70eSjsing 
7133afee70eSjsing // Convert to Montgomery form z := (2^384 * x) mod p_384
7143afee70eSjsing // Input x[6]; output z[6]
7153afee70eSjsing extern void bignum_tomont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
7163afee70eSjsing extern void bignum_tomont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
7173afee70eSjsing 
7183afee70eSjsing // Convert to Montgomery form z := (2^576 * x) mod p_521
7193afee70eSjsing // Input x[9]; output z[9]
7203afee70eSjsing extern void bignum_tomont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
7213afee70eSjsing 
7223afee70eSjsing // Triple modulo p_256, z := (3 * x) mod p_256
7233afee70eSjsing // Input x[4]; output z[4]
7243afee70eSjsing extern void bignum_triple_p256 (uint64_t z[static 4], uint64_t x[static 4]);
7253afee70eSjsing extern void bignum_triple_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
7263afee70eSjsing 
7273afee70eSjsing // Triple modulo p_256k1, z := (3 * x) mod p_256k1
7283afee70eSjsing // Input x[4]; output z[4]
7293afee70eSjsing extern void bignum_triple_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
7303afee70eSjsing extern void bignum_triple_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
7313afee70eSjsing 
7323afee70eSjsing // Triple modulo p_384, z := (3 * x) mod p_384
7333afee70eSjsing // Input x[6]; output z[6]
7343afee70eSjsing extern void bignum_triple_p384 (uint64_t z[static 6], uint64_t x[static 6]);
7353afee70eSjsing extern void bignum_triple_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
7363afee70eSjsing 
7373afee70eSjsing // Triple modulo p_521, z := (3 * x) mod p_521, assuming x reduced
7383afee70eSjsing // Input x[9]; output z[9]
7393afee70eSjsing extern void bignum_triple_p521 (uint64_t z[static 9], uint64_t x[static 9]);
7403afee70eSjsing extern void bignum_triple_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
7413afee70eSjsing 
7423afee70eSjsing // Montgomery ladder step for curve25519
7433afee70eSjsing // Inputs point[8], pp[16], b; output rr[16]
7443afee70eSjsing extern void curve25519_ladderstep(uint64_t rr[16],uint64_t point[8],uint64_t pp[16],uint64_t b);
7453afee70eSjsing extern void curve25519_ladderstep_alt(uint64_t rr[16],uint64_t point[8],uint64_t pp[16],uint64_t b);
7463afee70eSjsing 
7473afee70eSjsing // Projective scalar multiplication, x coordinate only, for curve25519
7483afee70eSjsing // Inputs scalar[4], point[4]; output res[8]
7493afee70eSjsing extern void curve25519_pxscalarmul(uint64_t res[static 8],uint64_t scalar[static 4],uint64_t point[static 4]);
7503afee70eSjsing extern void curve25519_pxscalarmul_alt(uint64_t res[static 8],uint64_t scalar[static 4],uint64_t point[static 4]);
7513afee70eSjsing 
7523afee70eSjsing // x25519 function for curve25519
7533afee70eSjsing // Inputs scalar[4], point[4]; output res[4]
7543afee70eSjsing extern void curve25519_x25519(uint64_t res[static 4],uint64_t scalar[static 4],uint64_t point[static 4]);
7553afee70eSjsing extern void curve25519_x25519_alt(uint64_t res[static 4],uint64_t scalar[static 4],uint64_t point[static 4]);
7563afee70eSjsing 
7573afee70eSjsing // x25519 function for curve25519 on base element 9
7583afee70eSjsing // Input scalar[4]; output res[4]
7593afee70eSjsing extern void curve25519_x25519base(uint64_t res[static 4],uint64_t scalar[static 4]);
7603afee70eSjsing extern void curve25519_x25519base_alt(uint64_t res[static 4],uint64_t scalar[static 4]);
7613afee70eSjsing 
7623afee70eSjsing // Extended projective addition for edwards25519
7633afee70eSjsing // Inputs p1[16], p2[16]; output p3[16]
7643afee70eSjsing extern void edwards25519_epadd(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 16]);
7653afee70eSjsing extern void edwards25519_epadd_alt(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 16]);
7663afee70eSjsing 
7673afee70eSjsing // Extended projective doubling for edwards25519
7683afee70eSjsing // Inputs p1[12]; output p3[16]
7693afee70eSjsing extern void edwards25519_epdouble(uint64_t p3[static 16],uint64_t p1[static 12]);
7703afee70eSjsing extern void edwards25519_epdouble_alt(uint64_t p3[static 16],uint64_t p1[static 12]);
7713afee70eSjsing 
7723afee70eSjsing // Projective doubling for edwards25519
7733afee70eSjsing // Inputs p1[12]; output p3[12]
7743afee70eSjsing extern void edwards25519_pdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
7753afee70eSjsing extern void edwards25519_pdouble_alt(uint64_t p3[static 12],uint64_t p1[static 12]);
7763afee70eSjsing 
7773afee70eSjsing // Extended projective + precomputed mixed addition for edwards25519
7783afee70eSjsing // Inputs p1[16], p2[12]; output p3[16]
7793afee70eSjsing extern void edwards25519_pepadd(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 12]);
7803afee70eSjsing extern void edwards25519_pepadd_alt(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 12]);
7813afee70eSjsing 
7823afee70eSjsing // Point addition on NIST curve P-256 in Montgomery-Jacobian coordinates
7833afee70eSjsing // Inputs p1[12], p2[12]; output p3[12]
7843afee70eSjsing extern void p256_montjadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 12]);
7853afee70eSjsing 
7863afee70eSjsing // Point doubling on NIST curve P-256 in Montgomery-Jacobian coordinates
7873afee70eSjsing // Inputs p1[12]; output p3[12]
7883afee70eSjsing extern void p256_montjdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
7893afee70eSjsing 
7903afee70eSjsing // Point mixed addition on NIST curve P-256 in Montgomery-Jacobian coordinates
7913afee70eSjsing // Inputs p1[12], p2[8]; output p3[12]
7923afee70eSjsing extern void p256_montjmixadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 8]);
7933afee70eSjsing 
7943afee70eSjsing // Point addition on NIST curve P-384 in Montgomery-Jacobian coordinates
7953afee70eSjsing // Inputs p1[18], p2[18]; output p3[18]
7963afee70eSjsing extern void p384_montjadd(uint64_t p3[static 18],uint64_t p1[static 18],uint64_t p2[static 18]);
7973afee70eSjsing 
7983afee70eSjsing // Point doubling on NIST curve P-384 in Montgomery-Jacobian coordinates
7993afee70eSjsing // Inputs p1[18]; output p3[18]
8003afee70eSjsing extern void p384_montjdouble(uint64_t p3[static 18],uint64_t p1[static 18]);
8013afee70eSjsing 
8023afee70eSjsing // Point mixed addition on NIST curve P-384 in Montgomery-Jacobian coordinates
8033afee70eSjsing // Inputs p1[18], p2[12]; output p3[18]
8043afee70eSjsing extern void p384_montjmixadd(uint64_t p3[static 18],uint64_t p1[static 18],uint64_t p2[static 12]);
8053afee70eSjsing 
8063afee70eSjsing // Point addition on NIST curve P-521 in Jacobian coordinates
8073afee70eSjsing // Inputs p1[27], p2[27]; output p3[27]
8083afee70eSjsing extern void p521_jadd(uint64_t p3[static 27],uint64_t p1[static 27],uint64_t p2[static 27]);
8093afee70eSjsing 
8103afee70eSjsing // Point doubling on NIST curve P-521 in Jacobian coordinates
8113afee70eSjsing // Input p1[27]; output p3[27]
8123afee70eSjsing extern void p521_jdouble(uint64_t p3[static 27],uint64_t p1[static 27]);
8133afee70eSjsing 
8143afee70eSjsing // Point mixed addition on NIST curve P-521 in Jacobian coordinates
8153afee70eSjsing // Inputs p1[27], p2[18]; output p3[27]
8163afee70eSjsing extern void p521_jmixadd(uint64_t p3[static 27],uint64_t p1[static 27],uint64_t p2[static 18]);
8173afee70eSjsing 
8183afee70eSjsing // Point addition on SECG curve secp256k1 in Jacobian coordinates
8193afee70eSjsing // Inputs p1[12], p2[12]; output p3[12]
8203afee70eSjsing extern void secp256k1_jadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 12]);
8213afee70eSjsing 
8223afee70eSjsing // Point doubling on SECG curve secp256k1 in Jacobian coordinates
8233afee70eSjsing // Input p1[12]; output p3[12]
8243afee70eSjsing extern void secp256k1_jdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
8253afee70eSjsing 
8263afee70eSjsing // Point mixed addition on SECG curve secp256k1 in Jacobian coordinates
8273afee70eSjsing // Inputs p1[12], p2[8]; output p3[12]
8283afee70eSjsing extern void secp256k1_jmixadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 8]);
8293afee70eSjsing 
8303afee70eSjsing // Reverse the bytes in a single word
8313afee70eSjsing // Input a; output function return
8323afee70eSjsing extern uint64_t word_bytereverse (uint64_t a);
8333afee70eSjsing 
8343afee70eSjsing // Count leading zero bits in a single word
8353afee70eSjsing // Input a; output function return
8363afee70eSjsing extern uint64_t word_clz (uint64_t a);
8373afee70eSjsing 
8383afee70eSjsing // Count trailing zero bits in a single word
8393afee70eSjsing // Input a; output function return
8403afee70eSjsing extern uint64_t word_ctz (uint64_t a);
8413afee70eSjsing 
8423afee70eSjsing // Return maximum of two unsigned 64-bit words
8433afee70eSjsing // Inputs a, b; output function return
8443afee70eSjsing extern uint64_t word_max (uint64_t a, uint64_t b);
8453afee70eSjsing 
8463afee70eSjsing // Return minimum of two unsigned 64-bit words
8473afee70eSjsing // Inputs a, b; output function return
8483afee70eSjsing extern uint64_t word_min (uint64_t a, uint64_t b);
8493afee70eSjsing 
8503afee70eSjsing // Single-word negated modular inverse (-1/a) mod 2^64
8513afee70eSjsing // Input a; output function return
8523afee70eSjsing extern uint64_t word_negmodinv (uint64_t a);
8533afee70eSjsing 
8543afee70eSjsing // Single-word reciprocal, 2^64 + ret = ceil(2^128/a) - 1 if MSB of "a" is set
8553afee70eSjsing // Input a; output function return
8563afee70eSjsing extern uint64_t word_recip (uint64_t a);
857