rlib
Convenience library for useful things
Loading...
Searching...
No Matches
Multi-precision integer (mpint)

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

ruint8r_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.
 
rcharr_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 + mont_r_squared are reusable across as many FE operations as the modulus is in scope for.

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 [0, p), outputs in [0, p). Add / sub commute with the Montgomery transform, so they work both for normal-form and Mont-form operands.

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.
 

Detailed Description

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:

RMpintFE_Big is the RSA-width parallel to RMpintFE, generated from the same template; the API mirrors the smaller type byte-for-byte.

Macro Definition Documentation

◆ r_mpint_bits_used

#define r_mpint_bits_used (   mpi)
Value:
((ruint)((mpi)->dig_used > 0 ? \
(ruint)(((ruint)(mpi)->dig_used * sizeof (rmpint_digit) * 8) - \
(ruint)RUINT32_CLZ (r_mpint_get_digit (mpi, (mpi)->dig_used - 1))) : \
((ruint)0)))
ruint32 rmpint_digit
Digit machine word backing rmpint storage.
Definition rmpint.h:76
#define r_mpint_get_digit(mpi, d)
Read a digit, treating reads past dig_used as zero.
Definition rmpint.h:350
unsigned int ruint
Unsigned int.
Definition rtypes.h:157

Bit length of mpi's magnitude.

◆ r_mpint_bytes_used

#define r_mpint_bytes_used (   mpi)
Value:
((ruint)((mpi)->dig_used > 0 ? \
(ruint)(((ruint)(mpi)->dig_used * sizeof (rmpint_digit)) - \
(ruint)RUINT32_CLZ (r_mpint_get_digit (mpi, (mpi)->dig_used - 1)) / 8) : \
((ruint)0)))

Byte length of mpi's magnitude (without leading zeros).

◆ r_mpint_clamp

#define r_mpint_clamp (   mpi)
Value:
while ((mpi)->dig_used > 0 && (mpi)->data[(mpi)->dig_used-1] == 0) \
(mpi)->dig_used--; \
(mpi)->sign = (mpi)->dig_used > 0 ? (mpi)->sign : 0; \
#define R_STMT_START
Start a brace-free multi-statement macro body; pair with R_STMT_END.
Definition rmacros.h:201
#define R_STMT_END
End an R_STMT_START body (suppresses MSVC C4127 on the while(0)).
Definition rmacros.h:204

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.

◆ R_MPINT_FE_BIG_MAX_DIGITS

#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.

◆ R_MPINT_FE_MAX_DIGITS

#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.

◆ r_mpint_get_digit

#define r_mpint_get_digit (   mpi,
 
)     ((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.

Enumeration Type Documentation

◆ 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.

Enumerator
R_MPINT_ERROR 

Test failed (e.g. negative input).

R_MPINT_NON_PRIME 

Witness found - composite.

R_MPINT_CERTAIN_PRIME 

Exactly prime (small / by trial division).

R_MPINT_POSSIBLE_PRIME 

No witness in t rounds.

Function Documentation

◆ r_mpint_clear()

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.

◆ r_mpint_div()

rboolean r_mpint_div ( rmpint q,
rmpint r,
const rmpint n,
const rmpint d 
)

Quotient + remainder of n / d.

Either q or r may be NULL to discard that half.

◆ r_mpint_exp()

rboolean r_mpint_exp ( rmpint dst,
const rmpint b,
ruint16  e 
)

dst = b^e for a small unsigned exponent e.

For modular exponentiation see r_mpint_expmod and the constant-time variants.

◆ r_mpint_expmod()

rboolean r_mpint_expmod ( rmpint dst,
const rmpint b,
const rmpint e,
const rmpint m 
)

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.

◆ r_mpint_expmod_ct()

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.

Parameters
dstDestination.
bBase (treated as non-secret).
eExponent (secret-safe).
mModulus (must be odd).
exp_bitsMust 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.
Note
Residual leak: rmpint backs the intermediates, so each per-bit Mont mul iterates the intermediate value's 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.

◆ r_mpint_expmod_ct_with_mp()

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.

◆ r_mpint_fe_big_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.

Parameters
dstDestination (in rmpint form).
baseBase (public).
expExponent (secret-safe).
mModulus (must be odd).
ctxPer-modulus Montgomery context for m.
mont_r_squaredR^2 mod m.
exp_bitsDrives 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).

◆ r_mpint_fe_compute_r_squared()

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)).

Used to feed mont_r_squared into r_mpint_fe_mont_in / r_mpint_fe_invmod_mont.

◆ 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).

Parameters
outDestination, in Mont form.
a_MInput in Mont form.
p_minus_2(p - 2), in Mont form.
p_minus_2_bitsBit length of (p - 2); drives the inner exponentiation loop.
mont_r_squaredR^2 mod p, in Mont form.
ctxPer-modulus Montgomery context.

◆ r_mpint_fe_mod_ct()

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.

◆ r_mpint_fe_mont_ctx_init()

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.

◆ r_mpint_fe_mont_in()

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.

◆ r_mpint_fe_mul_mont()

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.

◆ r_mpint_fe_select_ct()

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).

◆ r_mpint_fe_to_mpint()

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.

Value-dependent, but the value has left the CT path by this point - it's en route to a public output.

◆ r_mpint_gen_prime_full()

rboolean r_mpint_gen_prime_full ( rmpint mpi,
rsize  bits,
rboolean  safe,
RPrng prng 
)

Generate a random prime of bits bits.

Parameters
mpiDestination.
bitsTarget bit length.
safeIf TRUE, generate a safe prime p with (p-1)/2 also prime.
prngRandomness source.

◆ r_mpint_get_digit_ct()

static rmpint_digit r_mpint_get_digit_ct ( const rmpint mpi,
ruint32  d 
)
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.

◆ r_mpint_init_from()

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.

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.

◆ r_mpint_init_secure()

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.

◆ r_mpint_init_str()

void r_mpint_init_str ( rmpint mpi,
const rchar str,
const rchar **  endptr,
ruint  base 
)

Initialise by parsing str in base.

Parameters
mpiDestination.
strASCII digit string.
endptrOut: pointer past the last consumed character (NULL to ignore).
baseNumeric base (2..16).

◆ r_mpint_isprime_t()

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.

◆ r_mpint_montgomery_setup()

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.

◆ r_mpint_set_secure_clear()

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.

◆ r_mpint_swap_ct()

void r_mpint_swap_ct ( rmpint a,
rmpint b,
ruint32  bit 
)

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.

◆ r_mpint_to_binary()

rboolean r_mpint_to_binary ( const rmpint mpi,
ruint8 bin,
rsize size 
)

Write mpi's absolute value into a caller buffer.

Parameters
mpiThe source value.
binDestination byte buffer.
sizeOn entry: buffer capacity. On success: bytes written.

◆ r_mpint_to_binary_new()

ruint8 * r_mpint_to_binary_new ( const rmpint mpi,
rsize size 
)

Allocate a fresh big-endian byte buffer holding mpi's absolute value.

Parameters
mpiThe source value.
sizeOut: length of the returned buffer.

◆ r_mpint_to_binary_with_size()

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.

Returns FALSE if the value doesn't fit in size bytes.