|
rlib
Convenience library for useful things
|
Heap-allocated big-integer rmpint plus the fixed-width Montgomery-form RMpintFE companions used by rlib's constant-time crypto primitives. More...
Files | |
| file | rmpint.h |
| Multi-precision integer arithmetic plus fixed-width Montgomery-form field elements (RMpintFE / RMpintFE_Big). | |
Data Structures | |
| struct | rmpint |
| Heap-backed multi-precision integer. More... | |
| struct | RMpintFE |
| Fixed-width inline-storage field element used by the ECC scalar-mul ladder. More... | |
| struct | RMpintFEMontCtx |
| Per-modulus Montgomery context. More... | |
| struct | RMpintFE_Big |
| RSA-width parallel to RMpintFE. More... | |
| struct | RMpintFE_BigMontCtx |
| Per-modulus Montgomery context for RMpintFE_Big. More... | |
Macros | |
| #define | RMPINT_DEF_DIGITS 64 |
| Default initial digit capacity for r_mpint_init. | |
| #define | RMPINT_DEF_ISPRIME_T 8 |
| Default Miller-Rabin round count for r_mpint_isprime. | |
| #define | R_MPINT_FLAG_SECURE_CLEAR (1u << 0) |
Flag: wipe data via r_memclear_secure on r_mpint_clear. | |
| #define | R_MPINT_INIT { 0, 0, 0, 0, NULL } |
| Static initialiser for an empty (zero-valued) rmpint. | |
| #define | r_mpint_init(mpi) r_mpint_init_size (mpi, RMPINT_DEF_DIGITS) |
| Initialise with the default digit capacity (RMPINT_DEF_DIGITS). | |
| #define | R_MPINT_FE_MAX_DIGITS 18 |
| Maximum digit width for RMpintFE. | |
| #define | R_MPINT_FE_BIG_MAX_DIGITS 257 |
| Maximum digit width for RMpintFE_Big. | |
Typedefs | |
| typedef ruint32 | rmpint_digit |
| Digit machine word backing rmpint storage. | |
| typedef ruint64 | rmpint_word |
| Double-width word for digit multiplications. | |
Prime generation and testing | |
| enum | RMpintPrimeTest { R_MPINT_ERROR = -1 , R_MPINT_NON_PRIME = 0 , R_MPINT_CERTAIN_PRIME , R_MPINT_POSSIBLE_PRIME } |
| Result of a Miller-Rabin primality test. More... | |
| rboolean | r_mpint_gen_prime_full (rmpint *mpi, rsize bits, rboolean safe, RPrng *prng) |
Generate a random prime of bits bits. | |
| RMpintPrimeTest | r_mpint_isprime_t (const rmpint *mpi, ruint t) |
Miller-Rabin primality test with t rounds. | |
| #define | r_mpint_gen_prime(mpi, bits, prng) r_mpint_gen_prime_full (mpi, bits, FALSE, prng) |
| Convenience: generate a (non-safe) prime. | |
| #define | r_mpint_isprime(mpi) r_mpint_isprime_t (mpi, RMPINT_DEF_ISPRIME_T) |
| Convenience: r_mpint_isprime_t with RMPINT_DEF_ISPRIME_T rounds. | |
Initialisation, secure-clear handling and lifecycle | |
| void | r_mpint_init_size (rmpint *mpi, ruint16 digits) |
Initialise mpi with a caller-chosen digit capacity. | |
| void | r_mpint_init_secure (rmpint *mpi) |
| Initialise with the secure-clear flag set. | |
| void | r_mpint_init_binary_secure (rmpint *mpi, rconstpointer data, rsize size) |
| One-shot init from raw bytes with the secure flag set, so a key imported from a buffer never spends a moment with the secure-clear flag clear. | |
| void | r_mpint_init_copy_secure (rmpint *mpi, const rmpint *b) |
| One-shot init-from-copy with the secure flag set, for cloning a key into a fresh secure-clear mpint. | |
| void | r_mpint_set_secure_clear (rmpint *mpi) |
Flip R_MPINT_FLAG_SECURE_CLEAR on an existing mpint. | |
| void | r_mpint_init_from (rmpint *dst, const rmpint *src1,...) |
Initialise dst with the default size and OR in R_MPINT_FLAG_SECURE_CLEAR if any source in the NULL-terminated argument list has it set. | |
| void | r_mpint_init_size_from (rmpint *dst, ruint16 digits, const rmpint *src1,...) |
| Same as r_mpint_init_from but with a caller-chosen initial digit capacity, for call sites that allocate a specifically-sized scratch up front. | |
| void | r_mpint_init_binary (rmpint *mpi, rconstpointer data, rsize size) |
| Initialise from a big-endian byte buffer. | |
| void | r_mpint_init_str (rmpint *mpi, const rchar *str, const rchar **endptr, ruint base) |
Initialise by parsing str in base. | |
| void | r_mpint_init_copy (rmpint *dst, const rmpint *src) |
Initialise as a copy of src. | |
| void | r_mpint_clear (rmpint *mpi) |
Release mpi's digit storage. | |
Binary / string conversion | |
| ruint8 * | r_mpint_to_binary_new (const rmpint *mpi, rsize *size) |
Allocate a fresh big-endian byte buffer holding mpi's absolute value. | |
| rboolean | r_mpint_to_binary (const rmpint *mpi, ruint8 *bin, rsize *size) |
Write mpi's absolute value into a caller buffer. | |
| rboolean | r_mpint_to_binary_with_size (const rmpint *mpi, ruint8 *bin, rsize size) |
Write mpi's absolute value left-zero-padded to exactly size bytes. | |
| rchar * | r_mpint_to_str (const rmpint *mpi) |
Allocate a decimal string representation of mpi. Caller frees with r_free. | |
Value-setting helpers | |
| void | r_mpint_zero (rmpint *mpi) |
Set mpi to zero (preserves capacity and flags). | |
| void | r_mpint_set (rmpint *mpi, const rmpint *b) |
Copy b's value into mpi. | |
| void | r_mpint_set_binary (rmpint *mpi, rconstpointer data, rsize size) |
Set mpi from a big-endian byte buffer. | |
| void | r_mpint_set_i32 (rmpint *mpi, rint32 value) |
| Set from a signed 32-bit value. | |
| void | r_mpint_set_u32 (rmpint *mpi, ruint32 value) |
| Set from an unsigned 32-bit value. | |
| void | r_mpint_set_i64 (rmpint *mpi, rint64 value) |
| Set from a signed 64-bit value. | |
| void | r_mpint_set_u64 (rmpint *mpi, ruint64 value) |
| Set from an unsigned 64-bit value. | |
Constant-time helpers | |
| void | r_mpint_swap_ct (rmpint *a, rmpint *b, ruint32 bit) |
| Constant-time conditional swap. | |
| static rmpint_digit | r_mpint_get_digit_ct (const rmpint *mpi, ruint32 d) |
| Constant-time digit accessor. | |
| ruint32 | r_mpint_ctz (const rmpint *mpi) |
Count trailing zero bits in the magnitude of mpi. | |
| #define | r_mpint_get_digit(mpi, d) ((d) < (mpi)->dig_used ? (mpi)->data[d] : (rmpint_digit)0) |
Read a digit, treating reads past dig_used as zero. | |
Comparison | |
| int | r_mpint_cmp (const rmpint *a, const rmpint *b) |
Signed compare: returns <0 / 0 / >0 like memcmp. | |
| int | r_mpint_ucmp (const rmpint *a, const rmpint *b) |
| Unsigned (magnitude) compare. | |
| int | r_mpint_cmp_i32 (const rmpint *a, rint32 b) |
| Signed compare against a 32-bit value. | |
| int | r_mpint_ucmp_u32 (const rmpint *a, ruint32 b) |
| Unsigned compare against a 32-bit value. | |
Basic arithmetic | |
| rboolean | r_mpint_add (rmpint *dst, const rmpint *a, const rmpint *b) |
dst = a + b. | |
| rboolean | r_mpint_add_i32 (rmpint *dst, const rmpint *a, rint32 b) |
dst = a + b (b is a signed 32-bit immediate). | |
| rboolean | r_mpint_add_u32 (rmpint *dst, const rmpint *a, ruint32 b) |
dst = a + b (b is an unsigned 32-bit immediate). | |
| rboolean | r_mpint_sub (rmpint *dst, const rmpint *a, const rmpint *b) |
dst = a - b. | |
| rboolean | r_mpint_sub_i32 (rmpint *dst, const rmpint *a, rint32 b) |
dst = a - b (b is a signed 32-bit immediate). | |
| rboolean | r_mpint_sub_u32 (rmpint *dst, const rmpint *a, ruint32 b) |
dst = a - b (b is an unsigned 32-bit immediate). | |
| rboolean | r_mpint_shl (rmpint *dst, const rmpint *a, ruint32 bits) |
dst = a << bits. | |
| rboolean | r_mpint_shr (rmpint *dst, const rmpint *a, ruint32 bits) |
dst = a >> bits. | |
| rboolean | r_mpint_shl_digit (rmpint *dst, const rmpint *a, ruint16 d) |
dst = a shifted left by d whole digits. | |
| rboolean | r_mpint_shr_digit (rmpint *dst, const rmpint *a, ruint16 d) |
dst = a shifted right by d whole digits. | |
| rboolean | r_mpint_mul (rmpint *dst, const rmpint *a, const rmpint *b) |
dst = a * b. | |
| rboolean | r_mpint_mul_i32 (rmpint *dst, const rmpint *a, rint32 b) |
dst = a * b (b is a signed 32-bit immediate). | |
| rboolean | r_mpint_mul_u32 (rmpint *dst, const rmpint *a, ruint32 b) |
dst = a * b (b is an unsigned 32-bit immediate). | |
| rboolean | r_mpint_div (rmpint *q, rmpint *r, const rmpint *n, const rmpint *d) |
Quotient + remainder of n / d. | |
| rboolean | r_mpint_div_i32 (rmpint *q, rmpint *r, const rmpint *n, rint32 d) |
| Divide by a signed 32-bit divisor. | |
| rboolean | r_mpint_div_u32 (rmpint *q, rmpint *r, const rmpint *n, ruint32 d) |
| Divide by an unsigned 32-bit divisor. | |
| rboolean | r_mpint_exp (rmpint *dst, const rmpint *b, ruint16 e) |
dst = b^e for a small unsigned exponent e. | |
| #define | r_mpint_mod(dst, n, d) r_mpint_div (NULL, dst, n, d) |
| Convenience: remainder-only division. | |
| #define | r_mpint_mod_i32(dst, n, d) r_mpint_div_i32 (NULL, dst, n, d) |
| Convenience: remainder-only division by signed 32-bit. | |
| #define | r_mpint_mod_u32(dst, n, d) r_mpint_div_u32 (NULL, dst, n, d) |
| Convenience: remainder-only division by unsigned 32-bit. | |
| #define | r_mpint_mulmod(dst, a, b, d) (r_mpint_mul (dst, a, b) && r_mpint_mod (dst, dst, d)) |
Convenience: dst = (a * b) mod d. | |
| #define | r_mpint_mulmod_i32(dst, a, b, d) (r_mpint_mul (dst, a, b) && r_mpint_mod_i32 (dst, dst, d)) |
Convenience: dst = (a * b) mod d (signed immediate). | |
| #define | r_mpint_mulmod_u32(dst, a, b, d) (r_mpint_mul (dst, a, b) && r_mpint_mod_u32 (dst, dst, d)) |
Convenience: dst = (a * b) mod d (unsigned immediate). | |
Number-theoretic operations | |
| rboolean | r_mpint_invmod (rmpint *dst, const rmpint *a, const rmpint *m) |
Modular inverse: dst = a^-1 mod m. | |
| rboolean | r_mpint_expmod (rmpint *dst, const rmpint *b, const rmpint *e, const rmpint *m) |
Modular exponentiation: dst = b^e mod m. | |
| rboolean | r_mpint_expmod_ct (rmpint *dst, const rmpint *b, const rmpint *e, const rmpint *m, ruint exp_bits) |
| Constant-time modular exponentiation. | |
| rboolean | r_mpint_montgomery_setup (rmpint_digit *mp, const rmpint *m) |
Compute the per-modulus Montgomery inverse mp = -m^-1 mod 2^digit_bits. | |
| rboolean | r_mpint_expmod_ct_with_mp (rmpint *dst, const rmpint *b, const rmpint *e, const rmpint *m, rmpint_digit mp, ruint exp_bits) |
Variant of r_mpint_expmod_ct that takes the per-modulus Montgomery inverse mp as input rather than deriving it from m on every call. | |
| rboolean | r_mpint_gcd (rmpint *dst, const rmpint *a, const rmpint *b) |
| Greatest common divisor. | |
| rboolean | r_mpint_lcm (rmpint *dst, const rmpint *a, const rmpint *b) |
| Least common multiple. | |
RMpintFE: per-modulus setup | |
Both helpers are one-time costs paid by the caller before any FE arithmetic; the resulting ctx + | |
| rboolean | r_mpint_fe_mont_ctx_init (RMpintFEMontCtx *ctx, const rmpint *m) |
Fill ctx (p, mp, n_digits) from an mpint modulus. | |
| rboolean | r_mpint_fe_compute_r_squared (RMpintFE *out, const rmpint *m, ruint16 n) |
Compute R^2 mod m for the supplied n-digit modulus (R = 2^(32*n)). | |
RMpintFE: lifecycle / conversion | |
| void | r_mpint_fe_zero (RMpintFE *x) |
Zero x's first R_MPINT_FE_MAX_DIGITS digits. | |
| void | r_mpint_fe_copy (RMpintFE *dst, const RMpintFE *src) |
Copy src -> dst (full width). | |
| void | r_mpint_fe_from_mpint (RMpintFE *fe, const rmpint *mpi, ruint16 n) |
Copy mpi -> fe, zero-padded to n digits. Truncates beyond n. | |
| rboolean | r_mpint_fe_to_mpint (rmpint *mpi, const RMpintFE *fe, ruint16 n) |
Copy fe -> mpi, ending with r_mpint_clamp so the mpint side stays canonical. | |
RMpintFE: constant-time helpers (no field arithmetic) | |
| rmpint_digit | r_mpint_fe_iszero_ct (const RMpintFE *x, ruint16 n) |
All-ones mask iff x's low n digits are zero; all-zeros otherwise. | |
| void | r_mpint_fe_select_ct (RMpintFE *out, rmpint_digit mask, const RMpintFE *a, const RMpintFE *b, ruint16 n) |
out := (mask == all-ones) ? a : b, digit-wise over n digits. | |
| void | r_mpint_fe_swap_ct (RMpintFE *a, RMpintFE *b, ruint32 bit, ruint16 n) |
Branchless XOR-swap of two FEs gated on bit. | |
RMpintFE: modular arithmetic mod p | |
Inputs in | |
| void | r_mpint_fe_add (RMpintFE *out, const RMpintFE *a, const RMpintFE *b, const RMpintFEMontCtx *ctx) |
| Modular addition. | |
| void | r_mpint_fe_sub (RMpintFE *out, const RMpintFE *a, const RMpintFE *b, const RMpintFEMontCtx *ctx) |
| Modular subtraction. | |
| void | r_mpint_fe_mul_mont (RMpintFE *out, const RMpintFE *a, const RMpintFE *b, const RMpintFEMontCtx *ctx) |
Montgomery multiplication via CIOS: out := a * b * R^-1 mod p, where R = 2^(32 * n_digits). | |
| void | r_mpint_fe_sqr_mont (RMpintFE *out, const RMpintFE *a, const RMpintFEMontCtx *ctx) |
| Montgomery squaring. | |
| void | r_mpint_fe_mont_in (RMpintFE *out, const RMpintFE *a, const RMpintFE *mont_r_squared, const RMpintFEMontCtx *ctx) |
| Lift from normal form into Montgomery form. | |
| void | r_mpint_fe_mont_out (RMpintFE *out, const RMpintFE *a, const RMpintFEMontCtx *ctx) |
| Lift from Montgomery form back into normal form. | |
RMpintFE: derived operations | |
| void | r_mpint_fe_invmod_mont (RMpintFE *out, const RMpintFE *a_M, const RMpintFE *p_minus_2, ruint p_minus_2_bits, const RMpintFE *mont_r_squared, const RMpintFEMontCtx *ctx) |
Fermat-based modular inversion in Mont form: out := a_M^(p-2) mod p (also in Mont form). | |
RMpintFE: wide (non-modular) primitives | |
Used by the RSA CRT recombination to assemble the final plaintext outside any single field. | |
| void | r_mpint_fe_mul_ct (RMpintFE *out, const RMpintFE *a, ruint16 a_n, const RMpintFE *b, ruint16 b_n) |
| Wide multiply (operands of different digit widths). | |
| void | r_mpint_fe_add_ct (RMpintFE *out, const RMpintFE *a, ruint16 a_n, const RMpintFE *b, ruint16 b_n) |
| Wide add. | |
| void | r_mpint_fe_mod_ct (RMpintFE *out, const RMpintFE *a, const RMpintFEMontCtx *ctx) |
Conditional-subtract-once reduce: out = (a < p) ? a : a - p. | |
RMpintFE_Big: counterparts to the RMpintFE primitives | |
Function semantics match the RMpintFE primitives above byte-for-byte (they are emitted from the same template); only the storage width and the type / function name spellings differ. The ctx / r-squared / exponent-bits inputs are the same role; consult the RMpintFE comments above for details. | |
| rboolean | r_mpint_fe_big_mont_ctx_init (RMpintFE_BigMontCtx *ctx, const rmpint *m) |
| See r_mpint_fe_mont_ctx_init. | |
| rboolean | r_mpint_fe_big_compute_r_squared (RMpintFE_Big *out, const rmpint *m, ruint16 n) |
| See r_mpint_fe_compute_r_squared. | |
| void | r_mpint_fe_big_zero (RMpintFE_Big *x) |
| See r_mpint_fe_zero. | |
| void | r_mpint_fe_big_copy (RMpintFE_Big *dst, const RMpintFE_Big *src) |
| See r_mpint_fe_copy. | |
| void | r_mpint_fe_big_from_mpint (RMpintFE_Big *fe, const rmpint *mpi, ruint16 n) |
| See r_mpint_fe_from_mpint. | |
| rboolean | r_mpint_fe_big_to_mpint (rmpint *mpi, const RMpintFE_Big *fe, ruint16 n) |
| See r_mpint_fe_to_mpint. | |
| rmpint_digit | r_mpint_fe_big_iszero_ct (const RMpintFE_Big *x, ruint16 n) |
| See r_mpint_fe_iszero_ct. | |
| void | r_mpint_fe_big_select_ct (RMpintFE_Big *out, rmpint_digit mask, const RMpintFE_Big *a, const RMpintFE_Big *b, ruint16 n) |
| See r_mpint_fe_select_ct. | |
| void | r_mpint_fe_big_swap_ct (RMpintFE_Big *a, RMpintFE_Big *b, ruint32 bit, ruint16 n) |
| See r_mpint_fe_swap_ct. | |
| void | r_mpint_fe_big_add (RMpintFE_Big *out, const RMpintFE_Big *a, const RMpintFE_Big *b, const RMpintFE_BigMontCtx *ctx) |
| See r_mpint_fe_add. | |
| void | r_mpint_fe_big_sub (RMpintFE_Big *out, const RMpintFE_Big *a, const RMpintFE_Big *b, const RMpintFE_BigMontCtx *ctx) |
| See r_mpint_fe_sub. | |
| void | r_mpint_fe_big_mul_mont (RMpintFE_Big *out, const RMpintFE_Big *a, const RMpintFE_Big *b, const RMpintFE_BigMontCtx *ctx) |
| See r_mpint_fe_mul_mont. | |
| void | r_mpint_fe_big_sqr_mont (RMpintFE_Big *out, const RMpintFE_Big *a, const RMpintFE_BigMontCtx *ctx) |
| See r_mpint_fe_sqr_mont. | |
| void | r_mpint_fe_big_mont_in (RMpintFE_Big *out, const RMpintFE_Big *a, const RMpintFE_Big *mont_r_squared, const RMpintFE_BigMontCtx *ctx) |
| See r_mpint_fe_mont_in. | |
| void | r_mpint_fe_big_mont_out (RMpintFE_Big *out, const RMpintFE_Big *a, const RMpintFE_BigMontCtx *ctx) |
| See r_mpint_fe_mont_out. | |
| void | r_mpint_fe_big_invmod_mont (RMpintFE_Big *out, const RMpintFE_Big *a_M, const RMpintFE_Big *p_minus_2, ruint p_minus_2_bits, const RMpintFE_Big *mont_r_squared, const RMpintFE_BigMontCtx *ctx) |
| See r_mpint_fe_invmod_mont. | |
| void | r_mpint_fe_big_mul_ct (RMpintFE_Big *out, const RMpintFE_Big *a, ruint16 a_n, const RMpintFE_Big *b, ruint16 b_n) |
| See r_mpint_fe_mul_ct. | |
| void | r_mpint_fe_big_add_ct (RMpintFE_Big *out, const RMpintFE_Big *a, ruint16 a_n, const RMpintFE_Big *b, ruint16 b_n) |
| See r_mpint_fe_add_ct. | |
| void | r_mpint_fe_big_mod_ct (RMpintFE_Big *out, const RMpintFE_Big *a, const RMpintFE_BigMontCtx *ctx) |
| See r_mpint_fe_mod_ct. | |
| rboolean | r_mpint_fe_big_expmod_ct (rmpint *dst, const rmpint *base, const rmpint *exp, const rmpint *m, const RMpintFE_BigMontCtx *ctx, const RMpintFE_Big *mont_r_squared, ruint exp_bits) |
Modular exponentiation in Z_m: dst = base^exp mod m. | |
Inline predicates and metadata accessors | |
| #define | r_mpint_iszero(mpi) ((mpi)->dig_used == 0) |
TRUE iff mpi is zero. | |
| #define | r_mpint_iseven(mpi) ((mpi)->dig_used > 0 && (((mpi)->data[0] & 1) == 0)) |
TRUE iff the magnitude of mpi is even. | |
| #define | r_mpint_isodd(mpi) ((mpi)->dig_used > 0 && (((mpi)->data[0] & 1) == 1)) |
TRUE iff the magnitude of mpi is odd. | |
| #define | r_mpint_isneg(mpi) ((mpi)->dig_used > 0 && (mpi)->sign) |
TRUE iff mpi is strictly negative. | |
| #define | r_mpint_digits_used(mpi) (mpi)->dig_used |
Number of digits mpi's magnitude occupies. | |
| #define | r_mpint_bytes_used(mpi) |
Byte length of mpi's magnitude (without leading zeros). | |
| #define | r_mpint_bits_used(mpi) |
Bit length of mpi's magnitude. | |
| #define | r_mpint_clamp(mpi) |
Shrink dig_used until the leading digit is non-zero; clear sign if the value is zero. | |
Heap-allocated big-integer rmpint plus the fixed-width Montgomery-form RMpintFE companions used by rlib's constant-time crypto primitives.
The module has two layers:
_ct suffixed variants (r_mpint_swap_ct, r_mpint_get_digit_ct, r_mpint_expmod_ct) avoid the most obvious timing leaks for the operations that handle secret material.R_MPINT_FE_MAX_DIGITS) so every primitive iterates exactly the modulus's digit count regardless of operand value, giving genuine constant-time arithmetic at the cycle-count level (no residual leak through r_mpint_clamp shrinking dig_used to the value's bit length).RMpintFE_Big is the RSA-width parallel to RMpintFE, generated from the same template; the API mirrors the smaller type byte-for-byte.
| #define r_mpint_bits_used | ( | mpi | ) |
Bit length of mpi's magnitude.
| #define r_mpint_bytes_used | ( | mpi | ) |
Byte length of mpi's magnitude (without leading zeros).
| #define r_mpint_clamp | ( | mpi | ) |
Shrink dig_used until the leading digit is non-zero; clear sign if the value is zero.
Operations may leave trailing zero digits in place; r_mpint_clamp normalises the representation so predicates and serialisers see the canonical bit-length.
| #define R_MPINT_FE_BIG_MAX_DIGITS 257 |
Maximum digit width for RMpintFE_Big.
Covers up to RSA-8192 (256 32-bit digits for the full modulus, 128 for a CRT half) plus one carry-slot margin. Bump this if you need RSA-16384 or wider.
| #define R_MPINT_FE_MAX_DIGITS 18 |
Maximum digit width for RMpintFE.
Sized for secp521r1 (17 32-bit digits) plus one headroom slot for the Montgomery accumulator's top carry. DSA |q| (256 bits) fits comfortably; RSA moduli do not - that's what RMpintFE_Big is for.
| #define r_mpint_get_digit | ( | mpi, | |
| d | |||
| ) | ((d) < (mpi)->dig_used ? (mpi)->data[d] : (rmpint_digit)0) |
Read a digit, treating reads past dig_used as zero.
mpint operations promise that data[0 .. dig_used) carries the value, but several producers (e.g. the final shr in r_mpint_div, and any path that shortens dig_used without zeroing the now-unused tail) leave stale bytes behind in data[dig_used .. dig_alloc). Without this clamp, consumers that loop up to MAX(a->dig_used, b->dig_used) and read both operands - notably r_mpint_add with dst aliasing the shorter operand - end up folding stale data into the result.
| enum RMpintPrimeTest |
Result of a Miller-Rabin primality test.
CERTAIN_PRIME is reserved for small values where trial division reaches an exact verdict; larger primes are reported as POSSIBLE_PRIME with a confidence proportional to the number of rounds run.
| void r_mpint_clear | ( | rmpint * | mpi | ) |
Release mpi's digit storage.
If R_MPINT_FLAG_SECURE_CLEAR is set, the buffer is wiped via r_memclear_secure before being freed.
Quotient + remainder of n / d.
Either q or r may be NULL to discard that half.
dst = b^e for a small unsigned exponent e.
For modular exponentiation see r_mpint_expmod and the constant-time variants.
Modular exponentiation: dst = b^e mod m.
Variable-time on the exponent; not safe for secret exponents. Use r_mpint_expmod_ct for RSA / DSA private operations.
| rboolean r_mpint_expmod_ct | ( | rmpint * | dst, |
| const rmpint * | b, | ||
| const rmpint * | e, | ||
| const rmpint * | m, | ||
| ruint | exp_bits | ||
| ) |
Constant-time modular exponentiation.
Iterates exactly exp_bits bits over the exponent and routes the per-bit dispatch through r_mpint_swap_ct rather than secret-indexed lookups; the per-iteration Montgomery reduce runs through the CT variant. The base b is treated as non-secret: the initial lift into Montgomery form is variable-time.
| dst | Destination. |
| b | Base (treated as non-secret). |
| e | Exponent (secret-safe). |
| m | Modulus (must be odd). |
| exp_bits | Must upper-bound the bit length of e - silent truncation otherwise. bit_count(m) is always safe; a tighter bound (e.g. bit_count(q) for DSA's k<q) saves work. This is the one timing channel the caller fully controls; pick the same value across calls if uniformity matters. |
dig_used. That leaks the bit length of the partial product, not the exponent. Removing this would require either a fixed-width type sized for the modulus (cf. RMpintFE for ECC) or non-clamping rmpint variants. For DSA's mod-p path the leak is on intermediate g^(partial-k) values, not on k directly. | rboolean r_mpint_expmod_ct_with_mp | ( | rmpint * | dst, |
| const rmpint * | b, | ||
| const rmpint * | e, | ||
| const rmpint * | m, | ||
| rmpint_digit | mp, | ||
| ruint | exp_bits | ||
| ) |
Variant of r_mpint_expmod_ct that takes the per-modulus Montgomery inverse mp as input rather than deriving it from m on every call.
Callers that sign / decrypt repeatedly with the same modulus (RSA private operations, DSA signing) cache mp on their key struct - one r_mpint_montgomery_setup at construction instead of one per call. Same exp_bits semantics and residual-leak behaviour as r_mpint_expmod_ct.
| rboolean r_mpint_fe_big_expmod_ct | ( | rmpint * | dst, |
| const rmpint * | base, | ||
| const rmpint * | exp, | ||
| const rmpint * | m, | ||
| const RMpintFE_BigMontCtx * | ctx, | ||
| const RMpintFE_Big * | mont_r_squared, | ||
| ruint | exp_bits | ||
| ) |
Modular exponentiation in Z_m: dst = base^exp mod m.
base is reduced mod m internally if needed (variable-time on base; for RSA the base is the public ciphertext, so the reduce isn't a leak). The exponent flows through a 4-bit windowed Montgomery exponentiation with constant-time table lookup via FE_Big primitives - no dig_used residual on intermediate values the way r_mpint_expmod_ct has, since FE_Big storage is fixed-width.
| dst | Destination (in rmpint form). |
| base | Base (public). |
| exp | Exponent (secret-safe). |
| m | Modulus (must be odd). |
| ctx | Per-modulus Montgomery context for m. |
| mont_r_squared | R^2 mod m. |
| exp_bits | Drives the iteration count: the loop runs exactly ceil(exp_bits / 4) windows regardless of the exponent's actual bit length, so callers wanting a uniform timing profile across keys can pass the modulus's bit length (or any constant >= the exponent's true bit length). |
Compute R^2 mod m for the supplied n-digit modulus (R = 2^(32*n)).
Used to feed mont_r_squared into r_mpint_fe_mont_in / r_mpint_fe_invmod_mont.
| void r_mpint_fe_invmod_mont | ( | RMpintFE * | out, |
| const RMpintFE * | a_M, | ||
| const RMpintFE * | p_minus_2, | ||
| ruint | p_minus_2_bits, | ||
| const RMpintFE * | mont_r_squared, | ||
| const RMpintFEMontCtx * | ctx | ||
| ) |
Fermat-based modular inversion in Mont form: out := a_M^(p-2) mod p (also in Mont form).
Requires p prime and a coprime to p (a == 0 returns 0).
| out | Destination, in Mont form. |
| a_M | Input in Mont form. |
| p_minus_2 | (p - 2), in Mont form. |
| p_minus_2_bits | Bit length of (p - 2); drives the inner exponentiation loop. |
| mont_r_squared | R^2 mod p, in Mont form. |
| ctx | Per-modulus Montgomery context. |
| void r_mpint_fe_mod_ct | ( | RMpintFE * | out, |
| const RMpintFE * | a, | ||
| const RMpintFEMontCtx * | ctx | ||
| ) |
Conditional-subtract-once reduce: out = (a < p) ? a : a - p.
Useful only when the caller can guarantee a < 2p; the RSA CRT case (m2 mod p with m2 < q < 2p) qualifies.
| rboolean r_mpint_fe_mont_ctx_init | ( | RMpintFEMontCtx * | ctx, |
| const rmpint * | m | ||
| ) |
Fill ctx (p, mp, n_digits) from an mpint modulus.
Returns FALSE if m is even or larger than R_MPINT_FE_MAX_DIGITS digits.
| void r_mpint_fe_mont_in | ( | RMpintFE * | out, |
| const RMpintFE * | a, | ||
| const RMpintFE * | mont_r_squared, | ||
| const RMpintFEMontCtx * | ctx | ||
| ) |
Lift from normal form into Montgomery form.
Needs mont_r_squared (= R^2 mod p) precomputed by the caller via r_mpint_fe_compute_r_squared - it lives outside RMpintFEMontCtx because not every caller needs it.
| void r_mpint_fe_mul_mont | ( | RMpintFE * | out, |
| const RMpintFE * | a, | ||
| const RMpintFE * | b, | ||
| const RMpintFEMontCtx * | ctx | ||
| ) |
Montgomery multiplication via CIOS: out := a * b * R^-1 mod p, where R = 2^(32 * n_digits).
If a and b are in Mont form, out is too.
| void r_mpint_fe_select_ct | ( | RMpintFE * | out, |
| rmpint_digit | mask, | ||
| const RMpintFE * | a, | ||
| const RMpintFE * | b, | ||
| ruint16 | n | ||
| ) |
out := (mask == all-ones) ? a : b, digit-wise over n digits.
Safe to alias out with a or b (digits read before write).
Copy fe -> mpi, ending with r_mpint_clamp so the mpint side stays canonical.
Value-dependent, but the value has left the CT path by this point - it's en route to a public output.
Generate a random prime of bits bits.
| mpi | Destination. |
| bits | Target bit length. |
| safe | If TRUE, generate a safe prime p with (p-1)/2 also prime. |
| prng | Randomness source. |
|
inlinestatic |
Constant-time digit accessor.
Reads mpi->data[d] iff d < dig_alloc (dig_alloc is a public quantity), then masks the result with (d < dig_used). The compare on dig_used is branchless, so the timing depends only on d and dig_alloc, never on dig_used (which for secret material like an RSA exponent would leak the active digit count if read directly).
Use this in any inner loop that indexes a secret mpint at known-public positions; for non-secret material the plain r_mpint_get_digit is fine and faster on paths where the typical d is far past dig_used.
Initialise dst with the default size and OR in R_MPINT_FLAG_SECURE_CLEAR if any source in the NULL-terminated argument list has it set.
Scratch mpints inside arithmetic primitives use this so they inherit the secure-clear treatment of whichever operand contributed to them, without each call site repeating the conditional.
| void r_mpint_init_secure | ( | rmpint * | mpi | ) |
Initialise with the secure-clear flag set.
Use this for any mpint that will hold secret material at any point in its life - the flag is sticky across set / copy / arithmetic, so callers only need to remember to use this at init time.
Initialise by parsing str in base.
| mpi | Destination. |
| str | ASCII digit string. |
| endptr | Out: pointer past the last consumed character (NULL to ignore). |
| base | Numeric base (2..16). |
| RMpintPrimeTest r_mpint_isprime_t | ( | const rmpint * | mpi, |
| ruint | t | ||
| ) |
Miller-Rabin primality test with t rounds.
The probability of a false POSSIBLE_PRIME verdict drops by a factor of 4 per round.
| rboolean r_mpint_montgomery_setup | ( | rmpint_digit * | mp, |
| const rmpint * | m | ||
| ) |
Compute the per-modulus Montgomery inverse mp = -m^-1 mod 2^digit_bits.
Used by r_mpint_expmod_ct_with_mp and any other caller that wants to cache mp once per modulus rather than recomputing on every Montgomery operation. m must be odd.
| void r_mpint_set_secure_clear | ( | rmpint * | mpi | ) |
Flip R_MPINT_FLAG_SECURE_CLEAR on an existing mpint.
Useful when an mpint was init'd via the non-secure constructors (r_mpint_init_binary / r_mpint_init_copy / r_mpint_init_str) and only afterwards turns out to need secure handling.
Constant-time conditional swap.
If bit is non-zero, exchange the metadata and data pointer of a and b; if zero, leave both untouched. Same execution time and memory access pattern regardless of bit, so a Montgomery ladder driven by it doesn't leak the scalar's bit pattern through the per-step branch shape. Only the pointers are swapped (not the contents of data), so this is O(1) regardless of operand size.
Write mpi's absolute value into a caller buffer.
| mpi | The source value. |
| bin | Destination byte buffer. |
| size | On entry: buffer capacity. On success: bytes written. |
Allocate a fresh big-endian byte buffer holding mpi's absolute value.
| mpi | The source value. |
| size | Out: length of the returned buffer. |